本文共 2218 字,大约阅读时间需要 7 分钟。
到目前为止,我们建立的模型,其实都是独立的,并没有内在的关联性。通过层级建模,我们可以实现更多精彩的模型联动效果。
我们之前建立了很多模型,包括:
对于大多数图形API来说,采取最小完备的观点,即:
在OpenGL应用程序中,必须通过几何变换把图符从建模标架变换到世界标架,得到一个实例
实例变化把每个图符实例按照所需的大小,方向和位置放入到场景中:𝑴= 𝑻𝑹𝑺
这样就有了模型实例,但对象之间的关系还没建立起,还需要下面的层次建模。
层级模型其实核心就是要建立起层次树,需要确定把哪种信息放在节点上,哪种信息放在边上。一般而言,以节点代表要绘制的实例,边上存储变换矩阵。例如:
model_view = RotateY(Theta[Base] ); //支架变换矩阵base(); //绘制支架 model_view = model_view * Translate(0.0, BASE_HEIGHT, 0.0) * RotateZ(Theta[LowerArm]); //下臂变换矩阵lower_arm(); //绘制下臂 model_view = model_view * Translate(0.0, LOWER_ARM_HEIGHT, 0.0) * RotateZ(Theta[UpperArm]); //上臂变换矩阵upper_arm(); //绘制上臂
这就够了吗?看情况。如果你图元是默认的,这样就好了,但如果图元本身还有变换,则应该乘上图元本身的模型矩阵,伪代码如下:
void upper_arm(){ mat4 instance = Translate( 0.0, 0.5 * UPPER_ARM_HEIGHT, 0.0 ) * Scale(UA_WIDTH, UA_HEIGHT, UA_WIDTH ) ; //按长宽高缩放正方体,并且平移使得底面在y=0上 glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance ); //将完整的模-视矩阵传给shader glDrawArrays( GL_TRIANGLES, 0, NumVertices ); //绘制相应的三角面片}
我们直接采用树的先序遍历即可:
// modelview初始化是单位阵void paintRobot(mat4 modelview) { /* modelview = modelview*局部变换矩阵 */ /* 绘制 */ /* if (还有部位没画) { paintRobot(modelview) } */}
我们还是问一句,这够了吗?同样,还是看情况。如果你图元是默认的,这样就好了,但如果图元本身还有变换,则应该乘上图元本身的模型矩阵。但对于机器人来说,如果没设置模型矩阵,出来的效果会很奇怪。伪代码如下:
void upper_arm(){ mvstack.push( model_view ); //保存当前模-视变换矩阵 mat4 instance = Translate( 0.0, 0.5 * UPPER_ARM_HEIGHT, 0.0 ) * Scale(UA_WIDTH, UA_HEIGHT, UA_WIDTH ) ; //按长宽高缩放正方体,并且平移使得底面在y=0上 glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance ); //将完整的模-视矩阵传给shader colorCube(); // 给部件赋色 glDrawArrays( GL_TRIANGLES, 0, NumVertices ); //绘制相应的三角面片 model_view = mvstack.pop(); //恢复当前模-视变换矩阵}
转载地址:http://patg.baihongyu.com/