переместить объект по пути Безье в 3d: проблема вращения - PullRequest
1 голос
/ 05 июня 2011

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

  • найти точку по Безье (вектор положения)
  • найти касательную, нормальную, бинормальную (френет кадр)
  • найтиугол между вектором тангенса и осью x
  • (то же самое для нормали и оси y, а также бинормальной оси и оси z)
  • матрица push
  • перевод в положение, поворот в углахнарисовать объект
  • pop matrix

, но все идет не так, как я ожидал: повороты кажутся случайными и не следуют кривой.какие-либо предложения?

Ответы [ 2 ]

4 голосов
/ 05 июня 2011

У вас будут проблемы с кадром Френе, потому что, к сожалению, он не определен, когда кривая даже на мгновение прямая (имеет исчезающую кривизну), и она демонстрирует дикие колебания в ориентации вокруг точек, где нормаль колеблющейся плоскости имеетзначительные изменения в направлении, особенно в точках перегиба, где нормальное переворачивание.

Я бы рекомендовал использовать то, что называется фреймом епископа (вы можете найти его в Google и узнать, как его вычислить в дискретной настройке).Его также называют параллельной транспортной рамой или рамкой минимального вращения - у него есть то преимущество, что рамка всегда определяется, и она меняет ориентацию контролируемым образом.

Я не думаю, что проблемы сКадры Frenet обязательно объясняют проблемы, с которыми вы сталкиваетесь.Вам следует начать с нескольких простых тестовых случаев - например, кривых Безье, ограниченных плоскостью XY, и переходить к вычислениям, пока не найдете, что не так.

2 голосов
/ 05 июня 2011

Вместо вычисления углов просто вставьте кадр в матрицу вида модели. Normal, Binormal и Tangent идут в верхнем левом углу матрицы 3x3, перевод в 4-м столбце и элемент 4,4 равен 1. Вместо фрейма Frenet используйте уже упомянутый фрейм Bishop. Так в коде:

// assuming you manage your curve in a (opaque) struct Bezier
struct BezierCurve;

typedef float vec3[3];

void bezierEvaluate(BezierCurve *bezier, float t, vec3 normal, vec3 binormal, vec3 tangent, vec3 pos);

void apply_bezier_transform(Bezier *bezier, float t)
{
    float M[16]; // OpenGL uses column major ordering
    // and this code is a excellent example why it does so:

   bezierEvaluate(bezier, t, &M[0], &M[4], &M[8], &M[12]);
   M[3] = M[7] = M[11] = 0.;
   M[15] = 1.;

   glMultMatrixf(M);
}
...