Giter Club home page Giter Club logo

joltphysics's Introduction

CLA assistant Build Status Quality Gate Status Bugs Code Smells

Jolt Physics

A multi core friendly rigid body physics and collision detection library suitable for games and VR applications, used by Horizon Forbidden West.

Horizon Forbidden West Cover Art

Ragdoll Pile
A YouTube video showing a ragdoll pile simulated with Jolt Physics.

For more demos and videos go to the Samples section.

Design Considerations

So why create yet another physics engine? First of all, this has been a personal learning project and secondly I wanted to address some issues that I had with existing physics engines:

  • In games we usually need to do many more things than to simulate the physics world and we need to do this across multiple threads. We therefore place a lot of emphasis on concurrently accessing the physics simulation data outside of the main physics simulation update:
    • Sections of the world can be loaded / unloaded in the background. A batch of physics bodies can be prepared on a background thread without locking or affecting the physics simulation and then inserted into the world all at once with a minimal impact on performance.
    • Collision queries can run in parallel with other operations like insertion / removal of bodies. The query code is guaranteed to see a body in a consistent state, but when a body is changed during a collision query there is no guarantee if the change is visible to the query or not. If a thread modifies the position of a body and then does a collision query, it will immediately see the updated state (this is often a problem when working with a read version and a write version of the world).
    • It is also possible to run collision queries in parallel to the main physics simulation by doing the broad phase query before the simulation step. This way, long running processes (like navigation mesh generation) can be spread out across multiple frames while still running the physics simulation every frame.
  • One of the main sources of performance problems we found was waking up too many bodies while loading / unloading content. Therefore, bodies will not automatically wake up when created and neighboring bodies will not be woken up when bodies are removed. This can be triggered manually if desired.
  • The simulation runs deterministically, so you could replicate a simulation to a remote client by merely replicating the inputs to the simulation. Read the Deterministic Simulation section to understand the limits of this.
  • The simulation of this physics engine tries to simulate behavior of rigid bodies in the real world but makes approximations in the simulation so should mainly be used for games or VR simulations.

Features

  • Simulation of rigid bodies of various shapes using continuous collision detection:
    • Sphere.
    • Box.
    • Capsule.
    • Tapered-capsule.
    • Cylinder.
    • Convex hull.
    • Compound.
    • Mesh (triangle).
    • Terrain (height field).
  • Simulation of constraints between bodies:
    • Fixed.
    • Point.
    • Distance (including springs).
    • Hinge.
    • Slider (also called prismatic).
    • Cone.
    • Rack and Pinion.
    • Gear.
    • Pulley.
    • Smooth spline paths.
    • Swing-twist (for humanoid shoulders).
    • 6 DOF.
  • Motors to drive the constraints.
  • Collision detection:
    • Casting rays.
    • Testing shapes vs shapes.
    • Casting a shape vs another shape.
    • Broadphase only tests for quickly determining which objects may intersect.
  • Sensors (trigger volumes).
  • Animated ragdolls:
    • Hard keying (kinematic only rigid bodies).
    • Soft keying (setting velocities on dynamic rigid bodies).
    • Driving constraint motors to an animated pose.
    • Mapping a high detail (animation) skeleton onto a low detail (ragdoll) skeleton and vice versa.
  • Game character simulation (capsule)
    • Rigid body character. Moves during the physics simulation. Cheapest option and most accurate collision response between character and dynamic bodies.
    • Virtual character. Does not have a rigid body in the world but simulates one using collision checks. Updated outside of the physics update for more control. Less accurate interaction with dynamic bodies.
  • Vehicles
    • Wheeled vehicles.
    • Tracked vehicles.
    • Motorcycles.
  • Soft body simulation (e.g. a soft ball or piece of cloth).
    • Edge constraints.
    • Dihedral bend constraints.
    • Tetrahedron volume constraints.
    • Long range attachment constraints (also called tethers).
    • Limiting the simulation to stay within a certain range of a skinned vertex.
    • Internal pressure.
    • Collision with simulated rigid bodies.
    • Collision tests against soft bodies.
  • Water buoyancy calculations.
  • An optional double precision mode that allows large worlds.

Supported Platforms

  • Windows (VS2019, VS2022) x86/x64/ARM32/ARM64 (Desktop/UWP)
  • Linux (tested on Ubuntu 22.04) x64/ARM64
  • FreeBSD
  • Android (tested on Android 14) x86/x64/ARM32/ARM64
  • Platform Blue (a popular game console) x64
  • macOS (tested on Monterey) x64/ARM64
  • iOS (tested on iOS 15) x64/ARM64
  • WebAssembly, see this separate project.

Required CPU features

  • On x86 the minimal requirements are SSE2 but the library can be compiled using SSE4.1, SSE4.2, AVX, AVX2, or AVX512.
  • On ARM64 the library by default compiles with NEON and FP16, on ARM32 it can be compiled without any special CPU instructions.

Documentation

To learn more about Jolt go to the Architecture and API documentation.

To get started, look at the HelloWorld example. A HelloWorld example using CMake FetchContent is also available to show how you can integrate Jolt Physics in a CMake project.

