123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- 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.
- 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.
- ===========================================================================
- */
- #pragma hdrstop
- #include "../idlib/precompiled.h"
- #include "tr_local.h"
- #include "Model_local.h"
- #include "Model_md3.h"
- /***********************************************************************
- idMD3Mesh
- ***********************************************************************/
- #define LL(x) x=LittleLong(x)
- /*
- =================
- idRenderModelMD3::InitFromFile
- =================
- */
- void idRenderModelMD3::InitFromFile( const char *fileName ) {
- int i, j;
- md3Header_t *pinmodel;
- md3Frame_t *frame;
- md3Surface_t *surf;
- md3Shader_t *shader;
- md3Triangle_t *tri;
- md3St_t *st;
- md3XyzNormal_t *xyz;
- md3Tag_t *tag;
- void *buffer;
- int version;
- int size;
- name = fileName;
- size = fileSystem->ReadFile( fileName, &buffer, NULL );
- if (!size || size<0 ) {
- return;
- }
- pinmodel = (md3Header_t *)buffer;
- version = LittleLong (pinmodel->version);
- if (version != MD3_VERSION) {
- fileSystem->FreeFile( buffer );
- common->Warning( "InitFromFile: %s has wrong version (%i should be %i)",
- fileName, version, MD3_VERSION);
- return;
- }
- size = LittleLong(pinmodel->ofsEnd);
- dataSize += size;
- md3 = (md3Header_t *)Mem_Alloc( size, TAG_MODEL );
- memcpy (md3, buffer, LittleLong(pinmodel->ofsEnd) );
- LL(md3->ident);
- LL(md3->version);
- LL(md3->numFrames);
- LL(md3->numTags);
- LL(md3->numSurfaces);
- LL(md3->ofsFrames);
- LL(md3->ofsTags);
- LL(md3->ofsSurfaces);
- LL(md3->ofsEnd);
- if ( md3->numFrames < 1 ) {
- common->Warning( "InitFromFile: %s has no frames", fileName );
- fileSystem->FreeFile( buffer );
- return;
- }
-
- // swap all the frames
- frame = (md3Frame_t *) ( (byte *)md3 + md3->ofsFrames );
- for ( i = 0 ; i < md3->numFrames ; i++, frame++) {
- frame->radius = LittleFloat( frame->radius );
- for ( j = 0 ; j < 3 ; j++ ) {
- frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
- frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
- frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
- }
- }
- // swap all the tags
- tag = (md3Tag_t *) ( (byte *)md3 + md3->ofsTags );
- for ( i = 0 ; i < md3->numTags * md3->numFrames ; i++, tag++) {
- for ( j = 0 ; j < 3 ; j++ ) {
- tag->origin[j] = LittleFloat( tag->origin[j] );
- tag->axis[0][j] = LittleFloat( tag->axis[0][j] );
- tag->axis[1][j] = LittleFloat( tag->axis[1][j] );
- tag->axis[2][j] = LittleFloat( tag->axis[2][j] );
- }
- }
- // swap all the surfaces
- surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces );
- for ( i = 0 ; i < md3->numSurfaces ; i++) {
- LL(surf->ident);
- LL(surf->flags);
- LL(surf->numFrames);
- LL(surf->numShaders);
- LL(surf->numTriangles);
- LL(surf->ofsTriangles);
- LL(surf->numVerts);
- LL(surf->ofsShaders);
- LL(surf->ofsSt);
- LL(surf->ofsXyzNormals);
- LL(surf->ofsEnd);
-
- if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
- common->Error( "InitFromFile: %s has more than %i verts on a surface (%i)",
- fileName, SHADER_MAX_VERTEXES, surf->numVerts );
- }
- if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
- common->Error( "InitFromFile: %s has more than %i triangles on a surface (%i)",
- fileName, SHADER_MAX_INDEXES / 3, surf->numTriangles );
- }
-
- // change to surface identifier
- surf->ident = 0; //SF_MD3;
- // lowercase the surface name so skin compares are faster
- int slen = (int)strlen( surf->name );
- for( j = 0; j < slen; j++ ) {
- surf->name[j] = tolower( surf->name[j] );
- }
- // strip off a trailing _1 or _2
- // this is a crutch for q3data being a mess
- j = strlen( surf->name );
- if ( j > 2 && surf->name[j-2] == '_' ) {
- surf->name[j-2] = 0;
- }
- // register the shaders
- shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
- for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) {
- const idMaterial *sh;
- sh = declManager->FindMaterial( shader->name );
- shader->shader = sh;
- }
- // swap all the triangles
- tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
- for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
- LL(tri->indexes[0]);
- LL(tri->indexes[1]);
- LL(tri->indexes[2]);
- }
- // swap all the ST
- st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
- for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
- st->st[0] = LittleFloat( st->st[0] );
- st->st[1] = LittleFloat( st->st[1] );
- }
- // swap all the XyzNormals
- xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
- for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )
- {
- xyz->xyz[0] = LittleShort( xyz->xyz[0] );
- xyz->xyz[1] = LittleShort( xyz->xyz[1] );
- xyz->xyz[2] = LittleShort( xyz->xyz[2] );
- xyz->normal = LittleShort( xyz->normal );
- }
- // find the next surface
- surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
- }
-
- fileSystem->FreeFile( buffer );
- }
- /*
- =================
- idRenderModelMD3::IsDynamicModel
- =================
- */
- dynamicModel_t idRenderModelMD3::IsDynamicModel() const {
- return DM_CACHED;
- }
- /*
- =================
- idRenderModelMD3::LerpMeshVertexes
- =================
- */
- void idRenderModelMD3::LerpMeshVertexes ( srfTriangles_t *tri, const struct md3Surface_s *surf, const float backlerp, const int frame, const int oldframe ) const {
- short *oldXyz, *newXyz;
- float oldXyzScale, newXyzScale;
- int vertNum;
- int numVerts;
- newXyz = (short *)((byte *)surf + surf->ofsXyzNormals) + (frame * surf->numVerts * 4);
- newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
- numVerts = surf->numVerts;
- if ( backlerp == 0 ) {
- //
- // just copy the vertexes
- //
- for (vertNum=0 ; vertNum < numVerts ; vertNum++, newXyz += 4 ) {
- idDrawVert *outvert = &tri->verts[tri->numVerts];
- outvert->xyz.x = newXyz[0] * newXyzScale;
- outvert->xyz.y = newXyz[1] * newXyzScale;
- outvert->xyz.z = newXyz[2] * newXyzScale;
- tri->numVerts++;
- }
- } else {
- //
- // interpolate and copy the vertexes
- //
- oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals) + (oldframe * surf->numVerts * 4);
- oldXyzScale = MD3_XYZ_SCALE * backlerp;
- for (vertNum=0 ; vertNum < numVerts ; vertNum++, oldXyz += 4, newXyz += 4 ) {
- idDrawVert *outvert = &tri->verts[tri->numVerts];
- // interpolate the xyz
- outvert->xyz.x = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
- outvert->xyz.y = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
- outvert->xyz.z = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
- tri->numVerts++;
- }
- }
- }
- /*
- =============
- idRenderModelMD3::InstantiateDynamicModel
- =============
- */
- idRenderModel *idRenderModelMD3::InstantiateDynamicModel( const struct renderEntity_s *ent, const viewDef_t *view, idRenderModel *cachedModel ) {
- int i, j;
- float backlerp;
- int * triangles;
- int indexes;
- int numVerts;
- md3Surface_t * surface;
- int frame, oldframe;
- idRenderModelStatic *staticModel;
- if ( cachedModel ) {
- delete cachedModel;
- cachedModel = NULL;
- }
- staticModel = new (TAG_MODEL) idRenderModelStatic;
- staticModel->bounds.Clear();
- surface = (md3Surface_t *) ((byte *)md3 + md3->ofsSurfaces);
- // TODO: these need set by an entity
- frame = ent->shaderParms[SHADERPARM_MD3_FRAME]; // probably want to keep frames < 1000 or so
- oldframe = ent->shaderParms[SHADERPARM_MD3_LASTFRAME];
- backlerp = ent->shaderParms[SHADERPARM_MD3_BACKLERP];
- for( i = 0; i < md3->numSurfaces; i++ ) {
- srfTriangles_t *tri = R_AllocStaticTriSurf();
- R_AllocStaticTriSurfVerts( tri, surface->numVerts );
- R_AllocStaticTriSurfIndexes( tri, surface->numTriangles * 3 );
- tri->bounds.Clear();
- modelSurface_t surf;
- surf.geometry = tri;
- md3Shader_t* shaders = (md3Shader_t *) ((byte *)surface + surface->ofsShaders);
- surf.shader = shaders->shader;
- LerpMeshVertexes( tri, surface, backlerp, frame, oldframe );
- triangles = (int *) ((byte *)surface + surface->ofsTriangles);
- indexes = surface->numTriangles * 3;
- for (j = 0 ; j < indexes ; j++) {
- tri->indexes[j] = triangles[j];
- }
- tri->numIndexes += indexes;
- const idVec2 * texCoords = (idVec2 *) ((byte *)surface + surface->ofsSt);
- numVerts = surface->numVerts;
- for ( j = 0; j < numVerts; j++ ) {
- tri->verts[j].SetTexCoord( texCoords[j] );
- }
- R_BoundTriSurf( tri );
- staticModel->AddSurface( surf );
- staticModel->bounds.AddPoint( surf.geometry->bounds[0] );
- staticModel->bounds.AddPoint( surf.geometry->bounds[1] );
- // find the next surface
- surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd );
- }
- return staticModel;
- }
- /*
- =====================
- idRenderModelMD3::Bounds
- =====================
- */
- idBounds idRenderModelMD3::Bounds(const struct renderEntity_s *ent) const {
- idBounds ret;
- ret.Clear();
- if (!ent || !md3) {
- // just give it the editor bounds
- ret.AddPoint(idVec3(-10,-10,-10));
- ret.AddPoint(idVec3( 10, 10, 10));
- return ret;
- }
- md3Frame_t *frame = (md3Frame_t *)( (byte *)md3 + md3->ofsFrames );
- ret.AddPoint( frame->bounds[0] );
- ret.AddPoint( frame->bounds[1] );
- return ret;
- }
|