Thread: one final problem with rotation

  1. #1
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743

    Question one final problem with rotation

    Well, my engine is nearing completion.

    One problem remains. It is a problem that I have probably handled in the past, and therefore should know how to fix....but...it has escaped my mind and I am not sure how to handle it. So any help would be appreciated.

    Once again I am working with 3d models.

    At the current moment I am rotating certain areas/parts/meshes of my models, however, they are rotating around a pivot point that I do not want them to rotate around.

    For example, when I try to rotate the leg to make it look like my model is walking, it will rotate around the origin. I do not want it to do that. I want it to rotate around a certain point of the mesh.

    Here is some code snippets (they are kind of long, you may skip them if you want to, there is a JPEG diagram at the bottom of the post):

    Code:
    struct ROTATE_DTP
    {
    	ROTATE_DTP ( )
    	{
    		entireModel = 0;
    		rotateMeshID = 0;
    		rotateAxis = X;
    		rotateDeg = 0;
    		
    		isRotationBlock = false;
    		rotationBlockMeshID = NULL;
    		xRot = 0;
    		yRot = 0;
    		zRot = 0;
    	}
    
    	//variables for NON-rotation blcoks.  AKA entire model rotations and single mesh rotations
    	bool		entireModel;
    	uint		rotateMeshID;
    	AXIS_DTP	rotateAxis;
    	float		rotateDeg;
    	
    	//variables for rotation blocks
    	bool		isRotationBlock;		//to say if it is a rotation block
    	bool		*rotationBlockMeshID;	//stores mesh ID's in the rotation block
    	float		xRot, yRot, zRot;		//rotation values for rotation blocks only
    
    };
    
    ...
    
    void MODEL_DTP::DrawModel	( void )
    {
    	ROTATE_DTP rotate;	//the current rotation that needs to be done
    	bool isRotate = false;			
    
    	//Push the matrix for rotation purposes
    	glPushMatrix ( );
    
    	//Do the rotations that need to be done on the rotation stack
    	while ( !rotation.empty() )
    	{
    		
    		rotate = rotation.top();
    		rotation.pop();
    		
    
    		if ( rotate.entireModel )
    		{
    			glRotatef ( rotate.rotateDeg, (rotate.rotateAxis == X),
    						(rotate.rotateAxis == Y), (rotate.rotateAxis == Z) );
    		}	
    		else if ( rotate.isRotationBlock )
    		{
    			glPushMatrix ( );
    
    			glRotatef ( rotate.xRot, 1.0, 0.0, 0.0 );
    			glRotatef ( rotate.yRot, 0.0, 1.0, 0.0 );
    			glRotatef ( rotate.zRot, 0.0, 0.0, 1.0 );
    
    			for ( int n = 0; n < UnitModel.GetMeshCount(); n++ )
    			{
    				if ( rotate.rotationBlockMeshID[n] )
    				{
    					glBindTexture ( GL_TEXTURE_2D, texture [MECH_METAL] );	
    					LMesh &mesh = UnitModel.GetMesh(n);
    		
    					// Texturing Contour Anchored To The Object
    					glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
    					// Texturing Contour Anchored To The Object
    					glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
    					glEnable(GL_TEXTURE_GEN_S);			// Auto Texture Generation
    					glEnable(GL_TEXTURE_GEN_T);			// Auto Texture Generation		
    
    					glVertexPointer(4, GL_FLOAT, 0, &mesh.GetVertex(0));
    					glNormalPointer(GL_FLOAT, 0, &mesh.GetNormal(0));
    					glColorPointer(3, GL_FLOAT, 0, &mesh.GetBinormal(0));
    					glDrawElements(GL_TRIANGLES, mesh.GetTriangleCount()*3, 
                            GL_UNSIGNED_SHORT, &mesh.GetTriangle(0));
    
    					//set the master list variable to true for this mesh
    					//so we know not to draw this mesh in the main drawing loop
    					rotationBlockMeshIDMasterList[n] = true;
    				}
    			}
    
    			glPopMatrix ( );
    		}
    		else 
    		{
    			rotateMeshMatrix[rotate.rotateMeshID][rotate.rotateAxis] = rotate;
    		}
    	}
    	
    
    	//Do the drawing of the model after the rotating has been done
    	for (uint i= 0; i<UnitModel.GetMeshCount(); i++)
        {
    		isRotate =  (!rotateMeshMatrix[i][0].entireModel) ||
    					(!rotateMeshMatrix[i][1].entireModel) ||
    					(!rotateMeshMatrix[i][2].entireModel);
    
    		//Skip the drawing of this mesh, if it was part of a rotation block
    		//and no more rotations need to be done to it.
    		if ( rotationBlockMeshIDMasterList[i] )
    		{
    			rotationBlockMeshIDMasterList[i] = false; //resets it for the next frame			
    			continue;
    		}			
    		
    
    		if ( isRotate ) 
    		{
    			glPushMatrix ( );
    			
    			if ( !rotateMeshMatrix[i][0].entireModel )
    				glRotatef ( rotateMeshMatrix[i][0].rotateDeg,
    							1.0f, 0.0f, 0.0f );
    			if ( !rotateMeshMatrix[i][1].entireModel )
    				glRotatef ( rotateMeshMatrix[i][1].rotateDeg,
    							0.0f, 1.0f, 0.0f );
    			if ( !rotateMeshMatrix[i][2].entireModel )
    				glRotatef ( rotateMeshMatrix[i][2].rotateDeg,
    							0.0f, 0.0f, 1.0f );
    		}
    
    		glBindTexture ( GL_TEXTURE_2D, texture [MECH_METAL] );	
            LMesh &mesh = UnitModel.GetMesh(i);
    		
    		// Texturing Contour Anchored To The Object
    		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
    		// Texturing Contour Anchored To The Object
    		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
    		glEnable(GL_TEXTURE_GEN_S);			// Auto Texture Generation
    		glEnable(GL_TEXTURE_GEN_T);			// Auto Texture Generation
    
    		
    
            glVertexPointer(4, GL_FLOAT, 0, &mesh.GetVertex(0));
            glNormalPointer(GL_FLOAT, 0, &mesh.GetNormal(0));
            glColorPointer(3, GL_FLOAT, 0, &mesh.GetBinormal(0));
            glDrawElements(GL_TRIANGLES, mesh.GetTriangleCount()*3, 
                            GL_UNSIGNED_SHORT, &mesh.GetTriangle(0));
    
    		if ( isRotate )
    			glPopMatrix ( );
    		
    
        }
    
    	glDisable ( GL_TEXTURE_GEN_S );
    	glDisable ( GL_TEXTURE_GEN_T );
    
    	//Pop off the matrix
    	glPopMatrix ( );		
    
    }
    
    ...
    
    void MODEL_DTP::RotateModel ( float deg, AXIS_DTP axisID )
    {
    	ROTATE_DTP rot;
    
    	rot.entireModel = true;
    	rot.rotateAxis = axisID;
    	rot.rotateDeg = deg;
    								
    	rotation.push ( rot );
    }
    
    ...
    
    //Terminated by a -1
    void MODEL_DTP::RotateBlock ( float xRot, float yRot, float zRot, ... )
    {
    	ROTATE_DTP rotationBlock;
    
    	rotationBlock.isRotationBlock = true;
    	rotationBlock.xRot = xRot;
    	rotationBlock.yRot = yRot;
    	rotationBlock.zRot = zRot;
    	rotationBlock.rotationBlockMeshID = new bool [ UnitModel.GetMeshCount() ];
    
    	for ( int k = 0; k < UnitModel.GetMeshCount(); k++ )
    		rotationBlock.rotationBlockMeshID[k] = false;
    
    	va_list ap;
    
    	int arg;
    
    	va_start ( ap, zRot );
    
    	while ( !((arg = va_arg(ap, int)) == -1) )
    	{		
    		rotationBlock.rotationBlockMeshID[arg] = true;
    	}
    
    	va_end(ap);
    	
    	rotation.push ( rotationBlock );
    }
    
    ...
    
    //rotate a mesh a certain # of degrees on an axis
    void MODEL_DTP::RotateMesh	( GLuint meshID, float deg, AXIS_DTP axisID )
    {
    	ROTATE_DTP rot;
    
    	rot.entireModel = false;
    	rot.rotateMeshID = meshID;
    	rot.rotateAxis = axisID;
    	rot.rotateDeg = deg;
    
    	rotation.push ( rot );
    }
    Here is a diagram:
    Last edited by DavidP; 11-18-2003 at 05:16 PM.
    My Website

    "Circular logic is good because it is."

  2. #2
    Registered User grady's Avatar
    Join Date
    Oct 2003
    Posts
    27
    Translate to black dot labeled "pivot point" then rotate.
    Last edited by grady; 11-18-2003 at 08:26 PM.

  3. #3
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    yeah i was thinking about that....problem is...i'm not exactly sure what the coordinate of that black dot is on the pivot point....

    looks like i am going to have to delve deep into the model and look at each point individually!

    how fun! (especially when there are about 18000 points)
    My Website

    "Circular logic is good because it is."

  4. #4
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Sounds like you need rotation around an arbitrary point. The steps to perform that are as follows:

    1) Translate the point to the origin ( -px, -py, -pz )
    2) Perform the rotation
    3) Translate the point back to position ( px, py, pz )

    So multiply those matrices in the correct order and you should be fine. Let me know if you have any problems.

    EDIT: Forgot this game was 3D! Look up the formula for rotation around an arbitrary vector. The quick steps are.

    1) Translate the vector so it passes through origin
    2) Rotate the vector onto one of the primary axis.
    3) Do rotation w.r.t. that standard axis.
    4) Inverse of Step 2
    5) Inverse of Step 1
    Last edited by MrWizard; 11-19-2003 at 10:29 PM.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM
  2. character string problem
    By pinkpenguin in forum C Programming
    Replies: 4
    Last Post: 11-29-2005, 01:53 AM
  3. scanf problem
    By pinkpenguin in forum C Programming
    Replies: 2
    Last Post: 11-29-2005, 01:52 AM
  4. Replies: 5
    Last Post: 11-07-2005, 11:34 PM
  5. searching problem
    By DaMenge in forum C Programming
    Replies: 9
    Last Post: 09-12-2005, 01:04 AM