Sign in to follow this  

rotation prob

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a tile based map which I want to render in 3 layers. layer1. base tile 2. static models and 3. animated models. When I render a static model on a particular tile, it seems to render in the right place and it gets redrawn in the right place when I scroll the screen. The problem is I want to rotate the model to face a different direction so I use Matrix.RotationX(angleX) to rotate the model, but when I scroll the screen the model is not drawn on the right tile. Here is the code involved. thanks in advance for any help on this.
map class important snippets

		//initialise tiles 
		public void initTiles(int noTiles)
		{
			//set base tile value 		
			for(int i = 0;i < noTiles;i++)
			{
				TileClass tile = new TileClass();
				tile.setValue(0,0);
				tiles.Add(tile);
				
			}

			//set layer 2 values for static Models
			TileClass setTile = (TileClass) tiles[470];
			setTile.setValue(1,1);
			tiles[470] = setTile;

		}

		public void renderMapTiles()
		{
			
			//render horizontally
			for(int y = 0; y < mapHeight; y++)
			{
				//render vertically
				for(int x = 0; x < mapWidth; x++)
				{
					//figure out the tile to display
					TileClass ti = new TileClass();
					ti = (TileClass) tiles[x + (y * mapWidth)];
					tileToRender = ti.getValue(0);
					//calculate the position
					xPos = (0.7f * x) + xPosChange;
					yPos = (0.7f * y) + yPosChange;
					//int[] adjacency = adjBuffer.Read(typeof(int),
					//set the position of the tile and render
					renderTile(xPos,yPos);
					//render the second layer if need be
					if(ti.getValue(1) != 0)
					{
						
						tentMesh.setPos(xPos,yPos,0.0f);
						tentMesh.rotate(10,10,0);
						tentMesh.DrawMesh(ref device);
						
						
					}
				
				}
			}
		}
		public void renderTile(float xPos,float yPos)
		{
			// Draw the Mesh
			//DrawMesh(xPos, yPos, 0.0f,0);
			grassMesh.setPos(xPos,yPos,0.0f);
			grassMesh.DrawMesh(ref device);
		}
		/// <summary>
		/// We will initialize our graphics device here
		/// </summary>
		public void InitializeGraphics()
		{
			// Set our presentation parameters
			PresentParameters presentParams = new PresentParameters();

			presentParams.Windowed = true;
			presentParams.SwapEffect = SwapEffect.Discard;
			presentParams.AutoDepthStencilFormat = DepthFormat.D16;
			presentParams.EnableAutoDepthStencil = true;

			// Create our device
			device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);

			// Load our meshes
			grassMesh.LoadMesh(@"..\..\worldagrassa.x",ref device);
			tentMesh.LoadMesh(@"..\..\tent.x",ref device);
			tentMesh.rotate(100,100,100);

			//LoadMesh(@"..\..\worldagrassa.x");
			//LoadMesh(@"..\..\tent.x");
			

			
		}


