Scaling bodies

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Scaling bodies

Postby collerblade » Thu Jan 25, 2018 9:12 am

is there any way to scale bodies like collisions ? I mean NewtonBodySetScale() exists, but it scales the collision. If i have shared collision (for example car body hull, or millions of barrels), i want to scale them individually. Is that poosibile, or do i have to create separate collisions for every body. Is sharing collisions achive anything (speedwise)?
I think NewtonBodySetScale is a bit missleading now.
TY
collerblade
 
Posts: 88
Joined: Mon Apr 05, 2010 12:09 pm

Re: Scaling bodies

Postby Julio Jerez » Thu Jan 25, 2018 9:47 am

NewtonBodySetScale scale only the body passed in the argument nothing else.

Bodies shared collision instance not a collision. all shapes can be scaled independenly.
check out the scale demos.

and sharing shapes save lot of memory. shape has a complex connectivity graph that use substantial memory.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Scaling bodies

Postby JernejL » Thu Jan 25, 2018 12:02 pm

I think you mean NewtonBodySetCollisionScale function - newton 3 and not newton 3 NewtonBodySetScale?

Julio: i think this one will scale the collision shape and affect all other bodies using it:

newton.cpp:

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();
   NewtonCollision* const collision = NewtonBodyGetCollision(bodyPtr);

   dgFloat32 mass = body->GetInvMass().m_w > dgFloat32 (0.0f) ? body->GetMass().m_w : dgFloat32 (0.0f);
   NewtonCollisionSetScale (collision, scaleX, scaleY, scaleZ);

   NewtonJoint* nextJoint;
   for (NewtonJoint* joint = NewtonBodyGetFirstContactJoint(bodyPtr); joint; joint = nextJoint) {
      dgConstraint* const contactJoint = (dgConstraint*)joint;
      nextJoint = NewtonBodyGetNextContactJoint(bodyPtr, joint);
      //world->DestroyConstraint (contactJoint);
      contactJoint->ResetMaxDOF();
   }
    NewtonBodySetMassProperties (bodyPtr, mass, collision);
   body->UpdateCollisionMatrix(dgFloat32(0.0f), 0);
   world->GetBroadPhase()->ResetEntropy ();
}


What collerblade means is he'd like to share the shape and use it with different scales - you can't do that currently, but you could serialize the shape and make a new copy via unserialization, simplier bodies like cubes, spheres are easy to copy, maybe an idea for newton.. a routine which clones a shape, something like NewtonCollisionCreateIndependantCopy() ?
Help improving the Newton Game Dynamics WIKI
User avatar
JernejL
 
Posts: 1578
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Scaling bodies

Postby Julio Jerez » Thu Jan 25, 2018 12:32 pm

No this is not correct.
When a body is created, the body does not get a reference to the shape that is passed in. Instead it uses the shape as a copy constructor to make a complete new copy.
This new copy is what get a signed to the body.
Thy calling get collision on a body and compare it to the one that was use to make it, you will see they are different.
What different shape share, is the solid primitive that form the shape, which is just a geometrical object.

Look at file dgCollisionInstance.cop so that you can see how it works. All scaling, and matrix operation is done there and applylid to the solid collision that is shared.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Scaling bodies

Postby collerblade » Fri Jan 26, 2018 5:30 am

I was living in the last 10 years, knowing that collisions are unique, separated, reference counted objects. But -looks like- that was a lie.
If only the shapes are shared, but not the collision, why does collision reference counting exitst?
Why cant we create only shapes? And when we attach it to the body, than a collision is created (internally). Like in box2d.
How about compound collisions? are collisions copied, when added to compound collision?
collerblade
 
Posts: 88
Joined: Mon Apr 05, 2010 12:09 pm

Re: Scaling bodies

Postby Julio Jerez » Fri Jan 26, 2018 9:34 am

well part of the problem is trying to use a library as if it was a different library.
I do not know how those libraries do it, I only know how Newton does it.

in newton there is a class class dgCollisionInstance
which is the object that you get back whe you create a collision.
the object contain a reference to a unique collision shape that is managed by the world.

Take for example a box, there can be different boxes types based on the size but the are only one copy of each box of the same sizes. this is the code that makes a box

Code: Select all
NewtonCollision* NewtonCreateBox(const NewtonWorld* const newtonWorld, dFloat dx, dFloat dy, dFloat dz, int shapeID, const dFloat* const offsetMatrix)
{
   TRACE_FUNCTION(__FUNCTION__);
   Newton* const world = (Newton *)newtonWorld;
   dgMatrix matrix (dgGetIdentityMatrix());
   if (offsetMatrix) {
       matrix = dgMatrix (offsetMatrix);
   }
   return (NewtonCollision*) world->CreateBox (dx, dy, dz, shapeID, matrix);
}

and this is how the low lever object is created.
Code: Select all
dgCollisionInstance* dgWorld::CreateBox(dgFloat32 dx, dgFloat32 dy, dgFloat32 dz, dgInt32 shapeID, const dgMatrix& offsetMatrix)
{
   dgUnsigned32 crc = dgCollisionBox::CalculateSignature(dx, dy, dz);
   dgBodyCollisionList::dgTreeNode* node = dgBodyCollisionList::Find (crc);
   if (!node) {
      dgCollision* const collision = new  (m_allocator) dgCollisionBox (m_allocator, crc, dx, dy, dz);
      node = dgBodyCollisionList::Insert (collision, crc);
   }
   return CreateInstance (node->GetInfo(), shapeID, offsetMatrix);
}


you can see that it tries to find a box that matches the size of the box, if it does not find it, it makes a unique collision Box and add it to the cache. if it find one is just uses the node.
then it creates a box using that pointer to the box in the cache.
It is the call to CreateInstance that add a reference to the unique collision shape.

when you create a body of any kind, this is the function call
Code: Select all
void dgBody::AttachCollision (dgCollisionInstance* const collisionSrc)
{
   dgCollisionInstance* const instance = new (m_world->GetAllocator()) dgCollisionInstance (*collisionSrc);
   m_world->GetBroadPhase()->CollisionChange (this, instance);
   if (m_collision) {
      m_collision->Release();
   }
   m_collision = instance;
   m_equilibrium = 0;
}


you see that it creates a new collision instance from the argument, then it releases the collision that is in the body and assigns this new one.
the reason is uses reference is because other data structures has references to some collisions shape.

in the pass in new 1.0 the collision instance was part of the collision base class, and the cache uses the extra data like scale to make the hash, but that was making the cash bigger dificult to maintain. so it was separated quite earlly by the late version of newtion 1.5

this is the same for all shapes including compound and scene with the exception of soft bodies collisions which each get a duplicate of the shape.

Coumpound are trees of CollsionInstances, so each child is the same as a collision Instance on a body.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Scaling bodies

Postby collerblade » Fri Jan 26, 2018 9:44 am

Thanks Julio, everything is clear now.
collerblade
 
Posts: 88
Joined: Mon Apr 05, 2010 12:09 pm


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 7 guests

cron