Model_md3.cpp (10740B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #pragma hdrstop 30 #include "../idlib/precompiled.h" 31 32 #include "tr_local.h" 33 #include "Model_local.h" 34 #include "Model_md3.h" 35 36 /*********************************************************************** 37 38 idMD3Mesh 39 40 ***********************************************************************/ 41 42 #define LL(x) x=LittleLong(x) 43 44 /* 45 ================= 46 idRenderModelMD3::InitFromFile 47 ================= 48 */ 49 void idRenderModelMD3::InitFromFile( const char *fileName ) { 50 int i, j; 51 md3Header_t *pinmodel; 52 md3Frame_t *frame; 53 md3Surface_t *surf; 54 md3Shader_t *shader; 55 md3Triangle_t *tri; 56 md3St_t *st; 57 md3XyzNormal_t *xyz; 58 md3Tag_t *tag; 59 void *buffer; 60 int version; 61 int size; 62 63 64 name = fileName; 65 66 size = fileSystem->ReadFile( fileName, &buffer, NULL ); 67 if (!size || size<0 ) { 68 return; 69 } 70 71 pinmodel = (md3Header_t *)buffer; 72 73 version = LittleLong (pinmodel->version); 74 if (version != MD3_VERSION) { 75 fileSystem->FreeFile( buffer ); 76 common->Warning( "InitFromFile: %s has wrong version (%i should be %i)", 77 fileName, version, MD3_VERSION); 78 return; 79 } 80 81 size = LittleLong(pinmodel->ofsEnd); 82 dataSize += size; 83 md3 = (md3Header_t *)Mem_Alloc( size, TAG_MODEL ); 84 85 memcpy (md3, buffer, LittleLong(pinmodel->ofsEnd) ); 86 87 LL(md3->ident); 88 LL(md3->version); 89 LL(md3->numFrames); 90 LL(md3->numTags); 91 LL(md3->numSurfaces); 92 LL(md3->ofsFrames); 93 LL(md3->ofsTags); 94 LL(md3->ofsSurfaces); 95 LL(md3->ofsEnd); 96 97 if ( md3->numFrames < 1 ) { 98 common->Warning( "InitFromFile: %s has no frames", fileName ); 99 fileSystem->FreeFile( buffer ); 100 return; 101 } 102 103 // swap all the frames 104 frame = (md3Frame_t *) ( (byte *)md3 + md3->ofsFrames ); 105 for ( i = 0 ; i < md3->numFrames ; i++, frame++) { 106 frame->radius = LittleFloat( frame->radius ); 107 for ( j = 0 ; j < 3 ; j++ ) { 108 frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); 109 frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); 110 frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); 111 } 112 } 113 114 // swap all the tags 115 tag = (md3Tag_t *) ( (byte *)md3 + md3->ofsTags ); 116 for ( i = 0 ; i < md3->numTags * md3->numFrames ; i++, tag++) { 117 for ( j = 0 ; j < 3 ; j++ ) { 118 tag->origin[j] = LittleFloat( tag->origin[j] ); 119 tag->axis[0][j] = LittleFloat( tag->axis[0][j] ); 120 tag->axis[1][j] = LittleFloat( tag->axis[1][j] ); 121 tag->axis[2][j] = LittleFloat( tag->axis[2][j] ); 122 } 123 } 124 125 // swap all the surfaces 126 surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces ); 127 for ( i = 0 ; i < md3->numSurfaces ; i++) { 128 129 LL(surf->ident); 130 LL(surf->flags); 131 LL(surf->numFrames); 132 LL(surf->numShaders); 133 LL(surf->numTriangles); 134 LL(surf->ofsTriangles); 135 LL(surf->numVerts); 136 LL(surf->ofsShaders); 137 LL(surf->ofsSt); 138 LL(surf->ofsXyzNormals); 139 LL(surf->ofsEnd); 140 141 if ( surf->numVerts > SHADER_MAX_VERTEXES ) { 142 common->Error( "InitFromFile: %s has more than %i verts on a surface (%i)", 143 fileName, SHADER_MAX_VERTEXES, surf->numVerts ); 144 } 145 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { 146 common->Error( "InitFromFile: %s has more than %i triangles on a surface (%i)", 147 fileName, SHADER_MAX_INDEXES / 3, surf->numTriangles ); 148 } 149 150 // change to surface identifier 151 surf->ident = 0; //SF_MD3; 152 153 // lowercase the surface name so skin compares are faster 154 int slen = (int)strlen( surf->name ); 155 for( j = 0; j < slen; j++ ) { 156 surf->name[j] = tolower( surf->name[j] ); 157 } 158 159 // strip off a trailing _1 or _2 160 // this is a crutch for q3data being a mess 161 j = strlen( surf->name ); 162 if ( j > 2 && surf->name[j-2] == '_' ) { 163 surf->name[j-2] = 0; 164 } 165 166 // register the shaders 167 shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); 168 for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) { 169 const idMaterial *sh; 170 171 sh = declManager->FindMaterial( shader->name ); 172 shader->shader = sh; 173 } 174 175 // swap all the triangles 176 tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); 177 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { 178 LL(tri->indexes[0]); 179 LL(tri->indexes[1]); 180 LL(tri->indexes[2]); 181 } 182 183 // swap all the ST 184 st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); 185 for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { 186 st->st[0] = LittleFloat( st->st[0] ); 187 st->st[1] = LittleFloat( st->st[1] ); 188 } 189 190 // swap all the XyzNormals 191 xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); 192 for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) 193 { 194 xyz->xyz[0] = LittleShort( xyz->xyz[0] ); 195 xyz->xyz[1] = LittleShort( xyz->xyz[1] ); 196 xyz->xyz[2] = LittleShort( xyz->xyz[2] ); 197 198 xyz->normal = LittleShort( xyz->normal ); 199 } 200 201 202 // find the next surface 203 surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); 204 } 205 206 fileSystem->FreeFile( buffer ); 207 } 208 209 /* 210 ================= 211 idRenderModelMD3::IsDynamicModel 212 ================= 213 */ 214 dynamicModel_t idRenderModelMD3::IsDynamicModel() const { 215 return DM_CACHED; 216 } 217 218 /* 219 ================= 220 idRenderModelMD3::LerpMeshVertexes 221 ================= 222 */ 223 void idRenderModelMD3::LerpMeshVertexes ( srfTriangles_t *tri, const struct md3Surface_s *surf, const float backlerp, const int frame, const int oldframe ) const { 224 short *oldXyz, *newXyz; 225 float oldXyzScale, newXyzScale; 226 int vertNum; 227 int numVerts; 228 229 newXyz = (short *)((byte *)surf + surf->ofsXyzNormals) + (frame * surf->numVerts * 4); 230 231 newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp); 232 233 numVerts = surf->numVerts; 234 235 if ( backlerp == 0 ) { 236 // 237 // just copy the vertexes 238 // 239 for (vertNum=0 ; vertNum < numVerts ; vertNum++, newXyz += 4 ) { 240 241 idDrawVert *outvert = &tri->verts[tri->numVerts]; 242 243 outvert->xyz.x = newXyz[0] * newXyzScale; 244 outvert->xyz.y = newXyz[1] * newXyzScale; 245 outvert->xyz.z = newXyz[2] * newXyzScale; 246 247 tri->numVerts++; 248 } 249 } else { 250 // 251 // interpolate and copy the vertexes 252 // 253 oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals) + (oldframe * surf->numVerts * 4); 254 255 oldXyzScale = MD3_XYZ_SCALE * backlerp; 256 257 for (vertNum=0 ; vertNum < numVerts ; vertNum++, oldXyz += 4, newXyz += 4 ) { 258 259 idDrawVert *outvert = &tri->verts[tri->numVerts]; 260 261 // interpolate the xyz 262 outvert->xyz.x = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale; 263 outvert->xyz.y = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale; 264 outvert->xyz.z = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale; 265 266 tri->numVerts++; 267 } 268 } 269 } 270 271 /* 272 ============= 273 idRenderModelMD3::InstantiateDynamicModel 274 ============= 275 */ 276 idRenderModel *idRenderModelMD3::InstantiateDynamicModel( const struct renderEntity_s *ent, const viewDef_t *view, idRenderModel *cachedModel ) { 277 int i, j; 278 float backlerp; 279 int * triangles; 280 int indexes; 281 int numVerts; 282 md3Surface_t * surface; 283 int frame, oldframe; 284 idRenderModelStatic *staticModel; 285 286 if ( cachedModel ) { 287 delete cachedModel; 288 cachedModel = NULL; 289 } 290 291 staticModel = new (TAG_MODEL) idRenderModelStatic; 292 staticModel->bounds.Clear(); 293 294 surface = (md3Surface_t *) ((byte *)md3 + md3->ofsSurfaces); 295 296 // TODO: these need set by an entity 297 frame = ent->shaderParms[SHADERPARM_MD3_FRAME]; // probably want to keep frames < 1000 or so 298 oldframe = ent->shaderParms[SHADERPARM_MD3_LASTFRAME]; 299 backlerp = ent->shaderParms[SHADERPARM_MD3_BACKLERP]; 300 301 for( i = 0; i < md3->numSurfaces; i++ ) { 302 303 srfTriangles_t *tri = R_AllocStaticTriSurf(); 304 R_AllocStaticTriSurfVerts( tri, surface->numVerts ); 305 R_AllocStaticTriSurfIndexes( tri, surface->numTriangles * 3 ); 306 tri->bounds.Clear(); 307 308 modelSurface_t surf; 309 310 surf.geometry = tri; 311 312 md3Shader_t* shaders = (md3Shader_t *) ((byte *)surface + surface->ofsShaders); 313 surf.shader = shaders->shader; 314 315 LerpMeshVertexes( tri, surface, backlerp, frame, oldframe ); 316 317 triangles = (int *) ((byte *)surface + surface->ofsTriangles); 318 indexes = surface->numTriangles * 3; 319 for (j = 0 ; j < indexes ; j++) { 320 tri->indexes[j] = triangles[j]; 321 } 322 tri->numIndexes += indexes; 323 324 const idVec2 * texCoords = (idVec2 *) ((byte *)surface + surface->ofsSt); 325 326 numVerts = surface->numVerts; 327 for ( j = 0; j < numVerts; j++ ) { 328 tri->verts[j].SetTexCoord( texCoords[j] ); 329 } 330 331 R_BoundTriSurf( tri ); 332 333 staticModel->AddSurface( surf ); 334 staticModel->bounds.AddPoint( surf.geometry->bounds[0] ); 335 staticModel->bounds.AddPoint( surf.geometry->bounds[1] ); 336 337 // find the next surface 338 surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd ); 339 } 340 341 return staticModel; 342 } 343 344 /* 345 ===================== 346 idRenderModelMD3::Bounds 347 ===================== 348 */ 349 350 idBounds idRenderModelMD3::Bounds(const struct renderEntity_s *ent) const { 351 idBounds ret; 352 353 ret.Clear(); 354 355 if (!ent || !md3) { 356 // just give it the editor bounds 357 ret.AddPoint(idVec3(-10,-10,-10)); 358 ret.AddPoint(idVec3( 10, 10, 10)); 359 return ret; 360 } 361 362 md3Frame_t *frame = (md3Frame_t *)( (byte *)md3 + md3->ofsFrames ); 363 364 ret.AddPoint( frame->bounds[0] ); 365 ret.AddPoint( frame->bounds[1] ); 366 367 return ret; 368 } 369