public class StaticMesh
	{
		
		private Mesh mesh = null;
		private Material[] meshMaterials;
		private Texture[] meshTextures;

		//vars to handle rotation matrix
		private float angleX,angleY,angleZ;
		private float posX,posY,posZ;
		private Matrix meshView;

		public StaticMesh()
		{
				meshView = Matrix.Zero;
		}

		public void LoadMesh(string file,ref Device device)
		{
			ExtendedMaterial[] mtrl;

			// Load our mesh
			mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl);

			// If we have any materials, store them
			if ((mtrl != null) && (mtrl.Length > 0))
			{
				meshMaterials = new Material[mtrl.Length];
				meshTextures = new Texture[mtrl.Length];

				// Store each material and texture
				for (int i = 0; i < mtrl.Length; i++)
				{
					meshMaterials[i] = mtrl[i].Material3D;
					if ((mtrl[i].TextureFilename != null) && (mtrl[i].TextureFilename != string.Empty))
					{
						// We have a texture, try to load it
						meshTextures[i] = TextureLoader.FromFile(device, @"..\..\" + mtrl[i].TextureFilename);
					}
				}
			}
		}

//		public void DrawMesh(float x, float y, float z,ref Device device)
//		{
//		
//			device.Transform.World =   Matrix.Translation(x,y,z) * meshView;
//				//Matrix.Translation(x,y,z) * Matrix.RotationX(rotX) * Matrix.RotationY(rotY) * Matrix.RotationZ(rotZ);
//			for (int i = 0; i < meshMaterials.Length; i++)
//			{
//				device.Material = meshMaterials[i];
//				device.SetTexture(0, meshTextures[i]);
//				mesh.DrawSubset(i); 
//			}
//			
//		}
		public void DrawMesh(ref Device device)
		{
			
			device.Transform.World = Matrix.Translation(posX,posY,posZ)* Matrix.RotationX(angleX) * Matrix.RotationY(angleY)* Matrix.RotationZ(angleZ);
			for (int i = 0; i < meshMaterials.Length; i++)
			{
				device.Material = meshMaterials[i];
				device.SetTexture(0, meshTextures[i]);
				mesh.DrawSubset(i); 
			}
			
		}
		public void setPos(float x, float y, float z)
		{
			posX = x;
			posY = y;
			posZ = z;
			
		}
		public void rotate(float x,float y,float z)
		{			
			
			angleX = x;
			angleY = y;
			angleZ = z;
			
		}
	}
}

Share this post


Link to post
Share on other sites
Try reording your matrix multiplications:

From this:
Matrix.Translation(posX,posY,posZ)* Matrix.RotationX(angleX) * Matrix.RotationY(angleY)* Matrix.RotationZ(angleZ);

To this:

Matrix.RotationX(angleX) * Matrix.RotationY(angleY)* Matrix.RotationZ(angleZ) * Matrix.Translation(posX,posY,posZ);

Also consider using RotationYawPitchRoll instead of the three axis rotations or using AffineTransform which allows you to specify a center point as for the rotation.

Share this post


Link to post
Share on other sites
I still cant seem to get the mesh to rotate into the desired position. Is there a way to return the centre co-ordinates of a mesh? I could then maybe use this with Matrix.RotationAxis .

Share this post


Link to post
Share on other sites
Hopefully your mesh is centered at 0,0, if it is not here is my advice:
1. Open up your 3D modeler whatever it is.
2. Move the mesh so that it is centered at 0,0.
3. Save it.

If you don't want to do that there are a number of ways to get the center of the mesh depending on how you define the "center of a mesh". You could use the center of the bounding sphere or the center of the bounding box (see the Geometry class) or you could average the verticies or you could open it in your modeler and see where it is.

Do what you want, but if its center is not at the origin you will probalby want to translate its center to the origin before rotating it:

World = TranslateCenterToOrigin * Rotation * TranslationToWorldPosition;

If you are moving your map around with the world matrix (maybe not such a good idea) you will additionally have to multiply the mesh's transform by the map's transform to get it to stay in the same place on the map.

Share this post


Link to post
Share on other sites
so is its centered origin not related to where it is in 3d space? am I supposed to use Matrix.Translation or is there a TranslateCenterToOrigin method in MDX. thanks for the help.

Share this post


Link to post
Share on other sites
If this is in 2 dimensions then you can just do the following.

1. Find the centre point of the quad and put it in a D2DXVECTOR2 like this -
(I assume that you are storing your quad as a RECT if not then I am sure you can work it out)

D3DXVECTOR2 CentrePosition;
CentrePosition.x = QuadRect.left + (QuadRect.right - QuadRect.left)/2;
CentrePosition.y = QuadRect.bottom + (QuadRect.top - QuadRect.bottom)/2;

2. The you subtract this from every vertex of the quad, it si much easier if you make the four corners of the quad into D3DXVECTOR2's first then you can just do this:

TopLeft -= CentrePosition;
TopRight -= CentrePosition;

etc etc

3. Apply the formula that I already mentioned to each of these points, but make sure that you save the the results to a different D3DXVECTOR2 for each point.

4. Then we need to translate the new poionts back, so you do the opposite of step 2 and add the centre position back on to each of the corner vectors that you have.

Note: If you are going to be rotating a lot of objects very often it may be better not to use a RECT and to make your own struct for the quad like this one.

