2016-04-02 11 views
1

Я пытаюсь прикрепить профили 2d формы к сплайновой кривой. В определенных точках сплайна я получаю странные искажающие артефакты в моей геометрии, как показано на изображении. Как я могу избежать этого, используя уравнения Frenet-Frame?Избегайте скручивания артефактов в экструзии сплайнов [OpenGL, C++]

Мои текущие расчеты для нормальной, бинормалью и касательной:

forward_tangent_vector = glm::normalize(pointforward - pointmid); 
backward_tangent_vector = glm::normalize(pointmid - pointback); 
second_order_tangent = glm::normalize(forward_tangent_vector - backward_tangent_vector); 
binormal = glm::normalize(glm::cross(forward_tangent_vector,second_order_tangent)); 
normal = glm::normalize(glm::cross(binormal, forward_tangent_vector)); 

//translation matrix 
T = glm::translate(T, pointmid); 

normal_axis = glm::vec3(0, 1, 0); 
rotationAxis = glm::cross(normal_axis, forward_tangent_vector); 
rotationAngle = glm::acos(glm::dot(normal_axis, forward_tangent_vector)); 

//rotation matrix 
R = glm::rotate(R, glm::degrees(rotationAngle), rotationAxis); 

enter image description here

ответ

3

Вы пали жертвой hairy ball theorem:

Общей проблемой в компьютерной графике является для генерации ненулевой вектор в 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). Вот почему вы получаете толчок в своей трубе.

Что нужно сделать вместо hardcoding (0,1,0), - взять первую производную сплайна (вектор скорости/касания), взять вторую производную сплайна (вектор ускорения/нормали) и взять их кросс-произведения (бинормальная). Нормализовать эти три вектора, и вы получите так называемый Frenet-frame, набор из 3 взаимно перпендикулярных векторов вокруг сплайна.

Обратите внимание, что ваш сплайн должен быть C2-непрерывным, иначе вы получите похожие «завихрения», вызванные разрывами во второй производной (например, ускорение/нормальный вектор).

Как только у вас есть Frenet-frame, это вопрос простой замены базы для работы в этой системе координат. Не путайте с glm::rotate, просто вставьте векторы x, y, z в матрицу в виде строк (или столбцов? Я не уверен, что конвенция GLM использует ...), и это будет ваша матрица преобразования.

+1

Хорошо, проблема в том, что я не могу гарантировать, будет ли кривая непрерывной C2. Кривая генерируется алгоритмом, который может или не может обеспечивать непрерывную кривую C2. Когда у меня есть матрица 'tbn', как я могу изменить основу этих профилей окружностей (2d-формы). – jaykumarark

+0

Просто умножьте вершины на эту матрицу. Также не забудьте перевести начало координат в начало фрейма. –