Matrix对象之间的距离,相对于父对象,使用XNA?

时间:2011-08-04 04:20:35

标签: c# matrix xna

我想了解如何测量两个3D对象之间的距离,让我们称它们为父对象和子对象。将父母视为汽车的车身,将孩子视为汽车的轮子。

我理解如何根据世界空间中的物体位置获得差异,但我希望根据父亲相对物体空间获得差异作为衡量标准。

例如,如果父母面向东方且孩子是父母的2X,3Y,则以相对意义来衡量。这样如果父母旋转了60度,则儿童的相对位置在对象空间中保持2x,3y的距离。在世界空间感觉中,儿童对象测量作为Vector3将是完全不同的。

基本上我只想要一种可预测的方法来获得差异,以便专利右侧的子对象始终保持在父对象的右侧。

这是父组件,此更新每帧运行:

[Serializable]
    public class Component_Parent : BaseComponentAutoSerialization<ISceneEntity>
    {
        public override void OnUpdate(GameTime gameTime)
        {
            PassThrough.ParentMatrix = ParentObject.World;
            PassThrough.ParentTranslation = ParentObject.World.Translation;


        }
    }

下一部分是子组件:

[Serializable]
    public class Component_Child : BaseComponentAutoSerialization<ISceneEntity>
    {
        Vector3 _parentOffset;
        Quaternion _parentQuaternionOffset;

        public override void OnUpdate(GameTime gameTime)
        {
            // Get a sceneobject from the ParentObject
            SceneObject sceneobject = (SceneObject)ParentObject;

            // This relies on the position never being at 0,0,0 for setup, so please don't do that
            // or change it with more look ups so that you don't need to rely on a Zero Vector3 :-)
            if (PassThrough.GroupSetupMode || _parentOffset == Vector3.Zero)
            {
                if (PassThrough.ParentTranslation != Vector3.Zero)
                {
                    _parentOffset = sceneobject.World.Translation - PassThrough.ParentTranslation;

                    // Decompose World Matrix (Parent)
                    Quaternion parentQ = new Quaternion();
                    Vector3 parentSpot = new Vector3();
                    Vector3 parentScale = new Vector3();
                    PassThrough.ParentMatrix.Decompose(out parentScale, out parentQ, out parentSpot);

                    Matrix identity = Matrix.Identity;

                    // Decompose Identity Matrix (Parent)
                    Quaternion identityQ = new Quaternion();
                    Vector3 identitySpot = new Vector3();
                    Vector3 identityScale = new Vector3();
                    identity.Decompose(out identityScale, out identityQ, out identitySpot);

                    _parentQuaternionOffset = identityQ - parentQ;
                }
            }
            else
            {
                if (_parentOffset != Vector3.Zero)
                {

                    // Decompose World Matrix (Child)
                    Quaternion rotationQ = new Quaternion();
                    Vector3 spot = new Vector3();
                    Vector3 scale = new Vector3();
                    sceneobject.World.Decompose(out scale, out rotationQ, out spot);


                    // Decompose World Matrix (Parent)
                    Quaternion parentQ = new Quaternion();
                    Vector3 parentSpot = new Vector3();
                    Vector3 parentScale = new Vector3();
                    PassThrough.ParentMatrix.Decompose(out parentScale, out parentQ, out parentSpot);

                    Matrix location = Matrix.CreateTranslation(PassThrough.ParentTranslation);
                    Matrix rotation = Matrix.CreateFromQuaternion(parentQ);

                    Matrix rotation2 = Matrix.CreateFromQuaternion(_parentQuaternionOffset);

                    Matrix newWorld = rotation * location;

                    Vector3 testTranslation = newWorld.Translation + ((newWorld.Left * _parentOffset.X) + (newWorld.Up * _parentOffset.Y) + (newWorld.Forward * _parentOffset.Z));
                    Matrix scaleM = Matrix.CreateScale(scale);



                    //sceneobject.World = scaleM * (rotation * (Matrix.CreateTranslation(testTranslation)));
                    sceneobject.World = (Matrix.CreateTranslation(testTranslation));
                }
            }
        }
    }

我认为它跟踪身份矩阵跟踪偏移旋转有什么关系,我已经开始尝试添加一些代码来实现这种效果,但实际上不确定接下来会发生什么。

