2019-03-13 19:20:07 +00:00
/*
2020-06-04 21:01:28 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2019-03-13 19:20:07 +00:00
Copyright ( C ) 1997 - 2001 Id Software , Inc .
2020-06-04 21:01:28 +00:00
This file is part of Quake 2 source code .
2019-03-13 19:20:07 +00:00
2020-06-04 21:01:28 +00:00
Quake 2 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 2 of the License ,
or ( at your option ) any later version .
2019-03-13 19:20:07 +00:00
2020-06-04 21:01:28 +00:00
Quake 2 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 .
2019-03-13 19:20:07 +00:00
You should have received a copy of the GNU General Public License
2020-06-04 21:01:28 +00:00
along with Quake 2 source code ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2019-03-13 19:20:07 +00:00
*/
2020-06-04 21:01:28 +00:00
2019-03-13 19:20:07 +00:00
// r_model.c -- model loading and caching
# include "r_local.h"
model_t * loadmodel ;
int modfilelen ;
void * ModChunk_Begin ( size_t maxsize ) ;
void * ModChunk_Alloc ( size_t size ) ;
size_t ModChunk_End ( void ) ;
void ModChunk_Free ( void * base ) ;
size_t Mod_GetAllocSizeSprite ( model_t * mod , void * buffer ) ;
void Mod_LoadSpriteModel ( model_t * mod , void * buffer ) ;
void Mod_LoadBrushModel ( model_t * mod , void * buffer ) ;
# ifdef MD2_AS_MD3
size_t Mod_GetAllocSizeMD2New ( model_t * mod , void * buffer ) ;
void Mod_LoadAliasMD2ModelNew ( model_t * mod , void * buffer ) ;
# else
size_t Mod_GetAllocSizeMD2Old ( model_t * mod , void * buffer ) ;
void Mod_LoadAliasMD2ModelOld ( model_t * mod , void * buffer ) ;
# endif
//Harven++ MD3
size_t Mod_GetAllocSizeMD3 ( model_t * mod , void * buffer ) ;
void Mod_LoadAliasMD3Model ( model_t * mod , void * buffer ) ;
//Harven-- MD3
model_t * Mod_LoadModel ( model_t * mod , qboolean crash ) ;
byte mod_novis [ MAX_MAP_LEAFS / 8 ] ;
# define MAX_MOD_KNOWN (MAX_MODELS*2) // Knightmare- was 512
model_t mod_known [ MAX_MOD_KNOWN ] ;
int mod_numknown ;
// the inline * models from the current map are kept seperate
model_t mod_inline [ MAX_MOD_KNOWN ] ;
int registration_sequence ;
qboolean registration_active ; // map registration flag
/*
= = = = = = = = = = = = = = =
Mod_PointInLeaf
= = = = = = = = = = = = = = =
*/
mleaf_t * Mod_PointInLeaf ( vec3_t p , model_t * model )
{
mnode_t * node ;
float d ;
cplane_t * plane ;
if ( ! model | | ! model - > nodes )
VID_Error ( ERR_DROP , " Mod_PointInLeaf: bad model " ) ;
node = model - > nodes ;
while ( 1 )
{
if ( node - > contents ! = - 1 )
return ( mleaf_t * ) node ;
plane = node - > plane ;
d = DotProduct ( p , plane - > normal ) - plane - > dist ;
if ( d > 0 )
node = node - > children [ 0 ] ;
else
node = node - > children [ 1 ] ;
}
return NULL ; // never reached
}
/*
= = = = = = = = = = = = = = = = = = =
Mod_DecompressVis
= = = = = = = = = = = = = = = = = = =
*/
byte * Mod_DecompressVis ( byte * in , model_t * model )
{
static byte decompressed [ MAX_MAP_LEAFS / 8 ] ;
int c ;
byte * out ;
int row ;
row = ( model - > vis - > numclusters + 7 ) > > 3 ;
out = decompressed ;
if ( ! in )
{ // no vis info, so make all visible
while ( row )
{
* out + + = 0xff ;
row - - ;
}
return decompressed ;
}
do
{
if ( * in )
{
* out + + = * in + + ;
continue ;
}
c = in [ 1 ] ;
in + = 2 ;
while ( c )
{
* out + + = 0 ;
c - - ;
}
} while ( out - decompressed < row ) ;
return decompressed ;
}
/*
= = = = = = = = = = = = = =
Mod_ClusterPVS
= = = = = = = = = = = = = =
*/
byte * Mod_ClusterPVS ( int cluster , model_t * model )
{
if ( cluster = = - 1 | | ! model - > vis )
return mod_novis ;
return Mod_DecompressVis ( ( byte * ) model - > vis + model - > vis - > bitofs [ cluster ] [ DVIS_PVS ] ,
model ) ;
}
//===============================================================================
/*
= = = = = = = = = = = = = = = =
Mod_Modellist_f
= = = = = = = = = = = = = = = =
*/
void Mod_Modellist_f ( void )
{
int i ;
model_t * mod ;
int total ;
total = 0 ;
VID_Printf ( PRINT_ALL , " Loaded models: \n " ) ;
for ( i = 0 , mod = mod_known ; i < mod_numknown ; i + + , mod + + )
{
if ( ! mod - > name [ 0 ] )
continue ;
VID_Printf ( PRINT_ALL , " %8i : %s \n " , mod - > extradatasize , mod - > name ) ;
total + = mod - > extradatasize ;
}
VID_Printf ( PRINT_ALL , " Total resident: %i \n " , total ) ;
}
/*
= = = = = = = = = = = = = = =
Mod_Init
= = = = = = = = = = = = = = =
*/
void Mod_Init ( void )
{
memset ( mod_novis , 0xff , sizeof ( mod_novis ) ) ;
registration_active = false ; // map registration flag
}
/*
= = = = = = = = = = = = = = = = = =
Mod_ForName
Loads in a model for the given name
= = = = = = = = = = = = = = = = = =
*/
model_t * Mod_ForName ( char * name , qboolean crash )
{
model_t * mod ;
unsigned * buf ;
int i ;
if ( ! name [ 0 ] )
VID_Error ( ERR_DROP , " Mod_ForName: NULL name " ) ;
//
// inline models are grabbed only from worldmodel
//
if ( name [ 0 ] = = ' * ' )
{
i = atoi ( name + 1 ) ;
if ( i < 1 | | ! r_worldmodel | | i > = r_worldmodel - > numsubmodels )
VID_Error ( ERR_DROP , " bad inline model number " ) ;
return & mod_inline [ i ] ;
}
//
// search the currently loaded models
//
for ( i = 0 , mod = mod_known ; i < mod_numknown ; i + + , mod + + )
{
if ( ! mod - > name [ 0 ] )
continue ;
if ( ! strcmp ( mod - > name , name ) )
return mod ;
}
//
// find a free model slot spot
//
for ( i = 0 , mod = mod_known ; i < mod_numknown ; i + + , mod + + )
{
if ( ! mod - > name [ 0 ] )
break ; // free spot
}
if ( i = = mod_numknown )
{
if ( mod_numknown = = MAX_MOD_KNOWN )
VID_Error ( ERR_DROP , " mod_numknown == MAX_MOD_KNOWN " ) ;
mod_numknown + + ;
}
// strncpy (mod->name, name);
Q_strncpyz ( mod - > name , name , sizeof ( mod - > name ) ) ;
//
// load the file
//
modfilelen = FS_LoadFile ( mod - > name , & buf ) ;
if ( ! buf )
{
if ( crash )
VID_Error ( ERR_DROP , " Mod_NumForName: %s not found " , mod - > name ) ;
memset ( mod - > name , 0 , sizeof ( mod - > name ) ) ;
return NULL ;
}
loadmodel = mod ;
//
// fill it in
//
// call the apropriate loader
switch ( LittleLong ( * ( unsigned * ) buf ) )
{
case IDALIASHEADER :
# ifdef MD2_AS_MD3
// loadmodel->extradata = Hunk_Begin (0x800000); // was 0x500000
loadmodel - > extradata = ModChunk_Begin ( Mod_GetAllocSizeMD2New ( mod , buf ) ) ;
Mod_LoadAliasMD2ModelNew ( mod , buf ) ;
# else
// loadmodel->extradata = Hunk_Begin (0x200000);
loadmodel - > extradata = ModChunk_Begin ( Mod_GetAllocSizeMD2Old ( mod , buf ) ) ;
Mod_LoadAliasMD2ModelOld ( mod , buf ) ;
# endif // MD2_AS_MD3
loadmodel - > extradatasize = ModChunk_End ( ) ;
break ;
//Harven++ MD3
case IDMD3HEADER :
// loadmodel->extradata = Hunk_Begin (0x800000);
loadmodel - > extradata = ModChunk_Begin ( Mod_GetAllocSizeMD3 ( mod , buf ) ) ;
Mod_LoadAliasMD3Model ( mod , buf ) ;
loadmodel - > extradatasize = ModChunk_End ( ) ;
break ;
//Harven-- MD3
case IDSPRITEHEADER :
// loadmodel->extradata = Hunk_Begin (0x10000);
loadmodel - > extradata = ModChunk_Begin ( Mod_GetAllocSizeSprite ( mod , buf ) ) ;
Mod_LoadSpriteModel ( mod , buf ) ;
loadmodel - > extradatasize = ModChunk_End ( ) ;
break ;
case IDBSPHEADER :
loadmodel - > extradata = Hunk_Begin ( 0x2000000 ) ; // was 0x1000000
Mod_LoadBrushModel ( mod , buf ) ;
loadmodel - > extradatasize = Hunk_End ( ) ;
break ;
default :
VID_Error ( ERR_DROP , " Mod_NumForName: unknown fileid for %s " , mod - > name ) ;
break ;
}
// loadmodel->extradatasize = Hunk_End ();
FS_FreeFile ( buf ) ;
return mod ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BRUSHMODEL LOADING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
byte * mod_base ;
/*
= = = = = = = = = = = = = = = = =
Mod_LoadLighting
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadLighting ( lump_t * l )
{
if ( ! l - > filelen )
{
loadmodel - > lightdata = NULL ;
return ;
}
loadmodel - > lightdata = Hunk_Alloc ( l - > filelen ) ;
memcpy ( loadmodel - > lightdata , mod_base + l - > fileofs , l - > filelen ) ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadVisibility
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadVisibility ( lump_t * l )
{
int i ;
if ( ! l - > filelen )
{
loadmodel - > vis = NULL ;
return ;
}
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 + + )
{
loadmodel - > vis - > bitofs [ i ] [ 0 ] = LittleLong ( loadmodel - > vis - > bitofs [ i ] [ 0 ] ) ;
loadmodel - > vis - > bitofs [ i ] [ 1 ] = LittleLong ( loadmodel - > vis - > bitofs [ i ] [ 1 ] ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadVertexes
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadVertexes ( lump_t * l )
{
dvertex_t * in ;
mvertex_t * out ;
int i , count ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
loadmodel - > vertexes = out ;
loadmodel - > numvertexes = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out - > position [ 0 ] = LittleFloat ( in - > point [ 0 ] ) ;
out - > position [ 1 ] = LittleFloat ( in - > point [ 1 ] ) ;
out - > position [ 2 ] = LittleFloat ( in - > point [ 2 ] ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
RadiusFromBounds
= = = = = = = = = = = = = = = = =
*/
float RadiusFromBounds ( vec3_t mins , vec3_t maxs )
{
int i ;
vec3_t corner ;
for ( i = 0 ; i < 3 ; i + + )
{
corner [ i ] = fabs ( mins [ i ] ) > fabs ( maxs [ i ] ) ? fabs ( mins [ i ] ) : fabs ( maxs [ i ] ) ;
}
return VectorLength ( corner ) ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadSubmodels
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadSubmodels ( lump_t * l )
{
dmodel_t * in ;
mmodel_t * out ;
int i , j , count ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
// Knightmare- catch submodel overflow
if ( count > = MAX_MOD_KNOWN )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: too many submodels (%i >= %i) in %s " , count , MAX_MOD_KNOWN , loadmodel - > name ) ;
loadmodel - > submodels = out ;
loadmodel - > numsubmodels = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
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 ] ) ;
}
out - > radius = RadiusFromBounds ( out - > mins , out - > maxs ) ;
out - > headnode = LittleLong ( in - > headnode ) ;
out - > firstface = LittleLong ( in - > firstface ) ;
out - > numfaces = LittleLong ( in - > numfaces ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadEdges
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadEdges ( lump_t * l )
{
dedge_t * in ;
medge_t * out ;
int i , count ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_Alloc ( ( count + 1 ) * sizeof ( * out ) ) ;
loadmodel - > edges = out ;
loadmodel - > numedges = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out - > v [ 0 ] = ( unsigned short ) LittleShort ( in - > v [ 0 ] ) ;
out - > v [ 1 ] = ( unsigned short ) LittleShort ( in - > v [ 1 ] ) ;
}
}
//=======================================================
// store the names of last textures that failed to load
2019-06-05 23:08:30 +00:00
# define NUM_FAIL_TEXTURES 256
2019-03-13 19:20:07 +00:00
char lastFailedTexture [ NUM_FAIL_TEXTURES ] [ MAX_OSPATH ] ;
2020-08-02 02:54:35 +00:00
unsigned int lastFailedTextureHash [ NUM_FAIL_TEXTURES ] ;
2019-03-13 19:20:07 +00:00
static unsigned failedTexListIndex ;
/*
= = = = = = = = = = = = = = =
Mod_InitFailedTexList
= = = = = = = = = = = = = = =
*/
void Mod_InitFailedTexList ( void )
{
int i ;
for ( i = 0 ; i < NUM_FAIL_TEXTURES ; i + + ) {
Com_sprintf ( lastFailedTexture [ i ] , sizeof ( lastFailedTexture [ i ] ) , " \0 " ) ;
lastFailedTextureHash [ i ] = 0 ;
}
failedTexListIndex = 0 ;
}
/*
= = = = = = = = = = = = = = =
Mod_CheckTexFailed
= = = = = = = = = = = = = = =
*/
qboolean Mod_CheckTexFailed ( char * name )
{
2020-08-02 02:54:35 +00:00
int i ;
unsigned int hash ;
2019-03-13 19:20:07 +00:00
hash = Com_HashFileName ( name , 0 , false ) ;
for ( i = 0 ; i < NUM_FAIL_TEXTURES ; i + + )
{
if ( hash = = lastFailedTextureHash [ i ] ) { // compare hash first
if ( lastFailedTexture [ i ] & & strlen ( lastFailedTexture [ i ] )
& & ! strcmp ( name , lastFailedTexture [ i ] ) )
{ // we already tried to load this image, didn't find it
return true ;
}
}
}
return false ;
}
/*
= = = = = = = = = = = = = = =
Mod_AddToFailedTexList
= = = = = = = = = = = = = = =
*/
void Mod_AddToFailedTexList ( char * name )
{
Com_sprintf ( lastFailedTexture [ failedTexListIndex ] , sizeof ( lastFailedTexture [ failedTexListIndex ] ) , " %s " , name ) ;
lastFailedTextureHash [ failedTexListIndex ] = Com_HashFileName ( name , 0 , false ) ;
failedTexListIndex + + ;
// wrap around to start of list
if ( failedTexListIndex > = NUM_FAIL_TEXTURES )
failedTexListIndex = 0 ;
}
/*
= = = = = = = = = = = = = = =
Mod_FindTexture
A wrapper function that uses a failed list
to speed map load times
= = = = = = = = = = = = = = =
*/
image_t * Mod_FindTexture ( char * name , imagetype_t type )
{
image_t * image ;
// don't try again to load a texture that just failed
if ( Mod_CheckTexFailed ( name ) )
return glMedia . notexture ;
image = R_FindImage ( name , type ) ;
if ( ! image | | ( image = = glMedia . notexture ) )
Mod_AddToFailedTexList ( name ) ;
return image ;
}
//=======================================================
// store the names and sizes of size reference .wal files
typedef struct walsize_s
{
2020-08-02 02:54:35 +00:00
char name [ MAX_OSPATH ] ;
unsigned int hash ;
int width ;
int height ;
2019-03-13 19:20:07 +00:00
} walsize_t ;
2019-06-05 23:08:30 +00:00
# define NUM_WALSIZES 1024
2019-03-13 19:20:07 +00:00
walsize_t walSizeList [ NUM_WALSIZES ] ;
static unsigned walSizeListIndex ;
/*
= = = = = = = = = = = = = = =
Mod_InitWalSizeList
= = = = = = = = = = = = = = =
*/
void Mod_InitWalSizeList ( void )
{
int i ;
for ( i = 0 ; i < NUM_WALSIZES ; i + + ) {
Com_sprintf ( walSizeList [ i ] . name , sizeof ( walSizeList [ i ] . name ) , " \0 " ) ;
walSizeList [ i ] . hash = 0 ;
walSizeList [ i ] . width = 0 ;
walSizeList [ i ] . height = 0 ;
}
walSizeListIndex = 0 ;
}
/*
= = = = = = = = = = = = = = =
Mod_CheckWalSizeList
= = = = = = = = = = = = = = =
*/
qboolean Mod_CheckWalSizeList ( const char * name , int * width , int * height )
{
2020-08-02 02:54:35 +00:00
int i ;
unsigned int hash ;
2019-03-13 19:20:07 +00:00
hash = Com_HashFileName ( name , 0 , false ) ;
for ( i = 0 ; i < NUM_WALSIZES ; i + + )
{
if ( hash = = walSizeList [ i ] . hash ) { // compare hash first
if ( walSizeList [ i ] . name & & strlen ( walSizeList [ i ] . name )
& & ! strcmp ( name , walSizeList [ i ] . name ) )
{ // return size of texture
if ( width )
* width = walSizeList [ i ] . width ;
if ( height )
* height = walSizeList [ i ] . height ;
return true ;
}
}
}
return false ;
}
/*
= = = = = = = = = = = = = = =
Mod_AddToWalSizeList
= = = = = = = = = = = = = = =
*/
void Mod_AddToWalSizeList ( const char * name , int width , int height )
{
Com_sprintf ( walSizeList [ walSizeListIndex ] . name , sizeof ( walSizeList [ walSizeListIndex ] . name ) , " %s " , name ) ;
walSizeList [ walSizeListIndex ] . hash = Com_HashFileName ( name , 0 , false ) ;
walSizeList [ walSizeListIndex ] . width = width ;
walSizeList [ walSizeListIndex ] . height = height ;
walSizeListIndex + + ;
// wrap around to start of list
if ( walSizeListIndex > = NUM_WALSIZES )
walSizeListIndex = 0 ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_GetWalSize
Adapted from Q2E
= = = = = = = = = = = = = = = = =
*/
static void Mod_GetWalSize ( const char * name , int * width , int * height )
{
char path [ MAX_QPATH ] ;
miptex_t * mt ;
Com_sprintf ( path , sizeof ( path ) , " textures/%s.wal " , name ) ;
if ( Mod_CheckWalSizeList ( name , width , height ) ) // check if already in list
return ;
FS_LoadFile ( path , ( void * * ) & mt ) ; // load .wal file
if ( ! mt )
{ // set null value to tell us to get actual size of texture
* width = * height = - 1 ;
Mod_AddToWalSizeList ( name , * width , * height ) ; // add to list
return ;
}
* width = LittleLong ( mt - > width ) ; // grab size from wal
* height = LittleLong ( mt - > height ) ;
FS_FreeFile ( ( void * ) mt ) ; // free the wal
Mod_AddToWalSizeList ( name , * width , * height ) ; // add to list
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadTexinfo
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadTexinfo ( lump_t * l )
{
texinfo_t * in ;
mtexinfo_t * out , * step ;
int i , j , count ;
char name [ MAX_QPATH ] ;
int next ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
loadmodel - > texinfo = out ;
loadmodel - > numtexinfo = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
for ( j = 0 ; j < 8 ; j + + )
out - > vecs [ 0 ] [ j ] = LittleFloat ( in - > vecs [ 0 ] [ j ] ) ;
out - > flags = LittleLong ( in - > flags ) ;
next = LittleLong ( in - > nexttexinfo ) ;
if ( next > 0 )
out - > next = loadmodel - > texinfo + next ;
else
out - > next = NULL ;
Com_sprintf ( name , sizeof ( name ) , " textures/%s.wal " , in - > texture ) ;
out - > image = Mod_FindTexture ( name , it_wall ) ; // was R_FindImage
if ( ! out - > image )
{
VID_Printf ( PRINT_ALL , " Couldn't load %s \n " , name ) ;
out - > image = glMedia . notexture ;
}
// Added glow
Com_sprintf ( name , sizeof ( name ) , " textures/%s_glow.wal " , in - > texture ) ;
out - > glow = Mod_FindTexture ( name , it_skin ) ; // was R_FindImage
if ( ! out - > glow )
out - > glow = glMedia . notexture ;
// Q2E HACK: find .wal dimensions for texture coord generation
// NOTE: Once Q3 map support is added, be be sure to disable this
// for Q3 format maps, because they will be natively textured with
// hi-res textures.
Mod_GetWalSize ( in - > texture , & out - > texWidth , & out - > texHeight ) ;
// If no .wal texture was found, use width & height of actual texture
if ( out - > texWidth = = - 1 | | out - > texHeight = = - 1 )
{
out - > texWidth = out - > image - > width ;
out - > texHeight = out - > image - > height ;
}
}
// count animation frames
for ( i = 0 ; i < count ; i + + )
{
out = & loadmodel - > texinfo [ i ] ;
out - > numframes = 1 ;
for ( step = out - > next ; step & & step ! = out ; step = step - > next )
out - > numframes + + ;
}
}
/*
= = = = = = = = = = = = = = = =
CalcSurfaceExtents
Fills in s - > texturemins [ ] and s - > extents [ ]
= = = = = = = = = = = = = = = =
*/
void CalcSurfaceExtents ( msurface_t * s )
{
float mins [ 2 ] , maxs [ 2 ] , val ;
int i , j , e ;
mvertex_t * v ;
mtexinfo_t * tex ;
int bmins [ 2 ] , bmaxs [ 2 ] ;
mins [ 0 ] = mins [ 1 ] = 999999 ;
maxs [ 0 ] = maxs [ 1 ] = - 99999 ;
tex = s - > texinfo ;
for ( i = 0 ; i < s - > numedges ; i + + )
{
e = loadmodel - > surfedges [ s - > firstedge + i ] ;
if ( e > = 0 )
v = & loadmodel - > vertexes [ loadmodel - > edges [ e ] . v [ 0 ] ] ;
else
v = & loadmodel - > vertexes [ loadmodel - > edges [ - e ] . v [ 1 ] ] ;
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 ] ;
if ( val < mins [ j ] )
mins [ j ] = val ;
if ( val > maxs [ j ] )
maxs [ j ] = val ;
}
}
for ( i = 0 ; i < 2 ; i + + )
{
bmins [ i ] = floor ( mins [ i ] / 16 ) ;
bmaxs [ i ] = ceil ( maxs [ i ] / 16 ) ;
s - > texturemins [ i ] = bmins [ i ] * 16 ;
s - > extents [ i ] = ( bmaxs [ i ] - bmins [ i ] ) * 16 ;
// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
// VID_Error (ERR_DROP, "Bad surface extents");
}
}
void R_BuildPolygonFromSurface ( msurface_t * fa ) ;
void R_CreateSurfaceLightmap ( msurface_t * surf ) ;
void R_EndBuildingLightmaps ( void ) ;
void R_BeginBuildingLightmaps ( model_t * m ) ;
/*
= = = = = = = = = = = = = = = = =
Mod_LoadFaces
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadFaces ( lump_t * l )
{
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 ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
loadmodel - > surfaces = out ;
loadmodel - > numsurfaces = count ;
currentmodel = loadmodel ;
R_BeginBuildingLightmaps ( loadmodel ) ;
for ( surfnum = 0 ; surfnum < count ; surfnum + + , in + + , out + + )
{
out - > firstedge = LittleLong ( in - > firstedge ) ;
out - > numedges = LittleShort ( in - > numedges ) ;
out - > flags = 0 ;
out - > polys = NULL ;
planenum = LittleShort ( in - > planenum ) ;
side = LittleShort ( in - > side ) ;
if ( side )
out - > flags | = SURF_PLANEBACK ;
out - > plane = loadmodel - > planes + planenum ;
ti = LittleShort ( in - > texinfo ) ;
if ( ti < 0 | | ti > = loadmodel - > numtexinfo )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: bad texinfo number " ) ;
out - > texinfo = loadmodel - > texinfo + ti ;
CalcSurfaceExtents ( out ) ;
// lighting info
for ( i = 0 ; i < MAXLIGHTMAPS ; i + + )
out - > styles [ i ] = in - > styles [ i ] ;
i = LittleLong ( in - > lightofs ) ;
if ( i = = - 1 )
out - > samples = NULL ;
else
out - > samples = loadmodel - > lightdata + i ;
// set the drawing flags
if ( out - > texinfo - > flags & SURF_WARP )
{
out - > flags | = SURF_DRAWTURB ;
for ( i = 0 ; i < 2 ; i + + )
{
2020-02-23 19:07:48 +00:00
out - > extents [ i ] = ( WORLD_SIZE * 2 ) ; // was 16384
out - > texturemins [ i ] = - WORLD_SIZE ; // was -8192
2019-03-13 19:20:07 +00:00
}
R_SubdivideSurface ( out ) ; // cut up polygon for warps
}
// Knightmare- Psychospaz's envmapping
// windows get glass (envmap) effect... -psychospaz
// but warp surfaces and solid alphas don't
else if ( out - > texinfo - > flags & ( SURF_TRANS33 | SURF_TRANS66 ) )
//&& !((out->texinfo->flags & SURF_TRANS33) && (out->texinfo->flags & SURF_TRANS66)) )
{
if ( ! ( out - > texinfo - > flags & SURF_NOLIGHTENV ) )
out - > flags | = SURF_ENVMAP ;
}
// create lightmaps and polygons
//if ( !(out->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP) ) )
if ( ! ( out - > texinfo - > flags & ( SURF_SKY | SURF_WARP ) ) )
R_CreateSurfaceLightmap ( out ) ;
if ( ! ( out - > texinfo - > flags & SURF_WARP ) )
R_BuildPolygonFromSurface ( out ) ;
}
R_EndBuildingLightmaps ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_SetParent
= = = = = = = = = = = = = = = = =
*/
void Mod_SetParent ( mnode_t * node , mnode_t * parent )
{
node - > parent = parent ;
if ( node - > contents ! = - 1 )
return ;
Mod_SetParent ( node - > children [ 0 ] , node ) ;
Mod_SetParent ( node - > children [ 1 ] , node ) ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadNodes
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadNodes ( lump_t * l )
{
int i , j , count , p ;
dnode_t * in ;
mnode_t * out ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
loadmodel - > nodes = out ;
loadmodel - > numnodes = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
out - > minmaxs [ j ] = LittleShort ( in - > mins [ j ] ) ;
out - > minmaxs [ 3 + j ] = LittleShort ( in - > maxs [ j ] ) ;
}
p = LittleLong ( in - > planenum ) ;
out - > plane = loadmodel - > planes + p ;
out - > firstsurface = LittleShort ( in - > firstface ) ;
out - > numsurfaces = LittleShort ( in - > numfaces ) ;
out - > contents = - 1 ; // differentiate from leafs
for ( j = 0 ; j < 2 ; j + + )
{
p = LittleLong ( in - > children [ j ] ) ;
if ( p > = 0 )
out - > children [ j ] = loadmodel - > nodes + p ;
else
out - > children [ j ] = ( mnode_t * ) ( loadmodel - > leafs + ( - 1 - p ) ) ;
}
}
Mod_SetParent ( loadmodel - > nodes , NULL ) ; // sets nodes and leafs
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadLeafs
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadLeafs ( lump_t * l )
{
dleaf_t * in ;
mleaf_t * out ;
int i , j , count , p ;
glpoly_t * poly ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
loadmodel - > leafs = out ;
loadmodel - > numleafs = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
out - > minmaxs [ j ] = LittleShort ( in - > mins [ j ] ) ;
out - > minmaxs [ 3 + j ] = LittleShort ( in - > maxs [ j ] ) ;
}
p = LittleLong ( in - > contents ) ;
out - > contents = p ;
out - > cluster = LittleShort ( in - > cluster ) ;
out - > area = LittleShort ( in - > area ) ;
out - > firstmarksurface = loadmodel - > marksurfaces +
( unsigned short ) LittleShort ( in - > firstleafface ) ; // Knightmare- make sure this doesn't turn negative!
out - > nummarksurfaces = LittleShort ( in - > numleaffaces ) ;
// underwater flag for caustics
//if (out->contents & (CONTENTS_WATER|CONTENTS_SLIME) )
if ( out - > contents & ( MASK_WATER ) )
{ unsigned int flag ;
if ( out - > contents & CONTENTS_LAVA )
flag = SURF_UNDERLAVA ;
else if ( out - > contents & CONTENTS_SLIME )
flag = SURF_UNDERSLIME ;
else
flag = SURF_UNDERWATER ;
for ( j = 0 ; j < out - > nummarksurfaces ; j + + )
{
out - > firstmarksurface [ j ] - > flags | = flag ;
for ( poly = out - > firstmarksurface [ j ] - > polys ; poly ; poly = poly - > next )
poly - > flags | = flag ;
}
}
}
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadMarksurfaces
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadMarksurfaces ( lump_t * l )
{
int i , j , count ;
unsigned short * in ; // Knightmare- changed to unsigned short
msurface_t * * out ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
loadmodel - > marksurfaces = out ;
loadmodel - > nummarksurfaces = count ;
for ( i = 0 ; i < count ; i + + )
{
j = ( unsigned short ) LittleShort ( in [ i ] ) ; // Knightmare- make this unsigned!
if ( j < 0 | | j > = loadmodel - > numsurfaces )
VID_Error ( ERR_DROP , " Mod_ParseMarksurfaces: bad surface number " ) ;
out [ i ] = loadmodel - > surfaces + j ;
}
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadSurfedges
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadSurfedges ( lump_t * l )
{
int i , count ;
int * in , * out ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 | | count > = MAX_MAP_SURFEDGES )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: bad surfedges count in %s: %i " ,
loadmodel - > name , count ) ;
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
loadmodel - > surfedges = out ;
loadmodel - > numsurfedges = count ;
for ( i = 0 ; i < count ; i + + )
out [ i ] = LittleLong ( in [ i ] ) ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadPlanes
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadPlanes ( lump_t * l )
{
int i , j ;
cplane_t * out ;
dplane_t * in ;
int count ;
int bits ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
VID_Error ( ERR_DROP , " MOD_LoadBmodel: funny lump size in %s " , loadmodel - > name ) ;
count = l - > filelen / sizeof ( * in ) ;
//original bug- Quake2Max
// out = Hunk_Alloc ( count*2*sizeof(*out));
out = Hunk_Alloc ( count * sizeof ( * out ) ) ;
loadmodel - > planes = out ;
loadmodel - > numplanes = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
bits = 0 ;
for ( j = 0 ; j < 3 ; j + + )
{
out - > normal [ j ] = LittleFloat ( in - > normal [ j ] ) ;
if ( out - > normal [ j ] < 0 )
bits | = 1 < < j ;
}
out - > dist = LittleFloat ( in - > dist ) ;
out - > type = LittleLong ( in - > type ) ;
out - > signbits = bits ;
}
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadBrushModel
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadBrushModel ( model_t * mod , void * buffer )
{
int i ;
dheader_t * header ;
mmodel_t * bm ;
loadmodel - > type = mod_brush ;
if ( loadmodel ! = mod_known )
VID_Error ( ERR_DROP , " Loaded a brush model after the world " ) ;
header = ( dheader_t * ) buffer ;
i = LittleLong ( header - > version ) ;
if ( i ! = BSPVERSION )
VID_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 ] ;
* starmod = * loadmodel ;
starmod - > firstmodelsurface = bm - > firstface ;
starmod - > nummodelsurfaces = bm - > numfaces ;
starmod - > firstnode = bm - > headnode ;
if ( starmod - > firstnode > = loadmodel - > numnodes )
VID_Error ( ERR_DROP , " Inline model %i has bad firstnode " , i ) ;
VectorCopy ( bm - > maxs , starmod - > maxs ) ;
VectorCopy ( bm - > mins , starmod - > mins ) ;
starmod - > radius = bm - > radius ;
if ( i = = 0 )
* loadmodel = * starmod ;
starmod - > numleafs = bm - > visleafs ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
MODEL MEMORY ALLOCATION
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
// It turns out that the Hunk_Begin(), Hunk_Alloc(), and Hunk_Free()
// functions used for BSP, alias model, and sprite loading are a wrapper around
// VirtualAlloc()/VirtualFree() on Win32 and they should only be used
// rarely and for large blocks of memory. After about 185-190 VirtualAlloc()
// reserve calls are made on Win7 x64, the subsequent call fails. Bad Carmack, bad!
// These ModChunk_ functions are a replacement that wrap around malloc()/free()
// and return pointers into sections aligned on cache lines.
// The only caveat is that the allocation size passed to ModChunk_Begin() is
// immediately allocated, not reserved. Calling it with a maximum memory size
// for each model type would be hugely wasteful. So a size equal or greater to
// the total amount requested via ModChunk_Alloc() calls in the model loading
// functions must be calculated first.
int modChunkCount ;
byte * modChunkMemBase ;
size_t modChunkMaxSize ;
size_t modChunkCurSize ;
void * ModChunk_Begin ( size_t maxsize )
{
// alocate a chunk of memory, should be exact size needed!
modChunkCurSize = 0 ;
modChunkMaxSize = maxsize ;
modChunkMemBase = malloc ( maxsize ) ;
if ( ! modChunkMemBase )
Sys_Error ( " ModChunk_Begin: malloc of size %i failed, %i chunks already allocated " , maxsize , modChunkCount ) ;
memset ( modChunkMemBase , 0 , maxsize ) ;
return ( void * ) modChunkMemBase ;
}
void * ModChunk_Alloc ( size_t size )
{
// round to cacheline
size = ( size + 31 ) & ~ 31 ;
modChunkCurSize + = size ;
if ( modChunkCurSize > modChunkMaxSize )
Sys_Error ( " ModChunk_Alloc: overflow " ) ;
return ( void * ) ( modChunkMemBase + modChunkCurSize - size ) ;
}
size_t ModChunk_End ( void )
{
// free the remaining unused virtual memory
modChunkCount + + ;
// VID_Printf (PRINT_ALL, "modChunkCount: %i\n", modChunkCount);
return modChunkCurSize ;
}
void ModChunk_Free ( void * base )
{
if ( base )
free ( base ) ;
modChunkCount - - ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
ALIAS MODELS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = =
Mod_ParseBlendMode
md3 skin protoshaders
= = = = = = = = = = = = = = = = =
*/
GLenum Mod_ParseBlendMode ( char * name )
{
if ( ! name ) return - 1 ;
if ( ! Q_strcasecmp ( name , " gl_zero " ) )
return GL_ZERO ;
if ( ! Q_strcasecmp ( name , " gl_one " ) )
return GL_ONE ;
if ( ! Q_strcasecmp ( name , " gl_src_color " ) )
return GL_SRC_COLOR ;
if ( ! Q_strcasecmp ( name , " gl_one_minus_src_color " ) )
return GL_ONE_MINUS_SRC_COLOR ;
if ( ! Q_strcasecmp ( name , " gl_src_alpha " ) )
return GL_SRC_ALPHA ;
if ( ! Q_strcasecmp ( name , " gl_one_minus_src_alpha " ) )
return GL_ONE_MINUS_SRC_ALPHA ;
if ( ! Q_strcasecmp ( name , " gl_dst_alpha " ) )
return GL_DST_ALPHA ;
if ( ! Q_strcasecmp ( name , " gl_one_minus_dst_alpha " ) )
return GL_ONE_MINUS_DST_ALPHA ;
if ( ! Q_strcasecmp ( name , " gl_dst_color " ) )
return GL_DST_COLOR ;
if ( ! Q_strcasecmp ( name , " gl_one_minus_dst_color " ) )
return GL_ONE_MINUS_DST_COLOR ;
if ( ! Q_strcasecmp ( name , " gl_src_alpha_saturate " ) )
return GL_SRC_ALPHA_SATURATE ;
if ( ! Q_strcasecmp ( name , " gl_constant_color " ) )
return GL_CONSTANT_COLOR ;
if ( ! Q_strcasecmp ( name , " gl_one_minus_constant_color " ) )
return GL_ONE_MINUS_CONSTANT_COLOR ;
if ( ! Q_strcasecmp ( name , " gl_constant_alpha " ) )
return GL_CONSTANT_ALPHA ;
if ( ! Q_strcasecmp ( name , " gl_one_minus_constant_alpha " ) )
return GL_ONE_MINUS_CONSTANT_ALPHA ;
else
return - 1 ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_GetNextParm
md3 skin protoshaders
= = = = = = = = = = = = = = = = =
*/
qboolean Mod_GetNextParm ( char * * data , char * * output )
{
if ( ! * data ) return false ;
* output = COM_ParseExt ( data , false ) ;
if ( ! * data ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: EOF without closing brace \n " ) ;
return false ;
}
if ( ! * output [ 0 ] )
return false ;
if ( * output [ 0 ] = = ' } ' ) {
// VID_Printf (PRINT_ALL, S_COLOR_YELLOW"Mod_ParseModelScript: closing brace without data\n");
return false ;
}
return true ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_ParseWaveFunc
md3 skin protoshaders
= = = = = = = = = = = = = = = = =
*/
qboolean Mod_ParseWaveFunc ( char * * data , waveForm_t * out )
{
char * tok = NULL ;
if ( ! * data | | ! out ) return false ;
if ( ! Mod_GetNextParm ( data , & tok ) )
return false ;
if ( ! Q_strcasecmp ( tok , " sin " ) )
* out = WAVEFORM_SIN ;
else if ( ! Q_strcasecmp ( tok , " triangle " ) )
* out = WAVEFORM_TRIANGLE ;
else if ( ! Q_strcasecmp ( tok , " square " ) )
* out = WAVEFORM_SQUARE ;
else if ( ! Q_strcasecmp ( tok , " sawtooth " ) )
* out = WAVEFORM_SAWTOOTH ;
else if ( ! Q_strcasecmp ( tok , " inversesawtooth " ) )
* out = WAVEFORM_INVERSESAWTOOTH ;
else if ( ! Q_strcasecmp ( tok , " noise " ) )
* out = WAVEFORM_NOISE ;
else {
* out = - 1 ;
return false ;
}
return true ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_ParseFloat
md3 skin protoshaders
= = = = = = = = = = = = = = = = =
*/
qboolean Mod_ParseFloat ( char * * data , float * outnum , qboolean normalized )
{
char * token = NULL ;
if ( ! * data | | ! outnum ) return false ;
if ( ! Mod_GetNextParm ( data , & token ) )
return false ;
if ( normalized )
* outnum = max ( min ( atof ( token ) , 1.0f ) , 0.0f ) ;
else
* outnum = atof ( token ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_ParseModelScript
skin protoshaders
= = = = = = = = = = = = = = = = =
*/
void Mod_ParseModelScript ( maliasskin_t * skin , char * * data , char * dataStart , int dataSize , char * meshname , int skinnum , char * scriptname )
{
char * token = NULL , * token2 = NULL ;
char glowname [ MD3_MAX_PATH ] ;
int i ;
renderparms_t * skinParms = & skin - > renderparms ;
// get the opening curly brace
token = COM_ParseExt ( data , true ) ;
if ( ! * data ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: unexpected EOF in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
return ;
}
if ( token [ 0 ] ! = ' { ' ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: found %s when expecting { in %s.%i in %s \n " , token , meshname , skinnum , scriptname ) ;
return ;
}
// go through all the parms
while ( * data < ( dataStart + dataSize ) )
{
token = COM_ParseExt ( data , true ) ;
if ( ! * data ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: EOF in %s.%i in %s without closing brace \n " , meshname , skinnum , scriptname ) ;
break ;
}
if ( token [ 0 ] = = ' } ' ) break ; // end of skin
if ( ! Q_strcasecmp ( token , " twosided " ) )
skinParms - > twosided = true ;
else if ( ! Q_strcasecmp ( token , " alphatest " ) ) {
skinParms - > alphatest = true ;
skinParms - > noshadow = true ; // also noshadow
}
else if ( ! Q_strcasecmp ( token , " fullbright " ) )
skinParms - > fullbright = true ;
else if ( ! Q_strcasecmp ( token , " nodraw " ) ) {
skinParms - > nodraw = true ;
skinParms - > noshadow = true ; // also noshadow
}
else if ( ! Q_strcasecmp ( token , " noshadow " ) )
skinParms - > noshadow = true ;
else if ( ! Q_strcasecmp ( token , " nodiffuse " ) )
skinParms - > nodiffuse = true ;
else if ( ! Q_strcasecmp ( token , " envmap " ) )
{
if ( ! Mod_ParseFloat ( data , & skinParms - > envmap , true ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameter for 'envmap' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
}
else if ( ! Q_strcasecmp ( token , " alpha " ) | | ! Q_strcasecmp ( token , " trans " ) )
{
if ( ! Mod_ParseFloat ( data , & skinParms - > basealpha , true ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameter for 'alpha' or 'trans' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
}
else if ( ! Q_strcasecmp ( token , " tcmod " ) )
{
if ( ! Mod_GetNextParm ( data , & token ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameter for 'tcmod' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
if ( ! Q_strcasecmp ( token , " translate " ) ) {
if ( ! Mod_ParseFloat ( data , & skinParms - > translate_x , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameters for 'tcmod translate' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
if ( ! Mod_ParseFloat ( data , & skinParms - > translate_y , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameter for 'tcmod translate' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
skinParms - > translate_x = 0.0f ;
break ;
}
}
else if ( ! Q_strcasecmp ( token , " rotate " ) ) {
if ( ! Mod_ParseFloat ( data , & skinParms - > rotate , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameter for 'tcmod rotate' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
}
else if ( ! Q_strcasecmp ( token , " scale " ) ) {
if ( ! Mod_ParseFloat ( data , & skinParms - > scale_x , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameters for 'tcmod scale' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
if ( ! Mod_ParseFloat ( data , & skinParms - > scale_y , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameter for 'tcmod scale' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
skinParms - > scale_x = 1.0f ;
break ;
}
}
else if ( ! Q_strcasecmp ( token , " stretch " ) )
{
if ( ! Mod_ParseWaveFunc ( data , & skinParms - > stretch . type ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing or invalid waveform for 'tcmod stretch' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
for ( i = 0 ; i < 4 ; i + + )
if ( ! Mod_ParseFloat ( data , & skinParms - > stretch . params [ i ] , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameters for 'tcmod stretch' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
}
else if ( ! Q_strcasecmp ( token , " turb " ) )
{ // first parm (base) is unused, so just read twice
for ( i = 0 ; i < 4 ; i + + )
if ( ! Mod_ParseFloat ( data , & skinParms - > turb . params [ i ] , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameters for 'tcmod turb' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
skinParms - > turb . type = WAVEFORM_SIN ;
}
else if ( ! Q_strcasecmp ( token , " scroll " ) )
{
if ( ! Mod_ParseFloat ( data , & skinParms - > scroll_x , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameters for 'tcmod scroll' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
if ( ! Mod_ParseFloat ( data , & skinParms - > scroll_y , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameter for 'tcmod scroll' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
skinParms - > scroll_x = 0.0f ;
break ;
}
}
else {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: unknown type '%s' for 'tcmod' in %s.%i in %s \n " , token , meshname , skinnum , scriptname ) ;
break ;
}
}
else if ( ! Q_strcasecmp ( token , " blendfunc " ) )
{ // parse blend parm
if ( ! Mod_GetNextParm ( data , & token ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameter(s) for 'blendfunc' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
if ( ! Q_strcasecmp ( token , " add " ) ) {
skinParms - > blendfunc_src = GL_ONE ;
skinParms - > blendfunc_dst = GL_ONE ;
}
else if ( ! Q_strcasecmp ( token , " filter " ) ) {
skinParms - > blendfunc_src = GL_DST_COLOR ;
skinParms - > blendfunc_dst = GL_ZERO ;
}
else if ( ! Q_strcasecmp ( token , " blend " ) ) {
skinParms - > blendfunc_src = GL_SRC_ALPHA ;
skinParms - > blendfunc_dst = GL_ONE_MINUS_SRC_ALPHA ;
}
else
{ // parse 2nd blend parm
if ( ! Mod_GetNextParm ( data , & token2 ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing 2nd parameter for 'blendfunc' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
skinParms - > blendfunc_src = Mod_ParseBlendMode ( token ) ;
if ( skinParms - > blendfunc_src = = - 1 ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: invalid src blend func in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
skinParms - > blendfunc_dst = Mod_ParseBlendMode ( token2 ) ;
if ( skinParms - > blendfunc_dst = = - 1 ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: invalid dst blend func in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
}
skinParms - > blend = true ;
}
else if ( ! Q_strcasecmp ( token , " glow " ) )
{
if ( ! Mod_GetNextParm ( data , & token ) ) { // glowname
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing image name for 'glow' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
memcpy ( glowname , token , MD3_MAX_PATH ) ;
if ( ! Mod_GetNextParm ( data , & token ) ) { // type
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing 'identity' or 'wave' for 'glow' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
if ( ! Q_strcasecmp ( token , " wave " ) ) {
if ( ! Mod_ParseWaveFunc ( data , & skinParms - > glow . type ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing or invalid waveform for 'glow <glowskin> wave' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
for ( i = 0 ; i < 4 ; i + + )
if ( ! Mod_ParseFloat ( data , & skinParms - > glow . params [ i ] , false ) ) {
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: missing parameters for 'glow <glowskin> wave' in %s.%i in %s \n " , meshname , skinnum , scriptname ) ;
break ;
}
}
else if ( ! Q_strcasecmp ( token , " identity " ) )
skinParms - > glow . type = - 1 ;
else { // only wave or identity
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: unknown type '%s' for 'glow' in %s.%i in %s \n " , token , meshname , skinnum , scriptname ) ;
break ;
}
skin - > glowimage = R_FindImage ( glowname , it_skin ) ;
if ( skin - > glowimage )
memcpy ( skin - > glowname , glowname , MD3_MAX_PATH ) ;
}
else { // invalid parameter
VID_Printf ( PRINT_ALL , S_COLOR_YELLOW " Mod_ParseModelScript: unknown parameter '%s' in %s.%i in %s \n " , token , meshname , skinnum , scriptname ) ;
break ;
}
}
}
/*
= = = = = = = = = = = = = = = = =
Mod_SetRenderParmsDefaults
md3 skin protoshaders
= = = = = = = = = = = = = = = = =
*/
void Mod_SetRenderParmsDefaults ( renderparms_t * parms )
{
parms - > twosided = false ;
parms - > alphatest = false ;
parms - > fullbright = false ;
parms - > nodraw = false ;
parms - > noshadow = false ;
parms - > nodiffuse = false ;
parms - > envmap = 0.0f ;
parms - > basealpha = 1.0f ;
parms - > blend = false ;
parms - > blendfunc_src = - 1 ;
parms - > blendfunc_dst = - 1 ;
parms - > glow . type = - 1 ;
parms - > translate_x = 0.0f ;
parms - > translate_y = 0.0f ;
parms - > rotate = 0.0f ;
parms - > scale_x = 1.0f ;
parms - > scale_y = 1.0f ;
parms - > stretch . type = - 1 ;
parms - > turb . type = - 1 ;
parms - > scroll_x = 0.0f ;
parms - > scroll_y = 0.0f ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadModelScript
md3 skin protoshaders
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadModelScript ( model_t * mod , maliasmodel_t * aliasmod )
{
char scriptname [ MAX_QPATH ] ;
char * buf , * parse_data , * token = NULL , * token2 = NULL ;
int buf_size , i , j ; //, k;
qboolean skinname_found ;
renderparms_t * skinParms ;
// set defaults
for ( i = 0 ; i < aliasmod - > num_meshes ; i + + )
for ( j = 0 ; j < aliasmod - > meshes [ i ] . num_skins ; j + + ) {
Mod_SetRenderParmsDefaults ( & aliasmod - > meshes [ i ] . skins [ j ] . renderparms ) ;
aliasmod - > meshes [ i ] . skins [ j ] . glowimage = NULL ;
}
2019-10-08 07:39:06 +00:00
COM_StripExtension ( mod - > name , scriptname , sizeof ( scriptname ) ) ;
2019-03-13 19:20:07 +00:00
// strncat (scriptname, ".script");
Q_strncatz ( scriptname , " .script " , sizeof ( scriptname ) ) ;
buf_size = FS_LoadFile ( scriptname , & buf ) ;
if ( buf_size < 1 )
return ;
//else
// VID_Printf (PRINT_ALL, "Mod_LoadModelScript: loaded model script for %s with %i meshes.\n", mod->name, aliasmod->num_meshes);
for ( i = 0 ; i < aliasmod - > num_meshes ; i + + )
{
for ( j = 0 ; j < aliasmod - > meshes [ i ] . num_skins ; j + + )
{
skinParms = & aliasmod - > meshes [ i ] . skins [ j ] . renderparms ;
// search the script file for that meshname
skinname_found = false ;
parse_data = buf ; // copy data postion
while ( parse_data < ( buf + buf_size ) )
{
token = COM_Parse ( & parse_data ) ;
if ( ! parse_data ) break ;
if ( ! token ) break ;
if ( ! Q_strncasecmp ( token , aliasmod - > meshes [ i ] . name , strlen ( aliasmod - > meshes [ i ] . name ) )
& & ( atoi ( COM_FileExtension ( token ) ) = = j ) ) {
skinname_found = true ;
break ;
}
}
// then if that skinname is found, load the parms for that skin
if ( skinname_found )
Mod_ParseModelScript ( & aliasmod - > meshes [ i ] . skins [ j ] , & parse_data , buf , buf_size , aliasmod - > meshes [ i ] . name , j , scriptname ) ;
}
}
FS_FreeFile ( buf ) ;
// check if model has any alpha surfaces for sorting
for ( i = 0 ; i < aliasmod - > num_meshes ; i + + )
for ( j = 0 ; j < aliasmod - > meshes [ i ] . num_skins ; j + + )
if ( aliasmod - > meshes [ i ] . skins [ j ] . renderparms . blend | | aliasmod - > meshes [ i ] . skins [ j ] . renderparms . basealpha < 1.0f )
mod - > hasAlpha = true ;
//VID_Printf (PRINT_ALL, "Mod_LoadModelScript: loaded model script for %s with %i bytes per skin.\n", mod->name, sizeof(renderparms_t));
}
# ifndef MD2_AS_MD3
# ifdef PROJECTION_SHADOWS // projection shadows from BeefQuake R6
/*
= = = = = = = = = = = = = = = = =
Mod_FindMD2TriangleWithEdge
= = = = = = = = = = = = = = = = =
*/
signed int Mod_FindMD2TriangleWithEdge ( short p1 , short p2 , dtriangle_t * ignore , dmdl_t * hdr )
{
dtriangle_t * tris = ( dtriangle_t * ) ( ( unsigned char * ) hdr + hdr - > ofs_tris ) ;
int i , match , count ;
count = 0 ;
match = - 1 ;
for ( i = 0 ; i < hdr - > num_tris ; i + + , tris + + )
{
if ( ( tris - > index_xyz [ 0 ] = = p2 & & tris - > index_xyz [ 1 ] = = p1 )
| | ( tris - > index_xyz [ 1 ] = = p2 & & tris - > index_xyz [ 2 ] = = p1 )
| | ( tris - > index_xyz [ 2 ] = = p2 & & tris - > index_xyz [ 0 ] = = p1 ) ) {
if ( tris ! = ignore )
match = i ;
count + + ;
}
else if ( ( tris - > index_xyz [ 0 ] = = p1 & & tris - > index_xyz [ 1 ] = = p2 )
| | ( tris - > index_xyz [ 1 ] = = p1 & & tris - > index_xyz [ 2 ] = = p2 )
| | ( tris - > index_xyz [ 2 ] = = p1 & & tris - > index_xyz [ 0 ] = = p2 ) )
count + + ;
}
if ( count > 2 )
match = - 1 ;
return match ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_BuildMD2TriangleNeighbors
= = = = = = = = = = = = = = = = =
*/
void Mod_BuildMD2TriangleNeighbors ( model_t * mod )
{
dmdl_t * hdr = ( dmdl_t * ) mod - > extradata ;
dtriangle_t * tris = ( dtriangle_t * ) ( ( unsigned char * ) hdr + hdr - > ofs_tris ) ;
int i , * n ;
for ( i = 0 , n = mod - > edge_tri ; i < hdr - > num_tris ; i + + , n + = 3 , tris + + )
{
n [ 0 ] = Mod_FindMD2TriangleWithEdge ( tris - > index_xyz [ 0 ] , tris - > index_xyz [ 1 ] , tris , hdr ) ;
n [ 1 ] = Mod_FindMD2TriangleWithEdge ( tris - > index_xyz [ 1 ] , tris - > index_xyz [ 2 ] , tris , hdr ) ;
n [ 2 ] = Mod_FindMD2TriangleWithEdge ( tris - > index_xyz [ 2 ] , tris - > index_xyz [ 0 ] , tris , hdr ) ;
}
}
# endif // end projection shadows from BeefQuake R6
/*
= = = = = = = = = = = = = = = = =
Mod_GetAllocSizeMD2Old
Calc exact alloc size for MD2 in memory
= = = = = = = = = = = = = = = = =
*/
size_t Mod_GetAllocSizeMD2Old ( model_t * mod , void * buffer )
{
dmdl_t * pinmodel ;
size_t allocSize ;
pinmodel = ( dmd2_t * ) buffer ;
allocSize = ( LittleLong ( pinmodel - > ofs_end ) + 31 ) & ~ 31 ;
return allocSize ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadAliasMD2ModelOld
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadAliasMD2ModelOld ( model_t * mod , void * buffer )
{
int i , j ;
dmdl_t * pinmodel , * pheader ;
dstvert_t * pinst , * poutst ;
dtriangle_t * pintri , * pouttri ;
daliasframe_t * pinframe , * poutframe ;
int * pincmd , * poutcmd ;
int version ;
pinmodel = ( dmdl_t * ) buffer ;
version = LittleLong ( pinmodel - > version ) ;
if ( version ! = ALIAS_VERSION )
VID_Error ( ERR_DROP , " %s has wrong version number (%i should be %i) " ,
mod - > name , version , ALIAS_VERSION ) ;
// pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
pheader = ModChunk_Alloc ( LittleLong ( pinmodel - > ofs_end ) ) ;
// byte swap the header fields and sanity check
for ( i = 0 ; i < sizeof ( dmdl_t ) / 4 ; i + + )
( ( int * ) pheader ) [ i ] = LittleLong ( ( ( int * ) buffer ) [ i ] ) ;
if ( pheader - > skinheight > MAX_LBM_HEIGHT )
VID_Error ( ERR_DROP , " model %s has a skin taller than %d " , mod - > name ,
MAX_LBM_HEIGHT ) ;
if ( pheader - > num_xyz < = 0 )
VID_Error ( ERR_DROP , " model %s has no vertices " , mod - > name ) ;
if ( pheader - > num_xyz > MAX_VERTS )
VID_Error ( ERR_DROP , " model %s has too many vertices " , mod - > name ) ;
if ( pheader - > num_st < = 0 )
VID_Error ( ERR_DROP , " model %s has no st vertices " , mod - > name ) ;
if ( pheader - > num_tris < = 0 )
VID_Error ( ERR_DROP , " model %s has no triangles " , mod - > name ) ;
if ( pheader - > num_frames < = 0 )
VID_Error ( ERR_DROP , " model %s has no frames " , mod - > name ) ;
//
// load base s and t vertices (not used in gl version)
//
pinst = ( dstvert_t * ) ( ( byte * ) pinmodel + pheader - > ofs_st ) ;
poutst = ( dstvert_t * ) ( ( byte * ) pheader + pheader - > ofs_st ) ;
for ( i = 0 ; i < pheader - > num_st ; i + + )
{
poutst [ i ] . s = LittleShort ( pinst [ i ] . s ) ;
poutst [ i ] . t = LittleShort ( pinst [ i ] . t ) ;
}
//
// load triangle lists
//
pintri = ( dtriangle_t * ) ( ( byte * ) pinmodel + pheader - > ofs_tris ) ;
pouttri = ( dtriangle_t * ) ( ( byte * ) pheader + pheader - > ofs_tris ) ;
for ( i = 0 ; i < pheader - > num_tris ; i + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
pouttri [ i ] . index_xyz [ j ] = LittleShort ( pintri [ i ] . index_xyz [ j ] ) ;
pouttri [ i ] . index_st [ j ] = LittleShort ( pintri [ i ] . index_st [ j ] ) ;
}
}
//
// load the frames
//
for ( i = 0 ; i < pheader - > num_frames ; i + + )
{
pinframe = ( daliasframe_t * ) ( ( byte * ) pinmodel
+ pheader - > ofs_frames + i * pheader - > framesize ) ;
poutframe = ( daliasframe_t * ) ( ( byte * ) pheader
+ pheader - > ofs_frames + i * pheader - > framesize ) ;
memcpy ( poutframe - > name , pinframe - > name , sizeof ( poutframe - > name ) ) ;
for ( j = 0 ; j < 3 ; j + + )
{
poutframe - > scale [ j ] = LittleFloat ( pinframe - > scale [ j ] ) ;
poutframe - > translate [ j ] = LittleFloat ( pinframe - > translate [ j ] ) ;
}
// verts are all 8 bit, so no swapping needed
memcpy ( poutframe - > verts , pinframe - > verts ,
pheader - > num_xyz * sizeof ( dtrivertx_t ) ) ;
}
//
// load the glcmds
//
pincmd = ( int * ) ( ( byte * ) pinmodel + pheader - > ofs_glcmds ) ;
poutcmd = ( int * ) ( ( byte * ) pheader + pheader - > ofs_glcmds ) ;
for ( i = 0 ; i < pheader - > num_glcmds ; i + + )
poutcmd [ i ] = LittleLong ( pincmd [ i ] ) ;
// register all skins
memcpy ( ( char * ) pheader + pheader - > ofs_skins , ( char * ) pinmodel + pheader - > ofs_skins ,
pheader - > num_skins * MAX_SKINNAME ) ;
for ( i = 0 ; i < pheader - > num_skins ; i + + )
{
mod - > skins [ 0 ] [ i ] = R_FindImage ( ( char * ) pheader + pheader - > ofs_skins + i * MAX_SKINNAME , it_skin ) ;
}
mod - > mins [ 0 ] = - 32 ;
mod - > mins [ 1 ] = - 32 ;
mod - > mins [ 2 ] = - 32 ;
mod - > maxs [ 0 ] = 32 ;
mod - > maxs [ 1 ] = 32 ;
mod - > maxs [ 2 ] = 32 ;
# ifdef PROJECTION_SHADOWS // projection shadows from BeefQuake R6
mod - > edge_tri = malloc ( sizeof ( int ) * pheader - > num_tris * 3 ) ;
Mod_BuildMD2TriangleNeighbors ( mod ) ;
# endif // end projection shadows from BeefQuake R6
mod - > hasAlpha = false ;
// Mod_LoadMD2ModelScript (mod, pheader); // md2 skin scripting
mod - > type = mod_md2 ;
}
# endif // MD2_AS_MD3
//Harven++ MD3
//
// Some Vic code here not fully used
//
/*
= = = = = = = = = = = = = = =
Mod_FindTriangleWithEdge
= = = = = = = = = = = = = = =
*/
int Mod_FindTriangleWithEdge ( maliasmesh_t * mesh , index_t p1 , index_t p2 , int ignore )
{
int i , match , count ;
index_t * indexes ;
count = 0 ;
match = - 1 ;
for ( i = 0 , indexes = mesh - > indexes ; i < mesh - > num_tris ; i + + , indexes + = 3 )
{
if ( ( indexes [ 0 ] = = p2 & & indexes [ 1 ] = = p1 )
| | ( indexes [ 1 ] = = p2 & & indexes [ 2 ] = = p1 )
| | ( indexes [ 2 ] = = p2 & & indexes [ 0 ] = = p1 ) ) {
if ( i ! = ignore )
match = i ;
count + + ;
}
else if ( ( indexes [ 0 ] = = p1 & & indexes [ 1 ] = = p2 )
| | ( indexes [ 1 ] = = p1 & & indexes [ 2 ] = = p2 )
| | ( indexes [ 2 ] = = p1 & & indexes [ 0 ] = = p2 ) )
count + + ;
}
// detect edges shared by three triangles and make them seams
if ( count > 2 )
match = - 1 ;
return match ;
}
/*
= = = = = = = = = = = = = = =
Mod_BuildTriangleNeighbors
= = = = = = = = = = = = = = =
*/
void Mod_BuildTriangleNeighbors ( maliasmesh_t * mesh )
{
int i , * n ;
index_t * index ;
for ( i = 0 , n = mesh - > trneighbors , index = mesh - > indexes ; i < mesh - > num_tris ; i + + , n + = 3 , index + = 3 )
{
n [ 0 ] = Mod_FindTriangleWithEdge ( mesh , index [ 0 ] , index [ 1 ] , i ) ;
n [ 1 ] = Mod_FindTriangleWithEdge ( mesh , index [ 1 ] , index [ 2 ] , i ) ;
n [ 2 ] = Mod_FindTriangleWithEdge ( mesh , index [ 2 ] , index [ 0 ] , i ) ;
}
}
# ifdef MD2_AS_MD3
/*
= = = = = = = = = = = = = = = = =
NormalToLatLong
= = = = = = = = = = = = = = = = =
*/
void NormalToLatLong ( const vec3_t normal , byte bytes [ 2 ] )
{
int lat , lng ;
if ( normal [ 0 ] = = 0 & & normal [ 1 ] = = 0 ) {
if ( normal [ 2 ] > 0 ) {
// Lattitude = 0, Longitude = 0
bytes [ 0 ] = 0 ;
bytes [ 1 ] = 0 ;
}
else {
// Lattitude = 0, Longitude = 128
bytes [ 0 ] = 128 ;
bytes [ 1 ] = 0 ;
}
}
else {
lat = RAD2DEG ( atan2 ( normal [ 1 ] , normal [ 0 ] ) ) * ( 255.0 / 360.0 ) ;
lng = RAD2DEG ( acos ( normal [ 2 ] ) ) * ( 255.0 / 360.0 ) ;
bytes [ 0 ] = lng & 0xff ;
bytes [ 1 ] = lat & 0xff ;
}
}
int md2IndRemap [ MAX_TRIANGLES * 3 ] ;
unsigned int md2TempIndex [ MAX_TRIANGLES * 3 ] ;
unsigned int md2TempStIndex [ MAX_TRIANGLES * 3 ] ;
/*
= = = = = = = = = = = = = = = = =
Mod_GetAllocSizeMD2New
Calc exact alloc size for MD2 in memory
= = = = = = = = = = = = = = = = =
*/
size_t Mod_GetAllocSizeMD2New ( model_t * mod , void * buffer )
{
int i , j , numFrames , numMeshes , numTris , numIndex , numVerts , numSkins ;
dmdl_t * pinmodel ;
dtriangle_t * pintri ;
// int md2IndRemap[MAX_TRIANGLES*3];
// unsigned int md2TempIndex[MAX_TRIANGLES*3], md2TempStIndex[MAX_TRIANGLES*3];
size_t headerSize , meshSize , indexSize , coordSize , frameSize , vertSize , trNeighborsSize , skinSize ;
size_t allocSize ;
pinmodel = ( dmdl_t * ) buffer ;
numFrames = LittleLong ( pinmodel - > num_frames ) ;
numMeshes = 1 ;
numTris = LittleLong ( pinmodel - > num_tris ) ;
// count unique verts
// numVerts = LittleLong(pinmodel->num_xyz);
numVerts = 0 ;
numIndex = numTris * 3 ;
pintri = ( dtriangle_t * ) ( ( byte * ) pinmodel + LittleLong ( pinmodel - > ofs_tris ) ) ;
for ( i = 0 ; i < numTris ; i + + )
{
md2TempIndex [ i * 3 + 0 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_xyz [ 0 ] ) ;
md2TempIndex [ i * 3 + 1 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_xyz [ 1 ] ) ;
md2TempIndex [ i * 3 + 2 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_xyz [ 2 ] ) ;
md2TempStIndex [ i * 3 + 0 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_st [ 0 ] ) ;
md2TempStIndex [ i * 3 + 1 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_st [ 1 ] ) ;
md2TempStIndex [ i * 3 + 2 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_st [ 2 ] ) ;
}
memset ( md2IndRemap , - 1 , MAX_TRIANGLES * 3 * sizeof ( int ) ) ;
for ( i = 0 ; i < numIndex ; i + + )
{
if ( md2IndRemap [ i ] ! = - 1 ) continue ;
for ( j = 0 ; j < numIndex ; j + + )
{
if ( j = = i ) continue ;
if ( ( md2TempIndex [ j ] = = md2TempIndex [ i ] ) & & ( md2TempStIndex [ j ] = = md2TempStIndex [ i ] ) )
md2IndRemap [ j ] = i ;
}
}
for ( i = 0 ; i < numIndex ; i + + )
{
if ( md2IndRemap [ i ] = = - 1 ) numVerts + + ;
}
numSkins = max ( LittleLong ( pinmodel - > num_skins ) , 1 ) ; // hack because player models have no skin refs
// calc sizes rounded to cacheline
headerSize = ( sizeof ( maliasmodel_t ) + 31 ) & ~ 31 ;
meshSize = ( ( sizeof ( maliasmesh_t ) * numMeshes ) + 31 ) & ~ 31 ;
indexSize = ( ( sizeof ( index_t ) * numTris * 3 ) + 31 ) & ~ 31 ;
coordSize = ( ( sizeof ( maliascoord_t ) * numVerts ) + 31 ) & ~ 31 ;
frameSize = ( ( sizeof ( maliasframe_t ) * numFrames ) + 31 ) & ~ 31 ;
vertSize = ( ( numFrames * numVerts * sizeof ( maliasvertex_t ) ) + 31 ) & ~ 31 ;
trNeighborsSize = ( ( sizeof ( int ) * numTris * 3 ) + 31 ) & ~ 31 ;
skinSize = ( ( sizeof ( maliasskin_t ) * numSkins ) + 31 ) & ~ 31 ;
allocSize = headerSize + meshSize + indexSize + coordSize + frameSize + vertSize + trNeighborsSize + skinSize ;
return allocSize ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadAliasMD2ModelNew
Based on md2 loading code in Q2E 0.40
Mod_GetAllocSizeMD2 ( ) must be called first to init
index and remap arrays .
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadAliasMD2ModelNew ( model_t * mod , void * buffer )
{
int i , j ;
int version ;
dmdl_t * pinmodel ;
daliasframe_t * pinframe ;
dtriangle_t * pintri ;
dstvert_t * pincoord ;
maliasmodel_t * poutmodel ;
maliasframe_t * poutframe ;
maliasmesh_t * poutmesh ;
maliasskin_t * poutskin ;
maliasvertex_t * poutvert ;
maliascoord_t * poutcoord ;
index_t * poutindex ;
char name [ MD3_MAX_PATH ] ;
// int md2IndRemap[MAX_TRIANGLES*3];
// unsigned md2TempIndex[MAX_TRIANGLES*3], md2TempStIndex[MAX_TRIANGLES*3];
int numIndices , numVertices ;
double skinWidth , skinHeight ;
vec3_t normal ;
pinmodel = ( dmdl_t * ) buffer ;
// poutmodel = Hunk_Alloc (sizeof(maliasmodel_t));
poutmodel = ModChunk_Alloc ( sizeof ( maliasmodel_t ) ) ;
// byte swap the header fields and sanity check
version = LittleLong ( pinmodel - > version ) ;
if ( version ! = ALIAS_VERSION ) {
VID_Error ( ERR_DROP , " %s has wrong version number (%i should be %i) " ,
mod - > name , version , ALIAS_VERSION ) ;
}
poutmodel - > num_frames = LittleLong ( pinmodel - > num_frames ) ;
if ( poutmodel - > num_frames > MAX_FRAMES | | poutmodel - > num_frames < = 0 )
VID_Error ( ERR_DROP , " model %s has invalid number of frames (%i) " , mod - > name , poutmodel - > num_frames ) ;
poutmodel - > num_tags = 0 ;
poutmodel - > num_meshes = 1 ;
skinWidth = 1.0 / ( double ) LittleLong ( pinmodel - > skinwidth ) ;
skinHeight = 1.0 / ( double ) LittleLong ( pinmodel - > skinheight ) ;
//
// load mesh info
//
// poutmesh = poutmodel->meshes = Hunk_Alloc(sizeof(maliasmesh_t));
poutmesh = poutmodel - > meshes = ModChunk_Alloc ( sizeof ( maliasmesh_t ) ) ;
Com_sprintf ( poutmesh - > name , sizeof ( poutmesh - > name ) , " md2mesh " ) ; // mesh name in script must match this
poutmesh - > num_tris = LittleLong ( pinmodel - > num_tris ) ;
if ( poutmesh - > num_tris > MAX_TRIANGLES | | poutmesh - > num_tris < = 0 )
VID_Error ( ERR_DROP , " model %s has invalid number of triangles (%i) " , mod - > name , poutmesh - > num_tris ) ;
poutmesh - > num_verts = LittleLong ( pinmodel - > num_xyz ) ;
if ( poutmesh - > num_verts > MAX_VERTS | | poutmesh - > num_verts < = 0 )
VID_Error ( ERR_DROP , " model %s has invalid number of vertices (%i) " , mod - > name , poutmesh - > num_verts ) ;
poutmesh - > num_skins = LittleLong ( pinmodel - > num_skins ) ;
if ( poutmesh - > num_skins > MAX_MD2SKINS | | poutmesh - > num_skins < 0 )
Com_Error ( ERR_DROP , " model %s has invalid number of skins (%i) " , mod - > name , poutmesh - > num_skins ) ;
pintri = ( dtriangle_t * ) ( ( byte * ) pinmodel + LittleLong ( pinmodel - > ofs_tris ) ) ;
// DO NOT DELETE!!! Needed if Mod_GetAllocSizeMD2() is removed!
/* for (i=0; i < poutmesh->num_tris; i++)
{
md2TempIndex [ i * 3 + 0 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_xyz [ 0 ] ) ;
md2TempIndex [ i * 3 + 1 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_xyz [ 1 ] ) ;
md2TempIndex [ i * 3 + 2 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_xyz [ 2 ] ) ;
md2TempStIndex [ i * 3 + 0 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_st [ 0 ] ) ;
md2TempStIndex [ i * 3 + 1 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_st [ 1 ] ) ;
md2TempStIndex [ i * 3 + 2 ] = ( unsigned ) LittleShort ( pintri [ i ] . index_st [ 2 ] ) ;
} */
//
// build list of unique vertices
//
numIndices = poutmesh - > num_tris * 3 ;
numVertices = 0 ;
// poutindex = poutmesh->indexes = Hunk_Alloc( sizeof(index_t) * poutmesh->num_tris * 3 );
poutindex = poutmesh - > indexes = ModChunk_Alloc ( sizeof ( index_t ) * poutmesh - > num_tris * 3 ) ;
// DO NOT DELETE!!! Needed if Mod_GetAllocSizeMD2() is removed!
/* memset(md2IndRemap, -1, MAX_TRIANGLES * 3 * sizeof(int));
for ( i = 0 ; i < numIndices ; i + + )
{
if ( md2IndRemap [ i ] ! = - 1 )
continue ;
for ( j = 0 ; j < numIndices ; j + + )
{
if ( j = = i )
continue ;
if ( ( md2TempIndex [ j ] = = md2TempIndex [ i ] ) & & ( md2TempStIndex [ j ] = = md2TempStIndex [ i ] ) )
md2IndRemap [ j ] = i ;
}
} */
//
// count unique vertices
//
for ( i = 0 ; i < numIndices ; i + + )
{
if ( md2IndRemap [ i ] ! = - 1 )
continue ;
poutindex [ i ] = numVertices + + ;
md2IndRemap [ i ] = i ;
}
poutmesh - > num_verts = numVertices ;
//
// remap remaining indices
//
for ( i = 0 ; i < numIndices ; i + + ) {
if ( md2IndRemap [ i ] ! = i )
poutindex [ i ] = poutindex [ md2IndRemap [ i ] ] ;
}
//
// load base S and T vertices
//
pincoord = ( dstvert_t * ) ( ( byte * ) pinmodel + LittleLong ( pinmodel - > ofs_st ) ) ;
// poutcoord = poutmesh->stcoords = Hunk_Alloc ( sizeof(maliascoord_t) * poutmesh->num_verts );
poutcoord = poutmesh - > stcoords = ModChunk_Alloc ( sizeof ( maliascoord_t ) * poutmesh - > num_verts ) ;
for ( i = 0 ; i < numIndices ; i + + ) {
poutcoord [ poutindex [ i ] ] . st [ 0 ] = ( float ) ( ( ( double ) LittleShort ( pincoord [ md2TempStIndex [ md2IndRemap [ i ] ] ] . s ) + 0.5 ) * skinWidth ) ;
poutcoord [ poutindex [ i ] ] . st [ 1 ] = ( float ) ( ( ( double ) LittleShort ( pincoord [ md2TempStIndex [ md2IndRemap [ i ] ] ] . t ) + 0.5 ) * skinHeight ) ;
}
//
// load the frames
//
// poutframe = poutmodel->frames = Hunk_Alloc ( sizeof(maliasframe_t) * poutmodel->num_frames );
// poutvert = poutmesh->vertexes = Hunk_Alloc ( poutmodel->num_frames * poutmesh->num_verts * sizeof(maliasvertex_t) );
poutframe = poutmodel - > frames = ModChunk_Alloc ( sizeof ( maliasframe_t ) * poutmodel - > num_frames ) ;
poutvert = poutmesh - > vertexes = ModChunk_Alloc ( poutmodel - > num_frames * poutmesh - > num_verts * sizeof ( maliasvertex_t ) ) ;
mod - > radius = 0 ;
ClearBounds ( mod - > mins , mod - > maxs ) ;
for ( i = 0 ; i < poutmodel - > num_frames ; i + + , pinframe + + , poutframe + + , poutvert + = numVertices )
{
pinframe = ( daliasframe_t * ) ( ( byte * ) pinmodel + LittleLong ( pinmodel - > ofs_frames ) + i * LittleLong ( pinmodel - > framesize ) ) ;
poutframe - > scale [ 0 ] = LittleFloat ( pinframe - > scale [ 0 ] ) ;
poutframe - > scale [ 1 ] = LittleFloat ( pinframe - > scale [ 1 ] ) ;
poutframe - > scale [ 2 ] = LittleFloat ( pinframe - > scale [ 2 ] ) ;
poutframe - > translate [ 0 ] = LittleFloat ( pinframe - > translate [ 0 ] ) ;
poutframe - > translate [ 1 ] = LittleFloat ( pinframe - > translate [ 1 ] ) ;
poutframe - > translate [ 2 ] = LittleFloat ( pinframe - > translate [ 2 ] ) ;
VectorCopy ( poutframe - > translate , poutframe - > mins ) ;
VectorMA ( poutframe - > translate , 255 , poutframe - > scale , poutframe - > maxs ) ;
poutframe - > radius = RadiusFromBounds ( poutframe - > mins , poutframe - > maxs ) ;
mod - > radius = max ( mod - > radius , poutframe - > radius ) ;
AddPointToBounds ( poutframe - > mins , mod - > mins , mod - > maxs ) ;
AddPointToBounds ( poutframe - > maxs , mod - > mins , mod - > maxs ) ;
//
// load the vertexes and normals
//
for ( j = 0 ; j < numIndices ; j + + )
{
poutvert [ poutindex [ j ] ] . xyz [ 0 ] = ( short ) pinframe - > verts [ md2TempIndex [ md2IndRemap [ j ] ] ] . v [ 0 ] ;
poutvert [ poutindex [ j ] ] . xyz [ 1 ] = ( short ) pinframe - > verts [ md2TempIndex [ md2IndRemap [ j ] ] ] . v [ 1 ] ;
poutvert [ poutindex [ j ] ] . xyz [ 2 ] = ( short ) pinframe - > verts [ md2TempIndex [ md2IndRemap [ j ] ] ] . v [ 2 ] ;
poutvert [ poutindex [ j ] ] . lightnormalindex = pinframe - > verts [ md2TempIndex [ md2IndRemap [ j ] ] ] . lightnormalindex ;
normal [ 0 ] = r_avertexnormals [ poutvert [ poutindex [ j ] ] . lightnormalindex ] [ 0 ] ;
normal [ 1 ] = r_avertexnormals [ poutvert [ poutindex [ j ] ] . lightnormalindex ] [ 1 ] ;
normal [ 2 ] = r_avertexnormals [ poutvert [ poutindex [ j ] ] . lightnormalindex ] [ 2 ] ;
NormalToLatLong ( normal , poutvert [ poutindex [ j ] ] . normal ) ;
}
}
//
// build triangle neighbors
//
// poutmesh->trneighbors = Hunk_Alloc ( sizeof(int) * poutmesh->num_tris * 3 );
poutmesh - > trneighbors = ModChunk_Alloc ( sizeof ( int ) * poutmesh - > num_tris * 3 ) ;
Mod_BuildTriangleNeighbors ( poutmesh ) ;
//
// register all skins
//
if ( poutmesh - > num_skins < = 0 ) // hack for player models with no skin refs
{
// poutskin = poutmesh->skins = Hunk_Alloc ( sizeof(maliasskin_t) * 1 );
poutskin = poutmesh - > skins = ModChunk_Alloc ( sizeof ( maliasskin_t ) * 1 ) ;
poutmesh - > num_skins = 1 ;
Com_sprintf ( name , sizeof ( name ) , " players/male/grunt.pcx " ) ;
memcpy ( poutskin - > name , name , MD3_MAX_PATH ) ;
Com_sprintf ( poutskin - > glowname , sizeof ( poutskin - > glowname ) , " \0 " ) ; // set null glowskin
mod - > skins [ 0 ] [ 0 ] = R_FindImage ( name , it_skin ) ;
}
else
{
// poutskin = poutmesh->skins = Hunk_Alloc ( sizeof(maliasskin_t) * poutmesh->num_skins );
poutskin = poutmesh - > skins = ModChunk_Alloc ( sizeof ( maliasskin_t ) * poutmesh - > num_skins ) ;
for ( i = 0 ; i < poutmesh - > num_skins ; i + + , poutskin + + )
{
memcpy ( name , ( ( char * ) pinmodel + LittleLong ( pinmodel - > ofs_skins ) + i * MAX_SKINNAME ) , MD3_MAX_PATH ) ;
memcpy ( poutskin - > name , name , MD3_MAX_PATH ) ;
Com_sprintf ( poutskin - > glowname , sizeof ( poutskin - > glowname ) , " \0 " ) ; // set null glowskin
mod - > skins [ 0 ] [ i ] = R_FindImage ( name , it_skin ) ;
}
}
mod - > hasAlpha = false ;
Mod_LoadModelScript ( mod , poutmodel ) ; // md3 skin scripting
//if (mod->hasAlpha)
// VID_Printf (PRINT_ALL, "Mod_LoadAliasMD2Model: model %s has trans mesh\n", mod->name);
mod - > type = mod_alias ;
}
# endif // MD2_AS_MD3
//
// And here some Vic and some my (Harven)
//
/*
= = = = = = = = = = = = = = = = =
Mod_GetAllocSizeMD3
Calc exact alloc size for MD3 in memory
= = = = = = = = = = = = = = = = =
*/
size_t Mod_GetAllocSizeMD3 ( model_t * mod , void * buffer )
{
int i , numFrames , numTags , numMeshes , numSkins , numTris , numVerts ;
dmd3_t * pinmodel ;
dmd3mesh_t * pinmesh ;
size_t headerSize , frameSize , tagSize , meshSize ;
size_t skinSize = 0 , indexSize = 0 , coordSize = 0 , vertSize = 0 , trNeighborsSize = 0 ;
size_t allocSize ;
pinmodel = ( dmd3_t * ) buffer ;
numFrames = LittleLong ( pinmodel - > num_frames ) ;
numTags = LittleLong ( pinmodel - > num_tags ) ;
numMeshes = LittleLong ( pinmodel - > num_meshes ) ;
// calc sizes rounded to cacheline
headerSize = ( sizeof ( maliasmodel_t ) + 31 ) & ~ 31 ;
frameSize = ( ( sizeof ( maliasframe_t ) * numFrames ) + 31 ) & ~ 31 ;
tagSize = ( ( sizeof ( maliastag_t ) * numFrames * numTags ) + 31 ) & ~ 31 ;
meshSize = ( ( sizeof ( maliasmesh_t ) * numMeshes ) + 31 ) & ~ 31 ;
pinmesh = ( dmd3mesh_t * ) ( ( byte * ) pinmodel + LittleLong ( pinmodel - > ofs_meshes ) ) ;
for ( i = 0 ; i < numMeshes ; i + + )
{
numSkins = LittleLong ( pinmesh - > num_skins ) ;
numTris = LittleLong ( pinmesh - > num_tris ) ;
numVerts = LittleLong ( pinmesh - > num_verts ) ;
skinSize + = ( ( sizeof ( maliasskin_t ) * numSkins ) + 31 ) & ~ 31 ;
indexSize + = ( ( sizeof ( index_t ) * numTris * 3 ) + 31 ) & ~ 31 ;
coordSize + = ( ( sizeof ( maliascoord_t ) * numVerts ) + 31 ) & ~ 31 ;
vertSize + = ( ( numFrames * numVerts * sizeof ( maliasvertex_t ) ) + 31 ) & ~ 31 ;
trNeighborsSize + = ( ( sizeof ( int ) * numTris * 3 ) + 31 ) & ~ 31 ;
pinmesh = ( dmd3mesh_t * ) ( ( byte * ) pinmesh + LittleLong ( pinmesh - > meshsize ) ) ;
}
allocSize = headerSize + frameSize + tagSize + meshSize + skinSize + indexSize + coordSize + vertSize + trNeighborsSize ;
return allocSize ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadAliasMD3Model
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadAliasMD3Model ( model_t * mod , void * buffer )
{
int version , maxdotindex , i , j , l , k ;
dmd3_t * pinmodel ;
dmd3frame_t * pinframe ;
dmd3tag_t * pintag ;
dmd3mesh_t * pinmesh ;
dmd3skin_t * pinskin ;
dmd3coord_t * pincoord ;
dmd3vertex_t * pinvert ;
index_t * pinindex , * poutindex ;
maliasvertex_t * poutvert ;
maliascoord_t * poutcoord ;
maliasskin_t * poutskin ;
maliasmesh_t * poutmesh ;
maliastag_t * pouttag ;
maliasframe_t * poutframe ;
maliasmodel_t * poutmodel ;
char name [ MD3_MAX_PATH ] ;
float lat , lng , maxdot ;
vec3_t normal ;
pinmodel = ( dmd3_t * ) buffer ;
version = LittleLong ( pinmodel - > version ) ;
if ( version ! = MD3_ALIAS_VERSION )
{
VID_Error ( ERR_DROP , " %s has wrong version number (%i should be %i) " ,
mod - > name , version , MD3_ALIAS_VERSION ) ;
}
// poutmodel = Hunk_Alloc (sizeof(maliasmodel_t));
poutmodel = ModChunk_Alloc ( sizeof ( maliasmodel_t ) ) ;
// byte swap the header fields and sanity check
poutmodel - > num_frames = LittleLong ( pinmodel - > num_frames ) ;
poutmodel - > num_tags = LittleLong ( pinmodel - > num_tags ) ;
poutmodel - > num_meshes = LittleLong ( pinmodel - > num_meshes ) ;
if ( poutmodel - > num_frames < = 0 )
VID_Error ( ERR_DROP , " model %s has no frames " , mod - > name ) ;
else if ( poutmodel - > num_frames > MD3_MAX_FRAMES )
VID_Error ( ERR_DROP , " model %s has too many frames " , mod - > name ) ;
if ( poutmodel - > num_tags > MD3_MAX_TAGS )
VID_Error ( ERR_DROP , " model %s has too many tags " , mod - > name ) ;
else if ( poutmodel - > num_tags < 0 )
VID_Error ( ERR_DROP , " model %s has invalid number of tags " , mod - > name ) ;
if ( poutmodel - > num_meshes < = 0 )
VID_Error ( ERR_DROP , " model %s has no meshes " , mod - > name ) ;
else if ( poutmodel - > num_meshes > MD3_MAX_MESHES )
VID_Error ( ERR_DROP , " model %s has too many meshes " , mod - > name ) ;
//
// load the frames
//
pinframe = ( dmd3frame_t * ) ( ( byte * ) pinmodel + LittleLong ( pinmodel - > ofs_frames ) ) ;
// poutframe = poutmodel->frames = Hunk_Alloc ( sizeof(maliasframe_t) * poutmodel->num_frames);
poutframe = poutmodel - > frames = ModChunk_Alloc ( sizeof ( maliasframe_t ) * poutmodel - > num_frames ) ;
mod - > radius = 0 ;
ClearBounds ( mod - > mins , mod - > maxs ) ;
for ( i = 0 ; i < poutmodel - > num_frames ; i + + , pinframe + + , poutframe + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
poutframe - > mins [ j ] = LittleFloat ( pinframe - > mins [ j ] ) ;
poutframe - > maxs [ j ] = LittleFloat ( pinframe - > maxs [ j ] ) ;
poutframe - > scale [ j ] = MD3_XYZ_SCALE ;
poutframe - > translate [ j ] = LittleFloat ( pinframe - > translate [ j ] ) ;
}
poutframe - > radius = LittleFloat ( pinframe - > radius ) ;
mod - > radius = max ( mod - > radius , poutframe - > radius ) ;
AddPointToBounds ( poutframe - > mins , mod - > mins , mod - > maxs ) ;
AddPointToBounds ( poutframe - > maxs , mod - > mins , mod - > maxs ) ;
}
//
// load the tags
//
pintag = ( dmd3tag_t * ) ( ( byte * ) pinmodel + LittleLong ( pinmodel - > ofs_tags ) ) ;
// pouttag = poutmodel->tags = Hunk_Alloc( sizeof(maliastag_t) * poutmodel->num_frames * poutmodel->num_tags);
pouttag = poutmodel - > tags = ModChunk_Alloc ( sizeof ( maliastag_t ) * poutmodel - > num_frames * poutmodel - > num_tags ) ;
for ( i = 0 ; i < poutmodel - > num_frames ; i + + )
{
for ( l = 0 ; l < poutmodel - > num_tags ; l + + , pintag + + , pouttag + + )
{
memcpy ( pouttag - > name , pintag - > name , MD3_MAX_PATH ) ;
for ( j = 0 ; j < 3 ; j + + ) {
pouttag - > orient . origin [ j ] = LittleFloat ( pintag - > orient . origin [ j ] ) ;
pouttag - > orient . axis [ 0 ] [ j ] = LittleFloat ( pintag - > orient . axis [ 0 ] [ j ] ) ;
pouttag - > orient . axis [ 1 ] [ j ] = LittleFloat ( pintag - > orient . axis [ 1 ] [ j ] ) ;
pouttag - > orient . axis [ 2 ] [ j ] = LittleFloat ( pintag - > orient . axis [ 2 ] [ j ] ) ;
}
/* VID_Printf (PRINT_ALL, "Tag origin: (%f %f %f) axis X: (%f %f %f) Y: (%f %f %f) Z: (%f %f %f)\n",
pouttag - > orient . origin [ 0 ] , pouttag - > orient . origin [ 1 ] , pouttag - > orient . origin [ 2 ] ,
pouttag - > orient . axis [ 0 ] [ 0 ] , pouttag - > orient . axis [ 0 ] [ 1 ] , pouttag - > orient . axis [ 0 ] [ 2 ] ,
pouttag - > orient . axis [ 1 ] [ 0 ] , pouttag - > orient . axis [ 1 ] [ 1 ] , pouttag - > orient . axis [ 1 ] [ 2 ] ,
pouttag - > orient . axis [ 2 ] [ 0 ] , pouttag - > orient . axis [ 2 ] [ 1 ] , pouttag - > orient . axis [ 2 ] [ 2 ] ) ;
*/
}
}
//
// load the meshes
//
pinmesh = ( dmd3mesh_t * ) ( ( byte * ) pinmodel + LittleLong ( pinmodel - > ofs_meshes ) ) ;
// poutmesh = poutmodel->meshes = Hunk_Alloc ( sizeof(maliasmesh_t)*poutmodel->num_meshes);
poutmesh = poutmodel - > meshes = ModChunk_Alloc ( sizeof ( maliasmesh_t ) * poutmodel - > num_meshes ) ;
for ( i = 0 ; i < poutmodel - > num_meshes ; i + + , poutmesh + + )
{
memcpy ( poutmesh - > name , pinmesh - > name , MD3_MAX_PATH ) ;
if ( strncmp ( ( const char * ) pinmesh - > id , " IDP3 " , 4 ) )
{
VID_Error ( ERR_DROP , " mesh %s in model %s has wrong id (%i should be %i) " ,
poutmesh - > name , mod - > name , LittleLong ( ( int ) pinmesh - > id ) , IDMD3HEADER ) ;
}
poutmesh - > num_tris = LittleLong ( pinmesh - > num_tris ) ;
poutmesh - > num_skins = LittleLong ( pinmesh - > num_skins ) ;
poutmesh - > num_verts = LittleLong ( pinmesh - > num_verts ) ;
if ( poutmesh - > num_skins < = 0 )
VID_Error ( ERR_DROP , " mesh %i in model %s has no skins " , i , mod - > name ) ;
else if ( poutmesh - > num_skins > MD3_MAX_SHADERS )
VID_Error ( ERR_DROP , " mesh %i in model %s has too many skins " , i , mod - > name ) ;
if ( poutmesh - > num_tris < = 0 )
VID_Error ( ERR_DROP , " mesh %i in model %s has no triangles " , i , mod - > name ) ;
else if ( poutmesh - > num_tris > MD3_MAX_TRIANGLES )
VID_Error ( ERR_DROP , " mesh %i in model %s has too many triangles " , i , mod - > name ) ;
if ( poutmesh - > num_verts < = 0 )
VID_Error ( ERR_DROP , " mesh %i in model %s has no vertices " , i , mod - > name ) ;
else if ( poutmesh - > num_verts > MD3_MAX_VERTS )
VID_Error ( ERR_DROP , " mesh %i in model %s has too many vertices " , i , mod - > name ) ;
//
// register all skins
//
pinskin = ( dmd3skin_t * ) ( ( byte * ) pinmesh + LittleLong ( pinmesh - > ofs_skins ) ) ;
// poutskin = poutmesh->skins = Hunk_Alloc( sizeof(maliasskin_t) * poutmesh->num_skins );
poutskin = poutmesh - > skins = ModChunk_Alloc ( sizeof ( maliasskin_t ) * poutmesh - > num_skins ) ;
for ( j = 0 ; j < poutmesh - > num_skins ; j + + , pinskin + + , poutskin + + )
{
memcpy ( name , pinskin - > name , MD3_MAX_PATH ) ;
if ( name [ 1 ] = = ' o ' )
name [ 0 ] = ' m ' ;
if ( name [ 1 ] = = ' l ' )
name [ 0 ] = ' p ' ;
memcpy ( poutskin - > name , name , MD3_MAX_PATH ) ;
Com_sprintf ( poutskin - > glowname , sizeof ( poutskin - > glowname ) , " \0 " ) ; // set null glowskin
mod - > skins [ i ] [ j ] = R_FindImage ( name , it_skin ) ;
}
//
// load the indexes
//
pinindex = ( index_t * ) ( ( byte * ) pinmesh + LittleLong ( pinmesh - > ofs_tris ) ) ;
// poutindex = poutmesh->indexes = Hunk_Alloc( sizeof(index_t) * poutmesh->num_tris * 3 );
poutindex = poutmesh - > indexes = ModChunk_Alloc ( sizeof ( index_t ) * poutmesh - > num_tris * 3 ) ;
for ( j = 0 ; j < poutmesh - > num_tris ; j + + , pinindex + = 3 , poutindex + = 3 )
{
poutindex [ 0 ] = ( index_t ) LittleLong ( pinindex [ 0 ] ) ;
poutindex [ 1 ] = ( index_t ) LittleLong ( pinindex [ 1 ] ) ;
poutindex [ 2 ] = ( index_t ) LittleLong ( pinindex [ 2 ] ) ;
}
//
// load the texture coordinates
//
pincoord = ( dmd3coord_t * ) ( ( byte * ) pinmesh + LittleLong ( pinmesh - > ofs_tcs ) ) ;
// poutcoord = poutmesh->stcoords = Hunk_Alloc( sizeof(maliascoord_t) * poutmesh->num_verts);
poutcoord = poutmesh - > stcoords = ModChunk_Alloc ( sizeof ( maliascoord_t ) * poutmesh - > num_verts ) ;
for ( j = 0 ; j < poutmesh - > num_verts ; j + + , pincoord + + , poutcoord + + )
{
poutcoord - > st [ 0 ] = LittleFloat ( pincoord - > st [ 0 ] ) ;
poutcoord - > st [ 1 ] = LittleFloat ( pincoord - > st [ 1 ] ) ;
}
//
// load the vertexes and normals
//
pinvert = ( dmd3vertex_t * ) ( ( byte * ) pinmesh + LittleLong ( pinmesh - > ofs_verts ) ) ;
// poutvert = poutmesh->vertexes = Hunk_Alloc(poutmodel->num_frames * poutmesh->num_verts * sizeof(maliasvertex_t));
poutvert = poutmesh - > vertexes = ModChunk_Alloc ( poutmodel - > num_frames * poutmesh - > num_verts * sizeof ( maliasvertex_t ) ) ;
for ( l = 0 ; l < poutmodel - > num_frames ; l + + )
{
for ( j = 0 ; j < poutmesh - > num_verts ; j + + , pinvert + + , poutvert + + )
{
poutvert - > xyz [ 0 ] = LittleShort ( pinvert - > point [ 0 ] ) ;
poutvert - > xyz [ 1 ] = LittleShort ( pinvert - > point [ 1 ] ) ;
poutvert - > xyz [ 2 ] = LittleShort ( pinvert - > point [ 2 ] ) ;
poutvert - > normal [ 0 ] = ( LittleShort ( pinvert - > norm ) > > 0 ) & 0xff ;
poutvert - > normal [ 1 ] = ( LittleShort ( pinvert - > norm ) > > 8 ) & 0xff ;
lat = ( pinvert - > norm > > 8 ) & 0xff ;
lng = ( pinvert - > norm & 0xff ) ;
lat * = M_PI / 128 ;
lng * = M_PI / 128 ;
normal [ 0 ] = cos ( lat ) * sin ( lng ) ;
normal [ 1 ] = sin ( lat ) * sin ( lng ) ;
normal [ 2 ] = cos ( lng ) ;
// use ye olde quantized normals for shading
maxdot = - 999999.0 ;
maxdotindex = - 1 ;
for ( k = 0 ; k < NUMVERTEXNORMALS ; k + + )
{
float dot = DotProduct ( normal , r_avertexnormals [ k ] ) ;
if ( dot > maxdot ) {
maxdot = dot ;
maxdotindex = k ;
}
}
poutvert - > lightnormalindex = maxdotindex ;
}
}
pinmesh = ( dmd3mesh_t * ) ( ( byte * ) pinmesh + LittleLong ( pinmesh - > meshsize ) ) ;
//
// build triangle neighbors
//
// poutmesh->trneighbors = Hunk_Alloc (sizeof(int) * poutmesh->num_tris * 3);
poutmesh - > trneighbors = ModChunk_Alloc ( sizeof ( int ) * poutmesh - > num_tris * 3 ) ;
Mod_BuildTriangleNeighbors ( poutmesh ) ;
}
mod - > hasAlpha = false ;
Mod_LoadModelScript ( mod , poutmodel ) ; // md3 skin scripting
//if (mod->hasAlpha)
// VID_Printf (PRINT_ALL, "Mod_LoadAliasMD3Model: model %s has trans mesh\n", mod->name);
mod - > type = mod_alias ;
}
//Harven-- MD3
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
SPRITE MODELS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = =
Mod_GetAllocSizeSprite
Calc exact alloc size for sprite in memory
= = = = = = = = = = = = = = = = =
*/
size_t Mod_GetAllocSizeSprite ( model_t * mod , void * buffer )
{
size_t allocSize ;
// calc memory allocation size
allocSize = ( ( modfilelen ) + 31 ) & ~ 31 ;
return allocSize ;
}
/*
= = = = = = = = = = = = = = = = =
Mod_LoadSpriteModel
= = = = = = = = = = = = = = = = =
*/
void Mod_LoadSpriteModel ( model_t * mod , void * buffer )
{
dsprite_t * sprin , * sprout ;
int i ;
sprin = ( dsprite_t * ) buffer ;
// sprout = Hunk_Alloc (modfilelen);
sprout = ModChunk_Alloc ( modfilelen ) ;
sprout - > ident = LittleLong ( sprin - > ident ) ;
sprout - > version = LittleLong ( sprin - > version ) ;
sprout - > numframes = LittleLong ( sprin - > numframes ) ;
if ( sprout - > version ! = SPRITE_VERSION )
VID_Error ( ERR_DROP , " %s has wrong version number (%i should be %i) " ,
mod - > name , sprout - > version , SPRITE_VERSION ) ;
if ( sprout - > numframes > MAX_MD2SKINS )
VID_Error ( ERR_DROP , " %s has too many frames (%i > %i) " ,
mod - > name , sprout - > numframes , MAX_MD2SKINS ) ;
// byte swap everything
for ( i = 0 ; i < sprout - > numframes ; i + + )
{
sprout - > frames [ i ] . width = LittleLong ( sprin - > frames [ i ] . width ) ;
sprout - > frames [ i ] . height = LittleLong ( sprin - > frames [ i ] . height ) ;
sprout - > frames [ i ] . origin_x = LittleLong ( sprin - > frames [ i ] . origin_x ) ;
sprout - > frames [ i ] . origin_y = LittleLong ( sprin - > frames [ i ] . origin_y ) ;
memcpy ( sprout - > frames [ i ] . name , sprin - > frames [ i ] . name , MAX_SKINNAME ) ;
mod - > skins [ 0 ] [ i ] = R_FindImage ( sprout - > frames [ i ] . name ,
it_sprite ) ;
}
mod - > type = mod_sprite ;
}
//=============================================================================
/*
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
R_BeginRegistration
Specifies the model that will be used as the world
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
*/
void R_BeginRegistration ( char * model )
{
char fullname [ MAX_QPATH ] ;
cvar_t * flushmap ;
registration_sequence + + ;
r_oldviewcluster = - 1 ; // force markleafs
Mod_InitFailedTexList ( ) ; // clear failed texture list
Mod_InitWalSizeList ( ) ; // clear wal size list
Com_sprintf ( fullname , sizeof ( fullname ) , " maps/%s.bsp " , model ) ;
// explicitly free the old map if different
// this guarantees that mod_known[0] is the world map
flushmap = Cvar_Get ( " flushmap " , " 0 " , 0 ) ;
2020-07-04 05:31:44 +00:00
Cvar_SetDescription ( " flushmap " , " Forces reload of same map when set to 1. " ) ;
2020-03-20 03:37:01 +00:00
if ( strcmp ( mod_known [ 0 ] . name , fullname ) | | flushmap - > integer ) {
2019-03-13 19:20:07 +00:00
Mod_Free ( & mod_known [ 0 ] ) ;
// clear this on map change (case of different server and autodownloading)
R_InitFailedImgList ( ) ;
}
r_worldmodel = Mod_ForName ( fullname , true ) ;
r_viewcluster = - 1 ;
registration_active = true ; // map registration flag
}
/*
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
R_RegisterModel
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
*/
struct model_s * R_RegisterModel ( char * name )
{
model_t * mod ;
int i ;
dsprite_t * sprout ;
# ifndef MD2_AS_MD3 // Knightmare- no longer used!
dmdl_t * pheader ;
# endif // MD2_AS_MD3
// Harven++ MD3
maliasmodel_t * pheader3 ;
// Harven-- MD3
// Knightmare- MD3 autoreplace code
2020-07-29 10:05:09 +00:00
int len = ( int ) strlen ( name ) ;
2019-03-13 19:20:07 +00:00
if ( ! strcmp ( name + len - 4 , " .md2 " ) ) // look if we have a .md2 file
{
char s [ 128 ] ;
// strncpy(s,name);
Q_strncpyz ( s , name , sizeof ( s ) ) ;
s [ len - 1 ] = ' 3 ' ;
mod = R_RegisterModel ( s ) ;
if ( mod )
return mod ;
}
// end Knightmare
mod = Mod_ForName ( name , false ) ;
if ( mod )
{
mod - > registration_sequence = registration_sequence ;
// register any images used by the models
if ( mod - > type = = mod_sprite )
{
sprout = ( dsprite_t * ) mod - > extradata ;
for ( i = 0 ; i < sprout - > numframes ; i + + )
mod - > skins [ 0 ] [ i ] = R_FindImage ( sprout - > frames [ i ] . name , it_sprite ) ;
}
# ifndef MD2_AS_MD3 // Knightmare- no longer used!
else if ( mod - > type = = mod_md2 )
{
pheader = ( dmdl_t * ) mod - > extradata ;
for ( i = 0 ; i < pheader - > num_skins ; i + + )
mod - > skins [ 0 ] [ i ] = R_FindImage ( ( char * ) pheader + pheader - > ofs_skins + i * MAX_SKINNAME , it_skin ) ;
mod - > numframes = pheader - > num_frames ;
}
# endif // MD2_AS_MD3
// Harven++ MD3
else if ( mod - > type = = mod_alias )
{
int k ;
pheader3 = ( maliasmodel_t * ) mod - > extradata ;
for ( i = 0 ; i < pheader3 - > num_meshes ; i + + )
{
for ( k = 0 ; k < pheader3 - > meshes [ i ] . num_skins ; k + + ) {
mod - > skins [ i ] [ k ] = R_FindImage ( pheader3 - > meshes [ i ] . skins [ k ] . name , it_skin ) ;
if ( strlen ( pheader3 - > meshes [ i ] . skins [ k ] . glowname ) )
pheader3 - > meshes [ i ] . skins [ k ] . glowimage = R_FindImage ( pheader3 - > meshes [ i ] . skins [ k ] . glowname , it_skin ) ;
}
}
mod - > numframes = pheader3 - > num_frames ;
}
// Harven-- MD3
else if ( mod - > type = = mod_brush )
{
for ( i = 0 ; i < mod - > numtexinfo ; i + + ) {
mod - > texinfo [ i ] . image - > registration_sequence = registration_sequence ;
mod - > texinfo [ i ] . glow - > registration_sequence = registration_sequence ;
}
}
}
return mod ;
}
/*
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
R_EndRegistration
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
*/
void R_EndRegistration ( void )
{
int i ;
model_t * mod ;
for ( i = 0 , mod = mod_known ; i < mod_numknown ; i + + , mod + + )
{
if ( ! mod - > name [ 0 ] )
continue ;
if ( mod - > registration_sequence ! = registration_sequence )
{ // don't need this model
Mod_Free ( mod ) ;
}
}
R_FreeUnusedImages ( ) ;
registration_active = false ; // map registration flag
}
//=============================================================================
/*
= = = = = = = = = = = = = = = =
Mod_Free
= = = = = = = = = = = = = = = =
*/
void Mod_Free ( model_t * mod )
{
// Knightmare- only brush models use the hunk system now
// Hunk_Free (mod->extradata);
switch ( mod - > type )
{
case mod_brush :
Hunk_Free ( mod - > extradata ) ;
break ;
case mod_alias :
case mod_sprite :
default :
ModChunk_Free ( mod - > extradata ) ;
break ;
}
# ifdef PROJECTION_SHADOWS // projection shadows from BeefQuake R6
if ( mod - > edge_tri )
free ( mod - > edge_tri ) ;
# endif // end projection shadows from BeefQuake R6
memset ( mod , 0 , sizeof ( * mod ) ) ;
}
/*
= = = = = = = = = = = = = = = =
Mod_FreeAll
= = = = = = = = = = = = = = = =
*/
void Mod_FreeAll ( void )
{
int i ;
for ( i = 0 ; i < mod_numknown ; i + + )
{
if ( mod_known [ i ] . extradatasize )
Mod_Free ( & mod_known [ i ] ) ;
}
}