2017-10-12 65 views
0

我創建了一個包含它的主體和較小部件的「約7+部件」,它在不同的位置「附加」到它。我的目標是旋轉整個對象。我試圖在構造整個對象之前簡單地調用glRotatef(angle, 0, 1, 0),但我意識到這似乎是圍繞原點旋轉「一切」,無論翻譯是什麼。下面的代碼是試圖旋轉身體本身並旋轉附件。旋轉一個多部件對象

// glRotatef(angle, 0, 1, 0); //old way of rotating the object 

// body 
glPushMatrix(); 
    // movement 
    glTranslatef(subx, suby + y, subz); 
    //rotating the body itself 
    glRotatef(angle, 0, 1, 0); 
    // starting position of the body 
    glScalef(9.0, 1.75, 1.75); 
    glTranslatef(-subx, -suby, -subz); 
    glTranslatef(subx, suby, subz); 
    glutSolidSphere(1.0, 50, 50); 
glPopMatrix(); 

// attached part 
glPushMatrix(); 
    // movement 
    glTranslatef(rot1x, rot1y + y, rot1z); 
    // attempting to rotate the part while 'attached to' the body 
    glRotatef(angle, 0, 1, 0); 
    //placing the part on the object in starting position 
    glRotatef(rot1angle, rot1xrot, rot1yrot, rot1zrot); 
    glTranslatef(-rot1x, -rot1y, -rot1z); 
    glTranslatef(rot1x, rot1y, rot1z); 
    gluPartialDisk(gluNewQuadric(), 0, 1, 50, 1, 0, 100.0); 
glPopMatrix(); 

我似乎無法環繞需要什麼,以便發生爲對象的小部分與對象的身體正常轉動我的頭(一個固定的點?)。

回答

1

矩陣堆棧上的操作是基於彼此的。每個操作的參考系統是當前的轉換。如果你想轉換一個由一堆對象組成的對象,那麼你必須知道每個子對象與對象聯合體的參考位置的相對位置。然後,您必須執行以下步驟:

  • 將每個對象移動到世界上的一個公共位置(glTranslate)。
  • 定向的對象(glRotate
  • 移動每個對象的相對位置在對象工會

// dynamic position in the world 
float refPosX, refPosY, refPosZ; 

// dynamic orientation 
float angle; 

// constant positions of the sub object relative to the object union 
float subPosX[], subPosY[], subPosZ[]; 


for (int i = 0 i < noOfObj, ++i) // for each object 
{ 
    glPushMatrix(); 
    glTranslatef(refPosX, refPosY, refPosZ); 
    glRotatef(angle, 0, 1, 0); 
    glTranslatef(subPosX[i], subPosY[i], subPosZ[i]); 
    glScalef(9.0, 1.75, 1.75); 

    ..... // draw the object here 

    glPopMatrix(); 
} 


glTranslate文檔:

glTranslate親由x y z推翻譯文。當前矩陣(參見glMatrixMode)由該平移矩陣相乘,與產品替換當前矩陣,

和看到的glRotate文檔:

glRotate產生角度的旋轉而繞矢量x y z。當前矩陣(見glMatrixMode)通過與產品替換當前矩陣旋轉矩陣相乘,


注意,轉換矩陣是這樣的:

Matrix4x4 translate; 

translate[0] : (1, 0, 0, 0) 
translate[1] : (0, 1, 0, 0) 
translate[2] : (0, 0, 1, 0) 
translate[3] : (tx, ty, tz, 1) 

和周圍的旋轉矩陣Y軸是這樣的:

Matrix4x4 rotate; 
float  angle; 

rotate[0] : (cos(angle), 0, sin(angle), 0) 
rotate[1] : (0,   1, 0,   0) 
rotate[2] : (-sin(angle), 0, cos(angle), 0) 
rotate[3] : (0,   0, 0,   1) 

矩陣乘法的工作原理是這樣的:

Matrix4x4 A, B, C; 

// C = A * B 
for (int k = 0; k < 4; ++ k) 
    for (int l = 0; l < 4; ++ l) 
     C[k][l] = A[0][l] * B[k][0] + A[1][l] * B[k][1] + A[2][l] * B[k][2] + A[3][l] * B[k][3]; 


translate * rotate結果是這樣的:

model[0] : (cos(angle), 0, sin(angle), 0) 
model[1] : (0,   1, 0,   0) 
model[2] : (-sin(angle), 0, cos(angle), 0) 
model[3] : (tx,   ty, tz,   1) 

translate * rotate


注,rotate * translate結果將是:

model[0] : (cos(angle),      0, sin(angle),      0) 
model[1] : (0,        1, 0,        0) 
model[2] : (-sin(angle),     0, cos(angle),      0) 
model[3] : (cos(angle)*tx - sin(angle)*tx, ty, sin(angle)*tz + cos(angle)*tz, 1) 

rotate * translate

2
  1. 你缺少glMatrixMode電話

    如果你只使用GL_MODELVIEW比它的工作原理(如果最後設置爲活動),但是當你的代碼長得更長,並添加其他電話你可能會打破這種突然你的代碼將無法按預期工作(並且很難調試)。因此,最好在任何轉換塊代碼之前添加glMatrixMode(GL_MODELVIEW);

  2. 您是push/pop荷蘭國際集團錯誤

    你的對象嵌套這樣的矩陣也必須被嵌套。這意味着附屬於所有者部分的任何部分必須以所有者部分矩陣開始。所以你需要有一些部件的層次結構(組裝順序),以便你知道哪些部件附着在哪些部件和哪些部件上。

    所以你應該有連接到任何部分零件列表...喜歡的東西:

    List<int> part[noOfObj]; 
    

    連接到它,因此任何part[i], i=<0,noOfObj-1>有孩子的部分part[i][0,1,2...,part[i].num-1](其中num是列表的大小)。主要部分是part[0]。改變的事情了一點,但簡單的遞歸幫助:

    void part_draw(int ix) // this is just recursion call used by the main function do not use it directly 
    { 
    glMatrixMode(GL_MODELVIEW); 
    glPushMatrix(); 
    glTranslatef(subPosX[ix], subPosY[ix], subPosZ[ix]); 
    
    glPushMatrix();   // this should not be here 
    glScalef(9.0, 1.75, 1.75); // this should not be here 
    ..... // draw the object ix here 
    glMatrixMode(GL_MODELVIEW);// this should not be here 
    glPopMatrix();    // this should not be here 
    
    for (int iy=0;iy<part[ix].num,iy++) 
        part_draw(part[ix][iy]); 
    
    glMatrixMode(GL_MODELVIEW); 
    glPopMatrix(); 
    } 
    
    void mesh_draw() // this is the main rendering routine which you should use 
    { 
    glMatrixMode(GL_MODELVIEW); 
    glPushMatrix(); 
    glTranslatef(refPosX, refPosX, refPosZ); 
    glRotatef(angle, 0, 1, 0); 
    
    part_draw(0); 
    
    glMatrixMode(GL_MODELVIEW); 
    glPopMatrix(); 
    } 
    

    現在提防subPosX/Y/Z位置必須在父零件座標系。此外,這將不適用於循環嵌套對象(循環),因爲這將導致無限循環導致堆棧溢出