DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

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