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

永遠也不完美的程序

不斷學習,不斷實踐,不斷的重構……

常用鏈接

統計

積分與排名

好友鏈接

最新評論

MD5Mesh and MD5Anim files formats(Doom 3's models)

Written by David Henry, 21th august of 2005

NOTE: this has nothing to do with the cryptographic hash function also called “MD5”.

Introduction

The MD5 model format comes from id Software's Doom 3 first person shooter, released in august 2004. The mesh data and animation data are separated in distinct files. These are ASCII files and are human readable. Here are some generalities about the MD5 format:

  • Model's geometric data are stored in *.md5mesh files;
  • Animations are stored in *.md5anim files;
  • Supports Skeletal Animation;
  • Supports Vertex Skinning;
  • Uses quaternions for orientation.

Textures are in separate files (TGA, DDS, or whatever you want). In Doom 3, they are controlled by the *.mtr files in the /materials directory from the game's *.pk4 files. The MTR files are not covered here.

Working with quaternions

The MD5 Mesh and MD5 Anim formats work with quaternions. Quaternions are magic mathematical objects which can represent an orientation. Quaternions are an extension of the complex numbers. If you just discover them now, or don't know how to use them, take a look at a computer graphics math book or at an online FAQ about them.

Quaternions are an alternative to matrices for representing a rotation. Quaternions can't hold information about position (like 4x4 matrices), just the orientation. They can hold the same information as 3x3 rotation matrices.

There is not a lot of things to know about quaternions here, just some formulas:

  • Quaternion multiplication (Quat × Quat);
  • Rotation of a point by a quaternion;
  • Quaternion inverse;
  • Quaternion normalization;
  • Quaternion interpolation (SLERP), for smooth animation.

Quaternions are represented by four components: w, x, y and z. Orientation quaternions are unit quaternions.

In the MD5 Mesh and MD5 Anim files, only the x, y and z components are stored. You'll have to compute the w-component yourself, given the three others.

Computing the w-component

Since we deal with only unit quaternions (their length is 1.0), we can obtain the last component with this formula:

float t = 1.0f - (q.x * q.x) - (q.y * q.y) - (q.z * q.z);
if (t < 0.0f)
{
q.w = 0.0f;
}
else
{
q.w = -sqrt (t);
}

Others quaternion operations

A realy quick overview of needed quaternion operations and formulas. For more about them, refer to a 3D Math book, an online FAQ or Wikipedia.

The quaternion multiplication allows to concatenate two rotations. The product of two quaternions Qa and Qb is given by the following formula :

Qa.Qb = (wa, va)(wb, vb) = (wawb - va·vb, wavb + wbva + wa×wb)

After expanding and making simplifications, we have the following result :

r.w = (qa.w * qb.w) - (qa.x * qb.x) - (qa.y * qb.y) - (qa.z * qb.z);
r.x = (qa.x * qb.w) + (qa.w * qb.x) + (qa.y * qb.z) - (qa.z * qb.y);
r.y = (qa.y * qb.w) + (qa.w * qb.y) + (qa.z * qb.x) - (qa.x * qb.z);
r.z = (qa.z * qb.w) + (qa.w * qb.z) + (qa.x * qb.y) - (qa.y * qb.x);

Be careful! Quaternions are non-commutative, i.e. Qa × Qb ≠ Qb × Qa.

The rotation of a point by a quaternion is given by the formula:

R = Q.P.Q*

Where R is the resultant quaternion, Q is the orientation quaternion by which you want to perform a rotation, Q* the conjugate of Q and P is the point converted to a quaternion. To convert a 3D vector to a quaternion, copy the x, y and z components and set the w component to 0. This is the same for quaternion to vector conversion: take the x, y and z components and forget the w.

Note: here the “.” is the multiplication operator.

Quaternion inverse can be obtained, for unit quaternions, by negating the x, y and z components (this is equal to the conjugate quaternion):

inverse(<w, x, y, z>) = conjugate(<w, x, y, z>) = <w, -x, -y, -z>

Quaternion normalization is exactly the same as for vectors, but with four components.

I will not cover the quaternions spherical linear interpolation (SLERP) here, but you can look at the sample code (at the end of this document), or in books, or in the web for the formula. Spherical linear interpolation is used to interpolate two orientations. It is usefull for skeletal animation.

MD5 Mesh

The MD5 Mesh files have the “md5mesh” extension. They contain the geometric data of the models:

  • Model's bind-pose skeleton;
  • One or multiple meshes. Each mesh have its proper data:
    • Vertices;
    • Triangles;
    • Vertex weights;
    • A shader name.

Reading a md5mesh file

When parsing the MD5 Mesh file, you can find comments. They start with the “//” string and goes to the end of the line. They are here just for humans who want to take a look at the file with a text editor, they don't affect model's data. You can ignore them.

Before loading the geometric data, you will find some precious variables needed to check if this is a valid md5mesh file and for allocating memory:

MD5Version 10
commandline "<string>"
numJoints <int>
numMeshes <int>

The first line tell you the version of the format. This is an integer. Doom 3's MD5 version is 10. This document covers the version 10 of the format. Olders (or newers) may differ in some points in the structure of the format.

Then comes the commmandline string used by Doom 3 with the exportmodels console command. I have nothing to tell you about it.

numJoints is the number of joints of the model's skeleton. numMeshes is the number of meshes of the model contained in the md5mesh file.

After that you have the bind-pose skeleton's joints:

joints {
"name" parent ( pos.x pos.y pos.z ) ( orient.x orient.y orient.z )
...
}

name (string) is the joint's name. parent (int) is the joint's parent index. If it is equal to -1, then the joint has no parent joint and is what we call a root joint. pos.x, pos.y and pos.z (float) are the joint's position in space. orient.x, orient.y and orient.z (float) are the joint's orientation quaternion x, y and z components. After reading a joint, you must calculate the w component.

After the skeleton, there are the meshes. Each mesh is in the form:

mesh {
shader "<string>"
numverts <int>
vert vertIndex ( s t ) startWeight countWeight
vert ...
numtris <int>
tri triIndex vertIndex[0] vertIndex[1] vertIndex[2]
tri ...
numweights <int>
weight weightIndex joint bias ( pos.x pos.y pos.z )
weight ...
}

The shader string is defined in the MTR files (/materials directory) of Doom 3 and tell you what are the textures to apply to the mesh and how to combine them.

numverts (int) is the number of vertices of the mesh. After this variable, you have the vertex list. vertIndex (int) is the vertex index. s and t (float) are the texture coordinates (also called UV coords). In the MD5 Mesh format, a vertex hasn't a proper position. Instead, its position is computed from vertex weights (this is explained later in this document). countWeight (int) is the number of weights, starting from the startWeight (int) index, which are used to calculate the final vertex position.

numtris is the number of triangles of the mesh. triIndex (int) is the index of the triangle. Each is defined by three vertex indices composing it: vertIndex[0], vertIndex[1] and vertIndex[2] (int).

numweights (int) is the number of weights of the mesh. weightIndex (int) is the weight index. joint (int) is the joint it depends of. bias (float) is a factor in the ]0.0, 1.0] range which defines the contribution of this weight when computing a vertex position. pos.x, pos.y and pos.z (float) are the weight's position in space.

