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.

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);

}

//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;
//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.AutoDepthStencilFormat = DepthFormat.D16;
presentParams.EnableAutoDepthStencil = true;

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

tentMesh.rotate(100,100,100);

}

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;

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 on other sites

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 on other sites
yep, that worked. thanks a lot that was giving me a headache.

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 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 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 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;

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.

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

Hope this helps, kind regards.

Mark Coleman

Share on other sites

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 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 on other sites
Quote:
 Original post by dazscottI 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 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 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 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 on other sites
I'm sorry, you are probably just going to have to play with it until you get it right. Are you sure that you mean 4.7/PI and not PI/4.7?

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.

Create an account

Register a new account

• Forum Statistics

• Total Topics
628730
• Total Posts
2984427

• 25
• 11
• 10
• 16
• 14