scaling during runtime does not process intersecting bodies

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

scaling during runtime does not process intersecting bodies

Postby JoeJ » Sun Jan 26, 2014 1:03 pm

I have a big box and some smaller boxes resting on top if it.
Big box is scaled from 100-300%, animated by some sine.
I'd like to modify contact velocities, so the small boxes move nicely with the growing / shrinking big box.

The problem is that GenericContactProcess callback is almost never called -
no matter if there are intersections or empty space below (small boxes don't fall down like expected).
Sometimes it is called for a few steps but mostly not.

Seems like a sleeping issue, so i put this to force torque callback for every body:
NewtonBodySetSleepState(body, 0);
NewtonBodySetFreezeState(body, 0);
NewtonBodySetAutoSleep(body, 0);
... but it does not help. What could be wrong?
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Sun Jan 26, 2014 1:34 pm

As a workaround, the problem disappears if i do this:

NewtonInvalidateCache (world); // <--
NewtonUpdate (world, step);
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby Julio Jerez » Sun Jan 26, 2014 3:23 pm

if you scale a collision shape, there is no way the body will be awarded of that, even if so call SetFrezze, Freesisng deal with cinta constraints, where has no relation to the geometrey of a shape.

the only way to do that is by delete in the contact joint witch is what invalidate cache is doing.

A more efficient way is to call, which scale the collision and also notified the Broaphase of the change.

void NewtonBodySetCollisionScale (const NewtonBody* const bodyPtr, dFloat scaleX, dFloat scaleY, dFloat scaleZ)

try that, and se how it goes.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Sun Jan 26, 2014 3:52 pm

NewtonBodySetCollisionScale is a bit better, but it does not do the trick alone.
It seems this works:

NewtonBodySetCollisionScale
+ manually delete contacts
+ NewtonBodySetSleepState(body, 0) for affected bodies in force torque callback:


However, i might do something wrong on deleting contacts, because my code
Code: Select all
for (NewtonJoint* joint = NewtonBodyGetFirstContactJoint(body); joint;
                  joint = NewtonBodyGetNextContactJoint(body, joint))
            {
               for (void* contact = NewtonContactJointGetFirstContact (joint); contact;
                  contact = NewtonContactJointGetNextContact (joint, contact))
               {
                  NewtonContactJointRemoveContact (joint, contact);                         
               }
            }


causes a bad read access in dgList:

Code: Select all
void Unlink ()
      {
-->         if (m_prev) {
            m_prev->m_next = m_next;
         }

         if (m_next) {
            m_next->m_prev = m_prev;
         }
         m_prev = NULL;
         m_next = NULL;
      }


Is there a better way to delete contacts?
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Sun Jan 26, 2014 4:07 pm

Forget about it, this works:
Code: Select all
for (NewtonJoint* joint = NewtonBodyGetFirstContactJoint(body); joint;
                  joint = NewtonBodyGetNextContactJoint(body, joint))
            {
               while (void* contact = NewtonContactJointGetFirstContact (joint))
                  NewtonContactJointRemoveContact (joint, contact);                         
            }
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby Julio Jerez » Sun Jan 26, 2014 4:24 pm

JoeJ wrote:Forget about it, this works:
Code: Select all
for (NewtonJoint* joint = NewtonBodyGetFirstContactJoint(body); joint;
                  joint = NewtonBodyGetNextContactJoint(body, joint))
            {
               while (void* contact = NewtonContactJointGetFirstContact (joint))
                  NewtonContactJointRemoveContact (joint, contact);                         
            }


actually that code should be added to this NewtonBodySetCollisionScale function
I will do that, It is important that you call the NewtonBodySetCollisionScale because if you mak ehe collsion larger, the brad phase will no reside the AABB and it will no calculate the new contacts.
I will add that secund part that delete the concact
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: scaling during runtime does not process intersecting bod

Postby Julio Jerez » Sun Jan 26, 2014 4:36 pm

Ok I added, This is how the function look now.
Code: Select all
void NewtonBodySetCollisionScale (const NewtonBody* const bodyPtr, dFloat scaleX, dFloat scaleY, dFloat scaleZ)
{
   TRACE_FUNCTION(__FUNCTION__);
   dgBody* const body = (dgBody *)bodyPtr;
   dgWorld* const world = body->GetWorld();
   NewtonCollisionSetScale(NewtonBodyGetCollision(bodyPtr), scaleX, scaleY, scaleZ);
   world->GetBroadPhase()->ResetEntropy ();

   NewtonJoint* nextJoint;
   for (NewtonJoint* contactJoint = NewtonBodyGetFirstContactJoint(bodyPtr); contactJoint; contactJoint = nextJoint) {
      nextJoint = NewtonBodyGetNextContactJoint(bodyPtr, contactJoint);
      world->DestroyConstraint ((dgConstraint*)contactJoint);
   }
}
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Mon Jan 27, 2014 8:58 am

That's fine, now i don't need to set Sleep State manually to zero anymore :)

I had no luck making the boxes example work like expected, and i have doupts modifying contat acc is the right (or only) way to do it.
What i've done:
Calculate scaling velocity: (contact point - scaleBodyCom) * (newscale / oldscale - 1.0) / timestep
Either use this or make a relative velocity with the other body's velocity at contact point (I'm unsure if NewtonMaterialSetAcceleration expects relative or world values)
Rotate tangents to match scaling velocity direction.
NewtonMaterialSetAcceleration (scaleVel.Dot(normal btw. tangent) * some_constant), optionally subtract NewtonMaterialGetContactSpeed

