问题
I have a question concerning a single mesh (building) that contains a collection of animated objects (these objects make up the complete building, rising up from the ground when it is constructed, at different speeds and rotations).
The animated objects in the mesh all have their own position and rotation animation tracks. I export it from 3DS Max as an ASE, convert it into a properietary format andd use it in my gaming engine.
So, at the moment, I can successfully display the animated positions of all of the animated objects in the mesh. Doing the following:
The scale, rotation and translation variables are the transformation information for the building. This is valid for all the sub-objects. The pos variable indicates the sub-objects position relative to the building centre.
foreach (GeometricObject geoObject in mesh.GeoObjects)
{
Vector3 pos = geoObject.AnimationData.PositionTrack[(int)m_keyFrameTime];
Vector3 translatedPos = new Vector3(translation.X + pos.X,
translation.Y + pos.Y,
translation.Z + pos.Z)
_eRenderer.ActiveCamera.World = Matrix.CreateScale(scale) *
Matrix.CreateFromQuaternion(rotation) *
Matrix.CreateTranslation(translatedPos);
}
This displays the animated building (rising from the ground) perfectly and alll sub-objects are in their correct positions.
Now, the problem comes in when I try to rotate the sub-objects. I have tried a quite a few different approaches, but the translation of the sub-objects always seems to get messed up after I have rotated the sub-object. This is what I currently have, but it is still messed up:
foreach (GeometricObject geoObject in mesh.GeoObjects)
{
Vector3 pos = geoObject.AnimationData.PositionTrack[(int)m_keyFrameTime];
Vector3 translatedPos = new Vector3(translation.X, translation.Y, translation.Z)
Matrix rotateSubObjects;
rotateSubObjects = Matrix.CreateTranslation(new Vector3(pos.X, pos.Y, pos.Z));
rotateSubObjects *= Matrix.CreateFromQuaternion(geoObject.AnimationData.RotationTrack[(int)m_keyFrameTime]);
_eRenderer.ActiveCamera.World = Matrix.CreateScale(scale) *
Matrix.CreateFromQuaternion(rotation) *
Matrix.CreateTranslation(translatedPos) *
rotateSubObjects;
}
I have read that I might need to translate the sub-objects back to its origin for it to rotate around its origin, and then translate it back to its world position, but I'm not sure how to do that in this case.
I'm out of ideas, any help would be appreciated! Regards, Riaan.
回答1:
The transformation you're looking for is this:
Matrix positionRotationMatrix = Matrix.CreateTranslation(-parentPosition)
* Matrix.CreateFromQuaternion(parentRotation)
* Matrix.CreateTranslation(parentPosition);
Vector3 translation = Vector3.Transform(parentPosition + relativePosition,
positionRotationMatrix);
You define your world matrix with the new sub-objects position (translation
variable):
Matrix worldMatrix = Matrix.CreateScale(scale)
* Matrix.CreateFromQuaternion(rotation)
* Matrix.CreateFromQuaternion(parentRotation)
* Matrix.CreateTranslation(translation);
To demonstrate, here's a cube (parent) that is being rotated around it's position, with an arrow whose position and rotation are defined in relation to its parents position and rotation. The arrow follows the cubes rotation, and rotates around it's Z axis independently.
Values used for the demonstration:
parentPosition = Vector3(-1.1f, 0f, -2); //cube
relativePosition = Vector3(0, 0, -3); //arrow
parentRotation = Quaternion.CreateFromRotationMatrix(
Matrix.CreateRotationZ(angle)
* Matrix.CreateRotationY(angle)
* Matrix.CreateRotationX(0.5f));
rotation = Quaternion.CreateFromYawPitchRoll(0f, 0f, angle);
angle += 0.05f;
来源:https://stackoverflow.com/questions/13890820/rotating-objects-attached-to-other-objects