struct Quad
{
D3DXVECTOR2 TopLeft;
D3DXVECTOR2 TopRight;
D3DXVECTOR2 BottomLeft;
D3DXVECTOR2 BottomRight;
};

Hope this helps, kind regards.

Mark Coleman

Share this post


Link to post
Share on other sites
To help your understanding on spaces:

Object Space is the space the the mesh/quad is defined in. It's origin is is the point that all the vertices in the model are relative to. This is the space that define verts in or the space that they are specified in an x file or whatever.

World Space is an arbitrary space generally representing the scene, a model is moved from object space to world space when all its verticies are multiplied by the world transform. The world transform determines the position of models in the scene.

Screen Space is what you see on your monitor and is generated from world space by multiplying every world transformed vert by the View and Projection matrices.

All these transforms are done at once in the hardware, but this is conceptually what is going on.

So:
If you know the center of rotation of an object in object space (objectRotationCenter) and you know the position of the object in world space (worldPosition) and the rotation of the object rouund its rotation center (objRotation).
Than your world transform should be somehting like:
Translate( -objectRotationCenter) * Rotate(objRotation) * Translate( objectRotationCenter + worldPosition)
Or Better Yet:
Matrix.AffineTransformation(1, objectRotationCenter, Quaternion.RotationYawPitchRoll(objRotation), worldPosition);

Sorry if this is a bit confusing.

Share this post


Link to post
Share on other sites
thanks for the feedback guys, I'm still in a bit of a rut though, the steps I have taken are.
s1. went into 3ds max and made sure that it was centred to 0,0,0
and exported it using panda exporter

s2. incremented the rot angle each time I draw the mesh so I can see the models movement in 3d space

s3. tried a few million different matrix combinations but can't seem to get the model in the position I want

I tried the following also, but the model just sinks into the map.

Vector3 one = new Vector3(0,0,0);
Vector3 two = new Vector3(posX,posY,posZ);
Vector3 vec = (Vector3) one + two;


device.Transform.World = Matrix.Translation(0,0,0) * Matrix.RotationAxis(new Vector3(0,0,0),angleX) * Matrix.Translation(vec);



Share this post


Link to post
Share on other sites
Quote:
Original post by dazscott
I tried the following also, but the model just sinks into the map.


What do you mean sinks into the map? Try to describe the behavior for us a little better. Is it in the right place but obscured partially by the background? How are you scrolling the screen? Are you using the view or the world matrix to do your scrolling?

Matrix.RotationAxis(new Vector3(0,0,0),angleX) is wrong. The first parameter is an axis and 0,0,0 does not specify an axis. I don't know what the result will be with 0,0,0. 0,1,0 is the y axis, 1,0,0 is the x axis. An axis really ought to be normalized vector.

Share this post


Link to post
Share on other sites
Here is how it is at the moment. It sits in the right place, but its facing the wrong direction. I'd like to have the open section of the tent facing the opposite way, but I cant seem to get it to rotate that way. I am using the World matrix to handle scrolling by changing the xPos and yPos variables. hope I've made things clearer.Thanks again for the help.



using this code.


//to set position and rotation

tentMesh.setPos(xPos,yPos,0.0f);

tentMesh.rotate(0f /(float)Math.PI ,4.7f / (float)Math.PI, 0f / (float)Math.PI);

tentMesh.DrawMesh(ref device);


//to draw
device.Transform.World = Matrix.RotationYawPitchRoll(angleX, angleY, angleZ) * Matrix.Translation(posX,posY,posZ);







[Edited by - dazscott on March 14, 2005 11:16:01 AM]

Share this post


Link to post
Share on other sites
Ok, I cannot see your picture, but I can say this: Use the View matrix for scrolling and the world matrix for positioning. Trying to use just the world matrix to do everyting is going to lead to no end of troubles for you.

Share this post


Link to post
Share on other sites
I fixed up the links to the images. any suggestions on how I can get the tent to face the opposite direction? when I increase the yaw rotation this happens.



pitch is set to 4.7f thats how I got it to face roof side up.
So how can I get it to rotate on the axis I want? thanks guys
code same as previous post.

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this