Some algorithms used by Jolt are described in detail in my GDC 2022 talk Architecting Jolt Physics for 'Horizon Forbidden West' (slides, slides with speaker notes, video).

Compiling

  • The library has been tested to compile with Cl (Visual Studio 2019-2022), Clang 10+ and GCC 9+.
  • It uses C++17 and only depends on the standard template library.
  • It doesn't make use of compiler generated RTTI or exceptions.
  • If you want to run on Platform Blue you'll need to provide your own build environment and PlatformBlue.h file due to NDA requirements (see Core.h for further info).

For build instructions go to the Build section. When upgrading from an older version of the library go to the Release Notes or API Changes sections.

Performance

If you're interested in how Jolt scales with multiple CPUs and compares to other physics engines, take a look at this document.

Folder Structure

  • Assets - This folder contains assets used by the TestFramework, Samples and JoltViewer.
  • Build - Contains everything needed to build the library, see the Build section.
  • Docs - Contains documentation for the library.
  • HelloWorld - A simple application demonstrating how to use the Jolt Physics library.
  • Jolt - All source code for the library is in this folder.
  • JoltViewer - It is possible to record the output of the physics engine using the DebugRendererRecorder class (a .jor file), this folder contains the source code to an application that can visualize a recording. This is useful for e.g. visualizing the output of the PerformanceTest from different platforms. Currently available on Windows only.
  • PerformanceTest - Contains a simple application that runs a performance test and collects timing information.
  • Samples - This contains the sample application, see the Samples section. Currently available on Windows only.
  • TestFramework - A rendering framework to visualize the results of the physics engine. Used by Samples and JoltViewer. Currently available on Windows only.
  • UnitTests - A set of unit tests to validate the behavior of the physics engine.
  • WebIncludes - A number of JavaScript resources used by the internal profiling framework of the physics engine.

Bindings For Other Languages

Integrations in Other Engines

See a list of projects that use Jolt Physics here.

License

The project is distributed under the MIT license.

Contributions

All contributions are welcome! If you intend to make larger changes, please discuss first in the GitHub Discussion section. For non-trivial changes, we require that you agree to a Contributor Agreement. When you create a PR, CLA assistant will prompt you to sign it.

joltphysics's People

Contributors

andreacatania avatar bttner avatar crocdialer avatar cuppajoeman avatar dependabot[bot] avatar docace avatar duchainer avatar enhex avatar erwincoumans avatar joshua-ashton avatar jrouwe avatar kylen97 avatar lexxik avatar marv7000 avatar mdzhb avatar michal-z avatar mihe avatar mrezai avatar nicsavichev avatar ocohen avatar phoenixillusion avatar santagada avatar scorr avatar sirlynix avatar sjharb avatar slartibarty avatar thendrix avatar tianxing113 avatar tksuoran avatar wunkolo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

joltphysics's Issues

Language Clarification: Concurrently accessing the physics simulation

In games we usually need to do many more things than to simulate the physics world and we need to do this across multiple threads. We therefore place a lot of emphasis on concurrently accessing the physics simulation data outside of the main physics simulation update:

Just asking for a clarification here, as the language makes it a bit confusing. Is Jolt intended to be run on it's own thread, while sharing a thread pool with the main application thread. Or is it designed to run on the main application thread.

BodyInterface is missing functions to apply forces

There are functions for AddImpulse and AddAngularImpulse, but nothing for forces. I know it would be easy to add those, but I am hesitant to contribute actual code changes myself, since I work closely with the Havok team (MS employee) and some might see that as crossing a line.

Broadphase and ObjectLayer filters are missing context

I'm currently looking into how to implement collision filtering.

So far I have found these filtering options:

  • in the broadphase via ObjectVsBroadPhaseLayerFilter
  • pair-wise via 16 bit "layer" information through ObjectLayerPairFilter
  • pair-wise via 32 bit "group IDs" and CollisionGroup / GroupFilter

I'm trying to figure out which of these I should use for what. I assume I should use the broadphase filter to separate static/dynamic objects and maybe stuff like "query shapes" (kinematic bodies that are only used for raycasts but not for simulation - e.g. for character hit boxes). Anything else that makes sense to separate in the broadphase? Triggers maybe?

I guess the GroupFilter is the most flexible, but also the slowest one. Not sure exactly when this is really needed, maybe for very special cases like the player object ?

I would like to use the object layer filter to do a quick bitmask check to see whether layer1 objects should collide with layer2 objects. However, the 16 bit layer value is not sufficient for this, so I would need to look up the collision matrix somewhere else.

Unfortunately PhysicsSystem::Init only takes a raw C function pointer for ObjectVsBroadPhaseLayerFilter and ObjectLayerPairFilter, which means all collision filtering information would need to be hard-coded in those functions (or global).

Interestingly, NarrowPhaseQuery::CastRay already does a similar thing, but that one takes BroadPhaseLayerFilter and ObjectLayerFilter as interfaces, so that I can pass along context information.

It would be great if PhysicsSystem::Init would also take interfaces instead.

