Blog好久没有更新了,Alchemy3D的MD2导入已经完美完成,给大家介绍下相关技术。
———————————————————————————————————————
MD2模型文件格式是在id software 于1997年11月发布Quake 2时推广出来的。
相对其他格式来说,这算是老技术了,但是比较有用的是它支持纹理,网格以及动画系统。使用它可以很自由设置帧动画,多更衣纹理。
目前alchemy3d已经完美地支持MD2格式的导入,当然这句话是废话。
好吧,请看大屏幕:
下面说说MD2的动画。
MD2的动画是渐变动画,所谓渐变动画,就是每个关键帧记录当前顶点位置信息,然后每一次调用帧按照时间对其进行缓冲,让他们看起来是连续的,这就成了动画的效果。
这样说可能会觉得很抽象,下面来看看GL的调用方式:
void
RenderFrame (int n, const struct md2_model_t *mdl)
{
int i, j;
GLfloat s, t;
vec3_t v;
struct md2_frame_t *pframe;
struct md2_vertex_t *pvert;
/* Check if n is in a valid range */
if ((n < 0) || (n > mdl->header.num_frames - 1))
return;
/* Enable model's texture */
glBindTexture (GL_TEXTURE_2D, mdl->tex_id);
/* Draw the model */
glBegin (GL_TRIANGLES);
/* Draw each triangle */
for (i = 0; i < mdl->header.num_tris; ++i)
{
/* Draw each vertex */
for (j = 0; j < 3; ++j)
{
pframe = &mdl->frames[n];
pvert = &pframe->verts[mdl->triangles[i].vertex[j]];
/* Compute texture coordinates */
s = (GLfloat)mdl->texcoords[mdl->triangles[i].st[j]].s / mdl->header.skinwidth;
t = (GLfloat)mdl->texcoords[mdl->triangles[i].st[j]].t / mdl->header.skinheight;
/* Pass texture coordinates to OpenGL */
glTexCoord2f (s, t);
/* Normal vector */
glNormal3fv (anorms_table[pvert->normalIndex]);
/* Calculate vertex real position */
v[0] = (pframe->scale[0] * pvert->v[0]) + pframe->translate[0];
v[1] = (pframe->scale[1] * pvert->v[1]) + pframe->translate[1];
v[2] = (pframe->scale[2] * pvert->v[2]) + pframe->translate[2];
glVertex3fv (v);
}
}
glEnd ();
}
下面是渐变处理:
struct md2_frame_t *pframe1, *pframe2;
struct md2_vertex_t *pvert1, *pvert2;
vec3_t v_curr, v_next, v;
for (/*
*/)
{
pframe1 = &mdl->frames[current];
pframe2 = &mdl->frames[current + 1];
pvert1 = &pframe1->verts[mdl->triangles[i].vertex[j]];
pvert2 = &pframe2->verts[mdl->triangles[i].vertex[j]];
/*
*/
v_curr[0] = (pframe1->scale[0] * pvert1->v[0]) + pframe1->translate[0];
v_curr[1] = (pframe1->scale[1] * pvert1->v[1]) + pframe1->translate[1];
v_curr[2] = (pframe1->scale[2] * pvert1->v[2]) + pframe1->translate[2];
v_next[0] = (pframe2->scale[0] * pvert2->v[0]) + pframe2->translate[0];
v_next[1] = (pframe2->scale[1] * pvert2->v[1]) + pframe2->translate[1];
v_next[2] = (pframe2->scale[2] * pvert2->v[2]) + pframe2->translate[2];
v[0] = v_curr[0] + interp * (v_next[0] - v_curr[0]);
v[1] = v_curr[1] + interp * (v_next[1] - v_curr[1]);
v[2] = v_curr[2] + interp * (v_next[2] - v_curr[2]);
/*
*/
}
好的,我假设你已经了解MD2动画是如何运转的,让我们回到Alchemy3D的Demo上,如果你足够细心,可能已经发现了某些问题,比如它前后的动作似乎是不关联的。
这是怎么回事呢,其实MD2的动画并不是单一的,具体的说每个模型的动画都是由帧动画的集合组成。每个帧动画都可以是独立存在的,它包含了自己的帧长度。要想获取单个帧动画,我们必须把它们从MD2的动画堆里提取出来。
对计算机图形学动画有些了解的朋友也许会知道,每个关键帧都会包含自己的帧名字,MD2的关键帧名字格式是这样的:
[帧动画名][帧动画第n帧]
现在我们所要做的就是把帧动画名提取出来,与你想要的动画匹配,像这样:
( ch = strstr( animation -> frames[i].name, name ) ) == animation -> frames[i].name
//然后检查后面是否全部是数字
ch += strlen( name );
match = TRUE;
while( * ch != '\0' )
{
if( !isdigit( ( int )( * ch ++ ) ) )
{
match = FALSE;
break;
}
}
