-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace Newton Dynamics with Jolt Physics #287
Conversation
Really great start to this! I applaud your communication and consistency thereof! |
.gitmodules
Outdated
@@ -37,3 +37,6 @@ | |||
[submodule "3rdparty/freetype"] | |||
path = 3rdparty/freetype | |||
url = https://github.com/freetype/freetype | |||
[submodule "3rdparty/JoltPhysics"] | |||
path = 3rdparty/JoltPhysics | |||
url = [email protected]:jrouwe/JoltPhysics.git |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you didn't already do this, please make sure you track an "official" release by git-tag, if that exists for Jolt.
For all the other submodules, except the Magnum graphics related ones, I Just track whatever the latest official release tag is.
For magnum, they just kind of stopped doing releases, so i just periodically bump to the latest commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be tracking v5.0.0 ? hopefully
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Jolt submodule is set to use a git+ssh protocol, and this only works if your client is setup with a valid GitHub SSH credential (e.g. it cannot be cloned anonymously this way)
Like the other dependencies I'm assuming this should be using the HTTPS URI of https://github.com/jrouwe/JoltPhysics.git
so that it can be cloned anonymously
@@ -201,15 +201,15 @@ VehicleData VehicleBuilder::finalize_release() | |||
|
|||
// reserve node-to-machine partitions | |||
rPerNodeType.nodeToMach.data_reserve(rPerNodeType.m_connectCountTotal); | |||
for (NodeId node : rPerNodeType.nodeIds.bitview().zeros()) | |||
for (NodeId node : rPerNodeType.nodeIds) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't disagree with this change, but I'm not really sure how related to the Jolt physics change it is.
Maybe this should be in it's own stand-alone PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is ! Sorry it is not the cleanest, I have two other PRs open and this is one of them. I kinda figured I would start with the most advanced version of the code I could, as this PR will take me quite some time anyway. I'll just rebase whenever it is merged.
I am mostly finished here, but I get some weird behavior in Release mode only. Valgrind doesn't tell me anything, so I'm not sure where to look. If I could get some additional testing / a review it would be great. Jolt produces compilation warnings on Windows with Wall, so I disabled warnings in Jolt (at least, hopefully, I don't have MSVC to test it locally). Currently I left all the Newton code up, and examples simply have to include Jolt.h or Newton.h to switch physics engine. I'm not sure how relevant that is, though. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! I'd assume the Newton submodule should be kept around for benchmarking? Fairly simple to just make a copy of each test scenario. I don't mind this being merged in a non-final state as long as it mostly works; I'd like to figure out how to get around doing planet terrain colliders.
src/ospjolt/activescene/joltinteg.h
Outdated
va_end(list); | ||
|
||
// Print to the TTY | ||
std::cout << buffer << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be OSP_LOG_*
, though I'm wondering if spdlog or fmt has a built-in function for va_list
static constexpr ObjectLayer NON_MOVING = 0; | ||
static constexpr ObjectLayer MOVING = 1; | ||
static constexpr ObjectLayer NUM_LAYERS = 2; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not important right now, though I'm wondering if we're going to need to dynamically reassign these and filters at runtime eventually.
case EShape::Cylinder: | ||
//cylinder needs to be internally rotated 90° to match with graphics | ||
joltShape = (Shape *) new CylinderShape(1.0f, 2.0f); | ||
joltShape = (Shape *) new RotatedTranslatedShape(Vec3Arg::sZero(), Quat::sRotation(Vec3::sAxisX(), JPH_PI/2), joltShape); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just put new CylinderShape(1.0f, 2.0f)
into the constructor
Quat joltRotation(rawQuat[0], rawQuat[1], rawQuat[2], rawQuat[3]); | ||
|
||
//scale the shape directly | ||
pJoltShape->mShape = pJoltShape->mShape->ScaleShape(Vec3Arg(scale.x(), scale.y(), scale.z())).Get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary comment + huh, that's a knockoff Rust Result? (not really)
I'm not sure if this is an absolute or relative scale. I have a feeling it's relative, which is not what we want to do here.
Or wouldn't this continuously accumulate more and more layers of ScaledShape each time orient_shape is called? eg: each time a compound shape is modified
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create_primitive and orient_shape previously exists to fit around Newton Dynamic's model. The way to just 'make a shape given a position/rotation/scale' in Jolt is likely different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the compound shape (collider) transform supposed to be absolute ? I assumed it was relative to the compound shape transform (mostly because the recursive function starts with identity transform)
That is, the final absolute transform needs to be "compound shape transform" * "relative subshape transform".
I do agree that there are better ways to handle this though. I'll scrap orient_shape and create_primitive to make something that only adds ScaledShape wrapper when it is needed (ie when we are not creating the shape in the same spot, and when the shape is not already scaled).
|
||
//TODO this is locking on all bodies. Is it bad ? | ||
//The easy fix is to provide multiple step listeners for disjoint sets of bodies, which can then run in parallel. | ||
//It might not be worth it considering this function should be quite fast. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now this works, but maybe a custom Constraint is the way to go later on for ForceFactors?
Docs says all bodies are all locked within PhysicsStepListener, and bodies can be accessed directly.
I think keeping newton for a short amount of time might be worth doing, but we should definitely be removing it if jolt is working at a similar level or better. Newton doesn't compile on a bunch of targets, and it's code is a bonkers mess. I'd rather just be done with it. |
@@ -0,0 +1,39 @@ | |||
/** | |||
* Open Space Program | |||
* Copyright © 2019-2024 Open Space Program Project |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arguably the copyright date for this file only starts in 2024, not 2019.
I'm not a lawyer, so i'm not 100% certain how this should be done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied some things straight from the forcefactor.h in ospnewton which starts in 2019, but honestly I have no idea either.
// These determine which physics calculations are required for a certain | ||
// rigid body, such as gravity, thurst, or aerodynamics. | ||
// Forces are assignable at runtime in ACtxJoltWorld::m_factors | ||
using ForceFactors_t = std::array<uint64_t, 1u>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use an array of size one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this to provide a strong typedef? or is the goal here to generically support any number of items in the array, but start with only 1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(not my code, so I can't be 100% sure)
I think the intent is to be able to have a bigger array, so that more than 64 forces can be supported. Currently some things break if the array is bigger though.
src/ospjolt/activescene/joltinteg.h
Outdated
static void TraceImpl(const char *inFMT, ...) | ||
{ | ||
// Format the message | ||
va_list list; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm very, very, very, wary of C++ code using va_list / va_start.
What's driving the use of a C-style variadic function instead of a C++ template function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow, there don't seem to be another way.
Basically, I updated it to use spdlog, and the problem is, the spdlog function takes 2 arguments then variadics, and jolt expects 1 argument then variadics. So the only way seem to be to "unwrap" the variadics using vsnprintf, then call spdlog::trace.
I just looked into it and I'm pretty annoyed there isn't a simpler way.
Template function can't be used here, as Jolt expects a generic function pointer that can be used for any type of values.
src/ospjolt/activescene/joltinteg.h
Outdated
*/ | ||
namespace Layers | ||
{ | ||
static constexpr ObjectLayer NON_MOVING = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason not to use an enum class for these constants? They look a lot like enum values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Jolt expects "ObjectLayer" values, which is basically u16. Is there a way to make an enum which can be compared against another type easily in c++ ? For exemple in a switch statement
#include <osp/activescene/basic.h> | ||
#include <osp/core/id_map.h> | ||
|
||
#include <Jolt/Jolt.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from https://github.com/jrouwe/JoltPhysics/blob/master/HelloWorld/HelloWorld.cpp
// The Jolt headers don't include Jolt.h. Always include Jolt.h before including any other Jolt header.
// You can use Jolt.h in your precompiled header to speed up compilation.
#include <Jolt/Jolt.h>
wow, what an absolutely bullshit decision.
src/ospjolt/activescene/joltinteg.h
Outdated
case Layers::MOVING: | ||
return true; // Moving collides with everything | ||
default: | ||
JPH_ASSERT(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outside the scope of this PR, but we should probably make a more advanced ASSERT implementation for OSP that automatically does fun things like generating coredumps, generating back traces, and so on.
|
||
TransformedShapePtr_t SysJolt::create_primitive(ACtxJoltWorld &rCtxWorld, osp::EShape shape) | ||
{ | ||
Shape* joltShape; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::unique_ptr
To fix the msvc analyzer workflow, we'll need to link against the debug build of the microsoft libraries when building the Debug config. That's controlled by https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html but it doesn't seem to be working properly? |
This should be mostly done, except for the windows build issue, which I can't seem to find a solution to. If no new idea arise, I will probably setup the project on my windows machine to do some more in-depth testing. I'm still a bit unsure of some design decision (like the jolt / osp ids), but it's the best I could come up with that compiles. |
BroadPhaseLayer GetBroadPhaseLayer(ObjectLayer inLayer) const override | ||
{ | ||
JPH_ASSERT(inLayer < Layers::NUM_LAYERS); | ||
return mObjectToBroadPhase[inLayer]; |
Check warning
Code scanning / PREfast
Reading invalid data from 'this->mObjectToBroadPhase'. Warning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is covered by the assert?
The only constructor initializes the array up to Layers::NUM_LAYERS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've seen clang-tidy do similar things on custom asserts. Under the 'show paths' button, it says it's assuming that the condition inLayer < Layers::NUM_LAYERS
is false, and doesn't know the program should just panic in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's specifically a function attribute to tag functions like that as "If you get here, assume everything after it is unreachable".
but i don't think there's an attribute like that for MSVC... (if someone knows about one, please tell me, as i really would like to use it at work...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that these code scanners are scanning based on MSVC, not clang / gcc.
Github requires "Sarif" output to be able to ingest analyzer results, and clang / gcc don't support that format for their analyzer tools.
I did one more pass on the code and rebased it. I feel like it's pretty much done on my end. |
One thing I forgot to note, is that the rockets in the vehicle test scenario have a bit of a pendulum effect on them. Something is up with the center-of-mass or torque calculations. I don't mind this being fixed later. does this PR still need WIP in the title? |
I have no objection to merging this code as is. @Lamakaio can you please do three (relatively) minor things so we can merge it?
|
Absolutely ! I'll do that tomorrow. |
Should be all done. I also fixed the pendulum effect, there was a stray minus sign in the center of mass calculations. (sorry for the multiple pushes I broke some things while rebasing and rewriting the history apparently...) |
Ok, passing CI, approval from CapitalAsterisk and myself, and nice commit organization. Lets merge it! |
I am making this PR to track the work on replacing Newton Dynamics with Jolt Physics.
If it's not the right way to track things, feel free to remove it.