简体   繁体   中英

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.

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.

在此处输入图片说明

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

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 )

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. 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). Then cross this new X axis vector with the new Y axis vector to get a new Z axis vector. Store this in your orientation matrix for the child.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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