"Ghosted Reactions Bug" [SOLVED]

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

"Ghosted Reactions Bug" [SOLVED]

Postby MeltingPlastic » Thu Aug 09, 2018 3:46 pm

I am getting some strange behavior with bodes experiencing "forces" or something when a non contacting body is moved. The following is a simple video where spheres come to a stable rest and I only add a force to the left most sphere and that results in other spheres moving:


https://youtu.be/9VyfMKva9Zo
This is in Debug Mode On VS2017

Edit: This only happens in debug mode. Release mode seems fine.
Double Edit: It does in fact happen in release mode as well - just slightly less frequent.
Last edited by MeltingPlastic on Sun Aug 12, 2018 3:07 pm, edited 1 time in total.
MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm

Re: "Ghosted Reactions Bug"

Postby Julio Jerez » Sat Aug 11, 2018 3:38 pm

ok I am trying to debug this, but the first thing I see is that the demo is different.
there is not gravity and the balls are close together.
been like that is a very different problems because touching one actives all the bodies that are touching, so is difficult to see if there is a bug of if is correct behavior.

can you set it jut like it is on the video, also make sure there is gravity so that it exposes the bug if they is one. this is how the scene looks like now which is different.
walkcycle1.png
walkcycle1.png (499.71 KiB) Viewed 4902 times


also if you change the demo, and you are make a repro, make sure you us ethe latest dll,
so that is has better chance to debug
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: "Ghosted Reactions Bug"

Postby MeltingPlastic » Sat Aug 11, 2018 5:20 pm

Here is a new demo with both of my issues (both built with latest newton commit: 1e1b8aa6112ff73b5ac1b660d1edd3b1df535cba)

https://drive.google.com/open?id=1XOPMOVhNeXfCjfQEEW5pi9NYbbpfu21C
MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm

Re: "Ghosted Reactions Bug"

Postby MeltingPlastic » Sat Aug 11, 2018 10:49 pm

Heres the latest demo this time without the compound collision bug in user side code from the other post:
https://drive.google.com/open?id=1OGJ635ggmoEx787oNqxQjPeiC90fpgXq

Click-holding and moving the sphere just applies a force to the center of the body proportional to the distance which is why it tends to oscillate un-damped.
MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm

Re: "Ghosted Reactions Bug"

Postby Julio Jerez » Sat Aug 11, 2018 11:52 pm

ok it is what I suspected, the problem is that when you apply the extra pick force to a body, for some reason it is applied to more than one.

this only happens in multithreaded mode, If set to run in single thread or thread emulation and is does not happens.

In Newton the force and torque call back is called in multithreaded mode, so when you set four thread you will be getting 4 force and torque call back at once.

if you are saving the pick body, somehow the pointer is changed to a different body and more than selected body get the same force applied.

you need to take care of that cituation. I cannot imagine how it manage to select more than one body, but I have noticed some engines and some languages do not deal with multithread, I do not think that's the case with your engine, but the pick body is getting mess-up in multithread mode.

here is a trace of what is happing, I just picked the ball on the left side, which happen to be body 16,
I traced the frame number, the body unique id, and if the force applied when is different than gravity, and you can see that body 16 get the pick force, but then some time other body also get the same force.
Body: 56, 17, 42 and 30 and that is th host force.

    frame: 1724
    16 1.532926 -1.691885 -2.485924

    two bodies get the same force
    frame: 1726
    16 1.125853 -1.444019 -1.822207
    59 1.125853 -1.444019 -1.822207

    frame: 1727
    16 0.855418 -1.291135 -1.394094
    frame: 1728
    16 0.620337 -1.146585 -1.020576
    frame: 1729
    16 0.422908 -1.012628 -0.705406
    frame: 1730
    17 0.264193 -0.891600 -0.450515
    16 0.264193 -0.891600 -0.450515

    two bodies get the same force
    frame: 1731
    17 0.143967 -0.786397 -0.255883
    16 0.143967 -0.786397 -0.255883

    frame: 1783
    16 -18.633497 6.495630 29.041204

    two bodies get the same force
    frame: 1784
    50 -17.239986 5.604869 26.243061
    16 -17.239986 5.604869 26.243061

    frame: 1785
    16 -15.342542 5.293510 23.082762
    frame: 1786
    16 -12.471945 4.694885 18.576246
    frame: 1787
    frame: 1788

    frame: 1810
    42 14.315579 -3.353570 -21.119461
    16 14.315579 -3.353570 -21.119461
    frame: 1811
    16 8.745609 -2.611737 -12.691769
    frame: 1812

    frame: 1836
    16 -5.621719 1.223242 7.739384
    frame: 1837
    16 -2.512180 0.674699 3.027277
    frame: 1838
    42 -0.836818 0.026788 0.621812
    16 -0.836818 0.026788 0.621812

    frame: 1856
    16 14.814254 -0.022406 -30.649712
    30 14.814254 -0.022406 -30.649712
    frame: 1857
    16 10.116482 -0.529484 -21.055931
    frame: 1858
    16 6.238332 -0.379757 -12.750408
    frame: 1859
    16 3.205807 -0.306992 -6.343636

