@xiaojian233
2016-08-21T08:08:13.000000Z
字数 3513
阅读 2035
项目展示
这个项目是编写一个3D 的模型渲染程序,然后在程序里面看效果。
模型文件是obj 格式的,可以在3DMAX 和Maya 中导出这种格式。
除了渲染外,还可以定义动作链。
这个什么意思呢?
就是说,我想要让模型动起来,比如,汽车开动。
汽车开动的时候,车身需要位移,同时,车轮还要自转。
这一整个过程,我称之为动作链。
彼时还没有学《游戏引擎架构分析》,并不懂得如何用更好的数据结构去组织。
最后我使用了线性表的数据结构。这是个坑。现在看来,当年的选择实在太愚蠢了。
不过好歹,还是实现了想要的功能。
在构思这个项目的时候,需要回答几个问题:
一个好的设计应该是数据和代码分离的。上面的几个问题都属于数据,那最好的方法,就是把它们分离出来,不和程序相关。
这个时候,我就想到了脚本。
或者说,叫配置文件更恰当吧。
下面为了统一起见,模块名为脚本系统。
程序默认读入一个配置文件,在里面定义了各种各样的参数,然后程序解释,输出。
主要定义的数据,如下。
首先定义了纹理。
纹理主要为它分配了纹理ID 和 纹理图像的路径。
示例如下:
texture 黑色质感{name: "tex/黑色质感.bmp"}texture 车身纹理{name: "tex/车身纹理-24.bmp"}texture cover{name: "Obj/伞部件obj/cover.bmp"}
texture 指定这是个纹理,后面跟着的是纹理的ID,name 制定的纹理的路径。
材质系数的作用是根据Phong 着色模型定义的,主要是RGB 三个分量的影响。
Phong 着色模型这里就不讨论了。
material 车身{ambient:(0.5, 0.5, 0.5, 1.0)diffuse:(1.0, 1.0, 1.0, 1.0)specular:(1.0, 1.0, 1.0, 1.0)shininess: 100.0}
模型的定义由obj 指定
其中texId 就是指上面定义的纹理ID。
matID 就是指上面定义的材质系数ID。
//---------------------------------------车站obj 车站_logo{name: "Obj/Station/车站_logo.obj"texId: 绿色纹理matId: 车身}//---------------------------------------公交车obj 车身{name: "Obj/busV2/车身.obj"texId: 车身纹理matId: 车身}
项目中车站的建模如下:
*注:并没有纹理
动作链的定义分为两部分。
首先定义了动作单元(actionunit), 主要是定义各种刚体的运动,如平移,旋转等。
动作单元还可以互相组合。
语法是:
ID + 动作关键字 + 参数
actionunit{车前进 Translate: ( 0.000672837, -0.00179407 , 1.18088 ) true车后退 Translate: ( -0.000672837, 0.00179407 , -1.18088 ) true前左前转 Rotate: ( 21.972, -2.243, 49.37, 1 ) ( 5.257, 0, 0 ) 5前右前转 Rotate: ( -47.378, -2.206, 49.329, 1 ) ( 5.232, 0, 0 ) 5后左前转 Rotate: ( 22.337, -2.243, -83.627, 1 ) ( 5.244, 0.0369999, -0.0419998 ) 5后右前转 Rotate: ( -47.38, -2.099, -84.061, 1 ) ( 5.257, 0, 0 ) 5前左后转 Rotate: ( 21.972, -2.243, 49.37, 1 ) ( -5.257, 0, 0 ) 5前右后转 Rotate: ( -47.378, -2.206, 49.329, 1 ) ( -5.232, 0, 0 ) 5后左后转 Rotate: ( 22.337, -2.243, -83.627, 1 ) ( -5.244, -0.0369999, 0.0419998 ) 5后右后转 Rotate: ( -47.38, -2.099, -84.061, 1 ) ( -5.257, 0, 0 ) 5右转弯 Rotate:( -50.389, 64.974, -38.018, 1 ) (0, -1, 0) 5 true左转弯 Rotate:( 33.768, 64.974, -38.018, 1) (0, 1 , 0) 5 true_turn右转弯平移 Translate: ( 0.000672837, -0.00179407 , 1.18088 )//_turn右转弯旋转 Rotate:_turn车前进旋转 Rotate:(0, 0, 0, 1) (0, -1, 0) 5_turn车前进旋转左 Rotate:(0, 0, 0, 1) (0, 1, 0) 5Turn右 Turn: 车前进 _turn车前进旋转Turn右转弯平移 Turn: 右转弯 _turn右转弯平移Turn左 Turn: 车前进 _turn车前进旋转左Turn左转弯平移 Turn: 左转弯 _turn右转弯平移//------------------------可以旋转的雨伞雨伞顺时针 Rotate:( -141.874, -3.344, -355.445, 1 ) ( -46.064, -46.909, 0.367981 ) 5雨伞中心 Rotate: (-151.241, -10.379, -355.515, 1.0) (0, 1, 0) 5 true雨伞逆时针 Rotate:( -141.874, -3.344, -355.445, 1 ) ( 46.064, 46.909, -0.367981 ) 5雨伞逆中心 Rotate: (-151.241, -10.379, -355.515, 1.0) (0, -1, 0) 5 true}
定义完动作单元后,就可以定义动作了。
action 指定这是个动作链,后面是模型ID,指定这个动作链绑定到哪个模型上。
跟着的是一个启动的动作单元ID(如车前进)和触发键(如t)。
然后大括号下跟着触发的动作单元,由模型ID 和动作单元ID 指定。
公交车的动作链定义如下:
action 车身{车前进 t{玻璃面 车前进倒后镜 车前进前挡风玻璃 车前进轮胎前左 车前进轮胎前右 车前进轮胎后左 车前进轮胎后右 车前进车毂前左 车前进车毂前右 车前进车毂后左 车前进车毂后右 车前进车毂前左 前左前转轮胎前左 前左前转车毂前右 前右前转轮胎前右 前右前转车毂后左 后左前转轮胎后左 后左前转车毂后右 后右前转轮胎后右 后右前转车身 Turn右转弯平移车身 Turn左转弯平移}车后退 T{玻璃面 车后退倒后镜 车后退前挡风玻璃 车后退轮胎前左 车后退轮胎前右 车后退轮胎后左 车后退轮胎后右 车后退车毂前左 车后退车毂前右 车后退车毂后左 车后退车毂后右 车后退车毂前左 前左后转轮胎前左 前左后转车毂前右 前右后转轮胎前右 前右后转车毂后左 后左后转轮胎后左 后左后转车毂后右 后右后转轮胎后右 后右后转}右转弯 r{车身 Turn右玻璃面 右转弯倒后镜 右转弯前挡风玻璃 右转弯轮胎前左 右转弯轮胎前右 右转弯轮胎后左 右转弯轮胎后右 右转弯车毂前左 右转弯车毂前右 右转弯车毂后左 右转弯车毂后右 右转弯车身 车前进玻璃面 车前进倒后镜 车前进前挡风玻璃 车前进轮胎前左 车前进轮胎前右 车前进轮胎后左 车前进轮胎后右 车前进车毂前左 车前进车毂前右 车前进车毂后左 车前进车毂后右 车前进车毂前左 前左前转轮胎前左 前左前转车毂前右 前右前转轮胎前右 前右前转车毂后左 后左前转轮胎后左 后左前转车毂后右 后右前转轮胎后右 后右前转车身 Turn右转弯平移}左转弯 l{车身 Turn左玻璃面 左转弯倒后镜 左转弯前挡风玻璃 左转弯轮胎前左 左转弯轮胎前右 左转弯轮胎后左 左转弯轮胎后右 左转弯车毂前左 左转弯车毂前右 左转弯车毂后左 左转弯车毂后右 左转弯车身 车前进玻璃面 车前进倒后镜 车前进前挡风玻璃 车前进轮胎前左 车前进轮胎前右 车前进轮胎后左 车前进轮胎后右 车前进车毂前左 车前进车毂前右 车前进车毂后左 车前进车毂后右 车前进车毂前左 前左前转轮胎前左 前左前转车毂前右 前右前转轮胎前右 前右前转车毂后左 后左前转轮胎后左 后左前转车毂后右 后右前转轮胎后右 后右前转车身 Turn左转弯平移}}
公交车的模型如下:
而动起来的公交车如下:
注释支持 //, 上面也有看到了。
光的着色模型使用了经典的Phong 着色模型。
基于OpenGL 去实现,Shader 使用了GLSL。
顶点着色器如下:
片元着色器如下:
如今看来,这个项目实在是稚嫩。
晦涩难懂的脚本设置,不够直观,没能做到所见即所得的效果。
但是每一次写代码都能够给自己带来进步,每次都会反思自己在项目中的表现。
期待自己更好吧~
END,感谢阅读。
Email : li.xiaojian233@qq.com