问题
I have a model that has a bone which has a translated offset from the parent bone (it is not positioned at the tail of the parent bone). In Blender, where the model was made, I can rotate the bone and see the attached mesh rotate correctly. However, when I attempt to rotate the bone in my code, it seems to rotate it about the tail of the parent. I'm messing something up in the Matrix math (my worst enemy).
Update:
protected override void Update(GameTime gameTime)
{
bone.Transform = Matrix.CreateFromYawPitchRoll(0f, 0.5f, 0f);
base.Update(gameTime);
}
Pretty standard, but if it matters, Draw:
private void DrawModel(Model model, GraphicsDevice graphics, Matrix viewMatrix, Matrix projectionMatrix)
{
Matrix[] boneTransforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(boneTransforms);
Matrix worldMatrix = orientation * Matrix.CreateTranslation(position);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = boneTransforms[mesh.ParentBone.Index] * worldMatrix;
effect.View = viewMatrix;
effect.Projection = projectionMatrix;
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
// Set the fog to match the black background color
effect.FogEnabled = true;
effect.FogColor = Vector3.Zero;
effect.FogStart = 1000;
effect.FogEnd = 3200;
}
mesh.Draw();
}
}
Here's screen shots to show the problem http://s1231.photobucket.com/albums/ee516/Neovivacity/?action=view¤t=boneRotation.png
回答1:
Ok, this may not be the most straightforward way of solving this, but I have a fix for anyone who's also having a similar issue.
When loading the Model, store the original transform. Then you multiply the bone's transform like I did. Finally you get the original transforms Translation, oringalTranform.Translation for example, and get bone's new transform. To adjust for the offset, bone.Transform *= Matrix.CreateTranslation(originalTranslation - newTranslation).
Here's a code snippet from my solution:
public void LoadContent(ContentManager content)
{
Model = content.Load<Model>(ModelName);
//Set the Bone pointers and transform matrices
AileronLBone = Model.Bones["LAileron"];
AileronRBone = Model.Bones["RAileron"];
ElevatorBone = Model.Bones["Elevator"];
RudderBone = Model.Bones["Rudder"];
FlapsBone = Model.Bones["Flaps"];
if (AileronLBone != null) AileronLTransform = AileronLBone.Transform;
if (AileronRBone != null) AileronRTransform = AileronRBone.Transform;
if (ElevatorBone != null) ElevatorTransform = ElevatorBone.Transform;
if (RudderBone != null) RudderTransform = RudderBone.Transform;
if (FlapsBone != null) FlapsTransform = FlapsBone.Transform;
}
public void Update(GameTime gameTime)
{
SetOffsetRotation(ElevatorBone, ElevatorTransform, ElevatorRotation);
}
public void SetOffsetRotation(ModelBone bone, Matrix transform, float rotation)
{
Vector3 oringalTrans = transform.Translation;
bone.Transform *= Matrix.CreateRotationX(rotation);
Vector3 newTrans = bone.Transform.Translation;
bone.Transform *= Matrix.CreateTranslation(oringalTrans - newTrans);
}
来源:https://stackoverflow.com/questions/8791845/xna-rotate-a-bone-with-an-offset-translation