Broadphase rebuild

I now watched your GDC talk, very interesting. One thing that you mentioned is the broadphase rebuilding, and you said you rebuild the tree and then swap it, so that it can be accessed in a multi-threaded way.

When you said "we do this", it wasn't clear to me, whether "we" referred to Jolt in general, or the game and how it integrates Jolt. Ie. does Jolt rebuild/optimize the broadphase automatically as needed already or not?

In my engine, I am adding and activating bodies one by one, which you mention is pretty bad. Of course most of that happens in the first frame when the level is loaded. Should I keep track of this and trigger a rebuild at some point? Should I just rebuild the broadphase for dynamic objects every frame? Are there helpers to do this in the background as you do in the game?

Also you mentioned that the navmesh generation may run for several seconds, but you said that you swap the broadphase trees at the end of the frame. Just out of curiosity to clarify, does each navmesh generation step just keep using that one tree for its entire duration, no matter how long it takes, or do you somehow tell it at the end of the frame to now continue with the new tree?

Materials, restitution, friction

I'm a bit surprised to see that restitution and friction are set on bodies. I was expecting those to be material parameters or at least to be per shape. As far as I can see, materials are purely a way to attach (shared) user data to shapes.

In our engine we have materials that define the behavior of surfaces, e.g. which sounds and particle effects to use for interactions, and we also edit restitution and friction there, since it makes sense. This way we create e.g. "ice" and "stone" materials and define all their physical behavior once (rendering properties are defined somewhere else, so that physical properties can be shared across many materials).
That means I can build a compound object with one shape made of ice and one shape made of stone. With PhysX those shapes would also slide and bounce accordingly, in Jolt I would currently need to somehow give the whole body one restitution and friction value.

Granted, this is a rare use case and I can understand that from a performance and memory perspective you neither want to store these values per shape, nor want to do another memory fetch into the material for every contact. Still, wanted to point out that this is a bit unexpected and that the name "PhysicsMaterial" conveys something more to me than being just for custom data.

Character Controller ground detection problems

The way the character controller checks for the ground state has a few problems.

It simply makes an overlap check with the character shape at the current location to determine which bodies it touches. Unfortunately, this is very unreliable. In many cases there will be no overlap at all, simply because after the simulation the CC is standing ON the ground, but not PENETRATING the ground and thus the check may or may not return the ground body, depending on floating point accuracy I'd guess.

Simply debug drawing the ground position of the CC and the ground state shows that it flickers between different states. It becomes very apparent when you want to apply the ground velocity (moving platforms), which randomly slide away beneath the CC.

One way I have attempted to fix this, is to move the ground check artificially 1cm downwards. This fixes the ground detection BENEATH the CC.
However, the 'sliding' state is equally affected by this. Once you jump into a wall, the overlap check may or may not return the wall object and thus vary between 'sliding' and 'in air'. To prevent the player to be able to pin the CC to a wall by walking/flying into it, I want to clamp the input velocity against the touched surface. So I need to reliably know when the CC touches a wall. Here I can't use the 'move a tiny bit downwards' tricky though. Instead, the CC shape would need to be expanded slightly. Since the user provided CC shape is used for the overlap check, I currently don't see how this could be accomplished inside Jolt.

At the moment I think my best bet would be to copy&paste the Jolt CC ground detection code into my code, and adjust it with my own (known) expanded capsule shape. Not a horrible solution actually, but maybe you have an idea how to make this more usable for everyone.

STL, OOM, and exceptions

The readme mentions two seemingly-contradictory points about Jolt:

  • It uses C++17 and only depends on the standard template library.
    -It doesn't make use of compiler generated RTTI or exceptions.

STL containers expect allocaters, even the STLAlignedAllocator provided, to throw an exception on Out Of Memory (OOM) and never to return NULL. I have ran into an OOM situation and it was Not Pretty.

I don't see a path towards fixing this without getting rid of STL containers, is this something there's interest in mainlining?

Implement an un-damped length constraint

Maybe I am misunderstanding the comment here, but what I want is to be able to really pull on it with a lot and it never exceed the maximum length of the rope (like the Point constraints but with a minLength.)

Job / Barrier interface access and compile time efficiencies

I'm in the middle of implementing a job system for a custom platform, and I noticed that barriers and jobs are restrictively access controlled - for example, Barrier::OnJobFinished() implementations fail to compile unless the barrier implementation is declared inside the class implementing the job system interface, since Job is protected. This means I cannot expose a custom job system by merely declaring a class implementing JobSystem in a public header and hide the implementation of my Barrier implementation from the user.

I understand the convenience, but is this level of access control necessary? Job is like a COM interface, I'd prefer looser access controls that allow me to experiment with job system barrier implementations with the implementation static / in an anonymous namespace inside a single compilation unit.

Would you accept a PR moving Job outside of JobSystem so barrier implementations can be opaque?

Constraints should have a flag whether to ignore collisions between joined objects

AFAIK all other physics engines by default ignore collisions between joined objects. This is quite sensible, since the abstract physics shapes would otherwise often collide with each other, or it's quite difficult to setup physics shapes that don't touch while joined. For ragdolls this is particularly tricky.

