2004-08-22 22:29:09 +00:00
# include "quakedef.h"
2004-12-15 19:53:30 +00:00
# ifdef RGLQUAKE
2004-08-22 22:29:09 +00:00
# include "glquake.h"
# include "shader.h"
# include "hash.h"
2004-11-29 01:21:00 +00:00
# ifdef ZYMOTICMODELS
# define SKELETALMODELS
# endif
2004-08-22 22:29:09 +00:00
//FIXME
typedef struct
{
float scale [ 3 ] ; // multiply qbyte verts by this
float translate [ 3 ] ; // then add this
char name [ 16 ] ; // frame name from grabbing
dtrivertx_t verts [ 1 ] ; // variable sized
} dmd2aliasframe_t ;
// entity_state_t->renderfx flags
# define Q2RF_MINLIGHT 1 // allways have some light (viewmodel)
# define Q2RF_VIEWERMODEL 2 // don't draw through eyes, only mirrors
# define Q2RF_WEAPONMODEL 4 // only draw through eyes
# define Q2RF_FULLBRIGHT 8 // allways draw full intensity
# define Q2RF_DEPTHHACK 16 // for view weapon Z crunching
# define Q2RF_TRANSLUCENT 32
# define Q2RF_FRAMELERP 64
# define Q2RF_BEAM 128
# define Q2RF_CUSTOMSKIN 256 // skin is an index in image_precache
# define Q2RF_GLOW 512 // pulse lighting for bonus items
# define Q2RF_SHELL_RED 1024
# define Q2RF_SHELL_GREEN 2048
# define Q2RF_SHELL_BLUE 4096
//ROGUE
# define Q2RF_IR_VISIBLE 0x00008000 // 32768
# define Q2RF_SHELL_DOUBLE 0x00010000 // 65536
# define Q2RF_SHELL_HALF_DAM 0x00020000
# define Q2RF_USE_DISGUISE 0x00040000
//ROGUE
extern cvar_t gl_part_flame , gl_part_torch , r_fullbrightSkins , r_fb_models ;
extern cvar_t r_noaliasshadows ;
void R_TorchEffect ( vec3_t pos , int type ) ;
void GLMod_FloodFillSkin ( qbyte * skin , int skinwidth , int skinheight ) ;
extern char loadname [ 32 ] ; // for hunk tags
int numTempColours ;
byte_vec4_t * tempColours ;
int numTempVertexCoords ;
2005-05-13 10:42:48 +00:00
vec3_t * tempVertexCoords ;
2004-08-22 22:29:09 +00:00
int numTempNormals ;
vec3_t * tempNormals ;
extern cvar_t gl_ati_truform ;
2004-11-18 17:55:04 +00:00
extern cvar_t r_vertexdlights ;
2004-08-22 22:29:09 +00:00
typedef struct {
int ofs_indexes ;
int numindexes ;
int ofs_trineighbours ;
int numskins ;
int ofsskins ;
2004-11-23 01:23:45 +00:00
qboolean sharesverts ; //used with models with two shaders using the same vertex.
2004-08-22 22:29:09 +00:00
int numverts ;
int ofs_st_array ;
int groups ;
int groupofs ;
int nextsurf ;
2004-11-17 18:13:33 +00:00
2004-11-23 01:23:45 +00:00
int numbones ;
int ofsbones ;
int numtransforms ;
int ofstransforms ;
//these exist only in the root mesh.
2004-12-24 08:45:56 +00:00
int numtagframes ;
2004-11-17 18:13:33 +00:00
int numtags ;
int ofstags ;
2004-08-22 22:29:09 +00:00
} galiasinfo_t ;
//frame is an index into this
typedef struct {
2004-11-29 01:21:00 +00:00
# ifdef SKELETALMODELS
2004-11-23 01:23:45 +00:00
qboolean isskeletal ;
2004-11-29 01:21:00 +00:00
# endif
2004-08-22 22:29:09 +00:00
int numposes ;
float rate ;
int poseofs ;
} galiasgroup_t ;
typedef struct {
int ofsverts ;
int ofsnormals ;
vec3_t scale ;
vec3_t scale_origin ;
} galiaspose_t ;
2004-11-29 01:21:00 +00:00
# ifdef SKELETALMODELS
2004-11-23 01:23:45 +00:00
typedef struct {
int parent ;
} galiasbone_t ;
typedef struct {
//skeletal poses refer to this.
int vertexindex ;
int boneindex ;
vec4_t org ;
} galisskeletaltransforms_t ;
2004-11-29 01:21:00 +00:00
# endif
2004-11-23 01:23:45 +00:00
2004-08-22 22:29:09 +00:00
//we can't be bothered with animating skins.
//We'll load up to four of them but after that you're on your own
typedef struct {
int skinwidth ;
int skinheight ;
int ofstexels ; //this is 8bit for frame 0 only. only valid in q1 models without replacement textures, used for colourising player skins.
float skinspeed ;
int texnums ;
int ofstexnums ;
} galiasskin_t ;
typedef struct {
int base ;
int bump ;
int fullbright ;
2004-10-19 16:10:14 +00:00
shader_t * shader ;
2004-08-22 22:29:09 +00:00
} galiastexnum_t ;
typedef struct {
char name [ MAX_QPATH ] ;
galiastexnum_t texnum ;
int colour ;
int skinnum ;
bucket_t bucket ;
} galiascolourmapped_t ;
static hashtable_t skincolourmapped ;
static vec3_t shadevector ;
static vec3_t shadelight , ambientlight ;
static void R_LerpFrames ( mesh_t * mesh , galiaspose_t * p1 , galiaspose_t * p2 , float lerp , qbyte alpha , float expand )
{
extern cvar_t r_nolerp , r_nolightdir ;
float blerp = 1 - lerp ;
int i ;
float l ;
int temp ;
vec3_t * p1v , * p2v ;
vec3_t * p1n , * p2n ;
2004-09-20 23:25:38 +00:00
p1v = ( vec3_t * ) ( ( char * ) p1 + p1 - > ofsverts ) ;
p2v = ( vec3_t * ) ( ( char * ) p2 + p2 - > ofsverts ) ;
2004-08-22 22:29:09 +00:00
2004-09-20 23:25:38 +00:00
p1n = ( vec3_t * ) ( ( char * ) p1 + p1 - > ofsnormals ) ;
p2n = ( vec3_t * ) ( ( char * ) p2 + p2 - > ofsnormals ) ;
2004-08-22 22:29:09 +00:00
if ( p1v = = p2v | | r_nolerp . value )
{
2004-09-20 23:25:38 +00:00
mesh - > normals_array = ( vec3_t * ) ( ( char * ) p1 + p1 - > ofsnormals ) ;
2005-05-13 10:42:48 +00:00
mesh - > xyz_array = p1v ;
2004-08-22 22:29:09 +00:00
if ( r_nolightdir . value )
{
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
2004-12-09 23:45:14 +00:00
mesh - > colors_array [ i ] [ 0 ] = /*ambientlight[0]/2*/ + shadelight [ 0 ] ;
mesh - > colors_array [ i ] [ 1 ] = /*ambientlight[1]/2*/ + shadelight [ 1 ] ;
mesh - > colors_array [ i ] [ 2 ] = /*ambientlight[2]/2*/ + shadelight [ 2 ] ;
2004-08-22 22:29:09 +00:00
mesh - > colors_array [ i ] [ 3 ] = alpha ;
}
}
else
{
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
l = DotProduct ( mesh - > normals_array [ i ] , shadevector ) ;
temp = l * ambientlight [ 0 ] + shadelight [ 0 ] ;
if ( temp < 0 ) temp = 0 ;
else if ( temp > 255 ) temp = 255 ;
mesh - > colors_array [ i ] [ 0 ] = temp ;
temp = l * ambientlight [ 1 ] + shadelight [ 1 ] ;
if ( temp < 0 ) temp = 0 ;
else if ( temp > 255 ) temp = 255 ;
mesh - > colors_array [ i ] [ 1 ] = temp ;
temp = l * ambientlight [ 2 ] + shadelight [ 2 ] ;
if ( temp < 0 ) temp = 0 ;
else if ( temp > 255 ) temp = 255 ;
mesh - > colors_array [ i ] [ 2 ] = temp ;
mesh - > colors_array [ i ] [ 3 ] = alpha ;
}
}
}
else
{
if ( r_nolightdir . value )
{
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
mesh - > normals_array [ i ] [ 0 ] = p1n [ i ] [ 0 ] * lerp + p2n [ i ] [ 0 ] * blerp ;
mesh - > normals_array [ i ] [ 1 ] = p1n [ i ] [ 1 ] * lerp + p2n [ i ] [ 1 ] * blerp ;
mesh - > normals_array [ i ] [ 2 ] = p1n [ i ] [ 2 ] * lerp + p2n [ i ] [ 2 ] * blerp ;
mesh - > xyz_array [ i ] [ 0 ] = p1v [ i ] [ 0 ] * lerp + p2v [ i ] [ 0 ] * blerp ;
mesh - > xyz_array [ i ] [ 1 ] = p1v [ i ] [ 1 ] * lerp + p2v [ i ] [ 1 ] * blerp ;
mesh - > xyz_array [ i ] [ 2 ] = p1v [ i ] [ 2 ] * lerp + p2v [ i ] [ 2 ] * blerp ;
mesh - > colors_array [ i ] [ 0 ] = ambientlight [ 0 ] ;
mesh - > colors_array [ i ] [ 1 ] = ambientlight [ 1 ] ;
mesh - > colors_array [ i ] [ 2 ] = ambientlight [ 2 ] ;
mesh - > colors_array [ i ] [ 3 ] = alpha ;
}
}
else
{
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
mesh - > normals_array [ i ] [ 0 ] = p1n [ i ] [ 0 ] * lerp + p2n [ i ] [ 0 ] * blerp ;
mesh - > normals_array [ i ] [ 1 ] = p1n [ i ] [ 1 ] * lerp + p2n [ i ] [ 1 ] * blerp ;
mesh - > normals_array [ i ] [ 2 ] = p1n [ i ] [ 2 ] * lerp + p2n [ i ] [ 2 ] * blerp ;
mesh - > xyz_array [ i ] [ 0 ] = p1v [ i ] [ 0 ] * lerp + p2v [ i ] [ 0 ] * blerp ;
mesh - > xyz_array [ i ] [ 1 ] = p1v [ i ] [ 1 ] * lerp + p2v [ i ] [ 1 ] * blerp ;
mesh - > xyz_array [ i ] [ 2 ] = p1v [ i ] [ 2 ] * lerp + p2v [ i ] [ 2 ] * blerp ;
l = DotProduct ( mesh - > normals_array [ i ] , shadevector ) ;
temp = l * ambientlight [ 0 ] + shadelight [ 0 ] ;
if ( temp < 0 ) temp = 0 ;
else if ( temp > 255 ) temp = 255 ;
mesh - > colors_array [ i ] [ 0 ] = temp ;
temp = l * ambientlight [ 1 ] + shadelight [ 1 ] ;
if ( temp < 0 ) temp = 0 ;
else if ( temp > 255 ) temp = 255 ;
mesh - > colors_array [ i ] [ 1 ] = temp ;
temp = l * ambientlight [ 2 ] + shadelight [ 2 ] ;
if ( temp < 0 ) temp = 0 ;
else if ( temp > 255 ) temp = 255 ;
mesh - > colors_array [ i ] [ 2 ] = temp ;
mesh - > colors_array [ i ] [ 3 ] = alpha ;
}
}
}
if ( expand )
{
2005-05-13 10:42:48 +00:00
if ( mesh - > xyz_array = = p1v )
2004-08-22 22:29:09 +00:00
{
2005-05-13 10:42:48 +00:00
mesh - > xyz_array = tempVertexCoords ;
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
mesh - > xyz_array [ i ] [ 0 ] = p1v [ i ] [ 0 ] + mesh - > normals_array [ i ] [ 0 ] * expand ;
mesh - > xyz_array [ i ] [ 1 ] = p1v [ i ] [ 1 ] + mesh - > normals_array [ i ] [ 1 ] * expand ;
mesh - > xyz_array [ i ] [ 2 ] = p1v [ i ] [ 2 ] + mesh - > normals_array [ i ] [ 2 ] * expand ;
}
}
else
{
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
mesh - > xyz_array [ i ] [ 0 ] + = mesh - > normals_array [ i ] [ 0 ] * expand ;
mesh - > xyz_array [ i ] [ 1 ] + = mesh - > normals_array [ i ] [ 1 ] * expand ;
mesh - > xyz_array [ i ] [ 2 ] + = mesh - > normals_array [ i ] [ 2 ] * expand ;
}
2004-08-22 22:29:09 +00:00
}
}
}
2004-11-29 01:21:00 +00:00
# ifdef SKELETALMODELS
2004-11-23 01:23:45 +00:00
static void R_BuildSkeletalMesh ( mesh_t * mesh , float * plerp , float * * pose , int poses , galiasbone_t * bones , int bonecount , galisskeletaltransforms_t * weights , int numweights )
{
float bonepose [ 256 ] [ 12 ] ;
float * outhead ;
galisskeletaltransforms_t * v ;
int i , k , b ;
float * out , * matrix , m [ 12 ] ;
// vertex weighted skeletal
// interpolate matrices and concatenate them to their parents
for ( i = 0 ; i < bonecount ; i + + )
{
for ( k = 0 ; k < 12 ; k + + )
m [ k ] = 0 ;
for ( b = 0 ; b < poses ; b + + )
{
matrix = pose [ b ] + i * 12 ;
for ( k = 0 ; k < 12 ; k + + )
m [ k ] + = matrix [ k ] * plerp [ b ] ;
}
if ( bones [ i ] . parent > = 0 )
R_ConcatTransforms ( ( void * ) bonepose [ bones [ i ] . parent ] , ( void * ) m , ( void * ) bonepose [ i ] ) ;
else
for ( k = 0 ; k < 12 ; k + + ) //parentless
bonepose [ i ] [ k ] = m [ k ] ;
}
outhead = ( float * ) mesh - > xyz_array ;
// blend the vertex bone weights
memset ( outhead , 0 , mesh - > numvertexes * sizeof ( mesh - > xyz_array [ 0 ] ) ) ;
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
mesh - > normals_array [ i ] [ 0 ] = 0 ;
mesh - > normals_array [ i ] [ 1 ] = 0 ;
mesh - > normals_array [ i ] [ 2 ] = 1 ;
mesh - > colors_array [ i ] [ 0 ] = ambientlight [ 0 ] ;
mesh - > colors_array [ i ] [ 1 ] = ambientlight [ 1 ] ;
mesh - > colors_array [ i ] [ 2 ] = ambientlight [ 2 ] ;
mesh - > colors_array [ i ] [ 3 ] = 255 ; //alpha;
/*
mesh - > xyz_array [ i ] [ 0 ] = 0 ;
mesh - > xyz_array [ i ] [ 1 ] = 0 ;
mesh - > xyz_array [ i ] [ 2 ] = 0 ;
mesh - > xyz_array [ i ] [ 3 ] = 1 ;
*/
}
v = weights ;
for ( i = 0 ; i < numweights ; i + + , v + + )
{
2005-05-13 10:42:48 +00:00
out = outhead + v - > vertexindex * 3 ;
2004-11-23 01:23:45 +00:00
matrix = bonepose [ v - > boneindex ] ;
// FIXME: this can very easily be optimized with SSE or 3DNow
out [ 0 ] + = v - > org [ 0 ] * matrix [ 0 ] + v - > org [ 1 ] * matrix [ 1 ] + v - > org [ 2 ] * matrix [ 2 ] + v - > org [ 3 ] * matrix [ 3 ] ;
out [ 1 ] + = v - > org [ 0 ] * matrix [ 4 ] + v - > org [ 1 ] * matrix [ 5 ] + v - > org [ 2 ] * matrix [ 6 ] + v - > org [ 3 ] * matrix [ 7 ] ;
out [ 2 ] + = v - > org [ 0 ] * matrix [ 8 ] + v - > org [ 1 ] * matrix [ 9 ] + v - > org [ 2 ] * matrix [ 10 ] + v - > org [ 3 ] * matrix [ 11 ] ;
}
}
2004-11-29 01:21:00 +00:00
# endif
2004-11-23 01:23:45 +00:00
2004-09-07 23:09:15 +00:00
static void R_GAliasAddDlights ( mesh_t * mesh , vec3_t org , vec3_t angles )
{
int l , v ;
vec3_t rel ;
vec3_t dir ;
float dot , d , a , f ;
for ( l = 0 ; l < MAX_DLIGHTS ; l + + )
{
2004-11-27 08:16:25 +00:00
if ( cl_dlights [ l ] . radius )
2004-09-07 23:09:15 +00:00
{
VectorSubtract ( cl_dlights [ l ] . origin ,
org ,
dir ) ;
if ( Length ( dir ) > cl_dlights [ l ] . radius + mesh - > radius ) //far out man!
continue ;
2005-02-28 07:16:19 +00:00
rel [ 0 ] = - DotProduct ( dir , currententity - > axis [ 0 ] ) ;
rel [ 1 ] = - DotProduct ( dir , currententity - > axis [ 1 ] ) ; //quake's crazy.
rel [ 2 ] = - DotProduct ( dir , currententity - > axis [ 2 ] ) ;
2004-09-07 23:09:15 +00:00
/*
glBegin ( GL_LINES ) ;
glVertex3f ( 0 , 0 , 0 ) ;
glVertex3f ( rel [ 0 ] , rel [ 1 ] , rel [ 2 ] ) ;
glEnd ( ) ;
*/
for ( v = 0 ; v < mesh - > numvertexes ; v + + )
{
VectorSubtract ( mesh - > xyz_array [ v ] , rel , dir ) ;
dot = DotProduct ( dir , mesh - > normals_array [ v ] ) ;
if ( dot > 0 )
{
d = DotProduct ( dir , dir ) ;
a = 1 / d ;
if ( a > 0 )
{
a * = 10000000 * dot / sqrt ( d ) ;
f = mesh - > colors_array [ v ] [ 0 ] + a * cl_dlights [ l ] . color [ 0 ] ;
if ( f > 255 )
f = 255 ;
else if ( f < 0 )
f = 0 ;
mesh - > colors_array [ v ] [ 0 ] = f ;
f = mesh - > colors_array [ v ] [ 1 ] + a * cl_dlights [ l ] . color [ 1 ] ;
if ( f > 255 )
f = 255 ;
else if ( f < 0 )
f = 0 ;
mesh - > colors_array [ v ] [ 1 ] = f ;
f = mesh - > colors_array [ v ] [ 2 ] + a * cl_dlights [ l ] . color [ 2 ] ;
if ( f > 255 )
f = 255 ;
else if ( f < 0 )
f = 0 ;
mesh - > colors_array [ v ] [ 2 ] = f ;
}
// else
// mesh->colors_array[v][1] =255;
}
// else
// mesh->colors_array[v][2] =255;
}
}
}
}
2004-11-23 01:23:45 +00:00
static qboolean R_GAliasBuildMesh ( mesh_t * mesh , galiasinfo_t * inf , int frame1 , int frame2 , float lerp , float alpha )
2004-08-22 22:29:09 +00:00
{
galiasgroup_t * g1 , * g2 ;
2005-05-15 18:49:04 +00:00
2004-08-22 22:29:09 +00:00
if ( ! inf - > groups )
{
2004-10-26 14:54:59 +00:00
Con_DPrintf ( " Model with no frames (%s) \n " , currententity - > model - > name ) ;
2004-11-23 01:23:45 +00:00
return false ;
2004-08-22 22:29:09 +00:00
}
if ( frame1 < 0 )
{
2004-10-26 14:54:59 +00:00
Con_DPrintf ( " Negative frame (%s) \n " , currententity - > model - > name ) ;
2004-08-22 22:29:09 +00:00
frame1 = 0 ;
}
if ( frame2 < 0 )
{
2004-10-26 14:54:59 +00:00
Con_DPrintf ( " Negative frame (%s) \n " , currententity - > model - > name ) ;
2004-08-22 22:29:09 +00:00
frame2 = frame1 ;
}
if ( frame1 > = inf - > groups )
{
2004-10-26 14:54:59 +00:00
Con_DPrintf ( " Too high frame %i (%s) \n " , frame1 , currententity - > model - > name ) ;
2004-08-22 22:29:09 +00:00
frame1 = 0 ;
}
if ( frame2 > = inf - > groups )
{
2004-10-26 14:54:59 +00:00
Con_DPrintf ( " Too high frame %i (%s) \n " , frame2 , currententity - > model - > name ) ;
2004-08-22 22:29:09 +00:00
frame2 = frame1 ;
}
if ( lerp < = 0 )
frame2 = frame1 ;
2004-11-23 01:23:45 +00:00
else if ( lerp > = 1 )
2004-08-22 22:29:09 +00:00
frame1 = frame2 ;
if ( numTempColours < inf - > numverts )
{
if ( tempColours )
BZ_Free ( tempColours ) ;
tempColours = BZ_Malloc ( sizeof ( * tempColours ) * inf - > numverts ) ;
numTempColours = inf - > numverts ;
}
if ( numTempNormals < inf - > numverts )
{
if ( tempNormals )
BZ_Free ( tempNormals ) ;
tempNormals = BZ_Malloc ( sizeof ( * tempNormals ) * inf - > numverts ) ;
numTempNormals = inf - > numverts ;
}
if ( numTempVertexCoords < inf - > numverts )
{
if ( tempVertexCoords )
BZ_Free ( tempVertexCoords ) ;
tempVertexCoords = BZ_Malloc ( sizeof ( * tempVertexCoords ) * inf - > numverts ) ;
numTempVertexCoords = inf - > numverts ;
}
2005-05-15 18:49:04 +00:00
mesh - > numvertexes = inf - > numverts ;
2004-10-19 16:10:14 +00:00
mesh - > indexes = ( index_t * ) ( ( char * ) inf + inf - > ofs_indexes ) ;
2004-08-22 22:29:09 +00:00
mesh - > numindexes = inf - > numindexes ;
2005-05-15 18:49:04 +00:00
if ( inf - > sharesverts )
return false ; //don't generate the new vertex positions. We still have them all.
2004-09-20 23:25:38 +00:00
mesh - > st_array = ( vec2_t * ) ( ( char * ) inf + inf - > ofs_st_array ) ;
2004-08-22 22:29:09 +00:00
mesh - > lmst_array = NULL ;
mesh - > colors_array = tempColours ;
mesh - > xyz_array = tempVertexCoords ;
2004-09-20 23:25:38 +00:00
mesh - > trneighbors = ( int * ) ( ( char * ) inf + inf - > ofs_trineighbours ) ;
2004-08-22 22:29:09 +00:00
2004-11-23 01:23:45 +00:00
mesh - > normals_array = tempNormals ;
2004-09-20 23:25:38 +00:00
g1 = ( galiasgroup_t * ) ( ( char * ) inf + inf - > groupofs + sizeof ( galiasgroup_t ) * frame1 ) ;
g2 = ( galiasgroup_t * ) ( ( char * ) inf + inf - > groupofs + sizeof ( galiasgroup_t ) * frame2 ) ;
2004-08-22 22:29:09 +00:00
2004-11-23 01:23:45 +00:00
//we don't support meshes with one pose skeletal and annother not.
//we don't support meshes with one group skeletal and annother not.
2004-11-29 01:21:00 +00:00
# ifdef SKELETALMODELS
2004-11-23 01:23:45 +00:00
if ( g1 - > isskeletal )
{
int l = 0 ;
float plerp [ 4 ] ;
float * pose [ 4 ] ;
float mlerp ; //minor lerp, poses within a group.
mlerp = cl . time * g1 - > rate ;
frame1 = mlerp ;
frame2 = frame1 + 1 ;
mlerp - = frame1 ;
frame1 = frame1 % g1 - > numposes ;
frame2 = frame2 % g1 - > numposes ;
2004-11-23 15:30:34 +00:00
plerp [ l ] = ( 1 - mlerp ) * ( 1 - lerp ) ;
2004-11-23 01:23:45 +00:00
if ( plerp [ l ] > 0 )
pose [ l + + ] = ( float * ) ( ( char * ) g1 + g1 - > poseofs + sizeof ( float ) * inf - > numbones * 12 * frame1 ) ;
2004-11-23 15:30:34 +00:00
plerp [ l ] = ( mlerp ) * ( 1 - lerp ) ;
2004-11-23 01:23:45 +00:00
if ( plerp [ l ] > 0 )
pose [ l + + ] = ( float * ) ( ( char * ) g1 + g1 - > poseofs + sizeof ( float ) * inf - > numbones * 12 * frame2 ) ;
mlerp = cl . time * g2 - > rate ;
frame1 = mlerp ;
frame2 = frame1 + 1 ;
mlerp - = frame1 ;
frame1 = frame1 % g2 - > numposes ;
frame2 = frame2 % g2 - > numposes ;
2004-11-23 15:30:34 +00:00
plerp [ l ] = ( 1 - mlerp ) * ( lerp ) ;
2004-11-23 01:23:45 +00:00
if ( plerp [ l ] > 0 )
pose [ l + + ] = ( float * ) ( ( char * ) g2 + g2 - > poseofs + sizeof ( float ) * inf - > numbones * 12 * frame1 ) ;
2004-11-23 15:30:34 +00:00
plerp [ l ] = ( mlerp ) * ( lerp ) ;
2004-11-23 01:23:45 +00:00
if ( plerp [ l ] > 0 )
pose [ l + + ] = ( float * ) ( ( char * ) g2 + g2 - > poseofs + sizeof ( float ) * inf - > numbones * 12 * frame2 ) ;
2004-11-23 14:58:32 +00:00
/*
pose [ 0 ] = ( float * ) ( ( char * ) g1 + g1 - > poseofs ) ;
2004-11-23 01:23:45 +00:00
plerp [ 0 ] = 1 ;
plerp [ 1 ] = 0 ;
plerp [ 3 ] = 0 ;
plerp [ 4 ] = 0 ;
l = 1 ;
*/
R_BuildSkeletalMesh ( mesh , plerp , pose , l , ( galiasbone_t * ) ( ( char * ) inf + inf - > ofsbones ) , inf - > numbones , ( galisskeletaltransforms_t * ) ( ( char * ) inf + inf - > ofstransforms ) , inf - > numtransforms ) ;
return false ;
}
2004-11-29 01:21:00 +00:00
# endif
2004-11-23 01:23:45 +00:00
2004-08-22 22:29:09 +00:00
if ( g1 = = g2 ) //lerping within group is only done if not changing group
{
lerp = cl . time * g1 - > rate ;
frame1 = lerp ;
frame2 = frame1 + 1 ;
lerp - = frame1 ;
frame1 = frame1 % g1 - > numposes ;
frame2 = frame2 % g1 - > numposes ;
}
2004-11-23 01:23:45 +00:00
else //don't bother with a four way lerp. Yeah, this will produce jerkyness with models with just framegroups.
2004-08-22 22:29:09 +00:00
{
frame1 = 0 ;
frame2 = 0 ;
}
R_LerpFrames ( mesh , ( galiaspose_t * ) ( ( char * ) g1 + g1 - > poseofs + sizeof ( galiaspose_t ) * frame1 ) ,
( galiaspose_t * ) ( ( char * ) g2 + g2 - > poseofs + sizeof ( galiaspose_t ) * frame2 ) ,
1 - lerp , ( qbyte ) ( alpha * 255 ) , currententity - > fatness ) ; //20*sin(cl.time));
2004-11-23 01:23:45 +00:00
return true ; //to allow the mesh to be dlighted.
2004-08-22 22:29:09 +00:00
}
void GL_GAliasFlushSkinCache ( void )
{
int i ;
bucket_t * b ;
for ( i = 0 ; i < skincolourmapped . numbuckets ; i + + )
{
while ( ( b = skincolourmapped . bucket [ i ] ) )
{
skincolourmapped . bucket [ i ] = b - > next ;
BZ_Free ( b - > data ) ;
}
}
if ( skincolourmapped . bucket )
BZ_Free ( skincolourmapped . bucket ) ;
skincolourmapped . bucket = NULL ;
skincolourmapped . numbuckets = 0 ;
}
static galiastexnum_t * GL_ChooseSkin ( galiasinfo_t * inf , char * modelname , entity_t * e )
{
galiasskin_t * skins ;
galiastexnum_t * texnums ;
int frame ;
int tc , bc ;
2005-03-20 02:57:11 +00:00
if ( ! gl_nocolors . value )
2004-08-22 22:29:09 +00:00
{
2005-02-06 02:47:36 +00:00
if ( e - > scoreboard )
2004-09-26 00:30:42 +00:00
{
2005-02-06 02:47:36 +00:00
if ( ! e - > scoreboard - > skin )
Skin_Find ( e - > scoreboard ) ;
tc = e - > scoreboard - > topcolor ;
bc = e - > scoreboard - > bottomcolor ;
//colour forcing
if ( cl . splitclients < 2 & & ! ( cl . fpd & FPD_NO_FORCE_COLOR ) ) //no colour/skin forcing in splitscreen.
2004-09-26 00:30:42 +00:00
{
2005-02-06 02:47:36 +00:00
if ( cl . teamplay & & ! strcmp ( e - > scoreboard - > team , cl . players [ cl . playernum [ 0 ] ] . team ) )
{
if ( cl_teamtopcolor > = 0 )
tc = cl_teamtopcolor ;
if ( cl_teambottomcolor > = 0 )
bc = cl_teambottomcolor ;
}
else
{
if ( cl_enemytopcolor > = 0 )
tc = cl_enemytopcolor ;
if ( cl_enemybottomcolor > = 0 )
bc = cl_enemybottomcolor ;
}
2004-09-26 00:30:42 +00:00
}
}
2004-08-22 22:29:09 +00:00
else
{
2005-02-06 02:47:36 +00:00
tc = 1 ;
bc = 1 ;
2004-08-22 22:29:09 +00:00
}
2005-02-06 02:47:36 +00:00
if ( tc ! = 1 | | bc ! = 1 | | ( e - > scoreboard & & e - > scoreboard - > skin ) )
2004-08-22 22:29:09 +00:00
{
2005-02-06 02:47:36 +00:00
int inwidth , inheight ;
int tinwidth , tinheight ;
char * skinname ;
qbyte * original ;
int cc ;
galiascolourmapped_t * cm ;
2005-03-20 02:57:11 +00:00
char hashname [ 512 ] ;
2005-02-06 02:47:36 +00:00
cc = ( tc < < 4 ) | bc ;
2005-03-20 02:57:11 +00:00
if ( e - > scoreboard & & e - > scoreboard - > skin & & ! gl_nocolors . value )
2004-08-22 22:29:09 +00:00
{
2005-03-20 02:57:11 +00:00
sprintf ( hashname , " %s$%s " , modelname , e - > scoreboard - > skin - > name ) ;
skinname = hashname ;
2004-08-22 22:29:09 +00:00
}
2005-03-20 02:57:11 +00:00
else
skinname = modelname ;
2005-02-06 02:47:36 +00:00
if ( ! skincolourmapped . numbuckets )
Hash_InitTable ( & skincolourmapped , 256 , BZ_Malloc ( Hash_BytesForBuckets ( 256 ) ) ) ;
for ( cm = Hash_Get ( & skincolourmapped , skinname ) ; cm ; cm = Hash_GetNext ( & skincolourmapped , skinname , cm ) )
{
if ( cm - > colour = = cc & & cm - > skinnum = = e - > skinnum )
{
return & cm - > texnum ;
}
}
2005-03-20 02:57:11 +00:00
if ( ! inf - > numskins )
{
skins = NULL ;
texnums = NULL ;
}
else
{
skins = ( galiasskin_t * ) ( ( char * ) inf + inf - > ofsskins ) ;
if ( ! skins - > texnums )
return NULL ;
if ( e - > skinnum > = 0 & & e - > skinnum < inf - > numskins )
skins + = e - > skinnum ;
texnums = ( galiastexnum_t * ) ( ( char * ) skins + skins - > ofstexnums ) ;
}
2005-02-06 02:47:36 +00:00
//colourmap isn't present yet.
cm = BZ_Malloc ( sizeof ( * cm ) ) ;
Q_strncpyz ( cm - > name , skinname , sizeof ( cm - > name ) ) ;
2005-02-09 19:32:09 +00:00
Hash_Add ( & skincolourmapped , cm - > name , cm , & cm - > bucket ) ;
2005-02-06 02:47:36 +00:00
cm - > colour = cc ;
cm - > skinnum = e - > skinnum ;
cm - > texnum . fullbright = 0 ;
cm - > texnum . base = 0 ;
2005-03-20 02:57:11 +00:00
if ( ! texnums )
{ //load just the skin
if ( e - > scoreboard & & e - > scoreboard - > skin )
{
original = Skin_Cache8 ( e - > scoreboard - > skin ) ;
if ( ! original )
return NULL ;
inwidth = e - > scoreboard - > skin - > width ;
inheight = e - > scoreboard - > skin - > height ;
cm - > texnum . base = cm - > texnum . fullbright = GL_LoadTexture ( e - > scoreboard - > skin - > name , inwidth , inheight , original , true , false ) ;
return & cm - > texnum ;
}
return NULL ;
}
2005-02-06 02:47:36 +00:00
cm - > texnum . bump = texnums [ cm - > skinnum ] . bump ; //can't colour bumpmapping
2005-03-28 00:11:59 +00:00
if ( ( ! texnums | | ! strcmp ( modelname , " progs/player.mdl " ) ) & & e - > scoreboard & & e - > scoreboard - > skin )
2004-12-09 23:45:14 +00:00
{
2005-02-06 02:47:36 +00:00
original = Skin_Cache8 ( e - > scoreboard - > skin ) ;
inwidth = e - > scoreboard - > skin - > width ;
inheight = e - > scoreboard - > skin - > height ;
2004-12-09 23:45:14 +00:00
}
else
{
original = NULL ;
inwidth = 0 ;
2005-03-28 00:11:59 +00:00
inheight = 0 ;
2004-12-09 23:45:14 +00:00
}
2005-02-06 02:47:36 +00:00
if ( ! original )
2004-08-22 22:29:09 +00:00
{
2005-02-06 02:47:36 +00:00
if ( skins - > ofstexels )
{
original = ( qbyte * ) skins + skins - > ofstexels ;
inwidth = skins - > skinwidth ;
inheight = skins - > skinheight ;
}
2004-08-22 22:29:09 +00:00
else
{
2005-02-06 02:47:36 +00:00
original = NULL ;
inwidth = 0 ;
inheight = 0 ;
2004-08-22 22:29:09 +00:00
}
}
2005-02-06 02:47:36 +00:00
tinwidth = skins - > skinwidth ;
tinheight = skins - > skinheight ;
if ( original )
2004-08-22 22:29:09 +00:00
{
2005-02-06 02:47:36 +00:00
int i , j ;
qbyte translate [ 256 ] ;
unsigned translate32 [ 256 ] ;
static unsigned pixels [ 512 * 512 ] ;
unsigned * out ;
unsigned frac , fracstep ;
unsigned scaled_width , scaled_height ;
qbyte * inrow ;
texnums = & cm - > texnum ;
texnums - > base = 0 ;
texnums - > fullbright = 0 ;
scaled_width = gl_max_size . value < 512 ? gl_max_size . value : 512 ;
scaled_height = gl_max_size . value < 512 ? gl_max_size . value : 512 ;
for ( i = 0 ; i < 256 ; i + + )
translate [ i ] = i ;
tc < < = 4 ;
bc < < = 4 ;
for ( i = 0 ; i < 16 ; i + + )
{
if ( tc < 128 ) // the artists made some backwards ranges. sigh.
translate [ TOP_RANGE + i ] = tc + i ;
else
translate [ TOP_RANGE + i ] = tc + 15 - i ;
if ( bc < 128 )
translate [ BOTTOM_RANGE + i ] = bc + i ;
else
translate [ BOTTOM_RANGE + i ] = bc + 15 - i ;
}
for ( i = 0 ; i < 256 ; i + + )
translate32 [ i ] = d_8to24rgbtable [ translate [ i ] ] ;
out = pixels ;
fracstep = tinwidth * 0x10000 / scaled_width ;
for ( i = 0 ; i < scaled_height ; i + + , out + = scaled_width )
2004-08-22 22:29:09 +00:00
{
2005-03-28 00:11:59 +00:00
inrow = original + inwidth * ( i * inheight / scaled_height ) ;
2005-02-06 02:47:36 +00:00
frac = fracstep > > 1 ;
for ( j = 0 ; j < scaled_width ; j + = 4 )
{
out [ j ] = translate32 [ inrow [ frac > > 16 ] ] ;
frac + = fracstep ;
out [ j + 1 ] = translate32 [ inrow [ frac > > 16 ] ] ;
frac + = fracstep ;
out [ j + 2 ] = translate32 [ inrow [ frac > > 16 ] ] ;
frac + = fracstep ;
out [ j + 3 ] = translate32 [ inrow [ frac > > 16 ] ] ;
frac + = fracstep ;
}
2004-08-22 22:29:09 +00:00
}
2005-02-06 02:47:36 +00:00
texnums - > base = texture_extension_number + + ;
GL_Bind ( texnums - > base ) ;
qglTexImage2D ( GL_TEXTURE_2D , 0 , gl_solid_format , scaled_width , scaled_height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , pixels ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
//now do the fullbrights.
out = pixels ;
fracstep = tinwidth * 0x10000 / scaled_width ;
for ( i = 0 ; i < scaled_height ; i + + , out + = scaled_width )
{
2005-03-28 00:11:59 +00:00
inrow = original + inwidth * ( i * inheight / scaled_height ) ;
2005-02-06 02:47:36 +00:00
frac = fracstep > > 1 ;
for ( j = 0 ; j < scaled_width ; j + = 1 )
{
if ( inrow [ frac > > 16 ] < 255 - vid . fullbright )
( ( char * ) ( & out [ j ] ) ) [ 3 ] = 0 ; //alpha 0
frac + = fracstep ;
}
}
texnums - > fullbright = texture_extension_number + + ;
GL_Bind ( texnums - > fullbright ) ;
qglTexImage2D ( GL_TEXTURE_2D , 0 , gl_alpha_format , scaled_width , scaled_height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , pixels ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2004-08-22 22:29:09 +00:00
}
2005-02-06 02:47:36 +00:00
else
{
skins = ( galiasskin_t * ) ( ( char * ) inf + inf - > ofsskins ) ;
if ( e - > skinnum > = 0 & & e - > skinnum < inf - > numskins )
skins + = e - > skinnum ;
if ( ! skins - > texnums )
return NULL ;
frame = cl . time * skins - > skinspeed ;
frame = frame % skins - > texnums ;
texnums = ( galiastexnum_t * ) ( ( char * ) skins + skins - > ofstexnums + frame * sizeof ( galiastexnum_t ) ) ;
memcpy ( & cm - > texnum , texnums , sizeof ( cm - > texnum ) ) ;
}
return & cm - > texnum ;
2004-08-22 22:29:09 +00:00
}
}
2005-03-18 06:14:33 +00:00
if ( ! inf - > numskins )
return NULL ;
2004-09-13 04:16:52 +00:00
skins = ( galiasskin_t * ) ( ( char * ) inf + inf - > ofsskins ) ;
2004-08-22 22:29:09 +00:00
if ( e - > skinnum > = 0 & & e - > skinnum < inf - > numskins )
skins + = e - > skinnum ;
if ( ! skins - > texnums )
return NULL ;
frame = cl . time * skins - > skinspeed ;
frame = frame % skins - > texnums ;
2004-09-13 04:16:52 +00:00
texnums = ( galiastexnum_t * ) ( ( char * ) skins + skins - > ofstexnums + frame * sizeof ( galiastexnum_t ) ) ;
2004-08-22 22:29:09 +00:00
return texnums ;
}
static int numFacing ;
static qbyte * triangleFacing ;
static void R_CalcFacing ( mesh_t * mesh , vec3_t lightpos )
{
float * v1 , * v2 , * v3 ;
vec3_t d1 , d2 , norm ;
int i ;
2004-10-19 16:10:14 +00:00
index_t * indexes = mesh - > indexes ;
2004-08-22 22:29:09 +00:00
int numtris = mesh - > numindexes / 3 ;
if ( numFacing < numtris )
{
if ( triangleFacing )
BZ_Free ( triangleFacing ) ;
triangleFacing = BZ_Malloc ( sizeof ( * triangleFacing ) * numtris ) ;
numFacing = numtris ;
}
for ( i = 0 ; i < numtris ; i + + , indexes + = 3 )
{
v1 = ( float * ) ( mesh - > xyz_array + indexes [ 0 ] ) ;
v2 = ( float * ) ( mesh - > xyz_array + indexes [ 1 ] ) ;
v3 = ( float * ) ( mesh - > xyz_array + indexes [ 2 ] ) ;
VectorSubtract ( v1 , v2 , d1 ) ;
VectorSubtract ( v3 , v2 , d2 ) ;
CrossProduct ( d1 , d2 , norm ) ;
triangleFacing [ i ] = ( ( lightpos [ 0 ] - v1 [ 0 ] ) * norm [ 0 ] + ( lightpos [ 1 ] - v1 [ 1 ] ) * norm [ 1 ] + ( lightpos [ 2 ] - v1 [ 2 ] ) * norm [ 2 ] ) > 0 ;
}
}
# define PROJECTION_DISTANCE 30000
static int numProjectedShadowVerts ;
static vec3_t * ProjectedShadowVerts ;
static void R_ProjectShadowVolume ( mesh_t * mesh , vec3_t lightpos )
{
int numverts = mesh - > numvertexes ;
int i ;
2005-05-13 10:42:48 +00:00
vec3_t * input = mesh - > xyz_array ;
2004-08-22 22:29:09 +00:00
vec3_t * projected ;
if ( numProjectedShadowVerts < numverts )
{
if ( ProjectedShadowVerts )
BZ_Free ( ProjectedShadowVerts ) ;
ProjectedShadowVerts = BZ_Malloc ( sizeof ( * ProjectedShadowVerts ) * numverts ) ;
numProjectedShadowVerts = numverts ;
}
projected = ProjectedShadowVerts ;
for ( i = 0 ; i < numverts ; i + + )
{
projected [ i ] [ 0 ] = input [ i ] [ 0 ] + ( input [ i ] [ 0 ] - lightpos [ 0 ] ) * PROJECTION_DISTANCE ;
projected [ i ] [ 1 ] = input [ i ] [ 1 ] + ( input [ i ] [ 1 ] - lightpos [ 1 ] ) * PROJECTION_DISTANCE ;
projected [ i ] [ 2 ] = input [ i ] [ 2 ] + ( input [ i ] [ 2 ] - lightpos [ 2 ] ) * PROJECTION_DISTANCE ;
}
}
static void R_DrawShadowVolume ( mesh_t * mesh )
{
int t ;
vec3_t * proj = ProjectedShadowVerts ;
2005-05-13 10:42:48 +00:00
vec3_t * verts = mesh - > xyz_array ;
2004-10-19 16:10:14 +00:00
index_t * indexes = mesh - > indexes ;
2004-08-22 22:29:09 +00:00
int * neighbours = mesh - > trneighbors ;
int numtris = mesh - > numindexes / 3 ;
2005-01-07 02:54:22 +00:00
qglBegin ( GL_TRIANGLES ) ;
2004-08-22 22:29:09 +00:00
for ( t = 0 ; t < numtris ; t + + )
{
if ( triangleFacing [ t ] )
{
//draw front
2005-01-07 02:54:22 +00:00
qglVertex3fv ( verts [ indexes [ t * 3 + 0 ] ] ) ;
qglVertex3fv ( verts [ indexes [ t * 3 + 1 ] ] ) ;
qglVertex3fv ( verts [ indexes [ t * 3 + 2 ] ] ) ;
2004-08-22 22:29:09 +00:00
//draw back
2005-01-07 02:54:22 +00:00
qglVertex3fv ( proj [ indexes [ t * 3 + 1 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 0 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 2 ] ] ) ;
2004-08-22 22:29:09 +00:00
//draw side caps
if ( neighbours [ t * 3 + 0 ] < 0 | | ! triangleFacing [ neighbours [ t * 3 + 0 ] ] )
{
2005-01-07 02:54:22 +00:00
qglVertex3fv ( verts [ indexes [ t * 3 + 1 ] ] ) ;
qglVertex3fv ( verts [ indexes [ t * 3 + 0 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 0 ] ] ) ;
qglVertex3fv ( verts [ indexes [ t * 3 + 1 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 0 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 1 ] ] ) ;
2004-08-22 22:29:09 +00:00
}
if ( neighbours [ t * 3 + 1 ] < 0 | | ! triangleFacing [ neighbours [ t * 3 + 1 ] ] )
{
2005-01-07 02:54:22 +00:00
qglVertex3fv ( verts [ indexes [ t * 3 + 2 ] ] ) ;
qglVertex3fv ( verts [ indexes [ t * 3 + 1 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 1 ] ] ) ;
qglVertex3fv ( verts [ indexes [ t * 3 + 2 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 1 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 2 ] ] ) ;
2004-08-22 22:29:09 +00:00
}
if ( neighbours [ t * 3 + 2 ] < 0 | | ! triangleFacing [ neighbours [ t * 3 + 2 ] ] )
{
2005-01-07 02:54:22 +00:00
qglVertex3fv ( verts [ indexes [ t * 3 + 0 ] ] ) ;
qglVertex3fv ( verts [ indexes [ t * 3 + 2 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 2 ] ] ) ;
qglVertex3fv ( verts [ indexes [ t * 3 + 0 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 2 ] ] ) ;
qglVertex3fv ( proj [ indexes [ t * 3 + 0 ] ] ) ;
2004-08-22 22:29:09 +00:00
}
}
}
2005-01-07 02:54:22 +00:00
qglEnd ( ) ;
2004-08-22 22:29:09 +00:00
}
2005-02-09 19:32:09 +00:00
void GL_DrawAliasMesh_Sketch ( mesh_t * mesh )
2004-12-11 03:45:47 +00:00
{
int i ;
extern int gldepthfunc ;
# ifdef Q3SHADERS
R_UnlockArrays ( ) ;
# endif
2005-01-07 02:54:22 +00:00
qglDepthFunc ( gldepthfunc ) ;
qglDepthMask ( 1 ) ;
2004-12-11 03:45:47 +00:00
if ( gldepthmin = = 0.5 )
qglCullFace ( GL_BACK ) ;
else
qglCullFace ( GL_FRONT ) ;
GL_TexEnv ( GL_MODULATE ) ;
2005-01-07 02:54:22 +00:00
qglDisable ( GL_TEXTURE_2D ) ;
2004-12-11 03:45:47 +00:00
2005-05-13 10:42:48 +00:00
qglVertexPointer ( 3 , GL_FLOAT , 0 , mesh - > xyz_array ) ;
2005-01-07 02:54:22 +00:00
qglEnableClientState ( GL_VERTEX_ARRAY ) ;
2004-12-11 03:45:47 +00:00
2005-01-07 02:54:22 +00:00
if ( mesh - > normals_array & & qglNormalPointer ) //d3d wrapper doesn't support normals, and this is only really needed for truform
2004-12-11 03:45:47 +00:00
{
2005-01-07 02:54:22 +00:00
qglNormalPointer ( GL_FLOAT , 0 , mesh - > normals_array ) ;
qglEnableClientState ( GL_NORMAL_ARRAY ) ;
2004-12-11 03:45:47 +00:00
}
if ( mesh - > colors_array )
{
2005-01-07 02:54:22 +00:00
qglColorPointer ( 4 , GL_UNSIGNED_BYTE , 0 , mesh - > colors_array ) ;
qglEnableClientState ( GL_COLOR_ARRAY ) ;
2004-12-11 03:45:47 +00:00
}
else
2005-01-07 02:54:22 +00:00
qglDisableClientState ( GL_COLOR_ARRAY ) ;
2004-12-11 03:45:47 +00:00
2005-01-07 02:54:22 +00:00
qglEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
qglTexCoordPointer ( 2 , GL_FLOAT , 0 , mesh - > st_array ) ;
2004-12-11 03:45:47 +00:00
2005-01-07 02:54:22 +00:00
qglDrawElements ( GL_TRIANGLES , mesh - > numindexes , GL_UNSIGNED_INT , mesh - > indexes ) ;
2004-12-11 03:45:47 +00:00
2005-01-07 02:54:22 +00:00
qglDisableClientState ( GL_VERTEX_ARRAY ) ;
qglDisableClientState ( GL_COLOR_ARRAY ) ;
qglDisableClientState ( GL_NORMAL_ARRAY ) ;
qglDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2004-12-11 03:45:47 +00:00
2005-01-07 02:54:22 +00:00
qglColor3f ( 0 , 0 , 0 ) ;
qglBegin ( GL_LINES ) ;
2004-12-11 03:45:47 +00:00
for ( i = 0 ; i < mesh - > numindexes ; i + = 3 )
{
float * v1 , * v2 , * v3 ;
int n ;
v1 = mesh - > xyz_array [ mesh - > indexes [ i + 0 ] ] ;
v2 = mesh - > xyz_array [ mesh - > indexes [ i + 1 ] ] ;
v3 = mesh - > xyz_array [ mesh - > indexes [ i + 2 ] ] ;
for ( n = 0 ; n < 3 ; n + + ) //rember we do this triangle AND the neighbours
{
2005-01-07 02:54:22 +00:00
qglVertex3f ( v1 [ 0 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
2004-12-11 03:45:47 +00:00
v1 [ 1 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
v1 [ 2 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ) ;
2005-01-07 02:54:22 +00:00
qglVertex3f ( v2 [ 0 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
2004-12-15 19:53:30 +00:00
v2 [ 1 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
v2 [ 2 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ) ;
2005-01-07 02:54:22 +00:00
qglVertex3f ( v2 [ 0 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
2004-12-11 03:45:47 +00:00
v2 [ 1 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
v2 [ 2 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ) ;
2005-01-07 02:54:22 +00:00
qglVertex3f ( v3 [ 0 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
2004-12-11 03:45:47 +00:00
v3 [ 1 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
v3 [ 2 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ) ;
2004-12-15 19:53:30 +00:00
2005-01-07 02:54:22 +00:00
qglVertex3f ( v3 [ 0 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
2004-12-15 19:53:30 +00:00
v3 [ 1 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
v3 [ 2 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ) ;
2005-01-07 02:54:22 +00:00
qglVertex3f ( v1 [ 0 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
2004-12-15 19:53:30 +00:00
v1 [ 1 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ,
v1 [ 2 ] + 0.5 * ( rand ( ) / ( float ) RAND_MAX - 0.5 ) ) ;
2004-12-11 03:45:47 +00:00
}
}
2005-01-07 02:54:22 +00:00
qglEnd ( ) ;
2004-12-11 03:45:47 +00:00
# ifdef Q3SHADERS
R_IBrokeTheArrays ( ) ;
# endif
}
2004-10-19 16:10:14 +00:00
void GL_DrawAliasMesh ( mesh_t * mesh , int texnum )
{
extern int gldepthfunc ;
# ifdef Q3SHADERS
R_UnlockArrays ( ) ;
# endif
2005-01-07 02:54:22 +00:00
qglDepthFunc ( gldepthfunc ) ;
qglDepthMask ( 1 ) ;
2005-04-26 16:04:12 +00:00
2004-10-19 16:10:14 +00:00
GL_Bind ( texnum ) ;
2004-12-09 23:45:14 +00:00
if ( gldepthmin = = 0.5 )
qglCullFace ( GL_BACK ) ;
else
qglCullFace ( GL_FRONT ) ;
2004-10-19 16:10:14 +00:00
2004-11-13 17:31:04 +00:00
GL_TexEnv ( GL_MODULATE ) ;
2005-05-13 10:42:48 +00:00
qglVertexPointer ( 3 , GL_FLOAT , 0 , mesh - > xyz_array ) ;
2005-01-07 02:54:22 +00:00
qglEnableClientState ( GL_VERTEX_ARRAY ) ;
2004-10-19 16:10:14 +00:00
2005-01-07 02:54:22 +00:00
if ( mesh - > normals_array & & qglNormalPointer ) //d3d wrapper doesn't support normals, and this is only really needed for truform
2004-10-19 16:10:14 +00:00
{
2005-01-07 02:54:22 +00:00
qglNormalPointer ( GL_FLOAT , 0 , mesh - > normals_array ) ;
qglEnableClientState ( GL_NORMAL_ARRAY ) ;
2004-10-19 16:10:14 +00:00
}
if ( mesh - > colors_array )
{
2005-01-07 02:54:22 +00:00
qglColorPointer ( 4 , GL_UNSIGNED_BYTE , 0 , mesh - > colors_array ) ;
qglEnableClientState ( GL_COLOR_ARRAY ) ;
2004-10-19 16:10:14 +00:00
}
2004-11-13 17:31:04 +00:00
else
2005-01-07 02:54:22 +00:00
qglDisableClientState ( GL_COLOR_ARRAY ) ;
2004-10-19 16:10:14 +00:00
2005-01-07 02:54:22 +00:00
qglEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
qglTexCoordPointer ( 2 , GL_FLOAT , 0 , mesh - > st_array ) ;
2004-10-19 16:10:14 +00:00
2005-01-07 02:54:22 +00:00
qglDrawElements ( GL_TRIANGLES , mesh - > numindexes , GL_UNSIGNED_INT , mesh - > indexes ) ;
2004-10-19 16:10:14 +00:00
2005-01-07 02:54:22 +00:00
qglDisableClientState ( GL_VERTEX_ARRAY ) ;
qglDisableClientState ( GL_COLOR_ARRAY ) ;
qglDisableClientState ( GL_NORMAL_ARRAY ) ;
qglDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2004-10-19 16:10:14 +00:00
# ifdef Q3SHADERS
R_IBrokeTheArrays ( ) ;
# endif
}
2004-08-22 22:29:09 +00:00
void R_DrawGAliasModel ( entity_t * e )
{
2004-12-11 03:45:47 +00:00
extern cvar_t r_drawflat ;
2004-11-27 08:16:25 +00:00
model_t * clmodel ;
2004-08-22 22:29:09 +00:00
vec3_t mins , maxs ;
vec3_t dist ;
vec_t add ;
int i ;
galiasinfo_t * inf ;
mesh_t mesh ;
galiastexnum_t * skin ;
float entScale ;
vec3_t lightdir ;
float tmatrix [ 3 ] [ 4 ] ;
2004-10-26 14:54:59 +00:00
currententity = e ;
2005-02-28 07:16:19 +00:00
// if (e->flags & Q2RF_VIEWERMODEL && e->keynum == cl.playernum[r_refdef.currentplayernum]+1)
// return;
2004-08-22 22:29:09 +00:00
2005-04-16 16:21:27 +00:00
if ( r_secondaryview & & e - > flags & Q2RF_WEAPONMODEL )
return ;
2004-11-27 08:16:25 +00:00
{
extern int cl_playerindex ;
if ( e - > scoreboard & & e - > model = = cl . model_precache [ cl_playerindex ] )
{
clmodel = e - > scoreboard - > model ;
if ( ! clmodel | | clmodel - > type ! = mod_alias )
clmodel = e - > model ;
}
else
clmodel = e - > model ;
}
2004-08-22 22:29:09 +00:00
VectorAdd ( e - > origin , clmodel - > mins , mins ) ;
VectorAdd ( e - > origin , clmodel - > maxs , maxs ) ;
2005-03-12 23:40:42 +00:00
if ( ! ( e - > flags & Q2RF_WEAPONMODEL ) )
if ( R_CullBox ( mins , maxs ) )
return ;
2004-08-22 22:29:09 +00:00
2005-04-18 17:12:18 +00:00
if ( ! ( r_refdef . flags & Q2RDF_NOWORLDMODEL ) )
2004-08-22 22:29:09 +00:00
{
2005-04-18 17:12:18 +00:00
if ( e - > flags & Q2RF_WEAPONMODEL )
cl . worldmodel - > funcs . LightPointValues ( r_refdef . vieworg , shadelight , ambientlight , lightdir ) ;
else
cl . worldmodel - > funcs . LightPointValues ( e - > origin , shadelight , ambientlight , lightdir ) ;
2004-08-22 22:29:09 +00:00
}
else
{
ambientlight [ 0 ] = ambientlight [ 1 ] = ambientlight [ 2 ] = shadelight [ 0 ] = shadelight [ 1 ] = shadelight [ 2 ] = 255 ;
lightdir [ 0 ] = 0 ;
lightdir [ 1 ] = 1 ;
lightdir [ 2 ] = 1 ;
}
2004-11-18 17:55:04 +00:00
if ( ! r_vertexdlights . value )
2004-08-22 22:29:09 +00:00
{
2004-09-07 23:09:15 +00:00
for ( i = 0 ; i < MAX_DLIGHTS ; i + + )
2004-08-22 22:29:09 +00:00
{
2004-11-27 08:16:25 +00:00
if ( cl_dlights [ i ] . radius )
2004-09-07 23:09:15 +00:00
{
VectorSubtract ( e - > origin ,
cl_dlights [ i ] . origin ,
dist ) ;
add = cl_dlights [ i ] . radius - Length ( dist ) ;
if ( add > 0 ) {
add * = 5 ;
ambientlight [ 0 ] + = add * cl_dlights [ i ] . color [ 0 ] ;
ambientlight [ 1 ] + = add * cl_dlights [ i ] . color [ 1 ] ;
ambientlight [ 2 ] + = add * cl_dlights [ i ] . color [ 2 ] ;
//ZOID models should be affected by dlights as well
shadelight [ 0 ] + = add * cl_dlights [ i ] . color [ 0 ] ;
shadelight [ 1 ] + = add * cl_dlights [ i ] . color [ 1 ] ;
shadelight [ 2 ] + = add * cl_dlights [ i ] . color [ 2 ] ;
}
2004-08-22 22:29:09 +00:00
}
}
}
2004-09-07 23:09:15 +00:00
else
{
}
2004-08-22 22:29:09 +00:00
for ( i = 0 ; i < 3 ; i + + ) //clamp light so it doesn't get vulgar.
{
if ( ambientlight [ i ] > 128 )
ambientlight [ i ] = 128 ;
if ( ambientlight [ i ] + shadelight [ i ] > 192 )
shadelight [ i ] = 192 - ambientlight [ i ] ;
}
if ( e - > flags & Q2RF_WEAPONMODEL )
{
for ( i = 0 ; i < 3 ; i + + )
{
if ( ambientlight [ i ] < 24 )
ambientlight [ i ] = shadelight [ i ] = 24 ;
}
}
//MORE HUGE HACKS! WHEN WILL THEY CEASE!
// clamp lighting so it doesn't overbright as much
// ZOID: never allow players to go totally black
if ( ! strcmp ( clmodel - > name , " progs/player.mdl " ) )
{
float fb = r_fullbrightSkins . value ;
if ( fb > cls . allow_fbskins )
fb = cls . allow_fbskins ;
if ( fb < 0 )
fb = 0 ;
if ( fb )
{
for ( i = 0 ; i < 3 ; i + + )
{
ambientlight [ i ] = max ( ambientlight [ i ] , 8 + fb * 120 ) ;
shadelight [ i ] = max ( shadelight [ i ] , 8 + fb * 120 ) ;
}
}
for ( i = 0 ; i < 3 ; i + + )
{
if ( ambientlight [ i ] < 8 )
ambientlight [ i ] = shadelight [ i ] = 8 ;
}
}
for ( i = 0 ; i < 3 ; i + + )
{
if ( ambientlight [ i ] > 128 )
ambientlight [ i ] = 128 ;
shadelight [ i ] / = 200.0 / 255 ;
ambientlight [ i ] / = 200.0 / 255 ;
}
if ( ( e - > drawflags & MLS_MASKIN ) = = MLS_ABSLIGHT )
{
shadelight [ 0 ] = shadelight [ 1 ] = shadelight [ 2 ] = e - > abslight ;
ambientlight [ 0 ] = ambientlight [ 1 ] = ambientlight [ 2 ] = 0 ;
}
//#define SHOWLIGHTDIR
{ //lightdir is absolute, shadevector is relative
2005-02-28 07:16:19 +00:00
shadevector [ 0 ] = DotProduct ( lightdir , e - > axis [ 0 ] ) ;
shadevector [ 1 ] = DotProduct ( lightdir , e - > axis [ 1 ] ) ;
shadevector [ 2 ] = DotProduct ( lightdir , e - > axis [ 2 ] ) ;
2004-08-22 22:29:09 +00:00
VectorNormalize ( shadevector ) ;
VectorCopy ( shadevector , mesh . lightaxis [ 2 ] ) ;
VectorVectors ( mesh . lightaxis [ 2 ] , mesh . lightaxis [ 1 ] , mesh . lightaxis [ 0 ] ) ;
2005-02-28 07:16:19 +00:00
VectorInverse ( mesh . lightaxis [ 1 ] ) ;
2004-08-22 22:29:09 +00:00
}
/*
an = e - > angles [ 1 ] / 180 * M_PI ;
shadevector [ 0 ] = cos ( - an ) ;
shadevector [ 1 ] = sin ( - an ) ;
shadevector [ 2 ] = 1 ;
VectorNormalize ( shadevector ) ;
*/
GL_DisableMultitexture ( ) ;
2004-11-13 17:31:04 +00:00
GL_TexEnv ( GL_MODULATE ) ;
2004-08-22 22:29:09 +00:00
if ( gl_smoothmodels . value )
2005-01-07 02:54:22 +00:00
qglShadeModel ( GL_SMOOTH ) ;
2004-08-22 22:29:09 +00:00
if ( gl_affinemodels . value )
2005-01-07 02:54:22 +00:00
qglHint ( GL_PERSPECTIVE_CORRECTION_HINT , GL_FASTEST ) ;
2004-08-22 22:29:09 +00:00
2005-01-07 02:54:22 +00:00
qglDisable ( GL_ALPHA_TEST ) ;
2004-08-22 22:29:09 +00:00
if ( e - > flags & Q2RF_DEPTHHACK )
2005-01-07 02:54:22 +00:00
qglDepthRange ( gldepthmin , gldepthmin + 0.3 * ( gldepthmax - gldepthmin ) ) ;
2004-08-22 22:29:09 +00:00
// glColor3f( 1,1,1);
if ( ( e - > model - > flags & EF_SPECIAL_TRANS ) ) //hexen2 flags.
{
2005-01-07 02:54:22 +00:00
qglEnable ( GL_BLEND ) ;
qglBlendFunc ( GL_ONE_MINUS_SRC_ALPHA , GL_SRC_ALPHA ) ;
2004-08-22 22:29:09 +00:00
// glColor3f( 1,1,1);
2005-01-07 02:54:22 +00:00
qglDisable ( GL_CULL_FACE ) ;
2004-08-22 22:29:09 +00:00
}
else if ( e - > drawflags & DRF_TRANSLUCENT )
{
2005-01-07 02:54:22 +00:00
qglEnable ( GL_BLEND ) ;
qglBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2004-08-22 22:29:09 +00:00
e - > alpha = r_wateralpha . value ;
2005-01-07 02:54:22 +00:00
// qglColor4f( 1,1,1,r_wateralpha.value);
2004-08-22 22:29:09 +00:00
}
else if ( ( e - > model - > flags & EF_TRANSPARENT ) )
{
2005-01-07 02:54:22 +00:00
qglEnable ( GL_BLEND ) ;
qglBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
// qglColor3f( 1,1,1);
2004-08-22 22:29:09 +00:00
}
else if ( ( e - > model - > flags & EF_HOLEY ) )
{
2005-01-07 02:54:22 +00:00
qglEnable ( GL_ALPHA_TEST ) ;
// qglEnable (GL_BLEND);
qglBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2004-08-22 22:29:09 +00:00
2005-01-07 02:54:22 +00:00
// qglColor3f( 1,1,1);
2004-08-22 22:29:09 +00:00
}
else if ( e - > alpha < 1 )
{
2005-01-07 02:54:22 +00:00
qglEnable ( GL_BLEND ) ;
qglBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2004-08-22 22:29:09 +00:00
}
else
{
2005-01-07 02:54:22 +00:00
qglDisable ( GL_BLEND ) ;
qglBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2004-08-22 22:29:09 +00:00
}
2005-01-07 02:54:22 +00:00
// qglEnable (GL_ALPHA_TEST);
2004-08-22 22:29:09 +00:00
2005-01-07 02:54:22 +00:00
qglPushMatrix ( ) ;
2004-08-22 22:29:09 +00:00
R_RotateForEntity ( e ) ;
if ( e - > scale ! = 1 & & e - > scale ! = 0 ) //hexen 2 stuff
{
vec3_t scale ;
vec3_t scale_origin ;
float xyfact , zfact ;
scale [ 0 ] = ( clmodel - > maxs [ 0 ] - clmodel - > mins [ 0 ] ) / 255 ;
scale [ 1 ] = ( clmodel - > maxs [ 1 ] - clmodel - > mins [ 1 ] ) / 255 ;
scale [ 2 ] = ( clmodel - > maxs [ 2 ] - clmodel - > mins [ 2 ] ) / 255 ;
scale_origin [ 0 ] = clmodel - > mins [ 0 ] ;
scale_origin [ 1 ] = clmodel - > mins [ 1 ] ;
scale_origin [ 2 ] = clmodel - > mins [ 2 ] ;
2005-01-07 02:54:22 +00:00
/* qglScalef( 1/scale[0],
2004-08-22 22:29:09 +00:00
1 / scale [ 1 ] ,
1 / scale [ 2 ] ) ;
2005-01-07 02:54:22 +00:00
qglTranslatef ( - scale_origin [ 0 ] ,
2004-08-22 22:29:09 +00:00
- scale_origin [ 1 ] ,
- scale_origin [ 2 ] ) ;
*/
if ( e - > scale ! = 0 & & e - > scale ! = 1 )
{
entScale = ( float ) e - > scale ;
switch ( e - > drawflags & SCALE_TYPE_MASKIN )
{
default :
case SCALE_TYPE_UNIFORM :
tmatrix [ 0 ] [ 0 ] = scale [ 0 ] * entScale ;
tmatrix [ 1 ] [ 1 ] = scale [ 1 ] * entScale ;
tmatrix [ 2 ] [ 2 ] = scale [ 2 ] * entScale ;
xyfact = zfact = ( entScale - 1.0 ) * 127.95 ;
break ;
case SCALE_TYPE_XYONLY :
tmatrix [ 0 ] [ 0 ] = scale [ 0 ] * entScale ;
tmatrix [ 1 ] [ 1 ] = scale [ 1 ] * entScale ;
tmatrix [ 2 ] [ 2 ] = scale [ 2 ] ;
xyfact = ( entScale - 1.0 ) * 127.95 ;
zfact = 1.0 ;
break ;
case SCALE_TYPE_ZONLY :
tmatrix [ 0 ] [ 0 ] = scale [ 0 ] ;
tmatrix [ 1 ] [ 1 ] = scale [ 1 ] ;
tmatrix [ 2 ] [ 2 ] = scale [ 2 ] * entScale ;
xyfact = 1.0 ;
zfact = ( entScale - 1.0 ) * 127.95 ;
break ;
}
switch ( currententity - > drawflags & SCALE_ORIGIN_MASKIN )
{
default :
case SCALE_ORIGIN_CENTER :
tmatrix [ 0 ] [ 3 ] = scale_origin [ 0 ] - scale [ 0 ] * xyfact ;
tmatrix [ 1 ] [ 3 ] = scale_origin [ 1 ] - scale [ 1 ] * xyfact ;
tmatrix [ 2 ] [ 3 ] = scale_origin [ 2 ] - scale [ 2 ] * zfact ;
break ;
case SCALE_ORIGIN_BOTTOM :
tmatrix [ 0 ] [ 3 ] = scale_origin [ 0 ] - scale [ 0 ] * xyfact ;
tmatrix [ 1 ] [ 3 ] = scale_origin [ 1 ] - scale [ 1 ] * xyfact ;
tmatrix [ 2 ] [ 3 ] = scale_origin [ 2 ] ;
break ;
case SCALE_ORIGIN_TOP :
tmatrix [ 0 ] [ 3 ] = scale_origin [ 0 ] - scale [ 0 ] * xyfact ;
tmatrix [ 1 ] [ 3 ] = scale_origin [ 1 ] - scale [ 1 ] * xyfact ;
tmatrix [ 2 ] [ 3 ] = scale_origin [ 2 ] - scale [ 2 ] * zfact * 2.0 ;
break ;
}
}
else
{
tmatrix [ 0 ] [ 0 ] = scale [ 0 ] ;
tmatrix [ 1 ] [ 1 ] = scale [ 1 ] ;
tmatrix [ 2 ] [ 2 ] = scale [ 2 ] ;
tmatrix [ 0 ] [ 3 ] = scale_origin [ 0 ] ;
tmatrix [ 1 ] [ 3 ] = scale_origin [ 1 ] ;
tmatrix [ 2 ] [ 3 ] = scale_origin [ 2 ] ;
}
/* if(clmodel->flags&EF_ROTATE)
{ // Floating motion
tmatrix [ 2 ] [ 3 ] + = sin ( currententity - > origin [ 0 ]
+ currententity - > origin [ 1 ] + ( cl . time * 3 ) ) * 5.5 ;
} */
2005-01-07 02:54:22 +00:00
qglTranslatef ( tmatrix [ 0 ] [ 3 ] , tmatrix [ 1 ] [ 3 ] , tmatrix [ 2 ] [ 3 ] ) ;
qglScalef ( tmatrix [ 0 ] [ 0 ] , tmatrix [ 1 ] [ 1 ] , tmatrix [ 2 ] [ 2 ] ) ;
2004-08-22 22:29:09 +00:00
2005-01-07 02:54:22 +00:00
qglScalef ( 1 / scale [ 0 ] ,
2004-08-22 22:29:09 +00:00
1 / scale [ 1 ] ,
1 / scale [ 2 ] ) ;
2005-01-07 02:54:22 +00:00
qglTranslatef ( - scale_origin [ 0 ] ,
2004-08-22 22:29:09 +00:00
- scale_origin [ 1 ] ,
- scale_origin [ 2 ] ) ;
}
inf = GLMod_Extradata ( clmodel ) ;
if ( qglPNTrianglesfATI & & gl_ati_truform . value )
2005-01-07 02:54:22 +00:00
qglEnable ( GL_PN_TRIANGLES_ATI ) ;
2004-08-22 22:29:09 +00:00
2004-11-13 17:31:04 +00:00
memset ( & mesh , 0 , sizeof ( mesh ) ) ;
2005-02-09 19:32:09 +00:00
for ( ; inf ; ( ( inf - > nextsurf ) ? ( inf = ( galiasinfo_t * ) ( ( char * ) inf + inf - > nextsurf ) ) : ( inf = NULL ) ) )
2004-08-22 22:29:09 +00:00
{
2005-04-18 17:12:18 +00:00
if ( R_GAliasBuildMesh ( & mesh , inf , e - > frame , e - > oldframe , e - > lerpfrac , e - > alpha ) & & r_vertexdlights . value )
2004-09-07 23:09:15 +00:00
R_GAliasAddDlights ( & mesh , e - > origin , e - > angles ) ;
2005-02-09 19:32:09 +00:00
2004-08-22 22:29:09 +00:00
c_alias_polys + = mesh . numindexes / 3 ;
2004-10-19 16:10:14 +00:00
2004-12-11 03:45:47 +00:00
if ( r_drawflat . value = = 2 )
2005-02-09 19:32:09 +00:00
{
GL_DrawAliasMesh_Sketch ( & mesh ) ;
continue ;
}
# ifdef Q3SHADERS
else if ( currententity - > forcedshader )
{
meshbuffer_t mb ;
R_IBrokeTheArrays ( ) ;
mb . entity = & r_worldentity ;
mb . shader = currententity - > forcedshader ;
mb . fog = NULL ;
mb . mesh = & mesh ;
mb . infokey = currententity - > keynum ;
mb . dlightbits = 0 ;
R_PushMesh ( & mesh , mb . shader - > features | MF_NONBATCHED | MF_COLORS ) ;
R_RenderMeshBuffer ( & mb , false ) ;
continue ;
}
# endif
skin = GL_ChooseSkin ( inf , clmodel - > name , e ) ;
if ( ! skin )
2004-10-19 16:10:14 +00:00
{
2005-01-07 02:54:22 +00:00
qglEnable ( GL_TEXTURE_2D ) ;
2005-02-09 19:32:09 +00:00
GL_DrawAliasMesh_Sketch ( & mesh ) ;
2004-10-19 16:10:14 +00:00
}
# ifdef Q3SHADERS
else if ( skin - > shader )
{
meshbuffer_t mb ;
mb . entity = & r_worldentity ;
mb . shader = skin - > shader ;
mb . fog = NULL ;
mb . mesh = & mesh ;
mb . infokey = currententity - > keynum ;
mb . dlightbits = 0 ;
R_IBrokeTheArrays ( ) ;
2004-11-13 17:31:04 +00:00
R_PushMesh ( & mesh , skin - > shader - > features | MF_NONBATCHED | MF_COLORS ) ;
2004-10-19 16:10:14 +00:00
R_RenderMeshBuffer ( & mb , false ) ;
}
# endif
2004-08-22 22:29:09 +00:00
else
{
2005-01-07 02:54:22 +00:00
qglEnable ( GL_TEXTURE_2D ) ;
2004-10-19 16:10:14 +00:00
// if (skin->bump)
// GL_DrawMeshBump(&mesh, skin->base, 0, skin->bump, 0);
// else
GL_DrawAliasMesh ( & mesh , skin - > base ) ;
2004-08-22 22:29:09 +00:00
if ( skin - > fullbright & & r_fb_models . value & & cls . allow_luma )
{
mesh . colors_array = NULL ;
2005-01-07 02:54:22 +00:00
qglEnable ( GL_BLEND ) ;
qglColor4f ( 1 , 1 , 1 , e - > alpha * r_fb_models . value ) ;
2004-08-22 22:29:09 +00:00
c_alias_polys + = mesh . numindexes / 3 ;
2004-10-19 16:10:14 +00:00
GL_DrawAliasMesh ( & mesh , skin - > fullbright ) ;
2004-08-22 22:29:09 +00:00
}
}
}
if ( qglPNTrianglesfATI & & gl_ati_truform . value )
2005-01-07 02:54:22 +00:00
qglDisable ( GL_PN_TRIANGLES_ATI ) ;
2004-08-22 22:29:09 +00:00
# ifdef SHOWLIGHTDIR //testing
2005-01-07 02:54:22 +00:00
qglDisable ( GL_TEXTURE_2D ) ;
qglBegin ( GL_LINES ) ;
qglColor3f ( 1 , 0 , 0 ) ;
qglVertex3f ( 0 ,
2004-08-22 22:29:09 +00:00
0 ,
0 ) ;
2005-01-07 02:54:22 +00:00
qglVertex3f ( 100 * mesh . lightaxis [ 0 ] [ 0 ] ,
2004-08-22 22:29:09 +00:00
100 * mesh . lightaxis [ 0 ] [ 1 ] ,
100 * mesh . lightaxis [ 0 ] [ 2 ] ) ;
2005-01-07 02:54:22 +00:00
qglColor3f ( 0 , 1 , 0 ) ;
qglVertex3f ( 0 ,
2004-08-22 22:29:09 +00:00
0 ,
0 ) ;
2005-01-07 02:54:22 +00:00
qglVertex3f ( 100 * mesh . lightaxis [ 1 ] [ 0 ] ,
2004-08-22 22:29:09 +00:00
100 * mesh . lightaxis [ 1 ] [ 1 ] ,
100 * mesh . lightaxis [ 1 ] [ 2 ] ) ;
2005-01-07 02:54:22 +00:00
qglColor3f ( 0 , 0 , 1 ) ;
qglVertex3f ( 0 ,
2004-08-22 22:29:09 +00:00
0 ,
0 ) ;
2005-01-07 02:54:22 +00:00
qglVertex3f ( 100 * mesh . lightaxis [ 2 ] [ 0 ] ,
2004-08-22 22:29:09 +00:00
100 * mesh . lightaxis [ 2 ] [ 1 ] ,
100 * mesh . lightaxis [ 2 ] [ 2 ] ) ;
2005-01-07 02:54:22 +00:00
qglEnd ( ) ;
qglEnable ( GL_TEXTURE_2D ) ;
2004-08-22 22:29:09 +00:00
# endif
2005-01-07 02:54:22 +00:00
qglPopMatrix ( ) ;
2004-08-22 22:29:09 +00:00
2005-01-07 02:54:22 +00:00
qglDisable ( GL_BLEND ) ;
2004-08-22 22:29:09 +00:00
2005-01-07 02:54:22 +00:00
qglBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2004-11-13 17:31:04 +00:00
GL_TexEnv ( GL_REPLACE ) ;
2004-08-22 22:29:09 +00:00
2005-01-07 02:54:22 +00:00
qglEnable ( GL_TEXTURE_2D ) ;
2004-08-22 22:29:09 +00:00
2005-01-07 02:54:22 +00:00
qglShadeModel ( GL_FLAT ) ;
2004-08-22 22:29:09 +00:00
if ( gl_affinemodels . value )
2005-01-07 02:54:22 +00:00
qglHint ( GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST ) ;
2004-08-22 22:29:09 +00:00
if ( e - > flags & Q2RF_DEPTHHACK )
2005-01-07 02:54:22 +00:00
qglDepthRange ( gldepthmin , gldepthmax ) ;
2004-08-22 22:29:09 +00:00
if ( ( currententity - > model - > flags & EF_SPECIAL_TRANS ) & & gl_cull . value )
2005-01-07 02:54:22 +00:00
qglEnable ( GL_CULL_FACE ) ;
2004-08-22 22:29:09 +00:00
if ( ( currententity - > model - > flags & EF_HOLEY ) )
2005-01-07 02:54:22 +00:00
qglDisable ( GL_ALPHA_TEST ) ;
2004-08-22 22:29:09 +00:00
# ifdef SHOWLIGHTDIR //testing
2005-01-07 02:54:22 +00:00
qglDisable ( GL_TEXTURE_2D ) ;
qglColor3f ( 1 , 1 , 1 ) ;
qglBegin ( GL_LINES ) ;
qglVertex3f ( currententity - > origin [ 0 ] ,
2004-08-22 22:29:09 +00:00
currententity - > origin [ 1 ] ,
currententity - > origin [ 2 ] ) ;
2005-01-07 02:54:22 +00:00
qglVertex3f ( currententity - > origin [ 0 ] + 100 * lightdir [ 0 ] ,
2004-08-22 22:29:09 +00:00
currententity - > origin [ 1 ] + 100 * lightdir [ 1 ] ,
currententity - > origin [ 2 ] + 100 * lightdir [ 2 ] ) ;
2005-01-07 02:54:22 +00:00
qglEnd ( ) ;
qglEnable ( GL_TEXTURE_2D ) ;
2004-08-22 22:29:09 +00:00
# endif
}
2004-12-09 23:45:14 +00:00
//returns result in the form of the result vector
void RotateLightVector ( vec3_t angles , vec3_t origin , vec3_t lightpoint , vec3_t result )
2004-08-22 22:29:09 +00:00
{
2004-12-09 23:45:14 +00:00
vec3_t f , r , u , offs ;
angles [ 0 ] * = - 1 ;
AngleVectors ( angles , f , r , u ) ;
angles [ 0 ] * = - 1 ;
offs [ 0 ] = lightpoint [ 0 ] - origin [ 0 ] ;
offs [ 1 ] = lightpoint [ 1 ] - origin [ 1 ] ;
offs [ 2 ] = lightpoint [ 2 ] - origin [ 2 ] ;
result [ 0 ] = DotProduct ( offs , f ) ;
result [ 1 ] = - DotProduct ( offs , r ) ;
result [ 2 ] = DotProduct ( offs , u ) ;
}
void GL_LightMesh ( mesh_t * mesh , vec3_t lightpos , vec3_t colours , float radius )
{
vec3_t dir ;
int i ;
float dot ;
2005-05-13 10:42:48 +00:00
vec3_t * xyz = mesh - > xyz_array ;
2004-12-09 23:45:14 +00:00
vec3_t * normals = mesh - > normals_array ;
byte_vec4_t * out = mesh - > colors_array ;
if ( normals )
{
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
VectorSubtract ( lightpos , xyz [ i ] , dir ) ;
dot = DotProduct ( dir , normals [ i ] ) ;
out [ i ] [ 0 ] = colours [ 0 ] * dot ;
out [ i ] [ 1 ] = colours [ 1 ] * dot ;
out [ i ] [ 2 ] = colours [ 2 ] * dot ;
out [ i ] [ 3 ] = 255 ;
}
}
else
{
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
{
VectorSubtract ( lightpos , xyz [ i ] , dir ) ;
out [ i ] [ 0 ] = colours [ 0 ] ;
out [ i ] [ 1 ] = colours [ 1 ] ;
out [ i ] [ 2 ] = colours [ 2 ] ;
out [ i ] [ 3 ] = 255 ;
}
}
}
void R_DrawGAliasModelLighting ( entity_t * e , vec3_t lightpos , vec3_t colours , float radius )
{
return ; //not ready yet
#if 0
2004-08-22 22:29:09 +00:00
model_t * clmodel = e - > model ;
vec3_t mins , maxs ;
vec3_t lightdir ;
galiasinfo_t * inf ;
mesh_t mesh ;
if ( e - > flags & Q2RF_VIEWERMODEL )
return ;
//Total insanity with r_shadows 2...
// if (!strcmp (clmodel->name, "progs/flame2.mdl"))
// CL_NewDlight (e, e->origin[0]-1, e->origin[1]+1, e->origin[2]+24, 200 + (rand()&31), host_frametime*2, 3);
// if (!strcmp (clmodel->name, "progs/armor.mdl"))
// CL_NewDlight (e->keynum, e->origin[0]-1, e->origin[1]+1, e->origin[2]+25, 200 + (rand()&31), host_frametime*2, 3);
VectorAdd ( e - > origin , clmodel - > mins , mins ) ;
VectorAdd ( e - > origin , clmodel - > maxs , maxs ) ;
if ( ! ( e - > flags & Q2RF_WEAPONMODEL ) )
if ( R_CullBox ( mins , maxs ) )
return ;
2004-12-09 23:45:14 +00:00
RotateLightVector ( e - > angles , e - > origin , lightpos , lightdir ) ;
2004-08-22 22:29:09 +00:00
GL_DisableMultitexture ( ) ;
2004-11-13 17:31:04 +00:00
GL_TexEnv ( GL_MODULATE ) ;
2004-08-22 22:29:09 +00:00
if ( gl_smoothmodels . value )
glShadeModel ( GL_SMOOTH ) ;
if ( gl_affinemodels . value )
glHint ( GL_PERSPECTIVE_CORRECTION_HINT , GL_FASTEST ) ;
if ( e - > flags & Q2RF_DEPTHHACK )
glDepthRange ( gldepthmin , gldepthmin + 0.3 * ( gldepthmax - gldepthmin ) ) ;
2004-12-09 23:45:14 +00:00
glColor3f ( colours [ 0 ] , colours [ 1 ] , colours [ 2 ] ) ;
2004-08-22 22:29:09 +00:00
glPushMatrix ( ) ;
R_RotateForEntity ( e ) ;
inf = GLMod_Extradata ( clmodel ) ;
if ( gl_ati_truform . value )
glEnable ( GL_PN_TRIANGLES_ATI ) ;
while ( inf )
{
R_GAliasBuildMesh ( & mesh , inf , e - > frame , e - > oldframe , e - > lerptime , e - > alpha ) ;
2004-12-09 23:45:14 +00:00
GL_LightMesh ( & mesh , lightdir , colours , radius ) ;
GL_DrawAliasMesh ( & mesh , 0 ) ;
2004-08-22 22:29:09 +00:00
if ( inf - > nextsurf )
2004-09-20 23:25:38 +00:00
inf = ( galiasinfo_t * ) ( ( char * ) inf + inf - > nextsurf ) ;
2004-08-22 22:29:09 +00:00
else
inf = NULL ;
}
glPopMatrix ( ) ;
if ( gl_ati_truform . value )
glDisable ( GL_PN_TRIANGLES_ATI ) ;
2004-11-13 17:31:04 +00:00
GL_TexEnv ( GL_REPLACE ) ;
2004-08-22 22:29:09 +00:00
glShadeModel ( GL_FLAT ) ;
if ( gl_affinemodels . value )
glHint ( GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST ) ;
if ( e - > flags & Q2RF_DEPTHHACK )
glDepthRange ( gldepthmin , gldepthmax ) ;
2004-12-09 23:45:14 +00:00
# endif
2004-08-22 22:29:09 +00:00
}
//FIXME: Be less agressive.
//This function will have to be called twice (for geforce cards), with the same data, so do the building once and rendering twice.
void R_DrawGAliasShadowVolume ( entity_t * e , vec3_t lightpos , float radius )
{
model_t * clmodel = e - > model ;
galiasinfo_t * inf ;
mesh_t mesh ;
vec3_t lightorg ;
if ( ! strcmp ( clmodel - > name , " progs/flame2.mdl " ) )
return ;
if ( ! strncmp ( clmodel - > name , " progs/bolt " , 10 ) )
return ;
if ( r_noaliasshadows . value )
return ;
RotateLightVector ( e - > angles , e - > origin , lightpos , lightorg ) ;
if ( Length ( lightorg ) > radius + clmodel - > radius )
return ;
2005-01-07 02:54:22 +00:00
qglPushMatrix ( ) ;
2004-08-22 22:29:09 +00:00
R_RotateForEntity ( e ) ;
inf = GLMod_Extradata ( clmodel ) ;
while ( inf )
{
if ( inf - > ofs_trineighbours )
{
2005-04-18 17:12:18 +00:00
R_GAliasBuildMesh ( & mesh , inf , e - > frame , e - > oldframe , e - > lerpfrac , e - > alpha ) ;
2004-08-22 22:29:09 +00:00
R_CalcFacing ( & mesh , lightorg ) ;
R_ProjectShadowVolume ( & mesh , lightorg ) ;
R_DrawShadowVolume ( & mesh ) ;
}
if ( inf - > nextsurf )
2004-09-20 23:25:38 +00:00
inf = ( galiasinfo_t * ) ( ( char * ) inf + inf - > nextsurf ) ;
2004-08-22 22:29:09 +00:00
else
inf = NULL ;
}
2005-01-07 02:54:22 +00:00
qglPopMatrix ( ) ;
2004-08-22 22:29:09 +00:00
}
static int R_FindTriangleWithEdge ( int * indexes , int numtris , int start , int end , int ignore )
{
int i ;
int match , count ;
count = 0 ;
match = - 1 ;
for ( i = 0 ; i < numtris ; i + + , indexes + = 3 )
{
if ( ( indexes [ 0 ] = = start & & indexes [ 1 ] = = end )
| | ( indexes [ 1 ] = = start & & indexes [ 2 ] = = end )
| | ( indexes [ 2 ] = = start & & indexes [ 0 ] = = end ) ) {
if ( i ! = ignore )
match = i ;
count + + ;
} else if ( ( indexes [ 1 ] = = start & & indexes [ 0 ] = = end )
| | ( indexes [ 2 ] = = start & & indexes [ 1 ] = = end )
| | ( indexes [ 0 ] = = start & & indexes [ 2 ] = = end ) ) {
count + + ;
}
}
// detect edges shared by three triangles and make them seams
if ( count > 2 )
match = - 1 ;
return match ;
}
static void R_BuildTriangleNeighbours ( int * neighbours , int * indexes , int numtris )
{
int i , * n ;
int * index ;
for ( i = 0 , index = indexes , n = neighbours ; i < numtris ; i + + , index + = 3 , n + = 3 )
{
n [ 0 ] = R_FindTriangleWithEdge ( indexes , numtris , index [ 1 ] , index [ 0 ] , i ) ;
n [ 1 ] = R_FindTriangleWithEdge ( indexes , numtris , index [ 2 ] , index [ 1 ] , i ) ;
n [ 2 ] = R_FindTriangleWithEdge ( indexes , numtris , index [ 0 ] , index [ 2 ] , i ) ;
}
}
void GL_GenerateNormals ( float * orgs , float * normals , int * indicies , int numtris , int numverts )
{
vec3_t d1 , d2 ;
vec3_t norm ;
int t , i , v1 , v2 , v3 ;
int tricounts [ MD2MAX_VERTS ] ;
vec3_t combined [ MD2MAX_VERTS ] ;
int triremap [ MD2MAX_VERTS ] ;
if ( numverts > MD2MAX_VERTS )
return ; //not an issue, you just loose the normals.
memset ( triremap , 0 , numverts * sizeof ( triremap [ 0 ] ) ) ;
v2 = 0 ;
for ( i = 0 ; i < numverts ; i + + ) //weld points
{
for ( v1 = 0 ; v1 < v2 ; v1 + + )
{
if ( orgs [ i * 3 + 0 ] = = combined [ v1 ] [ 0 ] & &
orgs [ i * 3 + 1 ] = = combined [ v1 ] [ 1 ] & &
orgs [ i * 3 + 2 ] = = combined [ v1 ] [ 2 ] )
{
triremap [ i ] = v1 ;
break ;
}
}
if ( v1 = = v2 )
{
combined [ v1 ] [ 0 ] = orgs [ i * 3 + 0 ] ;
combined [ v1 ] [ 1 ] = orgs [ i * 3 + 1 ] ;
combined [ v1 ] [ 2 ] = orgs [ i * 3 + 2 ] ;
v2 + + ;
triremap [ i ] = v1 ;
}
}
memset ( tricounts , 0 , v2 * sizeof ( tricounts [ 0 ] ) ) ;
memset ( combined , 0 , v2 * sizeof ( * combined ) ) ;
for ( t = 0 ; t < numtris ; t + + )
{
v1 = triremap [ indicies [ t * 3 ] ] ;
v2 = triremap [ indicies [ t * 3 + 1 ] ] ;
v3 = triremap [ indicies [ t * 3 + 2 ] ] ;
VectorSubtract ( ( orgs + v2 * 3 ) , ( orgs + v1 * 3 ) , d1 ) ;
VectorSubtract ( ( orgs + v3 * 3 ) , ( orgs + v1 * 3 ) , d2 ) ;
CrossProduct ( d1 , d2 , norm ) ;
VectorNormalize ( norm ) ;
VectorAdd ( norm , combined [ v1 ] , combined [ v1 ] ) ;
VectorAdd ( norm , combined [ v2 ] , combined [ v2 ] ) ;
VectorAdd ( norm , combined [ v3 ] , combined [ v3 ] ) ;
tricounts [ v1 ] + + ;
tricounts [ v2 ] + + ;
tricounts [ v3 ] + + ;
}
for ( i = 0 ; i < numverts ; i + + )
{
if ( tricounts [ triremap [ i ] ] )
{
VectorScale ( combined [ triremap [ i ] ] , 1.0f / tricounts [ triremap [ i ] ] , normals + i * 3 ) ;
}
}
}
2005-05-15 18:49:04 +00:00
int skinfilecount ;
int GL_BuildSkinFileList ( char * modelname )
{
char skinfilename [ MAX_QPATH ] ;
for ( skinfilecount = 0 ; ; skinfilecount + + )
{
_snprintf ( skinfilename , sizeof ( skinfilename ) - 1 , " %s_%i.skin " , modelname , skinfilecount ) ;
if ( ! COM_FCheckExists ( skinfilename ) )
break ;
}
return skinfilecount ;
}
//This is a hack. It uses an assuption about q3 player models.
void GL_ParseQ3SkinFile ( char * out , char * surfname , char * modelname )
{
const char * f , * p ;
char line [ 256 ] ;
COM_StripExtension ( modelname , line ) ;
strcat ( line , " _default.skin " ) ;
f = COM_LoadTempFile2 ( line ) ;
while ( f )
{
f = COM_ParseToken ( f ) ;
if ( ! f )
return ;
while ( * f = = ' ' | | * f = = ' \t ' )
f + + ;
if ( * f = = ' , ' )
{
if ( ! strcmp ( com_token , surfname ) )
{
f + + ;
COM_ParseToken ( f ) ;
strcpy ( out , com_token ) ;
return ;
}
}
p = strchr ( f , ' \n ' ) ;
if ( ! p )
f = f + strlen ( f ) ;
else
f = p + 1 ;
if ( ! * f )
break ;
}
}
galiasskin_t * GL_LoadSkinFile ( int * count , char * shadername , int skinnumber , unsigned char * rawdata , int width , int height , unsigned char * palette )
{
galiasskin_t * skin ;
galiastexnum_t * texnums ;
skin = Hunk_Alloc ( sizeof ( * skin ) + sizeof ( * texnums ) ) ;
texnums = ( galiastexnum_t * ) ( skin + 1 ) ; //texnums is seperate for skingroups/animating skins... Which this format doesn't support.
* count = 1 ;
skin - > ofstexnums = ( char * ) texnums - ( char * ) skin ;
skin - > texnums = 1 ;
texnums - > base = Mod_LoadHiResTexture ( shadername , " models " , true , true , true ) ;
return skin ;
}
2004-08-22 22:29:09 +00:00
//Q1 model loading
# if 1
static galiasinfo_t * galias ;
static model_t * loadmodel ;
static dmdl_t * pq1inmodel ;
# define NUMVERTEXNORMALS 162
extern float r_avertexnormals [ NUMVERTEXNORMALS ] [ 3 ] ;
static void * Q1_LoadFrameGroup ( daliasframetype_t * pframetype , int * seamremaps )
{
galiaspose_t * pose ;
galiasgroup_t * frame ;
dtrivertx_t * pinframe ;
int i , j , k ;
daliasgroup_t * ingroup ;
daliasinterval_t * intervals ;
vec3_t * normals ;
vec3_t * verts ;
2004-09-13 04:16:52 +00:00
frame = ( galiasgroup_t * ) ( ( char * ) galias + galias - > groupofs ) ;
2004-08-22 22:29:09 +00:00
for ( i = 0 ; i < pq1inmodel - > numframes ; i + + )
{
switch ( LittleLong ( pframetype - > type ) )
{
case ALIAS_SINGLE :
2004-09-13 04:16:52 +00:00
pinframe = ( dtrivertx_t * ) ( ( char * ) ( pframetype + 1 ) + sizeof ( daliasframe_t ) ) ;
2004-08-22 22:29:09 +00:00
pose = ( galiaspose_t * ) Hunk_Alloc ( sizeof ( galiaspose_t ) + sizeof ( vec3_t ) * 2 * galias - > numverts ) ;
frame - > poseofs = ( char * ) pose - ( char * ) frame ;
frame - > numposes = 1 ;
galias - > groups + + ;
verts = ( vec3_t * ) ( pose + 1 ) ;
normals = & verts [ galias - > numverts ] ;
pose - > ofsverts = ( char * ) verts - ( char * ) pose ;
pose - > ofsnormals = ( char * ) normals - ( char * ) pose ;
for ( j = 0 ; j < pq1inmodel - > numverts ; j + + )
{
verts [ j ] [ 0 ] = pinframe [ j ] . v [ 0 ] * pq1inmodel - > scale [ 0 ] + pq1inmodel - > scale_origin [ 0 ] ;
verts [ j ] [ 1 ] = pinframe [ j ] . v [ 1 ] * pq1inmodel - > scale [ 1 ] + pq1inmodel - > scale_origin [ 1 ] ;
verts [ j ] [ 2 ] = pinframe [ j ] . v [ 2 ] * pq1inmodel - > scale [ 2 ] + pq1inmodel - > scale_origin [ 2 ] ;
VectorCopy ( r_avertexnormals [ pinframe [ j ] . lightnormalindex ] , normals [ j ] ) ;
if ( seamremaps [ j ] ! = j )
{
VectorCopy ( verts [ j ] , verts [ seamremaps [ j ] ] ) ;
VectorCopy ( normals [ j ] , normals [ seamremaps [ j ] ] ) ;
}
}
// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts);
2004-09-13 04:16:52 +00:00
pframetype = ( daliasframetype_t * ) & pinframe [ pq1inmodel - > numverts ] ;
2004-08-22 22:29:09 +00:00
break ;
2005-05-13 10:42:48 +00:00
2004-08-22 22:29:09 +00:00
case ALIAS_GROUP :
2005-05-08 03:41:24 +00:00
case ALIAS_GROUP_SWAPPED : // prerelease
2004-09-13 04:16:52 +00:00
ingroup = ( daliasgroup_t * ) ( pframetype + 1 ) ;
2004-08-22 22:29:09 +00:00
2005-04-19 21:09:29 +00:00
pose = ( galiaspose_t * ) Hunk_Alloc ( LittleLong ( ingroup - > numframes ) * ( sizeof ( galiaspose_t ) + sizeof ( vec3_t ) * 2 * galias - > numverts ) ) ;
2004-08-22 22:29:09 +00:00
frame - > poseofs = ( char * ) pose - ( char * ) frame ;
frame - > numposes = LittleLong ( ingroup - > numframes ) ;
galias - > groups + + ;
verts = ( vec3_t * ) ( pose + frame - > numposes ) ;
normals = & verts [ galias - > numverts ] ;
intervals = ( daliasinterval_t * ) ( ingroup + 1 ) ;
frame - > rate = 1 / LittleFloat ( intervals - > interval ) ;
pinframe = ( dtrivertx_t * ) ( intervals + frame - > numposes ) ;
for ( k = 0 ; k < frame - > numposes ; k + + )
{
pose - > ofsverts = ( char * ) verts - ( char * ) pose ;
pose - > ofsnormals = ( char * ) normals - ( char * ) pose ;
pinframe = ( dtrivertx_t * ) ( ( char * ) pinframe + sizeof ( daliasframe_t ) ) ;
for ( j = 0 ; j < pq1inmodel - > numverts ; j + + )
{
verts [ j ] [ 0 ] = pinframe [ j ] . v [ 0 ] * pq1inmodel - > scale [ 0 ] + pq1inmodel - > scale_origin [ 0 ] ;
verts [ j ] [ 1 ] = pinframe [ j ] . v [ 1 ] * pq1inmodel - > scale [ 1 ] + pq1inmodel - > scale_origin [ 1 ] ;
verts [ j ] [ 2 ] = pinframe [ j ] . v [ 2 ] * pq1inmodel - > scale [ 2 ] + pq1inmodel - > scale_origin [ 2 ] ;
VectorCopy ( r_avertexnormals [ pinframe [ j ] . lightnormalindex ] , normals [ j ] ) ;
if ( seamremaps [ j ] ! = j )
{
VectorCopy ( verts [ j ] , verts [ seamremaps [ j ] ] ) ;
VectorCopy ( normals [ j ] , normals [ seamremaps [ j ] ] ) ;
}
}
verts = & normals [ galias - > numverts ] ;
normals = & verts [ galias - > numverts ] ;
pose + + ;
pinframe + = pq1inmodel - > numverts ;
}
// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts);
2004-09-13 04:16:52 +00:00
pframetype = ( daliasframetype_t * ) pinframe ;
2004-08-22 22:29:09 +00:00
break ;
default :
Sys_Error ( " Bad frame type \n " ) ;
}
frame + + ;
}
return pframetype ;
}
static void * Q1_LoadSkins ( daliasskintype_t * pskintype , qboolean alpha )
{
extern int gl_bumpmappingpossible ;
galiastexnum_t * texnums ;
char skinname [ MAX_QPATH ] ;
int i ;
int s , t ;
int * count ;
float * intervals ;
qbyte * data , * saved ;
galiasskin_t * outskin = ( galiasskin_t * ) ( ( char * ) galias + galias - > ofsskins ) ;
int texture ;
int fbtexture ;
s = pq1inmodel - > skinwidth * pq1inmodel - > skinheight ;
for ( i = 0 ; i < pq1inmodel - > numskins ; i + + )
{
switch ( LittleLong ( pskintype - > type ) )
{
case ALIAS_SKIN_SINGLE :
outskin - > skinwidth = pq1inmodel - > skinwidth ;
outskin - > skinheight = pq1inmodel - > skinheight ;
2005-04-26 16:04:12 +00:00
//LH's naming scheme ("models" is likly to be ignored)
2005-05-13 10:42:48 +00:00
fbtexture = 0 ;
2005-04-26 16:04:12 +00:00
_snprintf ( skinname , sizeof ( skinname ) , " %s_%i " , loadmodel - > name , i ) ;
texture = Mod_LoadReplacementTexture ( skinname , " models " , true , false , true ) ;
if ( texture )
2004-08-22 22:29:09 +00:00
{
2005-04-26 16:04:12 +00:00
_snprintf ( skinname , sizeof ( skinname ) , " %s_%i_luma " , loadmodel - > name , i ) ;
texture = Mod_LoadReplacementTexture ( skinname , " models " , true , false , true ) ;
}
else
{
sprintf ( skinname , " %s_%i " , loadname , i ) ;
texture = Mod_LoadReplacementTexture ( skinname , " models " , true , false , true ) ;
2004-08-22 22:29:09 +00:00
if ( texture & & r_fb_models . value )
{
2005-04-26 16:04:12 +00:00
sprintf ( skinname , " %s_%i_luma " , loadname , i ) ;
fbtexture = Mod_LoadReplacementTexture ( skinname , " models " , true , true , true ) ;
2004-08-22 22:29:09 +00:00
}
}
if ( ! texture )
{
texnums = Hunk_Alloc ( sizeof ( * texnums ) + s ) ;
saved = ( qbyte * ) ( texnums + 1 ) ;
outskin - > ofstexels = ( qbyte * ) ( saved ) - ( qbyte * ) outskin ;
memcpy ( saved , pskintype + 1 , s ) ;
GLMod_FloodFillSkin ( saved , outskin - > skinwidth , outskin - > skinheight ) ;
sprintf ( skinname , " %s_%i " , loadname , i ) ;
texture = GL_LoadTexture ( skinname , outskin - > skinwidth , outskin - > skinheight , saved , true , alpha ) ;
if ( r_fb_models . value )
{
sprintf ( skinname , " %s_%i_luma " , loadname , i ) ;
fbtexture = GL_LoadTextureFB ( skinname , outskin - > skinwidth , outskin - > skinheight , saved , true , true ) ;
}
}
else
{
texnums = Hunk_Alloc ( sizeof ( * texnums ) ) ;
outskin - > ofstexels = 0 ;
}
outskin - > texnums = 1 ;
outskin - > ofstexnums = ( char * ) texnums - ( char * ) outskin ;
texnums - > base = texture ;
texnums - > fullbright = fbtexture ;
2004-09-13 04:16:52 +00:00
pskintype = ( daliasskintype_t * ) ( ( char * ) ( pskintype + 1 ) + s ) ;
2004-08-22 22:29:09 +00:00
break ;
default :
outskin - > skinwidth = pq1inmodel - > skinwidth ;
outskin - > skinheight = pq1inmodel - > skinheight ;
count = ( int * ) ( pskintype + 1 ) ;
intervals = ( float * ) ( count + 1 ) ;
outskin - > texnums = LittleLong ( * count ) ;
data = ( qbyte * ) ( intervals + outskin - > texnums ) ;
texnums = Hunk_Alloc ( sizeof ( * texnums ) * outskin - > texnums ) ;
outskin - > ofstexnums = ( char * ) texnums - ( char * ) outskin ;
outskin - > ofstexels = 0 ;
for ( t = 0 ; t < outskin - > texnums ; t + + , data + = s , texnums + + )
{
2005-04-26 16:04:12 +00:00
texture = 0 ;
fbtexture = 0 ;
//LH naming scheme
if ( ! texture )
2004-08-22 22:29:09 +00:00
{
2005-04-26 16:04:12 +00:00
sprintf ( skinname , " %s_%i_%i " , loadmodel - > name , i , t ) ;
texture = Mod_LoadReplacementTexture ( skinname , " models " , true , false , true ) ;
2004-08-22 22:29:09 +00:00
}
2005-04-26 16:04:12 +00:00
if ( ! fbtexture & & r_fb_models . value )
{
sprintf ( skinname , " %s_%i_%i_luma " , loadmodel - > name , i , t ) ;
fbtexture = Mod_LoadReplacementTexture ( skinname , " models " , true , true , true ) ;
}
//Fuhquake naming scheme
if ( ! texture )
{
sprintf ( skinname , " %s_%i_%i " , loadname , i , t ) ;
texture = Mod_LoadReplacementTexture ( skinname , " models " , true , false , true ) ;
}
if ( ! fbtexture & & r_fb_models . value )
{
sprintf ( skinname , " %s_%i_%i_luma " , loadname , i , t ) ;
fbtexture = Mod_LoadReplacementTexture ( skinname , " models " , true , true , true ) ;
}
if ( ! texture | | ( ! fbtexture & & r_fb_models . value ) )
2004-08-22 22:29:09 +00:00
{
if ( t = = 0 )
{
saved = Hunk_Alloc ( s ) ;
outskin - > ofstexels = ( qbyte * ) ( saved ) - ( qbyte * ) outskin ;
}
else
saved = BZ_Malloc ( s ) ;
memcpy ( saved , pskintype + 1 , s ) ;
GLMod_FloodFillSkin ( saved , outskin - > skinwidth , outskin - > skinheight ) ;
2005-04-26 16:04:12 +00:00
if ( ! texture )
2004-08-22 22:29:09 +00:00
{
2005-04-26 16:04:12 +00:00
sprintf ( skinname , " %s_%i_%i " , loadname , i , t ) ;
texture = GL_LoadTexture ( skinname , outskin - > skinwidth , outskin - > skinheight , saved , true , alpha ) ;
2004-08-22 22:29:09 +00:00
}
2005-04-26 16:04:12 +00:00
if ( ! fbtexture & & r_fb_models . value )
2004-08-22 22:29:09 +00:00
{
2005-04-26 16:04:12 +00:00
sprintf ( skinname , " %s_%i_%i_luma " , loadname , i , t ) ;
fbtexture = GL_LoadTextureFB ( skinname , outskin - > skinwidth , outskin - > skinheight , saved , true , true ) ;
2004-08-22 22:29:09 +00:00
}
if ( t ! = 0 ) //only keep the first.
BZ_Free ( saved ) ;
}
2005-04-26 16:04:12 +00:00
texnums - > base = texture ;
texnums - > fullbright = fbtexture ;
2004-08-22 22:29:09 +00:00
}
2004-09-13 04:16:52 +00:00
pskintype = ( daliasskintype_t * ) data ;
2004-08-22 22:29:09 +00:00
break ;
}
outskin + + ;
}
galias - > numskins = pq1inmodel - > numskins ;
return pskintype ;
}
void GL_LoadQ1Model ( model_t * mod , void * buffer )
{
vec2_t * st_array ;
int hunkstart , hunkend , hunktotal ;
int version ;
int i , j , onseams ;
dstvert_t * pinstverts ;
dtriangle_t * pintriangles ;
int * seamremap ;
2004-10-19 16:10:14 +00:00
index_t * indexes ;
2004-08-22 22:29:09 +00:00
int size ;
loadmodel = mod ;
//we've got to have this bit
if ( ! strcmp ( loadmodel - > name , " progs/player.mdl " ) | |
! strcmp ( loadmodel - > name , " progs/eyes.mdl " ) )
{
unsigned short crc ;
qbyte * p ;
int len ;
char st [ 40 ] ;
CRC_Init ( & crc ) ;
for ( len = com_filesize , p = buffer ; len ; len - - , p + + )
CRC_ProcessByte ( & crc , * p ) ;
sprintf ( st , " %d " , ( int ) crc ) ;
Info_SetValueForKey ( cls . userinfo ,
! strcmp ( loadmodel - > name , " progs/player.mdl " ) ? pmodel_name : emodel_name ,
st , MAX_INFO_STRING ) ;
2005-02-28 07:16:19 +00:00
if ( cls . state > = ca_connected )
{
2005-03-23 22:14:08 +00:00
CL_SendClientCommand ( true , " setinfo %s %d " ,
2004-08-22 22:29:09 +00:00
! strcmp ( loadmodel - > name , " progs/player.mdl " ) ? pmodel_name : emodel_name ,
( int ) crc ) ;
}
}
hunkstart = Hunk_LowMark ( ) ;
pq1inmodel = ( dmdl_t * ) buffer ;
2004-12-11 16:44:36 +00:00
seamremap = ( int * ) pq1inmodel ; //I like overloading locals.
for ( i = 0 ; i < sizeof ( dmdl_t ) / 4 ; i + + )
seamremap [ i ] = LittleLong ( seamremap [ i ] ) ;
version = pq1inmodel - > version ;
2004-08-22 22:29:09 +00:00
if ( version ! = ALIAS_VERSION )
Sys_Error ( " %s has wrong version number (%i should be %i) " ,
mod - > name , version , ALIAS_VERSION ) ;
if ( pq1inmodel - > numframes < 1 | |
pq1inmodel - > numskins < 1 | |
pq1inmodel - > numtris < 1 | |
pq1inmodel - > numverts < 3 | |
pq1inmodel - > skinheight < 1 | |
pq1inmodel - > skinwidth < 1 )
Sys_Error ( " Model %s has an invalid quantity \n " , mod - > name ) ;
2004-12-11 16:44:36 +00:00
mod - > flags = pq1inmodel - > flags ;
2004-08-22 22:29:09 +00:00
size = sizeof ( galiasinfo_t )
+ pq1inmodel - > numframes * sizeof ( galiasgroup_t )
+ pq1inmodel - > numskins * sizeof ( galiasskin_t ) ;
galias = Hunk_Alloc ( size ) ;
galias - > groupofs = sizeof ( * galias ) ;
galias - > ofsskins = sizeof ( * galias ) + pq1inmodel - > numframes * sizeof ( galiasgroup_t ) ;
galias - > nextsurf = 0 ;
//skins
if ( mod - > flags & EF_HOLEY )
pinstverts = ( dstvert_t * ) Q1_LoadSkins ( ( daliasskintype_t * ) ( pq1inmodel + 1 ) , 3 ) ;
else if ( mod - > flags & EF_TRANSPARENT )
pinstverts = ( dstvert_t * ) Q1_LoadSkins ( ( daliasskintype_t * ) ( pq1inmodel + 1 ) , 2 ) ;
else if ( mod - > flags & EF_SPECIAL_TRANS )
pinstverts = ( dstvert_t * ) Q1_LoadSkins ( ( daliasskintype_t * ) ( pq1inmodel + 1 ) , 4 ) ;
else
pinstverts = ( dstvert_t * ) Q1_LoadSkins ( ( daliasskintype_t * ) ( pq1inmodel + 1 ) , 0 ) ;
// pinstverts = (dstvert_t *)Q1_LoadSkins((daliasskintype_t *)(pq1inmodel+1));
//count number of verts that are onseam.
for ( onseams = 0 , i = 0 ; i < pq1inmodel - > numverts ; i + + )
{
if ( pinstverts [ i ] . onseam )
onseams + + ;
}
seamremap = BZ_Malloc ( sizeof ( int ) * pq1inmodel - > numverts ) ;
galias - > numverts = pq1inmodel - > numverts + onseams ;
//st
st_array = Hunk_Alloc ( sizeof ( * st_array ) * ( pq1inmodel - > numverts + onseams ) ) ;
galias - > ofs_st_array = ( char * ) st_array - ( char * ) galias ;
for ( j = pq1inmodel - > numverts , i = 0 ; i < pq1inmodel - > numverts ; i + + )
{
st_array [ i ] [ 0 ] = LittleLong ( pinstverts [ i ] . s ) / ( float ) pq1inmodel - > skinwidth ;
st_array [ i ] [ 1 ] = LittleLong ( pinstverts [ i ] . t ) / ( float ) pq1inmodel - > skinheight ;
if ( pinstverts [ i ] . onseam )
{
st_array [ j ] [ 0 ] = st_array [ i ] [ 0 ] + 0.5 ;
st_array [ j ] [ 1 ] = st_array [ i ] [ 1 ] ;
seamremap [ i ] = j ;
j + + ;
}
else
seamremap [ i ] = i ;
}
//trianglelists;
pintriangles = ( dtriangle_t * ) & pinstverts [ pq1inmodel - > numverts ] ;
galias - > numindexes = pq1inmodel - > numtris * 3 ;
indexes = Hunk_Alloc ( galias - > numindexes * sizeof ( * indexes ) ) ;
galias - > ofs_indexes = ( char * ) indexes - ( char * ) galias ;
for ( i = 0 ; i < pq1inmodel - > numtris ; i + + )
{
if ( ! pintriangles [ i ] . facesfront )
{
indexes [ i * 3 + 0 ] = seamremap [ LittleLong ( pintriangles [ i ] . vertindex [ 0 ] ) ] ;
indexes [ i * 3 + 1 ] = seamremap [ LittleLong ( pintriangles [ i ] . vertindex [ 1 ] ) ] ;
indexes [ i * 3 + 2 ] = seamremap [ LittleLong ( pintriangles [ i ] . vertindex [ 2 ] ) ] ;
}
else
{
indexes [ i * 3 + 0 ] = LittleLong ( pintriangles [ i ] . vertindex [ 0 ] ) ;
indexes [ i * 3 + 1 ] = LittleLong ( pintriangles [ i ] . vertindex [ 1 ] ) ;
indexes [ i * 3 + 2 ] = LittleLong ( pintriangles [ i ] . vertindex [ 2 ] ) ;
}
}
//frames
Q1_LoadFrameGroup ( ( daliasframetype_t * ) & pintriangles [ pq1inmodel - > numtris ] , seamremap ) ;
BZ_Free ( seamremap ) ;
if ( r_shadows . value )
{
int * neighbours ;
neighbours = Hunk_Alloc ( sizeof ( int ) * 3 * pq1inmodel - > numtris ) ;
galias - > ofs_trineighbours = ( qbyte * ) neighbours - ( qbyte * ) galias ;
R_BuildTriangleNeighbours ( neighbours , indexes , pq1inmodel - > numtris ) ;
}
VectorCopy ( pq1inmodel - > scale_origin , mod - > mins ) ;
VectorMA ( mod - > mins , 255 , pq1inmodel - > scale , mod - > maxs ) ;
//
// move the complete, relocatable alias model to the cache
//
hunkend = Hunk_LowMark ( ) ;
2004-10-10 06:32:29 +00:00
Hunk_Alloc ( 0 ) ;
2004-08-22 22:29:09 +00:00
hunktotal = hunkend - hunkstart ;
Cache_Alloc ( & mod - > cache , hunktotal , loadname ) ;
mod - > type = mod_alias ;
if ( ! mod - > cache . data )
{
Hunk_FreeToLowMark ( hunkstart ) ;
return ;
}
memcpy ( mod - > cache . data , galias , hunktotal ) ;
Hunk_FreeToLowMark ( hunkstart ) ;
}
# endif
int Mod_ReadFlagsFromMD1 ( char * name , int md3version )
{
dmdl_t * pinmodel ;
char fname [ MAX_QPATH ] ;
COM_StripExtension ( name , fname ) ;
COM_DefaultExtension ( fname , " .mdl " ) ;
2004-10-19 16:10:14 +00:00
if ( strcmp ( name , fname ) ) //md3 renamed as mdl
2004-08-22 22:29:09 +00:00
{
COM_StripExtension ( name , fname ) ; //seeing as the md3 is named over the mdl,
COM_DefaultExtension ( fname , " .md1 " ) ; //read from a file with md1 (one, not an ell)
return 0 ;
}
pinmodel = ( dmdl_t * ) COM_LoadTempFile ( fname ) ;
if ( ! pinmodel ) //not found
return 0 ;
2004-12-11 16:44:36 +00:00
if ( LittleLong ( pinmodel - > ident ) ! = IDPOLYHEADER )
2004-08-22 22:29:09 +00:00
return 0 ;
2004-12-11 16:44:36 +00:00
if ( LittleLong ( pinmodel - > version ) ! = ALIAS_VERSION )
2004-08-22 22:29:09 +00:00
return 0 ;
2004-12-11 16:44:36 +00:00
return LittleLong ( pinmodel - > flags ) ;
2004-08-22 22:29:09 +00:00
}
# ifdef MD2MODELS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Q2 model loading
static galiasinfo_t * galias ;
static model_t * loadmodel ;
static md2_t * pq2inmodel ;
# define Q2NUMVERTEXNORMALS 162
extern vec3_t bytedirs [ Q2NUMVERTEXNORMALS ] ;
static void Q2_LoadSkins ( char * skins )
{
int i ;
galiastexnum_t * texnums ;
galiasskin_t * outskin = ( galiasskin_t * ) ( ( char * ) galias + galias - > ofsskins ) ;
2005-03-18 06:14:33 +00:00
galias - > numskins = pq2inmodel - > num_skins ;
2004-08-22 22:29:09 +00:00
2005-03-18 06:14:33 +00:00
for ( i = 0 ; i < pq2inmodel - > num_skins ; i + + , outskin + + )
2004-08-22 22:29:09 +00:00
{
texnums = Hunk_Alloc ( sizeof ( * texnums ) ) ;
outskin - > ofstexnums = ( char * ) texnums - ( char * ) outskin ;
outskin - > texnums = 1 ;
2005-03-18 06:14:33 +00:00
COM_CleanUpPath ( skins ) ; //blooming tanks.
2005-04-26 16:04:12 +00:00
texnums - > base = Mod_LoadReplacementTexture ( skins , " models " , true , false , true ) ;
2004-08-22 22:29:09 +00:00
outskin - > skinwidth = 0 ;
outskin - > skinheight = 0 ;
outskin - > skinspeed = 0 ;
skins + = MD2MAX_SKINNAME ;
}
}
# define MD2_MAX_TRIANGLES 4096
void GL_LoadQ2Model ( model_t * mod , void * buffer )
{
int hunkstart , hunkend , hunktotal ;
int version ;
int i , j ;
dmd2stvert_t * pinstverts ;
dmd2triangle_t * pintri ;
2004-10-19 16:10:14 +00:00
index_t * indexes ;
2004-08-22 22:29:09 +00:00
int numindexes ;
vec3_t min ;
vec3_t max ;
galiaspose_t * pose ;
galiasgroup_t * poutframe ;
dmd2aliasframe_t * pinframe ;
int framesize ;
vec3_t * verts ;
vec3_t * normals ;
vec2_t * st_array ;
int indremap [ MD2_MAX_TRIANGLES * 3 ] ;
unsigned short ptempindex [ MD2_MAX_TRIANGLES * 3 ] , ptempstindex [ MD2_MAX_TRIANGLES * 3 ] ;
int numverts ;
int size ;
loadmodel = mod ;
hunkstart = Hunk_LowMark ( ) ;
pq2inmodel = ( md2_t * ) buffer ;
2005-03-18 06:14:33 +00:00
//FIXME: Endian
2004-08-22 22:29:09 +00:00
version = LittleLong ( pq2inmodel - > version ) ;
if ( version ! = MD2ALIAS_VERSION )
Sys_Error ( " %s has wrong version number (%i should be %i) " ,
mod - > name , version , MD2ALIAS_VERSION ) ;
if ( pq2inmodel - > num_frames < 1 | |
pq2inmodel - > num_skins < 0 | |
pq2inmodel - > num_tris < 1 | |
pq2inmodel - > num_xyz < 3 | |
pq2inmodel - > num_st < 3 | |
pq2inmodel - > skinheight < 1 | |
pq2inmodel - > skinwidth < 1 )
Sys_Error ( " Model %s has an invalid quantity \n " , mod - > name ) ;
mod - > flags = 0 ;
2005-03-18 06:14:33 +00:00
loadmodel - > numframes = pq2inmodel - > num_frames ;
2004-08-22 22:29:09 +00:00
size = sizeof ( galiasinfo_t )
+ pq2inmodel - > num_frames * sizeof ( galiasgroup_t )
+ pq2inmodel - > num_skins * sizeof ( galiasskin_t ) ;
galias = Hunk_Alloc ( size ) ;
galias - > groupofs = sizeof ( * galias ) ;
galias - > ofsskins = sizeof ( * galias ) + pq2inmodel - > num_frames * sizeof ( galiasgroup_t ) ;
galias - > nextsurf = 0 ;
//skins
Q2_LoadSkins ( ( ( char * ) pq2inmodel + pq2inmodel - > ofs_skins ) ) ;
//trianglelists;
pintri = ( dmd2triangle_t * ) ( ( char * ) pq2inmodel + pq2inmodel - > ofs_tris ) ;
for ( i = 0 ; i < pq2inmodel - > num_tris ; i + + , pintri + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
ptempindex [ i * 3 + j ] = ( unsigned short ) LittleShort ( pintri - > xyz_index [ j ] ) ;
ptempstindex [ i * 3 + j ] = ( unsigned short ) LittleShort ( pintri - > st_index [ j ] ) ;
}
}
numindexes = galias - > numindexes = pq2inmodel - > num_tris * 3 ;
indexes = Hunk_Alloc ( galias - > numindexes * sizeof ( * indexes ) ) ;
galias - > ofs_indexes = ( char * ) indexes - ( char * ) galias ;
memset ( indremap , - 1 , sizeof ( indremap ) ) ;
numverts = 0 ;
for ( i = 0 ; i < numindexes ; i + + )
{
if ( indremap [ i ] ! = - 1 ) {
continue ;
}
for ( j = 0 ; j < numindexes ; j + + )
{
if ( j = = i ) {
continue ;
}
if ( ( ptempindex [ i ] = = ptempindex [ j ] ) & & ( ptempstindex [ i ] = = ptempstindex [ j ] ) ) {
indremap [ j ] = i ;
}
}
}
// count unique vertexes
for ( i = 0 ; i < numindexes ; i + + )
{
if ( indremap [ i ] ! = - 1 ) {
continue ;
}
indexes [ i ] = numverts + + ;
indremap [ i ] = i ;
}
Con_DPrintf ( " %s: remapped %i verts to %i \n " , mod - > name , pq2inmodel - > num_xyz , numverts ) ;
galias - > numverts = numverts ;
// remap remaining indexes
for ( i = 0 ; i < numindexes ; i + + )
{
if ( indremap [ i ] ! = i ) {
indexes [ i ] = indexes [ indremap [ i ] ] ;
}
}
// s and t vertices
pinstverts = ( dmd2stvert_t * ) ( ( qbyte * ) pq2inmodel + LittleLong ( pq2inmodel - > ofs_st ) ) ;
st_array = Hunk_Alloc ( sizeof ( * st_array ) * ( numverts ) ) ;
galias - > ofs_st_array = ( char * ) st_array - ( char * ) galias ;
for ( j = 0 ; j < numindexes ; j + + )
{
st_array [ indexes [ j ] ] [ 0 ] = ( float ) ( ( ( double ) LittleShort ( pinstverts [ ptempstindex [ indremap [ j ] ] ] . s ) + 0.5f ) / pq2inmodel - > skinwidth ) ;
st_array [ indexes [ j ] ] [ 1 ] = ( float ) ( ( ( double ) LittleShort ( pinstverts [ ptempstindex [ indremap [ j ] ] ] . t ) + 0.5f ) / pq2inmodel - > skinheight ) ;
}
//frames
ClearBounds ( mod - > mins , mod - > maxs ) ;
poutframe = ( galiasgroup_t * ) ( ( char * ) galias + galias - > groupofs ) ;
framesize = LittleLong ( pq2inmodel - > framesize ) ;
for ( i = 0 ; i < pq2inmodel - > num_frames ; i + + )
{
pose = ( galiaspose_t * ) Hunk_Alloc ( sizeof ( galiaspose_t ) + sizeof ( vec3_t ) * 2 * numverts ) ;
poutframe - > poseofs = ( char * ) pose - ( char * ) poutframe ;
poutframe - > numposes = 1 ;
galias - > groups + + ;
verts = ( vec3_t * ) ( pose + 1 ) ;
normals = & verts [ galias - > numverts ] ;
pose - > ofsverts = ( char * ) verts - ( char * ) pose ;
pose - > ofsnormals = ( char * ) normals - ( char * ) pose ;
pinframe = ( dmd2aliasframe_t * ) ( ( qbyte * ) pq2inmodel + LittleLong ( pq2inmodel - > ofs_frames ) + i * framesize ) ;
for ( j = 0 ; j < 3 ; j + + )
{
pose - > scale [ j ] = LittleFloat ( pinframe - > scale [ j ] ) ;
pose - > scale_origin [ j ] = LittleFloat ( pinframe - > translate [ j ] ) ;
}
for ( j = 0 ; j < numindexes ; j + + )
{
// verts are all 8 bit, so no swapping needed
verts [ indexes [ j ] ] [ 0 ] = pose - > scale_origin [ 0 ] + pose - > scale [ 0 ] * pinframe - > verts [ ptempindex [ indremap [ j ] ] ] . v [ 0 ] ;
verts [ indexes [ j ] ] [ 1 ] = pose - > scale_origin [ 1 ] + pose - > scale [ 1 ] * pinframe - > verts [ ptempindex [ indremap [ j ] ] ] . v [ 1 ] ;
verts [ indexes [ j ] ] [ 2 ] = pose - > scale_origin [ 2 ] + pose - > scale [ 2 ] * pinframe - > verts [ ptempindex [ indremap [ j ] ] ] . v [ 2 ] ;
VectorCopy ( bytedirs [ pinframe - > verts [ ptempindex [ indremap [ j ] ] ] . lightnormalindex ] , normals [ indexes [ j ] ] ) ;
}
// Mod_AliasCalculateVertexNormals ( numindexes, poutindex, numverts, poutvertex, qfalse );
VectorCopy ( pose - > scale_origin , min ) ;
VectorMA ( pose - > scale_origin , 255 , pose - > scale , max ) ;
// poutframe->radius = RadiusFromBounds ( min, max );
// mod->radius = max ( mod->radius, poutframe->radius );
AddPointToBounds ( min , mod - > mins , mod - > maxs ) ;
AddPointToBounds ( max , mod - > mins , mod - > maxs ) ;
// GL_GenerateNormals((float*)verts, (float*)normals, indexes, numindexes/3, numverts);
poutframe + + ;
}
if ( r_shadows . value )
{
int * neighbours ;
neighbours = Hunk_Alloc ( sizeof ( int ) * 3 * pq2inmodel - > num_tris ) ;
galias - > ofs_trineighbours = ( qbyte * ) neighbours - ( qbyte * ) galias ;
R_BuildTriangleNeighbours ( neighbours , indexes , pq2inmodel - > num_tris ) ;
}
/*
VectorCopy ( pq2inmodel - > scale_origin , mod - > mins ) ;
VectorMA ( mod - > mins , 255 , pq2inmodel - > scale , mod - > maxs ) ;
*/
//
// move the complete, relocatable alias model to the cache
//
hunkend = Hunk_LowMark ( ) ;
2004-10-19 16:10:14 +00:00
Hunk_Alloc ( 0 ) ;
2004-08-22 22:29:09 +00:00
hunktotal = hunkend - hunkstart ;
Cache_Alloc ( & mod - > cache , hunktotal , loadname ) ;
mod - > type = mod_alias ;
if ( ! mod - > cache . data )
{
Hunk_FreeToLowMark ( hunkstart ) ;
return ;
}
memcpy ( mod - > cache . data , galias , hunktotal ) ;
Hunk_FreeToLowMark ( hunkstart ) ;
}
# endif
2004-11-17 18:13:33 +00:00
typedef struct {
char name [ MAX_QPATH ] ;
vec3_t org ;
float ang [ 3 ] [ 3 ] ;
} md3tag_t ;
2004-08-22 22:29:09 +00:00
2004-11-23 01:23:45 +00:00
void GLMod_GetTag ( model_t * model , int tagnum , int frame , float * * org , float * * axis )
2004-11-17 18:13:33 +00:00
{
galiasinfo_t * inf ;
md3tag_t * t ;
2004-08-22 22:29:09 +00:00
2004-11-17 18:13:33 +00:00
* org = NULL ;
* axis = NULL ;
if ( ! model | | model - > type ! = mod_alias )
return ;
2004-08-22 22:29:09 +00:00
2004-11-17 18:13:33 +00:00
inf = Mod_Extradata ( model ) ;
t = ( md3tag_t * ) ( ( char * ) inf + inf - > ofstags ) ;
if ( tagnum < = 0 | | tagnum > inf - > numtags )
return ;
2004-12-24 08:45:56 +00:00
if ( frame < 0 | | frame > = inf - > numtagframes )
return ;
2004-11-17 18:13:33 +00:00
tagnum - - ; //tagnum 0 is 'use my angles/org'
2004-08-22 22:29:09 +00:00
2004-11-17 18:13:33 +00:00
t + = tagnum ;
2004-12-21 04:32:34 +00:00
t + = inf - > numtags * frame ;
2004-11-17 18:13:33 +00:00
* org = t - > org ;
* axis = ( float * ) t - > ang ;
}
2004-08-22 22:29:09 +00:00
2004-12-21 04:32:34 +00:00
int GLMod_TagNumForName ( model_t * model , char * name )
{
int i ;
galiasinfo_t * inf ;
md3tag_t * t ;
if ( ! model | | model - > type ! = mod_alias )
return 0 ;
inf = Mod_Extradata ( model ) ;
t = ( md3tag_t * ) ( ( char * ) inf + inf - > ofstags ) ;
for ( i = 0 ; i < inf - > numtags ; i + + )
{
2004-12-24 08:45:56 +00:00
if ( ! strcmp ( t [ i ] . name , name ) )
2004-12-21 04:32:34 +00:00
return i + 1 ;
}
return 0 ;
}
2004-08-22 22:29:09 +00:00
# ifdef MD3MODELS
//structures from Tenebrae
typedef struct {
int ident ;
int version ;
char name [ MAX_QPATH ] ;
int flags ; //Does anyone know what these are?
int numFrames ;
int numTags ;
int numSurfaces ;
int numSkins ;
int ofsFrames ;
int ofsTags ;
int ofsSurfaces ;
int ofsEnd ;
} md3Header_t ;
//then has header->numFrames of these at header->ofs_Frames
typedef struct md3Frame_s {
vec3_t bounds [ 2 ] ;
vec3_t localOrigin ;
float radius ;
char name [ 16 ] ;
} md3Frame_t ;
//there are header->numSurfaces of these at header->ofsSurfaces, following from ofsEnd
typedef struct {
int ident ; //
char name [ MAX_QPATH ] ; // polyset name
int flags ;
int numFrames ; // all surfaces in a model should have the same
int numShaders ; // all surfaces in a model should have the same
int numVerts ;
int numTriangles ;
int ofsTriangles ;
int ofsShaders ; // offset from start of md3Surface_t
int ofsSt ; // texture coords are common for all frames
int ofsXyzNormals ; // numVerts * numFrames
int ofsEnd ; // next surface follows
} md3Surface_t ;
//at surf+surf->ofsXyzNormals
typedef struct {
short xyz [ 3 ] ;
qbyte latlong [ 2 ] ;
} md3XyzNormal_t ;
//surf->numTriangles at surf+surf->ofsTriangles
typedef struct {
int indexes [ 3 ] ;
} md3Triangle_t ;
//surf->numVerts at surf+surf->ofsSt
typedef struct {
float s ;
float t ;
} md3St_t ;
typedef struct {
char name [ MAX_QPATH ] ;
int shaderIndex ;
} md3Shader_t ;
//End of Tenebrae 'assistance'
void GL_LoadQ3Model ( model_t * mod , void * buffer )
{
int hunkstart , hunkend , hunktotal ;
// int version;
int s , i , j , d ;
2004-10-19 16:10:14 +00:00
index_t * indexes ;
2004-08-22 22:29:09 +00:00
vec3_t min ;
vec3_t max ;
galiaspose_t * pose ;
2004-10-19 16:10:14 +00:00
galiasinfo_t * parent , * root ;
2004-08-22 22:29:09 +00:00
galiasgroup_t * group ;
galiasskin_t * skin ;
galiastexnum_t * texnum ;
vec3_t * verts ;
vec3_t * normals ;
vec2_t * st_array ;
float lat , lng ;
md3St_t * inst ;
md3Triangle_t * intris ;
md3XyzNormal_t * invert ;
md3Shader_t * inshader ;
int size ;
md3Header_t * header ;
md3Surface_t * surf ;
loadmodel = mod ;
hunkstart = Hunk_LowMark ( ) ;
header = buffer ;
// if (header->version != sdfs)
// Sys_Error("GL_LoadQ3Model: Bad version\n");
parent = NULL ;
2004-10-19 16:10:14 +00:00
root = NULL ;
2004-08-22 22:29:09 +00:00
min [ 0 ] = min [ 1 ] = min [ 2 ] = 0 ;
max [ 0 ] = max [ 1 ] = max [ 2 ] = 0 ;
surf = ( md3Surface_t * ) ( ( qbyte * ) header + header - > ofsSurfaces ) ;
for ( s = 0 ; s < header - > numSurfaces ; s + + )
{
2005-03-18 06:14:33 +00:00
if ( surf - > ident ! = MD3_IDENT )
Con_Printf ( " Warning: md3 sub-surface doesn't match ident \n " ) ;
2004-08-22 22:29:09 +00:00
size = sizeof ( galiasinfo_t ) + sizeof ( galiasgroup_t ) * header - > numFrames ;
galias = Hunk_Alloc ( size ) ;
galias - > groupofs = sizeof ( * galias ) ; //frame groups
galias - > groups = header - > numFrames ;
galias - > numverts = surf - > numVerts ;
galias - > numindexes = surf - > numTriangles * 3 ;
galias - > numskins = 1 ;
if ( parent )
2004-10-19 16:10:14 +00:00
parent - > nextsurf = ( qbyte * ) galias - ( qbyte * ) parent ;
else
root = galias ;
parent = galias ;
2004-08-22 22:29:09 +00:00
st_array = Hunk_Alloc ( sizeof ( vec2_t ) * galias - > numindexes ) ;
galias - > ofs_st_array = ( qbyte * ) st_array - ( qbyte * ) galias ;
inst = ( md3St_t * ) ( ( qbyte * ) surf + surf - > ofsSt ) ;
for ( i = 0 ; i < galias - > numverts ; i + + )
{
st_array [ i ] [ 0 ] = inst [ i ] . s ;
st_array [ i ] [ 1 ] = inst [ i ] . t ;
}
indexes = Hunk_Alloc ( sizeof ( * indexes ) * galias - > numindexes ) ;
galias - > ofs_indexes = ( qbyte * ) indexes - ( qbyte * ) galias ;
intris = ( md3Triangle_t * ) ( ( qbyte * ) surf + surf - > ofsTriangles ) ;
for ( i = 0 ; i < surf - > numTriangles ; i + + )
{
indexes [ i * 3 + 0 ] = intris [ i ] . indexes [ 0 ] ;
indexes [ i * 3 + 1 ] = intris [ i ] . indexes [ 1 ] ;
indexes [ i * 3 + 2 ] = intris [ i ] . indexes [ 2 ] ;
}
group = ( galiasgroup_t * ) ( galias + 1 ) ;
invert = ( md3XyzNormal_t * ) ( ( qbyte * ) surf + surf - > ofsXyzNormals ) ;
for ( i = 0 ; i < surf - > numFrames ; i + + )
{
pose = ( galiaspose_t * ) Hunk_Alloc ( sizeof ( galiaspose_t ) + sizeof ( vec3_t ) * 2 * surf - > numVerts ) ;
normals = ( vec3_t * ) ( pose + 1 ) ;
verts = normals + surf - > numVerts ;
pose - > ofsnormals = ( qbyte * ) normals - ( qbyte * ) pose ;
pose - > ofsverts = ( qbyte * ) verts - ( qbyte * ) pose ;
for ( j = 0 ; j < surf - > numVerts ; j + + )
{
lat = ( float ) invert [ j ] . latlong [ 0 ] * ( 2 * M_PI ) * ( 1.0 / 255.0 ) ;
lng = ( float ) invert [ j ] . latlong [ 1 ] * ( 2 * M_PI ) * ( 1.0 / 255.0 ) ;
normals [ j ] [ 0 ] = cos ( lng ) * sin ( lat ) ;
normals [ j ] [ 1 ] = sin ( lng ) * sin ( lat ) ;
normals [ j ] [ 2 ] = cos ( lat ) ;
for ( d = 0 ; d < 3 ; d + + )
{
verts [ j ] [ d ] = invert [ j ] . xyz [ d ] / 64.0f ;
if ( verts [ j ] [ d ] < min [ d ] )
min [ d ] = verts [ j ] [ d ] ;
if ( verts [ j ] [ d ] > max [ d ] )
max [ d ] = verts [ j ] [ d ] ;
}
}
pose - > scale [ 0 ] = 1 ;
pose - > scale [ 1 ] = 1 ;
pose - > scale [ 2 ] = 1 ;
pose - > scale_origin [ 0 ] = 0 ;
pose - > scale_origin [ 1 ] = 0 ;
pose - > scale_origin [ 2 ] = 0 ;
group - > numposes = 1 ;
group - > rate = 1 ;
group - > poseofs = ( qbyte * ) pose - ( qbyte * ) group ;
group + + ;
invert + = surf - > numVerts ;
}
if ( surf - > numShaders )
{
2004-10-26 23:06:29 +00:00
# ifndef Q3SHADERS
2004-08-22 22:29:09 +00:00
char name [ 1024 ] ;
2004-12-09 23:45:14 +00:00
extern int gl_bumpmappingpossible ;
2004-10-26 23:06:29 +00:00
# endif
2004-12-24 08:45:56 +00:00
skin = Hunk_Alloc ( surf - > numShaders * ( ( sizeof ( galiasskin_t ) + sizeof ( galiastexnum_t ) ) ) ) ;
2004-08-22 22:29:09 +00:00
galias - > ofsskins = ( qbyte * ) skin - ( qbyte * ) galias ;
texnum = ( galiastexnum_t * ) ( skin + surf - > numShaders ) ;
inshader = ( md3Shader_t * ) ( ( qbyte * ) surf + surf - > ofsShaders ) ;
for ( i = 0 ; i < surf - > numShaders ; i + + )
{
skin - > texnums = 1 ;
skin - > ofstexnums = ( qbyte * ) texnum - ( qbyte * ) skin ;
skin - > ofstexels = 0 ;
skin - > skinwidth = 0 ;
skin - > skinheight = 0 ;
skin - > skinspeed = 0 ;
2004-12-24 08:45:56 +00:00
if ( ! * inshader - > name ) //'fix' the shader by looking the surface name up in a skin file. This isn't perfect, but it does the job for basic models.
GL_ParseQ3SkinFile ( inshader - > name , surf - > name , loadmodel - > name ) ;
2004-10-19 16:10:14 +00:00
# ifdef Q3SHADERS
texnum - > shader = R_RegisterSkin ( inshader - > name ) ;
# else
2004-08-22 22:29:09 +00:00
2005-05-13 10:42:48 +00:00
texnum - > base = Mod_LoadHiResTexture ( inshader - > name , " models " , true , true , true ) ;
2004-08-22 22:29:09 +00:00
if ( ! texnum - > base )
{
strcpy ( name , loadmodel - > name ) ;
strcpy ( COM_SkipPath ( name ) , COM_SkipPath ( inshader - > name ) ) ; //eviile eh?
2005-05-13 10:42:48 +00:00
texnum - > base = Mod_LoadHiResTexture ( name , " models " , true , true , true ) ;
2004-08-22 22:29:09 +00:00
}
texnum - > bump = 0 ;
if ( gl_bumpmappingpossible )
{
COM_StripExtension ( inshader - > name , name ) ; //go for the normalmap
strcat ( name , " _norm " ) ;
2005-05-13 10:42:48 +00:00
texnum - > bump = Mod_LoadHiResTexture ( name , " models " , true , true , false ) ;
2004-08-22 22:29:09 +00:00
if ( ! texnum - > bump )
{
strcpy ( name , loadmodel - > name ) ;
COM_StripExtension ( COM_SkipPath ( inshader - > name ) , COM_SkipPath ( name ) ) ;
strcat ( name , " _norm " ) ;
2005-05-13 10:42:48 +00:00
texnum - > bump = Mod_LoadHiResTexture ( name , " models " , true , true , false ) ;
2004-08-22 22:29:09 +00:00
if ( ! texnum - > bump )
{
COM_StripExtension ( inshader - > name , name ) ; //bother, go for heightmap and convert
strcat ( name , " _bump " ) ;
2005-05-13 10:42:48 +00:00
texnum - > bump = Mod_LoadBumpmapTexture ( name , " models " ) ;
2004-08-22 22:29:09 +00:00
if ( ! texnum - > bump )
{
strcpy ( name , loadmodel - > name ) ;
strcpy ( COM_SkipPath ( name ) , COM_SkipPath ( inshader - > name ) ) ; //eviile eh?
COM_StripExtension ( name , name ) ;
strcat ( name , " _bump " ) ;
2005-05-13 10:42:48 +00:00
texnum - > bump = Mod_LoadBumpmapTexture ( name , " models " ) ;
2004-08-22 22:29:09 +00:00
}
}
}
}
if ( r_fb_models . value )
{
COM_StripExtension ( inshader - > name , name ) ; //go for the normalmap
strcat ( name , " _luma " ) ;
2005-05-13 10:42:48 +00:00
texnum - > fullbright = Mod_LoadHiResTexture ( name , " models " , true , true , true ) ;
2004-08-22 22:29:09 +00:00
if ( ! texnum - > base )
{
strcpy ( name , loadmodel - > name ) ;
strcpy ( COM_SkipPath ( name ) , COM_SkipPath ( inshader - > name ) ) ; //eviile eh?
COM_StripExtension ( name , name ) ;
strcat ( name , " _luma " ) ;
2005-05-13 10:42:48 +00:00
texnum - > fullbright = Mod_LoadBumpmapTexture ( name , " models " ) ;
2004-08-22 22:29:09 +00:00
}
}
2004-10-19 16:10:14 +00:00
# endif
2004-08-22 22:29:09 +00:00
skin + + ;
texnum + + ;
}
}
VectorCopy ( min , loadmodel - > mins ) ;
VectorCopy ( max , loadmodel - > maxs ) ;
if ( r_shadows . value )
{
int * neighbours ;
neighbours = Hunk_Alloc ( sizeof ( int ) * 3 * surf - > numTriangles ) ;
galias - > ofs_trineighbours = ( qbyte * ) neighbours - ( qbyte * ) galias ;
R_BuildTriangleNeighbours ( neighbours , indexes , surf - > numTriangles ) ;
}
surf = ( md3Surface_t * ) ( ( qbyte * ) surf + surf - > ofsEnd ) ;
}
2004-12-24 08:45:56 +00:00
if ( ! root )
root = Hunk_Alloc ( sizeof ( galiasinfo_t ) ) ;
root - > numtagframes = header - > numFrames ;
2004-11-17 18:13:33 +00:00
root - > numtags = header - > numTags ;
root - > ofstags = ( char * ) Hunk_Alloc ( header - > numTags * sizeof ( md3tag_t ) * header - > numFrames ) - ( char * ) root ;
memcpy ( ( char * ) root + root - > ofstags , ( char * ) header + header - > ofsTags , header - > numTags * sizeof ( md3tag_t ) * header - > numFrames ) ;
2004-08-22 22:29:09 +00:00
//
// move the complete, relocatable alias model to the cache
2004-11-17 18:13:33 +00:00
//
2004-08-22 22:29:09 +00:00
2004-10-19 16:10:14 +00:00
hunkend = Hunk_LowMark ( ) ;
2005-05-15 18:49:04 +00:00
mod - > flags = LittleLong ( header - > flags ) ;
if ( ! mod - > flags )
mod - > flags = Mod_ReadFlagsFromMD1 ( mod - > name , 0 ) ;
2004-08-22 22:29:09 +00:00
2004-10-19 16:10:14 +00:00
Hunk_Alloc ( 0 ) ;
2004-08-22 22:29:09 +00:00
hunktotal = hunkend - hunkstart ;
Cache_Alloc ( & mod - > cache , hunktotal , loadname ) ;
mod - > type = mod_alias ;
if ( ! mod - > cache . data )
{
Hunk_FreeToLowMark ( hunkstart ) ;
return ;
}
2004-10-19 16:10:14 +00:00
memcpy ( mod - > cache . data , root , hunktotal ) ;
2004-08-22 22:29:09 +00:00
Hunk_FreeToLowMark ( hunkstart ) ;
}
# endif
2004-11-23 01:23:45 +00:00
2004-11-29 01:21:00 +00:00
# ifdef ZYMOTICMODELS
2004-11-23 01:23:45 +00:00
typedef struct zymlump_s
{
int start ;
int length ;
} zymlump_t ;
typedef struct zymtype1header_s
{
char id [ 12 ] ; // "ZYMOTICMODEL", length 12, no termination
int type ; // 0 (vertex morph) 1 (skeletal pose) or 2 (skeletal scripted)
int filesize ; // size of entire model file
float mins [ 3 ] , maxs [ 3 ] , radius ; // for clipping uses
int numverts ;
int numtris ;
int numshaders ;
int numbones ; // this may be zero in the vertex morph format (undecided)
int numscenes ; // 0 in skeletal scripted models
// skeletal pose header
// lump offsets are relative to the file
zymlump_t lump_scenes ; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
zymlump_t lump_poses ; // float pose[numposes][numbones][6]; // animation data
zymlump_t lump_bones ; // zymbone_t bone[numbones];
zymlump_t lump_vertbonecounts ; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
zymlump_t lump_verts ; // zymvertex_t vert[numvertices]; // see vertex struct
zymlump_t lump_texcoords ; // float texcoords[numvertices][2];
zymlump_t lump_render ; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
zymlump_t lump_shaders ; // char shadername[numshaders][32]; // shaders used on this model
zymlump_t lump_trizone ; // byte trizone[numtris]; // see trizone explanation
} zymtype1header_t ;
typedef struct zymbone_s
{
char name [ 32 ] ;
int flags ;
int parent ; // parent bone number
} zymbone_t ;
typedef struct zymscene_s
{
char name [ 32 ] ;
float mins [ 3 ] , maxs [ 3 ] , radius ; // for clipping
float framerate ; // the scene will animate at this framerate (in frames per second)
int flags ;
int start , length ; // range of poses
} zymscene_t ;
typedef struct zymvertex_s
{
int bonenum ;
float origin [ 3 ] ;
} zymvertex_t ;
//this can generate multiple meshes (one for each shader).
//but only one set of transforms are ever generated.
void GLMod_LoadZymoticModel ( model_t * mod , void * buffer )
{
int i ;
int hunkstart , hunkend , hunktotal ;
zymtype1header_t * header ;
galiasinfo_t * root ;
galisskeletaltransforms_t * transforms ;
zymvertex_t * intrans ;
2004-11-23 16:14:49 +00:00
galiasskin_t * skin ;
2004-11-23 01:23:45 +00:00
galiasbone_t * bone ;
zymbone_t * inbone ;
int v ;
float multiplier ;
float * matrix , * inmatrix ;
2004-11-23 16:14:49 +00:00
vec2_t * stcoords ;
vec2_t * inst ;
2004-11-23 01:23:45 +00:00
int * vertbonecounts ;
galiasgroup_t * grp ;
zymscene_t * inscene ;
int * renderlist , count ;
index_t * indexes ;
2004-11-23 16:14:49 +00:00
char * shadername ;
2004-11-23 01:23:45 +00:00
loadmodel = mod ;
hunkstart = Hunk_LowMark ( ) ;
header = buffer ;
if ( memcmp ( header - > id , " ZYMOTICMODEL " , 12 ) )
Sys_Error ( " GLMod_LoadZymoticModel: doesn't appear to BE a zymotic! \n " ) ;
if ( BigLong ( header - > type ) ! = 1 )
Sys_Error ( " GLMod_LoadZymoticModel: only type 1 is supported \n " ) ;
for ( i = 0 ; i < sizeof ( zymtype1header_t ) / 4 ; i + + )
( ( int * ) header ) [ i ] = BigLong ( ( ( int * ) header ) [ i ] ) ;
if ( ! header - > numverts )
Sys_Error ( " GLMod_LoadZymoticModel: no vertexes \n " ) ;
if ( ! header - > numshaders )
Sys_Error ( " GLMod_LoadZymoticModel: no textures \n " ) ;
root = Hunk_AllocName ( sizeof ( galiasinfo_t ) * header - > numshaders , loadname ) ;
root - > numtransforms = header - > lump_verts . length / sizeof ( zymvertex_t ) ;
transforms = Hunk_Alloc ( root - > numtransforms * sizeof ( * transforms ) ) ;
root - > ofstransforms = ( char * ) transforms - ( char * ) root ;
vertbonecounts = ( int * ) ( ( char * ) header + header - > lump_vertbonecounts . start ) ;
intrans = ( zymvertex_t * ) ( ( char * ) header + header - > lump_verts . start ) ;
vertbonecounts [ 0 ] = BigLong ( vertbonecounts [ 0 ] ) ;
multiplier = 1.0f / vertbonecounts [ 0 ] ;
for ( i = 0 , v = 0 ; i < root - > numtransforms ; i + + )
{
while ( ! vertbonecounts [ v ] )
{
v + + ;
if ( v = = header - > numverts )
Sys_Error ( " GLMod_LoadZymoticModel: Too many transformations \n " ) ;
vertbonecounts [ v ] = BigLong ( vertbonecounts [ v ] ) ;
multiplier = 1.0f / vertbonecounts [ v ] ;
}
transforms [ i ] . vertexindex = v ;
transforms [ i ] . boneindex = BigLong ( intrans [ i ] . bonenum ) ;
transforms [ i ] . org [ 0 ] = multiplier * BigFloat ( intrans [ i ] . origin [ 0 ] ) ;
transforms [ i ] . org [ 1 ] = multiplier * BigFloat ( intrans [ i ] . origin [ 1 ] ) ;
transforms [ i ] . org [ 2 ] = multiplier * BigFloat ( intrans [ i ] . origin [ 2 ] ) ;
transforms [ i ] . org [ 3 ] = multiplier * 1 ;
vertbonecounts [ v ] - - ;
}
if ( intrans ! = ( zymvertex_t * ) ( ( char * ) header + header - > lump_verts . start ) )
Sys_Error ( " Vertex transforms list appears corrupt. " ) ;
2004-11-23 14:58:32 +00:00
if ( vertbonecounts ! = ( int * ) ( ( char * ) header + header - > lump_vertbonecounts . start ) )
Sys_Error ( " Vertex bone counts list appears corrupt. " ) ;
2004-11-23 01:23:45 +00:00
root - > numverts = v + 1 ;
root - > numbones = header - > numbones ;
bone = Hunk_Alloc ( root - > numtransforms * sizeof ( * transforms ) ) ;
inbone = ( zymbone_t * ) ( ( char * ) header + header - > lump_bones . start ) ;
for ( i = 0 ; i < root - > numbones ; i + + )
bone [ i ] . parent = BigLong ( inbone [ i ] . parent ) ;
root - > ofsbones = ( char * ) bone - ( char * ) root ;
renderlist = ( int * ) ( ( char * ) header + header - > lump_render . start ) ;
for ( i = 0 ; i < header - > numshaders ; i + + )
{
count = BigLong ( * renderlist + + ) ;
count * = 3 ;
indexes = Hunk_Alloc ( count * sizeof ( * indexes ) ) ;
root [ i ] . ofs_indexes = ( char * ) indexes - ( char * ) & root [ i ] ;
root [ i ] . numindexes = count ;
2004-11-23 16:14:49 +00:00
while ( count )
{ //invert
indexes [ count - 1 ] = BigLong ( renderlist [ count - 3 ] ) ;
indexes [ count - 2 ] = BigLong ( renderlist [ count - 2 ] ) ;
indexes [ count - 3 ] = BigLong ( renderlist [ count - 1 ] ) ;
count - = 3 ;
2004-11-23 01:23:45 +00:00
}
renderlist + = root [ i ] . numindexes ;
}
if ( renderlist ! = ( int * ) ( ( char * ) header + header - > lump_render . start + header - > lump_render . length ) )
Sys_Error ( " Render list appears corrupt. " ) ;
grp = Hunk_Alloc ( sizeof ( * grp ) * header - > numscenes * header - > numshaders ) ;
matrix = Hunk_Alloc ( header - > lump_poses . length ) ;
2004-11-23 14:58:32 +00:00
inmatrix = ( float * ) ( ( char * ) header + header - > lump_poses . start ) ;
2004-11-23 01:23:45 +00:00
for ( i = 0 ; i < header - > lump_poses . length / 4 ; i + + )
matrix [ i ] = BigFloat ( inmatrix [ i ] ) ;
inscene = ( zymscene_t * ) ( ( char * ) header + header - > lump_scenes . start ) ;
2004-11-23 16:14:49 +00:00
shadername = ( ( char * ) header + header - > lump_shaders . start ) ;
stcoords = Hunk_Alloc ( root [ 0 ] . numverts * sizeof ( vec2_t ) ) ;
inst = ( vec2_t * ) ( ( char * ) header + header - > lump_texcoords . start ) ;
for ( i = 0 ; i < header - > lump_texcoords . length / 8 ; i + + )
{
stcoords [ i ] [ 0 ] = BigFloat ( inst [ i ] [ 0 ] ) ;
stcoords [ i ] [ 1 ] = 1 - BigFloat ( inst [ i ] [ 1 ] ) ; //hmm. upside down skin coords?
}
for ( i = 0 ; i < header - > numshaders ; i + + , shadername + = 32 )
2004-11-23 01:23:45 +00:00
{
2004-11-23 16:14:49 +00:00
root [ i ] . ofs_st_array = ( char * ) stcoords - ( char * ) & root [ i ] ;
root [ i ] . groups = header - > numscenes ;
root [ i ] . groupofs = ( char * ) grp - ( char * ) & root [ i ] ;
2005-05-15 18:49:04 +00:00
skin = GL_LoadSkinFile ( & root [ i ] . numskins , shadername , i , NULL , 0 , 0 , NULL ) ;
2004-11-23 16:14:49 +00:00
root [ i ] . ofsskins = ( char * ) skin - ( char * ) & root [ i ] ;
2004-11-23 01:23:45 +00:00
}
2004-11-23 16:14:49 +00:00
2004-11-23 01:23:45 +00:00
for ( i = 0 ; i < header - > numscenes ; i + + , grp + + , inscene + + )
{
grp - > isskeletal = 1 ;
grp - > rate = BigFloat ( inscene - > framerate ) ;
grp - > numposes = BigLong ( inscene - > length ) ;
grp - > poseofs = ( char * ) matrix - ( char * ) grp ;
2004-11-23 15:30:34 +00:00
grp - > poseofs + = BigLong ( inscene - > start ) * 12 * sizeof ( float ) * root - > numbones ;
2004-11-23 01:23:45 +00:00
}
if ( inscene ! = ( zymscene_t * ) ( ( char * ) header + header - > lump_scenes . start + header - > lump_scenes . length ) )
Sys_Error ( " scene list appears corrupt. " ) ;
for ( i = 0 ; i < header - > numshaders - 1 ; i + + )
root [ i ] . nextsurf = sizeof ( galiasinfo_t ) ;
for ( i = 1 ; i < header - > numshaders ; i + + )
{
root [ i ] . sharesverts = true ;
root [ i ] . numbones = root [ 0 ] . numbones ;
root [ i ] . numverts = root [ 0 ] . numverts ;
root [ i ] . ofsbones = root [ 0 ] . ofsbones ;
2005-05-15 18:49:04 +00:00
root [ i - 1 ] . nextsurf = sizeof ( * root ) ;
2004-11-23 01:23:45 +00:00
}
//
// move the complete, relocatable alias model to the cache
//
hunkend = Hunk_LowMark ( ) ;
mod - > flags = Mod_ReadFlagsFromMD1 ( mod - > name , 0 ) ; //file replacement - inherit flags from any defunc mdl files.
Hunk_Alloc ( 0 ) ;
hunktotal = hunkend - hunkstart ;
Cache_Alloc ( & mod - > cache , hunktotal , loadname ) ;
mod - > type = mod_alias ;
if ( ! mod - > cache . data )
{
Hunk_FreeToLowMark ( hunkstart ) ;
return ;
}
memcpy ( mod - > cache . data , root , hunktotal ) ;
Hunk_FreeToLowMark ( hunkstart ) ;
2004-11-29 01:21:00 +00:00
}
# endif
2005-01-24 23:47:32 +00:00
# endif