Преобразование углов через матрицы.

Тема в разделе "WASM.OpenGL", создана пользователем AlexBond, 21 ноя 2008.

  1. AlexBond

    AlexBond Member

    Публикаций:
    0
    Регистрация:
    30 янв 2005
    Сообщения:
    69
    Адрес:
    Belarus
    Имеется следующая система задания угла
    Код (Text):
    1.   glRotatef(Rot.Z, 0, 0, 1);//Z
    2.   glRotatef(Rot.Y, 0, 1, 0);//y
    3.   glRotatef(Rot.X, 1, 0, 0);//X
    Необходимо дабавить еще одно преобразования, и из всего этого прийти к первичной системе, найдя новые углы
    Код (Text):
    1.   glRotatef(Rot.Z, 0, 0, 1);//Z
    2.   glRotatef(Rot.Y, 0, 1, 0);//y
    3.   glRotatef(Rot.X, 1, 0, 0);//X
    4.  
    5.   glRotatef(90, 0, 0, 1);//90 + Z
    =>
    Код (Text):
    1.   glRotatef(?, 0, 0, 1);//Z
    2.   glRotatef(?, 0, 1, 0);//y
    3.   glRotatef(?, 1, 0, 0);//X
    Вопрос как это сделать?
     
  2. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Код (Text):
    1.   glRotatef(-Rot.Z, 0, 0, 1);//-90-Z
    2.   glRotatef(-Rot.Y, 0, 1, 0);//-y
    3.   glRotatef(-Rot.X, 1, 0, 0);//-X
    ?
     
  3. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    rtfm
    http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/rotate.html
     
  4. AlexBond

    AlexBond Member

    Публикаций:
    0
    Регистрация:
    30 янв 2005
    Сообщения:
    69
    Адрес:
    Belarus
    Не получится, на рисунки, желтый блок - это исходный. Красный это по предложению KeSqueer с минусами. А нужно получить зеленый блок, который вписывается в коричневую фигуру.

    [​IMG]

    Тут все сложнее чем кажется...
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Зачем мудохаться с углами, когда есть матрицы? Получаешь матрицу, получаешь обратку.
     
  6. AlexBond

    AlexBond Member

    Публикаций:
    0
    Регистрация:
    30 янв 2005
    Сообщения:
    69
    Адрес:
    Belarus
    Мне нужно получить не матрицу, а углы: Rot.X Rot.Y Rot.Z, для записи в файл, т.к. обекты храниться именно в такой системе.
    если брать матрицу glRotate
    Код (Text):
    1. ⎡  x·x·(1 - c) + c   x·y·(1 - c) - z·s  x·z·(1 - c) + y·s  0 ⎤
    2. ⎢                                                            ⎥
    3. ⎢ y·x·(1 - c) + z·s   y·y·(1 - c) + c   y·z·(1 - c) - x·s  0 ⎥
    4. ⎢                                                            ⎥
    5. ⎢ x·z·(1 - c) - y·s  y·z·(1 - c) + x·s   z·z·(1 - c) + c   0 ⎥
    6. ⎢                                                            ⎥
    7. ⎣         0                  0                  0          1 ⎦
    то
    Код (Text):
    1.   glRotatef(Rot.Z, 0, 0, 1);//Z
    2.   glRotatef(Rot.Y, 0, 1, 0);//y
    3.   glRotatef(Rot.X, 1, 0, 0);//X
    будет иметь матрицу
    Код (Text):
    1. ⎡ 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 ⎤
    2. ⎢                                                                                                                                  ⎥
    3. ⎢ 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 ⎥
    4. ⎢                                                                                                                                  ⎥
    5. ⎢     - SIN(rotY)                      SIN(rotX)·COS(rotY)                                  COS(rotX)·COS(rotY)                  0 ⎥
    6. ⎢                                                                                                                                  ⎥
    7. ⎣          0                                    0                                                    0                           1 ⎦
    а код
    Код (Text):
    1.  glRotatef(Rot.Z, 0, 0, 1);//Z
    2.   glRotatef(Rot.Y, 0, 1, 0);//y
    3.   glRotatef(Rot.X, 1, 0, 0);//X
    4.  
    5.   glRotatef(90, 0, 0, 1);//90 + Z
    матрицу:
    Код (Text):
    1. ⎡ 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 ⎤
    2. ⎢                                                                                                                                    ⎥
    3. ⎢ 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 ⎥
    4. ⎢                                                                                                                                    ⎥
    5. ⎢                 SIN(rotX)·COS(rotY)                        SIN(rotY)                        COS(rotX)·COS(rotY)                  0 ⎥
    6. ⎢                                                                                                                                    ⎥
    7. ⎣                          0                                     0                                     0                           1 ⎦
    только что это мне дает....
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Это даёт то, что перейти к первичной системе гораздо проще. Что надо сохранять в файл, тебе виднее.
     
  8. AlexBond

    AlexBond Member

    Публикаций:
    0
    Регистрация:
    30 янв 2005
    Сообщения:
    69
    Адрес:
    Belarus
    А что такое первичная система? И что нам даст Обратная матрица?

    Уточню свою задачу мне нужно достать УГЛЫ из матрицы, вопрос как это сделать?

    Решить систему из двух матриц у меня не получилось...
     
  9. AlexBond

    AlexBond Member

    Публикаций:
    0
    Регистрация:
    30 янв 2005
    Сообщения:
    69
    Адрес:
    Belarus
    ... Призывал Гугла на помощь, и нашел решение ...

    http://www.flipcode.com/documents/matrfaq.html#Q37

    Алгоритм для получения угла (X,Y,Z) из Матрицы 4x4:

    Код (Text):
    1.          |  0  1  2  3 |
    2.     M =  |  4  5  6  7 |
    3.          |  8  9 10 11 |
    4.          | 12 13 14 15 |
    5.     -----------------------------------
    6.  
    7.     angle_y = D = -asin( mat[2]);        /* Calculate Y-axis angle */
    8.     C           =  cos( angle_y );
    9.     angle_y    *= RADIANS;
    10.  
    11.     if ( fabs( C ) > 0.005 )             /* Gimball lock? */
    12.       {
    13.       trx      =  mat[10] / C;           /* No, so get X-axis angle */
    14.       try      = -mat[6]  / C;
    15.  
    16.       angle_x  = atan2( try, trx ) * RADIANS;
    17.  
    18.       trx      =  mat[0] / C;            /* Get Z-axis angle */
    19.       try      = -mat[1] / C;
    20.  
    21.       angle_z  = atan2( try, trx ) * RADIANS;
    22.       }
    23.     else                                 /* Gimball lock has occurred */
    24.       {
    25.       angle_x  = 0;                      /* Set X-axis angle to zero */
    26.  
    27.       trx      = mat[5];                 /* And calculate Z-axis angle */
    28.       try      = mat[4];
    29.  
    30.       angle_z  = atan2( try, trx ) * RADIANS;
    31.       }
    32.  
    33.     angle_x = clamp( angle_x, 0, 360 );  /* Clamp all angles to range */
    34.     angle_y = clamp( angle_y, 0, 360 );
    35.     angle_z = clamp( angle_z, 0, 360 );
    36.  
    37.     -----------------------------------
    Тема закрыта.

    P.S. как всегда сам отвечаю на свои вопросы =)
     
  10. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    AlexBond
    Дело в том, что для перехода из одной системы координат в другую, никакие углы не нужны. Например объект находится в одной мировой матрице, затем мы перемножили эту матрицу на матрицу изменения (то что делают твои углы), для обратного перехода нужно конечную матрицу умножить на обратную матрицу перехода, и всё мы получили исходную. Этим то матрицы и удобны, что в них можно накапливать изменения, а также перемножать, получать обратные и т.д. Ну а задача получения матрицы из углов, тривиальна, как впрочем и вычисление обратной.
     
  11. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Booster
    Да матрицы удобны, тем что позволяют делать не думая и не понимая, что происходит, но если повороты простые (округ одной оси), а объекты многовершинные, то через углы есно намного быстрее.
    Матричное преобразование это мощная тяжёлая операция позволяющая сразу повернуть как надо, зачем применять её два раза "вполсилы", (соответственно удваивая время поворота) если промежуточный поворт не нужно отображать? так что ТС правильно поставил задачу.
    Да и разок разобраться чтобы просто знать что делаешь никогда не повредит ;)
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Y_Mur
    Вот это лучше матрицы?
    Правильно или нет поставил ТС задачу сказать сложно, да и к тому же существует множество правильных решений. Я написал, что не нужно заниматься всей этой тягомотиной с углами, для получения первоначальной CК, когда есть более простой и общий подход.
     
  13. sarin

    sarin Member

    Публикаций:
    0
    Регистрация:
    2 июн 2005
    Сообщения:
    30
    ХЕЛП! Пишу программку. Надо рассчитать "свободный полет" камеры.

    В начале обсчетов ставлю gluLookAt( 20,0,0, 0,0,0, 0,0,1 ); Затем отрисовано 3D пространство с объектами.

    Нужно реализовать обсчет движения камеры вперёд / назад и повороты влево/вправо и вверх/вниз (на определенный угол).
    При этом надо учитывать, что при поворотах нормаль (0,0,1) [к-рая смотрит вверх отн. камеры] меняется и точка куда направлена камера (0,0,0) тоже меняется.

    Может не пользоваться gluLookAt вовсе, а юзать glRotate/glTranslate?

    И еще вопрос: координаты ламп привязаны к позиции глаза наблюдателя (20,0,0).
    Я двигаюсь по 3D поверхности и лампы тоже "плывут". Как это лучше побороть.
     
  14. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    AlexBond
    glPushMatrix/glPopMatrix и не паримся.
     
  15. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    sarin
    Надо сделать свою камеру, на основе матриц или кватернионов. В уроках nehe это описано.
     
  16. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    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]
     
  17. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    gluLookAt
    Код (Text):
    1. LookAt:
    2.     push eax
    3.     push edx
    4.     sub esp, 128
    5.     mov eax, esp
    6.     mov edx, 30
    7. @@:
    8.      mov dword [eax+edx*4-4], 0
    9.     dec edx
    10.     jnz @b
    11.     mov eax, esp
    12.     finit
    13.     fld1
    14.     mov eax, 0x80000000
    15.     fstp qword [esp+120]
    16.     fld qword [esp+180]
    17.     fsub qword [esp+156]
    18.     xor dword [esp+160], eax
    19.     fld qword [esp+172]
    20.     fsub qword [esp+148]
    21.     xor dword [esp+152], eax
    22.     fld qword [esp+164]
    23.     fsub qword [esp+140]
    24.     xor dword [esp+144], eax
    25.     call v3sNormalize
    26.     fld qword [esp+204]
    27.     fld qword [esp+196]
    28.     fld qword [esp+188]
    29.     call v3sMultiplicate
    30.     call v3sNormalize
    31.     fxch st3
    32.     fst qword [esp+16]
    33.     xor dword [esp+20], eax
    34.     fxch st2
    35.     fxch st4
    36.     fst qword [esp+48]
    37.     xor dword [esp+52], eax
    38.     fxch st1
    39.     fxch st5
    40.     fst qword [esp+80]
    41.     xor dword [esp+84], eax
    42.     fxch st2
    43.     call v3sMultiplicate
    44.     fstp qword [esp+08]
    45.     fstp qword [esp+72]
    46.     fstp qword [esp+40]
    47.     fstp qword [esp+00]
    48.     fstp qword [esp+32]
    49.     fstp qword [esp+64]
    50.     call [glLoadMatrixd], esp
    51.     add esp, 128
    52.     pop dword [esp+32]
    53.     pop dword [esp+32]
    54.     pop dword [esp+32]
    55.     call [glTranslated]
    56.     pop edx
    57.     pop eax
    58.     ret 36
    59. ; in [st0,1,2 = source]
    60. ;x_x [st6, st7]
    61. ;out [st0,1,2 = destination]
    62. v3sNormalize:
    63.     fld st0
    64.     fmul st0, st0
    65.     fld st2
    66.     fmul st0, st0
    67.     faddp st1, st0
    68.     fld st3
    69.     fmul st0, st0
    70.     faddp st1, st0
    71.     fsqrt
    72.     ftst
    73.     fstsw ax
    74.     test ah, 0x44
    75.     jpo @f
    76.     fld1
    77.     fdivrp st1, st0
    78.     fmul st3, st0
    79.     fmul st2, st0
    80.     fmulp st1, st0
    81.     ret
    82. @@:
    83.     fstp st0
    84.     ret
    85. ; in [st0,1,2 = source2, st3,4,5 = source1]
    86. ;x_x [st6, st7]
    87. ;out [st0,1,2 = destination]
    88. v3sMultiplicate:
    89.     fld st4
    90.     fmul st0, st3
    91.     fld st6
    92.     fmul st0, st3
    93.     fsubp st1, st0
    94.     fxch st1
    95.     fld st4
    96.     fmul st3, st0
    97.     fmulp st4, st0
    98.     fld st0
    99.     fmul st0, st7
    100.     fsubrp st4, st0
    101.     fmul st0, st5
    102.     fsubp st2, st0
    103.     ret
     
  18. sarin

    sarin Member

    Публикаций:
    0
    Регистрация:
    2 июн 2005
    Сообщения:
    30
    А как это будет на Си?
     
  19. destrator

    destrator New Member

    Публикаций:
    0
    Регистрация:
    20 мар 2010
    Сообщения:
    16
    Для Column Major
    Код (Text):
    1. zaxis = normal(At - Eye)
    2. xaxis = normal(cross(Up, zaxis))
    3. yaxis = cross(zaxis, xaxis)
    4.    
    5.  xaxis.x           yaxis.x           zaxis.x          0
    6.  xaxis.y           yaxis.y           zaxis.y          0
    7.  xaxis.z           yaxis.z           zaxis.z          0
    8. -dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1
    Для Row Major, соответственно, строки и столбцы меняем местами.