Rotating a mesh

Started by
16 comments, last by ZitherMan 20 years ago
I've been trying to make some kind of system for moving and rotating my meshes. I thought i'd set the objects position to 0,0,0 then rotate and then move it back, but the object is rotating around some other point, not beeing 0,0,0. Does anyone have any idea why it does this? Here are some code-samples:
        
void CMesh::Rotate(D3DXVECTOR3 axis, long Speed)
{

	float old_x, old_y, old_z;
	old_x = m_vPos.x;
	old_y = m_vPos.y;
	old_z = m_vPos.z;
	SetPos(0,0,0);
	D3DXMatrixRotationAxis( &mtxRot, &axis, D3DXToRadian((float)Speed / 40.0f));
	D3DXVec3TransformCoord( &m_vLook, &m_vLook, &mtxRot );
	D3DXVec3TransformCoord( &m_vUp, &m_vUp, &mtxRot );
	SetPos(old_x, old_y, old_z);
}

void CMesh::SetPos(float x, float y, float z)
{
	m_vPos   = D3DXVECTOR3(x, y, z);  // Mesh Position

	Update();
}

void CMesh::Update()
{

	D3DXMatrixIdentity( &mesh );

	D3DXVec3Normalize( &m_vLook, &m_vLook );
	D3DXVec3Cross( &m_vRight, &m_vUp, &m_vLook );
	D3DXVec3Normalize( &m_vRight, &m_vRight );
	D3DXVec3Cross( &m_vUp, &m_vLook, &m_vRight );
	D3DXVec3Normalize( &m_vUp, &m_vUp );

	view._11 = m_vRight.x;
        view._12 = m_vUp.x;
        view._13 = m_vLook.x;
	view._14 = 0.0f;

	view._21 = m_vRight.y;
        view._22 = m_vUp.y;
        view._23 = m_vLook.y;
 	view._24 = 0.0f;

	view._31 = m_vRight.z;
        view._32 = m_vUp.z;
        view._33 = m_vLook.z;
	view._34 = 0.0f;

	view._41 = -D3DXVec3Dot( &m_vPos, &m_vRight );
	view._42 = -D3DXVec3Dot( &m_vPos, &m_vUp );
	view._43 = -D3DXVec3Dot( &m_vPos, &m_vLook );
	view._44 =  1.0f;
	

}
        
Is there a better way to do this (i guess there is)? I've heard something about some model-matrix but i havnt found any reference on it. Any help would be appreciated [edited by - ZitherMan on May 5, 2003 2:42:27 PM]
----------------------------
When hell freezes over it will be a pretty cool place to snowboard
Advertisement
Where are you moving the object to 0,0,0 ? Do you mean set it''s position to this or it''s rotation ?

If it isn't working, take a bath, have a think and try again...

I mean setting the position to 0,0,0 (x,y,z)
----------------------------
When hell freezes over it will be a pretty cool place to snowboard
anyone?

please i really need the help i can get here
----------------------------
When hell freezes over it will be a pretty cool place to snowboard
last try, please, i really need help
----------------------------
When hell freezes over it will be a pretty cool place to snowboard
Free your mind, young grasshopper. You see, in DirectX, meshes do not really exist.

Hard to believe, but the g_Device->SetTranform(DTS_WORLD) thing that may have looked so mysterious for such a long time is the solution to all your problems, assuming you''re in the same ditch I was a while back.

Meshes, in DirectX, like I said, don''t acutally exist. DirectX changes the relative position of a camera every time you render a new object, as long as you give it a transformation matrix. When you''re rotating an object, you''re actually just adding a rotation matrix to your overall transformation. So, instead of transforming the matrix to the center and all that jazz, just create a new matrix:

D3DXMATRIX mRotation;

Next: The amount the mesh will have rotated since the last frame will be incremented, not concretely determined, by your Speed variable. You''ll need a D3DXVECTOR3 member variable in your mesh to keep track of the orientation (call it m_Orientation). Now, increment the orientation according to your axis parameter, tampered in magnitude by your Speed variable. Even more important is a g_RotationFactor, which will determine how you''re going to convert your axis strength and speed into radians:

m_Orientation += axis * (float)speed / g_RotationFactor;

g_RotationFactor, as you can see, is a global float that you can adjust in your console (you DO have a console, don''t you?) until you find a good Speed-to-radian ratio, all without having to recompile.

Next up is the actual rotation transformation. You may already have this code in your Render or Update function - it''s pretty important stuff. You''ve already created a mRotation matrix, and now it''s time to use it. This nifty function will apply a given amount of x, y, and z rotation to a matrix which you can use to rotate anything by that amount:

D3DXMatrixRotationYawPitchRoll(&mRotation, m_Orientation.x, m_Orientation.y, m_Orientation.z);

When you render your object, you''re likely using a trasformation matrix in a line of code that looks like the following:

g_Device->SetTransform(DTDS_WORLD, &mTrans);

If so, just add the mRotation matrix to the stack of transformations. If you have no idea what I''m talking about, read on.

