Вы стали жертвой теоремы о волосатом шаре:
Распространенной проблемой в компьютерной графике является создание ненулевого вектора в R3, ортогонального заданному ненулевому. Не существует единой непрерывной функции, которая могла бы делать это для всех ненулевых входных векторов. Это следствие теоремы о волосатом шаре. Чтобы убедиться в этом, рассмотрим заданный вектор как радиус сферы и заметим, что нахождение ненулевого вектора, ортогонального данному, эквивалентно нахождению ненулевого вектора, касающегося поверхности этой сферы в том месте, где он касается радиус. Однако теорема о волосатом шаре говорит, что не существует непрерывной функции, которая может делать это для каждой точки на сфере (то есть для каждого заданного вектора).
Также см. это: http://blog.sigfpe.com/2006/10/oriented-fish-and-hairy-balls.html
Проблема заключается в этих двух строках:
normal_axis = glm::vec3(0, 1, 0);
rotationAxis = glm::cross(normal_axis, forward_tangent_vector);
Когда forward_tangent_vector
совпадает с (0,1,0)
, rotationAxis
становится (0,0,0)
. Вот почему у тебя трясется в трубе.
Что вам нужно сделать вместо жесткого кодирования (0,1,0)
, так это взять первую производную сплайна (вектор скорости/тангенса), взять вторую производную сплайна (вектор ускорения/нормали) и взять их перекрестные произведения (бинормали). Нормализуйте эти три вектора, и вы получите так называемую фрейм Френе, набор из 3-х взаимно перпендикулярных векторов вокруг сплайна.
Обратите внимание, что ваш сплайн должен быть C2-непрерывным, иначе вы получите аналогичные «повороты», вызванные разрывами во второй производной (также известной как ускорение / вектор нормали).
Когда у вас есть рамка Френе, достаточно просто изменить базис для работы в этой системе координат. Не возитесь с glm::rotate
, просто поместите единичные векторы x, y, z в матрицу в виде строк (или столбцов? Я не уверен, какое соглашение использует GLM...), и это будет ваша матрица преобразования.
person
Tamás Zahola
schedule
02.04.2016