Расстояние между объектами Matrix относительно ориентации родителей с использованием XNA? - PullRequest
2 голосов
/ 04 августа 2011

Я хотел бы понять, как измерить расстояние между двумя трехмерными объектами, давайте назовем их родительским объектом и дочерним объектом.Думайте о родителе как о кузове автомобиля, а ребенок - как о колесе автомобиля.

Я понимаю, как получить разницу, основываясь на положении объектов в мировом пространстве, но я хотел бы получить разницу как измерение, основанное на относительном объектном пространстве родителей.

Например, если родитель смотрит на восток, а ребенок в 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 ]

2 голосов
/ 05 августа 2011

Думаю колеса на машине.Я хочу, чтобы правое колесо всегда было в одном и том же месте относительно кузова автомобиля.

Звучит так, как будто вы хотите иметь возможность определить положение колеса для любой заданной ориентации или положения.из машины.Одним из встроенных методов, которым XNA должен здесь помочь, является Model.CopyAbsoluteBoneTransformsTo (Matrix []);Тем не менее, ваш код выглядит так, как будто вы хотите обрабатывать отношения родитель-потомок вручную.Так что вот способ сделать это без использования встроенного метода.Предполагается, что у вас есть информация о смещении во время загрузки:

Перед началом игровых циклов (скажем, в методе LoadContent), после загрузки автомобиля и руля и предполагая, что они загружаются в правильные позиции, вы можете затем создатьваш вектор смещения (_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.

Сохраните этот вектор и не изменяйте его.

Позже, после того, как матрица автомобиля будет смещена с помощью вращения или позиционирования, установите матрицу колеса следующим образомthis:

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

Это позволяет матрице колес наследовать любую информацию о вращении и поступательном движении от автомобиля, но смещает положение колеса соответствующим образом независимо от ориентации / положения автомобиля.

0 голосов
/ 07 августа 2011

Проблема заключалась в том, как я пытался использовать смещение мирового пространства.Благодаря прошивке из #XNA на EFnet этот код работает отлично:

 [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);
                }
            }
        }
    }
0 голосов
/ 04 августа 2011

Расстояние между двумя объектами НЕ является функцией обеих ориентаций.

То, что вы в основном хотите, - это расстояние дочернего объекта до линии ориентации родительского объекта. Предполагая, что у вас есть глобальная декартова система координат, это можно просто вычислить как h = sqrt (x ^ 2 + y ^ 2) * sin (Theta), где x и y - относительные координаты дочернего элемента относительно родителя, а Theta - ориентация родителя измеряется от оси х.

Но все же этот вопрос меня немного смущает. Если вы хотите убедиться, что ребенок находится справа от родителя, почему бы вам просто не проверить относительный x? Если он положительный, то справа, а если отрицательный - слева?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...