Game Development Community

Some odd matrix math(help needed)

by Benj · in Torque Game Engine · 10/31/2007 (2:15 pm) · 7 replies

Ok so, i made a console method for getting the offset of a point in a scene objects local object space using its inverse matrix.

that works.

now i wanted to make one that does the same with a script transform(position and axis angle).
this i'am having some problems with.

ConsoleMethod( SceneObject, transformToObjectSpace, const char*, 3, 3, "Multiplies a given transform by the objects inverse matrix(turning it to local object space)")
{
   char *returnBuffer = Con::getReturnBuffer(256);
   const MatrixF& imat = object->getWorldTransform();
   MatrixF mat;
   AngAxisF inputaa(mat);
   Point3F inputpos,pos;

   dSscanf(argv[2], "%g %g %g %g %g %g %g",
           &inputpos.x, &inputpos.y, &inputpos.z, &inputaa.axis.x, &inputaa.axis.y, &inputaa.axis.z, &inputaa.angle);

   inputaa.setMatrix(&mat);
   mat.setColumn(3,inputpos);

   mat.mul(imat);

   mat.getColumn(3, &pos);
   AngAxisF aa(mat);

   dSprintf(returnBuffer,256,"%g %g %g %g %g %g %g",
            pos.x,pos.y,pos.z,aa.axis.x,aa.axis.y,aa.axis.z,aa.angle);

   return returnBuffer;
}

i go in, place a object next to me, i open the console type a line in(ill post it here)
==>echo(1551.transformtoobjectspace(1562.gettransform()));
-5.33127 -10.162 32.0896 0.980506 -0.165641 0.10569 0.0914535

==>echo(1551.pointtoobjectspace(1562.getposition()));
0.18336 3.89822 -0.329147

==>echo(1551.gettransform());
450.044 277.742 221.366 0 0 1 0.0900025

==>echo(1562.gettransform());
450.577 281.608 221.037 0.669368 -0.0823103 0.738365 0.134901

the point version is correct, the transform is way off....

any ideas?

#1
10/31/2007 (7:06 pm)
Even weirder, i expose the inverse transform of a scene object to torquescript (copy and pasted gettransform but changed which matrix) and do the multiplication from script side, and i get the same off the wall result, yet when i do it as point x matrix i get the right result, eg a offset in local object space.
#2
10/31/2007 (11:11 pm)
Matrix multiplication is not communitive. I suspect you're multiplying the matrices in the wrong order. Try:

const MatrixF& transMat = object->getWorldTransform();
   MatrixF inMat; = input from script

   MatrixF outMat;
   outMat.mul(transMat, inMat);
   // return outMat

M.mul(a) = M * a -> M
M.mul(a, b) = a * b -> M
(see math/mMatrix.h)

Note that Matrix.mul(point) is actually "M * p -> p". The transformer goes first. M.mul(a) should be "M * a -> a" to be consistent with M.mul(p), but it isn't; so you'll want the M.mul(a,b) function instead.
#3
11/01/2007 (7:00 am)
Then why do i get the same off the wall result when i do matrixmul from torquescript with the world transform?

not sure what you meant about the mulp one but, my point version is this.
ConsoleMethod( SceneObject, pointToObjectSpace, const char*, 3, 3, "Multiplies a given point by the objects inverse matrix(turning it to local object space)")
{
   char *returnBuffer = Con::getReturnBuffer(128);
   const MatrixF& mat = object->getWorldTransform();
   Point3F p(0.0f, 0.0f, 0.0f);

   dSscanf(argv[2], "%g %g %g", &p.x, &p.y, &p.z);

   mat.mulP(p);

   dSprintf(returnBuffer, 128, "%g %g %g", p.x, p.y, p.z);
   return returnBuffer;
}

and it works fine.

i will try the separate matrix thing though.

edit: just tried:
outmat.mul(imat,mat);

didn't work.
#4
11/01/2007 (8:40 am)
Quote:Then why do i get the same off the wall result when i do matrixmul from torquescript with the world transform?

Probably because you're multiplying the matrices in the wrong order there too. What does your script multiplication look like?

Quote:not sure what you meant about the mulp one

What I mean is that if you compare Matrix::mul(Matrix) with Matrix::mulP(Point), you'll find they are inconsistent in their behavior.

Perhaps you're confusing yourself by not keeping your variable names consistent? in your Point function, let's change it to read:

ConsoleMethod( SceneObject, pointToObjectSpace, const char*, 3, 3, "Multiplies a given point by the objects inverse matrix(turning it to local object space)")
{
   char *returnBuffer = Con::getReturnBuffer(128);
   const MatrixF& [b]imat[/b] = object->getWorldTransform();
   Point3F p(0.0f, 0.0f, 0.0f);

   dSscanf(argv[2], "%g %g %g", &p.x, &p.y, &p.z);

   [b]imat[/b].mulP(p);

   dSprintf(returnBuffer, 128, "%g %g %g", p.x, p.y, p.z);
   return returnBuffer;
}

Now we'll take a direct comparison between your Point and Matrix multiplication functions:

imat.mulP(p) = imat * p
mat.mul(imat) = mat * imat

See the problem? Whereas

outMat.mul(imat, mat) = imat * mat

which is correct.

Quote:didn't work.

I tested it briefly to be sure, and found it to work fine. Perhaps you forgot to change the return values?

outmat.mul(imat, mat);

   [b]outmat[/b].getColumn(3, &pos);
   AngAxisF aa([b]outmat[/b]);

   dSprintf(returnBuffer,256,"%g %g %g %g %g %g %g",
            pos.x,pos.y,pos.z,aa.axis.x,aa.axis.y,aa.axis.z,aa.angle);

   return returnBuffer;
#5
11/01/2007 (10:19 am)
I get what your saying, its still spitting out the wrong values though. with this code
ConsoleMethod( SceneObject, transformToWorldSpace, const char*, 3, 3, "Multiplies a given transform(hopefully object space) by the objects matrix(turning it to world space)")
{
   char *returnBuffer = Con::getReturnBuffer(256);
   const MatrixF& imat = object->getTransform();
   MatrixF mat,outmat;
   AngAxisF inputaa(mat);
   Point3F inputpos,pos;

   dSscanf(argv[2], "%g %g %g %g %g %g %g",
           &inputpos.x, &inputpos.y, &inputpos.z, &inputaa.axis.x, &inputaa.axis.y, &inputaa.axis.z, &inputaa.angle);

   inputaa.setMatrix(&mat);
   mat.setColumn(3,inputpos);

   outmat.mul(imat,mat);

   outmat.getColumn(3, &pos);
   AngAxisF aa(outmat);

   dSprintf(returnBuffer,256,"%g %g %g %g %g %g %g",
            pos.x,pos.y,pos.z,aa.axis.x,aa.axis.y,aa.axis.z,aa.angle);

   return returnBuffer;
}

about the multiplication order, whats strange is when i do it on paper it works out as the matrix X the inverse, as when i test the math part in blender threw scripting.
#6
11/01/2007 (10:31 am)
O_o When did it become transformToWorldSpace? Are you sure you're working with the correct function?
#7
11/01/2007 (12:44 pm)
Errrrr..... >_>..... pay no attention to the man behind the curtain...... lol whoops, works now, thanks lol