Transformation matrix / translation problem

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Transformation matrix / translation problem

Postby Shaderman » Fri Mar 11, 2016 4:45 am

Hi.

I'm thinking about writing a newton dynamics plugin for the ShiVa engine. My first tests look promising so far, but I obviously have a problem with the transformation matrix. Here's a short video showing the problem: https://youtu.be/D5a68Ivh-kU

This is my current transform callback code:

Code: Select all
void SetTransformCallback(const NewtonBody* body, const dFloat* matrix, int threadIndex)
{
   BodyUserData* bud = (BodyUserData*)NewtonBodyGetUserData(body);
   S3DX::AIVariable hObject = S3DX::object.fromStaticHandle(bud->staticHandle);

   dMatrix transform (matrix);
   dQuaternion rot (transform);

   S3DX::object.setRotationQuaternion(hObject, rot.m_q0, rot.m_q1, rot.m_q2, rot.m_q3, S3DX::object.kGlobalSpace);
   S3DX::object.setTranslation(hObject, transform.m_posit.m_x, transform.m_posit.m_y, transform.m_posit.m_z, S3DX::object.kGlobalSpace);
}


I guess i need to modify the transformation matrix before setting translation and rotation of the ShiVa object. Unfortunately I'm lost when it comes to matrices, so any help is appreciated.

Thanks

Shaderman
Shaderman
 
Posts: 66
Joined: Tue Mar 08, 2016 2:51 am

Re: Transformation matrix / translation problem

Postby Julio Jerez » Fri Mar 11, 2016 10:06 am

not the order of setting the rotation or translation can no cause that.
that looks like a frame interpolation problem. Does the Shiva engine implement frame interpolation?
if this is the case there must be a function for setting but rotation and translation under a critical section.

also you need to implement the newton debug display to find out what is going on. this will show what the actual collision shape is doing.
look at the file ..\applications\demosSandbox\sdkDemos\toolBox\DebugDisplay.cpp
for some examples.

Code: Select all
   dMatrix transform (matrix);
   dQuaternion rot (transform);
also if you use quaternion instead of matrices, you can ignore the matrix and call the function NewtonBodyGetRotation, this will give to the quaternion and will keep frame to frame consistency
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Transformation matrix / translation problem

Postby JoeJ » Fri Mar 11, 2016 11:26 am

Shaderman wrote:S3DX::object.setRotationQuaternion(hObject, rot.m_q0, rot.m_q1, rot.m_q2, rot.m_q3, S3DX::object.kGlobalSpace);


Have you tried changing order of quat numbers?
Most people use x,y,z,w, but Newton uses w,x,y,z.
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: Transformation matrix / translation problem

Postby Shaderman » Fri Mar 11, 2016 3:20 pm

Thanks for your replies guys.

Julio Jerez wrote:not the order of setting the rotation or translation can no cause that.
that looks like a frame interpolation problem. Does the Shiva engine implement frame interpolation?
if this is the case there must be a function for setting but rotation and translation under a critical section.

There are callbacks like for example when a engine frame update begins or ends.
I've moved the code transform code to such a frame-update-begin- callback this location, not using the Newton transform callback anymore. Unfortunately this change made no difference.
This is also the place where I run NewtonUpdate with the last frame time I get from the engine btw.

Julio Jerez wrote:also you need to implement the newton debug display to find out what is going on.

Thanks for the suggestion Julio. There's no accessible OpenGL interface in the engine, so I can't use the debug display I'm afraid.

Julio Jerez wrote:also if you use quaternion instead of matrices, you can ignore the matrix and call the function NewtonBodyGetRotation, this will give to the quaternion and will keep frame to frame consistency

Thanks for the advice.

JoeJ wrote:Have you tried changing order of quat numbers?
Most people use x,y,z,w, but Newton uses w,x,y,z.

Thanks JoeJ, it looks like this is the way to go, but still needs some work. I've changed the quat to x,w,z,y and got a little closer.
Please watch this and this short video.

