青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

永遠(yuǎn)也不完美的程序

不斷學(xué)習(xí),不斷實踐,不斷的重構(gòu)……

常用鏈接

統(tǒng)計

積分與排名

好友鏈接

最新評論

MDL file format (Quake's models)

link:http://tfc.duke.free.fr/coding/mdl-specs-en.html
Written by David Henry, 20th December of 2004

Introduction

The MDL file format is the model format used in Quake (June 1996). MDL model files' characteristics are these:

  • Model's geometric data (triangles);
  • 8 bits texture data;
  • Frame-by-frame animations;

A MDL file can hold multiple textures.

MDL model file's extension is “mdl”. A MDL file is a binary file divided in two part: the header dans the data. The header contains all information needed to use and manipulate the data.

Header
Data

Variable sizes

Variable types used in this document have those sizes:

  • char: 1 byte
  • short: 2 bytes
  • int: 4 bytes
  • float: 4 bytes
  • ubyte: 1 unsigned byte

They correspond to C type sizes on the x86 architecture. Ensure that type sizes correspond to these ones if you're compiling for another architecture.

Endianess issues

Since the MDL file format is a binary format, you'll have to deal with endianess. MDL files are stored in little-endian (x86). If you're targetting a big-endian architecture (PowerPC, SPARC, ...), or simply want your program to be portable, you'll have to perform proper conversions for each word or double word read from the file.

The header

The header is a structure which comes at the beginning of the file:

/* MDL header */
struct mdl_header_t
{
int ident;            /* magic number: "IDPO" */
int version;          /* version: 6 */
vec3_t scale;         /* scale factor */
vec3_t translate;     /* translation vector */
float boundingradius;
vec3_t eyeposition;   /* eyes' position */
int num_skins;        /* number of textures */
int skinwidth;        /* texture width */
int skinheight;       /* texture height */
int num_verts;        /* number of vertices */
int num_tris;         /* number of triangles */
int num_frames;       /* number of frames */
int synctype;         /* 0 = synchron, 1 = random */
int flags;            /* state flag */
float size;
};

ident is the magic number of the file. It is used to identify the file type. ident must be equal to 1330660425 or to the string “IDPO”. We can obtain this number with the expression (('2'<<24) + ('P'<<16) + ('D'<<8) + 'I').

version is the version number of the file format and must be equal to 6.

scale and translate are needed to obtain the real vertex coordinates of the model. scale is a scale factor and translate a translation vector (or the origin of the model). You have to first multiply the respective value of scale with the vertex coordinate and then, add the respective value of translate to the result:

vreal[i] = (scale[i] * vertex[i]) + translate[i];

where i ranges from 0 ou 2 (x, y and z coordinates).

boundingradius is the radius of a sphere in which the whole model can fit (used for collision detection for exemple).

eyeposition is... eyes' position (if the model is for a monster or other NPC). Make what you want of it.

num_skins is the number of textures present in the file. skinwidth and skinheight are respectively the with and height of the textures. All textures must have the same size.

num_verts is the number of vertices of one frame.
num_tris is the number of triangles of the model.
num_frames is the number of frames of the model.

Data types

Vector

The vector, composed of three floating coordinates (x, y, z):

/* Vector */
typedef float vec3_t[3];

Texture information

Texture data come right after the header in the file. It can be a texture composed of a single picture or a group of pictures (animated texture).

/* Skin */
struct mdl_skin_t
{
int group;      /* 0 = single, 1 = group */
GLubyte *data;  /* texture data */
};

or:

/* Group of pictures */
struct mdl_groupskin_t
{
int group;     /* 1 = group */
int nb;        /* number of pics */
float *time;   /* time duration for each pic */
ubyte **data;  /* texture data */
};

time is an array of nb elements and data an array of nb arrays of skinwidth * skinheight elements (picture size).

Data pictures are contained in the data array and are in 8 bits color index mode. The colormap is generally in a separate LMP file (*.lmp). LMP files are binary files which contain only 768 bytes (256 colors in 24 bits). They are easy to use: just read the whole file in a buffer and it's done.

A colormap is avalaible in texte format.

There are num_skins objects of mdl_skin_t type or mdl_groupskin_t type.

Texture coordinates

Texture coordinates are stored in a structure as short integers.

/* Texture coords */
struct mdl_texcoord_t
{
int onseam;
int s;
int t;
};

Texture are generally divided in two pieces: one for the frontface of the model, and one for the backface. The backface piece must be translated of skinwidth/2 from the frontface piece.

onseam indicates if the vertex is on the boundary of two pieces.

To obtain real (s, t) coordinates (ranging from 0.0 to 1.0), you have to add 0.5 to the coordinates and then divide the result by skinwidth for s and skinheight for t.

There are num_verts (s, t) texture coordinates in a MDL model. Texture coordinate data come after texture data.

Triangles

Each triangle has an array of vertex indices and a flag to indicate if it is a frontface or a backface triangle.

/* Triangle info */
struct mdl_triangle_t
{
int facesfront;  /* 0 = backface, 1 = frontface */
int vertex[3];   /* vertex indices */
};

If a vertex which belong to a backface triangle is on the boundary of two pieces (onseam is true), you have to add skinwidth/2 to s in order to correct texture coordinates.

There are num_tris triangles in a MDL model. Triangle data follow texture coord. data in the file.

Vertices

Vertices are composed of “compressed” 3D coordinates, which are stored in one byte for each coordinate, and of a normal vector index. The normal vector array is stored in the anorms.h file of Quake and hold 162 vectors in floating point (3 float).

/* Compressed vertex */
struct mdl_vertex_t
{
unsigned char v[3];
unsigned char normalIndex;
};

Frames

Each frames has its vertex list and some other specific informations.

/* Simple frame */
struct mdl_simpleframe_t
{
struct mdl_vertex_t bboxmin; /* bouding box min */
struct mdl_vertex_t bboxmax; /* bouding box max */
char name[16];
struct mdl_vertex_t *verts;  /* vertex list of the frame */
};

bboxmin and bboxmax define a box in which the model can fit. name is the name of the frame. verts is the vertex list of the frame.

Frames can be simple frames or groups of frames. We can know if it's a simple frame or a group with a flag:

/* Model frame */
struct mdl_frame_t
{
int type;                        /* 0 = simple, !0 = group */
struct mdl_simpleframe_t frame;  /* this program can't read models
composed of group frames! */
};

or:

/* Group of simple frames */
struct mdl_groupframe_t
{
int type;                         /* !0 = group */
struct mdl_vertex_t min;          /* min pos in all simple frames */
struct mdl_vertex_t max;          /* max pos in all simple frames */
float *time;                      /* time duration for each frame */
struct mdl_simpleframe_t *frames; /* simple frame list */
};

time and frames are arrays of nb dimension. min and max correspond to the min and max positions in all simple frames of the frame group. time is the duration of each simple frame.

There are num_frames frames in a MDL model. Frames come after triangle data in the MDL file.

Reading a MDL file

Assuming that mdl_model_t is a structure holding all your model's data and *mdl a pointer on a mdl_model_t object, this code show how to load a MDL model file:

int
ReadMDLModel (const char *filename, struct mdl_model_t *mdl)
{
FILE *fp;
int i;
fp = fopen (filename, "rb");
if (!fp)
{
fprintf (stderr, "error: couldn't open \"%s\"!\n", filename);
return 0;
}
/* Read header */
fread (&mdl->header, 1, sizeof (struct mdl_header_t), fp);
if ((mdl->header.ident != 1330660425) ||
(mdl->header.version != 6))
{
/* Error! */
fprintf (stderr, "Error: bad version or identifier\n");
fclose (fp);
return 0;
}
/* Memory allocations */
mdl->skins = (struct mdl_skin_t *)
malloc (sizeof (struct mdl_skin_t) * mdl->header.num_skins);
mdl->texcoords = (struct mdl_texcoord_t *)
malloc (sizeof (struct mdl_texcoord_t) * mdl->header.num_verts);
mdl->triangles = (struct mdl_triangle_t *)
malloc (sizeof (struct mdl_triangle_t) * mdl->header.num_tris);
mdl->frames = (struct mdl_frame_t *)
malloc (sizeof (struct mdl_frame_t) * mdl->header.num_frames);
mdl->tex_id = (GLuint *)
malloc (sizeof (GLuint) * mdl->header.num_skins);
mdl->iskin = 0;
/* Read texture data */
for (i = 0; i < mdl->header.num_skins; ++i)
{
mdl->skins[i].data = (GLubyte *)malloc (sizeof (GLubyte)
* mdl->header.skinwidth * mdl->header.skinheight);
fread (&mdl->skins[i].group, sizeof (int), 1, fp);
fread (mdl->skins[i].data, sizeof (GLubyte),
mdl->header.skinwidth * mdl->header.skinheight, fp);
mdl->tex_id[i] = MakeTextureFromSkin (i, mdl);
free (mdl->skins[i].data);
mdl->skins[i].data = NULL;
}
fread (mdl->texcoords, sizeof (struct mdl_texcoord_t),
mdl->header.num_verts, fp);
fread (mdl->triangles, sizeof (struct mdl_triangle_t),
mdl->header.num_tris, fp);
/* Read frames */
for (i = 0; i < mdl->header.num_frames; ++i)
{
/* Memory allocation for vertices of this frame */
mdl->frames[i].frame.verts = (struct mdl_vertex_t *)
malloc (sizeof (struct mdl_vertex_t) * mdl->header.num_verts);
/* Read frame data */
fread (&mdl->frames[i].type, sizeof (long), 1, fp);
fread (&mdl->frames[i].frame.bboxmin,
sizeof (struct mdl_vertex_t), 1, fp);
fread (&mdl->frames[i].frame.bboxmax,
sizeof (struct mdl_vertex_t), 1, fp);
fread (mdl->frames[i].frame.name, sizeof (char), 16, fp);
fread (mdl->frames[i].frame.verts, sizeof (struct mdl_vertex_t),
mdl->header.num_verts, fp);
}
fclose (fp);
return 1;
}

Note: this code can't handle MDL files with group frames.

Rendering the model

Here is an exemple of how to draw a frame n of a model mdl:

void
RenderFrame (int n, const struct mdl_model_t *mdl)
{
int i, j;
GLfloat s, t;
vec3_t v;
struct mdl_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[mdl->iskin]);
/* 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)
{
pvert = &mdl->frames[n].frame.verts[mdl->triangles[i].vertex[j]];
/* Compute texture coordinates */
s = (GLfloat)mdl->texcoords[mdl->triangles[i].vertex[j]].s;
t = (GLfloat)mdl->texcoords[mdl->triangles[i].vertex[j]].t;
if (!mdl->triangles[i].facesfront &&
mdl->texcoords[mdl->triangles[i].vertex[j]].onseam)
{
s += mdl->header.skinwidth * 0.5f; /* Backface */
}
/* Scale s and t to range from 0.0 to 1.0 */
s = (s + 0.5) / mdl->header.skinwidth;
t = (t + 0.5) / mdl->header.skinheight;
/* Pass texture coordinates to OpenGL */
glTexCoord2f (s, t);
/* Normal vector */
glNormal3fv (anorms_table[pvert->normalIndex]);
/* Calculate real vertex position */
v[0] = (mdl->header.scale[0] * pvert->v[0]) + mdl->header.translate[0];
v[1] = (mdl->header.scale[1] * pvert->v[1]) + mdl->header.translate[1];
v[2] = (mdl->header.scale[2] * pvert->v[2]) + mdl->header.translate[2];
glVertex3fv (v);
}
}
glEnd ();
}

