Ответ 1
Некоторые полезные сведения о поворотах:
- Любые три ортонормированные векторы, расположенные в виде строк, определяют преобразование в новый базис (вращение в этот базис).
- Транспонирование любого вращения является его обратным.
- Таким образом, любые три ортонормированных вектора, расположенные в виде столбцов, определяют поворот из некоторого базиса в ваш "мировой" опорный кадр.
Таким образом, задача состоит в том, чтобы найти любой набор из трех ортонормированных векторов и упорядочить их как
| x1 x2 x3 0 |
| y1 y2 y3 0 |
| z1 z2 z3 0 |
| 0 0 0 1 |
это именно то, что пытается сделать описанный вами метод, если он не работает, тогда возникает проблема с вашей реализацией.
Мы можем, очевидно, использовать ваш нормальный как (x1, y1, z1), но проблема в том, что система имеет бесконечное множество решений для остальных двух векторов (хотя знание одного из них дает вам другое, как перекрестное произведение). Следующий код должен дать устойчивый вектор, перпендикулярный (x1, y1, z1):
float normal[3] = { ... };
int imin = 0;
for(int i=0; i<3; ++i)
if(std::abs(normal[i]) < std::abs(normal[imin]))
imin = i;
float v2[3] = {0,0,0};
float dt = normal[imin];
v2[imin] = 1;
for(int i=0;i<3;i++)
v2[i] -= dt*normal[i];
Это в основном использует ортогонализацию Грэма-Шмидта с размерностью, которая уже наиболее ортогональна нормальному вектору. v3 можно затем получить, взяв поперечное произведение normal
и v2
.
Возможно, вам потребуется немного позаботиться о ротации, о происхождении, поэтому вам нужно применить перевод после вращения, а для векторов столбцов, а не для векторов строк. Если вы используете OpenGL, смотрите, что OpenGL берет массивы в основном порядке столбца (а не в строчном порядке строки), поэтому вам может понадобиться транспонировать.
Боюсь, что я не тестировал выше, я просто набил его из некоторого кода, который я написал некоторое время назад, и адаптировал его к вашей проблеме! Надеюсь, я не забыл никаких подробностей.
Изменить: я что-то забыл:)
Вышеприведенная матрица предполагает, что ваш нормаль к многоугольнику находится вдоль оси x, и у меня есть скрытое подозрение, которого не будет, все, что вам нужно сделать, это поместить "нормальный" вектор в правильный столбец вращения матрицы и v2/v3 в двух других столбцах. Итак, если нормаль к вашему многоугольнику находится вдоль оси z, то нормаль идет в третьем столбце, а v2/v3 - в первых двух столбцах.
Извините, если это вызывает путаницу.