Sign in to follow this  

local vs world coordinates

This topic is 4682 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I understand matrix transformations but I can't make them work. I cant mix rotations and translations. How do I calculate the Loc coords(relative to object B) of object A(given in Wld coords). I have no problem finding the Loc rotations so I leave them out. objA relative to objB (WORLD->LOCAL) Given: ObjA Wpos = (wxA, wyA, wzA) ObjB Wpos = (wxB, wyB, wzB) ObjB Wrot = (whB, wpB, wbB) (h=heading, p=pitch, b=bank) Q: ObjA Lpos relative to ObjB = (lxA, lyA, lzA) (rotation is not needed) I'm creating 2 4x4 matrices with the given coords, one for each object. I multiply MatrixObjA with the inverse of MarixObjB. Should work but I get strange results as soon as I start moving ObjA away from Wpos (0,0,0). The problem is that I find too much information about this issue. I can't filter what I need and what I don't... Where can I find some clean code / function / explanation for this simple problem. Thanx in advance.

Share this post


Link to post
Share on other sites
Do I have to separate translation and rotation in order to inverse them?

If I do, is this how I inverse the translation of MatrixObjB:
inverse of
| 1 0 0 wxB|
| 0 1 0 wyB|
| 0 0 1 wzB|
| 0 0 0 1 |
=
| 1 0 0 -wxB|
| 0 1 0 -wyB|
| 0 0 1 -wzB|
| 0 0 0 -1 | or | 0 0 0 1 | (???)

Share this post


Link to post
Share on other sites
I tested all possibilities.

Using separate Translation/Rotation Matrices.
Inverting The one/the other.
...

Pfff, I know the sollution is very simple but I can't get there...

Help me out of this pit of doom...
THX

[Edited by - Ljilekor on February 13, 2005 9:58:29 AM]

Share this post


Link to post
Share on other sites
A function relativeTo() would take care of all parenting issues by using only vectors as arguments.

relativeTo(vec3d LPosResult, vec3d LRotResult, vec3d WPosObjB, vec3d WRotObjB, vec3d WPosObjA, vec3d WRotObjA)

Resulting in LPosResult and LRotResult containing the Local coords and orientation of ObjB relative to ObjA.

Could somebody show me how to code such a function, please.
(Nobody is answering... Is it because it's too basic/simple or ...)

Share this post


Link to post
Share on other sites
Let say you have a root (in this case parent), and a child inheriting this transform. Now as the root defines what is world coordinates you need to apply this transform to the child to get the childs world coordinates.
This transform is done as follows:


worldtrans.scale_ = root.scale_ * scale_;
worldtrans.rotation_ = root.rotation_ * rotation_;
worldtrans.translation_ = root.translation_ + root.scale_ * (root.rotation_ * translation_);




Then you have your worldtransform, which actually gives you the modelview matrix directly:

scale*rotation[0][0], rotation[1][0], rotation[2][0], 0.0f,
rotation[0][1], scale*rotation[1][1],rotation[2][1], 0.0f,
rotation[0][2],rotation[1][2], scale*rotation[2][2], 0.0f,
translate.x_, translate.y_, translate.z_, 1.0f


Note that this is actually the transpose of the modelview matrix (some opengl code).

Regards

Share this post


Link to post
Share on other sites
Quote:
(Nobody is answering... Is it because it's too basic/simple or ...)


No, it's not too basic or simple. Well, it is 'basic' as far as 3D math goes, but it's not simple. Transformations and rotations, coordinate systems, inverses, etc. can be pretty hard to get your head around, and there are many opportunities for error to be introduced.

If I understand correctly, you're trying to express the vertices of object A in the local space of object B. Let's assume that each has a 4x4 transformation matrix. First you need to get the verts from A's local space into world space, for which you should be able to use its matrix directly. Then, you need to get those world-space coordinates into B's local space, for which you should be able to use B's inverted matrix. By multiplying A's matrix with B's inverted matrix, you should get a matrix that transforms points from A's local space to B's local space. Perhaps you already know all this.

In any case, there are a lot of places where things can go wrong. Row- or column-major, order of multiplication, and so on. So I can't really tell you why you're having problems.

One thing I will mention is that for general transformations you don't really need a 4x4 matrix. Some libraries I've seen (and this is my preferred method) have a Transform or CoordinateSystem class that has a 3x3 rotation matrix and a translation vector. If you know that your transformations are limited to rotations and translations, the inverse can be computed more cheaply than in the general case. Also, formulating the problem in this way can make it easier to understand.

Anyway, sorry I can't offer any more specific help...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
It is very easy and trivial and there is no reason for anything to go wrong. You just need to write the equations and do some algebraic manipulations.

Say the Ma is the transformation matrix of object A, and Mb in the transformation matrix of Object B.
a point in the local space of object A can be transformed to global space by the following expression

Pw = Pa * Ma

Where:
Pw is the point in global space,
Pa is the same point in the local space of objecA
Ma in the transformation matrix of object A
* is the operator the Multiply a vector time a matrix

Similarly the same point in world space can be calculate by the expression

Pw = Pb * Mb

Now since Pw is the same point, then the two expressions can be equated

Pa * Ma = Pb * Mb

From here you can factor Pa by multiplying by the inverse matrix of Ma in both side

Pa * Ma * Ma’ = Pb * Mb * Ma’
Pa = Pb * (Mb * Ma’)

Now you have a formula that can take vectors from the local space of one object tyo the local space of another object, It is just multiplying the vector by the Matrix Mb * Ma’
Where Mb’ in the inverse matrix of Matrix A

Share this post


Link to post
Share on other sites
The AP's solution is the same as I gave - if you can implement that, you should get the results you're looking for. However:
Quote:
It is very easy and trivial and there is no reason for anything to go wrong.
Ideally, yes. But due to the different conventions involved (row or columns vectors and so on), one person applying code or equations given by another often gives the wrong results. So there are some subtleties that I think should not be taken for granted.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
No ideally and no subtleties, and not conventions.
The solution is the same regardless of implementation detain
For a system were the vectors and matrices are transposed the solution should be the same. Just formulate the equation in a transposed representation
For example

Trans (Pw) = tras(Pa* Ma) = Trans (Ma) * Trans (Pa)
Pwt = Mat * Pat
The rest is the same and it should arrive to

Pbt = (Mat’ * Mbt) * Pbt

Notice that the transpose of the last expression produces the exact same vector. This should work with any math library, and with any graphics API

Share this post


Link to post
Share on other sites
Quote:
Pbt = (Mat’ * Mbt) * Pbt
Did you mean Pat = (Mat' * Mbt)?
Quote:
No ideally and no subtleties, and not conventions.
Ok. It's not my intention to argue with you, and I'm always open to correction as that is the way to learn. So let me try to explain what I mean, and feel free to point out any errors.

If m is a matrix, the expression m1 = m2 * m3 may have different results in one math library than in another. Similarly, in some libraries a vector transform may be represented as v' = v * m, whereas in others it would be v' = m * v.

Obviously you understand those distinctions, but not everyone does - if they did, we probably wouldn't be answering the OP's question in the first place. Often when people ask these kinds of questions, others give the answer in the convention with which they are accustomed to working. When the person asking the question plugs those equations into their code, they don't work.

But, you might say, if I give v' = v * m, but their library uses column vectors, then v' = v * m shouldn't even compile, right? Well, I've seen several libraries that implement both pre- and post-multiplication for vectors, so that one is actually multiplication by the transpose (I don't know if this is a good idea or not). So the equation might compile just fine, but give the wrong results.

Maybe I'm wrong about this, and I welcome corrections.

Share this post


Link to post
Share on other sites
Thank u guys for the replies. Really, really great. I wish all forums where like this one.

I put some stuff in the wrong way. I need to be more specific. I'm a rigger / animator. I'm also developing plugins for a 3D application called messiah. (www.projectmessiah.com). I'm writing a tool for corrective morphing. It should take care of bone deformation problems (eg. the shoulder/arm area, hip/leg area, ...)

I'm having trouble implementing. I got some snippets that should show you where exactly my code fails. Thanks for taking the time to look into it.


I have a point position (wxp,wyp,wzp) given in global space.(don't need to convert LOC->GLOB)
I have a bone position/rotation, also given in global space. (wxb,wyb,wzb)/(whb,wpb,wbb)

Q: What's the local position (lxp,lyp,lzp) of the point in the bones' space ???

--------------------------------------------------------------------------------
#define _MatrixInit(m)
m[0][0]=1; m[0][1]=0; m[0][2]=0; m[0][3]=0;
m[1][0]=0; m[1][1]=1; m[1][2]=0; m[1][3]=0;
m[2][0]=0; m[2][1]=0; m[2][2]=1; m[2][3]=0;
m[3][0]=0; m[3][1]=0; m[3][2]=0; m[3][3]=1

#define _MatrixInvert(dst, src)
dst[0][0] = src[0][0];
dst[1][0] = src[0][1];
dst[2][0] = src[0][2];
dst[0][1] = src[1][0];
dst[1][1] = src[1][1];
dst[2][1] = src[1][2];
dst[0][2] = src[2][0];
dst[1][2] = src[2][1];
dst[2][2] = src[2][2]

#define _MatrixMult(p, m1, m2)
p[0][0] = (double)(m1[0][0]*m2[0][0] + m1[0][1]*m2[1][0] + m1[0][2]*m2[2][0] + m1[0][3]*m2[3][0]);
p[0][1] = (double)(m1[0][0]*m2[0][1] + m1[0][1]*m2[1][1] + m1[0][2]*m2[2][1] + m1[0][3]*m2[3][1]);
p[0][2] = (double)(m1[0][0]*m2[0][2] + m1[0][1]*m2[1][2] + m1[0][2]*m2[2][2] + m1[0][3]*m2[3][2]);
p[0][3] = (double)(m1[0][0]*m2[0][3] + m1[0][1]*m2[1][3] + m1[0][2]*m2[2][3] + m1[0][3]*m2[3][3]);
p[1][0] = (double)(m1[1][0]*m2[0][0] + m1[1][1]*m2[1][0] + m1[1][2]*m2[2][0] + m1[1][3]*m2[3][0]);
p[1][1] = (double)(m1[1][0]*m2[0][1] + m1[1][1]*m2[1][1] + m1[1][2]*m2[2][1] + m1[1][3]*m2[3][1]);
p[1][2] = (double)(m1[1][0]*m2[0][2] + m1[1][1]*m2[1][2] + m1[1][2]*m2[2][2] + m1[1][3]*m2[3][2]);
p[1][3] = (double)(m1[1][0]*m2[0][3] + m1[1][1]*m2[1][3] + m1[1][2]*m2[2][3] + m1[1][3]*m2[3][3]);
p[2][0] = (double)(m1[2][0]*m2[0][0] + m1[2][1]*m2[1][0] + m1[2][2]*m2[2][0] + m1[2][3]*m2[3][0]);
p[2][1] = (double)(m1[2][0]*m2[0][1] + m1[2][1]*m2[1][1] + m1[2][2]*m2[2][1] + m1[2][3]*m2[3][1]);
p[2][2] = (double)(m1[2][0]*m2[0][2] + m1[2][1]*m2[1][2] + m1[2][2]*m2[2][2] + m1[2][3]*m2[3][2]);
p[2][3] = (double)(m1[2][0]*m2[0][3] + m1[2][1]*m2[1][3] + m1[2][2]*m2[2][3] + m1[2][3]*m2[3][3]);
p[3][0] = (double)(m1[3][0]*m2[0][0] + m1[3][1]*m2[1][0] + m1[3][2]*m2[2][0] + m1[3][3]*m2[3][0]);
p[3][1] = (double)(m1[3][0]*m2[0][1] + m1[3][1]*m2[1][1] + m1[3][2]*m2[2][1] + m1[3][3]*m2[3][1]);
p[3][2] = (double)(m1[3][0]*m2[0][2] + m1[3][1]*m2[1][2] + m1[3][2]*m2[2][2] + m1[3][3]*m2[3][2]);
p[3][3] = (double)(m1[3][0]*m2[0][3] + m1[3][1]*m2[1][3] + m1[3][2]*m2[2][3] + m1[3][3]*m2[3][3])

vec3D wPpos, lPpos, wBpos, wBrot;
matrix mPoint, mBone, mInvBone, mResult;

--------------------------------------------------------------------------------

//INIT
_MatrixInit(mPoint);
...
_MatrixInit(mResult);

//Set the points' transformationMatrix
wPpos=getPointPos(...); //grabs the point pos in GLOBAL coords
mPoint[3][0]=wPpos[0];
mPoint[3][1]=wPpos[1];
mPoint[3][2]=wPpos[2];

//Set the bones' transformationMatrix
wBpos=getBonePos(...); //grabs the point pos in GLOBAL coords
wBrot=getBoneRot(...); //grabs the point rot in GLOBAL coords
MatrixRot(mBone, wBrot); // Fill mBone rotMatrix. Not going to get into details. Quite sure this worx fine.
mBone[3][0]=wBpos[0];
mBone[3][1]=wBpos[1];
mBone[3][2]=wBpos[2];

// Invert mBone
_MatrixInvert(mInvBone,mBone); // invert rotations
mInvBone[3][0]=-mBone[3][0]; // invert translation
mInvBone[3][1]=-mBone[3][1];
mInvBone[3][2]=-mBone[3][2];

// multiply matrices and get lPpos out of the mResult
_MatrixMult(mResult, mPoint, mInvBone);
lPpos[0] += mResult[3][0];
lPpos[1] += mResult[3][1];
lPpos[2] += mResult[3][2);
--------------------------------------------------------------------------------

vec3D lPpos should hold the local coordinates of the point in the bones' space...
Well, as long as wBpos stays(0.0, 0.0, 0.0) it is. otherwise strange stuff happens...

Hope this will help resolving the problem.

Again, thanks in advance for looking into this.

Share this post


Link to post
Share on other sites
It looks like you're just transposing the rotation portion of the matrix and negating the transform to get your inverse. I don't think that will work. You need to invert the entire matrix. If you already have a function for 4x4 matrix inversion, try that. If not, you may need to write one. It's a little involved, but you shouldn't have much trouble finding references.

I think there is an alternative, though, if you know the 3x3 portion is a rotation matrix only (no scaling, etc.).

Extract the translation vector from the original matrix, and then zero the translation portion of the matrix. Then transpose the upper 3x3 as you are already doing. Then, negate the translation vector, and multiply it by the (transposed) matrix. Finally, add the resulting translation back into the matrix.

I'm pretty sure that's right, but I'd have to check to be sure, so caveat emptor. But perhaps that will solve your problem.

Share this post


Link to post
Share on other sites

This topic is 4682 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this