diff options
Diffstat (limited to 'source/gl_models.c')
-rw-r--r-- | source/gl_models.c | 832 |
1 files changed, 143 insertions, 689 deletions
diff --git a/source/gl_models.c b/source/gl_models.c index 7937512..b2ff3d5 100644 --- a/source/gl_models.c +++ b/source/gl_models.c @@ -19,255 +19,59 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gl_local.h" - -#define Model_Malloc( size ) sys.HunkAlloc( &model->pool, size ) - -static model_t r_models[MAX_MODELS]; -static int r_numModels; - -static byte ll2byte[256][256]; - -static cvar_t *gl_override_models; - -static model_t *Model_Alloc( const char *name ) { - model_t *model; - int i; - - for( i = 0, model = r_models; i < r_numModels; i++, model++ ) { - if( !model->name[0] ) { - break; - } - } - - if( i == r_numModels ) { - if( r_numModels == MAX_MODELS ) { - Com_Error( ERR_DROP, "Model_Alloc: MAX_MODELS" ); - } - r_numModels++; - } - - strcpy( model->name, name ); - model->registration_sequence = registration_sequence; - model->type = MODEL_NULL; - - return model; -} - -static model_t *Model_Find( const char *name ) { - model_t *model; - aliasMesh_t *mesh; - int i, j; - - for( i = 0, model = r_models; i < r_numModels; i++, model++ ) { - if( !model->name[0] ) { - continue; - } - if( !Q_stricmp( model->name, name ) ) { - break; - } - } - - if( i == r_numModels ) { - return NULL; - } - - switch( model->type ) { - case MODEL_ALIAS: - for( i = 0; i < model->numMeshes; i++ ) { - mesh = &model->meshes[i]; - for( j = 0; j < mesh->numSkins; j++ ) { - mesh->skins[j]->registration_sequence = registration_sequence; - } - } - break; - case MODEL_SPRITE: - for( i = 0; i < model->numFrames; i++ ) { - model->sframes[i].image->registration_sequence = registration_sequence; - } - break; - default: - Com_Error( ERR_DROP, "Model_Find: bad model type: %d", model->type ); - break; - } - - model->registration_sequence = registration_sequence; - return model; -} - -static void Model_List_f( void ) { - int i; - model_t *model; - int bytes; - - Com_Printf( "------------------\n"); - bytes = 0; - - for( i = 0, model = r_models; i < r_numModels; i++, model++ ) { - if( !model->name[0] ) { - continue; - } - - Com_Printf( "%8"PRIz" : %s\n", model->pool.cursize, model->name ); - bytes += model->pool.cursize; - } - Com_Printf( "Total resident: %i\n", bytes ); -} - -void Model_FreeUnused( void ) { - model_t *model; - int i; - - for( i = 0, model = r_models; i < r_numModels; i++, model++ ) { - if( !model->name[0] ) { - continue; - } - if( model->registration_sequence != registration_sequence ) { - sys.HunkFree( &model->pool ); - model->name[0] = 0; - } - } -} - -void Model_FreeAll( void ) { - model_t *model; - int i; - - for( i = 0, model = r_models; i < r_numModels; i++, model++ ) { - if( !model->name[0] ) { - continue; - } - - sys.HunkFree( &model->pool ); - model->name[0] = 0; - } - - r_numModels = 0; -} - -static qboolean Model_LoadMd2( model_t *model, const byte *rawdata, int length ) { - dmdl_t header; - daliasframe_t *src_frame; - dtrivertx_t *src_vert; - dtriangle_t *src_tri; - dstvert_t *src_tc; - aliasFrame_t *dst_frame; - aliasVert_t *dst_vert; - aliasMesh_t *dst_mesh; +#include "d_md2.h" +#include "d_md3.h" +#include "d_sp2.h" + +qboolean MOD_LoadMD2( model_t *model, const void *rawdata, size_t length ) { + dmd2header_t header; + dmd2frame_t *src_frame; + dmd2trivertx_t *src_vert; + dmd2triangle_t *src_tri; + dmd2stvert_t *src_tc; + maliasframe_t *dst_frame; + maliasvert_t *dst_vert; + maliasmesh_t *dst_mesh; uint32_t *finalIndices; - tcoord_t *dst_tc; + maliastc_t *dst_tc; int i, j, k; - uint16_t remap[MAX_TRIANGLES*3]; - uint16_t vertIndices[MAX_TRIANGLES*3]; - uint16_t tcIndices[MAX_TRIANGLES*3]; - int numVerts, numIndices; + uint16_t remap[MD2_MAX_TRIANGLES*3]; + uint16_t vertIndices[MD2_MAX_TRIANGLES*3]; + uint16_t tcIndices[MD2_MAX_TRIANGLES*3]; + int numverts, numindices; char skinname[MAX_QPATH]; char *src_skin; image_t *skin; vec_t scaleS, scaleT; int val; vec3_t mins, maxs; - const byte *rawend; - -#define ERR( x ) \ - Com_WPrintf( "LoadMD2: %s: " x "\n", model->name ) if( length < sizeof( header ) ) { - ERR( "file too short" ); + Com_WPrintf( "%s is too short\n", model->name ); return qfalse; } /* byte swap the header */ - header = *( dmdl_t * )rawdata; + header = *( dmd2header_t * )rawdata; for( i = 0; i < sizeof( header )/4; i++ ) { (( uint32_t * )&header)[i] = LittleLong( (( uint32_t * )&header)[i] ); } - // check ident and version - if( header.ident != IDALIASHEADER ) { - ERR( "not an MD2 file" ); - return qfalse; - } - if( header.version != ALIAS_VERSION ) { - ERR( "bad version" ); - return qfalse; - } - - // check triangles - if( header.num_tris < 1 || header.num_tris > MAX_TRIANGLES ) { - ERR( "bad number of triangles" ); - return qfalse; - } - if( header.ofs_tris < sizeof( header ) || - header.ofs_tris + sizeof( dtriangle_t ) * header.num_tris > length ) - { - ERR( "bad triangles offset" ); - return qfalse; - } - - // check st - if( header.num_st < 3 || header.num_st > MAX_VERTS ) { - ERR( "bad number of st" ); - return qfalse; - } - if( header.ofs_st < sizeof( header ) || - header.ofs_st + sizeof( dstvert_t ) * header.num_st > length ) - { - ERR( "bad st offset" ); - return qfalse; - } - - // check xyz and frames - if( header.num_xyz < 3 || header.num_xyz > MAX_VERTS ) { - ERR( "bad number of xyz" ); - return qfalse; - } - if( header.num_frames < 1 || header.num_frames > MAX_FRAMES ) { - ERR( "bad number of frames" ); - return qfalse; - } - if( header.framesize < sizeof( daliasframe_t ) + ( header.num_xyz - 1 ) * sizeof( dtrivertx_t ) || - header.framesize > MAX_FRAMESIZE ) - { - ERR( "bad frame size" ); - return qfalse; - } - if( header.ofs_frames < sizeof( header ) || - header.ofs_frames + header.framesize * header.num_frames > length ) - { - ERR( "bad frames offset" ); - return qfalse; + if( !MOD_ValidateMD2( model, &header, length ) ) { + return qfalse; } - // check skins - if( header.num_skins < 0 || header.num_skins > MAX_MD2SKINS ) { - ERR( "bad number of skins" ); - return qfalse; - } - if( header.num_skins && ( header.ofs_skins < sizeof( header ) || - header.ofs_skins + MAX_SKINNAME * header.num_skins > length ) ) - { - ERR( "bad skins offset" ); - return qfalse; - } - if( header.skinwidth <= 0 || header.skinheight <= 0 ) { - ERR( "bad skin dimensions" ); - return qfalse; - } - - rawend = rawdata + length; - - model->type = MODEL_ALIAS; - sys.HunkBegin( &model->pool, 0x400000 ); + Hunk_Begin( &model->pool, 0x400000 ); /* load all triangle indices */ - src_tri = ( dtriangle_t * )( ( byte * )rawdata + header.ofs_tris ); + src_tri = ( dmd2triangle_t * )( ( byte * )rawdata + header.ofs_tris ); for( i = 0; i < header.num_tris; i++ ) { for( j = 0; j < 3; j++ ) { uint16_t idx_xyz = LittleShort( src_tri->index_xyz[j] ); uint16_t idx_st = LittleShort( src_tri->index_st[j] ); - if( idx_xyz > header.num_xyz || idx_st > header.num_st ) { - ERR( "bad indices" ); + if( idx_xyz >= header.num_xyz || idx_st >= header.num_st ) { + Com_WPrintf( "%s has bad triangle indices\n", model->name ); goto fail; } @@ -277,68 +81,68 @@ static qboolean Model_LoadMd2( model_t *model, const byte *rawdata, int length ) src_tri++; } - numIndices = header.num_tris * 3; + numindices = header.num_tris * 3; - model->meshes = Model_Malloc( sizeof( aliasMesh_t ) ); - model->numMeshes = 1; + model->meshes = Model_Malloc( sizeof( maliasmesh_t ) ); + model->nummeshes = 1; dst_mesh = model->meshes; - dst_mesh->indices = Model_Malloc( numIndices * sizeof( uint32_t ) ); - dst_mesh->numTris = header.num_tris; - dst_mesh->numIndices = numIndices; + dst_mesh->indices = Model_Malloc( numindices * sizeof( uint32_t ) ); + dst_mesh->numtris = header.num_tris; + dst_mesh->numindices = numindices; - for( i = 0; i < numIndices; i++ ) { + for( i = 0; i < numindices; i++ ) { remap[i] = 0xFFFF; } - numVerts = 0; - src_tc = ( dstvert_t * )( ( byte * )rawdata + header.ofs_st ); + numverts = 0; + src_tc = ( dmd2stvert_t * )( ( byte * )rawdata + header.ofs_st ); finalIndices = dst_mesh->indices; - for( i = 0; i < numIndices; i++ ) { + for( i = 0; i < numindices; i++ ) { if( remap[i] != 0xFFFF ) { continue; /* already remapped */ } - for( j = i + 1; j < numIndices; j++ ) { + for( j = i + 1; j < numindices; j++ ) { if( vertIndices[i] == vertIndices[j] && ( src_tc[tcIndices[i]].s == src_tc[tcIndices[j]].s && src_tc[tcIndices[i]].t == src_tc[tcIndices[j]].t ) ) { /* duplicate vertex */ remap[j] = i; - finalIndices[j] = numVerts; + finalIndices[j] = numverts; } } /* new vertex */ remap[i] = i; - finalIndices[i] = numVerts++; + finalIndices[i] = numverts++; } - dst_mesh->verts = Model_Malloc( numVerts * header.num_frames * sizeof( aliasVert_t ) ); - dst_mesh->tcoords = Model_Malloc( numVerts * sizeof( tcoord_t ) ); - dst_mesh->numVerts = numVerts; + dst_mesh->verts = Model_Malloc( numverts * header.num_frames * sizeof( maliasvert_t ) ); + dst_mesh->tcoords = Model_Malloc( numverts * sizeof( maliastc_t ) ); + dst_mesh->numverts = numverts; /* load all skins */ src_skin = ( char * )rawdata + header.ofs_skins; for( i = 0; i < header.num_skins; i++ ) { Q_strncpyz( skinname, src_skin, sizeof( skinname ) ); - skin = R_FindImage( skinname, it_skin ); + skin = IMG_Find( skinname, it_skin ); if( !skin ) { skin = r_notexture; } dst_mesh->skins[i] = skin; - src_skin += MAX_SKINNAME; + src_skin += MD2_MAX_SKINNAME; } - dst_mesh->numSkins = header.num_skins; + dst_mesh->numskins = header.num_skins; /* load all tcoords */ - src_tc = ( dstvert_t * )( ( byte * )rawdata + header.ofs_st ); + src_tc = ( dmd2stvert_t * )( ( byte * )rawdata + header.ofs_st ); dst_tc = dst_mesh->tcoords; skin = dst_mesh->skins[0]; scaleS = 1.0f / header.skinwidth; scaleT = 1.0f / header.skinheight; - for( i = 0; i < numIndices; i++ ) { + for( i = 0; i < numindices; i++ ) { if( remap[i] == i ) { float s = ( signed short )LittleShort( src_tc[ tcIndices[i] ].s ); float t = ( signed short )LittleShort( src_tc[ tcIndices[i] ].t ); @@ -349,10 +153,10 @@ static qboolean Model_LoadMd2( model_t *model, const byte *rawdata, int length ) } /* load all frames */ - model->frames = Model_Malloc( header.num_frames * sizeof( aliasFrame_t ) ); - model->numFrames = header.num_frames; + model->frames = Model_Malloc( header.num_frames * sizeof( maliasframe_t ) ); + model->numframes = header.num_frames; - src_frame = ( daliasframe_t * )( ( byte * )rawdata + header.ofs_frames ); + src_frame = ( dmd2frame_t * )( ( byte * )rawdata + header.ofs_frames ); dst_frame = model->frames; for( j = 0; j < header.num_frames; j++ ) { LittleVector( src_frame->scale, dst_frame->scale ); @@ -360,20 +164,20 @@ static qboolean Model_LoadMd2( model_t *model, const byte *rawdata, int length ) /* load frame vertices */ ClearBounds( mins, maxs ); - for( i = 0; i < numIndices; i++ ) { + for( i = 0; i < numindices; i++ ) { if( remap[i] == i ) { src_vert = &src_frame->verts[ vertIndices[i] ]; - dst_vert = &dst_mesh->verts[ j * numVerts + finalIndices[i] ]; + dst_vert = &dst_mesh->verts[ j * numverts + finalIndices[i] ]; dst_vert->pos[0] = src_vert->v[0]; dst_vert->pos[1] = src_vert->v[1]; dst_vert->pos[2] = src_vert->v[2]; k = src_vert->lightnormalindex; if( k >= NUMVERTEXNORMALS ) { - ERR( "bad normal index" ); + Com_WPrintf( "%s has bad normal indices\n", model->name ); goto fail; } - dst_vert->normalIndex = k; + dst_vert->normalindex = k; for ( k = 0; k < 3; k++ ) { val = dst_vert->pos[k]; @@ -393,21 +197,42 @@ static qboolean Model_LoadMd2( model_t *model, const byte *rawdata, int length ) VectorAdd( mins, dst_frame->translate, dst_frame->bounds[0] ); VectorAdd( maxs, dst_frame->translate, dst_frame->bounds[1] ); - src_frame = ( daliasframe_t * )( ( byte * )src_frame + header.framesize ); + src_frame = ( dmd2frame_t * )( ( byte * )src_frame + header.framesize ); dst_frame++; } - sys.HunkEnd( &model->pool ); + Hunk_End( &model->pool ); return qtrue; fail: - sys.HunkFree( &model->pool ); + Hunk_Free( &model->pool ); return qfalse; +} -#undef ERR +#if USE_MD3 +static byte ll2byte[256][256]; +static qboolean ll2byte_inited; + +static void ll2byte_init( void ) { + float s[2], c[2]; + vec3_t normal; + int i, j; + + for( i = 0; i < 256; i++ ) { + for( j = 0; j < 256; j++ ) { + s[0] = sin( i / 255.0f ); + c[0] = cos( i / 255.0f ); + + s[1] = sin( j / 255.0f ); + c[1] = cos( j / 255.0f ); + + VectorSet( normal, s[0] * c[1], s[0] * s[1], c[0] ); + ll2byte[i][j] = DirToByte( normal ); + } + } } -static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) { +qboolean MOD_LoadMD3( model_t *model, const void *rawdata, size_t length ) { dmd3header_t header; uint32_t offset; dmd3frame_t *src_frame; @@ -416,12 +241,12 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) dmd3coord_t *src_tc; dmd3skin_t *src_skin; uint32_t *src_idx; - aliasFrame_t *dst_frame; - aliasMesh_t *dst_mesh; - aliasVert_t *dst_vert; - tcoord_t *dst_tc; + maliasframe_t *dst_frame; + maliasmesh_t *dst_mesh; + maliasvert_t *dst_vert; + maliastc_t *dst_tc; uint32_t *dst_idx; - uint32_t numVerts, numTris, numSkins; + uint32_t numverts, numtris, numskins; uint32_t totalVerts; char skinname[MAX_QPATH]; image_t *skin; @@ -429,7 +254,7 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) int i, j; if( length < sizeof( header ) ) { - Com_WPrintf( "%s has length < header length\n", model->name ); + Com_WPrintf( "%s is too small to hold MD3 header\n", model->name ); return qfalse; } @@ -443,40 +268,30 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) Com_WPrintf( "%s is not an MD3 file\n", model->name ); return qfalse; } - if( header.version != MD3_VERSION ) { - Com_WPrintf( "%s has bad version: %d != %d\n", + Com_WPrintf( "%s has bad version: %d instead of %d\n", model->name, header.version, MD3_VERSION ); return qfalse; } - - if( header.num_frames < 1 ) { - Com_WPrintf( "%s has bad number of frames: %d\n", - model->name, header.num_frames ); - return qfalse; - } - if( header.num_frames > MD3_MAX_FRAMES ) { - Com_WPrintf( "%s has too many frames: %d > %d\n", - model->name, header.num_frames, MD3_MAX_FRAMES ); + if( header.num_frames < 1 || header.num_frames > MD3_MAX_FRAMES ) { + Com_WPrintf( "%s has bad number of frames\n", model->name ); return qfalse; } - - if( header.num_meshes < 1 || header.num_meshes > MD3_MAX_SURFACES ) { + if( header.num_meshes < 1 || header.num_meshes > MD3_MAX_MESHES ) { Com_WPrintf( "%s has bad number of meshes\n", model->name ); return qfalse; } - model->type = MODEL_ALIAS; - sys.HunkBegin( &model->pool, 0x400000 ); - model->numFrames = header.num_frames; - model->numMeshes = header.num_meshes; - model->meshes = Model_Malloc( sizeof( aliasMesh_t ) * header.num_meshes ); - model->frames = Model_Malloc( sizeof( aliasFrame_t ) * header.num_frames ); - - rawend = rawdata + length; + Hunk_Begin( &model->pool, 0x400000 ); + model->numframes = header.num_frames; + model->nummeshes = header.num_meshes; + model->meshes = Model_Malloc( sizeof( maliasmesh_t ) * header.num_meshes ); + model->frames = Model_Malloc( sizeof( maliasframe_t ) * header.num_frames ); + + rawend = ( byte * )rawdata + length; /* load all frames */ - src_frame = ( dmd3frame_t * )( rawdata + header.ofs_frames ); + src_frame = ( dmd3frame_t * )( ( byte * )rawdata + header.ofs_frames ); if( ( byte * )( src_frame + header.num_frames ) > rawend ) { Com_WPrintf( "%s has bad frames offset\n", model->name ); goto fail; @@ -494,7 +309,7 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) } /* load all meshes */ - src_mesh = ( dmd3mesh_t * )( rawdata + header.ofs_meshes ); + src_mesh = ( dmd3mesh_t * )( ( byte * )rawdata + header.ofs_meshes ); dst_mesh = model->meshes; for( i = 0; i < header.num_meshes; i++ ) { if( ( byte * )( src_mesh + 1 ) > rawend ) { @@ -502,49 +317,49 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) goto fail; } - numVerts = LittleLong( src_mesh->num_verts ); - numTris = LittleLong( src_mesh->num_tris ); + numverts = LittleLong( src_mesh->num_verts ); + numtris = LittleLong( src_mesh->num_tris ); - if( numVerts < 3 || numVerts > TESS_MAX_VERTICES ) { + if( numverts < 3 || numverts > TESS_MAX_VERTICES ) { Com_WPrintf( "%s has bad number of vertices for mesh %d\n", model->name, i ); goto fail; } - if( numTris < 1 || numTris > TESS_MAX_INDICES / 3 ) { + if( numtris < 1 || numtris > TESS_MAX_INDICES / 3 ) { Com_WPrintf( "%s has bad number of faces for mesh %d\n", model->name, i ); goto fail; } - dst_mesh->numTris = numTris; - dst_mesh->numIndices = numTris * 3; - dst_mesh->numVerts = numVerts; - dst_mesh->verts = Model_Malloc( sizeof( aliasVert_t ) * numVerts * header.num_frames ); - dst_mesh->tcoords = Model_Malloc( sizeof( tcoord_t ) * numVerts ); - dst_mesh->indices = Model_Malloc( sizeof( uint32_t ) * numTris * 3 ); + dst_mesh->numtris = numtris; + dst_mesh->numindices = numtris * 3; + dst_mesh->numverts = numverts; + dst_mesh->verts = Model_Malloc( sizeof( maliasvert_t ) * numverts * header.num_frames ); + dst_mesh->tcoords = Model_Malloc( sizeof( maliastc_t ) * numverts ); + dst_mesh->indices = Model_Malloc( sizeof( uint32_t ) * numtris * 3 ); /* load all skins */ - numSkins = LittleLong( src_mesh->num_skins ); - if( numSkins > MAX_MD2SKINS ) { + numskins = LittleLong( src_mesh->num_skins ); + if( numskins > MAX_ALIAS_SKINS ) { Com_WPrintf( "%s has bad number of skins for mesh %d\n", model->name, i ); goto fail; } offset = LittleLong( src_mesh->ofs_skins ); src_skin = ( dmd3skin_t * )( ( byte * )src_mesh + offset ); - if( ( byte * )( src_skin + numSkins ) > rawend ) { + if( ( byte * )( src_skin + numskins ) > rawend ) { Com_WPrintf( "%s has bad skins offset for mesh %d\n", model->name, i ); goto fail; } - for( j = 0; j < numSkins; j++ ) { + for( j = 0; j < numskins; j++ ) { Q_strncpyz( skinname, src_skin->name, sizeof( skinname ) ); - skin = R_FindImage( skinname, it_skin ); + skin = IMG_Find( skinname, it_skin ); if( !skin ) { skin = r_notexture; } dst_mesh->skins[j] = skin; } - dst_mesh->numSkins = numSkins; + dst_mesh->numskins = numskins; /* load all vertices */ - totalVerts = numVerts * header.num_frames; + totalVerts = numverts * header.num_frames; offset = LittleLong( src_mesh->ofs_verts ); src_vert = ( dmd3vertex_t * )( ( byte * )src_mesh + offset ); if( ( byte * )( src_vert + totalVerts ) > rawend ) { @@ -557,7 +372,11 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) dst_vert->pos[1] = ( signed short )LittleShort( src_vert->point[1] ); dst_vert->pos[2] = ( signed short )LittleShort( src_vert->point[2] ); - dst_vert->normalIndex = ll2byte[src_vert->norm[0]] + if( !ll2byte_inited ) { + ll2byte_init(); + ll2byte_inited = qtrue; + } + dst_vert->normalindex = ll2byte[src_vert->norm[0]] [src_vert->norm[1]]; src_vert++; dst_vert++; @@ -566,12 +385,12 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) /* load all texture coords */ offset = LittleLong( src_mesh->ofs_tcs ); src_tc = ( dmd3coord_t * )( ( byte * )src_mesh + offset ); - if( ( byte * )( src_tc + numVerts ) > rawend ) { + if( ( byte * )( src_tc + numverts ) > rawend ) { Com_WPrintf( "%s has bad tcoords offset for mesh %d\n", model->name, i ); goto fail; } dst_tc = dst_mesh->tcoords; - for( j = 0; j < numVerts; j++ ) { + for( j = 0; j < numverts; j++ ) { dst_tc->st[0] = LittleFloat( src_tc->st[0] ); dst_tc->st[1] = LittleFloat( src_tc->st[1] ); src_tc++; dst_tc++; @@ -580,16 +399,16 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) /* load all triangle indices */ offset = LittleLong( src_mesh->ofs_indexes ); src_idx = ( uint32_t * )( ( byte * )src_mesh + offset ); - if( ( byte * )( src_idx + numTris * 3 ) > rawend ) { + if( ( byte * )( src_idx + numtris * 3 ) > rawend ) { Com_WPrintf( "%s has bad indices offset for mesh %d\n", model->name, i ); goto fail; } dst_idx = dst_mesh->indices; - for( j = 0; j < numTris; j++ ) { + for( j = 0; j < numtris; j++ ) { dst_idx[0] = LittleLong( src_idx[0] ); dst_idx[1] = LittleLong( src_idx[1] ); dst_idx[2] = LittleLong( src_idx[2] ); - if( dst_idx[0] >= numVerts || dst_idx[1] >= numVerts || dst_idx[2] >= numVerts ) { + if( dst_idx[0] >= numverts || dst_idx[1] >= numverts || dst_idx[2] >= numverts ) { Com_WPrintf( "%s has bad indices for triangle %d in mesh %d\n", model->name, j, i ); goto fail; } @@ -601,398 +420,33 @@ static qboolean Model_LoadMd3( model_t *model, const byte *rawdata, int length ) dst_mesh++; } - sys.HunkEnd( &model->pool ); + Hunk_End( &model->pool ); return qtrue; fail: - sys.HunkFree( &model->pool ); + Hunk_Free( &model->pool ); return qfalse; } +#endif -#define Model_TempAlloc( ptr, size ) \ - do { ptr = ( void * )data; data += size; offset += size; } while( 0 ) - -static qboolean Model_WriteMd3( model_t *model, fileHandle_t f ) { - dmd3header_t *header; - uint32_t offset, length; - byte *data; - dmd3frame_t *dst_frame; - dmd3mesh_t *dst_mesh; - dmd3vertex_t *dst_vert; - dmd3coord_t *dst_tc; - dmd3skin_t *dst_skin; - uint32_t *dst_idx; - aliasFrame_t *src_frame; - aliasMesh_t *src_mesh; - aliasVert_t *src_vert; - tcoord_t *src_tc; - uint32_t *src_idx; - uint32_t totalVerts; - int i, j; - qboolean ret; - short pos[3]; - - // precalculate total length - length = sizeof( dmd3header_t ) + - model->numFrames * sizeof( dmd3frame_t ); - src_mesh = model->meshes; - for( i = 0; i < model->numMeshes; i++ ) { - length += sizeof( dmd3mesh_t ) + - src_mesh->numSkins * sizeof( dmd3skin_t ) + - src_mesh->numVerts * model->numFrames * sizeof( dmd3vertex_t ) + - src_mesh->numVerts * sizeof( dmd3coord_t ) + - src_mesh->numIndices * sizeof( uint32_t ); - src_mesh++; - } - - data = fs.AllocTempMem( length ); - offset = 0; - - // write header - Model_TempAlloc( header, sizeof( dmd3header_t ) ); - header->ident = LittleLong( MD3_IDENT ); - header->version = LittleLong( MD3_VERSION ); - memset( header->filename, 0, sizeof( header->filename ) ); - header->flags = 0; - header->num_frames = LittleLong( model->numFrames ); - header->num_tags = 0; - header->num_meshes = LittleLong( model->numMeshes ); - header->num_skins = 0; - - // write all frames - header->ofs_frames = LittleLong( offset ); - src_frame = model->frames; - Model_TempAlloc( dst_frame, model->numFrames * sizeof( dmd3frame_t ) ); - for( i = 0; i < model->numFrames; i++ ) { - LittleVector( src_frame->translate, dst_frame->translate ); - - LittleVector( src_frame->bounds[0], dst_frame->mins ); - LittleVector( src_frame->bounds[1], dst_frame->maxs ); - dst_frame->radius = LittleFloat( src_frame->radius ); - - memset( dst_frame->creator, 0, sizeof( dst_frame->creator ) ); - - src_frame++; dst_frame++; - } - - // write all meshes - header->ofs_meshes = LittleLong( offset ); - src_mesh = model->meshes; - for( i = 0; i < model->numMeshes; i++ ) { - offset = 0; - Model_TempAlloc( dst_mesh, sizeof( dmd3mesh_t ) ); - dst_mesh->ident = LittleLong( MD3_IDENT ); - memset( dst_mesh->name, 0, sizeof( dst_mesh->name ) ); - dst_mesh->flags = 0; - dst_mesh->num_frames = LittleLong( model->numFrames ); - dst_mesh->num_skins = LittleLong( src_mesh->numSkins ); - dst_mesh->num_tris = LittleLong( src_mesh->numTris ); - dst_mesh->num_verts = LittleLong( src_mesh->numVerts ); - - // write all skins - dst_mesh->ofs_skins = LittleLong( offset ); - Model_TempAlloc( dst_skin, sizeof( dmd3skin_t ) * src_mesh->numSkins ); - for( j = 0; j < src_mesh->numSkins; j++ ) { - memcpy( dst_skin->name, src_mesh->skins[j]->name, MAX_QPATH ); - dst_skin->unused = 0; - dst_skin++; - } - - // write all vertices - dst_mesh->ofs_verts = LittleLong( offset ); - totalVerts = src_mesh->numVerts * model->numFrames; - src_vert = src_mesh->verts; - src_frame = model->frames; - Model_TempAlloc( dst_vert, sizeof( dmd3vertex_t ) * totalVerts ); - for( j = 0; j < totalVerts; j++ ) { - pos[0] = src_vert->pos[0] * src_frame->scale[0] / MD3_XYZ_SCALE; - pos[1] = src_vert->pos[1] * src_frame->scale[1] / MD3_XYZ_SCALE; - pos[2] = src_vert->pos[2] * src_frame->scale[2] / MD3_XYZ_SCALE; - - dst_vert->point[0] = ( signed short )LittleShort( pos[0] ); - dst_vert->point[1] = ( signed short )LittleShort( pos[1] ); - dst_vert->point[2] = ( signed short )LittleShort( pos[2] ); - - // TODO: calc normal - - src_vert++; dst_vert++; - } - - // write all texture coords - dst_mesh->ofs_tcs = LittleLong( offset ); - src_tc = src_mesh->tcoords; - Model_TempAlloc( dst_tc, sizeof( dmd3coord_t ) * src_mesh->numVerts ); - for( j = 0; j < src_mesh->numVerts; j++ ) { - dst_tc->st[0] = LittleFloat( src_tc->st[0] ); - dst_tc->st[1] = LittleFloat( src_tc->st[1] ); - src_tc++; dst_tc++; - } - - // write all triangle indices - dst_mesh->ofs_indexes = LittleLong( offset ); - src_idx = src_mesh->indices; - Model_TempAlloc( dst_idx, sizeof( uint32_t ) * src_mesh->numIndices ); - for( j = 0; j < src_mesh->numTris; j++ ) { - dst_idx[0] = LittleLong( src_idx[0] ); - dst_idx[1] = LittleLong( src_idx[1] ); - dst_idx[2] = LittleLong( src_idx[2] ); - src_idx += 3; dst_idx += 3; - } - - dst_mesh->meshsize = LittleLong( offset ); - } - - header->ofs_tags = 0; - header->ofs_end = length; - - // write model to disk - ret = qtrue; - if( fs.Write( header, length, f ) != length ) { - ret = qfalse; - } - - fs.FreeFile( header ); - - return ret; -} - -static qboolean Model_LoadSp2( model_t *model, const byte *rawdata, int length ) { - dsprite_t *header; - dsprframe_t *src_frame; - spriteFrame_t *dst_frame; - unsigned ident, version, numframes, width, height; - char buffer[MAX_SKINNAME]; - image_t *image; - int i; - - if( length < sizeof( *header ) ) { - Com_EPrintf( "%s has length < header length\n", model->name ); - return qfalse; - } - - /* byte swap the header */ - header = ( dsprite_t * )rawdata; - for( i = 0; i < sizeof( header )/4; i++ ) { - (( uint32_t * )&header)[i] = LittleLong( (( uint32_t * )&header)[i] ); - } - - ident = LittleLong( header->ident ); - version = LittleLong( header->version ); - numframes = LittleLong( header->numframes ); - - if( ident != IDSPRITEHEADER ) { - Com_EPrintf( "%s is not an sp2 file\n", model->name ); - return qfalse; - } - if( version != SPRITE_VERSION ) { - Com_EPrintf( "%s has bad version: %d != %d\n", - model->name, version, ALIAS_VERSION ); - return qfalse; - } - if( numframes < 1 || numframes > MAX_MD2SKINS ) { - Com_EPrintf( "%s has bad number of frames: %d\n", - model->name, numframes ); - return qfalse; - } - - model->type = MODEL_SPRITE; - sys.HunkBegin( &model->pool, 0x10000 ); - - model->sframes = Model_Malloc( sizeof( spriteFrame_t ) * numframes ); - model->numFrames = numframes; - - src_frame = header->frames; - dst_frame = model->sframes; - for( i = 0; i < numframes; i++ ) { - width = LittleLong( src_frame->width ); - height = LittleLong( src_frame->height ); - if( width < 1 || height < 1 || width > MAX_TEXTURE_SIZE || height > MAX_TEXTURE_SIZE ) { - Com_WPrintf( "%s has bad image dimensions for frame #%d: %ux%u\n", - model->name, width, height, i ); - width = 1; - height = 1; - } - dst_frame->width = width; - dst_frame->height = height; - dst_frame->x = LittleLong( src_frame->origin_x ); - dst_frame->y = LittleLong( src_frame->origin_y ); - - Q_strncpyz( buffer, src_frame->name, sizeof( buffer ) ); - image = R_FindImage( buffer, it_sprite ); - if( !image ) { - Com_DPrintf( "Couldn't find image '%s' for frame #%d for sprite '%s'\n", - buffer, i, model->name ); - image = r_notexture; - } - dst_frame->image = image; - - dst_frame++; src_frame++; - } - - sys.HunkEnd( &model->pool ); - - return qtrue; -} - -void GL_GetModelSize( qhandle_t hModel, vec3_t mins, vec3_t maxs ) { - VectorClear( mins ); - VectorClear( maxs ); -} +void MOD_Reference( model_t *model ) { + int i, j; -qhandle_t GL_RegisterModel( const char *name ) { - int index, length = 0; - size_t namelen; - model_t *model; - byte *rawdata; - uint32_t ident; - qboolean success; - char buffer[MAX_QPATH]; - - if( name[0] == '*' ) { - /* inline bsp model */ - index = atoi( name + 1 ); - if( index < 1 || index >= r_world.numSubmodels ) { - Com_Error( ERR_DROP, "%s: bad inline model index: %d", __func__, index ); + if( model->frames ) { + for( i = 0; i < model->nummeshes; i++ ) { + maliasmesh_t *mesh = &model->meshes[i]; + for( j = 0; j < mesh->numskins; j++ ) { + mesh->skins[j]->registration_sequence = registration_sequence; + } } - return ~index; - } - - if( !strcmp( r_world.name, name ) ) { - /* TODO: change client code and remove this hack */ - return 0; - } - - namelen = strlen( name ); - if( namelen > MAX_QPATH - 1 ) { - Com_Error( ERR_DROP, "%s: oversize name", __func__ ); - } - - model = Model_Find( name ); - if( model ) { - goto finish; - } - - rawdata = NULL; - buffer[0] = 0; - if( gl_override_models->integer ) { - if( namelen > 4 && !strcmp( name + namelen - 4, ".md2" ) ) { - strcpy( buffer, name ); - buffer[namelen - 1] = '3'; - length = fs.LoadFile( buffer, ( void ** )&rawdata ); - } - } - if( !rawdata ) { - length = fs.LoadFile( name, ( void ** )&rawdata ); - if( !rawdata ) { - Com_DPrintf( "Couldn't load %s\n", name ); - return 0; + } else if( model->spriteframes ) { + for( i = 0; i < model->numframes; i++ ) { + model->spriteframes[i].image->registration_sequence = registration_sequence; } + } else { + Com_Error( ERR_FATAL, "%s: bad model type", __func__ ); } - if( length < 4 ) { - Com_WPrintf( "LoadXXX: %s: file too short\n", name ); - return 0; - } - - model = Model_Alloc( name ); - - ident = LittleLong( *( uint32_t * )rawdata ); - switch( ident ) { - case IDALIASHEADER: - success = Model_LoadMd2( model, rawdata, length ); - if( success && gl_override_models->integer > 1 ) { - fileHandle_t f; - - fs.FOpenFile( buffer, &f, FS_MODE_WRITE ); - if( f ) { - Model_WriteMd3( model, f ); - fs.FCloseFile( f ); - } - } - break; - case MD3_IDENT: - success = Model_LoadMd3( model, rawdata, length ); - break; - case IDSPRITEHEADER: - success = Model_LoadSp2( model, rawdata, length ); - break; - case IDBSPHEADER: - Com_WPrintf( "LoadXXX: %s: loaded BSP model after the world\n", name ); - success = qfalse; - break; - default: - Com_WPrintf( "LoadXXX: %s: unknown ident: %x\n", name, ident ); - success = qfalse; - break; - } - - fs.FreeFile( rawdata ); - - if( !success ) { - model->name[0] = 0; - return 0; - } - -finish: - index = ( model - r_models ) + 1; - return index; -} - -modelType_t *GL_ModelForHandle( qhandle_t hModel ) { - model_t *model; - bspSubmodel_t *submodel; - - if( !hModel ) { - return NULL; - } - - if( hModel & 0x80000000 ) { - hModel = ~hModel; - - if( hModel < 1 || hModel >= r_world.numSubmodels ) { - Com_Error( ERR_DROP, "GL_ModelForHandle: submodel %d out of range", hModel ); - } - - submodel = &r_world.submodels[hModel]; - return &submodel->type; - } - - if( hModel > r_numModels ) { - Com_Error( ERR_DROP, "GL_ModelForHandle: %d out of range", hModel ); - } - model = &r_models[ hModel - 1 ]; - if( !model->name[0] ) { - return NULL; - } - return &model->type; - -} - -void GL_InitModels( void ) { - float s[2], c[2]; - vec3_t normal; - int i, j; - - for( i = 0; i < 256; i++ ) { - for( j = 0; j < 256; j++ ) { - s[0] = sin( i / 255.0f ); - c[0] = cos( i / 255.0f ); - - s[1] = sin( j / 255.0f ); - c[1] = cos( j / 255.0f ); - - VectorSet( normal, s[0] * c[1], s[0] * s[1], c[0] ); - ll2byte[i][j] = DirToByte( normal ); - } - } - - gl_override_models = cvar.Get( "r_override_models", "0", - CVAR_ARCHIVE|CVAR_FILES ); - - cmd.AddCommand( "modellist", Model_List_f ); + model->registration_sequence = registration_sequence; } -void GL_ShutdownModels( void ) { - Model_FreeAll(); - cmd.RemoveCommand( "modellist" ); -} |