简体   繁体   English

如何将对象的Y轴与从其父对象的中心点开始的矢量对齐

[英]How to align the Y-Axis of an object with a vector eminating from the centre point of their parent

So I have an object (Sphere) and I want to align the y-axis of the sphere with the vector that is used to plot its mid-point. 因此,我有一个对象(球体),我想将球体的y轴与用于绘制其中点的向量对齐。

As it stands now, all objects created have the axis' set as shown below, so everything created in the world space has an axis orientation as seen in the picture below. 现在,所有创建的对象都具有如下所示的“轴”设置,因此,在世界空间中创建的所有对象都具有一个轴方向,如下图所示。 But I want the axis of the spheres in local coordinates to have their y axis in the direction of their parent object (the sphere which they surround) but I'm unsure what blanket transformation I could do for each object in order for this transformation to occur. 但是我希望局部坐标中的球体的轴的y轴朝向其父对象(它们所围绕的球体)的方向,但是我不确定我可以对每个对象进行什么整体变换以使变换为发生。

在此处输入图片说明

Pictured below is the desired orientation of the objects. 下图是对象的所需方向。

物体轴的期望方向

I need this orientation, so the child spheres instead of all pointing upwards like they do in both pictures below, pont outwards based on the orientation. 我需要这种方向,因此子球体(而不是像下面的两张图片一样都指向上方)会根据该方向向外伸出。 So if I was to generate a sphere at the bottom, rather than its child spheres being generated at the top of their x-axis and subsequently half merging with the large centre sphere, they point outwards away from the large centre sphere 因此,如果我要在底部生成一个球体,而不是在其x轴的顶部生成其子球体,然后将其与大的中心球体半合并,则它们会指向远离大的中心球体

Below is the code where I generate the spheres ( I generate more spheres in this code than pictured ie 9 but lessened the amount of spheres present in the pictures for clarification and not to clutter the image ) 下面是我生成球体的代码(我在此代码中生成的球体比图片中生成的球体多,即9个,但为清晰起见,减少了图片中存在的球体数量,以免使图像混乱)

bool static CreateSphereLevels(Sphere *parent, float childRadiusRatio, int levels,
            Material** materials)

{
    if (levels == 1) {
        for (int i = 0; i < 6; i++) {
            Sphere * s = new Sphere(childRadiusRatio, materials[i % 6]);
            parent->AddChild(s);
            float rm = parent->GetRadius() + s->GetRadius();
            if (i == 0)
                s->SetPosition(vec3(0.0f, rm, 0.0f));
            if (i >= 1 && i < 6)
                s->SetPosition(vec3(RotationY(60 * i) * vec4(0.0f, rm, 0.0f, 0.0f)));
            if (i == 1 || i == 3 || i == 5) {
                Sphere * sn = new Sphere(childRadiusRatio, materials[i]);
                parent->AddChild(sn);
                sn->SetPosition(vec3(RotationY(60 * i) * RotationZ(60) * vec4(0.0f, rm, 0.0f, 0.0f)));
            }
        }
        return true;
    }
    else {
        for (int i = 0; i < 6; i++) {
            Sphere * s = new Sphere(childRadiusRatio, materials[i % 6]);
            parent->AddChild(s);
            int newLevels = levels - 1;
            CreateSphereLevels(s, (childRadiusRatio / 3), newLevels, materials);
            float rm = parent->GetRadius() + s->GetRadius();
            if (i == 0)
                s->SetPosition(vec3(0.0f, rm, 0.0f));
            if (i >= 1 && i < 6)
                s->SetPosition(vec3(RotationY(60 * i) * vec4(0.0f, rm, 0.0f, 0.0f)));
            if (i == 1 || i == 3 || i == 5) {
                Sphere * sn = new Sphere(childRadiusRatio, materials[i]);
                parent->AddChild(sn);
                CreateSphereLevels(sn, (childRadiusRatio / 3), newLevels, materials);
                sn->SetPosition(vec3(RotationY(60 * i) * RotationZ(60) * vec4(0.0f, rm, 0.0f, 0.0f)));
            }
        }
    }
    return true;
}

Below now is the possible transformations that can be performed on my objects 现在,下面是可以对我的对象执行的可能转换

#ifndef RAYTRACER_SCENES_SCENEOBJECT_H
#define RAYTRACER_SCENES_SCENEOBJECT_H

#include <Raytracer/Scenes/SceneObjectType.h>

#include <vector>

namespace Raytracer
{
    namespace Scenes
    {
        class SceneObject
        {
        private:

