那么在OpenGL里面如果实现各个实体之间的相对运动呢?事实上OpenGL里面提供了这样的一对函数:glPushMatrix()和glPopMatrix()。其功能是前者把当前所有的矩阵栈都压入堆栈,后者刚好相反。先看下面的例子:
//对整个货车做运动变换A 变换A glPushMatrix(); //绘制货车主体 glPopMatrix(); glPushMatrix(); //绘制拖车主体 glPopMatrix(); |
上面代码看出来,在第一对glPushMatrix()和glPopMatrix()之间绘制的货车主体不会影响到第二对glPushMatrix()和glPopMatrix()里面绘制的拖车主体,也就是说,平行的两对glPushMatrix()和glPopMatrix()互相不影响。但是变换A却可以影响货车主体和拖车主体,因为它们是上下级的关系,而不是平行的关系。
所以从上面的分析中可以看出,可以利用glPushMatrix()和glPopMatrix()来实现主体和子体之间的相对运动,而且子体之间的绘制也不会相互影响,基于这样的思想,可以编制如下代码:(这里只列出主体代码DrawLorry和DrawWheel)
//m_rot 和m_trans分别表示轮胎的旋转量和整个货车在X轴上的平移量,已经在有关//函数里面进行了初始化 void CTerraintestView::DrawLorry() {//控制货车的运动 //这里施加的几何变换将影响到所有的下面绘制的物体 glTranslatef(m_trans,0,0); glColor3f(1.0,0.5,0); //绘制货车 glBegin(GL_POLYGON ); glVertex2f(-0.3f,0.2f); glVertex2f(-0.3f,-0.2f); glVertex2f(0.3f,-0.2f); glVertex2f(0.3f,0.2f); glEnd(); //绘制拉绳 glBegin(GL_LINES ); glVertex2f(-0.3,0); glVertex2f(-0.6,0); glEnd(); //绘制货车轮胎 glPushMatrix(); glTranslatef(0,-0.3f,0); glTranslatef(-0.2,0,0); glPushMatrix(); glRotatef(m_rot,0,0,1); DrawWheel(0.1); glPopMatrix(); glTranslatef(0.4,0,0); glRotatef(m_rot,0,0,1); DrawWheel(0.1); glPopMatrix(); glPushMatrix(); //总比货车滞后0.3 glTranslatef(-0.6,0,0); //绘制后面的拖车 glBegin(GL_POLYGON); glVertex2f(-0.2f,0.2f); glVertex2f(-0.2f,-0.2f); glVertex2f(0.2f,-0.2f); glVertex2f(0.2f,0.2f); glEnd(); //绘制拖车的轮胎 glPushMatrix(); glTranslatef(0,-0.3f,0); glTranslatef(-0.1,0,0); DrawWheel(0.1); glTranslatef(0.2,0,0); DrawWheel(0.1); glPopMatrix(); glPopMatrix(); } void CTerraintestView::DrawWheel(float radius) {//绘制轮胎 float step=0.05; float i; float x,y; glBegin(GL_LINE_STRIP ); glVertex2f(radius,0); for (i=step;i<360.0;i+=step) { //计算两个坐标 x=radius*cos(i*3.1415926/180.0); y=radius*sin(i*3.1415926/180.0); glVertex2f(x,y); } glEnd(); }
|
3.小结:
前面的分析看出,无论是对复杂的场景还是对多DOFs(自由度的简称)的物体来说,使用分解的方式将复杂物体分解为相对独立的子实体(对于更加复杂的场景需要建立场景的层次树),并结合glPushMatrix()和glPopMatrix()来实现对各个子实体的绘制,进而实现整个3D物体的绘制工作。这种思路对于大型的复杂场景的绘制尤为有用。
|