Имеется следующая система задания угла Код (Text): glRotatef(Rot.Z, 0, 0, 1);//Z glRotatef(Rot.Y, 0, 1, 0);//y glRotatef(Rot.X, 1, 0, 0);//X Необходимо дабавить еще одно преобразования, и из всего этого прийти к первичной системе, найдя новые углы Код (Text): glRotatef(Rot.Z, 0, 0, 1);//Z glRotatef(Rot.Y, 0, 1, 0);//y glRotatef(Rot.X, 1, 0, 0);//X glRotatef(90, 0, 0, 1);//90 + Z => Код (Text): glRotatef(?, 0, 0, 1);//Z glRotatef(?, 0, 1, 0);//y glRotatef(?, 1, 0, 0);//X Вопрос как это сделать?
Код (Text): glRotatef(-Rot.Z, 0, 0, 1);//-90-Z glRotatef(-Rot.Y, 0, 1, 0);//-y glRotatef(-Rot.X, 1, 0, 0);//-X ?
Не получится, на рисунки, желтый блок - это исходный. Красный это по предложению KeSqueer с минусами. А нужно получить зеленый блок, который вписывается в коричневую фигуру. Тут все сложнее чем кажется...
Мне нужно получить не матрицу, а углы: Rot.X Rot.Y Rot.Z, для записи в файл, т.к. обекты храниться именно в такой системе. если брать матрицу glRotate Код (Text): ⎡ x·x·(1 - c) + c x·y·(1 - c) - z·s x·z·(1 - c) + y·s 0 ⎤ ⎢ ⎥ ⎢ y·x·(1 - c) + z·s y·y·(1 - c) + c y·z·(1 - c) - x·s 0 ⎥ ⎢ ⎥ ⎢ x·z·(1 - c) - y·s y·z·(1 - c) + x·s z·z·(1 - c) + c 0 ⎥ ⎢ ⎥ ⎣ 0 0 0 1 ⎦ то Код (Text): glRotatef(Rot.Z, 0, 0, 1);//Z glRotatef(Rot.Y, 0, 1, 0);//y glRotatef(Rot.X, 1, 0, 0);//X будет иметь матрицу Код (Text): ⎡ COS(rotY)·COS(rotZ) SIN(rotX)·SIN(rotY)·COS(rotZ) - COS(rotX)·SIN(rotZ) COS(rotX)·SIN(rotY)·COS(rotZ) + SIN(rotX)·SIN(rotZ) 0 ⎤ ⎢ ⎥ ⎢ COS(rotY)·SIN(rotZ) COS(rotX)·COS(rotZ) + SIN(rotX)·SIN(rotY)·SIN(rotZ) COS(rotX)·SIN(rotY)·SIN(rotZ) - SIN(rotX)·COS(rotZ) 0 ⎥ ⎢ ⎥ ⎢ - SIN(rotY) SIN(rotX)·COS(rotY) COS(rotX)·COS(rotY) 0 ⎥ ⎢ ⎥ ⎣ 0 0 0 1 ⎦ а код Код (Text): glRotatef(Rot.Z, 0, 0, 1);//Z glRotatef(Rot.Y, 0, 1, 0);//y glRotatef(Rot.X, 1, 0, 0);//X glRotatef(90, 0, 0, 1);//90 + Z матрицу: Код (Text): ⎡ SIN(rotX)·SIN(rotY)·COS(rotZ) - COS(rotX)·SIN(rotZ) - COS(rotY)·COS(rotZ) COS(rotX)·SIN(rotY)·COS(rotZ) + SIN(rotX)·SIN(rotZ) 0 ⎤ ⎢ ⎥ ⎢ COS(rotX)·COS(rotZ) + SIN(rotX)·SIN(rotY)·SIN(rotZ) - COS(rotY)·SIN(rotZ) COS(rotX)·SIN(rotY)·SIN(rotZ) - SIN(rotX)·COS(rotZ) 0 ⎥ ⎢ ⎥ ⎢ SIN(rotX)·COS(rotY) SIN(rotY) COS(rotX)·COS(rotY) 0 ⎥ ⎢ ⎥ ⎣ 0 0 0 1 ⎦ только что это мне дает....
А что такое первичная система? И что нам даст Обратная матрица? Уточню свою задачу мне нужно достать УГЛЫ из матрицы, вопрос как это сделать? Решить систему из двух матриц у меня не получилось...
... Призывал Гугла на помощь, и нашел решение ... http://www.flipcode.com/documents/matrfaq.html#Q37 Алгоритм для получения угла (X,Y,Z) из Матрицы 4x4: Код (Text): | 0 1 2 3 | M = | 4 5 6 7 | | 8 9 10 11 | | 12 13 14 15 | ----------------------------------- angle_y = D = -asin( mat[2]); /* Calculate Y-axis angle */ C = cos( angle_y ); angle_y *= RADIANS; if ( fabs( C ) > 0.005 ) /* Gimball lock? */ { trx = mat[10] / C; /* No, so get X-axis angle */ try = -mat[6] / C; angle_x = atan2( try, trx ) * RADIANS; trx = mat[0] / C; /* Get Z-axis angle */ try = -mat[1] / C; angle_z = atan2( try, trx ) * RADIANS; } else /* Gimball lock has occurred */ { angle_x = 0; /* Set X-axis angle to zero */ trx = mat[5]; /* And calculate Z-axis angle */ try = mat[4]; angle_z = atan2( try, trx ) * RADIANS; } angle_x = clamp( angle_x, 0, 360 ); /* Clamp all angles to range */ angle_y = clamp( angle_y, 0, 360 ); angle_z = clamp( angle_z, 0, 360 ); ----------------------------------- Тема закрыта. P.S. как всегда сам отвечаю на свои вопросы =)
AlexBond Дело в том, что для перехода из одной системы координат в другую, никакие углы не нужны. Например объект находится в одной мировой матрице, затем мы перемножили эту матрицу на матрицу изменения (то что делают твои углы), для обратного перехода нужно конечную матрицу умножить на обратную матрицу перехода, и всё мы получили исходную. Этим то матрицы и удобны, что в них можно накапливать изменения, а также перемножать, получать обратные и т.д. Ну а задача получения матрицы из углов, тривиальна, как впрочем и вычисление обратной.
Booster Да матрицы удобны, тем что позволяют делать не думая и не понимая, что происходит, но если повороты простые (округ одной оси), а объекты многовершинные, то через углы есно намного быстрее. Матричное преобразование это мощная тяжёлая операция позволяющая сразу повернуть как надо, зачем применять её два раза "вполсилы", (соответственно удваивая время поворота) если промежуточный поворт не нужно отображать? так что ТС правильно поставил задачу. Да и разок разобраться чтобы просто знать что делаешь никогда не повредит
Y_Mur Вот это лучше матрицы? Правильно или нет поставил ТС задачу сказать сложно, да и к тому же существует множество правильных решений. Я написал, что не нужно заниматься всей этой тягомотиной с углами, для получения первоначальной CК, когда есть более простой и общий подход.
ХЕЛП! Пишу программку. Надо рассчитать "свободный полет" камеры. В начале обсчетов ставлю gluLookAt( 20,0,0, 0,0,0, 0,0,1 ); Затем отрисовано 3D пространство с объектами. Нужно реализовать обсчет движения камеры вперёд / назад и повороты влево/вправо и вверх/вниз (на определенный угол). При этом надо учитывать, что при поворотах нормаль (0,0,1) [к-рая смотрит вверх отн. камеры] меняется и точка куда направлена камера (0,0,0) тоже меняется. Может не пользоваться gluLookAt вовсе, а юзать glRotate/glTranslate? И еще вопрос: координаты ламп привязаны к позиции глаза наблюдателя (20,0,0). Я двигаюсь по 3D поверхности и лампы тоже "плывут". Как это лучше побороть.
gluLookAt(pos.x, pos.y, pos.z, pos.x+cos(ang.v)*sin(ang.h), pos.y+sin(ang.v), pos.z+cos(ang.v)*cos(ang.h), 0, 0, 1); в самом простом случае, когда не надо менять up. изменяя pos.x, pos.y, pos.z можно перемещаться [-∞..+∞, -∞..+∞, -∞..+∞, ну или около того ±∞/2], изменяя ang.h можно поворачиваться в горизонтальной плоскости [-180..180], а изменяя ang.v можно поворачиваться в вертикальной плоскости [-90..90]
gluLookAt Код (Text): LookAt: push eax push edx sub esp, 128 mov eax, esp mov edx, 30 @@: mov dword [eax+edx*4-4], 0 dec edx jnz @b mov eax, esp finit fld1 mov eax, 0x80000000 fstp qword [esp+120] fld qword [esp+180] fsub qword [esp+156] xor dword [esp+160], eax fld qword [esp+172] fsub qword [esp+148] xor dword [esp+152], eax fld qword [esp+164] fsub qword [esp+140] xor dword [esp+144], eax call v3sNormalize fld qword [esp+204] fld qword [esp+196] fld qword [esp+188] call v3sMultiplicate call v3sNormalize fxch st3 fst qword [esp+16] xor dword [esp+20], eax fxch st2 fxch st4 fst qword [esp+48] xor dword [esp+52], eax fxch st1 fxch st5 fst qword [esp+80] xor dword [esp+84], eax fxch st2 call v3sMultiplicate fstp qword [esp+08] fstp qword [esp+72] fstp qword [esp+40] fstp qword [esp+00] fstp qword [esp+32] fstp qword [esp+64] call [glLoadMatrixd], esp add esp, 128 pop dword [esp+32] pop dword [esp+32] pop dword [esp+32] call [glTranslated] pop edx pop eax ret 36 ; in [st0,1,2 = source] ;x_x [st6, st7] ;out [st0,1,2 = destination] v3sNormalize: fld st0 fmul st0, st0 fld st2 fmul st0, st0 faddp st1, st0 fld st3 fmul st0, st0 faddp st1, st0 fsqrt ftst fstsw ax test ah, 0x44 jpo @f fld1 fdivrp st1, st0 fmul st3, st0 fmul st2, st0 fmulp st1, st0 ret @@: fstp st0 ret ; in [st0,1,2 = source2, st3,4,5 = source1] ;x_x [st6, st7] ;out [st0,1,2 = destination] v3sMultiplicate: fld st4 fmul st0, st3 fld st6 fmul st0, st3 fsubp st1, st0 fxch st1 fld st4 fmul st3, st0 fmulp st4, st0 fld st0 fmul st0, st7 fsubrp st4, st0 fmul st0, st5 fsubp st2, st0 ret
Для Column Major Код (Text): zaxis = normal(At - Eye) xaxis = normal(cross(Up, zaxis)) yaxis = cross(zaxis, xaxis) xaxis.x yaxis.x zaxis.x 0 xaxis.y yaxis.y zaxis.y 0 xaxis.z yaxis.z zaxis.z 0 -dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1 Для Row Major, соответственно, строки и столбцы меняем местами.