In the first video, everything looks ok with the blue static box rotated around the Z-axis only. If I also change the rotation on the X- or Y- axis for this body, the problem shown in the 2nd video occurs.

I have only made changes to the translation and rotation of the bodies yet and assume I need to modify the collision matrix, too. Something like multiplying the identity matrix I use for collision creation with the required matrix changes from above.

Here's my current code, but I'm not sure what needs to be changed:

Code: Select all
NewtonCollision* CreateNewtonBoxCollision (NewtonWorld* world, S3DX::AIVariable staticHandle, int shapeId)
{
   S3DX::AIVariable hObject = S3DX::object.fromStaticHandle(staticHandle);
   S3DX::AIVariables<3> meshSize = getMeshSize(hObject, 0, true);

   dVector size(meshSize[0], meshSize[1], meshSize[2], 1.0f);
   dVector origin(0.f, 0.f, 0.f, 1.f);

   dMatrix offset(dGetIdentityMatrix());
   offset.m_posit = origin;

   return NewtonCreateBox (world, size.m_x, size.m_y, size.m_z, shapeId, &offset[0][0]);
}


Thanks again.

Shaderman
Shaderman
 
Posts: 66
Joined: Tue Mar 08, 2016 2:51 am

Re: Transformation matrix / translation problem

Postby Julio Jerez » Fri Mar 11, 2016 4:05 pm

I think Joe got it right, but
I've changed the quat to x,w,z,y and got a little closer.

That order makes no sense at all, do you mean change from (x, y, z, w) to (w, x, y, z) ?
basically you should write:
Code: Select all
S3DX::object.setRotationQuaternion(hObject, rot.m_q1, rot.m_q2, rot.m_q3, rot.m_q0, S3DX::object.kGlobalSpace);

I still suggest you implement the debug function.
you do not need opengl, all you need is a line drawing function.
after you get a way to see what the collision mesh is doing, you well see what is wrong.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Transformation matrix / translation problem

Postby Shaderman » Fri Mar 11, 2016 5:25 pm

Hi Julio,

let's go back to start. Here's another video showing collision debug lines, no matrix changes. Do you have an idea?

Btw things like NewtonCollisionForEachPolygonDo are sexy. I start loving Newton before I can make it work :mrgreen:

Thanks again for your help.

Shaderman
Shaderman
 
Posts: 66
Joined: Tue Mar 08, 2016 2:51 am

Re: Transformation matrix / translation problem

Postby Stucuk » Fri Mar 11, 2016 5:52 pm

Its the rotation. But did you do it as rot.m_q1, rot.m_q2, rot.m_q3, rot.m_q0 ?
User avatar
Stucuk
 
Posts: 801
Joined: Sat Mar 12, 2005 3:54 pm
Location: Scotland

Re: Transformation matrix / translation problem

Postby Shaderman » Fri Mar 11, 2016 6:06 pm

Hi Stucuk.

The last video was recorded using rot.m_q0, rot.m_q1, rot.m_q2, rot.m_q3, here's yet another video showing rot.m_q1, rot.m_q2, rot.m_q3, rot.m_q0.

Thanks

Shaderman
Last edited by Shaderman on Fri Mar 11, 2016 7:06 pm, edited 1 time in total.
Shaderman
 
Posts: 66
Joined: Tue Mar 08, 2016 2:51 am

Re: Transformation matrix / translation problem

Postby JoeJ » Fri Mar 11, 2016 6:26 pm

Now the debug lines are right, and just the graphics are wrong.
could be a handness issue, and you need to negate one axis of your matrix before you create the newton bodies (guessing x axis).
Or it is the same quat issue you have at body setup.
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: Transformation matrix / translation problem

Postby Julio Jerez » Fri Mar 11, 2016 6:30 pm

can you soon out so that we can see the entire scene?
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Transformation matrix / translation problem

