NewtonBodyGetContactJoint() outside of NewtonUpdate()

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby agi_shi » Wed Nov 18, 2009 12:29 pm

This is extremely useful for when you don't want to do something inside a callback. For example, instead of using a critical section inside a callback to change unrelated bodies, I can just move this logic into the main thread and then retrieve all the contacts with NewtonBodyGetContactJoint().

Anyways, there seems to be some sort of bug in doing this with triggers and dynamic bodies. If the trigger is set as a trigger volume OR manually rejects contacts in the contact callback, then NewtonBodyGetContactJoint() will only return contacts with static (mass == 0) bodies. However, if the trigger is NOT a trigger volume and does NOT reject any contacts (that is, other bodies can bounce off the trigger), then NewtonBodyGetContactJoint() returns all of the contacts, including both static and dynamic (mass > 0) ones. Obviously, though, if bodies need to bounce off the triggers to be detected then the triggers aren't very useful :mrgreen:

I haven't tested doing this inside a callback, only outside of NewtonUpdate(). I can't move my code into a callback because of thread safety.
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm

Re: NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby Julio Jerez » Wed Nov 18, 2009 1:10 pm

this is interesting, I have no done too many test with triggers it many very well still have some bugs.
do you have a test to debug this?
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby agi_shi » Wed Nov 18, 2009 4:14 pm

Julio Jerez wrote:this is interesting, I have no done too many test with triggers it many very well still have some bugs.
do you have a test to debug this?

I don't, I'll make one ASAP and post back.
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm

Re: NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby Julio Jerez » Wed Nov 18, 2009 4:29 pm

excelent.

agi_shi wrote:Obviously, though, if bodies need to bounce off the triggers to be detected then the triggers aren't very useful :mrgreen:

I agree, that would be moronic would'n it :mrgreen:

I beleive the expected behavior should be:
-If the trigger is set as a trigger volume then NewtonBodyGetContactJoint() will only return contacts joint with zeri contacts.
-If you manually rejects contacts in the contact callback then NewtonBodyGetContactJoint() will not return any joint at all because joints with zero contacts are disposed.
The idea of using a triggers is presisetelly to eliminate unesesarry work of calculation contact just to be rejected them.

This behavior should work the same way inside or outside a call back.
Is that what you are exopecting?
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby agi_shi » Wed Nov 18, 2009 4:47 pm

Julio Jerez wrote:I beleive the expected behavior should be:
-If the trigger is set as a trigger volume then NewtonBodyGetContactJoint() will only return contacts joint with zeri contacts.
-If you manually rejects contacts in the contact callback then NewtonBodyGetContactJoint() will not return any joint at all because joints with zero contacts are disposed.
The idea of using a triggers is presisetelly to eliminate unesesarry work of calculation contact just to be rejected them.

This behavior should work the same way inside or outside a call back.
Is that what you are exopecting?


Yes, that's what I'm expecting. Here's the simplest test case for the issue:
Code: Select all
#include <Newton.h>

#include <iostream>
#include <map>
#include <string>

void gravity(const NewtonBody *body, float dt, int threadId)
{
    float g[] = { 0, -9.81f, 0 };
    NewtonBodyAddForce(body, g);
}

std::map<NewtonBody*, std::string> names;

void collide(const NewtonJoint *contact, float dt, int threadId)
{
    NewtonBody *body0 = NewtonJointGetBody0(contact);
    NewtonBody *body1 = NewtonJointGetBody1(contact);
    std::cout << "colliding " << names[body0] << " and " << names[body1] << "\n";
}

int main()
{
    NewtonWorld *world = NewtonCreate(NULL, NULL);
    NewtonSetThreadsCount(world, 1); // to avoid thread safety issues right now

    int defMat = NewtonMaterialGetDefaultGroupID(world);
    int diagMat = NewtonMaterialCreateGroupID(world);
    NewtonMaterialSetCollisionCallback(world, defMat, diagMat, NULL, NULL, &collide);

    NewtonCollision *triggerBox = NewtonCreateBox(world, 1.0f, 1.0f, 1.0f, NULL, 0);
    NewtonCollision *box = NewtonCreateBox(world, 1.0f, 1.0f, 1.0f, NULL, 0);

    // define to use a trigger volume, otherwise #undef it
    #define USE_TRIGGER_VOLUME

    NewtonBody *trigger = NewtonCreateBody(world, triggerBox);
    #ifdef USE_TRIGGER_VOLUME
    NewtonCollisionSetAsTriggerVolume(NewtonBodyGetCollision(trigger), 1);
    #endif
    names[trigger] = "trigger";
    {
        NewtonBodySetMassMatrix(trigger, 1, 1, 1, 1);
        float triggerM[16];
        NewtonBodyGetMatrix(trigger, triggerM);
        // dynamic trigger at [0,0.5,0] but with no force/torque callback
        triggerM[13] = 0.5f;
        NewtonBodySetMatrix(trigger, triggerM);
        NewtonBodySetMaterialGroupID(trigger, diagMat);
    }

    NewtonBody *floor = NewtonCreateBody(world, box);
    names[floor] = "floor";
    {
        // static floor at [0,0,0]
        NewtonBodySetMassMatrix(floor, 0, 0, 0, 0);
    }

    NewtonBody *falling = NewtonCreateBody(world, box);
    names[falling] = "falling";
    {
        NewtonBodySetMassMatrix(falling, 1, 1, 1, 1);
        float fallingM[16];
        NewtonBodyGetMatrix(falling, fallingM);
        fallingM[13] = 5.0f;
        // falling box at [0,5,0]
        NewtonBodySetMatrix(falling, fallingM);
        NewtonBodySetForceAndTorqueCallback(falling, &gravity);
    }

    const float FREQ = 1.0f / 60.0f;
    for (float t = 0.0f; t < 10.0f; t += FREQ)
    {
        NewtonUpdate(world, FREQ);
    }

    NewtonDestroyAllBodies(world);
    NewtonReleaseCollision(world, triggerBox);
    NewtonReleaseCollision(world, box);
    NewtonDestroy(world);
}


