Несколько полезных вещей о вращениях:
- Любые три ортонормированных вектора, расположенных в виде строк, определяют преобразование в новый базис (поворот в этот базис).
- Транспонирование любого вращения - его обратное.
- Таким образом, любые три ортонормированных вектора, расположенных в виде столбцов, определяют поворот из некоторого базиса в вашу "мировую" систему отсчета.
Итак, проблема в том, чтобы найти любой набор из трех ортонормированных векторов и расположить их как
| 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 принимает массивы в главном порядке столбцов (а не в главном порядке строк C), поэтому вам может понадобиться транспонировать.
Боюсь, я не проверял вышеизложенное, я просто набрал его из некоторого кода, который я написал некоторое время назад, и адаптировал его к вашей проблеме! Надеюсь, я не забыл ни одной детали.
Редактировать: я что-то забыл :)
В приведенной выше матрице предполагается, что ваша нормаль к многоугольнику расположена вдоль оси x, и у меня есть подозрение, что этого не произойдет, все, что вам нужно сделать, это поместить вектор «нормали» в правильный столбец вращения матрица, и v2 / v3 в двух других столбцах. Таким образом, если нормаль к вашему многоугольнику находится вдоль оси z, то нормаль идет в 3-й столбец, а v2 / v3 - в первые два столбца.
Извините, если это вызывает путаницу.