Code: Select all
I am doing that by adding the debug code to the force an torque callback loop.

void dgBroadPhase::ApplyForceAndtorque(dgBroadphaseSyncDescriptor* const descriptor, dgBodyMasterList::dgListNode* node, dgInt32 threadID)
{
   dgFloat32 timestep = descriptor->m_timestep;
   const dgInt32 threadCount = m_world->GetThreadCount();
   while (node) {
      dgBody* const body = node->GetInfo().GetBody();
      body->m_resting = 1;
      if (DoNeedUpdate(node)) {
         if (body->IsRTTIType(dgBody::m_dynamicBodyRTTI)) {
            dgDynamicBody* const dynamicBody = (dgDynamicBody*)body;
            dynamicBody->ApplyExtenalForces(timestep, threadID);
if (dynamicBody->m_externalForce.m_x != 0) {
dgTrace (("%d %f %f %f\n", dynamicBody->m_uniqueID, dynamicBody->m_externalForce.m_x, dynamicBody->m_externalForce.m_y, dynamicBody->m_externalForce.m_z));
}

         }
      }

      for (dgInt32 i = 0; i < threadCount; i++) {
         node = node ? node->GetPrev() : NULL;
      }
   }
}
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: "Ghosted Reactions Bug"

Postby MeltingPlastic » Sun Aug 12, 2018 10:45 am

Interesting,

In Newton the force and torque call back is called in multithreaded mode, so when you set four thread you will be getting 4 force and torque call back at once.


Each callback is called for a unique body right? Ie in one newton "frame" no body should have its callback called twice. but many different bodies could have their callbacks called with potential overlap?


here is my callback - its pretty simple it just extracts my own NewtonRigidBody data structure from the userdata of the body. and then polls its "baked" force and torque and applies it:
Code: Select all
    void Newton_ApplyForceAndTorqueCallback(const NewtonBody* body, dFloat timestep, int threadIndex)
    {
        static dFloat Ixx;
        static dFloat Iyy;
        static dFloat Izz;
        static dFloat mass;
        static dVector netForce;
        static dVector netTorque;



        NewtonRigidBody* rigidBodyComp = static_cast<NewtonRigidBody*>(NewtonBodyGetUserData(body));

        rigidBodyComp->GetBakedForceAndTorque(netForce, netTorque);

        NewtonBodySetForce(body, &netForce[0]);
        NewtonBodySetTorque(body, &netTorque[0]);

    }


For some reason GetUserData is returning a non matching NewtonRigidBody sometimes.

In the main thread is where I use NewtonBodySetUserData. I am pretty sure I am not miss-matching userdata to bodies. If I were the effect would be constant.

Here is where I assign user data:
Code: Select all
            newtonBody_ = NewtonCreateDynamicBody(physicsWorld_->GetNewtonWorld(), resolvedCollision, &mat[0][0]);


            NewtonBodySetCollision(newtonBody_, resolvedCollision);

            mass_ = accumMass * massScale_;
            NewtonBodySetMassProperties(newtonBody_, mass_, resolvedCollision);

            NewtonBodySetUserData(newtonBody_, (void*)this);

            NewtonBodySetContinuousCollisionMode(newtonBody_, continuousCollision_);


            //assign callbacks
            NewtonBodySetForceAndTorqueCallback(newtonBody_, Newton_ApplyForceAndTorqueCallback);
            NewtonBodySetTransformCallback(newtonBody_, Newton_SetTransformCallback);
            NewtonBodySetDestructorCallback(newtonBody_, Newton_DestroyBodyCallback);

            bakeForceAndTorque();


Is it possible that GetUserData does not like to be called from a non-main thread?
MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm

Re: "Ghosted Reactions Bug"

Postby Julio Jerez » Sun Aug 12, 2018 12:39 pm

You can call get and set user data from anywhere.
Did you confirmed that in one frame you are getting mismatch user data?

The problem must be where to save the pointer to the body selected by the mouse, some how the function is called more than one with two different bodies,
We know the bodies are different because you can see they have different id.
Are you saying those body has the same use data?