With #define USE_TRIGGER_VOLUME, we get:
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
[more collisions with only the floor]
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor


#undef USE_TRIGGER_VOLUME and we get this output:
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and floor
colliding trigger and falling
colliding trigger and falling
colliding trigger and floor
colliding trigger and floor
colliding trigger and falling
colliding trigger and falling
colliding trigger and floor
colliding trigger and floor
colliding trigger and falling
colliding trigger and falling
colliding trigger and floor
colliding trigger and floor
colliding trigger and falling
colliding trigger and floor
colliding trigger and falling
colliding trigger and floor
colliding trigger and falling
colliding trigger and falling
colliding trigger and falling
colliding trigger and falling
colliding trigger and floor
colliding trigger and falling
colliding trigger and floor
colliding trigger and falling
colliding trigger and floor
colliding trigger and falling
colliding trigger and floor
colliding trigger and falling

This time, the trigger clearly collides with not only the floor, but the falling box, as well. (Except in this case the box would rest on top of the trigger, which is unwanted.)
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm

Re: NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby Julio Jerez » Wed Nov 18, 2009 5:26 pm

Looking at teh problem I this I knwo what coul be teh problems

Code: Select all
  NewtonCollision *triggerBox = NewtonCreateBox(world, 1.0f, 1.0f, 1.0f, NULL, 0);
   NewtonCollision *box = NewtonCreateBox(world, 1.0f, 1.0f, 1.0f, NULL, 0);

these two object will have the same pointer, so when you set one as trigget the oteh will also be a trigget.

Before I debug tonigh try this setting an ID to the Box that will be set as trigger volume, tah will foce teh cache to crate a different incance
Code: Select all
*triggerBox = NewtonCreateBox(world, 1.0f, 1.0f, 1.0f, NULL, 1);

see if it makes any difference.

locking more at the code, I believe that'st the problem when you make the Box a trigger volume then both are becoming trigger volumes,
this why you are only getting floor and trigget volume in the first test. Trigger volumes do not get reponded with trigger volumes.
try doing what I said and run the test again.

also you do get the call back for a trigger volome, but if you react the contact count you will see tha is is zero.
it have to be that way because then tehr will be no way to knwo if a body is in a trogget volume space.
of couse with the iterators you can now but for consistency the materail call back need to be called too.
if the call back you can check by using GetFirstContact() and it will be zero.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby agi_shi » Wed Nov 18, 2009 5:44 pm

Julio Jerez wrote:locking more at the code, I believe that'st the problem when you make the Box a trigger volume then both are becoming trigger volumes,
this why you are only getting floor and trigget volume in the first test. Trigger volumes do not get reponded with trigger volumes.
try doing what I said and run the test again.

You're right, that fixes it. (BTW, I screwed up the parameters, it should by 0 or 1 then NULL, not the other way around, but since NULL is 0 in C++, MSVC didn't say anything)

This is actually kind of weird, since in my main project collisions aren't shared. In fact, only the trigger is a box, and then all the dynamic objects are independent convex hull modifiers. So I'm not sure how to fix it in my main project...
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm

Re: NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby Julio Jerez » Wed Nov 18, 2009 5:57 pm

yes I saw the you had the parameterr transposed.
Maybe I should add ther trigger are a creation option so tha triger are unique by definition.

anyway, there still could be a bug, that bug was probaly a new one in the test you wrote, it does no necesarilly means it was the bug you are having in the project.
check make sure you do not have any side effects with collision shapes chnaging behavior .

what I would do is I use a Unique collision Shape ID for triggers,
#define MY_TRIGGER (and wierd value)
and run that test again, and if still does not work maybe you can send me a binary that I can test.

had you seen the Wiki Tutorial whe I implement a Hash Based material system using the Collision Ids and instead of Body gruop ID?
It is very simular to teh one in the engine but is is more flexible because it is unified for all shape types.
plus you get all the code funtionality to make your own changes.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: NewtonBodyGetContactJoint() outside of NewtonUpdate()

Postby Julio Jerez » Sun Nov 22, 2009 8:34 am

did you find the Bug? or it is still there?
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 0 guests

cron