旋转多部分对象

时间:2017-10-12 23:05:55

标签: opengl 3d rotation coordinate-transformation

我创造了一个物体,它有大约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();

为了让对象的较小部分与对象的主体(固定点?)正确旋转,我似乎无法绕过需要发生的事情。谢谢你的帮助。

2 个答案:

答案 0 :(得分: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

    现在提防 @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); if (convertView == null) { convertView = mInflater.inflate(R.layout.list_item, null); holder = new ViewHolder(); holder.Name = (TextView) convertView.findViewById(R.id.Recipe_Name); holder.Image_Block = (ImageView) convertView.findViewById(R.id.Recipe_Image); holder.Text_Recipe = (TextView) convertView.findViewById(R.id.Recipe_Text); holder.Text_Rarity = (TextView) convertView.findViewById(R.id.Recipe_Rarity); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } RowItem row_pos = rowItems.get(position); holder.Image_Block.setImageResource(row_pos.getImage_Block()); holder.Name.setText(row_pos.getName()); holder.Text_Recipe.setText(row_pos.getText_Recipe()); holder.Text_Rarity.setText(row_pos.getText_Rarity()); return convertView; } 位置必须位于父部件坐标系中。此外,这不适用于循环嵌套对象(循环),因为这会导致无限循环导致堆栈溢出

答案 1 :(得分: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的文档:

  

glTranslatex 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