2009-03-05 09:07:55 +00:00
|
|
|
/*
|
2010-10-21 08:12:50 +00:00
|
|
|
* Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
*
|
|
|
|
* This program 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 2 of the License, or (at
|
|
|
|
* your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* =======================================================================
|
|
|
|
*
|
2010-10-21 08:21:13 +00:00
|
|
|
* Model loading and caching. Includes the .bsp file format
|
2010-10-21 08:12:50 +00:00
|
|
|
*
|
|
|
|
* =======================================================================
|
|
|
|
*/
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2009-03-05 11:03:08 +00:00
|
|
|
#include "header/local.h"
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
#define MAX_MOD_KNOWN 512
|
|
|
|
|
|
|
|
model_t *loadmodel;
|
|
|
|
int modfilelen;
|
|
|
|
byte mod_novis [ MAX_MAP_LEAFS / 8 ];
|
|
|
|
model_t mod_known [ MAX_MOD_KNOWN ];
|
|
|
|
int mod_numknown;
|
|
|
|
int registration_sequence;
|
|
|
|
byte *mod_base;
|
|
|
|
|
|
|
|
void Mod_LoadSpriteModel ( model_t *mod, void *buffer );
|
|
|
|
void Mod_LoadBrushModel ( model_t *mod, void *buffer );
|
|
|
|
void Mod_LoadAliasModel ( model_t *mod, void *buffer );
|
|
|
|
model_t *Mod_LoadModel ( model_t *mod, qboolean crash );
|
|
|
|
void GL_BuildPolygonFromSurface ( msurface_t *fa );
|
|
|
|
void GL_CreateSurfaceLightmap ( msurface_t *surf );
|
|
|
|
void GL_EndBuildingLightmaps ( void );
|
|
|
|
void GL_BeginBuildingLightmaps ( model_t *m );
|
|
|
|
|
|
|
|
/* the inline * models from the current map are kept seperate */
|
|
|
|
model_t mod_inline [ MAX_MOD_KNOWN ];
|
|
|
|
|
|
|
|
mleaf_t *
|
|
|
|
Mod_PointInLeaf ( vec3_t p, model_t *model )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
mnode_t *node;
|
|
|
|
float d;
|
|
|
|
cplane_t *plane;
|
|
|
|
|
|
|
|
if ( !model || !model->nodes )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "Mod_PointInLeaf: bad model" );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
node = model->nodes;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
while ( 1 )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( node->contents != -1 )
|
|
|
|
{
|
|
|
|
return ( (mleaf_t *) node );
|
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
plane = node->plane;
|
2010-10-21 08:12:50 +00:00
|
|
|
d = DotProduct( p, plane->normal ) - plane->dist;
|
|
|
|
|
|
|
|
if ( d > 0 )
|
|
|
|
{
|
|
|
|
node = node->children [ 0 ];
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
else
|
2010-10-21 08:12:50 +00:00
|
|
|
{
|
|
|
|
node = node->children [ 1 ];
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
return ( NULL ); /* never reached */
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
byte *
|
|
|
|
Mod_DecompressVis ( byte *in, model_t *model )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
static byte decompressed [ MAX_MAP_LEAFS / 8 ];
|
|
|
|
int c;
|
|
|
|
byte *out;
|
|
|
|
int row;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
row = ( model->vis->numclusters + 7 ) >> 3;
|
2009-03-05 09:07:55 +00:00
|
|
|
out = decompressed;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !in )
|
|
|
|
{
|
|
|
|
/* no vis info, so make all visible */
|
|
|
|
while ( row )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
*out++ = 0xff;
|
|
|
|
row--;
|
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
return ( decompressed );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( *in )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
*out++ = *in++;
|
|
|
|
continue;
|
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
c = in [ 1 ];
|
2009-03-05 09:07:55 +00:00
|
|
|
in += 2;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
while ( c )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
*out++ = 0;
|
|
|
|
c--;
|
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
|
|
|
while ( out - decompressed < row );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
return ( decompressed );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
byte *
|
|
|
|
Mod_ClusterPVS ( int cluster, model_t *model )
|
|
|
|
{
|
|
|
|
if ( ( cluster == -1 ) || !model->vis )
|
|
|
|
{
|
|
|
|
return ( mod_novis );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
return ( Mod_DecompressVis( (byte *) model->vis + model->vis->bitofs [ cluster ] [ DVIS_PVS ],
|
|
|
|
model ) );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_Modellist_f ( void )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
int i;
|
|
|
|
model_t *mod;
|
|
|
|
int total;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
total = 0;
|
2010-10-21 08:12:50 +00:00
|
|
|
ri.Con_Printf( PRINT_ALL, "Loaded models:\n" );
|
|
|
|
|
|
|
|
for ( i = 0, mod = mod_known; i < mod_numknown; i++, mod++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !mod->name [ 0 ] )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
continue;
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ri.Con_Printf( PRINT_ALL, "%8i : %s\n", mod->extradatasize, mod->name );
|
2009-03-05 09:07:55 +00:00
|
|
|
total += mod->extradatasize;
|
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
ri.Con_Printf( PRINT_ALL, "Total resident: %i\n", total );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_Init ( void )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
memset( mod_novis, 0xff, sizeof ( mod_novis ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-21 08:12:50 +00:00
|
|
|
* Loads in a model for the given name
|
|
|
|
*/
|
|
|
|
model_t *
|
|
|
|
Mod_ForName ( char *name, qboolean crash )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
model_t *mod;
|
2009-03-05 09:07:55 +00:00
|
|
|
unsigned *buf;
|
2010-10-21 08:12:50 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if ( !name [ 0 ] )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
ri.Sys_Error( ERR_DROP, "Mod_ForName: NULL name" );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
/* inline models are grabbed only from worldmodel */
|
|
|
|
if ( name [ 0 ] == '*' )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
i = atoi( name + 1 );
|
|
|
|
|
|
|
|
if ( ( i < 1 ) || !r_worldmodel || ( i >= r_worldmodel->numsubmodels ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "bad inline model number" );
|
|
|
|
}
|
|
|
|
|
|
|
|
return ( &mod_inline [ i ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
/* search the currently loaded models */
|
|
|
|
for ( i = 0, mod = mod_known; i < mod_numknown; i++, mod++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !mod->name [ 0 ] )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !strcmp( mod->name, name ) )
|
|
|
|
{
|
|
|
|
return ( mod );
|
|
|
|
}
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
/* find a free model slot spot */
|
|
|
|
for ( i = 0, mod = mod_known; i < mod_numknown; i++, mod++ )
|
|
|
|
{
|
|
|
|
if ( !mod->name [ 0 ] )
|
|
|
|
{
|
|
|
|
break; /* free spot */
|
|
|
|
}
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( i == mod_numknown )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( mod_numknown == MAX_MOD_KNOWN )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "mod_numknown == MAX_MOD_KNOWN" );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
mod_numknown++;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
strcpy( mod->name, name );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
/* load the file */
|
|
|
|
modfilelen = ri.FS_LoadFile( mod->name, (void **) &buf );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !buf )
|
|
|
|
{
|
|
|
|
if ( crash )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "Mod_NumForName: %s not found", mod->name );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
memset( mod->name, 0, sizeof ( mod->name ) );
|
|
|
|
return ( NULL );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
loadmodel = mod;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
/* call the apropriate loader */
|
|
|
|
switch ( LittleLong( *(unsigned *) buf ) )
|
|
|
|
{
|
|
|
|
case IDALIASHEADER:
|
|
|
|
loadmodel->extradata = Hunk_Begin( 0x200000 );
|
|
|
|
Mod_LoadAliasModel( mod, buf );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDSPRITEHEADER:
|
|
|
|
loadmodel->extradata = Hunk_Begin( 0x10000 );
|
|
|
|
Mod_LoadSpriteModel( mod, buf );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDBSPHEADER:
|
|
|
|
loadmodel->extradata = Hunk_Begin( 0x1000000 );
|
|
|
|
Mod_LoadBrushModel( mod, buf );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ri.Sys_Error( ERR_DROP, "Mod_NumForName: unknown fileid for %s", mod->name );
|
|
|
|
break;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
loadmodel->extradatasize = Hunk_End();
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
ri.FS_FreeFile( buf );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
return ( mod );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Mod_LoadLighting ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !l->filelen )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
loadmodel->lightdata = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
loadmodel->lightdata = Hunk_Alloc( l->filelen );
|
|
|
|
memcpy( loadmodel->lightdata, mod_base + l->fileofs, l->filelen );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadVisibility ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
int i;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !l->filelen )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
loadmodel->vis = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
loadmodel->vis = Hunk_Alloc( l->filelen );
|
|
|
|
memcpy( loadmodel->vis, mod_base + l->fileofs, l->filelen );
|
|
|
|
|
|
|
|
loadmodel->vis->numclusters = LittleLong( loadmodel->vis->numclusters );
|
|
|
|
|
|
|
|
for ( i = 0; i < loadmodel->vis->numclusters; i++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
loadmodel->vis->bitofs [ i ] [ 0 ] = LittleLong( loadmodel->vis->bitofs [ i ] [ 0 ] );
|
|
|
|
loadmodel->vis->bitofs [ i ] [ 1 ] = LittleLong( loadmodel->vis->bitofs [ i ] [ 1 ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadVertexes ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
dvertex_t *in;
|
|
|
|
mvertex_t *out;
|
|
|
|
int i, count;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
|
|
|
|
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( count * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->vertexes = out;
|
|
|
|
loadmodel->numvertexes = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++, in++, out++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
out->position [ 0 ] = LittleFloat( in->point [ 0 ] );
|
|
|
|
out->position [ 1 ] = LittleFloat( in->point [ 1 ] );
|
|
|
|
out->position [ 2 ] = LittleFloat( in->point [ 2 ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
float
|
|
|
|
RadiusFromBounds ( vec3_t mins, vec3_t maxs )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
int i;
|
|
|
|
vec3_t corner;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < 3; i++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
corner [ i ] = fabs( mins [ i ] ) > fabs( maxs [ i ] ) ? fabs( mins [ i ] ) : fabs( maxs [ i ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
return ( VectorLength( corner ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadSubmodels ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
dmodel_t *in;
|
|
|
|
mmodel_t *out;
|
|
|
|
int i, j, count;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
|
|
|
|
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( count * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->submodels = out;
|
|
|
|
loadmodel->numsubmodels = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++, in++, out++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( j = 0; j < 3; j++ )
|
|
|
|
{
|
|
|
|
/* spread the mins / maxs by a pixel */
|
|
|
|
out->mins [ j ] = LittleFloat( in->mins [ j ] ) - 1;
|
|
|
|
out->maxs [ j ] = LittleFloat( in->maxs [ j ] ) + 1;
|
|
|
|
out->origin [ j ] = LittleFloat( in->origin [ j ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
out->radius = RadiusFromBounds( out->mins, out->maxs );
|
|
|
|
out->headnode = LittleLong( in->headnode );
|
|
|
|
out->firstface = LittleLong( in->firstface );
|
|
|
|
out->numfaces = LittleLong( in->numfaces );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadEdges ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
dedge_t *in;
|
|
|
|
medge_t *out;
|
2010-10-21 08:12:50 +00:00
|
|
|
int i, count;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
|
|
|
|
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( ( count + 1 ) * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->edges = out;
|
|
|
|
loadmodel->numedges = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++, in++, out++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
out->v [ 0 ] = (unsigned short) LittleShort( in->v [ 0 ] );
|
|
|
|
out->v [ 1 ] = (unsigned short) LittleShort( in->v [ 1 ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadTexinfo ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
texinfo_t *in;
|
|
|
|
mtexinfo_t *out, *step;
|
2010-10-21 08:12:50 +00:00
|
|
|
int i, j, count;
|
|
|
|
char name [ MAX_QPATH ];
|
|
|
|
int next;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
|
|
|
|
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( count * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->texinfo = out;
|
|
|
|
loadmodel->numtexinfo = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++, in++, out++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( j = 0; j < 8; j++ )
|
|
|
|
{
|
|
|
|
out->vecs [ 0 ] [ j ] = LittleFloat( in->vecs [ 0 ] [ j ] );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
out->flags = LittleLong( in->flags );
|
|
|
|
next = LittleLong( in->nexttexinfo );
|
|
|
|
|
|
|
|
if ( next > 0 )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
out->next = loadmodel->texinfo + next;
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
else
|
2010-10-21 08:12:50 +00:00
|
|
|
{
|
|
|
|
out->next = NULL;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
Com_sprintf( name, sizeof ( name ), "textures/%s.wal", in->texture );
|
|
|
|
|
2010-10-22 09:12:38 +00:00
|
|
|
out->image = R_FindImage( name, it_wall );
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
if ( !out->image )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
ri.Con_Printf( PRINT_ALL, "Couldn't load %s\n", name );
|
2009-03-05 09:07:55 +00:00
|
|
|
out->image = r_notexture;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
/* count animation frames */
|
|
|
|
for ( i = 0; i < count; i++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
out = &loadmodel->texinfo [ i ];
|
2009-03-05 09:07:55 +00:00
|
|
|
out->numframes = 1;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
for ( step = out->next; step && step != out; step = step->next )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
out->numframes++;
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-21 08:12:50 +00:00
|
|
|
* Fills in s->texturemins[] and s->extents[]
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
CalcSurfaceExtents ( msurface_t *s )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
float mins [ 2 ], maxs [ 2 ], val;
|
|
|
|
int i, j, e;
|
|
|
|
mvertex_t *v;
|
|
|
|
mtexinfo_t *tex;
|
|
|
|
int bmins [ 2 ], bmaxs [ 2 ];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
mins [ 0 ] = mins [ 1 ] = 999999;
|
|
|
|
maxs [ 0 ] = maxs [ 1 ] = -99999;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
tex = s->texinfo;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
for ( i = 0; i < s->numedges; i++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
e = loadmodel->surfedges [ s->firstedge + i ];
|
|
|
|
|
|
|
|
if ( e >= 0 )
|
|
|
|
{
|
|
|
|
v = &loadmodel->vertexes [ loadmodel->edges [ e ].v [ 0 ] ];
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
else
|
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
v = &loadmodel->vertexes [ loadmodel->edges [ -e ].v [ 1 ] ];
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( j = 0; j < 2; j++ )
|
|
|
|
{
|
|
|
|
val = v->position [ 0 ] * tex->vecs [ j ] [ 0 ] +
|
|
|
|
v->position [ 1 ] * tex->vecs [ j ] [ 1 ] +
|
|
|
|
v->position [ 2 ] * tex->vecs [ j ] [ 2 ] +
|
|
|
|
tex->vecs [ j ] [ 3 ];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( val < mins [ j ] )
|
|
|
|
{
|
|
|
|
mins [ j ] = val;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( val > maxs [ j ] )
|
|
|
|
{
|
|
|
|
maxs [ j ] = val;
|
|
|
|
}
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < 2; i++ )
|
|
|
|
{
|
|
|
|
bmins [ i ] = floor( mins [ i ] / 16 );
|
|
|
|
bmaxs [ i ] = ceil( maxs [ i ] / 16 );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
s->texturemins [ i ] = bmins [ i ] * 16;
|
|
|
|
s->extents [ i ] = ( bmaxs [ i ] - bmins [ i ] ) * 16;
|
|
|
|
}
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadFaces ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
dface_t *in;
|
|
|
|
msurface_t *out;
|
|
|
|
int i, count, surfnum;
|
|
|
|
int planenum, side;
|
|
|
|
int ti;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
|
|
|
|
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
|
|
|
|
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( count * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->surfaces = out;
|
|
|
|
loadmodel->numsurfaces = count;
|
|
|
|
|
|
|
|
currentmodel = loadmodel;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
GL_BeginBuildingLightmaps( loadmodel );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( surfnum = 0; surfnum < count; surfnum++, in++, out++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
out->firstedge = LittleLong( in->firstedge );
|
|
|
|
out->numedges = LittleShort( in->numedges );
|
2009-03-05 09:07:55 +00:00
|
|
|
out->flags = 0;
|
|
|
|
out->polys = NULL;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
planenum = LittleShort( in->planenum );
|
|
|
|
side = LittleShort( in->side );
|
|
|
|
|
|
|
|
if ( side )
|
|
|
|
{
|
|
|
|
out->flags |= SURF_PLANEBACK;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
out->plane = loadmodel->planes + planenum;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
ti = LittleShort( in->texinfo );
|
|
|
|
|
|
|
|
if ( ( ti < 0 ) || ( ti >= loadmodel->numtexinfo ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: bad texinfo number" );
|
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
out->texinfo = loadmodel->texinfo + ti;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
CalcSurfaceExtents( out );
|
|
|
|
|
|
|
|
/* lighting info */
|
|
|
|
for ( i = 0; i < MAXLIGHTMAPS; i++ )
|
|
|
|
{
|
|
|
|
out->styles [ i ] = in->styles [ i ];
|
|
|
|
}
|
|
|
|
|
|
|
|
i = LittleLong( in->lightofs );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( i == -1 )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
out->samples = NULL;
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
else
|
2010-10-21 08:12:50 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
out->samples = loadmodel->lightdata + i;
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* set the drawing flags */
|
|
|
|
if ( out->texinfo->flags & SURF_WARP )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
out->flags |= SURF_DRAWTURB;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
for ( i = 0; i < 2; i++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
out->extents [ i ] = 16384;
|
|
|
|
out->texturemins [ i ] = -8192;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
GL_SubdivideSurface( out ); /* cut up polygon for warps */
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
/* create lightmaps and polygons */
|
|
|
|
if ( !( out->texinfo->flags & ( SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP ) ) )
|
|
|
|
{
|
|
|
|
GL_CreateSurfaceLightmap( out );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !( out->texinfo->flags & SURF_WARP ) )
|
|
|
|
{
|
|
|
|
GL_BuildPolygonFromSurface( out );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
GL_EndBuildingLightmaps();
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_SetParent ( mnode_t *node, mnode_t *parent )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
node->parent = parent;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
if ( node->contents != -1 )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Mod_SetParent( node->children [ 0 ], node );
|
|
|
|
Mod_SetParent( node->children [ 1 ], node );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadNodes ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
int i, j, count, p;
|
|
|
|
dnode_t *in;
|
|
|
|
mnode_t *out;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
|
|
|
|
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( count * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->nodes = out;
|
|
|
|
loadmodel->numnodes = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++, in++, out++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( j = 0; j < 3; j++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
out->minmaxs [ j ] = LittleShort( in->mins [ j ] );
|
|
|
|
out->minmaxs [ 3 + j ] = LittleShort( in->maxs [ j ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
p = LittleLong( in->planenum );
|
2009-03-05 09:07:55 +00:00
|
|
|
out->plane = loadmodel->planes + p;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
out->firstsurface = LittleShort( in->firstface );
|
|
|
|
out->numsurfaces = LittleShort( in->numfaces );
|
|
|
|
out->contents = -1; /* differentiate from leafs */
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( j = 0; j < 2; j++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
p = LittleLong( in->children [ j ] );
|
|
|
|
|
|
|
|
if ( p >= 0 )
|
|
|
|
{
|
|
|
|
out->children [ j ] = loadmodel->nodes + p;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
else
|
2010-10-21 08:12:50 +00:00
|
|
|
{
|
|
|
|
out->children [ j ] = (mnode_t *) ( loadmodel->leafs + ( -1 - p ) );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
Mod_SetParent( loadmodel->nodes, NULL ); /* sets nodes and leafs */
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadLeafs ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
dleaf_t *in;
|
|
|
|
mleaf_t *out;
|
|
|
|
int i, j, count, p;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
|
|
|
|
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( count * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->leafs = out;
|
|
|
|
loadmodel->numleafs = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++, in++, out++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( j = 0; j < 3; j++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
out->minmaxs [ j ] = LittleShort( in->mins [ j ] );
|
|
|
|
out->minmaxs [ 3 + j ] = LittleShort( in->maxs [ j ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
p = LittleLong( in->contents );
|
2009-03-05 09:07:55 +00:00
|
|
|
out->contents = p;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
out->cluster = LittleShort( in->cluster );
|
|
|
|
out->area = LittleShort( in->area );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
out->firstmarksurface = loadmodel->marksurfaces +
|
2010-10-21 08:12:50 +00:00
|
|
|
LittleShort( in->firstleafface );
|
|
|
|
out->nummarksurfaces = LittleShort( in->numleaffaces );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadMarksurfaces ( lump_t *l )
|
|
|
|
{
|
|
|
|
int i, j, count;
|
|
|
|
short *in;
|
2009-03-05 09:07:55 +00:00
|
|
|
msurface_t **out;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
|
|
|
|
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
|
|
|
|
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( count * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->marksurfaces = out;
|
|
|
|
loadmodel->nummarksurfaces = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
j = LittleShort( in [ i ] );
|
|
|
|
|
|
|
|
if ( ( j < 0 ) || ( j >= loadmodel->numsurfaces ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "Mod_ParseMarksurfaces: bad surface number" );
|
|
|
|
}
|
|
|
|
|
|
|
|
out [ i ] = loadmodel->surfaces + j;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadSurfedges ( lump_t *l )
|
|
|
|
{
|
|
|
|
int i, count;
|
|
|
|
int *in, *out;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
|
|
|
|
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
|
|
|
|
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
|
|
|
|
if ( ( count < 1 ) || ( count >= MAX_MAP_SURFEDGES ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: bad surfedges count in %s: %i",
|
|
|
|
loadmodel->name, count );
|
|
|
|
}
|
|
|
|
|
|
|
|
out = Hunk_Alloc( count * sizeof ( *out ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
loadmodel->surfedges = out;
|
|
|
|
loadmodel->numsurfedges = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++ )
|
|
|
|
{
|
|
|
|
out [ i ] = LittleLong( in [ i ] );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadPlanes ( lump_t *l )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
int i, j;
|
|
|
|
cplane_t *out;
|
|
|
|
dplane_t *in;
|
|
|
|
int count;
|
|
|
|
int bits;
|
|
|
|
|
|
|
|
in = (void *) ( mod_base + l->fileofs );
|
|
|
|
|
|
|
|
if ( l->filelen % sizeof ( *in ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name );
|
|
|
|
}
|
|
|
|
|
|
|
|
count = l->filelen / sizeof ( *in );
|
|
|
|
out = Hunk_Alloc( count * 2 * sizeof ( *out ) );
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
loadmodel->planes = out;
|
|
|
|
loadmodel->numplanes = count;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < count; i++, in++, out++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
bits = 0;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
for ( j = 0; j < 3; j++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
out->normal [ j ] = LittleFloat( in->normal [ j ] );
|
|
|
|
|
|
|
|
if ( out->normal [ j ] < 0 )
|
|
|
|
{
|
|
|
|
bits |= 1 << j;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
out->dist = LittleFloat( in->dist );
|
|
|
|
out->type = LittleLong( in->type );
|
2009-03-05 09:07:55 +00:00
|
|
|
out->signbits = bits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_LoadBrushModel ( model_t *mod, void *buffer )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
int i;
|
|
|
|
dheader_t *header;
|
|
|
|
mmodel_t *bm;
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
loadmodel->type = mod_brush;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
if ( loadmodel != mod_known )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "Loaded a brush model after the world" );
|
|
|
|
}
|
|
|
|
|
|
|
|
header = (dheader_t *) buffer;
|
|
|
|
|
|
|
|
i = LittleLong( header->version );
|
|
|
|
|
|
|
|
if ( i != BSPVERSION )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* swap all the lumps */
|
|
|
|
mod_base = (byte *) header;
|
|
|
|
|
|
|
|
for ( i = 0; i < sizeof ( dheader_t ) / 4; i++ )
|
|
|
|
{
|
|
|
|
( (int *) header ) [ i ] = LittleLong( ( (int *) header ) [ i ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* load into heap */
|
|
|
|
Mod_LoadVertexes( &header->lumps [ LUMP_VERTEXES ] );
|
|
|
|
Mod_LoadEdges( &header->lumps [ LUMP_EDGES ] );
|
|
|
|
Mod_LoadSurfedges( &header->lumps [ LUMP_SURFEDGES ] );
|
|
|
|
Mod_LoadLighting( &header->lumps [ LUMP_LIGHTING ] );
|
|
|
|
Mod_LoadPlanes( &header->lumps [ LUMP_PLANES ] );
|
|
|
|
Mod_LoadTexinfo( &header->lumps [ LUMP_TEXINFO ] );
|
|
|
|
Mod_LoadFaces( &header->lumps [ LUMP_FACES ] );
|
|
|
|
Mod_LoadMarksurfaces( &header->lumps [ LUMP_LEAFFACES ] );
|
|
|
|
Mod_LoadVisibility( &header->lumps [ LUMP_VISIBILITY ] );
|
|
|
|
Mod_LoadLeafs( &header->lumps [ LUMP_LEAFS ] );
|
|
|
|
Mod_LoadNodes( &header->lumps [ LUMP_NODES ] );
|
|
|
|
Mod_LoadSubmodels( &header->lumps [ LUMP_MODELS ] );
|
|
|
|
mod->numframes = 2; /* regular and alternate animation */
|
|
|
|
|
|
|
|
/* set up the submodels */
|
|
|
|
for ( i = 0; i < mod->numsubmodels; i++ )
|
|
|
|
{
|
|
|
|
model_t *starmod;
|
|
|
|
|
|
|
|
bm = &mod->submodels [ i ];
|
|
|
|
starmod = &mod_inline [ i ];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
*starmod = *loadmodel;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
starmod->firstmodelsurface = bm->firstface;
|
|
|
|
starmod->nummodelsurfaces = bm->numfaces;
|
|
|
|
starmod->firstnode = bm->headnode;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( starmod->firstnode >= loadmodel->numnodes )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "Inline model %i has bad firstnode", i );
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorCopy( bm->maxs, starmod->maxs );
|
|
|
|
VectorCopy( bm->mins, starmod->mins );
|
2009-03-05 09:07:55 +00:00
|
|
|
starmod->radius = bm->radius;
|
2010-10-21 08:12:50 +00:00
|
|
|
|
|
|
|
if ( i == 0 )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
*loadmodel = *starmod;
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
starmod->numleafs = bm->visleafs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-21 08:12:50 +00:00
|
|
|
* Specifies the model that will be used as the world
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
R_BeginRegistration ( char *model )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
char fullname [ MAX_QPATH ];
|
|
|
|
cvar_t *flushmap;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
registration_sequence++;
|
2010-10-21 08:12:50 +00:00
|
|
|
r_oldviewcluster = -1; /* force markleafs */
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
Com_sprintf( fullname, sizeof ( fullname ), "maps/%s.bsp", model );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
/* explicitly free the old map if different
|
|
|
|
this guarantees that mod_known[0] is the world map */
|
|
|
|
flushmap = ri.Cvar_Get( "flushmap", "0", 0 );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( strcmp( mod_known [ 0 ].name, fullname ) || flushmap->value )
|
|
|
|
{
|
|
|
|
Mod_Free( &mod_known [ 0 ] );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
r_worldmodel = Mod_ForName( fullname, true );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
r_viewcluster = -1;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
struct model_s *
|
|
|
|
R_RegisterModel ( char *name )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
model_t *mod;
|
|
|
|
int i;
|
|
|
|
dsprite_t *sprout;
|
|
|
|
dmdl_t *pheader;
|
|
|
|
|
|
|
|
mod = Mod_ForName( name, false );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( mod )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
mod->registration_sequence = registration_sequence;
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
/* register any images used by the models */
|
|
|
|
if ( mod->type == mod_sprite )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
sprout = (dsprite_t *) mod->extradata;
|
|
|
|
|
|
|
|
for ( i = 0; i < sprout->numframes; i++ )
|
|
|
|
{
|
2010-10-22 09:12:38 +00:00
|
|
|
mod->skins [ i ] = R_FindImage( sprout->frames [ i ].name, it_sprite );
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
else if ( mod->type == mod_alias )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
pheader = (dmdl_t *) mod->extradata;
|
|
|
|
|
|
|
|
for ( i = 0; i < pheader->num_skins; i++ )
|
|
|
|
{
|
2010-10-22 09:12:38 +00:00
|
|
|
mod->skins [ i ] = R_FindImage( (char *) pheader + pheader->ofs_skins + i * MAX_SKINNAME, it_skin );
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
mod->numframes = pheader->num_frames;
|
|
|
|
}
|
2010-10-21 08:12:50 +00:00
|
|
|
else if ( mod->type == mod_brush )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < mod->numtexinfo; i++ )
|
|
|
|
{
|
|
|
|
mod->texinfo [ i ].image->registration_sequence = registration_sequence;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
return ( mod );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
R_EndRegistration ( void )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
int i;
|
|
|
|
model_t *mod;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0, mod = mod_known; i < mod_numknown; i++, mod++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( !mod->name [ 0 ] )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
continue;
|
2010-10-21 08:12:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( mod->registration_sequence != registration_sequence )
|
|
|
|
{
|
|
|
|
/* don't need this model */
|
|
|
|
Mod_Free( mod );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-22 09:12:38 +00:00
|
|
|
R_FreeUnusedImages();
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_Free ( model_t *mod )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
Hunk_Free( mod->extradata );
|
|
|
|
memset( mod, 0, sizeof ( *mod ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
void
|
|
|
|
Mod_FreeAll ( void )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
int i;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-21 08:12:50 +00:00
|
|
|
for ( i = 0; i < mod_numknown; i++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-21 08:12:50 +00:00
|
|
|
if ( mod_known [ i ].extradatasize )
|
|
|
|
{
|
|
|
|
Mod_Free( &mod_known [ i ] );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
2009-03-05 12:42:43 +00:00
|
|
|
|