I know that it may be possible to use the collision group filters to do this, but I haven't figured out yet how I would set things up such that two joined bones don't collide, but otherwise collide with the rest. I also can't imagine, that it is particularly efficient to use these filters everywhere.

If there is an easy way to set this up, I'd be interested to know. But I would still just prefer a flag on the constraints to disable collisions.

Good job

Hi,
I just integrated Jolt in my game engine (https://github.com/amerkoleci/alimer), currently my CI build using linux fails, I saw that MSVC and CLang 10.0 is only supported, any plans for GCC? Emscripten?

Keep up the good job and thanks for all hard job.

Serialize whole PhysicsSystem + shapes + constraints?

Hello!

I was interested in being able to dump the game's physics system and add a loader to the Samples to be able to play around with it there. It's also useful for viewing in the viewer.

Same goes for being able to report some issues with constraint stability in some instances, I wanted to dump my phys env so I could easily demonstrate how it's stable to start, then after playing around with it enough it will go crazy and fly all over. (There's lots of constrained convex objects interacting.)

There's a few paths I have tried for doing something like this, one was calling SaveState on PhysicsEnvironment, this doesn't seem to save the shapes that I can tell.

The other path is using the PhysicsScene, but this suffers from not replicating constraints as I have to convert it to use the the BodyCreationInfo.

Am I missing something?

No Plane shape

Bullet3 and IIRC ODE have a plane collision shape, which is useful in a few cases. Are there any plans to add a similar shape to Jolt? If not, would such a submission be accepted into mainline?

Add Debug draw helpers for ShapeCast & CastRay

It would be really helpful for debugging to have the ability to ->Draw a ShapeCast or RayCast wiuth the same params as a CastShapeVsShape or CastRay.

Obviously one can do their own with pShape->Draw, but for debugging sanity it would be really helpful to have a simple way to visualize individual traces and rays going on without any potential mess ups in the app's code getting the CentreOfMass offsets wrong, rotations/inverse rotations etc.

Right now in our code, that is what we are doing, with a little picture in picture window showing all the traces, but obviously it would be super nice to validate against exactly what Jolt is seeing.

Assertion failed when calling GetBodyCreationSettings

Found this invalid assertion when writing code for serializing object state:

When calling GetBodyCreationSettings, an assertion can trigger if an object has mMotionProperties != nullptr (ie. was created as Dynamic) but is currently set as motion type Static.

D3D12 Crash

Crash running Samples on VS2022 CL, Windows 11.

>	Samples.exe!DescriptorHeap::Init(ID3D12Device * inDevice, D3D12_DESCRIPTOR_HEAP_TYPE inType, D3D12_DESCRIPTOR_HEAP_FLAGS inFlags, unsigned int inNumber) Line 28	C++
 	Samples.exe!Renderer::Initialize() Line 262	C++
 	Samples.exe!Application::Application() Line 48	C++
 	Samples.exe!SamplesApp::SamplesApp() Line 301	C++
 	Samples.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 2147	C++