            /**
             * The transformation matrix to transform a point from world coordinates to local
             * coordinates.
             */
            glm::mat4x4 globalTransformation;

            glm::mat4x4 transformation;

            glm::mat4x4 globalToLocal;

            /**
             * Updates the global transformation based on the current transformation. This
             * includes child objects.
             */
            void UpdateTransformations();

            std::vector<SceneObject *> children;
            SceneObject * parent;

        public:

            /**
             * Constructs a new SceneObject.
             */
            SceneObject();

            /**
             * Destructs a SceneObject and deletes all child objects.
             */
            virtual ~SceneObject();

            /**
             * Adds a new child to this object.
             *
             * @param child The new child object. This object becomes child's parent object. This
             *   object takes ownership of child.
             * @return true if the child was added successfully, false otherwise.
             */
            bool AddChild(SceneObject *child);

            /**
             * Retrieves a list of all children of this object.
             *
             * @return A list of all children of this object
             */
            const std::vector<SceneObject *> &GetChildren() const;

            /**
            * Retrieves the position of this object in world space, i.e. the translation component
            * of the global transformation matrix.
            *
            * @return The global position of this object
            */
            const glm::vec3 GetGlobalPosition() const;

            /**
            * Retrieves a matrix that can be used to transform coordinates from world space to
            * object space. This is the inverse of the global transformation matrix.
            *
            * @return The inverse of the global transformation matrix
            */
            const glm::mat4x4 &GetGlobalToLocal() const;

            /**
             * Retrieves the global transformation matrix. The global transformation matrix is used
             * to transform coordinates from object space to world space.
             *
             * @return The global transformation matrix
             */
            const glm::mat4x4 &GetGlobalTransformation() const;

            /**
             * Retrieves the parent object of this object.
             *
             * @param The parent object of this object or NULL if this object has no parent
             */
            SceneObject *GetParent() const;

            /**
             * Retrieves the position of this object, i.e. the translation component of the
             * transformation matrix.
             *
             * @return The position of the object
             */
            const glm::vec3 GetPosition() const;

            /**
             * Retrieves the transformation matrix. The transformation matrix is used to transform
             * coordinates from object space to the object space of the parent object (or world
             * space if this object has no parent).
             *
             * @return The transformation matrix
             */
            const glm::mat4x4 &GetTransformation() const;

            /**
             * Checks whether this instance is of the given type.
             *
             * @param type The type to check against
             * @return true if this object is of type type, false otherwise
             */
            virtual bool IsInstanceOf(SceneObjectType type) const = 0;

            /**
            * Sets the global transformation matrix. The global transformation matrix is used
            * to transform coordinates from object space to world space.
            *
            * @param transformation The new global transformation matrix
            */
            void SetGlobalTransformation(const glm::mat4x4 &transformation);

            /**
             * Sets the position of this object, i.e. the translation component of the
             * transformation matrix.
             *
             * @param position The new position
             */
            void SetPosition(const glm::vec3 &position);

            /**
             * Sets the transformation matrix. The transformation matrix is used to transform
             * coordinates from object space to the object space of the parent object (or world
             * space if this object has no parent).
             *
             * @param transformation The new transformation matrix
             */
            void SetTransformation(const glm::mat4x4 &transformation);

            void ChildRemove(SceneObject * child);
        };
    }
}

#endif // RAYTRACER_SCENES_SCENEOBJECT_H

In other words, you want a way to point your child sphere at the parent one. 换句话说,您想要一种将子球指向父球的方法。

Compute a new Y axis direction for the child by subtracting the child's position from the parent's (to get a Y axis that points to the center of the parent) and normalize it. 通过从父母的位置减去孩子的位置(以获得指向父母中心的Y轴)并对其进行归一化,为孩子计算新的Y轴方向。 Compute a new X axis by crossing the new Y axis vector with the existing Z axis vector (in a left handed system), taking care to handle the case where they are pointing in the same direction or exactly opposite each other (possibly normalizing to remove error). 通过将新的Y轴向量与现有的Z轴向量相交(在左​​手系统中)来计算新的X轴,请小心处理它们指向相同方向或彼此完全相反的情况(可能通过归一化删除)错误)。 Then cross this new X axis vector with the new Y axis vector to get a new Z axis vector. 然后将此新的X轴向量与新的Y轴向量交叉,以获得新的Z轴向量。 Store this in your orientation matrix for the child. 将其存储在孩子的方向矩阵中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM