Sign in to follow this  
Kasya

matrix problem

Recommended Posts

Kasya    207
Hello, could you please tell me what im doing wrong:

struct Bone {

Vector3 position;
Quaternion orientation;
int parent; //-1 means no parent
String name;

}; //is used with Skeleton (as a resource)

struct TransformBone {

Matrix transform;
int parent;

}; //is used with SkeletonInstance




Skeleton2Instance(Skeleton * skel, SkeletonInstance * inst) {

for each (bone in skel->bones) {

TransformBone temp;
Matrix translation, orientation;
translation.Translate(bone.position);
bone.orientation.ToMatrix(orientation);
temp.transform = orientation * translation;
temp.parent = bone.parent;
inst->addBone(bone);

}


}



Translation works ok. now when i convert axis angle to Quaternion to rotate the bone, it doesn't rotate:

skel->addBone("Root", Vector3(0,0,0), Quaternion::Identity, -1);
Quaternion quat;
quat.SetAxis(Math::deg2rad(45), 0, 1, 0);
skel->addBone("Bone#1", Vector3(1,0,0), quat, 0);

Skeleton2Instance(skel, inst);



and here is the draw code:

foreach(bone in skelInstance) {


if(bone.parent != -1) {
   glBegin(GL_LINES);
   glVertex3f(parentBone.transform._12, parentBone.transform._13, parentBone.transform._14);
   glVertex3f(bone.transform._12, bone.transform._13, bone.transform._14);
   glEnd();

}


}



when i debug the application the translation and orientation matrices themselves are correctly stored. but after multiplication only the translation rows of transform matrix are filled correctly. others are 0. I tried MatrixIndentity too. no help. What i need is to get absolute position from the multiplication of translation and rotation matrix. I hope you understand the problem. Thanks, Kasya

Share this post


Link to post
Share on other sites
haegarr    7372
Hi. I see a couple of issues:

1st, what happens with "temp" in Skeleton2Instance? It seems to be computed and then dropped uselessly.

2nd, do you still follow the "Skeleton is a prototype resource and SkeletonInstance a, well, instance related to that prototype" philosophy?

3rd, if 2nd is answered with "yes", is there an appropriate handling done inside SkeletonInstance::addBone? Because the original "bone" is added to the SkeletonInstance!

4th, if 2nd is answered with "yes", why do you compute model global matrices inside Skeleton2Instance at all?

5th, you're using OpenGL for drawing. That implies column vector convention. On the other hand, you compute
temp.transform = orientation * translation
what seems me to be row vector convention. Are you aware of this?

6th, from your problem description, it seems me that the matrix multiplication is not okay, doesn't it? Have you checked that regardless from its use in skeletal animation?

Share this post


Link to post
Share on other sites
Kasya    207
1. right now its just a draft version. that's why i don't care about the memory leaks. i'll polish my code a little bit too (as I always when I make something work :) )

2. Yes. Why you said still follow? is that a bad practice? if yes, what should i use instead??

3. no its just typo mistake. it must be addBone(temp). sorry for confusion.

4. Could you please give some advice on the usage of this too? Maybe i only need absolute position inside my bone class... really have no idea about that one.

5. If this will at least do something i would be very happy. Additionally, i am going to implement a World class where the position will be multiplied and transposed depending on API. After I finish basic skeleton model (without animation), of course.

6. here is my multiplication function:


Matrix Matrix::operator*(const Matrix &m) const {

Matrix temp;

for (int i = 0; i < 16; i+=4) {

for (int j = 0; j < 4; j++) {

temp.row[i + j] = row[ i + 0 ] * m.row[ 0 + j ] + row[ i + 1 ] * m.row[ 4 + j ] +
row[ i + 2 ] * m.row[ 8 + j ] + row[ i + 3 ] * m.row[ 12 + j ];

}

}

return temp;

}



i don't think there must be a problem.

Thanks,
Kasya

Share this post


Link to post
Share on other sites
haegarr    7372
Quote:
Original post by Kasya
2. Yes. Why you said still follow? is that a bad practice? if yes, what should i use instead??
Hey, I'm the same haegarr who has suggested this in that big fat thread about animation blending back in August 2008. So why should I discourage from that way ;) It is just so that you may have gone another way in the meanwhile, so I wanted to be sure.

Quote:
Original post by Kasya
4. Could you please give some advice on the usage of this too? Maybe i only need absolute position inside my bone class... really have no idea about that one.

A bone in the SkeletonInstance needs both the relative (i.e. w.r.t. the parental bone) as well as the absolute (e.g. w.r.t. the model space) placement. The relative placement is usually influenced by the animation tracks. After all tracks have been processed, the absolute placement can be computed from the absolute placement of the parental bone and the relative placement of self. In some pseudo code:
self.absolute := parent.getAbsolute() * self.relative
where column vector notation is used! Herein a transformation matrix is to be composed as
matrix := position * orientation

Quote:
Original post by Kasya
5. If this will at least do something i would be very happy. Additionally, i am going to implement a World class where the position will be multiplied and transposed depending on API. After I finish basic skeleton model (without animation), of course.
Please notice that implementing a transposition will probably not be needed. The matrix layout of OpenGL and D3D is the same. This is because OpenGL uses column vector notation as well as column major order convention, while D3D uses row vector notation as well as row major order convention.

Quote:
Original post by Kasya
6. here is my multiplication function:
...
The routine implementation seems me to compute the transpose
( A * B )T
instead of
A * B
Please check this. And it is unclear whether row[i] actually returns the i-th scalar. From the naming I would say it accesses the i-th row vector.

Share this post


Link to post
Share on other sites
Kasya    207
Lol))) Thanks for the help!! I'll see how well i can implement it. About the multiplication: maybe i should just create this function without loops. And one more question: after the implementation, how should i render it? like:

glVertex3f(absolute._12, absolute._13, absolute._14);

Kasya

Share this post


Link to post
Share on other sites
haegarr    7372
Quote:
Original post by Kasya
About the multiplication: maybe i should just create this function without loops.
I'm quite sure you just need to exchange the row[] with the m.row[] but leave the indices where they are. I.e. the roles of the this and m matrices are just interchanged.

Quote:
Original post by Kasya
And one more question: after the implementation, how should i render it? like:

glVertex3f(absolute._12, absolute._13, absolute._14);
Notice please that a bone's absolute placement read from a SkeletonInstance defines its position and orientation w.r.t. the model space. If you draw a line from the parental bone's absolute position to the current child's absolute position, then you actually draw the parent's bone. The last bone in a chain (e.g. see the skeleton as a tree) cannot be drawn this way, because there is no length given for the line (i.e. each last bone has no end-point). This is because "bone" isn't the 100% correct term. It is actually the transformation matrix denoting the co-ordinate frame of the following limb.

Share this post


Link to post
Share on other sites

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