Closed kklouzal closed 2 years ago
Pinned it down to this function inside my ndBodyNotify
class:
virtual void OnApplyExternalForce(dInt32 threadIndex, dFloat32 timestep)
{
ndBodyDynamic* const dynamicBody = GetBody()->GetAsBodyDynamic();
if (dynamicBody)
{
dVector massMatrix(dynamicBody->GetMassMatrix());
dVector force(dVector(0.0f, -10.0f, 0.0f, 0.0f).Scale(massMatrix.m_w));
//dynamicBody->SetForce(force);
dynamicBody->SetTorque(dVector::m_zero);
}
}
Uncommenting dynamicBody->SetForce(force);
trips the assert. Is this perhaps a race condition?
call stack:
ndNewton_d.dll!dQuaternion::dQuaternion(const dVector & unitAxis, float angle) Line 95 C++ ndNewton_d.dll!ndBodyKinematic::IntegrateVelocity(float timestep) Line 431 C++ ndNewton_d.dll!ndBodyDynamic::IntegrateVelocity(float timestep) Line 287 C++ ndNewton_d.dll!
ndDynamicsUpdate::IntegrateBodies'::
2'::ndIntegrateBodies::Execute() Line 1362 C++ ndNewton_d.dll!dThreadPool::ExecuteJobs(dThreadPoolJob const jobs) Line 147 C++ ndNewton_d.dll!ndScene::SubmitJobs<ndDynamicsUpdate::IntegrateBodies'::
2'::ndIntegrateBodies>(void * const context) Line 262 C++ ndNewton_d.dll!ndDynamicsUpdate::IntegrateBodies() Line 1380 C++ ndNewton_d.dll!ndDynamicsUpdate::Update() Line 2033 C++ ndNewton_d.dll!ndWorld::SubStepUpdate(float timestep) Line 560 C++ ndNewton_d.dll!ndWorld::ThreadFunction() Line 476 C++ ndNewton_d.dll!ndWorldDefaultScene::ThreadFunction() Line 54 C++ ndNewton_d.dll!dThread::ThreadFunctionCallback() Line 111 C++ [External Code]
using code commit https://github.com/MADEAPPS/newton-dynamics/commit/3a9dec636e54ad75b1a3f14465d35e8078ec5173
That should not happen, position and rotation are independent, and not I do not think that's a race condition. is this in the Test cpp or something you write based on that.
This is in something I have written based off of test cpp.
The demo sandbox has way way too much going on to try and understand how to implement the library. Need a more basic set of examples to learn how to use the library so I learned what I could from test.
After further trial and error I have pinned down the direct cause being the value passed into ndWorld.Update() Too high or too low a value seems to throw this assert. Could be clamped to work around the problem but not sure what the min/max value can be here..
For your reference, I finally got the world stable with this main loop... Not sure but I may be calculating delta frame time incorrectly.. Physics simulation feels like it might be a little slow..
std::chrono::time_point<std::chrono::steady_clock> startFrame = std::chrono::high_resolution_clock::now();
std::chrono::time_point<std::chrono::steady_clock> endFrame = std::chrono::high_resolution_clock::now();
float deltaFrame = 0;
std::deque<float> Frames;
void PushFrameDelta(const float F) {
Frames.push_back(F);
if (Frames.size() > 30) {
Frames.pop_front();
}
}
const float GetDeltaFrames() const {
float DF = 0;
for (auto &F : Frames) {
DF += F;
}
return DF / Frames.size();
}
void VulkanDriver::mainLoop() {
while (!glfwWindowShouldClose(_Window)) {
//
// Mark Frame Start Time and Calculate Previous Frame Statistics
startFrame = std::chrono::high_resolution_clock::now();
float DF = GetDeltaFrames();
float FPS = (1.0f / DF);
if (_EventReceiver) {
_EventReceiver->_ConsoleMenu->SetStatusText(Gwen::Utility::Format(L"Stats (60 Frame Average) - FPS: %f - Frame Time: %f - Physics Time: %f - Scene Nodes: %i", FPS, DF, _ndWorld->GetUpdateTime(), _SceneGraph->SceneNodes.size()));
}
//
// Handle Inputs
glfwPollEvents();
//
// Perform Inputs
_EventReceiver->OnUpdate();
//
// Simulate Physics
//_ndWorld->Update(deltaFrame/1000.0f);
printf("Dela A %f B %f\n", deltaFrame, 1.0f/60.0f);
_ndWorld->Update(DF);
//
// Update Shader Uniforms
updateUniformBufferOffscreen(currentFrame);
updateUniformBufferComposition(currentFrame);
_SceneGraph->updateUniformBuffer(currentFrame);
//
// Draw Frame
Render();
//
// Mark Frame End Time and Calculate Delta
endFrame = std::chrono::high_resolution_clock::now();
deltaFrame = std::chrono::duration<double, std::milli>(endFrame - startFrame).count()/1000.f;
PushFrameDelta(deltaFrame);
}
//
// Wait for idle before shutting down
vkDeviceWaitIdle(_VulkanDevice->logicalDevice);
}
Any suggestions here?
More information.. Adding more substeps to the simulation also decreases the likelihood that this assert will trip. Setting 2 substeps with my current main loop trips the assert again.. 3 substeps seems fine for now but the more substeps you have the more processing that is required..
try sync again this was generate by a debug code committed by mistake.
Pulled latest source, still tripping this assert. Seems to be directly related to the timestep and amount of substeps.
> ndNewton_d.dll!ndQuaternion::ndQuaternion(const ndVector & unitAxis, float angle) Line 95 C++
ndNewton_d.dll!ndBodyKinematic::IntegrateVelocity(float timestep) Line 431 C++
ndNewton_d.dll!ndBodyPlayerCapsule::ResolveInterpenetrations(ndBodyPlayerCapsuleContactSolver & contactSolver, ndBodyPlayerCapsuleImpulseSolver & impulseSolver) Line 460 C++
ndNewton_d.dll!ndBodyPlayerCapsule::ResolveCollision(ndBodyPlayerCapsuleContactSolver & contactSolver, float timestep) Line 490 C++
ndNewton_d.dll!ndBodyPlayerCapsule::IntegrateExternalForce(float timestep) Line 801 C++
ndNewton_d.dll!`ndDynamicsUpdate::IntegrateUnconstrainedBodies'::`2'::ndIntegrateUnconstrainedBodies::Execute() Line 708 C++
ndNewton_d.dll!ndThreadPool::ExecuteJobs(ndThreadPoolJob * * const jobs) Line 147 C++
ndNewton_d.dll!ndScene::SubmitJobs<`ndDynamicsUpdate::IntegrateUnconstrainedBodies'::`2'::ndIntegrateUnconstrainedBodies>(void * const context) Line 262 C++
ndNewton_d.dll!ndDynamicsUpdate::IntegrateUnconstrainedBodies() Line 718 C++
ndNewton_d.dll!ndDynamicsUpdate::Update() Line 2022 C++
ndNewton_d.dll!ndWorld::SubStepUpdate(float timestep) Line 560 C++
ndNewton_d.dll!ndWorld::ThreadFunction() Line 476 C++
ndNewton_d.dll!ndWorldDefaultScene::ThreadFunction() Line 54 C++
ndNewton_d.dll!ndThread::ThreadFunctionCallback() Line 111 C++
Also a new one:
> ndNewton_d.dll!ndMatrix::TestOrthogonal(float tol) Line 289 C++
ndNewton_d.dll!ndBodyKinematic::IntegrateVelocity(float timestep) Line 437 C++
ndNewton_d.dll!ndBodyDynamic::IntegrateVelocity(float timestep) Line 287 C++
ndNewton_d.dll!`ndDynamicsUpdate::IntegrateBodies'::`2'::ndIntegrateBodies::Execute() Line 1362 C++
ndNewton_d.dll!ndThreadPool::ndThreadLockFreeUpdate::Execute() Line 38 C++
ndNewton_d.dll!ndThreadPool::ndWorkerThread::ThreadFunction() Line 65 C++
ndNewton_d.dll!ndThread::ThreadFunctionCallback() Line 111 C++
you have two different kind of code here, some that seems the player capsule, and some relate to time step. is this happening on that test demo in the download?
It looks like you fixed the original reason why this assert was being called. Now the issue has migrated into the callstack dealing with player capsule. Like before it only happens when I use a variable timestep OR if a dynamicBody comes in contact with my kinematicBody character controller. The character controller can touch static mesh fine, but touch dynamic body and trips assert.
oh I see, it comes from player capsule. I saw it. the crash bug is fixed now.
This was part of the problems of preparing the solve for GPU. what happen in the function integrate body is virtual. and I need to make non virtual so that I can call it form GPU. I removed it from the kinematic body, but the player capsule is now calling.
It is working now but is not correct because player code is moving the body, but also the solver and that is no correct. latter I have to make a special version of ndBodyKinematic::IntegrateVelocity(timestep) for the player.
but for now, is working and you probably won't notice the difference.
please sync again.
Looks like everything is running fine now without any asserts. great job! and thank you very much! :)
Followed basic 'Test' app for physics setup. Not sure where to being troubleshooting this one..
Runs fine changing 60 to 50...