【问题标题】:How do I rotate meshes around their local axes in XNA?如何在 XNA 中围绕局部轴旋转网格?
【发布时间】:2012-11-22 03:11:11
【问题描述】:

我的游戏中有一个对象,它有几个网格,当我尝试以任一方式旋转任一网格时,它只会围绕世界轴旋转,而不是围绕其局部轴旋转。我在类构造函数中有一个rotation = Matrix.Identity。每个网格都附加了这个类。那么这个类也包含方法:

...
public Matrix Transform{ get; set; }
public void Rotate(Vector3 newRot)
{
    rotation = Matrix.Identity;
    rotation *= Matrix.CreateFromAxisAngle(rotation.Up, MathHelper.ToRadians(newRot.X));
    rotation *= Matrix.CreateFromAxisAngle(rotation.Right, MathHelper.ToRadians(newRot.Y));
    rotation *= Matrix.CreateFromAxisAngle(rotation.Forward, MathHelper.ToRadians(newRot.Z));

    CreateMatrix();
}

private void CreateMatrix()
{
    Transform = Matrix.CreateScale(scale) * rotation * Matrix.CreateTranslation(Position);
}
...

现在是 Draw() 方法:

foreach (MeshProperties mesh in model.meshes)
{
    foreach (BasicEffect effect in mesh.Mesh.Effects)//Where Mesh is a ModelMesh that this class contains information about
    {
        effect.View = cam.view;
        effect.Projection = cam.projection;
        effect.World = mesh.Transform;
        effect.EnableDefaultLighting();
    }
    mesh.Mesh.Draw();
}

编辑: 恐怕我在某个地方搞砸了,或者你的技术不起作用,这就是我所做的。每当我移动整个对象(父对象)时,我都会将其 Vector3 Position; 设置为该新值。我还将每个 MeshProperties Vector3 Position; 设置为该值。然后在 CreateMatrix() 的 MeshProperties 中我这样做了:

...
Transform = RotationMatrix * Matrix.CreateScale(x, y, z) * RotationMatrix * Matrix.CreateTranslation(Position) * Matrix.CreateTranslation(Parent.Position);
...

地点:

public void Rotate(Vector3 newRot)
{
    Rotation = newRot;
    RotationMatrix = Matrix.CreateFromAxisAngle(Transform.Up,          MathHelper.ToRadians(Rotation.X)) * 
    Matrix.CreateFromAxisAngle(Transform.Forward, MathHelper.ToRadians(Rotation.Z)) * 
    Matrix.CreateFromAxisAngle(Transform.Right, MathHelper.ToRadians(Rotation.Y));
}

RotationVector3RotationMatrixTransform 在构造函数中都设置为 Matrix.Identity

问题是,如果我尝试围绕 Y 轴旋转,他应该在“静止不动”时旋转一圈。但他在旋转时四处移动。

【问题讨论】:

    标签: c# xna


    【解决方案1】:

    我不完全确定这是您想要的。我在这里假设您有一个对象,其中一些网格和位置偏离主对象位置的位置和方向,并且您希望相对于父对象围绕其局部轴旋转子对象。

    Matrix.CreateTranslation(-Parent.Position) *                  //Move mesh back...
    Matric.CreateTranslation(-Mesh.PositionOffset) *              //...to object space
    
    Matrix.CreateFromAxisAngle(Mesh.LocalAxis, AngleToRotateBy) * //Now rotate around your axis
    Matrix.CreateTranslation(Mesh.PositionOffset) *               //Move the mesh...
    Matrix.CreateTranslation(Parent.Position);                    //...back to world space
    

    当然,您通常会存储一个变换矩阵,它可以一步将网格从对象空间转换到世界空间,并且您还需要存储逆矩阵。您还将网格始终存储在对象坐标中,并且仅将其移动到世界坐标中进行渲染。这会简化一些事情:

    Matrix.CreateFromAxisAngle(Mesh.LocalAxis, AngleToRotateBy) * //We're already in object space, so just rotate
    ObjectToWorldTransform *
    Matrix.CreateTranslation(Parent.Position);
    

    我认为您可以简单地将示例中的 Mesh.Transform 设置为此并准备就绪。

    我希望这就是你要找的!

    【讨论】:

    • 实际上,所有的网格都有相同的位置。我知道这听起来很奇怪,但它正确地绘制了它们,而不是全部在一个地方。我不知道这怎么可能,知道怎么做吗?顺便说一句,您能否解释一下这些变量代表什么:(Mesh.LocalAxis ,objectToWorldTransformParent.Position) ?
    • 好吧,你说“围绕世界轴旋转,而不是它的局部轴”,所以 mesh.LocalAxis 是你想要围绕它旋转的任何轴! ObjectToWorldTransform 是一个从对象空间转换到世界空间的矩阵,即缩放 * 旋转 * 平移。 Parent.Position 是网格父级的位置,听起来您使用多个网格来表示一个对象,其中 parent.Position 将是对象的位置,而不是任何特定的网格。
    【解决方案2】:

    问题是,当我将模型导出为 .FBX 时,轴心点不在模型中心。从而使模型在旋转时移动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-06
      • 2018-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-22
      相关资源
      最近更新 更多