MADEAPPS / newton-dynamics

Newton Dynamics is an integrated solution for real time simulation of physics environments.
http://www.newtondynamics.com
Other
951 stars 182 forks source link

Crash in dgBody::GetFirstContact #146

Closed TrevorCash closed 5 years ago

TrevorCash commented 5 years ago

Got a random crash where joint is null in dgBody::GetFirstContact

image

Not yet sure how to reproduce.

Configuration was double precision, release. no acceleration plugins

JulioJerez commented 5 years ago

can you set a breakpoint on the function and run in debug to see the trace stack? I do not think the trace stack is valid.

TrevorCash commented 5 years ago

this is a better stack trace in my usage: image

my function is formContacts() which iterates over all contacts of a body. somehow node->GetInfo().m_joint is null - even though the body is valid in dgBody::GetFirstContact()

TrevorCash commented 5 years ago

Here is the call in my code that crashes: image

JulioJerez commented 5 years ago

tell tow more things. 1-Is thsi new wit the double, or does I happens in single mode 2-does this happen in single threaded mode. 3-in the trace stack I do not see any link for a newton call back. are you doing it from outside a newtion update?

I have no test that for a while, and with teh changes is possible is bloke, It seem impossible that a node in teh graph has a null contact, but that what is seem to be. if you can answer those question so that I can set a debug case.

JulioJerez commented 5 years ago

Ah also I assume this was a debug build?

TrevorCash commented 5 years ago

Yes Debug, multithreaded,

I am not using the callback - I am iterating the contacts outside the update.

I'll see if I can get a debugable demo too. It only crashes sometimes though

JulioJerez commented 5 years ago

Ah iterating outside the update should be even more secure. Just for narrowing some more, can you try in single thread mode?

TrevorCash commented 5 years ago

I can't get it to crash in single threaded.

Here is the Debug, multithreaded demos - they are hard for me to get to crash now, So I'm not sure. maybe a script could be made to loop-start the program untill it crashes.

https://drive.google.com/open?id=1NBjk9PZjWfUiLgbkGrRJB7gFTYacmgwn

TrevorCash commented 5 years ago

the 11_physics should in theory give the original crash. 201_physicstests gives aanother repeatable crash I am not sure what is causing.

JulioJerez commented 5 years ago

I see the assert, but I can't debug static libraries. you to linked it to a newton dll,

can you link to the newton dlls? also tell me what dll, double or single, 64 or 32 bit?

JulioJerez commented 5 years ago