D3D12 ERROR: ID3D12DescriptorHeap::GetGPUDescriptorHandleForHeapStart: GetGPUDescriptorHandleForHeapStart is invalid to call on a descriptor heap that does not have DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE set. If the heap is not supposed to be shader visible, then GetCPUDescriptorHandleForHeapStart would be the appropriate method to call. That call is valid both for shader visible and non shader visible descriptor heaps. [ STATE_GETTING ERROR #1315: DESCRIPTOR_HEAP_NOT_SHADER_VISIBLE]
D3D12: **BREAK** enabled for the previous message, which was: [ ERROR STATE_GETTING #1315: DESCRIPTOR_HEAP_NOT_SHADER_VISIBLE ]
Exception thrown at 0x00007FFC19F0478C (KernelBase.dll) in Samples.exe: 0x0000087A (parameters: 0x0000000000000001, 0x0000002D2434AFF0, 0x0000002D2434CDD0).
Unhandled exception at 0x00007FFC19F0478C (KernelBase.dll) in Samples.exe: 0x0000087A (parameters: 0x0000000000000001, 0x0000002D2434AFF0, 0x0000002D2434CDD0).

A friction issue

Any idea why the object "slides" and doesn't move with Jolt? Increasing the friction didn't work. Do you know if there is a solver parameter somewhere that I can tweak maybe?

https://www.youtube.com/watch?v=kOtn1sdNxuw

I know it's not an easy scene to repro so if you don't immediately know what the problem is I'll try to finish my PEEL integration and put all that on Github.

Locking two bodies at the same time (joint setup)

I am trying to create a joint between two bodies.

ConstraintSettings::Create expects two writable body references. I only have body IDs, so I'm trying to use two BodyLockWrite to lock both bodies and then create the joint. However, an assert fires, telling me that another write lock has already been taken.

In the samples I couldn't find anything similar, there the joints are always created in the same code that also creates the bodies, so it just holds pointers to those around for the needed duration.

What's the recommended way to do this?

Custom friction/restitution

I know that I can pass in custom friction and restitution values in the contact report. However, I found that on ContactConstraintManager there is also a function that is used to combine these values for two bodies, that looks like it might be a nicer fit. However, it looks like all this is internal and there doesn't seem to be a way to actuall get access to ContactConstraintManager ?

It also already uses a certain way to combine the values and now I'm wondering, whether it might do unnecessary double work to combine the values, when I then override them later in the contact report.

Maybe this callback could be exposed ?

Cool project!

Just gave it a go, and the performance and simulation robustness is very nice on my machine, compared to, for example my own physics engine ;) The only particular anomaly I spotted was in the big-heavy-cubes test, there seems to be a bit of interpenetration between the pairs of stacked cubes that doesn't quite resolve after a few seconds. I was impressed overall with how solid the constraint resolution is in your engine.

I was wondering if there is anything you can say about the history of the project? Is this a from scratch learning exercise, or it is one in a series of engines? I saw your other repo about swept ellipsoids, and imagine that you must have been working in this problem domain for a while already.

MeshShape integration issues / data ingress

I'm trying to integrate mesh shapes into an existing code base and I ran into performance regressions with MeshShape, and I had a few thoughts about the interface.

Right now you fill a MeshShapeSettings, which has std::vector<>s for vertices and indices, and pass that to the MeshShape constructor. Bullet, on the other hand, provides an interface through which the caller can expose read-only views into vertex and index data, which is a much better interface: https://github.com/bulletphysics/bullet3/blob/master/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h#L53

  • With MeshShape, I need to create, fill, and destroy STL containers, even though I might have the data right here in memory from a decompressed file on disk usually
  • Bullet lets me specify vertex stride, supporting packed formats and alignment padding
  • Bullet allows u16 and u32 indices, while MeshShapeSettings use the latter, so small meshes (and custom collision meshes) which are the majority need a processing step. Bullet handles existing index format via PHY_* types.
  • Bullet supports multi-part meshes which are common in some scenarios esp in editor

What's a good path to enable MeshShape to directly access existing data and avoid copies / etc?

web demo with wasm ?

Sorry to ask, because i know it's not easy to achieve, but it would surely be a hell of a demo.

CastRay questions

Hi, I'm currently testing integrating Jolt into our engine as a replacement for PhysX and have to say I'm extremely impressed. Awesome job!

So as I go along, I guess I'll create a bunch of tickets for questions and feedback.

In NarrowPhaseQuery there are two CastRay functions. The documentation isn't fully clear on what the first one does exactly. It says "returns true if it finds a hit closer than ioHit.mFraction". Does this mean it is an "any hit" function? I've tried it, and so far it always returned the closest hit, not just any hit, but maybe that's just because of my limited test case. So if I want the closest hit, which one should I use? Do I need a closest hit collector? And if all I want is to do an "any hit" check, what's the fastest option?

These things could be spelled out a bit more precisely in the code documentation.

Another thing I noticed is that the first CastRay function doesn't take RayCastSettings. Is that an oversight or is there a reason why these options don't make sense here?

Third, the RayCastResult doesn't contain information about the normal at the hit position. I'm a bit surprised by that, the normal can be quite useful (e.g. for bouncing / ricocheting of projectiles, particles and so on). Is there an easy and efficient way to compute the normal myself, that I haven't found yet? If not, would be nice, if the raycast function would return that, or have at least a flag to please compute the normal as well.

Fixed constraints really wobbly

Having a body of low mass, fixed to a body of much higher mass creates a really wobbly 'weld', especially rotation-wise.

Any idea how to improve this? I could maybe use a constraint with more DOF and fix their axes...

Rolling and/or spinning friction?

I am only getting started to learn Jolt. I don't seem to be able to find rolling or spinning friction in Jolt Physics. The other physics library I've used has rolling friction to stop round shapes (spheres, cylinders, capsules) from rolling forever. Spinning friction has comment torsional friction around contact normal.

Is it the case that Jolt Physics does not support rolling / spinning friction? Is there no friction applied in case of round shapes rolling? What would be the best approach to deal with this?

Add friction to all constraint types

The friction option on constraints is really nice for tweaking behavior. All of these constraints already support this:

  • hinge
  • swing twist
  • path
  • 6-dof
  • slider

It would be nice to have this also available in these constraints:

  • cone
  • point

Allow to create constraints with custom local frames

Setting up constraints in Jolt is really nice and easy, it was a joy to get up and running and have it working very quickly.

With PhysX I made the experience that setting up constraints can be quite painful, because it expects coordinate frames in the local frame of each body. This is often a mess to figure out. However, it does give you much more control.

In Jolt, when I for example set up a point constraint, I set the common position in world space. This assumes that at the time of setup, the two bodies are positioned exactly right, and it then computes the local frames internally.

This is, however, not always the case. If, for example, at runtime I want to glue two separate objects together, they won't be in the right place. If I can add a constraint with local frames, I could have the constraint snap them together as needed. With Jolt that is currently not possible, because the interface doesn't allow me to set this up.

It's the same for all other constraint types. E.g. for the slider constraint I can't specify how for along the allowed range a body is at start, because the interface expects that at simulation start they are always at offset 0. So I'd have to adjust the min/max limits accordingly every time I want to tweak something, rather than just moving the body around. So here the editing experience suffers.

Overall I like that Jolt makes getting up and running so easy, but I would like to additionally have a way to specify the local frames myself. Maybe through an additional constructor on the constraint, that I could call directly.

Sensor contact reporting issue

I'm trying to get triggers working and I'm observing curios behavior. I use a custom ContactListener. On contact added, if one of the bodies is a sensor, I set my trigger to active and use the two body IDs to remember this contact. On contact removed, I use the two body IDs to check whether this was a sensor contact and deactivate my trigger again.

I now have a dynamic box, falling into a trigger, which correctly activates it, then the box stays there and thus goes to sleep.

With just this setup, everything works as expected. However, when I add a second body to the scene, which doesn't interact with the sensor at all, the moment it creates any contact, anywhere, with any other body, the sensor contact gets removed.

Stepping through the code, I see in ContactConstraintManager::ManifoldCache::ContactPointRemovedCallbacks that every frame, if there was a new contact, old contacts that didn't happen again this frame, get removed.

I assume that because my box came to rest within the sensor, and the sensor generally doesn't affect the dynamic body, this kind of contact is not persisted and thus gets erroneously cleaned up here.

This does not happen, if the body moving through the sensor is not yet sleeping, while the other contact happens.

Caller-controlled worker threads

Would it be possible to modify Jolt to, optionally, allow the API caller to manage the worker threads? If the caller already has a thread pool it would be advantageous to call JobSystem.RunForThread(curThreadIdx); and avoid a context switch.

Easy way to wake bodies after joint update

Changing properties on a joint doesn't wake up actors, so might not have any effect.

The only way I've found to force an update is to do

PhysicsSystem->GetBodyInterface().ActivateBody(joint->GetBody2()->GetID());

Assuming that body1 is implicitly woken up as well, and may not exist, if the joint is anchored to the world.
Is there a simpler way?

Might be nice to simply have a "WakeBodies" function on the constraint class.

Add more documentation about penetration axis vs GetSurfaceNormal

One of the big Jolt gotchas that we hit was the fact that the documentation to get the normal states to use GetSurfaceNormal with the contact point, but that only ever returns the normals of a face, it does not include the edges.

We spent many many hours debugging our player code to find out that what we actually wanted was -(rotation * mPenetrationAxis).Normalized() because we wanted either the normal of the closest face or edge.

Probably makes sense to add some documentation about the differences here, we spent so so so many hours playing with collision tolerances, penetration tolerance and all sorts, until I had an OHHHH THAT WILL ONLY DO FACES AND NOT EDGES moment when comparing normal logs on edges with the old physics system.

Include path rooting

All includes are using the directives route #include <...> the problem is ... do you really think anyone consuming this library doesn't have a #include <Math/float4.h> to conflict with yours?

It would be convenient to either make the paths relative or at least change things around so that it's all #include <Jolt/...> for the non-std lib includes.

It was a relatively minor task to find replace all #include < with #include <Jolt/ and then fixup the stdlib includes, but it's a change that shouldn't have been necessary in the first place.

A trite problem, but one so obvious that if it is missed ... what else has been missed in the library? (figurative there, it looks quite excellent so far aside from header conflict hell, bloody love the positional motors)

User data on bodies and shapes

Both shapes and bodies have user data, but interestingly on bodies user data is a void* whereas on shapes it is a uint32. Is there a reason for this difference? I would have expected void* on both.

Furthermore, bodies are created with a BodyCreationSettings struct, which does not contain a member for user data. That means (as far as I can tell) that I first have to create the body and then use a BodyLockWrite to get access and set the user data. IMO it would be useful to be able to set the user data through the settings object.

ObjectToBroadPhaseLayer is too inflexible

I'm trying to get a grasp on how to set up broadphase layers, object layers and collision filtering.

Unfortunately, broadphase layers are directly linked to object layers, because you have to map from an object layer to a broadphase layer and (AFAIK) can't set the broadphaase layer of a body directly.

IMO the most flexible solution would be, if I could just set the broadphase layer of a body or shape directly. Another option would be to change the ObjectToBroadPhaseLayer type from a fixed array to a function pointer.

Here is what I am trying to achieve:

Users should be able to configure their own collision groups (up to 32 or 64 maybe). For every group they can decide with which other group those objects should collide with, so you get an NxN matrix. At runtime you need an array of size N which contains uint32 or uint64 masks that tell you which other collision group this group would collide with, so that you can make a quick bitmask check.

That is all data driven. Additionally, on the broadphase I want to have a few fixed layers:

  • Static geometry -> collides with dynamic and debris
  • Dynamic objects -> collides with static, dynamic and triggers
  • Triggers -> collides with dynamic
  • Query shapes -> collides with nothing, only for raycasts and overlap queries
  • Debris -> collides with static only

The assignment of these broadphase layers should not be up to the user, but simply depend on what kind of body is created. That means the same collision layer might be in use in different broadphase layers.

Under the restriction that I can't set the broadphase directly, I was thinking of using the 16 bit of the object layer, to store the broadphase layer index in the upper 8 bit and the collision group in the lower 8 bit. Then in my ObjectVsBroadPhaseLayerFilter I could easily extract the broadphase layer index from the object layer and check whether the two broadphase layers should interact.

However, since ObjectToBroadPhaseLayer is an array, I would need to create a huge lookup table to cover all combinations.

Finally, it would also be nice to set the object layer per shape, rather than per body, so that one can easily add details to an object that, for example, are picked up by certain raycasts, but are ignored when colliding with the world.

Told you I'd have some feedback :D Overall Jolt is really, really awesome, it's so polished for a first version, I'm quite impressed and am looking forward to seeing some of these remaining rough edges improved.

Cheers,
Jan.

Jolt.h inclusion indirectly disables warnings in project code

First of all, Jolt is amazing. We switched over from PhysX recently and it's โค. Thank you for this initiative!

Now to the issue, Jolt/Core/Core.h leaks disabled / ignored warnings into user code: https://github.com/jrouwe/JoltPhysics/blob/master/Jolt/Core/Core.h#L25 We found this out by noticing some expected warnings weren't treated as errors anymore after switching to Jolt.

We're working around this on our end, but I'm not sure what the preferred fix for the project would be. One way is changing to pragma push / pop, but that requires adding an "end" header to include after all of Jolt includes in user code.

The ideal change would likely be to only ignore these warnings where they occur instead of globally, using push / pop in the relevant functions.

Double-precision support?

Does Jolt supports double-precision? I tried Godot Engine physics and it does support it, I was able to simulate physics normally while 1000Km away from the origin.
However, my use case involves creating a lot of mesh colliders at runtime and I'm a concerned about several performance issues with Godot's physics engine, so I was considering giving Jolt a go at some point.

Constraints can sometimes go whacky mode

Sometimes having a system of fixed constraints can go crazy and fly all over if you prod them enough.

I have attached a repro case

Before:

image

After:

image

I had to change the LoadSnapshotTest to account for my object layers:

	Ref<PhysicsScene> scene = result.Get();
	for (BodyCreationSettings &settings : scene->GetBodies())
	{
		if (settings.mObjectLayer == 0 || settings.mObjectLayer == 1)
			settings.mObjectLayer = Layers::NON_MOVING;
		else
			settings.mObjectLayer = Layers::MOVING;
	}

	result.Get()->CreateBodies(mPhysicsSystem);

It's also marginally annoying that mUp points the wrong way too, but not the end of the world.

snapshot.zip

Jolt doesn't compile on Windows UWP

Just a heads up, Jolt doesn't compile on UWP. Not a big deal for me, I'll probably go without Jolt there for the time being.

The only thing that seems to not work there is in TickCounter.cpp. RegOpenKeyExA, RegQueryValueExA and RegCloseKey are not available in UWP. Everything else looks like it's compiling just fine.

PhysicsSystem::Update crashes when inCollisionSteps > 4

That's because PhysicsUpdateContext::Steps is an array with a fixed capacity.

I have specifically written my update loop such that it only calls Update once and rather uses multiple collision steps, to reduce unnecessary internal overhead, but apparently there is an undocumented limit here.

I would prefer, if there was no such limit.

FixedConstraint doesn't expose local frames

I just started using the local space frames for joints, works nicely :)