Postby Julio Jerez » Fri Mar 11, 2016 6:56 pm

JoeJ wrote:Or it is the same quat issue you have at body setup.

most likely that, Shaderman when you create the bodies and the collision shapes,
after you get the quaternions from your entities to set the initial rotation, you also need to do the reversal of the q0, q1, q2, q3.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Transformation matrix / translation problem

Postby Shaderman » Fri Mar 11, 2016 7:03 pm

Halleluja, I think I've got it!

It works with q1, q2, q3, q0 on creation and on updates combined with

q.m_q0 = -q.m_q0;
q.m_q1 = -q.m_q1;

on creation.

Awesome guys, I really appreciate your fast help!

[EDIT]replaced the last video with a zoomed out version[/EDIT]

Shaderman
Shaderman
 
Posts: 66
Joined: Tue Mar 08, 2016 2:51 am

Re: Transformation matrix / translation problem

Postby JoeJ » Sat Mar 12, 2016 2:01 am

Shaderman wrote:It works with q1, q2, q3, q0 on creation and on updates combined with

q.m_q0 = -q.m_q0;
q.m_q1 = -q.m_q1;

on creation.


That's negating x axis (q1) and the angle part (q0) af the quat.
Makes some sense, but i still wonder you have to use different conventions on update and setup.
Be sure to check the case where bodies are rotated by random values around all 3 axis at setup.
Can you show your creation code? (DirectX also has different matrix order and you might need to transpose).
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: Transformation matrix / translation problem

Postby Shaderman » Sat Mar 12, 2016 11:57 am

Hi JoeJ,

it's strange indeed.

I didn't think about my test setup in the first place. Isn't it silly to just test with box models? How would I notice, if objects are rotated by 180 degree for example? My code worked visually with boxes, but not with objects where I can see wrong rotations... Shame on me :oops:

I obviously had too much code to determine problems. Today I've spent some time simplifying things.
First thing I did was to disable the transformation updates and started working with q0, q1, q2, q3 order. I've applied the engine rotation to a NewtonBody without any collision update yet. Note: the object rotation is correct. When I start the engine with Newton, I see the same as in the engine editor. So far, so good, but the collision rotation is wrong.
There aren't any Newton collision updates running, it just seems to be incorrect right after creation. Here's a screenshot:

Image

This is how I placed some objects in the scene, each with arbitrary rotation around all axes. Exactly what I've setup in the engine editor. As you can see, he collisions are rotated and I have no idea why.

Here's my current relevant code (not perfect for sure because I'm testing :) )

Code: Select all
S3DX::AIVariable staticHandle = S3DX::object.getStaticHandle(hObject);
dFloat mass = nMass.GetNumberValue();
NewtonCollision* shape = CreateCollisionBox (it->second, staticHandle, 0);
NewtonBody* const body = CreateRigidBody (it->second, staticHandle, shape, mass);
NewtonDestroyCollision(shape);
NewtonInvalidateCache(it->second);


Code: Select all
NewtonCollision* CreateCollisionBox (NewtonWorld* world, S3DX::AIVariable staticHandle, int shapeId)
{
   S3DX::AIVariable hObject = S3DX::object.fromStaticHandle(staticHandle);
   S3DX::AIVariables<3> meshSize = getMeshSize(hObject, 0, true);
   dVector size(meshSize[0], meshSize[1], meshSize[2], 1.0f);
   return NewtonCreateBox (world, size.m_x, size.m_y, size.m_z, shapeId, NULL);
}


