主程序
md2文件操作完成。现在看main.cpp.
const float FLOOR_TEXTURE_SIZE = 15.0f; //The size of each floor "tile"
这是每个地板上方格的大小,也就是你在截图上看到的每层图像的copy.
float _angle = 30.0f;
MD2Model* _model;
int _textureId;
//The forward position of the guy relative to an arbitrary floor "tile"
float _guyPos = 0;
这是一些存储摄像机角度的变量,MD2Model的物体,层纹理的id,和人物走的距离模上地板的大小。
void initRendering() {
//...
//Load the model
_model = MD2Model::load("tallguy.md2");
if (_model != NULL) {
_model->setAnimation("run");
}
//Load the floor texture
Image* image = loadBMP("vtr.bmp");
_textureId = loadTexture(image);
delete image;
}
在我们initRendering函数中,我们加载模型和地板纹理。
void drawScene() {
//...
//Draw the guy
if (_model != NULL) {
glPushMatrix();
glTranslatef(0.0f, 4.5f, 0.0f);
glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
glScalef(0.5f, 0.5f, 0.5f);
_model->draw();
glPopMatrix();
}
这里我们绘制人物。我们需要变换,旋转,伸缩以使得人物大小合适,在合适的位置并朝着正确的方向。我找出了令人头疼的合适的变换和伸缩系数。合适的数值决定于我在Blender中创建的模型时设置的真实顶点位置。
//Draw the floor
glTranslatef(0.0f, -5.4f, 0.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBegin(GL_QUADS);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(2000 / FLOOR_TEXTURE_SIZE, _guyPos / FLOOR_TEXTURE_SIZE);
glVertex3f(-1000.0f, 0.0f, -1000.0f);
glTexCoord2f(2000 / FLOOR_TEXTURE_SIZE,
(2000 + _guyPos) / FLOOR_TEXTURE_SIZE);
glVertex3f(-1000.0f, 0.0f, 1000.0f);
glTexCoord2f(0.0f, (2000 + _guyPos) / FLOOR_TEXTURE_SIZE);
glVertex3f(1000.0f, 0.0f, 1000.0f);
glTexCoord2f(0.0f, _guyPos / FLOOR_TEXTURE_SIZE);
glVertex3f(1000.0f, 0.0f, -1000.0f);
glEnd();
//...
}
现在绘制地板。地板只是一个四处延伸到很远的四边形。为了使人物向前走,我们设置纹理坐标使得地板砖向合适的方向移动。
void update(int value) {
_angle += 0.7f;
if (_angle > 360) {
_angle -= 360;
}
//Advance the animation
if (_model != NULL) {
_model->advance(0.025f);
}
//Update _guyPos
_guyPos += 0.08f;
while (_guyPos > FLOOR_TEXTURE_SIZE) {
_guyPos -= FLOOR_TEXTURE_SIZE;
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
这是update函数。我们只增加镜头的角度和人物的位置,并调用MD2Model对象中的advance函数。我计算出_guyPos变量的增量。
所有这些,可以让一个3D人物行走啦!
练习:
- 改变MD2Model类中的advance函数,使得dt允许为负。然后通过动画后退和地板图片向前而不是向后滚动让人物向走行走。
- 让draw只画出单独的帧,而不进行插值。人物的动作应该不连贯了。即使只有很少的帧,通过插值也会使动作看起来流畅和连贯。
- 实现当用户按下空格键(key == ' '),人物禁止不动(不是镜头),然后用户再次按下空格,人物由开始移动。