Как выровнять ось Y объекта с вектором, исходящим из центральной точки их родителя

Итак, у меня есть объект (сфера), и я хочу выровнять ось Y сферы с вектором, который используется для построения ее средней точки.

В нынешнем виде все созданные объекты имеют ось ‘, как показано ниже, поэтому все, что создается в мировом пространстве, имеет ориентацию оси, как показано на рисунке ниже. Но я хочу, чтобы ось сфер в локальных координатах имела свою ось y в направлении своего родительского объекта (сферы, которую они окружают), но я не уверена, какое общее преобразование я мог бы сделать для каждого объекта, чтобы это преобразование происходят.

введите описание изображения здесь

На рисунке ниже показана желаемая ориентация объектов.

Желаемая ориентация оси объекта'

Мне нужна эта ориентация, чтобы дочерние сферы вместо всех указывали вверх, как они это делают на обеих рисунках ниже, а не наружу в зависимости от ориентации. Поэтому, если бы я должен был создать сферу внизу, а не ее дочерние сферы, сгенерированные наверху их оси X и впоследствии наполовину слитые с большой центральной сферой, они указывают наружу от большой центральной сферы

Ниже приведен код, в котором я генерирую сферы (в этом коде я генерирую больше сфер, чем показано на рисунке 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;
}

Ниже приведены возможные преобразования, которые могут быть выполнены на моих объектах.

#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

0

Решение

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

Вычислите новое направление оси Y для ребенка, вычтя позицию ребенка из родительской (чтобы получить ось Y, которая указывает на центр родителя) и нормализуйте ее. Вычислить новую ось X, пересекая новый вектор оси Y с существующим вектором оси Z (в левой системе), заботясь о том, чтобы обрабатывать случай, когда они указывают в одном направлении или точно друг против друга (возможно, нормализуются для удаления ошибка). Затем скрестите этот новый вектор оси X с новым вектором оси Y, чтобы получить новый вектор оси Z. Сохраните это в своей матрице ориентации для ребенка.

0

Другие решения

Других решений пока нет …