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.