Code: Select all
NewtonBody* CreateRigidBody (NewtonWorld* world, S3DX::AIVariable staticHandle, NewtonCollision* collision, dFloat mass)
{
   dVector origin;
   dVector inertia;

   S3DX::AIVariable hObject = S3DX::object.fromStaticHandle(staticHandle);
   S3DX::AIVariables<3> pos = S3DX::object.getTranslation(hObject, S3DX::object.kGlobalSpace);
   dVector position(pos[0], pos[1], pos[2]);
   S3DX::AIVariables<4> rot = S3DX::object.getRotationQuaternion(hObject, S3DX::object.kGlobalSpace);
   dQuaternion rotation(rot[0], rot[1], rot[2], rot[3]);
   dMatrix matrix(rotation, position);

   NewtonBody* const body = NewtonCreateDynamicBody(world, collision, &matrix[0][0]);
   
   //NewtonBodySetDestructorCallback (body, DestroyBodyCallback);
   
   NewtonConvexCollisionCalculateInertialMatrix (collision, &inertia[0], &origin[0]);   
   NewtonBodySetMassMatrix (body, mass, mass * inertia.m_x, mass * inertia.m_y, mass * inertia.m_z);
   NewtonBodySetCentreOfMass (body, &origin[0]);

   //NewtonBodySetForceAndTorqueCallback (body, ApplyForceAndTorqueCallback);
   //NewtonBodySetTransformCallback (body, SetTransformCallback);

   return body;
}


Thanks once again.

Shaderman
Shaderman
 
Posts: 66
Joined: Tue Mar 08, 2016 2:51 am

Re: Transformation matrix / translation problem

Postby JoeJ » Sat Mar 12, 2016 1:01 pm

Ok, i see you avoid the case where matrix order could be an issue, because you use only quats and positions.

First make sure about the quaternion numbers ordering in your engine.
Quaternion is similar to axis and angle rotation, three numbers store the axis (x,y,z) and w stores angle.
(That's not really true, but let's ignore those details).

Look for an axis and angle conversation in your quat class, for me this looks like:

__forceinline void FromAxisAndAngle (const qVec3 &axis, const float angle)
{
// memory order is xyzw for me
float rad = angle * 0.5f;
float scale = sinf(rad);
*((qVec3*)this) = axis * scale; // here i cast the quat directly to a vector, from that i know the first 3 numbers are xyz, because the axis vector is also xyz
w = cosf(rad); // here the 'angle' is set and i know it's the 4th number
}

So by looking at this function i could figure out what values store what even if i would not have written this myself, and the numbers would only be named float v[4].

When you're sure about that you need to reflect this here:

S3DX::AIVariables<4> rot = S3DX::object.getRotationQuaternion(hObject, 3DX::object.kGlobalSpace);
dQuaternion rotation(rot[0], rot[1], rot[2], rot[3]);

E.g. with my xyzw order i would need to change it to dQuaternion rotation(rot[1], rot[2], rot[3], rot[0]);
And the same of course any times when reading back a quat from newton.


Because you already tried that all and it still does not work, you most probably use a left handend coordinate system (DirectX) while Newton is right handed like OpenGL (or is it the other way around? Never sure what's left or right :)

Unfortunately i have no experince with this issue when using quaternions.
With a matrix you would need to negate one row or colum to flip direction,
but with quat it might be different because:
If you negate one axis number, you also need to negate the w number to ensure normalization gives 1 not -1, right?
I'm not sure if it works that way to give the expected rotation.
EDIT: Nonsense - signs are eliminated by squaring :oops:
Negate whatever you like :)

I suggest you create helper functions QuatFromNewton() and QuatToNewton() to ease the trial and error fun.



The rest of the post becomes obsolete because the nonsense above... :D

And if this does not work with all negation combinations, inside those functions convert the quat to a matrix, flip an axis and convert back to quat before you return.
Be warned that quat / matrix conversion may fail because it assumes correct handness, so use Newtons functions with dQuat and dMatrix, and your stuff with yours.
And also, Newton stores axis in rows, and yours may store them in rows.

Then, when it works it should be possible to figure out how to do this fast.
This has to happen to anybody at least once in life :)


EDIT: Because handness is only an issue with display, it should really be possible to make it work without any negations.
Last edited by JoeJ on Sat Mar 12, 2016 1:43 pm, edited 2 times in total.
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Next

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 6 guests