Animation

MDL models are frame-by-frame animated. A frame is a screenshot of an animation. To avoid jerked and ugly animations, we use linear interpolation between vertex coordinates of two consecutive frames (the current frame we are drawing and the next frame). We do the same for the normal vector:

struct mdl_vertex_t *pvert1, *pvert2;
vec3_t v;
for (/* ... */)
{
pvert1 = &mdl->frames[current].frame.verts[mdl->triangles[i].vertex[j]];
pvert2 = &mdl->frames[current + 1].frame.verts[mdl->triangles[i].vertex[j]];
/* ... */
v[0] = mdl->header.scale[0] * (pvert1->v[0] + interp * (pvert2->v[0] - pvert1->v[0])) + mdl->header.translate[0];
v[1] = mdl->header.scale[1] * (pvert1->v[1] + interp * (pvert2->v[1] - pvert1->v[1])) + mdl->header.translate[1];
v[2] = mdl->header.scale[2] * (pvert1->v[2] + interp * (pvert2->v[2] - pvert1->v[2])) + mdl->header.translate[2];
/* ... */
}

v is the final vertex to draw. interp is the interpolation percent between the two frames. It's a float which ranges from 0.0 to 1.0. When it is equal to 1.0, current is incremented by 1 and interp is reinitialized at 0.0. It is useless to interpolate texture coordinates because they are the same for all the model frames. It is preferable that interp is related to the program's number of rendering frame per second (fps).