Like I was talking about in the beginning, DirectX needs to know from what point the mesh will be rendered (the mesh doesn''t move - DirectX moves). This is done with the matrix thingies, as it looks like you''ve kind of already found out. Whatever matrix you''re using right now to transform the position (mTrans, for example), you''ll need to multiply - combine, in the common tongue - these two matrices. This is easier than it sounds:

D3DXMatrixMultiply(&mTrans, &mRotation, &mTrans);

And then you set the transformation matrix like I showed you with the SetTransform(DTDS_WORLD, &mTransfunction above.

The end result is, DirectX knows the new orientation of yer mesh, and when it renders it, the results should be visible. Don''t forget to tweek around with that g_RotationFactor variable.

Long winded, I know, but I hope it helped. I tried to give you the information I now know I needed when I was in the same fix a while back. I''ll be glad to answer any questions, if I can.

- TythosEternal



"Who''s John Galt?"
"Who's John Galt?"
Thank you very much! That made me understand things a little bit better.



My problem now, is that the mesh gets extremely deformed.
http://zith.cisko.org/screen.gif
there's like beams from the center of the screen, to the edges. When i move the camera, these "beams" get replaced with new ones. When i try to rotate, the same thing happens as when i move the camera

Here is the new code


      in CMesh::CMesh i dom_Orientation = D3DXVECTOR3(0.0f,0.0f,1.0f);void CMesh::Rotate(D3DXVECTOR3 axis, long Speed){	m_Orientation += axis * (float)Speed / 40.0f;	D3DXMatrixRotationYawPitchRoll(&mtxRot, m_Orientation.x, m_Orientation.y, m_Orientation.z);	D3DXMatrixMultiply(&trans, &mtxRot, &trans);}void CMesh::Render(){	m_D3DDevice->SetTransform(D3DTS_WORLD, &trans); 	for(DWORD i = 0; i < m_NumMaterials; i++)	{		// Set the material and texture for this subset		m_D3DDevice->SetMaterial(&m_Materials[i]);		m_D3DDevice->SetTexture(0, m_Textures[i]);		m_D3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);        		// Draw the mesh subset		m_Mesh->DrawSubset(i);	}}  



[edited by - ZitherMan on May 8, 2003 5:00:36 PM]
----------------------------
When hell freezes over it will be a pretty cool place to snowboard
Your render function should be reordered, first. Here''s what mine looks like:


  HRESULT CMesh::Render(){    HRESULT r = E_FAIL;    for (int i = 0; i < m_NumMaterials; i++)    {        m_Materials[i].Update();        m_D3DDevice->SetTexture(0, m_pTextures[i]);        r = m_Mesh->DrawSubset(i);    }    //You''ll need to reset the vertex shader...    m_D3DDevice->SetVertexShader(/*Whatever you''re using*/);    return r;}  


Wondering where the matrix stuff went? Good question. It goes into something called a frame class, which is basically a wrapper object for your mesh so you don''t have to deal with 60 of the same meshes in your game (like 60 of the same kind of alien) and then trying to update and render each individual mesh. Instead, you should only have one mesh object for each type of mesh in your game - one alien infantry mesh, for example, no matter how many alient infantry are in your level.

The frame is where you can do all your individual manipulation. This is also where you''ll have your rotate function, which will change the Orientation vector accordingly. A basic frame class will look something like this:


  class CFrame{private:    D3DXMATRIX m_mLocal;    D3DVECTOR3 m_vPosition;    D3DVECTOR3 m_vVelocity;    D3DVECTOR3 m_vOrientation;    CMesh m_YeOldeMesh;public:    CFrame();    ~CFrame();    //All your set and get functions for position, velocity, etc    void Rotate(D3DXVECTOR3 axis, long Speed);    void Update();    HRESULT Render();};  


Also, how are you creating your mesh, and how are you converting it to an x file (if you''re using a 3d modeling program)? Sometimes, especially with the more advanced modeling programs, the scale, rotation pivot point, and transformation centers can REALLY mess things up (imagine a TIE fighter stretched sideways until it''s about 100 times as wide as it is long and you''ll know what I mean).

The end conclusion, though, is that once you load your mesh, you should NEVER touch it. If it''s working fine, (and there''s no really big reason it shouldn''t, other than that render function), you should just encapsulate it and use it in your frame class.

- TythosEternal




"Who''s John Galt?"
"Who's John Galt?"
quote:Original post by TythosEternal
(...)
Also, how are you creating your mesh, and how are you converting it to an x file (if you''re using a 3d modeling program)? Sometimes, especially with the more advanced modeling programs, the scale, rotation pivot point, and transformation centers can REALLY mess things up (imagine a TIE fighter stretched sideways until it''s about 100 times as wide as it is long and you''ll know what I mean).


I can tell you that

The mesh is converted from 3ds to .x using the SDK converter (or at least that''s what zith told me that little thingie was ) The pivot point has been set at the very centre of the model before exporting, so that should not be a problem either.

BTW, you are amazing Tythos

Richard Olsson
maxed@johnbauer.org
Richard Olsson
Yeah thanks Tythos, you''ve cleared a lot up for me as well

"Wireless mice 4R3 73|-| 5UX0R" - Me

This topic is closed to new replies.

Advertisement