Я тут OpenGL-евскую модельно-видовую матрицу поизучал. Для начала, как её получить. С помощью функций glGet:
float M[16];
glGetFloatv(GL_MODELVIEW_MATRIX,M);
или
double M[16];
glGetDoublev(GL_MODELVIEW_MATRIX,M);
Сохранена матрица по столбцам:
И вот, что она из себя представляет (т.е. "что каждый из элементов значит"):
Здесь, i,j,k - базисные (направляющие) векторы текущей системы координат, t-вектор переноса (положение текущей системы координат?). Модельно-видовая матрица содержит их координаты в мировой системе координат (не в системе координат наблюдателя).
Это были мои умозаключения. Надеюсь, верные. И вот ещё, насчёт того, как матрица работает. Координаты вершины/нормали (V[4]) в виде матрицы 1х4 умножаются на эту матрицу так:
Умножаются матрицы по правилу "строку-на-столбец". В результате получается вектор (R[4]) с координатами:
R[0] = M[0]*V[0] + M[4]*V[1] + M[8]*V[2] + M[12]*V[3];
R[1] = M[1]*V[0] + M[5]*V[1] + M[9]*V[2] + M[13]*V[3];
R[2] = M[2]*V[0] + M[6]*V[1] + M[10]*V[2] + M[14]*V[3];
R[3] = M[3]*V[0] + M[7]*V[1] + M[11]*V[2] + M[15]*V[3];
Добавлено (03 Сен 2009, 05:05)
---------------------------------------------
Так вот к чему это я с матрицами вылез: понадобилось мне это для анимации моделей и, также, пригодится для работы с камерами на сцене. Лучше на примере камер поясню. В редакторе локации Варкрафта (не знаю, как в Меховском, но насчёт Вариковского я уверен на 100%) можно ставить несколько камер на сцене, и потом в сценарии прописывать "перейти к камере такой-то за такое-то время". И камера плавно перемещается и плавно поворачивается из любой точки карты ориентируясь в конечном итоге заданным образом. Камеры ставятся в редакторе просто: ориентировался как желаешь, чтоб камера смотрела - клик мышки - и камера создана. Т.е. в файл локации сохраняется ориентация камеры, а затем в процессе игры, когда камера может находится где угодно, в реал-тайме вычисляется вектор поворота, угол поворота, смещение и просчитывается анимация.
Короче говоря, задача выглядит так: есть два значения ориентации системы координат, выражающихся в значениях модельно-видовой матрицы в начале и в конце анимации, и нужно осуществить плавную анимацию для перехода от одной системы (==матрицы) к другой. Опытным путём (верчением карандашей в воздухе и извилин в голове ) я выяснил, что такой переход можно осуществить с помощью всего одного поворота (glRotate) и одного переноса (glTranslate). Плавность анимации достигается путём линейного изменения угла поворота и масштабирования вектора переноса.
Пусть M1[16] - значение модельновидовой матрицы в начале анимации, M2[16] - её значение в конце; полное время анимации - TimeFull, а время, прошедшее с начала анимации - TimeNow. Тогда текущее значение модельновидовой матрицы может быть получено в результате прогона следующего алгоритма:
1) Находим вектор поворота (ось вращения Rot[3]):
double Rot[3];
Rot[0] = M2[4]*M1[8] - M2[8]*M1[4] + M2[5]*M1[9] - M2[9]*M1[5] + M2[6]*M1[10] - M2[10]*M1[6];
Rot[1] = M2[8]*M1[0] - M2[0]*M1[8] + M2[9]*M1[1] - M2[1]*M1[9] + M2[10]*M1[2] - M2[2]*M1[10];
Rot[2] = M2[0]*M1[4] - M2[4]*M1[0] + M2[1]*M1[5] - M2[5]*M1[1] + M2[2]*M1[6] - M2[6]*M1[2];
К сожалению, он будет не единичной длины, но это не важно, ибо при вызове glRotate вектор поворота всё равно нормируется.
2) Находим полное значение угла поворота (Angle):
double CosAngle = (M1[0]*M2[0]+M1[1]*M2[1]+M1[2]*M2[2]+
M1[4]*M2[4]+M1[5]*M2[5]+M1[6]*M2[6]+
M1[8]*M2[8]+M1[9]*M2[9]+M1[10]*M2[10]-1) / 2.0;
double Angle = 0.0;
if(CosAngle<1.0)Angle = acos(CosAngle)*57.295779513082320876798154814105;
Тут проверка значения косинуса нужна лишь из-за погрешностей плавающей запятой. Просто CosAngle может в седьмом знаке нагрешить и вылезти чуть-чуть за 1 при нулевом угле поворота, и тогда функция acos навернётся.
3) Находим полный вектор переноса (Trans[3]):
Trans[0] = M2[12] - M1[12];
Trans[1] = M2[13] - M1[13];
Trans[2] = M2[14] - M1[14];
4) Находим процент выполнения анимации:
double AniPos = TimeNow / TimeFull;
5) Анимируем модель:
glLoadMatrixd(M1); //Переходим в систему координат детали в начале анимации
glRotated(Angle*AniPos, Rot[0],Rot[1],Rot[2]); //Поворачиваемся на часть угла, соответствующую проценту прохождения анимационной дорожки
glTranslated(Trans[0]*AniPos, Trans[1]*AniPos, Trans[2]*AniPos); //Смещаемся частично, соответственно проценту прохождения анимационной дорожки
В отличие от анимации камеры, анимацию моделей (вектор поворота, угол поворота, вектор переноса) можно просчитать заранее и хранить в файле моделей лишь готовые зачения.
Вот такую вот фигень я вывел, мдям...