I noticed that the fixed constraint does not expose any attachment frame, although internally it does have those values, of course.
I think it can be useful to be able to specify these frames, for cases where you want to dynamically link to objects and need them to snap together. Currently the constraint would just fix them in place, but that may not be sufficient for some game play scenarios.

Another option that I see is to use a different constraint type, e.g. a 6-dof constraint and configure it down to a fixed constraint.

Also another small thing I noticed, for which I don't want to create another ticket: For PhysicsSystem::GetBodyInterface(NoLock) there are no const variants. Would be nice to have them, because BodyInterface does have a couple of useful const functions.

Support for user allocator

We already discussed it so I know it's on your list, but I'd like to officially ask for adding a "user allocator". The goal would be to allocate all objects (not just the temporary ones) thought this allocator, so that we can accurately track memory usage.

Thanks!

Contract listener questions

When I visualize contacts, I see unexpected results.

Here is a box (if it doesn't play download the file and try with VLC, not sure what went wrong, but VLC works). The box falls down twice, once reporting contacts only on the ground, but the second time, it also reports a contact in the air (when it bounces back up).

contact.points.mp4

With the box it doesn't happen all the time, but with a sphere for the collision shape, I get this every time:

grafik

This is really weird, I don't see any reason why it should report a contact there.

And another question: This system is meant for impact sounds and so on. In PhysX the contact report gave me an "impulse" for each contact, so that I could determine how strong the impact was and pick a suitable reaction. Is that possible in Jolt? All I see is a penetration depth value, but I would expect this to be highly dependent on the framerate, rather than on the actual forces involved.

And yet another question: The ContactManifold structure holds mWorldSpaceContactPointsOn1+2. What's the dfifference? I would expect the manifold to be identical for both bodies involved, and since the points are given in world space, I don't see how these could ever differ? There is no helpful comment on the code about it.

Constructor init idiom incompatible with not using exceptions

A lot of classes, like JobSystemThreadPool, are initialized via parameters passed to their constructor. This prohibits, for example, creating one as a member of a stack object then initializing it after reading values from a config file etc. The other, bigger problem I ran into was that JobSystemThreadPool allocates memory for barriers in its constructor - but there's no way to report failure from a constructor without exceptions. Memory allocation isn't the issue here, I know you can ensure no OOM etc but the bigger picture of not being able to report failures from classes with complex constructors is fatal.

I think it would be better to move towards having explicit .Init() / .Teardown() functions to enable usage of the library in exception-free build environments.

MotorSettings could use more in-depth documentation

All physics engines I've worked with (PhysX, Bullet, Havok) expose some values that require some deep understanding of how physics solvers work (which I totally don't have). Surprisingly, the documentation for these values is always very shallow, I guess because the people writing the docs are also missing that deep understanding - your chance to be better! ;-)