The bind-pose skeleton

The model's skeleton stored in the MD5 Mesh files is what we call the “bind-pose skeleton”. It is generally in a position in which the model has been created.

Its joints are already in their final position, you don't have to make any precomputation on it, like adding the parent joint's position and rotating it or anything. Their position are in object space and independent of others joints.

Computing vertex positions

As said before, the vertex positions must be calculated from the weights. Each vertex has one or more weights, each of them having a position dependent of a joint (the position is in joint's local space), and a factor telling us how much it affects the vertex position. The sum of all weight factors of a vertex should be 1.0. This technique is called “vertex skinning” and allows a vertex to depend on more than one joint of the skeleton for better animation rendering.

First, each vertex' weight position must be converted from joint local space to object space. Then, sum all the weights multiplied by their bias value:

finalPos = (weight[0].pos * weight[0].bias) + ... + (weight[N].pos * weight[N].bias)

The vertex data that comes from the MD5 Mesh file has a start index and a count value. The start index is the index to the first weight used by the vertex. Then, all vertex' weight comes just right after this one. The count value indicates the number of weights used from the first weight. Here is the code to compute the final vertex positions (in object space) from their weights:

/* Setup vertices */
for (i = 0; i < mesh->num_verts; ++i)
{
vec3_t finalVertex = { 0.0f, 0.0f, 0.0f };
/* Calculate final vertex to draw with weights */
for (j = 0; j < mesh->vertices[i].count; ++j)
{
const struct md5_weight_t *weight = &mesh->weights[mesh->vertices[i].start + j];
const struct md5_joint_t *joint = &joints[weight->joint];
/* Calculate transformed vertex for this weight */
vec3_t wv;
Quat_rotatePoint (joint->orient, weight->pos, wv);
/* the sum of all weight->bias should be 1.0 */
finalVertex[0] += (joint->pos[0] + wv[0]) * weight->bias;
finalVertex[1] += (joint->pos[1] + wv[1]) * weight->bias;
finalVertex[2] += (joint->pos[2] + wv[2]) * weight->bias;
}
...
}

Texture coordinates

Each vertex has its own texture coordinates. The ST (or UV) texture coordinates for the upper-left corner of the texture are (0.0, 0.0). The ST texture coordinates for the lower-right corner are (1.0, 1.0).

The vertical direction is the inverse of the standard OpenGL direction for the T coordinate. This is like the DirectDraw Surface way. When loading a texture (other than a DDS file), you'll have to flip it vertically or take the oposite of the T texture coordinate for MD5 Mesh vertices (i.e., 1.0 - T).

Precomputing normals

You will probably need to compute normal vectors, for example for lighting. Here is how to compute them in order to get “weight normals”, like the weight positions (this method also works for tangents and bi-tangents):

First, compute all model's vertex positions in bind-pose (using the bind-pose skeleton).

Compute the vertex normals. You now have the normals in object space for the bind-pose skeleton.

For each weight of a vertex, transform the vertex normal by the inverse joint's orientation quaternion of the weight. You now have the normal in joint's local space.

Then when calculating the final vertex positions, you will be able to do the same for the normals, except you won't have to translate from the joint's position when converting from joint's local space to object space.

posted on 2008-11-06 11:54 狂爛球 閱讀(1238) 評論(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>
            亚洲黄色av一区| 亚洲精品日韩在线| 欧美福利视频在线观看| 香港久久久电影| 欧美亚洲免费在线| 欧美一乱一性一交一视频| 亚洲欧美经典视频| 久久久久国产精品一区三寸| 久久精品主播| 欧美剧在线免费观看网站| 欧美成人性生活| 国产精品久久久爽爽爽麻豆色哟哟| 欧美日韩一区二区在线观看| 亚洲国产91| 日韩视频永久免费| 欧美在线视频一区二区三区| 久久激情视频久久| 欧美日韩成人一区二区三区| 欧美美女操人视频| 国产午夜精品久久久久久免费视 | 久久精品视频亚洲| 午夜精品美女自拍福到在线| 久久久人人人| 欧美精品粉嫩高潮一区二区| 国产精品日本精品| 91久久国产综合久久| 99人久久精品视频最新地址| 亚洲欧美国产毛片在线| 国产精品一二三| 亚洲视频一区二区免费在线观看| 欧美在线观看你懂的| 亚洲人成绝费网站色www| 午夜激情综合网| 欧美日韩国产美| 日韩西西人体444www| 久久久久国产精品午夜一区| 日韩一级片网址| 欧美成人午夜视频| 亚洲日本久久| 91久久精品一区二区别| 久久综合给合久久狠狠色| 国产综合欧美| 午夜精品在线| 欧美一区三区二区在线观看| 国产精品一区二区男女羞羞无遮挡 | 伊人成人在线| 香蕉乱码成人久久天堂爱免费| 亚洲伦理精品| 欧美日韩免费一区二区三区| 日韩一级精品视频在线观看| 亚洲国产日韩欧美综合久久| 欧美在线视频网站| 在线亚洲国产精品网站| 欧美日韩一二三区| 亚洲淫片在线视频| 亚洲女人天堂成人av在线| 国产精品毛片一区二区三区| 一区二区欧美日韩视频| 亚洲人成在线播放| 欧美成人精品在线播放| 亚洲国产精品专区久久| 亚洲电影免费观看高清完整版 | 亚洲国产精品毛片| 欧美高清视频一区二区| 欧美精品三级| 先锋影院在线亚洲| 欧美一级视频免费在线观看| 国产精品jvid在线观看蜜臀| 欧美呦呦网站| 免费成人av在线| 一本色道久久加勒比88综合| 午夜欧美精品久久久久久久| 国产一区二区三区在线观看免费视频 | 亚洲欧洲日本在线| 日韩视频精品在线观看| 国产在线视频欧美| 亚洲精品乱码久久久久久| 欧美日本一区二区视频在线观看 | 伊人蜜桃色噜噜激情综合| 亚洲激情视频在线观看| 国产亚洲一区二区三区在线观看| 欧美激情精品| 国产精品无码专区在线观看| 欧美福利小视频| 国产精品视频不卡| 亚洲国产精品久久久久婷婷老年| 国产精品综合| 日韩午夜在线播放| 极品日韩av| 亚洲视频免费在线| 亚洲视频观看| 亚洲精品欧美专区| 合欧美一区二区三区| 亚洲视频免费在线观看| 亚洲免费观看高清完整版在线观看熊 | 一本色道久久综合亚洲精品按摩 | 久久精品国产免费看久久精品| 欧美国产激情二区三区| 久久伊人免费视频| 精品不卡一区| 久久精品一级爱片| 久久激情网站| 国产一区在线观看视频| 久久精品视频va| 久久久www成人免费无遮挡大片| 国产精品午夜春色av| 亚洲网在线观看| 午夜视频在线观看一区二区三区 | 欧美激情久久久久久| 亚洲理伦在线| 国产精品久久久久久久7电影 | 一区二区三区精品视频在线观看| 99国产精品视频免费观看| 欧美激情第3页| 亚洲午夜黄色| 蜜桃久久精品乱码一区二区| 伊人成年综合电影网| 欧美日韩一区精品| 亚洲欧美在线免费观看| 免费观看在线综合| 夜夜嗨av色综合久久久综合网| 国产精品99一区二区| 久久精品在线免费观看| 亚洲黄色成人| 欧美一区二区三区精品电影| 亚洲电影av| 国产精品一区视频| 欧美日韩在线观看视频| 1769国产精品| 亚洲精品国产精品国产自| 欧美制服丝袜第一页| 亚洲激情社区| 国产精品一区二区在线观看不卡| 久久人91精品久久久久久不卡| 一本色道久久加勒比精品| 欧美激情久久久久| 久久精品国产亚洲一区二区三区| 含羞草久久爱69一区| 欧美精品色网| 久久久综合精品| 午夜在线电影亚洲一区| 亚洲日韩欧美视频| 久久综合九色| 欧美成人免费在线视频| 欧美一区二区三区免费大片| 亚洲一级片在线观看| 亚洲影院污污.| 亚洲欧美国产日韩天堂区| 亚洲视频中文| 欧美一区二区| 久久久久久欧美| 久久婷婷综合激情| 欧美α欧美αv大片| 亚洲精品日韩一| 亚洲国产一区二区a毛片| 亚洲最新视频在线播放| 亚洲一区二区四区| 久久成人18免费网站| 久久爱另类一区二区小说| 毛片精品免费在线观看| 欧美激情网站在线观看| 国产老女人精品毛片久久| 黄色欧美成人| 亚洲性视频网站| 久久久久久黄| 亚洲一区二区毛片| 美女主播一区| 国产亚洲精品久久久| 亚洲精品一区二区三| 久久免费黄色| 夜夜夜精品看看| 欧美肥婆在线| 国产在线拍偷自揄拍精品| 亚洲系列中文字幕| 欧美大片免费观看在线观看网站推荐| 亚洲精品小视频在线观看| 欧美在线1区| 国产欧美日韩在线| 亚洲欧美在线另类| 亚洲破处大片| 亚洲人成人一区二区在线观看| 午夜一区在线| 欧美调教vk| 一本一本久久a久久精品牛牛影视| 久久久夜精品| 亚洲欧美激情在线视频| 国产精品免费在线| 亚洲免费小视频| 亚洲午夜伦理| 国产婷婷色一区二区三区在线| 欧美影院在线播放| 亚洲欧美综合v| 黑人巨大精品欧美一区二区| 久久久亚洲国产天美传媒修理工| 性欧美xxxx视频在线观看| 激情久久五月| 欧美激情亚洲国产| 欧美三日本三级少妇三2023| 亚洲男人第一网站| 欧美一区综合|