# Accumulating Rotation and Translation Matrices

The following code produces the desired output, but I want to replace it:

`````` void  BVH::RenderFigure( const Joint * joint, const double * data, float scale )
{
glPushMatrix();
glTranslatef( joint->offset[ 0 ] * scale,
joint->offset[ 1 ] * scale,
joint->offset[ 2 ] * scale );
int  i, j;
for ( i=0; i<joint->channels.size(); i++ )
{
Channel *  channel = joint->channels[ i ];
if ( channel->type == X_ROTATION )
glRotatef( data[ channel->index ], 1.0f, 0.0f, 0.0f );
else if ( channel->type == Y_ROTATION )
glRotatef( data[ channel->index ], 0.0f, 1.0f, 0.0f );
else if ( channel->type == Z_ROTATION )
glRotatef( data[ channel->index ], 0.0f, 0.0f, 1.0f );
}
glPointSize(5.0);
glBegin(GL_POINTS);
glVertex3f( 0,0,0 );
glEnd();

for ( i=0; i<joint->children.size(); i++ )
{
RenderFigure( joint->children[ i ], data, scale );
}
glPopMatrix();
}
``````

I would like to replace it with this code. The problem is combining all of the rotation matrices. If I uncomment the line M = parent * T it will produce the same render of the above code if I don’t do any rotations. This means my hierarchy is correct and that the translations are correct. I can’t figure out why the rotations don’t work. I am basically interested in building the model matrix so I can get the world coordinates of each point where each point is part of a hierarchical human figure as defined by the BVH file specification. This is why I am trying to render in this way. What am I doing wrong with the rotation matrices? I need to apply the rotations in this order (as defined in the BVH spec) Z, X, then Y. For each point it should be: Position = Mparent * M * (0,0,0,1) where M = RotationZXY * Offset

``````void BVH::getPositions( const Joint * joint, const double * data,
float scale, glm::mat4 parent)
{
glm::mat4 T = glm::translate((float)(joint->offset[ 0 ] * scale),
(float)(joint->offset[ 1 ] * scale),
(float)(joint->offset[ 2 ] * scale));
int  i, j;
double x,y,z;
for ( i=0; i<joint->channels.size(); i++ )
{
Channel *  channel = joint->channels[ i ];
if ( channel->type == X_ROTATION )
x = data[ channel->index ];
else if ( channel->type == Y_ROTATION )
y = data[ channel->index ];
else if ( channel->type == Z_ROTATION )
z = data[ channel->index ];
}

glm::mat4 Mx = glm::rotate((float)x,1.0f, 0.0f, 0.0f);
glm::mat4 My = glm::rotate((float)y, 0.0f, 1.0f, 0.0f);
glm::mat4 Mz = glm::rotate((float)z, 0.0f, 0.0f,  1.0f);

glm::mat4 M = My * Mx * Mz;
M =  M * T;
M =  parent * M;

//M = parent * T

glm::vec3 point = glm::vec3(M * glm::vec4(glm::vec3(0,0,0),1));
glPointSize(5.0);
glBegin(GL_POINTS);
glVertex3f( point.x,point.y,pointz );
glEnd();

for ( i=0; i<joint->children.size(); i++ )
{
getPositions( joint->children[ i ], data, scale, M );
}

}
``````

Change M = M * T to M = T * M

I tried that and I didn’t work, but I don’t think that makes sense. the vec3(0,0,0,1) is basically a column vector right? So if i have M = parent * T and then the M * Vec3(0,0,0,1) i am multiplying a 4x4 matrix by a column matrix to produce a column vector. I don’t understand why this doesn’t work because I am just doing to glrotate does except i am only doing the model matrix.

matrix multiplication is not commutative! A * B is not the same as B * A.

Your if() code in 2nd implementation does not match the first implementation. You should do something like:

``````
M = glm::translate ...
for() ...
if ( channel->type == X_ROTATION ) {
glm::mat4 Mx = glm::rotate((float)x,1.0f, 0.0f, 0.0f);
M = M * Mx;
}
...
}

``````

There is also another potential problem with Matrix * vector multiplication. Never expect result vec3 when you multiply matrix4x4. Let the W division be done in OpenGL, not in your code. Bad things will happen when W <= 0. In another words use glVertex4f.