Sign in to follow this  
icethelog

Rotating around a models forward, left and up vectors

Recommended Posts

Basically I am creating a rotation widget in a directx application in which you select a model, and rotate it on it's x,y and z axis by clicking and dragging on the widget. Similar to a rotation widget in software like 3DS max. There's something I don't understand about basic rotation because multiplying an x,y,z axis rotation together will cause different results depenending on the order in which they are multiplied together unless two of the axis are set to 0,0. The only way I can think to fix this, is to somehow be able to return the up,forward and right vectors from the world matrix currently rotating the model, and then use these as x,y and z axis for calculating rotation. Movement will always be restricted to one axis at a time. Any ideas on how to do this or am I thinking about it all wrong?

Share this post


Link to post
Share on other sites
Locking rotations and translations to a specific axis is the standard way of doing it AFAIK...it's how 3dsmax does it, it's how Sandbox2 does it, and it's how I do it in my map editor. I also have let the user select a transform mode (View, Local, Parent, World), like in 3dsmax and Sandbox2. This is basically how I do it...


private void RotateSelectedObjects(float moveX, float moveY)
{
// Rotate selected objects
Vector3 axis;
float moveAmount;
Matrix rotationMatrix;

if (lockedAxis == LockedAxis.XAxis)
{
moveAmount = moveY * 0.005f;
axis = new Vector3(1, 0, 0);
}
else if (lockedAxis == LockedAxis.YAxis)
{
moveAmount = moveX * 0.005f;
axis = new Vector3(0, 1, 0);
}
else
{
moveAmount = moveX * 0.005f;
axis = new Vector3(0, 0, 1);
}

Matrix[] rotations = new Matrix[level.SelectedObjects.Count];
for (int i = 0; i < level.SelectedObjects.Count; i++)
{
Matrix transform = GetTransformForObject(level.SelectedObjects[i]);
Vector3 transformedAxis = Vector3.TransformNormal(axis, Matrix.Invert(transform));
Matrix.CreateFromAxisAngle(ref transformedAxis, moveAmount, out rotationMatrix);
rotations[i] = rotationMatrix;
}

level.RotateSelectedObjects(rotations);
}

private Matrix GetTransformForObject(GameObject gameObject)
{
if (transformType == TransformType.View)
return level.Camera.ViewMatrix;
else if (transformType == TransformType.World)
return Matrix.Identity;
else if (transformType == TransformType.Local)
return Matrix.Invert(gameObject.WorldMatrix);
else if (transformType == TransformType.Parent)
{
if (gameObject.Parent != null)
return Matrix.Invert(gameObject.Parent.WorldMatrix);
else
return Matrix.Identity;
}

return Matrix.Identity;
}



moveX and moveY would be the amount the mouse cursor has moved in screen space...you might want to use something else if you're drawing something the user is manipulating like in 3dsmax. level.RotateSelectedObjects just applies the rotation matrix by multiplying rotation * worldMatrix;

Share this post


Link to post
Share on other sites

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