r_model_alias.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1997-2001 Id Software, Inc.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "r_local.h"
00027 #include "../../shared/parse.h"
00028 #include "r_state.h"
00029 
00030 /*
00031 ==============================================================================
00032 ALIAS MODELS
00033 ==============================================================================
00034 */
00035 
00036 void R_ModLoadAnims (mAliasModel_t *mod, void *buffer)
00037 {
00038     const char *text, *token;
00039     mAliasAnim_t *anim;
00040     int n;
00041 
00042     for (n = 0, text = buffer; text; n++)
00043         Com_Parse(&text);
00044     n /= 4;
00045     if (n > MAX_ANIMS)
00046         n = MAX_ANIMS;
00047 
00048     mod->animdata = (mAliasAnim_t *) Mem_PoolAlloc(n * sizeof(*mod->animdata), vid_modelPool, 0);
00049     anim = mod->animdata;
00050     text = buffer;
00051     mod->num_anims = 0;
00052 
00053     do {
00054         /* get the name */
00055         token = Com_Parse(&text);
00056         if (!text)
00057             break;
00058         Q_strncpyz(anim->name, token, sizeof(anim->name));
00059 
00060         /* get the start */
00061         token = Com_Parse(&text);
00062         if (!text)
00063             break;
00064         anim->from = atoi(token);
00065         if (anim->from < 0)
00066             Com_Error(ERR_FATAL, "R_ModLoadAnims: negative start frame for %s", mod->animname);
00067         else if (anim->from > mod->num_frames)
00068             Com_Error(ERR_FATAL, "R_ModLoadAnims: start frame is higher than models frame count (%i) (model: %s)",
00069                     mod->num_frames, mod->animname);
00070 
00071         /* get the end */
00072         token = Com_Parse(&text);
00073         if (!text)
00074             break;
00075         anim->to = atoi(token);
00076         if (anim->to < 0)
00077             Com_Error(ERR_FATAL, "R_ModLoadAnims: negative start frame for %s", mod->animname);
00078         else if (anim->to > mod->num_frames)
00079             Com_Error(ERR_FATAL, "R_ModLoadAnims: end frame is higher than models frame count (%i) (model: %s)",
00080                     mod->num_frames, mod->animname);
00081 
00082         /* get the fps */
00083         token = Com_Parse(&text);
00084         if (!text)
00085             break;
00086         anim->time = (atof(token) > 0.01) ? (1000.0 / atof(token)) : (1000.0 / 0.01);
00087 
00088         /* add it */
00089         mod->num_anims++;
00090         anim++;
00091     } while (mod->num_anims < MAX_ANIMS);
00092 }
00093 
00094 
00103 static void R_ModCalcNormalsAndTangents (mAliasMesh_t *mesh, int framenum, const vec3_t translate, qboolean backlerp)
00104 {
00105     int i, j;
00106     mAliasVertex_t *vertexes = &mesh->vertexes[framenum * mesh->num_verts];
00107     mAliasCoord_t *stcoords = mesh->stcoords;
00108     const int numIndexes = mesh->num_tris * 3;
00109     const int32_t *indexArray = mesh->indexes;
00110     vec3_t triangleNormals[MAX_ALIAS_TRIS];
00111     vec3_t triangleTangents[MAX_ALIAS_TRIS];
00112     vec3_t triangleBitangents[MAX_ALIAS_TRIS];
00113     float *texcoords, *verts, *normals, *tangents;
00114 
00115     /* set up array pointers for either the previous keyframe or the next keyframe */
00116     texcoords = mesh->texcoords;
00117     if (backlerp) {
00118         verts = mesh->verts;
00119         normals = mesh->normals;
00120         tangents = mesh->tangents;
00121     } else {
00122         verts = mesh->next_verts;
00123         normals = mesh->next_normals;
00124         tangents = mesh->next_tangents;
00125     }
00126 
00127     /* calculate per-triangle surface normals and tangents*/
00128     for (i = 0, j = 0; i < numIndexes; i += 3, j++) {
00129         vec3_t dir1, dir2;
00130         vec2_t dir1uv, dir2uv;
00131 
00132         /* calculate two mostly perpendicular edge directions */
00133         VectorSubtract(vertexes[indexArray[i + 0]].point, vertexes[indexArray[i + 1]].point, dir1);
00134         VectorSubtract(vertexes[indexArray[i + 2]].point, vertexes[indexArray[i + 1]].point, dir2);
00135         Vector2Subtract(stcoords[indexArray[i + 0]], stcoords[indexArray[i + 1]], dir1uv);
00136         Vector2Subtract(stcoords[indexArray[i + 2]], stcoords[indexArray[i + 1]], dir2uv);
00137 
00138         /* we have two edge directions, we can calculate a third vector from
00139          * them, which is the direction of the surface normal */
00140         CrossProduct(dir1, dir2, triangleNormals[j]);
00141         /* normalize */
00142         VectorNormalize(triangleNormals[j]);
00143 
00144         /* then we use the texture coordinates to calculate a tangent space */
00145         if ((dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]) != 0.0) {
00146             const float frac = 1.0 / (dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]);
00147             vec3_t tmp1, tmp2;
00148 
00149             /* calculate tangent */
00150             VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
00151             VectorMul(dir1uv[1] * frac, dir2, tmp2);
00152             VectorAdd(tmp1, tmp2, triangleTangents[j]);
00153 
00154             /* calculate bitangent */
00155             VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
00156             VectorMul(dir1uv[0] * frac, dir2, tmp2);
00157             VectorAdd(tmp1, tmp2, triangleBitangents[j]);
00158 
00159             /* normalize */
00160             VectorNormalize(triangleTangents[j]);
00161             VectorNormalize(triangleBitangents[j]);
00162         } else {
00163             VectorClear(triangleTangents[j]);
00164             VectorClear(triangleBitangents[j]);
00165         }
00166     }
00167 
00168     /* for each vertex */
00169     for (i = 0; i < mesh->num_verts; i++) {
00170         vec3_t n, b, v;
00171         vec4_t t;
00172         const int len = mesh->revIndexes[i].length;
00173         const int32_t *list = mesh->revIndexes[i].list;
00174 
00175         VectorClear(n);
00176         VectorClear(t);
00177         VectorClear(b);
00178 
00179         /* for each vertex that got mapped to this one (ie. for each triangle this vertex is a part of) */
00180         for (j = 0; j < len; j++) {
00181             const int32_t idx = list[j] / 3;
00182             VectorAdd(n, triangleNormals[idx], n);
00183             VectorAdd(t, triangleTangents[idx], t);
00184             VectorAdd(b, triangleBitangents[idx], b);
00185         }
00186 
00187         /* normalization here does shared-vertex smoothing */
00188         VectorNormalize(n);
00189         VectorNormalize(t);
00190         VectorNormalize(b);
00191 
00192         /* Grahm-Schmidt orthogonalization */
00193         Orthogonalize(t, n);
00194 
00195         /* calculate handedness */
00196         CrossProduct(n, t, v);
00197         t[3] = (DotProduct(v, b) < 0.0) ? -1.0 : 1.0;
00198 
00199         /* copy this vertex's info to all the right places in the arrays */
00200         for (j = 0; j < len; j++) {
00201             const int32_t idx = list[j];
00202             const int meshIndex = mesh->indexes[list[j]];
00203             Vector2Copy(stcoords[meshIndex], (texcoords + (2 * idx)));
00204             VectorAdd(vertexes[meshIndex].point, translate, (verts + (3 * idx)));
00205             VectorCopy(n, (normals + (3 * idx)));
00206             Vector4Copy(t, (tangents + (4 * idx)));
00207         }
00208     }
00209 }
00210 
00217 qboolean R_ModLoadMDX (model_t *mod)
00218 {
00219     int i;
00220     for (i = 0; i < mod->alias.num_meshes; i++) {
00221         mAliasMesh_t *mesh = &mod->alias.meshes[i];
00222         char mdxFileName[MAX_QPATH];
00223         byte *buffer = NULL, *buf;
00224         const int32_t *intbuf;
00225         int32_t numIndexes;
00226         uint32_t version;
00227         int sharedTris[MAX_ALIAS_VERTS];
00228 
00229         Com_StripExtension(mod->name, mdxFileName, sizeof(mdxFileName));
00230         Com_DefaultExtension(mdxFileName, sizeof(mdxFileName), ".mdx");
00231 
00232         if (FS_LoadFile(mdxFileName, &buffer) == -1)
00233             return qfalse;
00234 
00235         buf = buffer;
00236         if (strncmp((const char *) buf, IDMDXHEADER, strlen(IDMDXHEADER)))
00237             Com_Error(ERR_DROP, "No mdx file buffer given");
00238         buffer += strlen(IDMDXHEADER) * sizeof(char);
00239         version = LittleLong(*(uint32_t*) buffer);
00240         if (version != MDX_VERSION)
00241             Com_Error(ERR_DROP, "Invalid version of the mdx file, expected %i, found %i",
00242                     MDX_VERSION, version);
00243         buffer += sizeof(uint32_t);
00244 
00245         intbuf = (const int32_t *) buffer;
00246 
00247         mesh->num_verts = LittleLong(*intbuf);
00248         if (mesh->num_verts <= 0 || mesh->num_verts > MAX_ALIAS_VERTS)
00249             Com_Error(ERR_DROP, "mdx file for %s has to many (or no) vertices: %i", mod->name, mesh->num_verts);
00250         intbuf++;
00251         numIndexes = LittleLong(*intbuf);
00252         intbuf++;
00253 
00254         mesh->indexes = Mem_PoolAlloc(sizeof(int32_t) * numIndexes, vid_modelPool, 0);
00255         mesh->revIndexes = Mem_PoolAlloc(sizeof(mIndexList_t) * mesh->num_verts, vid_modelPool, 0);
00256         mesh->vertexes = Mem_PoolAlloc(sizeof(mAliasVertex_t) * mod->alias.num_frames * mesh->num_verts, vid_modelPool, 0);
00257 
00258         /* load index that maps triangle verts to Vertex objects */
00259         for (i = 0; i < numIndexes; i++) {
00260             mesh->indexes[i] = LittleLong(*intbuf);
00261             intbuf++;
00262         }
00263 
00264         for (i = 0; i < mesh->num_verts; i++)
00265             sharedTris[i] = 0;
00266 
00267         /* set up reverse-index that maps Vertex objects to a list of triangle verts */
00268         for (i = 0; i < numIndexes; i++)
00269             sharedTris[mesh->indexes[i]]++;
00270 
00271         for (i = 0; i < mesh->num_verts; i++) {
00272             mesh->revIndexes[i].length = 0;
00273             mesh->revIndexes[i].list = Mem_PoolAlloc(sizeof(int32_t) * sharedTris[i], vid_modelPool, 0);
00274         }
00275 
00276         for (i = 0; i < numIndexes; i++)
00277             mesh->revIndexes[mesh->indexes[i]].list[mesh->revIndexes[mesh->indexes[i]].length++] = i;
00278 
00279         FS_FreeFile(buf);
00280     }
00281 
00282     return qtrue;
00283 }
00284 
00292 void R_ModCalcUniqueNormalsAndTangents (mAliasMesh_t *mesh, int nFrames, float smoothness)
00293 {
00294     int i, j;
00295     vec3_t triangleNormals[MAX_ALIAS_TRIS];
00296     vec3_t triangleTangents[MAX_ALIAS_TRIS];
00297     vec3_t triangleBitangents[MAX_ALIAS_TRIS];
00298     const mAliasVertex_t *vertexes = mesh->vertexes;
00299     mAliasCoord_t *stcoords = mesh->stcoords;
00300     mAliasVertex_t *newVertexes;
00301     mAliasComplexVertex_t tmpVertexes[MAX_ALIAS_VERTS];
00302     vec3_t tmpBitangents[MAX_ALIAS_VERTS];
00303     mAliasCoord_t *newStcoords;
00304     const int numIndexes = mesh->num_tris * 3;
00305     const int32_t *indexArray = mesh->indexes;
00306     int32_t *newIndexArray;
00307     int indRemap[MAX_ALIAS_VERTS];
00308     int sharedTris[MAX_ALIAS_VERTS];
00309     int numVerts = 0;
00310 
00311     newIndexArray = Mem_PoolAlloc(sizeof(int32_t) * numIndexes, vid_modelPool, 0);
00312 
00313     /* calculate per-triangle surface normals */
00314     for (i = 0, j = 0; i < numIndexes; i += 3, j++) {
00315         vec3_t dir1, dir2;
00316         vec2_t dir1uv, dir2uv;
00317 
00318         /* calculate two mostly perpendicular edge directions */
00319         VectorSubtract(vertexes[indexArray[i + 0]].point, vertexes[indexArray[i + 1]].point, dir1);
00320         VectorSubtract(vertexes[indexArray[i + 2]].point, vertexes[indexArray[i + 1]].point, dir2);
00321         Vector2Subtract(stcoords[indexArray[i + 0]], stcoords[indexArray[i + 1]], dir1uv);
00322         Vector2Subtract(stcoords[indexArray[i + 2]], stcoords[indexArray[i + 1]], dir2uv);
00323 
00324         /* we have two edge directions, we can calculate a third vector from
00325          * them, which is the direction of the surface normal */
00326         CrossProduct(dir1, dir2, triangleNormals[j]);
00327 
00328         /* then we use the texture coordinates to calculate a tangent space */
00329         if ((dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]) != 0.0) {
00330             const float frac = 1.0 / (dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]);
00331             vec3_t tmp1, tmp2;
00332 
00333             /* calculate tangent */
00334             VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
00335             VectorMul(dir1uv[1] * frac, dir2, tmp2);
00336             VectorAdd(tmp1, tmp2, triangleTangents[j]);
00337 
00338             /* calculate bitangent */
00339             VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
00340             VectorMul(dir1uv[0] * frac, dir2, tmp2);
00341             VectorAdd(tmp1, tmp2, triangleBitangents[j]);
00342         } else {
00343             const float frac = 1.0 / (0.00001);
00344             vec3_t tmp1, tmp2;
00345 
00346             /* calculate tangent */
00347             VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
00348             VectorMul(dir1uv[1] * frac, dir2, tmp2);
00349             VectorAdd(tmp1, tmp2, triangleTangents[j]);
00350 
00351             /* calculate bitangent */
00352             VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
00353             VectorMul(dir1uv[0] * frac, dir2, tmp2);
00354             VectorAdd(tmp1, tmp2, triangleBitangents[j]);
00355         }
00356 
00357         /* normalize */
00358         VectorNormalize(triangleNormals[j]);
00359         VectorNormalize(triangleTangents[j]);
00360         VectorNormalize(triangleBitangents[j]);
00361 
00362         Orthogonalize(triangleTangents[j], triangleBitangents[j]);
00363     }
00364 
00365     /* do smoothing */
00366     for (i = 0; i < numIndexes; i++) {
00367         const int idx = (i - i % 3) / 3;
00368         VectorCopy(triangleNormals[idx], tmpVertexes[i].normal);
00369         VectorCopy(triangleTangents[idx], tmpVertexes[i].tangent);
00370         VectorCopy(triangleBitangents[idx], tmpBitangents[i]);
00371 
00372         for (j = 0; j < numIndexes; j++) {
00373             const int idx2 = (j - j % 3) / 3;
00374             /* don't add a vertex with itself */
00375             if (j == i)
00376                 continue;
00377 
00378             /* only average normals if vertices have the same position
00379              * and the normals aren't too far apart to start with */
00380             if (VectorEqual(vertexes[indexArray[i]].point, vertexes[indexArray[j]].point)
00381                     && DotProduct(triangleNormals[idx], triangleNormals[idx2]) > smoothness) {
00382                 /* average the normals */
00383                 VectorAdd(tmpVertexes[i].normal, triangleNormals[idx2], tmpVertexes[i].normal);
00384 
00385                 /* if the tangents match as well, average them too.
00386                  * Note that having matching normals without matching tangents happens
00387                  * when the order of vertices in two triangles sharing the vertex
00388                  * in question is different.  This happens quite frequently if the
00389                  * modeler does not go out of their way to avoid it. */
00390 
00391                 if (Vector2Equal(stcoords[indexArray[i]], stcoords[indexArray[j]])
00392                         && DotProduct(triangleTangents[idx], triangleTangents[idx2]) > smoothness
00393                         && DotProduct(triangleBitangents[idx], triangleBitangents[idx2]) > smoothness) {
00394                     /* average the tangents */
00395                     VectorAdd(tmpVertexes[i].tangent, triangleTangents[idx2], tmpVertexes[i].tangent);
00396                     VectorAdd(tmpBitangents[i], triangleBitangents[idx2], tmpBitangents[i]);
00397                 }
00398             }
00399         }
00400 
00401         VectorNormalize(tmpVertexes[i].normal);
00402         VectorNormalize(tmpVertexes[i].tangent);
00403         VectorNormalize(tmpBitangents[i]);
00404     }
00405 
00406     /* assume all vertices are unique until proven otherwise */
00407     for (i = 0; i < numIndexes; i++)
00408         indRemap[i] = -1;
00409 
00410     /* merge vertices that have become identical */
00411     for (i = 0; i < numIndexes; i++) {
00412         vec3_t n, b, t, v;
00413         if (indRemap[i] != -1)
00414             continue;
00415 
00416         for (j = i + 1; j < numIndexes; j++) {
00417             if (Vector2Equal(stcoords[indexArray[i]], stcoords[indexArray[j]])
00418                     && VectorEqual(vertexes[indexArray[i]].point, vertexes[indexArray[j]].point)
00419                     && (DotProduct(tmpVertexes[i].normal, tmpVertexes[j].normal) > smoothness)
00420                     && (DotProduct(tmpVertexes[i].tangent, tmpVertexes[j].tangent) > smoothness)) {
00421                 indRemap[j] = i;
00422                 newIndexArray[j] = numVerts;
00423             }
00424         }
00425 
00426         VectorCopy(tmpVertexes[i].normal, n);
00427         VectorCopy(tmpVertexes[i].tangent, t);
00428         VectorCopy(tmpBitangents[i], b);
00429 
00430         /* normalization here does shared-vertex smoothing */
00431         VectorNormalize(n);
00432         VectorNormalize(t);
00433         VectorNormalize(b);
00434 
00435         /* Grahm-Schmidt orthogonalization */
00436         VectorMul(DotProduct(t, n), n, v);
00437         VectorSubtract(t, v, t);
00438         VectorNormalize(t);
00439 
00440         /* calculate handedness */
00441         CrossProduct(n, t, v);
00442         tmpVertexes[i].tangent[3] = (DotProduct(v, b) < 0.0) ? -1.0 : 1.0;
00443         VectorCopy(n, tmpVertexes[i].normal);
00444         VectorCopy(t, tmpVertexes[i].tangent);
00445 
00446         newIndexArray[i] = numVerts++;
00447         indRemap[i] = i;
00448     }
00449 
00450     for (i = 0; i < numVerts; i++)
00451         sharedTris[i] = 0;
00452 
00453     for (i = 0; i < numIndexes; i++)
00454         sharedTris[newIndexArray[i]]++;
00455 
00456     /* set up reverse-index that maps Vertex objects to a list of triangle verts */
00457     mesh->revIndexes = Mem_PoolAlloc(sizeof(mIndexList_t) * numVerts, vid_modelPool, 0);
00458     for (i = 0; i < numVerts; i++) {
00459         mesh->revIndexes[i].length = 0;
00460         mesh->revIndexes[i].list = Mem_PoolAlloc(sizeof(int32_t) * sharedTris[i], vid_modelPool, 0);
00461     }
00462 
00463     /* merge identical vertexes, storing only unique ones */
00464     newVertexes = Mem_PoolAlloc(sizeof(mAliasVertex_t) * numVerts * nFrames, vid_modelPool, 0);
00465     newStcoords = Mem_PoolAlloc(sizeof(mAliasCoord_t) * numVerts, vid_modelPool, 0);
00466     for (i = 0; i < numIndexes; i++) {
00467         const int idx = indexArray[indRemap[i]];
00468         const int idx2 = newIndexArray[i];
00469 
00470         /* add vertex to new vertex array */
00471         VectorCopy(vertexes[idx].point, newVertexes[idx2].point);
00472         Vector2Copy(stcoords[idx], newStcoords[idx2]);
00473         mesh->revIndexes[idx2].list[mesh->revIndexes[idx2].length++] = i;
00474     }
00475 
00476     /* copy over the points from successive frames */
00477     for (i = 1; i < nFrames; i++) {
00478         for (j = 0; j < numIndexes; j++) {
00479             const int idx = indexArray[indRemap[j]] + (mesh->num_verts * i);
00480             const int idx2 = newIndexArray[j] + (numVerts * i);
00481 
00482             VectorCopy(vertexes[idx].point, newVertexes[idx2].point);
00483         }
00484     }
00485 
00486     /* copy new arrays back into original mesh */
00487     Mem_Free(mesh->stcoords);
00488     Mem_Free(mesh->indexes);
00489     Mem_Free(mesh->vertexes);
00490 
00491     mesh->num_verts = numVerts;
00492     mesh->vertexes = newVertexes;
00493     mesh->stcoords = newStcoords;
00494     mesh->indexes = newIndexArray;
00495 }
00496 
00497 
00498 image_t* R_AliasModelGetSkin (const char *modelFileName, const char *skin)
00499 {
00500     if (skin[0] != '.')
00501         return R_FindImage(skin, it_skin);
00502     else {
00503         char path[MAX_QPATH];
00504         Com_ReplaceFilename(modelFileName, skin, path, sizeof(path));
00505         return R_FindImage(path, it_skin);
00506     }
00507 }
00508 
00509 image_t* R_AliasModelState (const model_t *mod, int *mesh, int *frame, int *oldFrame, int *skin)
00510 {
00511     /* check animations */
00512     if ((*frame >= mod->alias.num_frames) || *frame < 0) {
00513         Com_Printf("R_AliasModelState %s: no such frame %d (# %i)\n", mod->name, *frame, mod->alias.num_frames);
00514         *frame = 0;
00515     }
00516     if ((*oldFrame >= mod->alias.num_frames) || *oldFrame < 0) {
00517         Com_Printf("R_AliasModelState %s: no such oldframe %d (# %i)\n", mod->name, *oldFrame, mod->alias.num_frames);
00518         *oldFrame = 0;
00519     }
00520 
00521     if (*mesh < 0 || *mesh >= mod->alias.num_meshes)
00522         *mesh = 0;
00523 
00524     if (!mod->alias.meshes)
00525         return NULL;
00526 
00527     /* use default skin - this is never null - but maybe the placeholder texture */
00528     if (*skin < 0 || *skin >= mod->alias.meshes[*mesh].num_skins)
00529         *skin = 0;
00530 
00531     if (!mod->alias.meshes[*mesh].num_skins)
00532         Com_Error(ERR_DROP, "Model with no skins");
00533 
00534     if (mod->alias.meshes[*mesh].skins[*skin].skin->texnum <= 0)
00535         Com_Error(ERR_DROP, "Texture is already freed and no longer uploaded, texnum is invalid for model %s",
00536                 mod->name);
00537 
00538     return mod->alias.meshes[*mesh].skins[*skin].skin;
00539 }
00540 
00554 void R_FillArrayData (mAliasModel_t* mod, mAliasMesh_t *mesh, float backlerp, int framenum, int oldframenum, qboolean prerender)
00555 {
00556     const mAliasFrame_t *frame, *oldframe;
00557     vec3_t move;
00558     const float frontlerp = 1.0 - backlerp;
00559     vec3_t r_mesh_verts[MAX_ALIAS_VERTS];
00560     vec_t *texcoord_array, *vertex_array_3d;
00561 
00562     frame = mod->frames + framenum;
00563     oldframe = mod->frames + oldframenum;
00564 
00565     /* try to do keyframe-interpolation on the GPU if possible*/
00566     if (r_state.lighting_enabled) {
00567         /* we only need to change the array data if we've switched to a new keyframe */
00568         if (mod->curFrame != framenum) {
00569             /* if we're rendering frames in order, the "next" keyframe from the previous
00570              * time through will be our "previous" keyframe now, so we can swap pointers
00571              * instead of generating it again from scratch */
00572             if (mod->curFrame == oldframenum) {
00573                 vec_t *tmp1 = mesh->verts;
00574                 vec_t *tmp2 = mesh->normals;
00575                 vec_t *tmp3 = mesh->tangents;
00576 
00577                 mesh->verts = mesh->next_verts;
00578                 mesh->next_verts = tmp1;
00579 
00580                 mesh->normals = mesh->next_normals;
00581                 mesh->next_normals = tmp2;
00582 
00583                 mesh->tangents = mesh->next_tangents;
00584                 mesh->next_tangents = tmp3;
00585 
00586                 /* if we're alternating between two keyframes, we don't need to generate
00587                  * anything; otherwise, generate the "next" keyframe*/
00588                 if (mod->oldFrame != framenum)
00589                     R_ModCalcNormalsAndTangents(mesh, framenum, frame->translate, qfalse);
00590             } else {
00591                 /* if we're starting a new animation or otherwise not rendering keyframes
00592                  * in order, we need to fill the arrays for both keyframes */
00593                 R_ModCalcNormalsAndTangents(mesh, oldframenum, oldframe->translate, qtrue);
00594                 R_ModCalcNormalsAndTangents(mesh, framenum, frame->translate, qfalse);
00595             }
00596             /* keep track of which keyframes are currently stored in our arrays */
00597             mod->oldFrame = oldframenum;
00598             mod->curFrame = framenum;
00599         }
00600     } else { /* otherwise, we have to do it on the CPU */
00601         const mAliasVertex_t *v, *ov;
00602         int i;
00603         assert(mesh->num_verts < lengthof(r_mesh_verts));
00604         v = &mesh->vertexes[framenum * mesh->num_verts];
00605         ov = &mesh->vertexes[oldframenum * mesh->num_verts];
00606 
00607         if (prerender)
00608             R_ModCalcNormalsAndTangents(mesh, 0, oldframe->translate, qtrue);
00609 
00610         for (i = 0; i < 3; i++)
00611             move[i] = backlerp * oldframe->translate[i] + frontlerp * frame->translate[i];
00612 
00613         for (i = 0; i < mesh->num_verts; i++, v++, ov++) {  /* lerp the verts */
00614             VectorSet(r_mesh_verts[i],
00615                     move[0] + ov->point[0] * backlerp + v->point[0] * frontlerp,
00616                     move[1] + ov->point[1] * backlerp + v->point[1] * frontlerp,
00617                     move[2] + ov->point[2] * backlerp + v->point[2] * frontlerp);
00618         }
00619 
00620         texcoord_array = texunit_diffuse.texcoord_array;
00621         vertex_array_3d = r_state.vertex_array_3d;
00622 
00624         for (i = 0; i < mesh->num_tris; i++) {  /* draw the tris */
00625             int j;
00626             for (j = 0; j < 3; j++) {
00627                 const int arrayIndex = 3 * i + j;
00628                 const int meshIndex = mesh->indexes[arrayIndex];
00629                 Vector2Copy(mesh->stcoords[meshIndex], texcoord_array);
00630                 VectorCopy(r_mesh_verts[meshIndex], vertex_array_3d);
00631 
00632                 texcoord_array += 2;
00633                 vertex_array_3d += 3;
00634             }
00635         }
00636     }
00637 }
00638 
00642 void R_ModLoadArrayData (mAliasModel_t *mod, mAliasMesh_t *mesh, qboolean loadNormals)
00643 {
00644     const int v = mesh->num_tris * 3 * 3;
00645     const int t = mesh->num_tris * 3 * 4;
00646     const int st = mesh->num_tris * 3 * 2;
00647 
00648     assert(mesh->verts == NULL);
00649     assert(mesh->texcoords == NULL);
00650     assert(mesh->normals == NULL);
00651     assert(mesh->tangents == NULL);
00652     assert(mesh->next_verts == NULL);
00653     assert(mesh->next_normals == NULL);
00654     assert(mesh->next_tangents == NULL);
00655 
00656     mesh->verts = (float *)Mem_PoolAlloc(sizeof(float) * v, vid_modelPool, 0);
00657     mesh->normals = (float *)Mem_PoolAlloc(sizeof(float) * v, vid_modelPool, 0);
00658     mesh->tangents = (float *)Mem_PoolAlloc(sizeof(float) * t, vid_modelPool, 0);
00659     mesh->texcoords = (float *)Mem_PoolAlloc(sizeof(float) * st, vid_modelPool, 0);
00660     if (mod->num_frames == 1) {
00661         R_FillArrayData(mod, mesh, 0.0, 0, 0, loadNormals);
00662     } else {
00663         mesh->next_verts = (float *)Mem_PoolAlloc(sizeof(float) * v, vid_modelPool, 0);
00664         mesh->next_normals = (float *)Mem_PoolAlloc(sizeof(float) * v, vid_modelPool, 0);
00665         mesh->next_tangents = (float *)Mem_PoolAlloc(sizeof(float) * t, vid_modelPool, 0);
00666 
00667         mod->curFrame = -1;
00668         mod->oldFrame = -1;
00669     }
00670 }

Generated by  doxygen 1.6.2