2017-10-12 61 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位置必须在父零件坐标系。此外,这将不适用于循环嵌套对象(循环),因为这将导致无限循环导致堆栈溢出