I'm currently applying a motor to a hinge constraint.

In MotorSettings what is the min force/torque limit? Does this have to do with the direction into which it goes? Or is "min" literally the minimum force/torque that is applied (that wouldn't make sense with the symmetric values though).

Why is there a distinction between torque and force? As far as I can tell, you always only drive one thing, right? Wouldn't that mean that every drive uses exclusively one value or the other, but never both? In that case, I'd simplify the struct (maybe always call it "force" and mention in the comment that this is a torque for rotational things).

For position targets, what exactly do mFrequency and mDamping do? Especially mFrequency doesn't tell me much. And can mDamping be larger than 1 ? Maybe give an example for when to set these values differently.

Also "position" is a bit of an overloaded term, when driving a hinge to a target angle, it is not immediately obvious that this is a "position" (I first thought this might rather apply to slider constraints).

I am also looking up a lot at implementation details to figure some stuff out. For example to see what "Set symmetric force limits" exactly means and under which conditions "IsValid" actually returns true/false.

Finally, why is driving a hinge to a target angle so weak?? I have set both force and torque limit to 10000 but it just stops when it encounters any resistance. However, driving the velocity instead, using a limit of 100 is already pretty strong and will push the same object easily out of the way.

Various mesh shape questions

I recently got triangle meshes and convex meshes up and running in my engine. It's all working, but there were a couple of things I'd like to ask about.

  1. How exactly am I supposed to serialize and deserialize baked/cooked meshes? If I understand it correctly, ConvexHullShapeSettings and MeshShapeSettings are kind of the "mesh resources", meaning the shared mesh state that is referenced by the individual shape instances. For the time being I just serialize the mesh data out myself and when I read the data, I create a new MeshShapeSettings or ConvexHullShapeSettings object from it, passing the data to their constructors. I would assume that this is not the most efficient way to do things. With other physics engines I made the experience that baking physics meshes can take quite some time, and I would prefer not to spend it during loading.

    I saw that the settings classes are derived from SerializableObject but from there on I didn't see an easy way to use this. I think I saw something about std::istream, which, to be frank, completely put me off, since I personally absolutely dislike the std stream stuff.

    Usually I would expect a lightweight reader / writer base class, that literally just needs a virtual "ReadBytes" and "WriteBytes" function, that I can derive from and implement.

  2. Convex hull generation is something that I guess can go wrong? At least in PhysX it could because it had a vertex limit of 255 (which is why I ended up writing my own anyway). Can that potentially happen in Jolt? And if so, how is that communicated through the ConvexHullShapeSettings interface?

  3. For tooling and debugging I have a component that can visualize a collision mesh. Since I don't want to store the mesh data twice, just for visualization purposes, I prefer to query the mesh data from the physics engine on demand instead. Here is what this looks like in the editor:

    image

    For this I found Shape::GetTrianglesNext(), which is a pretty cool function and I just gave it a huge AABB to retrieve everything. Still, I need to create a dummy shape for this, and I get the data in chunks. For the convex hull and triangle meshes, IF the data is somehow available as a vertex list and triangle index list, it would be nice to get direct access to that.

  4. Material pointers are set on the *Settings object and not on the *Shape object, as far as I can see. That makes sharing the same shape (usually convex hull) across different bodies with different materials difficult. E.g. when I create my "ice" boulder and my "rock" boulder, they can't use the same convex hull mesh, because the PhysicsMaterial can't be different, unless I somehow find another way to retrieve material parameters, but then the whole material idea would be pointless.

  5. Shape::Stats gives me the number of triangles in a shape, but not the number of (shared) vertices. If that information is available, would be nice to have.

  6. MeshShapeSettings takes vertices as FLOAT3 (VertexList), ConvexHullShapeSettings as Vec3 (which are actually __m128 and thus need different treatment).

Okay...that's all I got about that topic for the moment :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.