其他:

如果我的父对象面向世界空间的方向,那么一切都有效,如果它面向不同的方向,那么它就是一个问题,并且当它们被组合在一起时,孩子似乎旋转了相同的数量。

我上传了一个演示视频,试着解释一下:

http://www.youtube.com/watch?v=BzAKW4WBWYs

我还粘贴了组件的完整代码,静态传递和场景实体。

http://pastebin.com/5hEmiVx9

由于

3 个答案:

答案 0 :(得分:2)

  

想想汽车上的轮子。我希望右轮始终保持一致   相对于汽车车身的位置。

听起来您希望能够找到车轮的任何位置或位置的位置。 XNA必须帮助的一个内置方法是Model.CopyAbsoluteBoneTransformsTo(Matrix []);但是,您的代码看起来像是要手动处理父子关系。所以这是一种不使用内置方法的方法。它假设您在加载时确实有偏移信息:

在游戏循环开始之前(例如,在LoadContent方法中),在加载汽车&amp;轮并假设它们加载到正确的位置,然后您可以创建偏移向量(_parentOffset)

Vector3 _parentOffset = wheel.meshes[?].ParentBone.Transform.Translation - car.meshes[?].ParentBone.Transform.Translation;//where ? is the mesh index of the mesh you are setting up.

保存该矢量,不要修改它。

之后,在汽车的矩阵旋转和/或位置偏移后,设置车轮的矩阵如下:

Matrix wheelMatrix = carMatrix;
wheelMatrix.Translation += (wheelMatrix.Right * _parentOffset.X) +
                           (wheelMatrix.Up * _parentOffset.Y) +
                           (wheelMatrix.Backward * _parentOffset.Z);

这允许车轮矩阵将继承汽车的任何旋转和平移信息,但无论车辆的方向/位置如何,都将适当地移动车轮的位置。

答案 1 :(得分:0)

两个物体之间的距离不是两个方向的函数。

您基本上想要的是子对象与父对象的方向线的距离。假设你有一个全局笛卡尔坐标系,这可以简单地计算为h = sqrt(x ^ 2 + y ^ 2)* sin(Theta),x和y是孩子相对于父母和Theta的相对坐标。从x轴测量的父母的方向。

但问题仍然让我感到困惑。如果您只想确保孩子在父母的右侧,为什么不简单地检查相对x?如果它是肯定的,它在右侧,如果它是负的,它在左边?

答案 2 :(得分:0)

问题在于我试图利用世界空间的偏移量。 感谢在EFnet上从#XNA中闪现,这段代码完美无缺:

 [Serializable]
    public class Component_Child_fromxna : BaseComponentAutoSerialization<ISceneEntity>
    {
        Vector3 _parentOffset;
        Matrix _ParentMatrixOffset;


        public override void OnUpdate(GameTime gameTime)
        {
            // Get a sceneobject from the ParentObject
            SceneObject sceneObject = (SceneObject)ParentObject;


            // This relies on the position never being at 0,0,0 for setup, so please don't do that
            // or change it with more look ups so that you don't need to rely on a Zero Vector3 :-)
            if (PassThrough.GroupSetupMode || _parentOffset == Vector3.Zero)
            {
                if (PassThrough.ParentTranslation != Vector3.Zero)
                {
                    // The old offset - This is just in world space though...
                    _parentOffset = sceneObject.World.Translation - PassThrough.ParentTranslation;

                    // Get the distance between the child and the parent which we keep as the offset
                    // Inversing the ParentMatrix and multiplying it by the childs matrix gives an offset
                    // The offset is stored as a relative xyz, based on the parents object space
                    _ParentMatrixOffset = sceneObject.World * Matrix.Invert(PassThrough.ParentMatrix);
                }
            }
            else
            {
                if (_parentOffset != Vector3.Zero)
                {

                    //Matrix pLocation = Matrix.CreateTranslation(_parentOffset);
                    //sceneObject.World = Matrix.Multiply(pLocation, PassThrough.ParentMatrix);

                    sceneObject.World = Matrix.Multiply(_ParentMatrixOffset, PassThrough.ParentMatrix);
                }
            }
        }
    }