@xiaojian233
2016-08-21T16:08:13.000000Z
字数 3513
阅读 1809
项目展示
这个项目是编写一个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) 5
Turn右 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