If that is the case, you can test it by tracing the user data, along with the id.
I will try later, and I will commit the debug code so that you can test it.

If it turns out the user data changes, are you saying the somehow the user data is modified after the body was created. Other than set and get user data, the engine does not reference the user data anywhere else
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: "Ghosted Reactions Bug"

Postby Julio Jerez » Sun Aug 12, 2018 12:58 pm

I added the trace to teh use data, and no teh use data is no changing, but some how when picking a body in some case more than one body get teh same extra force, here is the trace
I commited the debug code so that you can run it and see what I did to test this.

    frame(569) body(16) 31cb4fe8 -0.000000 -0.463006 0.000000

    // two bodies get a diffrent force and torque call back
    frame(570) body(16) 31cb4fe8 -0.000000 -0.463006 0.000000
    frame(570) body(13) 31cb5420 -0.000000 -0.463006 0.000000

    frame(571) body(16) 31cb4fe8 -0.000000 -0.463006 0.000000

    frame(590) body(16) 31cb4fe8 -0.021799 -0.425815 0.031363

    // two bodies get a diffrent force and torque call back
    frame(591) body(21) 31cb48e0 -0.472476 -0.330577 0.464687
    frame(591) body(16) 31cb4fe8 -0.472476 -0.330577 0.464687

    frame(592) body(16) 31cb4fe8 -3.257755 1.352759 3.433551

    frame(593) body(16) 31cb4fe8 -6.229089 3.038258 6.511406

    frame(619) body(16) 31cb4fe8 1.909940 0.394057 -2.012341

    // two bodies get a diffrent force and torque call back
    frame(620) body(16) 31cb4fe8 2.352904 0.414872 -2.480146
    frame(620) body(18) 31cb4d18 2.352904 0.414872 -2.480146

    frame(621) body(16) 31cb4fe8 2.819798 0.418451 -2.973359

    frame(682) body(16) 31cb4fe8 5.659093 -0.068239 -5.919059

    // two bodies get a diffrent force and torque call back
    frame(683) body(16) 31cb4fe8 8.441802 0.077435 -8.800077
    frame(683) body(10) 31cb5858 8.441802 0.077435 -8.800077

you can see that body 16 always get the same user data body(16) 31cb4fe8
but in some frame some other body with its own user data also gets the same treatment.
To me this indicate that if has nothing to do with user data, is has to do with the code confusing the pointer to the pick body soem how it apply the extra force to more that one body at in the same frame when it get more than one call at the same time.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: "Ghosted Reactions Bug"

Postby MeltingPlastic » Sun Aug 12, 2018 2:53 pm

Found it! It was because I was using static variables in the callback which were not unique to each thread. Thanks!

Code: Select all
void Newton_ApplyForceAndTorqueCallback(const NewtonBody* body, dFloat timestep, int threadIndex)
    {
        static dFloat Ixx;
        static dFloat Iyy;
        static dFloat Izz;
        static dFloat mass;
        static dVector netForce;
        static dVector netTorque;



        NewtonRigidBody* rigidBodyComp = static_cast<NewtonRigidBody*>(NewtonBodyGetUserData(body));

        rigidBodyComp->GetBakedForceAndTorque(netForce, netTorque);

        NewtonBodySetForce(body, &netForce[0]);
        NewtonBodySetTorque(body, &netTorque[0]);

    }


Now I changed it to:
Code: Select all
void Newton_ApplyForceAndTorqueCallback(const NewtonBody* body, dFloat timestep, int threadIndex)
    {
        static thread_local dVector netForce;
        static thread_local dVector netTorque;



        NewtonRigidBody* rigidBodyComp = static_cast<NewtonRigidBody*>(NewtonBodyGetUserData(body));

        rigidBodyComp->GetBakedForceAndTorque(netForce, netTorque);

        NewtonBodySetForce(body, &netForce[0]);
        NewtonBodySetTorque(body, &netTorque[0]);

    }
MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm

Re: "Ghosted Reactions Bug"

Postby Julio Jerez » Sun Aug 12, 2018 3:06 pm

I was wondering about that, but i did not see anything there.
I was going to ask why are you using static variables in the first place, it seem to me that function should work if the variable are just simple local declaration.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: "Ghosted Reactions Bug" [SOLVED]

Postby MeltingPlastic » Sun Aug 12, 2018 3:07 pm

Yeah I could switch it to regular variables - I guess speed was on my mind. probably negligible though.
MeltingPlastic
 
Posts: 237
Joined: Fri Feb 07, 2014 11:30 pm


Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 7 guests

cron