void
Animate (int start, int end, int *frame, float *interp)
{
if ((*frame < start) || (*frame > end))
*frame = start;
if (*interp >= 1.0f)
{
/* Move to next frame */
*interp = 0.0f;
(*frame)++;
if (*frame >= end)
*frame = start;
}
}

Constants

Here are some constant values defining maximal dimensions:

  • Maximum number of triangles: 2048
  • Maximum number of vertices: 1024
  • Maximum number of texture coordinates: 1024
  • Maximum number of frames: 256
  • Number of precalculated normal vectors: 162

posted on 2008-11-04 15:51 狂爛球 閱讀(1192) 評論(0)  編輯 收藏 引用 所屬分類: 圖形編程

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美日本中文字幕| 午夜精品福利视频| 欧美岛国在线观看| 99精品视频免费全部在线| 久久婷婷人人澡人人喊人人爽| 亚洲国产一二三| 亚洲激情欧美激情| 宅男噜噜噜66国产日韩在线观看| 亚洲一区在线免费| 久久这里只精品最新地址| 久久久久久亚洲精品杨幂换脸| 欧美亚洲一区二区三区| 巨胸喷奶水www久久久免费动漫| 久久久五月天| 日韩一级不卡| 久久人人九九| 国产精品国产三级国产普通话三级 | 在线日韩视频| 一区二区欧美日韩视频| 欧美影院精品一区| 一区二区日韩精品| 久久婷婷蜜乳一本欲蜜臀| 欧美日韩黄色大片| 亚洲人成网在线播放| 西西人体一区二区| 亚洲精品乱码久久久久久蜜桃麻豆| 亚洲国产老妈| 亚洲国产精品一区二区第四页av| 久久aⅴ国产紧身牛仔裤| 99riav久久精品riav| 美女精品国产| 国产一区二区在线观看免费播放| 中文日韩电影网站| 欧美岛国在线观看| 久久亚洲春色中文字幕| 国产一区二区成人| 久久黄色级2电影| 欧美一区网站| 亚洲国产第一| 日韩视频免费在线| 国产精品白丝jk黑袜喷水| 正在播放欧美一区| 亚洲欧美精品在线观看| 海角社区69精品视频| 亚洲精品日韩在线观看| 国产精品成人va在线观看| 欧美一区日韩一区| 午夜一区不卡| 中国亚洲黄色| 欧美视频在线不卡| 亚洲人成人一区二区在线观看| 狠狠噜噜久久| 美女网站久久| 99ri日韩精品视频| 一区二区日韩欧美| 乱中年女人伦av一区二区| 裸体一区二区三区| 亚洲在线网站| 欧美刺激午夜性久久久久久久| 亚洲天堂成人| 免费不卡亚洲欧美| 欧美在线视频一区| 久久久精品国产免费观看同学| 欧美一级网站| 亚洲婷婷综合久久一本伊一区| 亚洲精品一区久久久久久| 日韩午夜精品| 亚洲视频碰碰| 韩国一区二区三区在线观看| 欧美成人69| 久久久www免费人成黑人精品| 91久久午夜| 国产美女诱惑一区二区| 一个色综合av| 亚洲欧美一区二区激情| 欧美亚洲成人精品| 亚洲欧美日本国产有色| 欧美影视一区| 136国产福利精品导航网址| 久久精品视频va| 欧美激情精品久久久久| 亚洲三级影院| 欧美成人精品福利| 亚洲视频在线观看免费| 美日韩丰满少妇在线观看| 亚洲欧美日韩中文在线制服| 免费不卡在线观看| 午夜欧美大尺度福利影院在线看| 精品二区视频| 激情小说亚洲一区| 国产精品视频福利| 欧美系列精品| 欧美日韩一区二区三区在线观看免| 久久精品国产欧美亚洲人人爽| 亚洲一区二三| 午夜影院日韩| 久久精品国产亚洲a| 久久久噜噜噜久噜久久| 久久五月婷婷丁香社区| 麻豆亚洲精品| 亚洲欧美国产另类| 亚洲剧情一区二区| 亚洲性xxxx| 久久久久久久999精品视频| 久久亚洲欧美| 欧美日韩视频在线| 久久综合五月| 韩国av一区二区三区| 久久乐国产精品| 亚洲成色999久久网站| 欧美一区二区三区婷婷月色| 欧美插天视频在线播放| 老妇喷水一区二区三区| 久久国产精品第一页| 久久福利毛片| 欧美午夜激情视频| 久久国产精品亚洲va麻豆| 久久综合一区| 久久一日本道色综合久久| 国产精品爽爽ⅴa在线观看| 久久天天狠狠| 欧美日韩亚洲天堂| 亚洲视频一二三| 亚洲中字黄色| 狠狠久久亚洲欧美专区| 欧美精品一区二区三区蜜桃| 亚洲欧美日韩直播| 免费欧美在线| 久久免费视频网| 亚洲日韩中文字幕在线播放| 亚洲国产网站| 中文久久乱码一区二区| 一道本一区二区| 亚洲国产欧美日韩精品| 欧美激情一区二区三区在线| 久久麻豆一区二区| 亚洲电影第三页| 麻豆精品网站| aa日韩免费精品视频一| 99成人在线| 一区二区三区免费在线观看| 欧美精品一卡| 亚洲另类黄色| 美女主播一区| 亚洲一区网站| 亚洲国产成人91精品| 欧美日韩在线观看一区二区| 欧美a级片网站| 亚洲性感美女99在线| 国产精品一区二区三区乱码| 亚洲视频免费在线观看| 亚洲午夜在线视频| 国产亚洲成av人片在线观看桃 | 亚洲影院在线观看| 一本色道久久88综合日韩精品| 亚洲精品乱码久久久久久日本蜜臀| 欧美日本高清一区| 久久国产乱子精品免费女 | 欧美日韩亚洲网| 久久精品最新地址| 欧美伦理影院| 老司机67194精品线观看| 欧美日韩一区在线播放| 欧美成人国产va精品日本一级| 欧美日韩蜜桃| 亚洲国产精品欧美一二99| 国产午夜精品久久久| 99re热这里只有精品视频| 一区二区三区高清不卡| 亚洲欧美中文在线视频| 亚洲国产成人不卡| 欧美激情中文字幕乱码免费| 亚洲午夜在线| 久久久久国产精品午夜一区| 亚洲高清在线观看| 一区二区三区高清视频在线观看| 国产亚洲精品久久久| 亚洲国产精品成人综合色在线婷婷 | 欧美a级一区| 老牛国产精品一区的观看方式| 国产精品久久久久久av福利软件| 国产麻豆日韩| 亚洲激情视频网| 亚洲一区二区网站| 亚洲国产精品免费| 欧美精品一区二区三| 国产偷国产偷亚洲高清97cao| 亚洲一区二区成人在线观看| 久久国产黑丝| 欧美一区二区视频在线| 亚洲国产福利在线| 亚洲电影在线免费观看| 久久在线精品| 欧美亚洲网站| 国产精品爽爽爽| 亚洲男女毛片无遮挡| 亚洲一区二区在线| 国产女人18毛片水18精品| 亚洲天堂av在线免费观看| 国内外成人在线|