Поворот геометрии для выравнивания по вектору направления

Я пытался заставить мою сгенерированную геометрию выровняться с вектором направления. Чтобы проиллюстрировать мою текущую проблему:

  • A = Правильно выровненная геометрия (просто треугольник для проверки)
  • B = неправильно выровненная геометрия

Пример проблемы

Мое текущее решение в коде для этого примера треугольника (этот код выполняется для всех узлов, которые вы видите на экране, начиная с разделения, я использую математическую библиотеку GLM):

glm::vec3 v1, v2, v3;

v1.x = -0.25f; 
v1.z = -0.25f; 

v2.x = 0.25f;
v2.z = -0.25f;

v3.x = 0.0f; 
v3.z = 0.25f;

v1.y = 0.0f;
v2.y = 0.0f;
v3.y = 0.0f;

glm::mat4x4 translate = glm::translate(glm::mat4x4(1.0f), sp.position);
glm::mat4x4 rotate = glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), sp.direction, glm::vec3(0.0f, 1.0f, 0.0f));

v1 = glm::vec4(translate * rotate * glm::vec4(v1, 1.0f)).swizzle(glm::comp::X, glm::comp::Y, glm::comp::Z);
v2 = glm::vec4(translate * rotate * glm::vec4(v2, 1.0f)).swizzle(glm::comp::X, glm::comp::Y, glm::comp::Z);
v3 = glm::vec4(translate * rotate * glm::vec4(v3, 1.0f)).swizzle(glm::comp::X, glm::comp::Y, glm::comp::Z);

Значения вектора направления для точки A:

  • х 0,000000000 с плавающей запятой
  • у 0,788205445 с плавающей запятой
  • z 0,615412235 поплавок

Значения вектора направления для точки B:

  • х 0,0543831661 с плавающей запятой
  • у 0,788205445 с плавающей запятой
  • z -0,613004684 с плавающей запятой

Изменить 1 (24.11.2013, 20:36): A и B не имеют никакого отношения, оба генерируются отдельно. При генерации A или B известны только положение и направление.

Я смотрел решения, размещенные здесь:

Но мне не удалось успешно повернуть мою геометрию, чтобы выровнять мой вектор направления. Я чувствую, что делаю что-то довольно фундаментальное неправильно.

Любая помощь будет принята с благодарностью!


person Yonathan    schedule 24.11.2013    source источник


Ответы (1)


Если A и B являются единичными векторами и вам нужна матрица вращения R, которая преобразует B так, чтобы она совпадала с A, начните с вычисления C = B x A (перекрестного произведения B и A). C — это ось вращения, а arcsin(|C|) — необходимый угол поворота.

Из них вы можете построить требуемую матрицу вращения. Похоже, что glm поддерживает это, поэтому я не буду объяснять дальше.

NB, если вы делаете много, много из этого в критичном для производительности коде, вы можете получить немного скорости, заметив |C| = sin(theta), sqrt(1 - |C|^2) = cos(theta) и самостоятельно вычислив матрицу с этими известными значениями sin(theta) и cos(theta). См., например, это обсуждение. Процедура glm возьмет ваш угол arcsin(|C|) и немедленно приступит к вычислению его sin и cos, что является небольшой тратой времени, поскольку вы уже знали их, а операции относительно дороги.

Если вращение происходит вокруг некоторой точки p, отличной от начала координат, то пусть T будет перемещением, которое переводит p в начало координат, и найдите X = T^-1 R T. Это X будет той трансформацией, которую вы хотите.

person Gene    schedule 24.11.2013
comment
Проблема здесь в том, что A и B не имеют отношения и не могут использоваться таким образом. При создании треугольника в точке A или B известны только положение и направление. Я уточню свой вопрос вверху, чтобы включить это. - person Yonathan; 24.11.2013
comment
@ Йонатан, друг мой, в этом нет абсолютно никакого смысла. Вы должны объяснить, какую точку и вектор необходимо перевести и/или повернуть в другую точку и вектор (или эквивалентное описание преобразования). - person Gene; 25.11.2013
comment
При создании треугольника в точке A или точке B у меня есть только перевод (положение) и направление, в котором он должен быть обращен. Перевод работает нормально, так как вы можете видеть, что оба треугольника расположены на темно-серой точке. Более светлая серая линия указывает направление, в котором должно быть указано лицо. То, что я пытаюсь сделать, это иметь эти треугольники на каждой серой точке, обращенной к следующей серой точке. Это позволяет в какой-то момент сгенерировать геометрию вдоль этих точек, которая правильно выравнивается. Поэтому я хочу создать матрицу для правильного поворота вершин этой геометрии. Надеюсь, это имеет больше смысла. - person Yonathan; 25.11.2013
comment
@Yonathan Тогда мой ответ применим. Если у вас есть треугольник с неправильным вектором нормали (A), и у вас есть две точки, описывающие правильный горизонтальный вектор (B), то вам нужно вращение, которое переводит A в B. Это то, что я описал. - person Gene; 25.11.2013
comment
Вы также можете использовать (A•B)/(|A||B|) для получения косинуса, поскольку скалярное произведение двух единичных векторов является косинусом угла между ними. - person Brian McCutchon; 02.12.2014