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

永遠(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 狂爛球 閱讀(1195) 評論(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>
            欧美激情第9页| 欧美在线3区| 欧美精品aa| 免费不卡中文字幕视频| 久久精品国产一区二区三| 亚洲国产高清在线| 99精品国产高清一区二区| 99国产精品国产精品毛片| 国产精品午夜在线观看| 欧美好吊妞视频| 国产精品九九久久久久久久| 久色婷婷小香蕉久久| 欧美日韩中国免费专区在线看| 亚洲成人自拍视频| 久久精品国内一区二区三区| 久久在线91| 亚洲欧美日本伦理| 女人色偷偷aa久久天堂| 欧美在线免费观看亚洲| 欧美日韩成人精品| 欧美韩日视频| 国产日韩一区二区三区| 久久精品1区| 欧美亚洲日本一区| 一本色道久久88综合亚洲精品ⅰ | 亚洲视频在线观看一区| 影音先锋久久精品| 亚洲欧美日韩国产精品| 国产嫩草一区二区三区在线观看 | 欧美电影免费观看| 欧美午夜宅男影院在线观看| 亚洲大黄网站| 国产精品成人va在线观看| 亚洲第一精品夜夜躁人人爽 | 欧美精品久久一区二区| 久久香蕉精品| 国产视频一区在线| 猫咪成人在线观看| 国产欧美1区2区3区| 一区二区成人精品| 一本一本久久a久久精品牛牛影视| 一本一本大道香蕉久在线精品| 欧美日韩一卡二卡| 亚洲人午夜精品| 亚洲国产三级网| 久久婷婷一区| 另类天堂视频在线观看| 国产欧美日韩亚州综合| 亚洲在线视频网站| 亚洲欧美日韩一区| 国产精品一区二区你懂得| 亚洲手机在线| 亚洲一区精品视频| 国产精品啊啊啊| 久久午夜影视| 精品福利免费观看| 久久久久久婷| 欧美成人亚洲成人日韩成人| 日韩一区二区精品视频| 欧美1区2区视频| 久久久久久久综合| 99re视频这里只有精品| 久久久水蜜桃| 亚洲在线播放电影| 国产精品美女一区二区| 一区二区三欧美| 日韩视频免费观看高清完整版| 欧美日韩免费高清| 欧美伊人精品成人久久综合97| 久久一区二区三区四区五区| 美日韩精品免费| 欧美精品videossex性护士| 91久久精品www人人做人人爽| 国产伦一区二区三区色一情| 亚洲欧美日韩国产综合精品二区| 日韩视频第一页| 欧美日韩一区二区三区四区五区| 乱码第一页成人| 国产精品欧美风情| 久久精品亚洲一区二区三区浴池 | 欧美一区二区啪啪| 麻豆精品精华液| 夜夜狂射影院欧美极品| 久久亚洲国产精品日日av夜夜| 亚洲欧美日韩精品在线| 国产午夜久久久久| 欧美激情性爽国产精品17p| 日韩视频欧美视频| 久久人91精品久久久久久不卡| 国产精品成人va在线观看| 销魂美女一区二区三区视频在线| 正在播放亚洲一区| 国产免费成人在线视频| 欧美成人午夜激情视频| 欧美99在线视频观看| 宅男噜噜噜66一区二区| 欧美精品粉嫩高潮一区二区| 亚洲午夜伦理| 亚洲国产精品123| 亚洲欧美在线aaa| 亚洲黄色三级| 国产欧美一区视频| 欧美一区二区成人| 免费欧美视频| 亚洲欧美日韩专区| 亚洲日本va午夜在线影院| 国产日本欧美在线观看| 欧美日韩一区二区在线播放| 久久精品在线观看| 亚洲一区二区三区视频| 91久久黄色| 亚洲天堂av图片| 亚洲第一中文字幕| 美女91精品| 欧美在线播放一区二区| 日韩一级视频免费观看在线| 欧美成人免费播放| 久久久久天天天天| 亚洲欧美日韩一区二区| 中日韩高清电影网| 日韩视频精品在线观看| 黄色综合网站| 国产日韩欧美高清免费| 欧美日韩精品欧美日韩精品| 欧美成人第一页| 国产精品一区二区欧美| 午夜精品免费在线| 欧美在线亚洲综合一区| 最新国产成人在线观看| 亚洲高清在线| 曰韩精品一区二区| 韩国一区二区在线观看| 国产亚洲欧美日韩一区二区| 国产精品日韩精品欧美精品| 欧美视频日韩视频| 欧美性猛交99久久久久99按摩| 亚洲一区二区三区激情| 亚洲人成7777| 亚洲欧洲日本mm| 亚洲精品在线视频观看| 欧美在线关看| 香蕉免费一区二区三区在线观看| 黄色成人免费网站| 国产欧美一区二区在线观看| 国产精品视频久久久| 国产精品自在线| 国产欧美日韩另类一区| 国产亚洲综合在线| 国产亚洲精品美女| 在线日韩av片| 国产精品免费在线| 国产精品一区二区久久国产| 国产精品在线看| 国内久久精品| 亚洲精品视频在线| 亚洲深夜激情| 欧美在线高清视频| 欧美成人xxx| 亚洲国产婷婷| 一区二区精品在线观看| 亚洲综合不卡| 亚洲国产成人精品久久久国产成人一区| 一本大道久久精品懂色aⅴ| 国产美女精品在线| 黄色一区二区在线| 亚洲国产一区二区在线| 国产精品99久久久久久久女警| 激情欧美一区二区三区| 亚洲国产精品va在线观看黑人| 国产精品swag| 国产精品免费观看在线| 国产亚洲精品美女| 亚洲日本中文字幕免费在线不卡| 国产午夜亚洲精品不卡| 在线免费观看日本一区| 亚洲日韩欧美视频一区| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 亚洲国产日韩欧美综合久久| 日韩一区二区久久| 亚洲高清在线观看| 这里只有精品视频在线| 欧美一区久久| 亚洲第一伊人| 亚洲网站视频福利| 久久久久国产精品午夜一区| 欧美理论视频| 激情综合在线| 国产一区999| 亚洲风情亚aⅴ在线发布| 亚洲图片激情小说| 久久亚洲影院| 亚洲手机在线| 母乳一区在线观看| 国产精品久久久久久久第一福利| 另类尿喷潮videofree| 欧美调教vk| 亚洲第一精品夜夜躁人人爽| 亚洲私人黄色宅男| 亚洲第一页在线| 欧美与欧洲交xxxx免费观看|