本文共 1843 字,大约阅读时间需要 6 分钟。
我们建立的模型都是独立的,没有内在关联性。通过层级建模,我们可以实现模型之间的联动效果。之前我们建立了许多模型,包括几何对象模型、材质模型、光源模型以及虚拟照相机模型。
对于大多数图形API来说,最小完备的观点是:只包含少数的基本图元,让用户通过这些基本图元构建更复杂的对象。这些基本图元被称为图符。在OpenGL应用程序中,必须通过几何变换将图符从建模标架变换到世界标架,得到一个实例。实例变换将每个图符实例按照所需的大小、方向和位置放入场景中:𝑴= 𝑻𝑹𝑺
层级模型的核心是建立层次树,确定哪种信息放在节点上,哪种信息放在边上。以机械臂为例,我们有三个模型对象:支架、下臂和上臂。它们的运动自由度如下:
伪代码如下:
model_view = RotateY(Theta[Base]); // 支架变换矩阵model_view = model_view * Translate(0.0, BASE_HEIGHT, 0.0) * RotateZ(Theta[LowerArm]); // 下臂变换矩阵model_view = model_view * Translate(0.0, LOWER_ARM_HEIGHT, 0.0) * RotateZ(Theta[UpperArm]); // 上臂变换矩阵
如果图元本身还有变换,需要乘上图元本身的模型矩阵。伪代码如下:
void upper_arm() { mat4 instance = Translate(0.0, 0.5 * UPPER_ARM_HEIGHT, 0.0) * Scale(UA_WIDTH, UA_HEIGHT, UA_WIDTH); glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance); colorCube(); glDrawArrays(GL_TRIANGLES, 0, NumVertices); model_view = mvstack.pop();} 我们采用树的先序遍历。以史蒂夫为例,其层次树为:
paintRobot 函数用于绘制机器人。paintRobot 函数。伪代码如下:
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); glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance); colorCube(); glDrawArrays(GL_TRIANGLES, 0, NumVertices); model_view = mvstack.pop();} 转载地址:http://patg.baihongyu.com/