To get reasonable results, some_constant needs to be 2-3 for tangent, and 500000 (!) for normal.
Small Boxes move in the right directions then and interpenetration is avoided, but simulation is not smooth, it's pretty jumpy.
Do you think it should be possible and i do something wrong?

There are the other solutions i see:

1. Before Scaling, create custom joints at contact position, they should successfully avoid penetration and do tangential motion with least friction as possible.
Delete the joints when scaling is done. I assume nonrealistic sideffects from this and also difficult to implement / slow, but my best bet so far.

2. Because realtime scaling might happen slowly and smoothly, it might suffice to temproary raise your 'penetration recovery speed' for affected bodies. Is that possible?
I mean the slow non-phsical motion you use to seperate interpenetrating bodies. This would not handle tangential motion, but it might be acceptable, pretty robust and easy to do.

3. You add the scaling velocity to your engine. (Lots of work? Performance drop?)
Even if you would do, there is another problem left:
Imagine there is a static rooftop above the scene. To use realtime scaling in games we would need to detect such a case, so that you can not further upscale objects to prevent penetration.
I assume this can be done by convex casting the small boxes on top in contact normal direction, and for the scaled box itself a temporary prescaled body might be tested somehow...
Sounds like "it will never work 100 %", but to be safe, upsacling of bodies in an island where one body has penetration > constant could be prohibited.

What do you think?

Here some Ascii-art to illustrate what i want:

Code: Select all
_O_O_
xxxxx
x   x

upscale table (small bodies (O) move up and sideways):

__O___O__
xxxxxxxxx
x       x
x       x

upscale table (small bodies move up only):

___O_O___
xxxxxxxxx
x       x
x       x


User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Thu Jan 30, 2014 6:01 am

NewtonBodySetJointRecursiveCollision does not have any effect, seems to be broken.
Strange is, even if i uncomment this in dgContact, bodies with a joint never collide against each other:

Code: Select all
void dgCollidingPairCollector::AddPair (dgContact* const contact, dgInt32 threadIndex)
{
   dgWorld* const world = (dgWorld*) this;
   dgBody* const body0 = contact->m_body0;
   dgBody* const body1 = contact->m_body1;
...
   /*if (!(body0->m_collideWithLinkedBodies & body1->m_collideWithLinkedBodies)) {
      if (world->AreBodyConnectedByJoints (body0, body1)) {
         return;
      }
   }*/



Can you fix this?
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Thu Jan 30, 2014 8:30 am

I tried to replace Newton contacts with custom joints and the result is good enough :D
I can even place box stacks on the growing / shrinking big box and all behaves like expected.
Two problems remain:
I need to model friction more accurate - you already gave me some advice, i need to look at that now...

The other problem comes from missing penetration depth information.
At the moment i predict penetration from the scale factor - in a perfect world that's accurate but actually the custom joint is unable to fix all penetration in one step,
and because i get only a single contact point from Newton i have no information about that accumulated error from previous steps.
I know penetration is calculated in Newton, but there's no function i can get it... could you add this? It's not the first time i miss it and it would be really useful.

EDIT:
Getting penetration is as easy as:

NewtonMaterial* const material = NewtonContactGetMaterial (contact);
float penetration = 0.5 * ((dgContactMaterial*) material)->m_penetration;
Last edited by JoeJ on Thu Jan 30, 2014 2:12 pm, edited 1 time in total.
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby Julio Jerez » Thu Jan 30, 2014 11:21 am

why don't you just copy the code from the friction joint
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Thu Jan 30, 2014 1:32 pm

Sure, but what code do you mean?
dgContact::JacobianContactDerivative ?
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby Julio Jerez » Thu Jan 30, 2014 3:11 pm

yes you can place a break point on this function
void dgContact::JacobianContactDerivative (dgContraintDescritor& params, const dgContactMaterial& contact, dgInt32 normalIndex, dgInt32& frictionIndex)

and see how it works
one thing I want to do for a long time is to expose user defined contacts, but I never put the time and effor to do int do it.

bascially t will be to subclass the dg Contact Joint and expose some functions, via the material interface
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Thu Jan 30, 2014 4:19 pm

Julio Jerez wrote:one thing I want to do for a long time is to expose user defined contacts, but I never put the time and effor to do int do it.


You should do, sounds like not so much work yielding lots of very cool and yet unexpected possibilities.
The sticky contacts idea you have is great, the single contact point for ragdoll foot idea i've tried is also promising, realtime scaling, easy motion control ...
All this is nice stuff for physics related gameplay like never seen before.
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: scaling during runtime does not process intersecting bod

Postby JoeJ » Tue Feb 11, 2014 9:24 am

I copied your code to a user joint and it works now like a standart contact - it was much easier than i thaught :)
There is one ugly thing:

class NewtonUserJoint: public dgUserConstraint
{
...
private:
dgContraintDescritor* m_param; // because this is private

friend myContactJoint; // ... i need to add this after every svn update
};

Is there a way i can get m_param without the friend :?: (Dunno cause i'm one of those who make everything public)


And for the penetration you use here: params.m_penetration[normalIndex] = penetration;
Ist it true i need to multiply the real world value by 2, like here: dgFloat32 penetration = (contactNormal % (contactPoint1 - contactPoint0)) * 2.0f; :?:
I ask because i need to do this to read the value from a standart contact: 0.5 * ((dgContactMaterial*) material)->m_penetration
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron