• 14
• 12
• 9
• 10
• 13

A problem with matrix transformations

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

Recommended Posts

I've changed my glPopMatrix/glPushMatrix code to use actual matrices to keep track of transformations step by step (joint hiearchy system), and ran into a problem along the way. Basically the problem is as follows... I start at top level where I retrieve the Modelview matrix from OpenGL, and pass it to each of the models I am about to render. Models are in turn split into meshes (bodyparts), which are grouped into a hiearchy (with the parent's transformation affecting the children). Inside each Model I start my CMatrix4x4 class with an Identity matrix and perform all my translate and rotate operations on that matrix as I move down the hiearchy and move meshes into place. Along the way I also perform frustum culling checks against the bounding spheres of each mesh to determine if I should draw it or not. At the end I multiply my CMatrix4x4 matrix by the Modelview matrix that I passed at the very beginning and logically (I think?) I should end up with a proper transformation... but I do not. Using this method frustum culling works perfectly (based on properly calculated object's coordinates), but the geometry is rendered all over the place. On the other hand if I start with the Modelview matrix at the very beginning instead of an Identity matrix and perform all calculations on that, (and avoid multiplying by the Modelview matrix at the end), then the geometry is rendered in proper places, but all frustum checks are messed up. I suppose one solution to this would be to perform the translation/rotation calculations twice, once for the Identity-origin matrix, another for a Modelview-origin. But there's got to be something I'm doing wrong?

Share on other sites
And since some resemblance of code is always helpful...

Part of the Engine::Render() function:

float fModelview[16];	glGetFloatv(GL_MODELVIEW_MATRIX, fModelview);	// Draw all the models that exist	unsigned short iM = pModel.size();	for (unsigned short i = 0; i < iM; i++)		if (pModel)		{			if (bTest) iTempGlobal += pModel->Render(fModelview, &Mode, pCamera->Frustum, iBoundCubemap, iBoundNCM);			else iTempGlobal += pModel->Render(fModelview, &Mode, pCamera->Frustum, iBoundCubemap, iBoundNCM, fP, &vAmbientColor);		}

Which calls the Model::Render function:

unsigned short Model::Render(float *fModelview, char *InMode, FrustumClass &pFrustum,		   unsigned int iCubemap, unsigned int iNormalizationCubemap, float *fInLight, CVector3 *vAmbientColor){     // if I start with an Identity matrix here, the frustum checks work, but actual model is in the wrong spot     CMatrix4x4 mTransRotMatrix(fModelview);     <perform my model translation/rotation on mTransRotMatrix>     if (!pFrustum.SphereInFrustum(vCenter * mTransRotMatrix, fRadius)) return 0;     unsigned short iM = pMesh.size(), iCount = 0;	for (unsigned short i = 0; i < iM; i++)		if (!pMesh->Hiearchial())			iCount += pMesh->RenderHiearchy(fModelview, mTransRotMatrix.fMat, InMode, pFrustum, iCubemap, iNormalizationCubemap, fInLight, vAmbientColor);     return iCount;}

Which in turn renders meshes:

unsigned short Mesh::RenderHiearchy(float *fModelview, float *fTransRotMatrix, char *InMode, FrustumClass &pFrustum,		  unsigned int iCubemap, unsigned int iNormalizationCubemap, float *fInLight, CVector3 *vAmbientColor){	CMatrix4x4 mMatrix(fTransRotMatrix);	// Move to the mesh position	mMatrix.Translate(vPos);        if (pFrustum.SphereInFrustum(vCenter * mMatrix, fRadius))	// The object is visible	{		iCount += RenderSelf(fModelview, mMatrix.fMat, InMode, pFrustum, iCubemap, iNormalizationCubemap, fInLight, vAmbientColor);		if (pHookpoint.empty()) return iCount;	}        unsigned short iH = pHookpoint.size();        for (unsigned short i = 0; i < iH; i++)	{		if (pHookpoint->pLink)		{			//pHookpoint->Recalculate();			CMatrix4x4 mTemp(mMatrix.fMat);	// Reset the temporary matrix back to the original values			mTemp.Translate(pHookpoint->vTranslate);			mTemp.Rotate(pHookpoint->fAngle, pHookpoint->vAxis);			iCount += pHookpoint->pLink->pMesh->RenderHiearchy(fModelview, mTemp.fMat, InMode, pFrustum, iCubemap, iNormalizationCubemap, fInLight, vAmbientColor);		}	}        return iCount;}

And that goes to the actual Mesh::RenderSelf() that renders the mesh itself in the proper place:

unsigned short Mesh::RenderSelf(float *fModelview, float *fTransRotMatrix, char *InMode, FrustumClass &pFrustum,		  unsigned int iCubemap, unsigned int iNormalizationCubemap,float *fInLight, CVector3 *vAmbientColor){	if (!bRender) return 0;        <actual mode settings here, light vector calculations for bump mapping, etc>        // Alternatively I create a new matrix here from fTransRotMat        // and multiply it by the Modelview matrix -- but then the geometry comes out wrong        glPushMatrix();	glLoadMatrixf(fTransRotMat);	try	{		glLockArrays(0, iVertexCount);		glDrawElements(GL_TRIANGLES, iIndexCount, GL_UNSIGNED_SHORT, iIndex);		glUnlockArrays();	}	catch (...)	{		Popup("Failed to render a mesh!");		bRender = false;	}		glPopMatrix();	return 1;}