Нахождение углов вращения между 3d точками - PullRequest
4 голосов
/ 08 ноября 2008

Я пишу программу, которая будет рисовать твердое тело вдоль кривой сплайна. Я использую Visual Studio 2005 и пишу на C ++ для OpenGL. Я использую FLTK, чтобы открыть мои окна (быстрый и легкий инструментарий).

В настоящее время у меня есть алгоритм, который будет рисовать кардинальный кубический сплайн с заданным набором контрольных точек, разбивая интервалы между точками на подинтервалы и рисуя отрезки линий между этими подточками. Количество подинтервалов является переменным.

Код рисования линий прекрасно работает и в основном работает следующим образом: я генерирую набор точек вдоль кривой сплайна, используя уравнение сплайна, и сохраняю их в массиве (в виде специальной структуры данных под названием Pnt3f, где координаты - 3 числа с плавающей запятой и есть некоторые удобные функции, такие как расстояние, длина, точка и перекрестный продукт). Тогда у меня есть один цикл, который перебирает массив точек и рисует их так:

glBegin(GL_LINE_STRIP);
for(pt = 0; pt<=numsubsegements ; ++pt) {
    glVertex3fv(pt.v());
}
glEnd();

Как уже говорилось, этот код прекрасно работает. Теперь я хочу вместо рисования линии выдавливать твердое тело. Мое текущее исследование - использование квадрики «цилиндр» для создания трубы вдоль линии. Это немного сложнее, так как я должен ориентировать openGL в направлении, в котором я хочу нарисовать цилиндр. Моя идея сделать это:

Psuedocode:

Push the current matrix,
translate to the first control point
rotate to face the next point
draw a cylinder (length = distance between the points)
Pop the matrix
repeat

Моя проблема - получить углы между точками. Мне нужны только рыскание и тангаж, крен не важен. Я знаю, что возьмите арккосинус точечного произведения двух точек, разделенных на величину обеих точек, вернем угол между ними, но это не то, что я могу передать в OpenGL для поворота. Я пытался сделать это в 2d, используя плоскость XZ, чтобы получить вращение x, и делая векторы точек из начала координат, но он не возвращает правильный угол.

Мой нынешний подход намного проще. Для каждой плоскости вращения (X и Y) найдите угол по:

арккосинус ((разница значений 'x') / расстояние между точками)

значение 'x' зависит от того, как вы настроили плоскость, хотя для моих расчетов я всегда использую мир x.

Если исключить некоторые проблемы, из-за которых он будет отображать правильный квадрант, который я еще не разработал, я хочу получить совет, чтобы выяснить, является ли это хорошей реализацией, или узнать, знает ли кто-то лучший способ.

Ответы [ 3 ]

1 голос
/ 08 ноября 2008

Несколько заметок:
Прежде всего это:

for(pt = 0; pt<=numsubsegements ; ++pt) {
  glBegin(GL_LINE_STRIP);
    glVertex3fv(pt.v());
}
glEnd();

не очень хороший способ рисовать что-либо. Вы ДОЛЖНЫ иметь один glEnd () для каждого glBegin (). Вы, вероятно, хотите получить glBegin () из цикла. тот факт, что это работает, - просто удача.

вторая вещь

Мое текущее исследование использует квадрик "цилиндр" для создания трубки вдоль линии

Это не будет работать так, как вы ожидаете. квадрик «цилиндр» имеет основание с плоским верхом и основание с плоским дном. Даже если вам удастся сделать правильные повороты в соответствии со сплайном, края плоских вершин будут выпадать из объема предполагаемой трубки, и она не будет гладкой. Вы можете попробовать это в 2D только с ручкой и бумагой. Попробуйте нарисовать гладкую трубку, используя только более короткие трубки с плоскими основаниями. Это невозможно.

В-третьих, к вашему актуальному вопросу, окончательным инструментом для таких вращений являются кватернионы . Это немного сложно объяснить в этой области, но вы можете найти много полезной информации, где бы вы ни посмотрели.
Если бы вы использовали QT вместо FLTK, вы могли бы также использовать libQGLViewer . Он имеет встроенный класс Quaternion, который спасет вас от реализации. Если у вас все еще есть выбор, я настоятельно рекомендую перейти на QT.

1 голос
/ 12 ноября 2008

Вы правы в формировании двух векторов из трех точек в двух соседних отрезках, а затем в использовании арккозина точечного произведения, чтобы получить угол между ними. Чтобы использовать этот угол, вам нужно определить ось, вокруг которой должно происходить вращение. Возьмите перекрестное произведение тех же двух векторов, чтобы получить эту ось. Затем вы можете построить матрицу преобразования , используя этот угол оси или передать ее в качестве параметров glRotate .

0 голосов
/ 08 ноября 2008

Рассматривали ли вы gluLookAt? Поместите контрольную точку в качестве точки глаза, следующую точку в качестве контрольной точки и сделайте вектор вверх перпендикулярным разнице между ними.

...