It seem some routine is generation a bogus contact point with a bad normal here DG_INLINE dgVector dgCollisionInstance::SupportVertexSpecial (const dgVector& dir, dgInt32* const vertexIndex) const { dgAssert (dir.m_w == dgFloat32 (0.0f)); dgAssert(dgAbs(dir.DotProduct(dir).GetScalar() - dgFloat32(1.0f)) < dgFloat32(1.0e-2f));

the may be a bug in teh double vector class, are you linking to double? al I did not see the plugin dlls, I am confused.

JulioJerez commented 5 years ago

ok I beleive the orginal bug dgBody::GetFirstContact is fixed now. I was confused wondering why I did not get it and it was because when I call that function, I do it from a callback. in the callback the joint is always valid since is passed as the argument.

for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
….

you are iterating over the contact joint on a body, there is nothing wrong with that, because is part of the interface, is it only that this the style use by other libraries where the do the update then quiery the scene for the result. I prefer the event driven system where you set a function to handle even when the happens.

what happen is that the engine is lazy, a body can have some dead joints that has not been deleted yet but that are inactive, this was an optimization that try to eliminator the churning that happens when two bodies come in close contact because the aabb overlap, but they are not colliding yet, in the case the engine create the link between the two bodies but there is not joint. then if the bodies later collide the joint is created, but many time the body aabb are simple overlapping and no colliding. adding a check for NULL fix it.

The otherhe problem that I saw is the assert on a contact normal that was not a unit vector, this will happen in debug and would happens with non uniform scale, are you doing that?

to my knowledge the normal should be proper normalized, but is possible that I missed one, in the demo I see you have cones, and some otherh shape but I do not see the error by inspecting the code.
so when you sync, if the asserts happens in

DG_INLINE dgVector dgCollisionInstance::SupportVertexSpecial (const dgVector& dir, dgInt32* const vertexIndex) const please let me know, the should be reproducible and has nothing to do with the latest changes. In fact I cannot make it happen in the sandbox

JulioJerez commented 5 years ago

I saw you close teh bug, did you get it running?

TrevorCash commented 5 years ago

I saw you changed that code - I'll try again soon. It was running before and was just very hard to replicate.

I'll reopen if I see any issues again because I think there are still a few issues I am having. (I need to spend some time and get debug dlls working with the Urho3D cmake system again)

Sorry for the confusion earlier

JulioJerez commented 5 years ago

I though early you have set up to link to dlls, That's usually good for sharing repro bugs.

TrevorCash commented 5 years ago

Ok here is a crash I am getting, this is from the latest master branch:

In this particular demo I am calling NewtonBodySetMatrix() after every newton update. Sometimes I get an error related to body equalibrium. https://drive.google.com/open?id=1SW8vCpnxkuRLQ5lt151Df28Ua7pBIffw.

This build has dlls in it.

TrevorCash commented 5 years ago

I call NewtonBodySetSleepState before every call to NewtonBodySetMatrix()

JulioJerez commented 5 years ago

I see a walking animation, it did not crash, do I have to do anything?

TrevorCash commented 5 years ago

Oh right click i think to tilt the platform around

JulioJerez commented 5 years ago

I see you call from outside

void dgBroadPhase::UpdateBody(dgBody* const body, dgInt32 threadIndex)
{
    if (m_rootNode && !m_rootNode->IsLeafNode() && body->m_masterNode) {
        dgBroadPhaseBodyNode* const node = body->GetBroadPhase();
        dgBody* const body1 = node->GetBody();
        dgAssert(body1 == body);
        dgAssert(!body1->m_equilibrium);

and that some how chaging the state of the body. Tell me this when you said crash, do you mean assert, of a hard crash that terminate the application.

TrevorCash commented 5 years ago

An assert not a hard crash

Get Outlook for Androidhttps://aka.ms/ghei36


From: NewtonDynamics notifications@github.com Sent: Sunday, February 17, 2019 5:54:57 PM To: MADEAPPS/newton-dynamics Cc: Trevor Cash; State change Subject: Re: [MADEAPPS/newton-dynamics] Crash in dgBody::GetFirstContact (#146)

I see you call from outside

void dgBroadPhase::UpdateBody(dgBody const body, dgInt32 threadIndex) { if (m_rootNode && !m_rootNode->IsLeafNode() && body->m_masterNode) { dgBroadPhaseBodyNode const node = body->GetBroadPhase(); dgBody* const body1 = node->GetBody(); dgAssert(body1 == body); dgAssert(!body1->m_equilibrium);

and that some how chaging the state of the body. Tell me this when you said crash, do you mean assert, of a hard crash that terminate the application.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHubhttps://github.com/MADEAPPS/newton-dynamics/issues/146#issuecomment-464537672, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ACcNi7auQ0ekrBV2db8B02ag5coyUg8Dks5vOfnhgaJpZM4a-kUG.

TrevorCash commented 5 years ago

The UpdateBody call originates from my call NewtonBodySetMatrix

TrevorCash commented 5 years ago
  1. NewtonBodySetMatrix
  2. SetMatrixResetSleep
  3. SetMatrix
  4. UpdateCollisionMatrix
  5. UpdateBody
JulioJerez commented 5 years ago

Ah ok, thsi should be eassy to fix, basically you are moving a static body which should be in equilibrium by definition. basically the function void NewtonBodySetMatrix(const NewtonBody const bodyPtr, const dFloat const matrixPtr) should activate the body before calling SetMatrixResetSleep I will fix it later.

TrevorCash commented 5 years ago

I do have a call to NewtonBodySetSleepState(newtonBody_, false); right before NewtonBodySetMatrix. So maybe its not working all of the time?

I added that early on in my integration to force wake the body.

JulioJerez commented 5 years ago

Now I am confused, I added the call and and the assert still happens, which means you must be running asyncrnous update, is this the case?

On Sun, Feb 17, 2019, 5:31 PM Trevor Cash <notifications@github.com wrote:

I do have a call to NewtonBodySetSleepState(newtonBody_, false); right before NewtonBodySetMatrix. So maybe its not working all of the time?

I added that early on in my integration to force wake the body.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MADEAPPS/newton-dynamics/issues/146#issuecomment-464545813, or mute the thread https://github.com/notifications/unsubscribe-auth/AHxHpEm1lnY69QdjcIHNeG5IOqVb0iQuks5vOgJsgaJpZM4a-kUG .

TrevorCash commented 5 years ago

Ah! That was my mistake - it is asynchronous. I just need to add a sync before the set matrix call!

JulioJerez commented 5 years ago

yes you just call NewtonWaitForUpdateToFinish before you are going to change the state of a body. this is why there is the listener, that allowed you do that kind of game play logic at the appropriate time.

you do not really want to change the state of collision object at drawing time, that lead to jiter and strange behavior that seem like bug, but is just state changes at the wrong time. check out some of the listener demo there are very easy to implement, and are not intrusive to the higher lever game engine. once you understand the Joints listeners are even easier.

the only down part is that once you start using listener, you start to separate from the way other engines do things, but that is an inevitable consequence.

TrevorCash commented 5 years ago

Got it, Makes sense - not sure why it did not occur to me earlier.