2004-08-21 01:25:48 +00:00
# include "quakedef.h"
2012-09-30 05:52:03 +00:00
# ifndef SERVERONLY
2004-08-21 01:25:48 +00:00
# include "glquake.h"
2007-05-25 22:16:29 +00:00
# endif
2009-11-04 21:16:50 +00:00
# include "com_mesh.h"
2004-08-21 01:25:48 +00:00
2012-08-01 23:46:20 +00:00
# define MAX_Q3MAP_INDICES 0x800000 //just a sanity limit
# define MAX_Q3MAP_VERTEXES 0x80000 //just a sanity limit
2004-08-21 01:25:48 +00:00
# define MAX_Q3MAP_BRUSHSIDES 0x30000
# define MAX_CM_BRUSHSIDES (MAX_Q3MAP_BRUSHSIDES << 1)
# define MAX_CM_BRUSHES (MAX_Q2MAP_BRUSHES << 1)
# define MAX_CM_PATCH_VERTS (4096)
# define MAX_CM_FACES (MAX_Q2MAP_FACES)
# define MAX_CM_PATCHES (0x10000)
# define MAX_CM_LEAFFACES (MAX_Q2MAP_LEAFFACES)
# define MAX_CM_AREAS MAX_Q2MAP_AREAS
# define Q3SURF_NODRAW 0x80 // don't generate a drawsurface at all
# define Q3SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes
# define Q3SURF_NONSOLID 0x4000 // don't collide against curves with this set
2009-11-04 21:16:50 +00:00
# if Q3SURF_NODRAW != TI_NODRAW
2004-08-21 01:25:48 +00:00
# error "nodraw isn't constant"
# endif
2005-08-03 23:14:59 +00:00
extern cvar_t r_shadow_bumpscale_basetexture ;
2004-08-21 01:25:48 +00:00
//these are in model.c (or gl_model.c)
2009-11-04 21:16:50 +00:00
qboolean RMod_LoadVertexes ( lump_t * l ) ;
2011-10-27 16:16:29 +00:00
qboolean RMod_LoadEdges ( lump_t * l , qboolean lm ) ;
2011-12-05 15:23:40 +00:00
qboolean RMod_LoadMarksurfaces ( lump_t * l , qboolean lm ) ;
2009-11-04 21:16:50 +00:00
qboolean RMod_LoadSurfedges ( lump_t * l ) ;
void RMod_LoadLighting ( lump_t * l ) ;
2004-08-21 01:25:48 +00:00
2010-08-28 17:14:38 +00:00
qboolean CM_Trace ( model_t * model , int forcehullnum , int frame , vec3_t axis [ 3 ] , vec3_t start , vec3_t end , vec3_t mins , vec3_t maxs , trace_t * trace ) ;
qboolean CM_NativeTrace ( model_t * model , int forcehullnum , int frame , vec3_t axis [ 3 ] , vec3_t start , vec3_t end , vec3_t mins , vec3_t maxs , unsigned int contents , trace_t * trace ) ;
unsigned int CM_NativeContents ( struct model_s * model , int hulloverride , int frame , vec3_t axis [ 3 ] , vec3_t p , vec3_t mins , vec3_t maxs ) ;
unsigned int Q2BSP_PointContents ( model_t * mod , vec3_t axis [ 3 ] , vec3_t p ) ;
2004-08-21 01:25:48 +00:00
extern char loadname [ 32 ] ;
extern model_t * loadmodel ;
2012-07-05 19:42:36 +00:00
void RMod_Batches_Build ( mesh_t * meshlist , model_t * mod , void ( * build ) ( model_t * mod , msurface_t * surf , void * cookie ) , void * buildcookie ) ;
2004-08-21 01:25:48 +00:00
float RadiusFromBounds ( vec3_t mins , vec3_t maxs )
{
int i ;
vec3_t corner ;
for ( i = 0 ; i < 3 ; i + + )
{
corner [ i ] = fabs ( mins [ i ] ) > fabs ( maxs [ i ] ) ? fabs ( mins [ i ] ) : fabs ( maxs [ i ] ) ;
}
return Length ( corner ) ;
}
void CalcSurfaceExtents ( msurface_t * s )
{
float mins [ 2 ] , maxs [ 2 ] , val ;
int i , j , e ;
mvertex_t * v ;
mtexinfo_t * tex ;
int bmins [ 2 ] , bmaxs [ 2 ] ;
mins [ 0 ] = mins [ 1 ] = 999999 ;
maxs [ 0 ] = maxs [ 1 ] = - 99999 ;
tex = s - > texinfo ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < s - > numedges ; i + + )
{
e = loadmodel - > surfedges [ s - > firstedge + i ] ;
if ( e > = 0 )
v = & loadmodel - > vertexes [ loadmodel - > edges [ e ] . v [ 0 ] ] ;
else
v = & loadmodel - > vertexes [ loadmodel - > edges [ - e ] . v [ 1 ] ] ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
for ( j = 0 ; j < 2 ; j + + )
{
2006-03-04 20:43:48 +00:00
val = v - > position [ 0 ] * tex - > vecs [ j ] [ 0 ] +
2004-08-21 01:25:48 +00:00
v - > position [ 1 ] * tex - > vecs [ j ] [ 1 ] +
v - > position [ 2 ] * tex - > vecs [ j ] [ 2 ] +
tex - > vecs [ j ] [ 3 ] ;
if ( val < mins [ j ] )
mins [ j ] = val ;
if ( val > maxs [ j ] )
maxs [ j ] = val ;
}
}
for ( i = 0 ; i < 2 ; i + + )
2006-03-04 20:43:48 +00:00
{
2004-08-21 01:25:48 +00:00
bmins [ i ] = floor ( mins [ i ] / 16 ) ;
bmaxs [ i ] = ceil ( maxs [ i ] / 16 ) ;
s - > texturemins [ i ] = bmins [ i ] * 16 ;
s - > extents [ i ] = ( bmaxs [ i ] - bmins [ i ] ) * 16 ;
2011-12-05 15:23:40 +00:00
// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 8176 ) //q2 uses 512. probably for skys.
// Con_Printf ("Bad surface extents (texture %s)\n", s->texinfo->texture->name);
2004-08-21 01:25:48 +00:00
}
}
void AddPointToBounds ( vec3_t v , vec3_t mins , vec3_t maxs )
{
int i ;
vec_t val ;
for ( i = 0 ; i < 3 ; i + + )
{
val = v [ i ] ;
if ( val < mins [ i ] )
mins [ i ] = val ;
if ( val > maxs [ i ] )
maxs [ i ] = val ;
}
}
void ClearBounds ( vec3_t mins , vec3_t maxs )
{
mins [ 0 ] = mins [ 1 ] = mins [ 2 ] = 99999 ;
maxs [ 0 ] = maxs [ 1 ] = maxs [ 2 ] = - 99999 ;
}
2010-07-11 02:22:39 +00:00
void Mod_SortShaders ( void )
{
2013-03-12 23:10:44 +00:00
//surely this isn't still needed?
2010-07-11 02:22:39 +00:00
texture_t * textemp ;
int i , j ;
//sort loadmodel->textures
for ( i = 0 ; i < loadmodel - > numtextures ; i + + )
{
for ( j = i + 1 ; j < loadmodel - > numtextures ; j + + )
{
if ( ( loadmodel - > textures [ i ] - > shader & & loadmodel - > textures [ j ] - > shader ) & & ( loadmodel - > textures [ j ] - > shader - > sort < loadmodel - > textures [ i ] - > shader - > sort ) )
{
textemp = loadmodel - > textures [ j ] ;
loadmodel - > textures [ j ] = loadmodel - > textures [ i ] ;
loadmodel - > textures [ i ] = textemp ;
}
}
}
}
2004-08-21 01:25:48 +00:00
# ifdef Q2BSPS
qbyte * ReadPCXPalette ( qbyte * buf , int len , qbyte * out ) ;
# ifdef SERVERONLY
# define Host_Error SV_Error
# endif
extern model_t * loadmodel ;
extern qbyte * mod_base ;
unsigned char d_q28to24table [ 1024 ] ;
/*
typedef struct q2csurface_s
{
char name [ 16 ] ;
int flags ;
int value ;
} q2csurface_t ;
*/
typedef struct q2mapsurface_s // used internally due to name len probs //ZOID
{
q2csurface_t c ;
char rname [ 32 ] ;
} q2mapsurface_t ;
2011-12-05 15:23:40 +00:00
typedef struct {
char shader [ MAX_QPATH ] ;
int brushNum ;
int visibleSide ; // the brush side that ray tests need to clip against (-1 == none)
} dfog_t ;
2004-08-21 01:25:48 +00:00
typedef struct
{
mplane_t * plane ;
q2mapsurface_t * surface ;
} q2cbrushside_t ;
typedef struct
{
int contents ;
int numsides ;
2010-03-14 14:35:56 +00:00
q2cbrushside_t * brushside ;
2004-08-21 01:25:48 +00:00
int checkcount ; // to avoid repeated testings
} q2cbrush_t ;
typedef struct
{
int numareaportals ;
int firstareaportal ;
int floodnum ; // if two areas have equal floodnums, they are connected
int floodvalid ;
} q2carea_t ;
typedef struct
{
int numareaportals [ MAX_CM_AREAS ] ;
} q3carea_t ;
typedef struct
{
vec3_t absmins , absmaxs ;
2010-03-14 14:35:56 +00:00
int numfacets ;
q2cbrush_t * facets ;
# define numbrushes numfacets
# define brushes facets
2004-08-21 01:25:48 +00:00
q2mapsurface_t * surface ;
int checkcount ; // to avoid repeated testings
} q3cpatch_t ;
typedef struct
{
int facetype ;
int numverts ;
int firstvert ;
int shadernum ;
int patch_cp [ 2 ] ;
} q3cface_t ;
2011-12-05 15:23:40 +00:00
typedef struct cmodel_s
{
vec3_t mins , maxs ;
vec3_t origin ; // for sounds or lights
int headnode ;
int numsurfaces ;
int firstsurface ;
int firstbrush ; //q3 submodels are considered small enough that you will never need to walk any sort of tree.
int num_brushes ; //the brushes are checked instead.
} cmodel_t ;
2010-07-11 02:22:39 +00:00
/*used to trace*/
2011-12-05 15:23:40 +00:00
static int checkcount ;
static mfog_t * map_fogs ;
static int map_numfogs ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numbrushsides ;
static q2cbrushside_t map_brushsides [ MAX_Q2MAP_BRUSHSIDES ] ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numtexinfo ;
static q2mapsurface_t * map_surfaces ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numplanes ;
static mplane_t map_planes [ MAX_Q2MAP_PLANES + 6 ] ; // extra for box hull
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numleafs = 1 ; // allow leaf funcs to be called without a map
static mleaf_t map_leafs [ MAX_MAP_LEAFS ] ;
static int emptyleaf ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numleafbrushes ;
static int map_leafbrushes [ MAX_Q2MAP_LEAFBRUSHES ] ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numcmodels ;
static cmodel_t map_cmodels [ MAX_Q2MAP_MODELS ] ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numbrushes ;
static q2cbrush_t map_brushes [ MAX_Q2MAP_BRUSHES ] ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numvisibility ;
2012-08-02 03:44:04 +00:00
static q2dvis_t * map_q2vis ;
static q3dvis_t * map_q3pvs ;
static q3dvis_t * map_q3phs ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numentitychars ;
static char * map_entitystring ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numareas = 1 ;
static q2carea_t map_q2areas [ MAX_Q2MAP_AREAS ] ;
static q3carea_t map_q3areas [ MAX_CM_AREAS ] ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numareaportals ;
static q2dareaportal_t map_areaportals [ MAX_Q2MAP_AREAPORTALS ] ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static q3cpatch_t map_patches [ MAX_CM_PATCHES ] ;
static int numpatches ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int map_leafpatches [ MAX_CM_LEAFFACES ] ;
static int numleafpatches ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numclusters = 1 ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static q2mapsurface_t nullsurface ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int floodvalid ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static qbyte portalopen [ MAX_Q2MAP_AREAPORTALS ] ; //memset will work if it's a qbyte, really it should be a qboolean
2004-08-21 01:25:48 +00:00
static int mapisq3 ;
2012-10-10 22:58:51 +00:00
cvar_t map_noareas = SCVAR ( " map_noareas " , " 0 " ) ; //1 for lack of mod support.
2006-02-11 02:09:43 +00:00
cvar_t map_noCurves = SCVARF ( " map_noCurves " , " 0 " , CVAR_CHEAT ) ;
cvar_t map_autoopenportals = SCVAR ( " map_autoopenportals " , " 1 " ) ; //1 for lack of mod support.
cvar_t r_subdivisions = SCVAR ( " r_subdivisions " , " 2 " ) ;
2004-08-21 01:25:48 +00:00
2005-08-26 22:56:51 +00:00
int CM_NumInlineModels ( model_t * model ) ;
2011-12-05 15:23:40 +00:00
cmodel_t * CM_InlineModel ( char * name ) ;
2004-08-21 01:25:48 +00:00
void CM_InitBoxHull ( void ) ;
void FloodAreaConnections ( void ) ;
2011-12-05 15:23:40 +00:00
static int c_pointcontents ;
static int c_traces , c_brush_traces ;
2004-08-21 01:25:48 +00:00
2004-10-19 16:10:14 +00:00
2011-12-05 15:23:40 +00:00
static vecV_t * map_verts ; //3points
static int numvertexes ;
2004-10-19 16:10:14 +00:00
2011-12-05 15:23:40 +00:00
static vec2_t * map_vertstmexcoords ;
2012-07-05 19:42:36 +00:00
static vec2_t * map_vertlstmexcoords [ 4 ] ;
2011-12-05 15:23:40 +00:00
static vec4_t * map_colors4f_array ;
static vec3_t * map_normals_array ;
static vec3_t * map_svector_array ;
static vec3_t * map_tvector_array ;
2004-08-21 01:25:48 +00:00
q3cface_t * map_faces ;
2011-12-05 15:23:40 +00:00
static int numfaces ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static index_t * map_surfindexes ;
static int map_numsurfindexes ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int * map_leaffaces ;
static int numleaffaces ;
2004-08-21 01:25:48 +00:00
int PlaneTypeForNormal ( vec3_t normal )
{
vec_t ax , ay , az ;
2006-03-04 20:43:48 +00:00
// NOTE: should these have an epsilon around 1.0?
2004-08-21 01:25:48 +00:00
if ( normal [ 0 ] > = 1.0 )
return PLANE_X ;
if ( normal [ 1 ] > = 1.0 )
return PLANE_Y ;
if ( normal [ 2 ] > = 1.0 )
return PLANE_Z ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
ax = fabs ( normal [ 0 ] ) ;
ay = fabs ( normal [ 1 ] ) ;
az = fabs ( normal [ 2 ] ) ;
if ( ax > = ay & & ax > = az )
return PLANE_ANYX ;
if ( ay > = ax & & ay > = az )
return PLANE_ANYY ;
return PLANE_ANYZ ;
}
void CategorizePlane ( mplane_t * plane )
{
int i ;
plane - > signbits = 0 ;
plane - > type = PLANE_ANYZ ;
for ( i = 0 ; i < 3 ; i + + )
{
if ( plane - > normal [ i ] < 0 )
plane - > signbits | = 1 < < i ;
if ( plane - > normal [ i ] = = 1.0f )
plane - > type = i ;
}
plane - > type = PlaneTypeForNormal ( plane - > normal ) ;
}
void PlaneFromPoints ( vec3_t verts [ 3 ] , mplane_t * plane )
{
vec3_t v1 , v2 ;
VectorSubtract ( verts [ 1 ] , verts [ 0 ] , v1 ) ;
VectorSubtract ( verts [ 2 ] , verts [ 0 ] , v2 ) ;
CrossProduct ( v2 , v1 , plane - > normal ) ;
VectorNormalize ( plane - > normal ) ;
plane - > dist = DotProduct ( verts [ 0 ] , plane - > normal ) ;
}
qboolean BoundsIntersect ( vec3_t mins1 , vec3_t maxs1 , vec3_t mins2 , vec3_t maxs2 )
{
return ( mins1 [ 0 ] < = maxs2 [ 0 ] & & mins1 [ 1 ] < = maxs2 [ 1 ] & & mins1 [ 2 ] < = maxs2 [ 2 ] & &
maxs1 [ 0 ] > = mins2 [ 0 ] & & maxs1 [ 1 ] > = mins2 [ 1 ] & & maxs1 [ 2 ] > = mins2 [ 2 ] ) ;
}
/*
= = = = = = = = = = = = = = =
Patch_FlatnessTest
= = = = = = = = = = = = = = =
*/
2010-03-14 14:35:56 +00:00
static int Patch_FlatnessTest ( float maxflat2 , const float * point0 , const float * point1 , const float * point2 )
2004-08-21 01:25:48 +00:00
{
2010-03-14 14:35:56 +00:00
float d ;
2004-08-21 01:25:48 +00:00
int ft0 , ft1 ;
2010-03-14 14:35:56 +00:00
vec3_t t , n ;
vec3_t v1 , v2 , v3 ;
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
VectorSubtract ( point2 , point0 , n ) ;
if ( ! VectorNormalize ( n ) )
2004-08-21 01:25:48 +00:00
return 0 ;
2010-03-14 14:35:56 +00:00
VectorSubtract ( point1 , point0 , t ) ;
d = - DotProduct ( t , n ) ;
VectorMA ( t , d , n , t ) ;
if ( DotProduct ( t , t ) < maxflat2 )
2004-08-21 01:25:48 +00:00
return 0 ;
2010-03-14 14:35:56 +00:00
VectorAvg ( point1 , point0 , v1 ) ;
VectorAvg ( point2 , point1 , v2 ) ;
VectorAvg ( v1 , v2 , v3 ) ;
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
ft0 = Patch_FlatnessTest ( maxflat2 , point0 , v1 , v3 ) ;
ft1 = Patch_FlatnessTest ( maxflat2 , v3 , v2 , point2 ) ;
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
return 1 + ( int ) ( floor ( max ( ft0 , ft1 ) ) + 0.5f ) ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = =
Patch_GetFlatness
= = = = = = = = = = = = = = =
*/
2010-03-14 14:35:56 +00:00
void Patch_GetFlatness ( float maxflat , const float * points , int comp , const int * patch_cp , int * flat )
2004-08-21 01:25:48 +00:00
{
int i , p , u , v ;
2010-03-14 14:35:56 +00:00
float maxflat2 = maxflat * maxflat ;
2004-08-21 01:25:48 +00:00
flat [ 0 ] = flat [ 1 ] = 0 ;
2010-03-14 14:35:56 +00:00
for ( v = 0 ; v < patch_cp [ 1 ] - 1 ; v + = 2 )
2004-08-21 01:25:48 +00:00
{
2010-03-14 14:35:56 +00:00
for ( u = 0 ; u < patch_cp [ 0 ] - 1 ; u + = 2 )
2004-08-21 01:25:48 +00:00
{
p = v * patch_cp [ 0 ] + u ;
2010-03-14 14:35:56 +00:00
i = Patch_FlatnessTest ( maxflat2 , & points [ p * comp ] , & points [ ( p + 1 ) * comp ] , & points [ ( p + 2 ) * comp ] ) ;
flat [ 0 ] = max ( flat [ 0 ] , i ) ;
i = Patch_FlatnessTest ( maxflat2 , & points [ ( p + patch_cp [ 0 ] ) * comp ] , & points [ ( p + patch_cp [ 0 ] + 1 ) * comp ] , & points [ ( p + patch_cp [ 0 ] + 2 ) * comp ] ) ;
flat [ 0 ] = max ( flat [ 0 ] , i ) ;
i = Patch_FlatnessTest ( maxflat2 , & points [ ( p + 2 * patch_cp [ 0 ] ) * comp ] , & points [ ( p + 2 * patch_cp [ 0 ] + 1 ) * comp ] , & points [ ( p + 2 * patch_cp [ 0 ] + 2 ) * comp ] ) ;
flat [ 0 ] = max ( flat [ 0 ] , i ) ;
i = Patch_FlatnessTest ( maxflat2 , & points [ p * comp ] , & points [ ( p + patch_cp [ 0 ] ) * comp ] , & points [ ( p + 2 * patch_cp [ 0 ] ) * comp ] ) ;
flat [ 1 ] = max ( flat [ 1 ] , i ) ;
i = Patch_FlatnessTest ( maxflat2 , & points [ ( p + 1 ) * comp ] , & points [ ( p + patch_cp [ 0 ] + 1 ) * comp ] , & points [ ( p + 2 * patch_cp [ 0 ] + 1 ) * comp ] ) ;
flat [ 1 ] = max ( flat [ 1 ] , i ) ;
i = Patch_FlatnessTest ( maxflat2 , & points [ ( p + 2 ) * comp ] , & points [ ( p + patch_cp [ 0 ] + 2 ) * comp ] , & points [ ( p + 2 * patch_cp [ 0 ] + 2 ) * comp ] ) ;
flat [ 1 ] = max ( flat [ 1 ] , i ) ;
2004-08-21 01:25:48 +00:00
}
}
}
/*
= = = = = = = = = = = = = = =
Patch_Evaluate_QuadricBezier
= = = = = = = = = = = = = = =
*/
2010-03-14 14:35:56 +00:00
static void Patch_Evaluate_QuadricBezier ( float t , const vec_t * point0 , const vec_t * point1 , const vec_t * point2 , vec_t * out , int comp )
2004-08-21 01:25:48 +00:00
{
2010-03-14 14:35:56 +00:00
int i ;
vec_t qt = t * t ;
vec_t dt = 2.0f * t , tt , tt2 ;
2004-08-21 01:25:48 +00:00
tt = 1.0f - dt + qt ;
2010-03-14 14:35:56 +00:00
tt2 = dt - 2.0f * qt ;
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
for ( i = 0 ; i < comp ; i + + )
out [ i ] = point0 [ i ] * tt + point1 [ i ] * tt2 + point2 [ i ] * qt ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = =
Patch_Evaluate
= = = = = = = = = = = = = = =
*/
2010-03-14 14:35:56 +00:00
void Patch_Evaluate ( const vec_t * p , const int * numcp , const int * tess , vec_t * dest , int comp )
2004-08-21 01:25:48 +00:00
{
int num_patches [ 2 ] , num_tess [ 2 ] ;
int index [ 3 ] , dstpitch , i , u , v , x , y ;
float s , t , step [ 2 ] ;
2010-03-14 14:35:56 +00:00
vec_t * tvec , * tvec2 ;
const vec_t * pv [ 3 ] [ 3 ] ;
vec4_t v1 , v2 , v3 ;
2004-08-21 01:25:48 +00:00
num_patches [ 0 ] = numcp [ 0 ] / 2 ;
num_patches [ 1 ] = numcp [ 1 ] / 2 ;
2010-03-14 14:35:56 +00:00
dstpitch = ( num_patches [ 0 ] * tess [ 0 ] + 1 ) * comp ;
2004-08-21 01:25:48 +00:00
step [ 0 ] = 1.0f / ( float ) tess [ 0 ] ;
step [ 1 ] = 1.0f / ( float ) tess [ 1 ] ;
2010-03-14 14:35:56 +00:00
for ( v = 0 ; v < num_patches [ 1 ] ; v + + )
2004-08-21 01:25:48 +00:00
{
2006-03-04 20:43:48 +00:00
// last patch has one more row
2010-03-14 14:35:56 +00:00
if ( v < num_patches [ 1 ] - 1 )
2004-08-21 01:25:48 +00:00
num_tess [ 1 ] = tess [ 1 ] ;
2010-03-14 14:35:56 +00:00
else
2004-08-21 01:25:48 +00:00
num_tess [ 1 ] = tess [ 1 ] + 1 ;
2010-03-14 14:35:56 +00:00
for ( u = 0 ; u < num_patches [ 0 ] ; u + + )
2004-08-21 01:25:48 +00:00
{
// last patch has one more column
2010-03-14 14:35:56 +00:00
if ( u < num_patches [ 0 ] - 1 )
2004-08-21 01:25:48 +00:00
num_tess [ 0 ] = tess [ 0 ] ;
2010-03-14 14:35:56 +00:00
else
2004-08-21 01:25:48 +00:00
num_tess [ 0 ] = tess [ 0 ] + 1 ;
2010-03-14 14:35:56 +00:00
index [ 0 ] = ( v * numcp [ 0 ] + u ) * 2 ;
2004-08-21 01:25:48 +00:00
index [ 1 ] = index [ 0 ] + numcp [ 0 ] ;
index [ 2 ] = index [ 1 ] + numcp [ 0 ] ;
// current 3x3 patch control points
2010-03-14 14:35:56 +00:00
for ( i = 0 ; i < 3 ; i + + )
2004-08-21 01:25:48 +00:00
{
2010-03-14 14:35:56 +00:00
pv [ i ] [ 0 ] = & p [ ( index [ 0 ] + i ) * comp ] ;
pv [ i ] [ 1 ] = & p [ ( index [ 1 ] + i ) * comp ] ;
pv [ i ] [ 2 ] = & p [ ( index [ 2 ] + i ) * comp ] ;
2004-08-21 01:25:48 +00:00
}
2006-03-04 20:43:48 +00:00
2010-03-14 14:35:56 +00:00
tvec = dest + v * tess [ 1 ] * dstpitch + u * tess [ 0 ] * comp ;
for ( y = 0 , t = 0.0f ; y < num_tess [ 1 ] ; y + + , t + = step [ 1 ] , tvec + = dstpitch )
2004-08-21 01:25:48 +00:00
{
2010-03-14 14:35:56 +00:00
Patch_Evaluate_QuadricBezier ( t , pv [ 0 ] [ 0 ] , pv [ 0 ] [ 1 ] , pv [ 0 ] [ 2 ] , v1 , comp ) ;
Patch_Evaluate_QuadricBezier ( t , pv [ 1 ] [ 0 ] , pv [ 1 ] [ 1 ] , pv [ 1 ] [ 2 ] , v2 , comp ) ;
Patch_Evaluate_QuadricBezier ( t , pv [ 2 ] [ 0 ] , pv [ 2 ] [ 1 ] , pv [ 2 ] [ 2 ] , v3 , comp ) ;
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
for ( x = 0 , tvec2 = tvec , s = 0.0f ; x < num_tess [ 0 ] ; x + + , s + = step [ 0 ] , tvec2 + = comp )
Patch_Evaluate_QuadricBezier ( s , v1 , v2 , v3 , tvec2 , comp ) ;
2004-08-21 01:25:48 +00:00
}
}
}
}
2010-03-14 14:35:56 +00:00
# define PLANE_NORMAL_EPSILON 0.00001
# define PLANE_DIST_EPSILON 0.01
static qboolean ComparePlanes ( const vec3_t p1normal , vec_t p1dist , const vec3_t p2normal , vec_t p2dist )
{
if ( fabs ( p1normal [ 0 ] - p2normal [ 0 ] ) < PLANE_NORMAL_EPSILON
& & fabs ( p1normal [ 1 ] - p2normal [ 1 ] ) < PLANE_NORMAL_EPSILON
& & fabs ( p1normal [ 2 ] - p2normal [ 2 ] ) < PLANE_NORMAL_EPSILON
& & fabs ( p1dist - p2dist ) < PLANE_DIST_EPSILON )
return true ;
return false ;
}
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
static void SnapVector ( vec3_t normal )
{
int i ;
for ( i = 0 ; i < 3 ; i + + )
{
if ( fabs ( normal [ i ] - 1 ) < PLANE_NORMAL_EPSILON )
{
VectorClear ( normal ) ;
normal [ i ] = 1 ;
break ;
}
if ( fabs ( normal [ i ] - - 1 ) < PLANE_NORMAL_EPSILON )
{
VectorClear ( normal ) ;
normal [ i ] = - 1 ;
break ;
}
}
}
# define Q_rint( x ) ( ( x ) < 0 ? ( (int)( ( x )-0.5f ) ) : ( (int)( ( x )+0.5f ) ) )
static void SnapPlane ( vec3_t normal , vec_t * dist )
{
SnapVector ( normal ) ;
if ( fabs ( * dist - Q_rint ( * dist ) ) < PLANE_DIST_EPSILON )
{
* dist = Q_rint ( * dist ) ;
}
}
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
PATCH LOADING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2010-03-14 14:35:56 +00:00
# define MAX_FACET_PLANES 32
# define cm_subdivlevel 15
/*
* CM_CreateFacetFromPoints
*/
static int CM_CreateFacetFromPoints ( q2cbrush_t * facet , vec3_t * verts , int numverts , q2mapsurface_t * shaderref , mplane_t * brushplanes )
{
2013-05-11 05:03:07 +00:00
int i , j ;
2010-03-14 14:35:56 +00:00
int axis , dir ;
vec3_t normal , mins , maxs ;
float d , dist ;
mplane_t mainplane ;
vec3_t vec , vec2 ;
int numbrushplanes ;
// set default values for brush
facet - > numsides = 0 ;
facet - > brushside = NULL ;
facet - > contents = shaderref - > c . value ;
// calculate plane for this triangle
PlaneFromPoints ( verts , & mainplane ) ;
if ( ComparePlanes ( mainplane . normal , mainplane . dist , vec3_origin , 0 ) )
return 0 ;
// test a quad case
if ( numverts > 3 )
{
d = DotProduct ( verts [ 3 ] , mainplane . normal ) - mainplane . dist ;
if ( d < - 0.1 | | d > 0.1 )
return 0 ;
if ( 0 )
{
vec3_t v [ 3 ] ;
mplane_t plane ;
// try different combinations of planes
for ( i = 1 ; i < 4 ; i + + )
{
VectorCopy ( verts [ i ] , v [ 0 ] ) ;
VectorCopy ( verts [ ( i + 1 ) % 4 ] , v [ 1 ] ) ;
VectorCopy ( verts [ ( i + 2 ) % 4 ] , v [ 2 ] ) ;
PlaneFromPoints ( v , & plane ) ;
if ( fabs ( DotProduct ( mainplane . normal , plane . normal ) ) < 0.9 )
return 0 ;
}
}
}
numbrushplanes = 0 ;
// add front plane
SnapPlane ( mainplane . normal , & mainplane . dist ) ;
VectorCopy ( mainplane . normal , brushplanes [ numbrushplanes ] . normal ) ;
brushplanes [ numbrushplanes ] . dist = mainplane . dist ; numbrushplanes + + ;
// calculate mins & maxs
ClearBounds ( mins , maxs ) ;
for ( i = 0 ; i < numverts ; i + + )
AddPointToBounds ( verts [ i ] , mins , maxs ) ;
// add the axial planes
for ( axis = 0 ; axis < 3 ; axis + + )
{
for ( dir = - 1 ; dir < = 1 ; dir + = 2 )
{
for ( i = 0 ; i < numbrushplanes ; i + + )
{
if ( brushplanes [ i ] . normal [ axis ] = = dir )
break ;
}
if ( i = = numbrushplanes )
{
VectorClear ( normal ) ;
normal [ axis ] = dir ;
if ( dir = = 1 )
dist = maxs [ axis ] ;
else
dist = - mins [ axis ] ;
VectorCopy ( normal , brushplanes [ numbrushplanes ] . normal ) ;
brushplanes [ numbrushplanes ] . dist = dist ; numbrushplanes + + ;
}
}
}
// add the edge bevels
for ( i = 0 ; i < numverts ; i + + )
{
j = ( i + 1 ) % numverts ;
2013-05-11 05:03:07 +00:00
// k = ( i + 2 ) % numverts;
2010-03-14 14:35:56 +00:00
VectorSubtract ( verts [ i ] , verts [ j ] , vec ) ;
if ( VectorNormalize ( vec ) < 0.5 )
continue ;
SnapVector ( vec ) ;
for ( j = 0 ; j < 3 ; j + + )
{
if ( vec [ j ] = = 1 | | vec [ j ] = = - 1 )
break ; // axial
}
if ( j ! = 3 )
continue ; // only test non-axial edges
// try the six possible slanted axials from this edge
for ( axis = 0 ; axis < 3 ; axis + + )
{
for ( dir = - 1 ; dir < = 1 ; dir + = 2 )
{
// construct a plane
VectorClear ( vec2 ) ;
vec2 [ axis ] = dir ;
CrossProduct ( vec , vec2 , normal ) ;
if ( VectorNormalize ( normal ) < 0.5 )
continue ;
dist = DotProduct ( verts [ i ] , normal ) ;
for ( j = 0 ; j < numbrushplanes ; j + + )
{
// if this plane has already been used, skip it
if ( ComparePlanes ( brushplanes [ j ] . normal , brushplanes [ j ] . dist , normal , dist ) )
break ;
}
if ( j ! = numbrushplanes )
continue ;
// if all other points are behind this plane, it is a proper edge bevel
for ( j = 0 ; j < numverts ; j + + )
{
if ( j ! = i )
{
d = DotProduct ( verts [ j ] , normal ) - dist ;
if ( d > 0.1 )
break ; // point in front: this plane isn't part of the outer hull
}
}
if ( j ! = numverts )
continue ;
// add this plane
VectorCopy ( normal , brushplanes [ numbrushplanes ] . normal ) ;
brushplanes [ numbrushplanes ] . dist = dist ; numbrushplanes + + ;
if ( numbrushplanes = = MAX_FACET_PLANES )
break ;
}
}
}
return ( facet - > numsides = numbrushplanes ) ;
}
/*
* CM_CreatePatch
*/
2010-05-01 22:47:47 +00:00
static void CM_CreatePatch ( q3cpatch_t * patch , q2mapsurface_t * shaderref , const vec_t * verts , const int * patch_cp )
2010-03-14 14:35:56 +00:00
{
int step [ 2 ] , size [ 2 ] , flat [ 2 ] ;
int i , j , k , u , v ;
int numsides , totalsides ;
q2cbrush_t * facets , * facet ;
2010-05-01 22:47:47 +00:00
vecV_t * points ;
2010-03-14 14:35:56 +00:00
vec3_t tverts [ 4 ] ;
qbyte * data ;
mplane_t * brushplanes ;
2010-05-01 22:47:47 +00:00
patch - > surface = shaderref ;
2010-03-14 14:35:56 +00:00
// find the degree of subdivision in the u and v directions
2010-05-01 22:47:47 +00:00
Patch_GetFlatness ( cm_subdivlevel , verts , sizeof ( vecV_t ) / sizeof ( vec_t ) , patch_cp , flat ) ;
2010-03-14 14:35:56 +00:00
step [ 0 ] = 1 < < flat [ 0 ] ;
step [ 1 ] = 1 < < flat [ 1 ] ;
size [ 0 ] = ( patch_cp [ 0 ] > > 1 ) * step [ 0 ] + 1 ;
size [ 1 ] = ( patch_cp [ 1 ] > > 1 ) * step [ 1 ] + 1 ;
if ( size [ 0 ] < = 0 | | size [ 1 ] < = 0 )
return ;
2011-05-15 13:23:13 +00:00
data = BZ_Malloc ( size [ 0 ] * size [ 1 ] * sizeof ( vecV_t ) +
2010-03-14 14:35:56 +00:00
( size [ 0 ] - 1 ) * ( size [ 1 ] - 1 ) * 2 * ( sizeof ( q2cbrush_t ) + 32 * sizeof ( mplane_t ) ) ) ;
2010-07-11 02:22:39 +00:00
points = ( vecV_t * ) data ; data + = size [ 0 ] * size [ 1 ] * sizeof ( vecV_t ) ;
2010-03-14 14:35:56 +00:00
facets = ( q2cbrush_t * ) data ; data + = ( size [ 0 ] - 1 ) * ( size [ 1 ] - 1 ) * 2 * sizeof ( q2cbrush_t ) ;
brushplanes = ( mplane_t * ) data ; data + = ( size [ 0 ] - 1 ) * ( size [ 1 ] - 1 ) * 2 * MAX_FACET_PLANES * sizeof ( mplane_t ) ;
// fill in
2010-05-01 22:47:47 +00:00
Patch_Evaluate ( verts , patch_cp , step , points [ 0 ] , sizeof ( vecV_t ) / sizeof ( vec_t ) ) ;
2010-03-14 14:35:56 +00:00
totalsides = 0 ;
patch - > numfacets = 0 ;
patch - > facets = NULL ;
ClearBounds ( patch - > absmins , patch - > absmaxs ) ;
// create a set of facets
for ( v = 0 ; v < size [ 1 ] - 1 ; v + + )
{
for ( u = 0 ; u < size [ 0 ] - 1 ; u + + )
{
i = v * size [ 0 ] + u ;
VectorCopy ( points [ i ] , tverts [ 0 ] ) ;
VectorCopy ( points [ i + size [ 0 ] ] , tverts [ 1 ] ) ;
VectorCopy ( points [ i + size [ 0 ] + 1 ] , tverts [ 2 ] ) ;
VectorCopy ( points [ i + 1 ] , tverts [ 3 ] ) ;
for ( i = 0 ; i < 4 ; i + + )
AddPointToBounds ( tverts [ i ] , patch - > absmins , patch - > absmaxs ) ;
// try to create one facet from a quad
numsides = CM_CreateFacetFromPoints ( & facets [ patch - > numfacets ] , tverts , 4 , shaderref , brushplanes + totalsides ) ;
if ( ! numsides )
{ // create two facets from triangles
VectorCopy ( tverts [ 3 ] , tverts [ 2 ] ) ;
numsides = CM_CreateFacetFromPoints ( & facets [ patch - > numfacets ] , tverts , 3 , shaderref , brushplanes + totalsides ) ;
if ( numsides )
{
totalsides + = numsides ;
patch - > numfacets + + ;
}
VectorCopy ( tverts [ 2 ] , tverts [ 0 ] ) ;
VectorCopy ( points [ v * size [ 0 ] + u + size [ 0 ] + 1 ] , tverts [ 2 ] ) ;
numsides = CM_CreateFacetFromPoints ( & facets [ patch - > numfacets ] , tverts , 3 , shaderref , brushplanes + totalsides ) ;
}
if ( numsides )
{
totalsides + = numsides ;
patch - > numfacets + + ;
}
}
}
2010-05-01 22:47:47 +00:00
if ( patch - > numfacets )
2010-03-14 14:35:56 +00:00
{
qbyte * data ;
2012-07-23 03:42:46 +00:00
data = Hunk_AllocName ( patch - > numfacets * sizeof ( q2cbrush_t ) + totalsides * ( sizeof ( q2cbrushside_t ) + sizeof ( mplane_t ) ) , " patch " ) ;
2010-03-14 14:35:56 +00:00
patch - > facets = ( q2cbrush_t * ) data ; data + = patch - > numfacets * sizeof ( q2cbrush_t ) ;
memcpy ( patch - > facets , facets , patch - > numfacets * sizeof ( q2cbrush_t ) ) ;
for ( i = 0 , k = 0 , facet = patch - > facets ; i < patch - > numfacets ; i + + , facet + + )
{
mplane_t * planes ;
q2cbrushside_t * s ;
facet - > brushside = ( q2cbrushside_t * ) data ; data + = facet - > numsides * sizeof ( q2cbrushside_t ) ;
planes = ( mplane_t * ) data ; data + = facet - > numsides * sizeof ( mplane_t ) ;
for ( j = 0 , s = facet - > brushside ; j < facet - > numsides ; j + + , s + + )
{
planes [ j ] = brushplanes [ k + + ] ;
s - > plane = & planes [ j ] ;
SnapPlane ( s - > plane - > normal , & s - > plane - > dist ) ;
CategorizePlane ( s - > plane ) ;
s - > surface = shaderref ;
}
}
for ( i = 0 ; i < 3 ; i + + )
{
// spread the mins / maxs by a pixel
patch - > absmins [ i ] - = 1 ;
patch - > absmaxs [ i ] + = 1 ;
}
}
BZ_Free ( points ) ;
}
2004-08-21 01:25:48 +00:00
//======================================================
/*
= = = = = = = = = = = = = = = = =
CM_CreatePatchesForLeafs
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CM_CreatePatchesForLeafs ( void )
2004-08-21 01:25:48 +00:00
{
int i , j , k ;
mleaf_t * leaf ;
q3cface_t * face ;
q2mapsurface_t * surf ;
q3cpatch_t * patch ;
int checkout [ MAX_CM_FACES ] ;
2010-03-14 14:35:56 +00:00
if ( map_noCurves . ival )
return true ;
2004-08-21 01:25:48 +00:00
memset ( checkout , - 1 , sizeof ( int ) * MAX_CM_FACES ) ;
for ( i = 0 , leaf = map_leafs ; i < numleafs ; i + + , leaf + + )
{
leaf - > numleafpatches = 0 ;
leaf - > firstleafpatch = numleafpatches ;
2010-03-14 14:35:56 +00:00
if ( leaf - > cluster = = - 1 )
2004-08-21 01:25:48 +00:00
continue ;
for ( j = 0 ; j < leaf - > numleaffaces ; j + + )
{
k = leaf - > firstleafface + j ;
if ( k > = numleaffaces ) {
break ;
}
k = map_leaffaces [ k ] ;
face = & map_faces [ k ] ;
if ( face - > facetype ! = MST_PATCH | | face - > numverts < = 0 )
continue ;
if ( face - > patch_cp [ 0 ] < = 0 | | face - > patch_cp [ 1 ] < = 0 )
continue ;
2010-07-11 02:22:39 +00:00
if ( face - > shadernum < 0 | | face - > shadernum > = loadmodel - > numtextures )
2004-08-21 01:25:48 +00:00
continue ;
surf = & map_surfaces [ face - > shadernum ] ;
if ( ! surf - > c . value | | ( surf - > c . flags & Q3SURF_NONSOLID ) )
continue ;
if ( numleafpatches > = MAX_CM_LEAFFACES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " CM_CreatePatchesForLeafs: map has too many faces \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
// the patch was already built
if ( checkout [ k ] ! = - 1 )
{
map_leafpatches [ numleafpatches ] = checkout [ k ] ;
patch = & map_patches [ checkout [ k ] ] ;
}
else
{
if ( numpatches > = MAX_CM_PATCHES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " CM_CreatePatchesForLeafs: map has too many patches \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
patch = & map_patches [ numpatches ] ;
map_leafpatches [ numleafpatches ] = numpatches ;
checkout [ k ] = numpatches + + ;
2006-03-04 20:43:48 +00:00
//gcc warns without this cast
2010-07-11 02:22:39 +00:00
CM_CreatePatch ( patch , surf , ( const vec_t * ) ( map_verts + face - > firstvert ) , face - > patch_cp ) ;
2004-08-21 01:25:48 +00:00
}
leaf - > contents | = patch - > surface - > c . value ;
leaf - > numleafpatches + + ;
numleafpatches + + ;
}
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
MAP LOADING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
qbyte * cmod_base ;
/*
= = = = = = = = = = = = = = = = =
CMod_LoadSubmodels
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadSubmodels ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q2dmodel_t * in ;
2011-12-05 15:23:40 +00:00
cmodel_t * out ;
2004-08-21 01:25:48 +00:00
int i , j , count ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no models \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
if ( count > MAX_Q2MAP_MODELS )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many models \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
numcmodels = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out = & map_cmodels [ i ] ;
for ( j = 0 ; j < 3 ; j + + )
{ // spread the mins / maxs by a pixel
out - > mins [ j ] = LittleFloat ( in - > mins [ j ] ) - 1 ;
out - > maxs [ j ] = LittleFloat ( in - > maxs [ j ] ) + 1 ;
out - > origin [ j ] = LittleFloat ( in - > origin [ j ] ) ;
}
out - > headnode = LittleLong ( in - > headnode ) ;
out - > firstsurface = LittleLong ( in - > firstface ) ;
out - > numsurfaces = LittleLong ( in - > numfaces ) ;
}
2006-03-13 05:54:12 +00:00
2013-03-12 23:12:30 +00:00
VectorCopy ( map_cmodels [ 0 ] . mins , loadmodel - > mins ) ;
VectorCopy ( map_cmodels [ 0 ] . maxs , loadmodel - > maxs ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadSurfaces
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadSurfaces ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q2texinfo_t * in ;
q2mapsurface_t * out ;
int i , count ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no surfaces \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-07-14 01:57:34 +00:00
// if (count > MAX_Q2MAP_TEXINFO)
// Host_Error ("Map has too many surfaces");
2004-08-21 01:25:48 +00:00
numtexinfo = count ;
2012-07-23 03:42:46 +00:00
out = map_surfaces = Hunk_AllocName ( count * sizeof ( * map_surfaces ) , " surfaces " ) ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
Q_strncpyz ( out - > c . name , in - > texture , sizeof ( out - > c . name ) ) ;
Q_strncpyz ( out - > rname , in - > texture , sizeof ( out - > rname ) ) ;
out - > c . flags = LittleLong ( in - > flags ) ;
out - > c . value = LittleLong ( in - > value ) ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
# ifndef SERVERONLY
2010-07-11 02:22:39 +00:00
texture_t * Mod_LoadWall ( char * name , char * sname )
2004-08-21 01:25:48 +00:00
{
2011-03-02 03:43:38 +00:00
q2miptex_t replacementwal ;
2004-08-21 01:25:48 +00:00
qbyte * in , * oin ;
texture_t * tex ;
q2miptex_t * wal ;
2009-11-04 21:16:50 +00:00
int j ;
2004-08-21 01:25:48 +00:00
char ln [ 32 ] ;
2009-11-04 21:16:50 +00:00
texnums_t tn ;
memset ( & tn , 0 , sizeof ( tn ) ) ;
2004-08-21 01:25:48 +00:00
2006-03-11 03:12:10 +00:00
COM_FileBase ( name , ln , sizeof ( ln ) ) ;
2004-08-21 01:25:48 +00:00
2009-11-04 21:16:50 +00:00
wal = ( void * ) FS_LoadMallocFile ( name ) ;
2004-08-21 01:25:48 +00:00
if ( ! wal )
2008-11-09 22:29:28 +00:00
{
2011-03-02 03:43:38 +00:00
tn . base = R_LoadReplacementTexture ( name , loadname , 0 ) ;
wal = & replacementwal ;
memset ( wal , 0 , sizeof ( * wal ) ) ;
Q_strncpyz ( wal - > name , name , sizeof ( wal - > name ) ) ;
wal - > width = image_width ;
wal - > height = image_height ;
2008-11-09 22:29:28 +00:00
}
2011-03-02 03:43:38 +00:00
else
tn . base = R_LoadReplacementTexture ( wal - > name , loadname , IF_NOALPHA ) ;
2004-08-21 01:25:48 +00:00
2005-05-18 23:52:55 +00:00
wal - > width = LittleLong ( wal - > width ) ;
wal - > height = LittleLong ( wal - > height ) ;
{
int i ;
for ( i = 0 ; i < MIPLEVELS ; i + + )
wal - > offsets [ i ] = LittleLong ( wal - > offsets [ i ] ) ;
}
wal - > flags = LittleLong ( wal - > flags ) ;
wal - > contents = LittleLong ( wal - > contents ) ;
wal - > value = LittleLong ( wal - > value ) ;
2009-11-04 21:16:50 +00:00
tex = Hunk_AllocName ( sizeof ( texture_t ) , ln ) ;
2004-08-21 01:25:48 +00:00
2009-11-04 21:16:50 +00:00
tex - > offsets [ 0 ] = wal - > offsets [ 0 ] ;
tex - > width = wal - > width ;
tex - > height = wal - > height ;
2004-08-21 01:25:48 +00:00
2009-11-04 21:16:50 +00:00
if ( ! TEXVALID ( tn . base ) )
2004-08-21 01:25:48 +00:00
{
2009-11-04 21:16:50 +00:00
tn . base = R_LoadReplacementTexture ( wal - > name , " bmodels " , IF_NOALPHA ) ;
if ( ! TEXVALID ( tn . base ) )
2011-03-02 03:43:38 +00:00
{
if ( ! wal - > offsets [ 0 ] )
{
//they will download eventually...
CL_CheckOrEnqueDownloadFile ( name , NULL , 0 ) ;
return NULL ;
}
2009-11-04 21:16:50 +00:00
tn . base = R_LoadTexture8Pal24 ( wal - > name , tex - > width , tex - > height , ( qbyte * ) wal + wal - > offsets [ 0 ] , d_q28to24table , IF_NOALPHA | IF_NOGAMMA ) ;
2011-03-02 03:43:38 +00:00
}
2004-08-21 01:25:48 +00:00
}
2011-03-02 03:43:38 +00:00
if ( wal - > offsets [ 0 ] )
{
in = Hunk_TempAllocMore ( wal - > width * wal - > height ) ;
oin = ( qbyte * ) wal + wal - > offsets [ 0 ] ;
for ( j = 0 ; j < wal - > width * wal - > height ; j + + )
in [ j ] = ( d_q28to24table [ oin [ j ] * 3 + 0 ] + d_q28to24table [ oin [ j ] * 3 + 1 ] + d_q28to24table [ oin [ j ] * 3 + 2 ] ) / 3 ;
tn . bump = R_LoadTexture8BumpPal ( va ( " %s_bump " , wal - > name ) , tex - > width , tex - > height , in , true ) ;
}
2009-11-04 21:16:50 +00:00
2011-03-02 03:43:38 +00:00
if ( wal ! = & replacementwal )
BZ_Free ( wal ) ;
2004-08-21 01:25:48 +00:00
2010-07-11 02:22:39 +00:00
tex - > shader = R_RegisterCustom ( sname , Shader_DefaultBSPQ2 , NULL ) ;
2009-11-04 21:16:50 +00:00
R_BuildDefaultTexnums ( & tn , tex - > shader ) ;
2004-08-21 01:25:48 +00:00
return tex ;
}
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadTexInfo ( lump_t * l ) //yes I know these load from the same place
2004-08-21 01:25:48 +00:00
{
q2texinfo_t * in ;
mtexinfo_t * out ;
int i , j , count ;
2005-03-24 17:17:59 +00:00
char name [ MAX_QPATH ] , * lwr ;
2010-07-11 02:22:39 +00:00
char sname [ MAX_QPATH ] ;
2004-08-21 01:25:48 +00:00
float len1 , len2 ;
int texcount ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
Con_Printf ( " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_AllocName ( count * sizeof ( * out ) , loadname ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
loadmodel - > textures = Hunk_AllocName ( sizeof ( texture_t * ) * count , loadname ) ;
texcount = 0 ;
loadmodel - > texinfo = out ;
loadmodel - > numtexinfo = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out - > flags = LittleLong ( in - > flags ) ;
2013-03-12 22:47:42 +00:00
for ( j = 0 ; j < 4 ; j + + )
2004-08-21 01:25:48 +00:00
out - > vecs [ 0 ] [ j ] = LittleFloat ( in - > vecs [ 0 ] [ j ] ) ;
2013-03-12 22:47:42 +00:00
for ( j = 0 ; j < 4 ; j + + )
out - > vecs [ 1 ] [ j ] = LittleFloat ( in - > vecs [ 1 ] [ j ] ) ;
2004-08-21 01:25:48 +00:00
len1 = Length ( out - > vecs [ 0 ] ) ;
len2 = Length ( out - > vecs [ 1 ] ) ;
len1 = ( len1 + len2 ) / 2 ;
if ( len1 < 0.32 )
out - > mipadjust = 4 ;
else if ( len1 < 0.49 )
out - > mipadjust = 3 ;
else if ( len1 < 0.99 )
out - > mipadjust = 2 ;
else
out - > mipadjust = 1 ;
2010-07-11 02:22:39 +00:00
if ( out - > flags & TI_SKY )
snprintf ( sname , sizeof ( sname ) , " sky/%s " , in - > texture ) ;
else if ( out - > flags & ( TI_WARP | TI_TRANS33 | TI_TRANS66 ) )
2013-03-12 23:13:39 +00:00
snprintf ( sname , sizeof ( sname ) , " %s/%s#ALPHA=%s " , ( ( out - > flags & TI_WARP ) ? " warp " : " trans " ) , in - > texture , ( ( out - > flags & TI_TRANS66 ) ? " 0.66 " : ( out - > flags & TI_TRANS33 ? " 0.33 " : " 1 " ) ) ) ;
2010-07-11 02:22:39 +00:00
else
snprintf ( sname , sizeof ( sname ) , " wall/%s " , in - > texture ) ;
//compact the textures.
2004-08-21 01:25:48 +00:00
for ( j = 0 ; j < texcount ; j + + )
{
2010-07-11 02:22:39 +00:00
if ( ! strcmp ( sname , loadmodel - > textures [ j ] - > name ) )
2004-08-21 01:25:48 +00:00
{
out - > texture = loadmodel - > textures [ j ] ;
break ;
}
}
if ( j = = texcount ) //load a new one
{
2005-03-24 17:17:59 +00:00
for ( lwr = in - > texture ; * lwr ; lwr + + )
{
2005-03-28 00:11:59 +00:00
if ( * lwr > = ' A ' & & * lwr < = ' Z ' )
2005-03-24 17:17:59 +00:00
* lwr = * lwr - ' A ' + ' a ' ;
}
2006-03-06 01:41:09 +00:00
snprintf ( name , sizeof ( name ) , " textures/%s.wal " , in - > texture ) ;
2004-08-21 01:25:48 +00:00
2010-07-11 02:22:39 +00:00
out - > texture = Mod_LoadWall ( name , sname ) ;
2004-12-24 08:45:56 +00:00
if ( ! out - > texture | | ! out - > texture - > width | | ! out - > texture - > height )
2004-08-21 01:25:48 +00:00
{
2012-07-23 03:42:46 +00:00
out - > texture = Hunk_AllocName ( sizeof ( texture_t ) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2 , in - > texture ) ;
2004-08-21 01:25:48 +00:00
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_WARNING " Couldn't load %s \n " , name ) ;
2004-12-24 08:45:56 +00:00
memcpy ( out - > texture , r_notexture_mip , sizeof ( texture_t ) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2 ) ;
2004-08-21 01:25:48 +00:00
}
2006-03-03 03:31:19 +00:00
2010-07-11 02:22:39 +00:00
Q_strncpyz ( out - > texture - > name , sname , sizeof ( out - > texture - > name ) ) ;
2004-08-21 01:25:48 +00:00
loadmodel - > textures [ texcount + + ] = out - > texture ;
}
}
loadmodel - > numtextures = texcount ;
2010-07-11 02:22:39 +00:00
Mod_SortShaders ( ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
# endif
/*
void CalcSurfaceExtents ( msurface_t * s )
{
float mins [ 2 ] , maxs [ 2 ] , val ;
int i , j , e ;
mvertex_t * v ;
mtexinfo_t * tex ;
int bmins [ 2 ] , bmaxs [ 2 ] ;
mins [ 0 ] = mins [ 1 ] = 999999 ;
maxs [ 0 ] = maxs [ 1 ] = - 99999 ;
tex = s - > texinfo ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < s - > numedges ; i + + )
{
e = loadmodel - > surfedges [ s - > firstedge + i ] ;
if ( e > = 0 )
v = & loadmodel - > vertexes [ loadmodel - > edges [ e ] . v [ 0 ] ] ;
else
v = & loadmodel - > vertexes [ loadmodel - > edges [ - e ] . v [ 1 ] ] ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
for ( j = 0 ; j < 2 ; j + + )
{
2006-03-04 20:43:48 +00:00
val = v - > position [ 0 ] * tex - > vecs [ j ] [ 0 ] +
2004-08-21 01:25:48 +00:00
v - > position [ 1 ] * tex - > vecs [ j ] [ 1 ] +
v - > position [ 2 ] * tex - > vecs [ j ] [ 2 ] +
tex - > vecs [ j ] [ 3 ] ;
if ( val < mins [ j ] )
mins [ j ] = val ;
if ( val > maxs [ j ] )
maxs [ j ] = val ;
}
}
for ( i = 0 ; i < 2 ; i + + )
2006-03-04 20:43:48 +00:00
{
2004-08-21 01:25:48 +00:00
bmins [ i ] = floor ( mins [ i ] / 16 ) ;
bmaxs [ i ] = ceil ( maxs [ i ] / 16 ) ;
s - > texturemins [ i ] = bmins [ i ] * 16 ;
s - > extents [ i ] = ( bmaxs [ i ] - bmins [ i ] ) * 16 ;
// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 )// 256 )
// Sys_Error ("Bad surface extents");
}
} */
/*
= = = = = = = = = = = = = = = = =
Mod_LoadFaces
= = = = = = = = = = = = = = = = =
*/
# ifndef SERVERONLY
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadFaces ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
2011-10-27 16:16:29 +00:00
dsface_t * in ;
2004-08-21 01:25:48 +00:00
msurface_t * out ;
int i , count , surfnum ;
int planenum , side ;
int ti ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
Con_Printf ( " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
out = Hunk_AllocName ( ( count + 6 ) * sizeof ( * out ) , loadname ) ; //spare for skybox
loadmodel - > surfaces = out ;
loadmodel - > numsurfaces = count ;
for ( surfnum = 0 ; surfnum < count ; surfnum + + , in + + , out + + )
{
out - > firstedge = LittleLong ( in - > firstedge ) ;
2006-03-04 20:43:48 +00:00
out - > numedges = LittleShort ( in - > numedges ) ;
2004-08-21 01:25:48 +00:00
out - > flags = 0 ;
planenum = LittleShort ( in - > planenum ) ;
side = LittleShort ( in - > side ) ;
if ( side )
2006-03-04 20:43:48 +00:00
out - > flags | = SURF_PLANEBACK ;
2004-08-21 01:25:48 +00:00
out - > plane = loadmodel - > planes + planenum ;
ti = LittleShort ( in - > texinfo ) ;
if ( ti < 0 | | ti > = loadmodel - > numtexinfo )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: bad texinfo number \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out - > texinfo = loadmodel - > texinfo + ti ;
# ifndef SERVERONLY
2009-11-04 21:16:50 +00:00
if ( out - > texinfo - > flags & TI_SKY )
2004-08-21 01:25:48 +00:00
{
out - > flags | = SURF_DRAWSKY ;
}
2009-11-04 21:16:50 +00:00
if ( out - > texinfo - > flags & TI_WARP )
2005-01-07 02:49:15 +00:00
{
out - > flags | = SURF_DRAWTURB | SURF_DRAWTILED ;
}
2004-08-21 01:25:48 +00:00
# endif
CalcSurfaceExtents ( out ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
// lighting info
for ( i = 0 ; i < MAXLIGHTMAPS ; i + + )
out - > styles [ i ] = in - > styles [ i ] ;
i = LittleLong ( in - > lightofs ) ;
if ( i = = - 1 )
out - > samples = NULL ;
else
2012-09-30 05:52:03 +00:00
out - > samples = loadmodel - > lightdata + i ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
// set the drawing flags
2006-03-04 20:43:48 +00:00
2009-11-04 21:16:50 +00:00
if ( out - > texinfo - > flags & TI_WARP )
2004-08-21 01:25:48 +00:00
{
out - > flags | = SURF_DRAWTURB ;
for ( i = 0 ; i < 2 ; i + + )
{
out - > extents [ i ] = 16384 ;
out - > texturemins [ i ] = - 8192 ;
}
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
# endif
void CMod_SetParent ( mnode_t * node , mnode_t * parent )
{
node - > parent = parent ;
if ( node - > contents ! = - 1 )
return ;
CMod_SetParent ( node - > children [ 0 ] , node ) ;
CMod_SetParent ( node - > children [ 1 ] , node ) ;
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadNodes
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadNodes ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q2dnode_t * in ;
int child ;
mnode_t * out ;
int i , j , count ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has no nodes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-05-26 12:55:34 +00:00
if ( count > MAX_MAP_NODES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many nodes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2012-07-23 03:42:46 +00:00
out = Hunk_AllocName ( sizeof ( mnode_t ) * count , " nodes " ) ;
2004-08-21 01:25:48 +00:00
loadmodel - > nodes = out ;
2005-08-26 22:56:51 +00:00
loadmodel - > numnodes = count ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , out + + , in + + )
{
memset ( out , 0 , sizeof ( * out ) ) ;
for ( j = 0 ; j < 3 ; j + + )
{
out - > minmaxs [ j ] = LittleShort ( in - > mins [ j ] ) ;
out - > minmaxs [ 3 + j ] = LittleShort ( in - > maxs [ j ] ) ;
}
out - > plane = map_planes + LittleLong ( in - > planenum ) ;
out - > firstsurface = LittleShort ( in - > firstface ) ;
out - > numsurfaces = LittleShort ( in - > numfaces ) ;
out - > contents = - 1 ; // differentiate from leafs
for ( j = 0 ; j < 2 ; j + + )
{
child = LittleLong ( in - > children [ j ] ) ;
out - > childnum [ j ] = child ;
if ( child < 0 )
out - > children [ j ] = ( mnode_t * ) ( map_leafs + - 1 - child ) ;
else
2005-08-26 22:56:51 +00:00
out - > children [ j ] = loadmodel - > nodes + child ;
2004-08-21 01:25:48 +00:00
}
}
CMod_SetParent ( loadmodel - > nodes , NULL ) ; // sets nodes and leafs
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadBrushes
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadBrushes ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q2dbrush_t * in ;
q2cbrush_t * out ;
int i , count ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count > MAX_Q2MAP_BRUSHES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many brushes " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out = map_brushes ;
numbrushes = count ;
for ( i = 0 ; i < count ; i + + , out + + , in + + )
{
2010-03-14 14:35:56 +00:00
//FIXME: missing bounds checks
out - > brushside = & map_brushsides [ LittleLong ( in - > firstside ) ] ;
2004-08-21 01:25:48 +00:00
out - > numsides = LittleLong ( in - > numsides ) ;
out - > contents = LittleLong ( in - > contents ) ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadLeafs
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadLeafs ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i , j ;
mleaf_t * out ;
q2dleaf_t * in ;
int count ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no leafs \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
// need to save space for box planes
if ( count > MAX_Q2MAP_PLANES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many planes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2006-03-04 20:43:48 +00:00
out = map_leafs ;
2004-08-21 01:25:48 +00:00
numleafs = count ;
numclusters = 0 ;
loadmodel - > leafs = out ;
loadmodel - > numleafs = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
memset ( out , 0 , sizeof ( * out ) ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
for ( j = 0 ; j < 3 ; j + + )
{
out - > minmaxs [ j ] = LittleShort ( in - > mins [ j ] ) ;
out - > minmaxs [ 3 + j ] = LittleShort ( in - > maxs [ j ] ) ;
}
out - > contents = LittleLong ( in - > contents ) ;
2008-08-06 12:11:27 +00:00
out - > cluster = ( unsigned short ) LittleShort ( in - > cluster ) ;
2009-08-08 12:49:51 +00:00
if ( out - > cluster = = 0xffff )
out - > cluster = - 1 ;
2009-11-04 21:16:50 +00:00
2004-08-21 01:25:48 +00:00
out - > area = LittleShort ( in - > area ) ;
2008-08-06 12:11:27 +00:00
out - > firstleafbrush = ( unsigned short ) LittleShort ( in - > firstleafbrush ) ;
out - > numleafbrushes = ( unsigned short ) LittleShort ( in - > numleafbrushes ) ;
2004-08-21 01:25:48 +00:00
out - > firstmarksurface = loadmodel - > marksurfaces +
2008-08-06 12:11:27 +00:00
( unsigned short ) LittleShort ( in - > firstleafface ) ;
out - > nummarksurfaces = ( unsigned short ) LittleShort ( in - > numleaffaces ) ;
2004-08-21 01:25:48 +00:00
if ( out - > cluster > = numclusters )
numclusters = out - > cluster + 1 ;
}
if ( map_leafs [ 0 ] . contents ! = Q2CONTENTS_SOLID )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map leaf 0 is not CONTENTS_SOLID \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
emptyleaf = - 1 ;
for ( i = 1 ; i < numleafs ; i + + )
{
if ( ! map_leafs [ i ] . contents )
{
emptyleaf = i ;
break ;
}
}
if ( emptyleaf = = - 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map does not have an empty leaf \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadPlanes
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadPlanes ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i , j ;
mplane_t * out ;
dplane_t * in ;
int count ;
int bits ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no planes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
// need to save space for box planes
2004-11-13 17:20:25 +00:00
if ( count > = MAX_Q2MAP_PLANES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many planes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2006-03-04 20:43:48 +00:00
out = map_planes ;
2004-08-21 01:25:48 +00:00
numplanes = count ;
loadmodel - > planes = out ;
loadmodel - > numplanes = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
bits = 0 ;
for ( j = 0 ; j < 3 ; j + + )
{
out - > normal [ j ] = LittleFloat ( in - > normal [ j ] ) ;
if ( out - > normal [ j ] < 0 )
bits | = 1 < < j ;
}
out - > dist = LittleFloat ( in - > dist ) ;
out - > type = LittleLong ( in - > type ) ;
out - > signbits = bits ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadLeafBrushes
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadLeafBrushes ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i ;
int * out ;
unsigned short * in ;
int count ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no planes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
// need to save space for box planes
if ( count > MAX_Q2MAP_LEAFBRUSHES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many leafbrushes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out = map_leafbrushes ;
numleafbrushes = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
* out = LittleShort ( * in ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadBrushSides
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadBrushSides ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i , j ;
q2cbrushside_t * out ;
q2dbrushside_t * in ;
int count ;
int num ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
// need to save space for box planes
if ( count > MAX_Q2MAP_BRUSHSIDES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many planes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2006-03-04 20:43:48 +00:00
out = map_brushsides ;
2004-08-21 01:25:48 +00:00
numbrushsides = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
num = LittleShort ( in - > planenum ) ;
out - > plane = & map_planes [ num ] ;
j = LittleShort ( in - > texinfo ) ;
if ( j > = numtexinfo )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Bad brushside texinfo \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out - > surface = & map_surfaces [ j ] ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadAreas
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadAreas ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i ;
q2carea_t * out ;
q2darea_t * in ;
int count ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count > MAX_Q2MAP_AREAS )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many areas \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out = map_q2areas ;
numareas = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out - > numareaportals = LittleLong ( in - > numareaportals ) ;
out - > firstareaportal = LittleLong ( in - > firstareaportal ) ;
out - > floodvalid = 0 ;
out - > floodnum = 0 ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadAreaPortals
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadAreaPortals ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i ;
q2dareaportal_t * out ;
q2dareaportal_t * in ;
int count ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count > MAX_Q2MAP_AREAS )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many areas \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out = map_areaportals ;
numareaportals = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out - > portalnum = LittleLong ( in - > portalnum ) ;
out - > otherarea = LittleLong ( in - > otherarea ) ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadVisibility
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CMod_LoadVisibility ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i ;
numvisibility = l - > filelen ;
2012-08-02 03:44:04 +00:00
// if (l->filelen > MAX_Q2MAP_VISIBILITY)
// {
// Con_Printf (CON_ERROR "Map has too large visibility lump\n");
// return false;
// }
2004-08-21 01:25:48 +00:00
2012-08-02 03:44:04 +00:00
map_q2vis = Hunk_AllocName ( l - > filelen , " vis " ) ;
memcpy ( map_q2vis , cmod_base + l - > fileofs , l - > filelen ) ;
2004-08-21 01:25:48 +00:00
loadmodel - > vis = map_q2vis ;
map_q2vis - > numclusters = LittleLong ( map_q2vis - > numclusters ) ;
for ( i = 0 ; i < map_q2vis - > numclusters ; i + + )
{
map_q2vis - > bitofs [ i ] [ 0 ] = LittleLong ( map_q2vis - > bitofs [ i ] [ 0 ] ) ;
map_q2vis - > bitofs [ i ] [ 1 ] = LittleLong ( map_q2vis - > bitofs [ i ] [ 1 ] ) ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadEntityString
= = = = = = = = = = = = = = = = =
*/
void CMod_LoadEntityString ( lump_t * l )
{
numentitychars = l - > filelen ;
2005-07-14 01:57:34 +00:00
// if (l->filelen > MAX_Q2MAP_ENTSTRING)
// Host_Error ("Map has too large entity lump");
2004-08-21 01:25:48 +00:00
2012-07-23 03:42:46 +00:00
map_entitystring = Hunk_AllocName ( l - > filelen + 1 , " ents " ) ;
2004-08-21 01:25:48 +00:00
memcpy ( map_entitystring , cmod_base + l - > fileofs , l - > filelen ) ;
loadmodel - > entities = map_entitystring ;
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadMarksurfaces ( lump_t * l )
2006-03-04 20:43:48 +00:00
{
2004-08-21 01:25:48 +00:00
int i , j , count ;
int * in ;
msurface_t * * out ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " CModQ3_LoadMarksurfaces: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2006-03-04 20:43:48 +00:00
out = Hunk_AllocName ( count * sizeof ( * out ) , loadname ) ;
2004-08-21 01:25:48 +00:00
loadmodel - > marksurfaces = out ;
loadmodel - > nummarksurfaces = count ;
for ( i = 0 ; i < count ; i + + )
{
j = LittleLong ( in [ i ] ) ;
if ( j < 0 | | j > = loadmodel - > numsurfaces )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Mod_ParseMarksurfaces: bad surface number \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out [ i ] = loadmodel - > surfaces + j ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadSubmodels ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q3dmodel_t * in ;
2011-12-05 15:23:40 +00:00
cmodel_t * out ;
2004-08-21 01:25:48 +00:00
int i , j , count ;
int * leafbrush ;
mleaf_t * bleaf ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no models \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
if ( count > MAX_Q2MAP_MODELS )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many models \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
numcmodels = count ;
mapisq3 = true ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out = & map_cmodels [ i ] ;
for ( j = 0 ; j < 3 ; j + + )
{ // spread the mins / maxs by a pixel
out - > mins [ j ] = LittleFloat ( in - > mins [ j ] ) - 1 ;
out - > maxs [ j ] = LittleFloat ( in - > maxs [ j ] ) + 1 ;
out - > origin [ j ] = ( out - > maxs [ j ] + out - > mins [ j ] ) / 2 ;
}
2011-12-23 03:12:29 +00:00
out - > firstsurface = LittleLong ( in - > firstsurface ) ;
out - > numsurfaces = LittleLong ( in - > num_surfaces ) ;
2004-08-21 01:25:48 +00:00
if ( ! i )
out - > headnode = 0 ;
else
{
//create a new leaf to hold the bruses and be directly clipped
out - > headnode = - 1 - numleafs ;
// out->firstbrush = LittleLong(in->firstbrush);
// out->num_brushes = LittleLong(in->num_brushes);
bleaf = & map_leafs [ numleafs + + ] ;
bleaf - > numleafbrushes = LittleLong ( in - > num_brushes ) ;
bleaf - > firstleafbrush = numleafbrushes ;
bleaf - > contents = 0 ;
leafbrush = & map_leafbrushes [ numleafbrushes ] ;
2012-11-27 03:23:19 +00:00
for ( j = 0 ; j < bleaf - > numleafbrushes ; j + + , leafbrush + + )
{
2004-08-21 01:25:48 +00:00
* leafbrush = LittleLong ( in - > firstbrush ) + j ;
bleaf - > contents | = map_brushes [ * leafbrush ] . contents ;
}
numleafbrushes + = bleaf - > numleafbrushes ;
}
//submodels
}
2005-08-07 18:08:13 +00:00
VectorCopy ( map_cmodels [ 0 ] . mins , loadmodel - > mins ) ;
VectorCopy ( map_cmodels [ 0 ] . maxs , loadmodel - > maxs ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2009-11-04 21:16:50 +00:00
qboolean CModQ3_LoadShaders ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
dq3shader_t * in ;
q2mapsurface_t * out ;
int i , count ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no shaders \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-07-14 01:57:34 +00:00
// else if (count > MAX_Q2MAP_TEXINFO)
// Host_Error ("Map has too many shaders");
2004-08-21 01:25:48 +00:00
numtexinfo = count ;
2012-07-23 03:42:46 +00:00
out = map_surfaces = Hunk_AllocName ( count * sizeof ( * out ) , " tsurfaces " ) ;
2004-08-21 01:25:48 +00:00
2012-07-23 03:42:46 +00:00
loadmodel - > texinfo = Hunk_AllocName ( sizeof ( mtexinfo_t ) * count , " texinfo " ) ;
2004-08-21 01:25:48 +00:00
loadmodel - > numtextures = count ;
2012-07-23 03:42:46 +00:00
loadmodel - > textures = Hunk_AllocName ( sizeof ( texture_t * ) * count , " textures " ) ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
2012-07-23 03:42:46 +00:00
loadmodel - > texinfo [ i ] . texture = Hunk_AllocName ( sizeof ( texture_t ) , in - > shadername ) ;
2004-08-21 01:25:48 +00:00
Q_strncpyz ( loadmodel - > texinfo [ i ] . texture - > name , in - > shadername , sizeof ( loadmodel - > texinfo [ i ] . texture - > name ) ) ;
loadmodel - > textures [ i ] = loadmodel - > texinfo [ i ] . texture ;
out - > c . flags = LittleLong ( in - > surfflags ) ;
out - > c . value = LittleLong ( in - > contents ) ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadVertexes ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q3dvertex_t * in ;
2009-11-04 21:16:50 +00:00
vecV_t * out ;
vec3_t * nout , * sout , * tout ;
2004-08-21 01:25:48 +00:00
int i , count , j ;
vec2_t * lmout , * stout ;
2009-11-04 21:16:50 +00:00
vec4_t * cout ;
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " CMOD_LoadVertexes: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count > MAX_Q3MAP_VERTEXES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many vertexes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2012-07-23 03:42:46 +00:00
out = Hunk_AllocName ( count * sizeof ( * out ) , " vert_v " ) ;
stout = Hunk_AllocName ( count * sizeof ( * stout ) , " vert_st " ) ;
lmout = Hunk_AllocName ( count * sizeof ( * lmout ) , " vert_lm1 " ) ;
cout = Hunk_AllocName ( count * sizeof ( * cout ) , " vert_c " ) ;
nout = Hunk_AllocName ( count * sizeof ( * nout ) , " vert_n " ) ;
sout = Hunk_AllocName ( count * sizeof ( * nout ) , " vert_s " ) ;
tout = Hunk_AllocName ( count * sizeof ( * nout ) , " vert_t " ) ;
2004-08-21 01:25:48 +00:00
map_verts = out ;
map_vertstmexcoords = stout ;
2012-07-05 19:42:36 +00:00
map_vertlstmexcoords [ 0 ] = lmout ;
map_vertlstmexcoords [ 1 ] = lmout ;
map_vertlstmexcoords [ 2 ] = lmout ;
map_vertlstmexcoords [ 3 ] = lmout ;
2009-11-04 21:16:50 +00:00
map_colors4f_array = cout ;
2004-10-26 15:30:13 +00:00
map_normals_array = nout ;
2009-11-04 21:16:50 +00:00
map_svector_array = sout ;
map_tvector_array = tout ;
2004-08-21 01:25:48 +00:00
numvertexes = count ;
for ( i = 0 ; i < count ; i + + , in + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
out [ i ] [ j ] = LittleFloat ( in - > point [ j ] ) ;
2004-10-26 15:30:13 +00:00
nout [ i ] [ j ] = LittleFloat ( in - > normal [ j ] ) ;
2004-08-21 01:25:48 +00:00
}
for ( j = 0 ; j < 2 ; j + + )
{
stout [ i ] [ j ] = LittleFloat ( ( ( float * ) in - > texcoords ) [ j ] ) ;
lmout [ i ] [ j ] = LittleFloat ( ( ( float * ) in - > texcoords ) [ j + 2 ] ) ;
}
2004-10-19 16:10:14 +00:00
for ( j = 0 ; j < 4 ; j + + )
{
2009-11-04 21:16:50 +00:00
cout [ i ] [ j ] = in - > color [ j ] / 255.0f ;
2004-10-19 16:10:14 +00:00
}
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModRBSP_LoadVertexes ( lump_t * l )
2005-04-21 00:02:01 +00:00
{
rbspvertex_t * in ;
2009-11-04 21:16:50 +00:00
vecV_t * out ;
vec3_t * nout , * sout , * tout ;
2005-04-21 00:02:01 +00:00
int i , count , j ;
vec2_t * lmout , * stout ;
2009-11-04 21:16:50 +00:00
vec4_t * cout ;
2012-07-05 19:42:36 +00:00
int sty ;
2005-04-21 00:02:01 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " CMOD_LoadVertexes: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count > MAX_Q3MAP_VERTEXES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many vertexes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
2012-07-23 03:42:46 +00:00
out = Hunk_AllocName ( count * sizeof ( * out ) , " vert_v " ) ;
stout = Hunk_AllocName ( count * sizeof ( * stout ) , " vert_st " ) ;
lmout = Hunk_AllocName ( MAXLIGHTMAPS * count * sizeof ( * lmout ) , " vert_lm4 " ) ;
cout = Hunk_AllocName ( count * sizeof ( * cout ) , " vert_c " ) ;
nout = Hunk_AllocName ( count * sizeof ( * nout ) , " vert_n " ) ;
sout = Hunk_AllocName ( count * sizeof ( * sout ) , " vert_s " ) ;
tout = Hunk_AllocName ( count * sizeof ( * tout ) , " vert_t " ) ;
2005-04-21 00:02:01 +00:00
map_verts = out ;
map_vertstmexcoords = stout ;
2012-07-05 19:42:36 +00:00
for ( sty = 0 ; sty < MAXLIGHTMAPS ; sty + + )
map_vertlstmexcoords [ sty ] = lmout + sty * count ;
2009-11-04 21:16:50 +00:00
map_colors4f_array = cout ;
2005-04-21 00:02:01 +00:00
map_normals_array = nout ;
2009-11-04 21:16:50 +00:00
map_svector_array = sout ;
map_tvector_array = tout ;
2005-04-21 00:02:01 +00:00
numvertexes = count ;
for ( i = 0 ; i < count ; i + + , in + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
out [ i ] [ j ] = LittleFloat ( in - > point [ j ] ) ;
nout [ i ] [ j ] = LittleFloat ( in - > normal [ j ] ) ;
}
for ( j = 0 ; j < 2 ; j + + )
{
stout [ i ] [ j ] = LittleFloat ( ( ( float * ) in - > texcoords ) [ j ] ) ;
2012-07-05 19:42:36 +00:00
for ( sty = 0 ; sty < MAXLIGHTMAPS ; sty + + )
map_vertlstmexcoords [ sty ] [ i ] [ j ] = LittleFloat ( ( ( float * ) in - > texcoords ) [ j + 2 * ( sty + 1 ) ] ) ;
2005-04-21 00:02:01 +00:00
}
for ( j = 0 ; j < 4 ; j + + )
{
cout [ i ] [ j ] = in - > color [ 0 ] [ j ] ;
}
}
2006-03-13 05:54:12 +00:00
return true ;
2005-04-21 00:02:01 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadIndexes ( lump_t * l )
2006-03-04 20:43:48 +00:00
{
2004-08-21 01:25:48 +00:00
int i , count ;
2007-05-25 22:16:29 +00:00
int * in ;
index_t * out ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2012-08-01 23:46:20 +00:00
if ( count < 1 | | count > = MAX_Q3MAP_INDICES )
2006-03-13 05:54:12 +00:00
{
2010-05-01 22:47:47 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: too many indicies in %s: %i \n " ,
loadmodel - > name , count ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2006-03-04 20:43:48 +00:00
out = Hunk_AllocName ( count * sizeof ( * out ) , loadmodel - > name ) ;
2004-08-21 01:25:48 +00:00
map_surfindexes = out ;
map_numsurfindexes = count ;
for ( i = 0 ; i < count ; i + + )
out [ i ] = LittleLong ( in [ i ] ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadFaces
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadFaces ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q3dface_t * in ;
q3cface_t * out ;
int i , count ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count > MAX_MAP_FACES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many faces \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out = BZ_Malloc ( count * sizeof ( * out ) ) ;
map_faces = out ;
numfaces = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out - > facetype = LittleLong ( in - > facetype ) ;
out - > shadernum = LittleLong ( in - > shadernum ) ;
out - > numverts = LittleLong ( in - > num_vertices ) ;
out - > firstvert = LittleLong ( in - > firstvertex ) ;
out - > patch_cp [ 0 ] = LittleLong ( in - > patchwidth ) ;
out - > patch_cp [ 1 ] = LittleLong ( in - > patchheight ) ;
}
2011-07-30 14:14:56 +00:00
loadmodel - > numsurfaces = i ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModRBSP_LoadFaces ( lump_t * l )
2005-04-21 00:02:01 +00:00
{
rbspface_t * in ;
q3cface_t * out ;
int i , count ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count > MAX_MAP_FACES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many faces \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
out = BZ_Malloc ( count * sizeof ( * out ) ) ;
map_faces = out ;
numfaces = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
out - > facetype = LittleLong ( in - > facetype ) ;
out - > shadernum = LittleLong ( in - > shadernum ) ;
out - > numverts = LittleLong ( in - > num_vertices ) ;
out - > firstvert = LittleLong ( in - > firstvertex ) ;
out - > patch_cp [ 0 ] = LittleLong ( in - > patchwidth ) ;
out - > patch_cp [ 1 ] = LittleLong ( in - > patchheight ) ;
}
loadmodel - > numsurfaces = i ;
2006-03-13 05:54:12 +00:00
return true ;
2005-04-21 00:02:01 +00:00
}
2012-09-30 05:52:03 +00:00
# ifndef SERVERONLY
2004-08-21 01:25:48 +00:00
2004-10-19 16:10:14 +00:00
/*
= = = = = = = = = = = = = = = = =
Mod_LoadFogs
= = = = = = = = = = = = = = = = =
*/
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadFogs ( lump_t * l )
2004-10-19 16:10:14 +00:00
{
dfog_t * in ;
mfog_t * out ;
q2cbrush_t * brush ;
q2cbrushside_t * visibleside , * brushsides ;
int i , j , count ;
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-10-19 16:10:14 +00:00
count = l - > filelen / sizeof ( * in ) ;
2012-07-23 03:42:46 +00:00
out = Hunk_AllocName ( count * sizeof ( * out ) , " fogs " ) ;
2004-10-19 16:10:14 +00:00
map_fogs = out ;
map_numfogs = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
if ( LittleLong ( in - > visibleSide ) = = - 1 )
{
continue ;
}
brush = map_brushes + LittleLong ( in - > brushNum ) ;
2010-03-14 14:35:56 +00:00
brushsides = brush - > brushside ;
2004-10-19 16:10:14 +00:00
visibleside = brushsides + LittleLong ( in - > visibleSide ) ;
out - > visibleplane = visibleside - > plane ;
2009-11-04 21:16:50 +00:00
out - > shader = R_RegisterShader_Lightmap ( in - > shader ) ;
R_BuildDefaultTexnums ( & out - > shader - > defaulttextures , out - > shader ) ;
2004-10-19 16:10:14 +00:00
out - > numplanes = brush - > numsides ;
2012-07-23 03:42:46 +00:00
out - > planes = Hunk_AllocName ( out - > numplanes * sizeof ( cplane_t * ) , " fogplane " ) ;
2004-10-19 16:10:14 +00:00
for ( j = 0 ; j < out - > numplanes ; j + + )
{
out - > planes [ j ] = brushsides [ j ] . plane ;
}
2012-10-10 22:58:51 +00:00
if ( ! out - > shader - > fog_dist )
{
//invalid fog shader, don't use.
out - > shader = NULL ;
out - > numplanes = 0 ;
}
2004-10-19 16:10:14 +00:00
}
2006-03-13 05:54:12 +00:00
return true ;
2004-10-19 16:10:14 +00:00
}
2005-05-26 12:55:34 +00:00
mfog_t * CM_FogForOrigin ( vec3_t org )
{
int i , j ;
mfog_t * ret = map_fogs ;
float dot ;
2012-10-08 04:36:10 +00:00
if ( ! map_numfogs | | ! cl . worldmodel | | cl . worldmodel - > fromgame ! = fg_quake3 )
2005-05-26 12:55:34 +00:00
return NULL ;
for ( i = 0 ; i < map_numfogs ; i + + , ret + + )
{
if ( ! ret - > numplanes )
continue ;
for ( j = 0 ; j < ret - > numplanes ; j + + )
{
dot = DotProduct ( ret - > planes [ j ] - > normal , org ) ;
if ( dot - ret - > planes [ j ] - > dist > 0 )
break ;
}
if ( j = = ret - > numplanes )
{
return ret ;
}
}
return NULL ;
}
2004-10-19 16:10:14 +00:00
2004-08-21 01:25:48 +00:00
//Convert a patch in to a list of glpolys
2011-06-29 18:39:11 +00:00
# define MAX_ARRAY_VERTS 65535
2004-08-21 01:25:48 +00:00
2011-06-29 18:39:11 +00:00
index_t tempIndexesArray [ MAX_ARRAY_VERTS * 6 ] ;
2004-08-21 01:25:48 +00:00
2012-07-05 19:42:36 +00:00
void GL_SizePatch ( mesh_t * mesh , int patchwidth , int patchheight , int numverts , int firstvert )
{
int patch_cp [ 2 ] , step [ 2 ] , size [ 2 ] , flat [ 2 ] ;
float subdivlevel ;
patch_cp [ 0 ] = patchwidth ;
patch_cp [ 1 ] = patchheight ;
if ( patch_cp [ 0 ] < = 0 | | patch_cp [ 1 ] < = 0 )
{
mesh - > numindexes = 0 ;
mesh - > numvertexes = 0 ;
return ;
}
subdivlevel = r_subdivisions . value ;
if ( subdivlevel < 1 )
subdivlevel = 1 ;
// find the degree of subdivision in the u and v directions
Patch_GetFlatness ( subdivlevel , map_verts [ firstvert ] , sizeof ( vecV_t ) / sizeof ( vec_t ) , patch_cp , flat ) ;
// allocate space for mesh
step [ 0 ] = ( 1 < < flat [ 0 ] ) ;
step [ 1 ] = ( 1 < < flat [ 1 ] ) ;
size [ 0 ] = ( patch_cp [ 0 ] / 2 ) * step [ 0 ] + 1 ;
size [ 1 ] = ( patch_cp [ 1 ] / 2 ) * step [ 1 ] + 1 ;
mesh - > numvertexes = size [ 0 ] * size [ 1 ] ;
mesh - > numindexes = ( size [ 0 ] - 1 ) * ( size [ 1 ] - 1 ) * 6 ;
}
2005-04-21 00:02:01 +00:00
//mesh_t *GL_CreateMeshForPatch ( model_t *mod, q3dface_t *surf )
2012-07-05 19:42:36 +00:00
void GL_CreateMeshForPatch ( model_t * mod , mesh_t * mesh , int patchwidth , int patchheight , int numverts , int firstvert )
2004-08-21 01:25:48 +00:00
{
2005-04-21 00:02:01 +00:00
int numindexes , patch_cp [ 2 ] , step [ 2 ] , size [ 2 ] , flat [ 2 ] , i , u , v , p ;
2004-10-19 16:10:14 +00:00
index_t * indexes ;
2004-08-21 01:25:48 +00:00
float subdivlevel ;
2012-07-05 19:42:36 +00:00
int sty ;
2004-08-21 01:25:48 +00:00
2005-04-21 00:02:01 +00:00
patch_cp [ 0 ] = patchwidth ;
patch_cp [ 1 ] = patchheight ;
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
if ( patch_cp [ 0 ] < = 0 | | patch_cp [ 1 ] < = 0 )
2009-07-25 11:05:06 +00:00
{
2012-07-05 19:42:36 +00:00
mesh - > numindexes = 0 ;
mesh - > numvertexes = 0 ;
return ;
2004-08-21 01:25:48 +00:00
}
subdivlevel = r_subdivisions . value ;
if ( subdivlevel < 1 )
subdivlevel = 1 ;
// find the degree of subdivision in the u and v directions
2010-03-14 14:35:56 +00:00
Patch_GetFlatness ( subdivlevel , map_verts [ firstvert ] , sizeof ( vecV_t ) / sizeof ( vec_t ) , patch_cp , flat ) ;
2004-08-21 01:25:48 +00:00
// allocate space for mesh
step [ 0 ] = ( 1 < < flat [ 0 ] ) ;
step [ 1 ] = ( 1 < < flat [ 1 ] ) ;
size [ 0 ] = ( patch_cp [ 0 ] / 2 ) * step [ 0 ] + 1 ;
size [ 1 ] = ( patch_cp [ 1 ] / 2 ) * step [ 1 ] + 1 ;
numverts = size [ 0 ] * size [ 1 ] ;
2010-05-01 22:47:47 +00:00
if ( numverts < 0 | | numverts > MAX_ARRAY_VERTS )
2012-07-05 19:42:36 +00:00
{
mesh - > numindexes = 0 ;
mesh - > numvertexes = 0 ;
return ;
}
2004-08-21 01:25:48 +00:00
2012-07-05 19:42:36 +00:00
if ( mesh - > numvertexes ! = numverts )
{
mesh - > numindexes = 0 ;
mesh - > numvertexes = 0 ;
return ;
}
2004-08-21 01:25:48 +00:00
// fill in
2010-05-01 22:47:47 +00:00
Patch_Evaluate ( map_verts [ firstvert ] , patch_cp , step , mesh - > xyz_array [ 0 ] , sizeof ( vecV_t ) / sizeof ( vec_t ) ) ;
Patch_Evaluate ( map_colors4f_array [ firstvert ] , patch_cp , step , mesh - > colors4f_array [ 0 ] , 4 ) ;
Patch_Evaluate ( map_normals_array [ firstvert ] , patch_cp , step , mesh - > normals_array [ 0 ] , 3 ) ;
Patch_Evaluate ( map_vertstmexcoords [ firstvert ] , patch_cp , step , mesh - > st_array [ 0 ] , 2 ) ;
2012-07-05 19:42:36 +00:00
for ( sty = 0 ; sty < MAXLIGHTMAPS ; sty + + )
{
if ( mesh - > lmst_array [ sty ] )
Patch_Evaluate ( map_vertlstmexcoords [ sty ] [ firstvert ] , patch_cp , step , mesh - > lmst_array [ sty ] [ 0 ] , 2 ) ;
}
2004-08-21 01:25:48 +00:00
// compute new indexes avoiding adding invalid triangles
numindexes = 0 ;
indexes = tempIndexesArray ;
for ( v = 0 , i = 0 ; v < size [ 1 ] - 1 ; v + + )
{
for ( u = 0 ; u < size [ 0 ] - 1 ; u + + , i + = 6 )
{
indexes [ 0 ] = p = v * size [ 0 ] + u ;
indexes [ 1 ] = p + size [ 0 ] ;
indexes [ 2 ] = p + 1 ;
2012-07-05 19:42:36 +00:00
// if ( !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[1]]) &&
// !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[2]]) &&
// !VectorEquals(mesh->xyz_array[indexes[1]], mesh->xyz_array[indexes[2]]) )
{
2004-08-21 01:25:48 +00:00
indexes + = 3 ;
numindexes + = 3 ;
}
indexes [ 0 ] = p + 1 ;
indexes [ 1 ] = p + size [ 0 ] ;
indexes [ 2 ] = p + size [ 0 ] + 1 ;
2012-07-05 19:42:36 +00:00
// if ( !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[1]]) &&
// !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[2]]) &&
// !VectorEquals(mesh->xyz_array[indexes[1]], mesh->xyz_array[indexes[2]]) )
{
2004-08-21 01:25:48 +00:00
indexes + = 3 ;
numindexes + = 3 ;
}
}
}
// allocate and fill index table
2012-07-05 19:42:36 +00:00
2004-08-21 01:25:48 +00:00
mesh - > numindexes = numindexes ;
2004-10-19 16:10:14 +00:00
memcpy ( mesh - > indexes , tempIndexesArray , numindexes * sizeof ( index_t ) ) ;
2012-07-05 19:42:36 +00:00
}
void CModRBSP_BuildSurfMesh ( model_t * mod , msurface_t * out , void * cookie )
{
rbspface_t * in = cookie ;
int idx = out - loadmodel - > surfaces ;
int sty ;
in + = idx ;
if ( LittleLong ( in - > facetype ) = = MST_PATCH )
{
GL_CreateMeshForPatch ( loadmodel , out - > mesh , LittleLong ( in - > patchwidth ) , LittleLong ( in - > patchheight ) , LittleLong ( in - > num_vertices ) , LittleLong ( in - > firstvertex ) ) ;
}
else if ( LittleLong ( in - > facetype ) = = MST_PLANAR | | LittleLong ( in - > facetype ) = = MST_TRIANGLE_SOUP )
{
unsigned int fv = LittleLong ( in - > firstvertex ) , i ;
for ( i = 0 ; i < out - > mesh - > numvertexes ; i + + )
{
VectorCopy ( map_verts [ fv + i ] , out - > mesh - > xyz_array [ i ] ) ;
Vector2Copy ( map_vertstmexcoords [ fv + i ] , out - > mesh - > st_array [ i ] ) ;
for ( sty = 0 ; sty < MAXLIGHTMAPS ; sty + + )
{
Vector2Copy ( map_vertlstmexcoords [ sty ] [ fv + i ] , out - > mesh - > lmst_array [ sty ] [ i ] ) ;
}
Vector4Copy ( map_colors4f_array [ fv + i ] , out - > mesh - > colors4f_array [ i ] ) ;
VectorCopy ( map_normals_array [ fv + i ] , out - > mesh - > normals_array [ i ] ) ;
}
fv = LittleLong ( in - > firstindex ) ;
for ( i = 0 ; i < out - > mesh - > numindexes ; i + + )
{
out - > mesh - > indexes [ i ] = map_surfindexes [ fv + i ] ;
}
}
else
{
/* //flare
int r , g , b ;
extern index_t r_quad_indexes [ 6 ] ;
static vec2_t st [ 4 ] = { { 0 , 0 } , { 0 , 1 } , { 1 , 1 } , { 1 , 0 } } ;
mesh = out - > mesh = ( mesh_t * ) Hunk_Alloc ( sizeof ( mesh_t ) ) ;
mesh - > xyz_array = ( vecV_t * ) Hunk_Alloc ( sizeof ( vecV_t ) * 4 ) ;
mesh - > colors4b_array = ( byte_vec4_t * ) Hunk_Alloc ( sizeof ( byte_vec4_t ) * 4 ) ;
mesh - > numvertexes = 4 ;
mesh - > indexes = r_quad_indexes ;
mesh - > st_array = st ;
mesh - > numindexes = 6 ;
VectorCopy ( in - > lightmap_origin , mesh - > xyz_array [ 0 ] ) ;
VectorCopy ( in - > lightmap_origin , mesh - > xyz_array [ 1 ] ) ;
VectorCopy ( in - > lightmap_origin , mesh - > xyz_array [ 2 ] ) ;
VectorCopy ( in - > lightmap_origin , mesh - > xyz_array [ 3 ] ) ;
r = LittleFloat ( in - > lightmap_vecs [ 0 ] [ 0 ] ) * 255.0f ;
r = bound ( 0 , r , 255 ) ;
g = LittleFloat ( in - > lightmap_vecs [ 0 ] [ 1 ] ) * 255.0f ;
g = bound ( 0 , g , 255 ) ;
b = LittleFloat ( in - > lightmap_vecs [ 0 ] [ 2 ] ) * 255.0f ;
b = bound ( 0 , b , 255 ) ;
mesh - > colors4b_array [ 0 ] [ 0 ] = r ;
mesh - > colors4b_array [ 0 ] [ 1 ] = g ;
mesh - > colors4b_array [ 0 ] [ 2 ] = b ;
mesh - > colors4b_array [ 0 ] [ 3 ] = 255 ;
Vector4Copy ( mesh - > colors4b_array [ 0 ] , mesh - > colors4b_array [ 1 ] ) ;
Vector4Copy ( mesh - > colors4b_array [ 0 ] , mesh - > colors4b_array [ 2 ] ) ;
Vector4Copy ( mesh - > colors4b_array [ 0 ] , mesh - > colors4b_array [ 3 ] ) ;
*/
}
2013-03-12 23:10:44 +00:00
Mod_AccumulateMeshTextureVectors ( out - > mesh ) ;
Mod_NormaliseTextureVectors ( out - > mesh - > normals_array , out - > mesh - > snormals_array , out - > mesh - > tnormals_array , out - > mesh - > numvertexes ) ;
2012-07-05 19:42:36 +00:00
}
void CModQ3_BuildSurfMesh ( model_t * mod , msurface_t * out , void * cookie )
{
q3dface_t * in = cookie ;
int idx = out - loadmodel - > surfaces ;
in + = idx ;
if ( LittleLong ( in - > facetype ) = = MST_PATCH )
{
GL_CreateMeshForPatch ( loadmodel , out - > mesh , LittleLong ( in - > patchwidth ) , LittleLong ( in - > patchheight ) , LittleLong ( in - > num_vertices ) , LittleLong ( in - > firstvertex ) ) ;
}
else if ( LittleLong ( in - > facetype ) = = MST_PLANAR | | LittleLong ( in - > facetype ) = = MST_TRIANGLE_SOUP )
{
unsigned int fv = LittleLong ( in - > firstvertex ) , i ;
for ( i = 0 ; i < out - > mesh - > numvertexes ; i + + )
{
VectorCopy ( map_verts [ fv + i ] , out - > mesh - > xyz_array [ i ] ) ;
Vector2Copy ( map_vertstmexcoords [ fv + i ] , out - > mesh - > st_array [ i ] ) ;
Vector2Copy ( map_vertlstmexcoords [ 0 ] [ fv + i ] , out - > mesh - > lmst_array [ 0 ] [ i ] ) ;
Vector4Copy ( map_colors4f_array [ fv + i ] , out - > mesh - > colors4f_array [ i ] ) ;
VectorCopy ( map_normals_array [ fv + i ] , out - > mesh - > normals_array [ i ] ) ;
}
fv = LittleLong ( in - > firstindex ) ;
for ( i = 0 ; i < out - > mesh - > numindexes ; i + + )
{
out - > mesh - > indexes [ i ] = map_surfindexes [ fv + i ] ;
}
}
else
{
/* //flare
int r , g , b ;
extern index_t r_quad_indexes [ 6 ] ;
static vec2_t st [ 4 ] = { { 0 , 0 } , { 0 , 1 } , { 1 , 1 } , { 1 , 0 } } ;
mesh = out - > mesh = ( mesh_t * ) Hunk_Alloc ( sizeof ( mesh_t ) ) ;
mesh - > xyz_array = ( vecV_t * ) Hunk_Alloc ( sizeof ( vecV_t ) * 4 ) ;
mesh - > colors4b_array = ( byte_vec4_t * ) Hunk_Alloc ( sizeof ( byte_vec4_t ) * 4 ) ;
mesh - > numvertexes = 4 ;
mesh - > indexes = r_quad_indexes ;
mesh - > st_array = st ;
mesh - > numindexes = 6 ;
VectorCopy ( in - > lightmap_origin , mesh - > xyz_array [ 0 ] ) ;
VectorCopy ( in - > lightmap_origin , mesh - > xyz_array [ 1 ] ) ;
VectorCopy ( in - > lightmap_origin , mesh - > xyz_array [ 2 ] ) ;
VectorCopy ( in - > lightmap_origin , mesh - > xyz_array [ 3 ] ) ;
r = LittleFloat ( in - > lightmap_vecs [ 0 ] [ 0 ] ) * 255.0f ;
r = bound ( 0 , r , 255 ) ;
g = LittleFloat ( in - > lightmap_vecs [ 0 ] [ 1 ] ) * 255.0f ;
g = bound ( 0 , g , 255 ) ;
b = LittleFloat ( in - > lightmap_vecs [ 0 ] [ 2 ] ) * 255.0f ;
b = bound ( 0 , b , 255 ) ;
mesh - > colors4b_array [ 0 ] [ 0 ] = r ;
mesh - > colors4b_array [ 0 ] [ 1 ] = g ;
mesh - > colors4b_array [ 0 ] [ 2 ] = b ;
mesh - > colors4b_array [ 0 ] [ 3 ] = 255 ;
Vector4Copy ( mesh - > colors4b_array [ 0 ] , mesh - > colors4b_array [ 1 ] ) ;
Vector4Copy ( mesh - > colors4b_array [ 0 ] , mesh - > colors4b_array [ 2 ] ) ;
Vector4Copy ( mesh - > colors4b_array [ 0 ] , mesh - > colors4b_array [ 3 ] ) ;
*/
}
2013-03-12 23:10:44 +00:00
Mod_AccumulateMeshTextureVectors ( out - > mesh ) ;
Mod_NormaliseTextureVectors ( out - > mesh - > normals_array , out - > mesh - > snormals_array , out - > mesh - > tnormals_array , out - > mesh - > numvertexes ) ;
2004-08-21 01:25:48 +00:00
}
2009-11-04 21:16:50 +00:00
qboolean CModQ3_LoadRFaces ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q3dface_t * in ;
msurface_t * out ;
mplane_t * pl ;
int count ;
int surfnum ;
2004-10-19 16:10:14 +00:00
int fv ;
2012-07-05 19:42:36 +00:00
int sty ;
2004-08-21 01:25:48 +00:00
2006-03-04 20:43:48 +00:00
mesh_t * mesh ;
2004-08-21 01:25:48 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2006-03-04 20:43:48 +00:00
out = Hunk_AllocName ( count * sizeof ( * out ) , loadmodel - > name ) ;
2004-10-19 16:10:14 +00:00
pl = Hunk_AllocName ( count * sizeof ( * pl ) , loadmodel - > name ) ; //create a new array of planes for speed.
2012-07-05 19:42:36 +00:00
mesh = Hunk_AllocName ( count * sizeof ( * mesh ) , loadmodel - > name ) ;
2004-08-21 01:25:48 +00:00
loadmodel - > surfaces = out ;
loadmodel - > numsurfaces = count ;
for ( surfnum = 0 ; surfnum < count ; surfnum + + , out + + , in + + , pl + + )
{
out - > plane = pl ;
out - > texinfo = loadmodel - > texinfo + LittleLong ( in - > shadernum ) ;
2012-07-05 19:42:36 +00:00
out - > lightmaptexturenums [ 0 ] = LittleLong ( in - > lightmapnum ) ;
out - > light_s [ 0 ] = LittleLong ( in - > lightmap_x ) ;
out - > light_t [ 0 ] = LittleLong ( in - > lightmap_y ) ;
out - > styles [ 0 ] = 255 ;
for ( sty = 1 ; sty < MAXLIGHTMAPS ; sty + + )
{
out - > styles [ sty ] = 255 ;
out - > lightmaptexturenums [ sty ] = - 1 ;
}
2005-07-09 16:36:26 +00:00
out - > extents [ 0 ] = ( LittleLong ( in - > lightmap_width ) - 1 ) < < 4 ;
out - > extents [ 1 ] = ( LittleLong ( in - > lightmap_height ) - 1 ) < < 4 ;
2011-07-30 14:14:56 +00:00
out - > samples = NULL ;
2004-08-21 01:25:48 +00:00
2012-07-05 19:42:36 +00:00
if ( loadmodel - > lightmaps . count < out - > lightmaptexturenums [ 0 ] + 1 )
loadmodel - > lightmaps . count = out - > lightmaptexturenums [ 0 ] + 1 ;
2006-03-13 05:54:12 +00:00
fv = LittleLong ( in - > firstvertex ) ;
{
vec3_t v [ 3 ] ;
VectorCopy ( map_verts [ fv + 0 ] , v [ 0 ] ) ;
VectorCopy ( map_verts [ fv + 1 ] , v [ 1 ] ) ;
VectorCopy ( map_verts [ fv + 2 ] , v [ 2 ] ) ;
PlaneFromPoints ( v , pl ) ;
CategorizePlane ( pl ) ;
}
2004-10-19 16:10:14 +00:00
2005-07-09 16:36:26 +00:00
if ( map_surfaces [ LittleLong ( in - > shadernum ) ] . c . value = = 0 | | map_surfaces [ LittleLong ( in - > shadernum ) ] . c . value & Q3CONTENTS_TRANSLUCENT )
2004-08-21 01:25:48 +00:00
//q3dm10's thingie is 0
out - > flags | = SURF_DRAWALPHA ;
2009-11-04 21:16:50 +00:00
if ( loadmodel - > texinfo [ LittleLong ( in - > shadernum ) ] . flags & TI_SKY )
2004-08-21 01:25:48 +00:00
out - > flags | = SURF_DRAWSKY ;
2004-10-19 16:10:14 +00:00
2009-11-04 21:16:50 +00:00
if ( ! out - > texinfo - > texture - > shader )
2004-10-19 16:10:14 +00:00
{
extern cvar_t r_vertexlight ;
2005-07-09 16:36:26 +00:00
if ( LittleLong ( in - > facetype ) = = MST_FLARE )
2004-10-19 16:10:14 +00:00
out - > texinfo - > texture - > shader = R_RegisterShader_Flare ( out - > texinfo - > texture - > name ) ;
2005-07-09 16:36:26 +00:00
else if ( LittleLong ( in - > facetype ) = = MST_TRIANGLE_SOUP | | r_vertexlight . value )
2004-10-19 16:10:14 +00:00
out - > texinfo - > texture - > shader = R_RegisterShader_Vertex ( out - > texinfo - > texture - > name ) ;
else
2009-11-04 21:16:50 +00:00
out - > texinfo - > texture - > shader = R_RegisterShader_Lightmap ( out - > texinfo - > texture - > name ) ;
2005-05-15 18:49:04 +00:00
2009-11-04 21:16:50 +00:00
R_BuildDefaultTexnums ( & out - > texinfo - > texture - > shader - > defaulttextures , out - > texinfo - > texture - > shader ) ;
2004-10-19 16:10:14 +00:00
}
2005-07-09 16:36:26 +00:00
if ( LittleLong ( in - > fognum ) = = - 1 | | ! map_numfogs )
2004-10-19 16:10:14 +00:00
out - > fog = NULL ;
else
2005-07-09 16:36:26 +00:00
out - > fog = map_fogs + LittleLong ( in - > fognum ) ;
2009-11-04 21:16:50 +00:00
2005-07-09 16:36:26 +00:00
if ( map_surfaces [ LittleLong ( in - > shadernum ) ] . c . flags & ( Q3SURF_NODRAW | Q3SURF_SKIP ) )
2004-08-21 01:25:48 +00:00
{
2012-07-05 19:42:36 +00:00
out - > mesh = & mesh [ surfnum ] ;
out - > mesh - > numindexes = 0 ;
out - > mesh - > numvertexes = 0 ;
2004-08-21 01:25:48 +00:00
}
2005-07-09 16:36:26 +00:00
else if ( LittleLong ( in - > facetype ) = = MST_PATCH )
2004-08-21 01:25:48 +00:00
{
2012-07-05 19:42:36 +00:00
out - > mesh = & mesh [ surfnum ] ;
GL_SizePatch ( out - > mesh , LittleLong ( in - > patchwidth ) , LittleLong ( in - > patchheight ) , LittleLong ( in - > num_vertices ) , LittleLong ( in - > firstvertex ) ) ;
2005-04-21 00:02:01 +00:00
}
2005-07-09 16:36:26 +00:00
else if ( LittleLong ( in - > facetype ) = = MST_PLANAR | | LittleLong ( in - > facetype ) = = MST_TRIANGLE_SOUP )
2005-04-21 00:02:01 +00:00
{
2012-07-05 19:42:36 +00:00
out - > mesh = & mesh [ surfnum ] ;
out - > mesh - > numindexes = LittleLong ( in - > num_indexes ) ;
out - > mesh - > numvertexes = LittleLong ( in - > num_vertices ) ;
/*
2009-11-04 21:16:50 +00:00
Mod_AccumulateMeshTextureVectors ( out - > mesh ) ;
2012-07-05 19:42:36 +00:00
*/
2005-04-21 00:02:01 +00:00
}
else
{
2012-07-05 19:42:36 +00:00
out - > mesh = & mesh [ surfnum ] ;
out - > mesh - > numindexes = 6 ;
out - > mesh - > numvertexes = 4 ;
}
2005-04-21 00:02:01 +00:00
}
2005-05-26 12:55:34 +00:00
2010-07-11 02:22:39 +00:00
Mod_SortShaders ( ) ;
2006-03-13 05:54:12 +00:00
return true ;
2005-04-21 00:02:01 +00:00
}
2009-11-04 21:16:50 +00:00
qboolean CModRBSP_LoadRFaces ( lump_t * l )
2005-04-21 00:02:01 +00:00
{
rbspface_t * in ;
msurface_t * out ;
mplane_t * pl ;
int count ;
int surfnum ;
int fv ;
2012-07-05 19:42:36 +00:00
int j ;
2005-04-21 00:02:01 +00:00
mesh_t * mesh ;
2006-03-04 20:43:48 +00:00
2005-04-21 00:02:01 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
count = l - > filelen / sizeof ( * in ) ;
2006-03-04 20:43:48 +00:00
out = Hunk_AllocName ( count * sizeof ( * out ) , loadmodel - > name ) ;
2005-04-21 00:02:01 +00:00
pl = Hunk_AllocName ( count * sizeof ( * pl ) , loadmodel - > name ) ; //create a new array of planes for speed.
2012-07-05 19:42:36 +00:00
mesh = Hunk_AllocName ( count * sizeof ( * mesh ) , loadmodel - > name ) ;
2005-04-21 00:02:01 +00:00
loadmodel - > surfaces = out ;
loadmodel - > numsurfaces = count ;
for ( surfnum = 0 ; surfnum < count ; surfnum + + , out + + , in + + , pl + + )
{
out - > plane = pl ;
out - > texinfo = loadmodel - > texinfo + LittleLong ( in - > shadernum ) ;
in - > facetype = LittleLong ( in - > facetype ) ;
2012-07-05 19:42:36 +00:00
for ( j = 0 ; j < 4 & & j < MAXLIGHTMAPS ; j + + )
{
out - > lightmaptexturenums [ j ] = LittleLong ( in - > lightmapnum [ j ] ) ;
out - > light_s [ j ] = LittleLong ( in - > lightmap_offs [ 0 ] [ j ] ) ;
out - > light_t [ j ] = LittleLong ( in - > lightmap_offs [ 1 ] [ j ] ) ;
out - > styles [ j ] = in - > lm_styles [ j ] ;
if ( loadmodel - > lightmaps . count < out - > lightmaptexturenums [ j ] + 1 )
loadmodel - > lightmaps . count = out - > lightmaptexturenums [ j ] + 1 ;
}
out - > extents [ 0 ] = ( LittleLong ( in - > lightmap_width ) - 1 ) < < 4 ;
out - > extents [ 1 ] = ( LittleLong ( in - > lightmap_height ) - 1 ) < < 4 ;
2011-07-30 14:14:56 +00:00
out - > samples = NULL ;
2005-04-21 00:02:01 +00:00
2006-03-13 05:54:12 +00:00
fv = LittleLong ( in - > firstvertex ) ;
{
vec3_t v [ 3 ] ;
VectorCopy ( map_verts [ fv + 0 ] , v [ 0 ] ) ;
VectorCopy ( map_verts [ fv + 1 ] , v [ 1 ] ) ;
VectorCopy ( map_verts [ fv + 2 ] , v [ 2 ] ) ;
PlaneFromPoints ( v , pl ) ;
CategorizePlane ( pl ) ;
}
2005-04-21 00:02:01 +00:00
if ( map_surfaces [ in - > shadernum ] . c . value = = 0 | | map_surfaces [ in - > shadernum ] . c . value & Q3CONTENTS_TRANSLUCENT )
//q3dm10's thingie is 0
out - > flags | = SURF_DRAWALPHA ;
2009-11-04 21:16:50 +00:00
if ( loadmodel - > texinfo [ in - > shadernum ] . flags & TI_SKY )
2005-04-21 00:02:01 +00:00
out - > flags | = SURF_DRAWSKY ;
2009-11-04 21:16:50 +00:00
if ( ! out - > texinfo - > texture - > shader )
2005-04-21 00:02:01 +00:00
{
extern cvar_t r_vertexlight ;
if ( in - > facetype = = MST_FLARE )
out - > texinfo - > texture - > shader = R_RegisterShader_Flare ( out - > texinfo - > texture - > name ) ;
else if ( in - > facetype = = MST_TRIANGLE_SOUP | | r_vertexlight . value )
out - > texinfo - > texture - > shader = R_RegisterShader_Vertex ( out - > texinfo - > texture - > name ) ;
else
2009-11-04 21:16:50 +00:00
out - > texinfo - > texture - > shader = R_RegisterShader_Lightmap ( out - > texinfo - > texture - > name ) ;
R_BuildDefaultTexnums ( & out - > texinfo - > texture - > shader - > defaulttextures , out - > texinfo - > texture - > shader ) ;
2005-04-21 00:02:01 +00:00
}
2012-10-10 22:58:51 +00:00
if ( in - > fognum < 0 | | in - > fognum > = map_numfogs | | ! map_fogs [ in - > fognum ] . shader )
2005-04-21 00:02:01 +00:00
out - > fog = NULL ;
else
out - > fog = map_fogs + in - > fognum ;
2012-07-05 19:42:36 +00:00
if ( map_surfaces [ LittleLong ( in - > shadernum ) ] . c . flags & ( Q3SURF_NODRAW | Q3SURF_SKIP ) )
2005-04-21 00:02:01 +00:00
{
2012-07-05 19:42:36 +00:00
out - > mesh = & mesh [ surfnum ] ;
out - > mesh - > numindexes = 0 ;
out - > mesh - > numvertexes = 0 ;
2005-04-21 00:02:01 +00:00
}
2012-07-05 19:42:36 +00:00
else if ( LittleLong ( in - > facetype ) = = MST_PATCH )
2005-04-21 00:02:01 +00:00
{
2012-07-05 19:42:36 +00:00
out - > mesh = & mesh [ surfnum ] ;
GL_SizePatch ( out - > mesh , LittleLong ( in - > patchwidth ) , LittleLong ( in - > patchheight ) , LittleLong ( in - > num_vertices ) , LittleLong ( in - > firstvertex ) ) ;
2004-08-21 01:25:48 +00:00
}
2012-07-05 19:42:36 +00:00
else if ( LittleLong ( in - > facetype ) = = MST_PLANAR | | LittleLong ( in - > facetype ) = = MST_TRIANGLE_SOUP )
2004-08-21 01:25:48 +00:00
{
2012-07-05 19:42:36 +00:00
out - > mesh = & mesh [ surfnum ] ;
out - > mesh - > numindexes = LittleLong ( in - > num_indexes ) ;
out - > mesh - > numvertexes = LittleLong ( in - > num_vertices ) ;
/*
Mod_AccumulateMeshTextureVectors ( out - > mesh ) ;
*/
2004-08-21 01:25:48 +00:00
}
2004-10-19 16:10:14 +00:00
else
{
2012-07-05 19:42:36 +00:00
out - > mesh = & mesh [ surfnum ] ;
out - > mesh - > numindexes = 6 ;
out - > mesh - > numvertexes = 4 ;
}
2004-08-21 01:25:48 +00:00
}
2013-03-12 23:10:44 +00:00
Mod_SortShaders ( ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
# endif
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadLeafFaces ( lump_t * l )
2006-03-04 20:43:48 +00:00
{
2004-08-21 01:25:48 +00:00
int i , j , count ;
int * in ;
int * out ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2006-03-04 20:43:48 +00:00
if ( count > MAX_Q2MAP_LEAFFACES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many leaffaces \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out = BZ_Malloc ( count * sizeof ( * out ) ) ;
map_leaffaces = out ;
numleaffaces = count ;
for ( i = 0 ; i < count ; i + + )
{
j = LittleLong ( in [ i ] ) ;
if ( j < 0 | | j > = numfaces )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " CMod_LoadLeafFaces: bad surface number \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out [ i ] = j ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadNodes ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i , j , count , p ;
q3dnode_t * in ;
mnode_t * out ;
//dnode_t
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2006-03-04 20:43:48 +00:00
out = Hunk_AllocName ( count * sizeof ( * out ) , loadname ) ;
2004-08-21 01:25:48 +00:00
if ( count > MAX_MAP_NODES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Too many nodes on map \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
loadmodel - > nodes = out ;
loadmodel - > numnodes = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
out - > minmaxs [ j ] = LittleLong ( in - > mins [ j ] ) ;
out - > minmaxs [ 3 + j ] = LittleLong ( in - > maxs [ j ] ) ;
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
p = LittleLong ( in - > plane ) ;
out - > plane = loadmodel - > planes + p ;
out - > firstsurface = 0 ; //LittleShort (in->firstface);
out - > numsurfaces = 0 ; //LittleShort (in->numfaces);
out - > contents = - 1 ;
for ( j = 0 ; j < 2 ; j + + )
{
p = LittleLong ( in - > children [ j ] ) ;
out - > childnum [ j ] = p ;
if ( p > = 0 )
{
out - > children [ j ] = loadmodel - > nodes + p ;
}
else
out - > children [ j ] = ( mnode_t * ) ( loadmodel - > leafs + ( - 1 - p ) ) ;
}
}
CMod_SetParent ( loadmodel - > nodes , NULL ) ; // sets nodes and leafs
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadBrushes ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
q3dbrush_t * in ;
q2cbrush_t * out ;
int i , count ;
int shaderref ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count > MAX_Q2MAP_BRUSHES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many brushes " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out = map_brushes ;
numbrushes = count ;
for ( i = 0 ; i < count ; i + + , out + + , in + + )
{
shaderref = LittleLong ( in - > shadernum ) ;
out - > contents = map_surfaces [ shaderref ] . c . value ;
2010-03-14 14:35:56 +00:00
out - > brushside = & map_brushsides [ LittleLong ( in - > firstside ) ] ;
2004-08-21 01:25:48 +00:00
out - > numsides = LittleLong ( in - > num_sides ) ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadLeafs ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i , j ;
mleaf_t * out ;
q3dleaf_t * in ;
int count ;
q2cbrush_t * brush ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no leafs \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
// need to save space for box planes
if ( count > MAX_MAP_LEAFS )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Too many leaves on map " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2006-03-04 20:43:48 +00:00
out = map_leafs ;
2004-08-21 01:25:48 +00:00
numleafs = count ;
numclusters = 0 ;
loadmodel - > leafs = out ;
loadmodel - > numleafs = count ;
emptyleaf = - 1 ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
2005-07-09 17:14:55 +00:00
out - > minmaxs [ 0 + j ] = LittleLong ( in - > mins [ j ] ) ;
out - > minmaxs [ 3 + j ] = LittleLong ( in - > maxs [ j ] ) ;
2004-08-21 01:25:48 +00:00
}
out - > cluster = LittleLong ( in - > cluster ) ;
out - > area = LittleLong ( in - > area ) + 1 ;
out - > firstleafface = LittleLong ( in - > firstleafsurface ) ;
out - > numleaffaces = LittleLong ( in - > num_leafsurfaces ) ;
out - > contents = 0 ;
out - > firstleafbrush = LittleLong ( in - > firstleafbrush ) ;
out - > numleafbrushes = LittleLong ( in - > num_leafbrushes ) ;
out - > firstmarksurface = loadmodel - > marksurfaces +
LittleLong ( in - > firstleafsurface ) ;
out - > nummarksurfaces = LittleLong ( in - > num_leafsurfaces ) ;
if ( out - > minmaxs [ 0 ] > out - > minmaxs [ 3 + 0 ] | | out - > minmaxs [ 1 ] > out - > minmaxs [ 3 + 1 ] | |
2009-07-18 20:46:42 +00:00
out - > minmaxs [ 2 ] > out - > minmaxs [ 3 + 2 ] | | VectorEquals ( out - > minmaxs , out - > minmaxs + 3 ) )
2004-08-21 01:25:48 +00:00
{
out - > nummarksurfaces = 0 ;
}
for ( j = 0 ; j < out - > numleafbrushes ; j + + )
{
brush = & map_brushes [ map_leafbrushes [ out - > firstleafbrush + j ] ] ;
out - > contents | = brush - > contents ;
}
if ( out - > area > = numareas ) {
numareas = out - > area + 1 ;
}
if ( ! out - > contents ) {
emptyleaf = i ;
}
}
// if map doesn't have an empty leaf - force one
if ( emptyleaf = = - 1 ) {
if ( numleafs > = MAX_MAP_LEAFS - 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map does not have an empty leaf \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out - > cluster = - 1 ;
out - > area = - 1 ;
out - > numleafbrushes = 0 ;
out - > contents = 0 ;
out - > firstleafbrush = 0 ;
Con_DPrintf ( " Forcing an empty leaf: %i \n " , numleafs ) ;
emptyleaf = numleafs + + ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadPlanes ( lump_t * l )
2006-03-04 20:43:48 +00:00
{
2004-08-21 01:25:48 +00:00
int i , j ;
mplane_t * out ;
Q3PLANE_t * in ;
int count ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2006-03-04 20:43:48 +00:00
out = map_planes ; //Hunk_AllocName ( count*2*sizeof(*out), loadname);
2004-08-21 01:25:48 +00:00
2005-05-26 12:55:34 +00:00
if ( count > MAX_MAP_PLANES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Too many planes on map \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-05-26 12:55:34 +00:00
2004-08-21 01:25:48 +00:00
numplanes = count ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
loadmodel - > planes = out ;
loadmodel - > numplanes = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
for ( j = 0 ; j < 3 ; j + + )
{
out - > normal [ j ] = LittleFloat ( in - > n [ j ] ) ;
}
out - > dist = LittleFloat ( in - > d ) ;
CategorizePlane ( out ) ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadLeafBrushes ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i ;
int * out ;
int * in ;
int count ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
if ( count < 1 )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map with no leafbrushes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
// need to save space for box planes
if ( count > MAX_Q2MAP_LEAFBRUSHES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many leafbrushes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out = map_leafbrushes ;
numleafbrushes = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
* out = LittleLong ( * in ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadBrushSides ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
int i , j ;
q2cbrushside_t * out ;
q3dbrushside_t * in ;
int count ;
int num ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
// need to save space for box planes
if ( count > MAX_Q2MAP_BRUSHSIDES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many planes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2006-03-04 20:43:48 +00:00
out = map_brushsides ;
2004-08-21 01:25:48 +00:00
numbrushsides = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
num = LittleLong ( in - > planenum ) ;
out - > plane = & map_planes [ num ] ;
j = LittleLong ( in - > texinfo ) ;
if ( j > = numtexinfo )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Bad brushside texinfo \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
out - > surface = & map_surfaces [ j ] ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModRBSP_LoadBrushSides ( lump_t * l )
2005-04-21 00:02:01 +00:00
{
int i , j ;
q2cbrushside_t * out ;
rbspbrushside_t * in ;
int count ;
int num ;
in = ( void * ) ( cmod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
count = l - > filelen / sizeof ( * in ) ;
// need to save space for box planes
if ( count > MAX_Q2MAP_BRUSHSIDES )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Map has too many planes \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
2006-03-04 20:43:48 +00:00
out = map_brushsides ;
2005-04-21 00:02:01 +00:00
numbrushsides = count ;
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
num = LittleLong ( in - > planenum ) ;
out - > plane = & map_planes [ num ] ;
j = LittleLong ( in - > texinfo ) ;
if ( j > = numtexinfo )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Bad brushside texinfo \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
out - > surface = & map_surfaces [ j ] ;
}
2006-03-13 05:54:12 +00:00
return true ;
2005-04-21 00:02:01 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadVisibility ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
2005-05-26 12:55:34 +00:00
if ( l - > filelen = = 0 )
{
int i ;
numclusters = 0 ;
for ( i = 0 ; i < loadmodel - > numleafs ; i + + )
if ( numclusters < = loadmodel - > leafs [ i ] . cluster )
numclusters = loadmodel - > leafs [ i ] . cluster + 1 ;
2004-08-21 01:25:48 +00:00
2005-05-26 12:55:34 +00:00
numclusters + + ;
2004-08-21 01:25:48 +00:00
2012-07-23 03:42:46 +00:00
map_q3pvs = Hunk_AllocName ( sizeof ( * map_q3pvs ) + ( numclusters + 7 ) / 8 * numclusters , " pvs " ) ;
2012-07-07 05:17:43 +00:00
memset ( map_q3pvs , 0xff , sizeof ( * map_q3pvs ) + ( numclusters + 7 ) / 8 * numclusters ) ;
2005-05-26 12:55:34 +00:00
map_q3pvs - > numclusters = numclusters ;
numvisibility = 0 ;
map_q3pvs - > rowsize = ( map_q3pvs - > numclusters + 7 ) / 8 ;
}
else
{
numvisibility = l - > filelen ;
2004-08-21 01:25:48 +00:00
2012-08-02 03:44:04 +00:00
map_q3pvs = Hunk_AllocName ( l - > filelen , " pvs " ) ;
2005-05-26 12:55:34 +00:00
loadmodel - > vis = ( q2dvis_t * ) map_q3pvs ;
2012-08-02 03:44:04 +00:00
memcpy ( map_q3pvs , cmod_base + l - > fileofs , l - > filelen ) ;
2005-05-26 12:55:34 +00:00
numclusters = map_q3pvs - > numclusters = LittleLong ( map_q3pvs - > numclusters ) ;
map_q3pvs - > rowsize = LittleLong ( map_q3pvs - > rowsize ) ;
}
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
# ifndef SERVERONLY
2013-03-12 23:09:25 +00:00
void CModQ3_LoadLighting ( lump_t * l )
{
qbyte * in = mod_base + l - > fileofs ;
qbyte * out ;
unsigned int samples = l - > filelen ;
int m , s ;
int mapsize = loadmodel - > lightmaps . width * loadmodel - > lightmaps . height * 3 ;
int maps ;
extern cvar_t gl_overbright ;
extern qbyte lmgamma [ 256 ] ;
extern void BuildLightMapGammaTable ( float g , float c ) ;
loadmodel - > engineflags & = ~ MDLF_RGBLIGHTING ;
//round up the samples, in case the last one is partial.
maps = ( ( samples + mapsize - 1 ) & ~ ( mapsize - 1 ) ) / mapsize ;
//q3 maps have built in 4-fold overbright.
//if we're not rendering with that, we need to brighten the lightmaps in order to keep the darker parts the same brightness. we loose the 2 upper bits. those bright areas become uniform and indistinct.
gl_overbright . flags | = CVAR_LATCH ;
BuildLightMapGammaTable ( 1 , ( 1 < < ( 2 - gl_overbright . ival ) ) ) ;
loadmodel - > engineflags | = MDLF_RGBLIGHTING ;
loadmodel - > lightdata = out = Hunk_AllocName ( samples , " lit data " ) ;
//be careful here, q3bsp deluxemapping is done using interleaving. we want to unoverbright ONLY lightmaps and not deluxemaps.
for ( m = 0 ; m < maps ; m + + )
{
if ( loadmodel - > lightmaps . deluxemapping & & ( m & 1 ) )
{
//no gamma for deluxemap
for ( s = 0 ; s < mapsize ; s + = 3 )
{
* out + + = in [ 0 ] ;
* out + + = in [ 1 ] ;
* out + + = in [ 2 ] ;
in + = 3 ;
}
}
else
{
for ( s = 0 ; s < mapsize ; s + + )
{
* out + + = lmgamma [ * in + + ] ;
}
if ( r_lightmap_saturation . value ! = 1.0f )
SaturateR8G8B8 ( out - mapsize , mapsize , r_lightmap_saturation . value ) ;
}
}
}
2006-03-13 05:54:12 +00:00
qboolean CModQ3_LoadLightgrid ( lump_t * l )
2004-08-21 01:25:48 +00:00
{
dq3gridlight_t * in ;
dq3gridlight_t * out ;
q3lightgridinfo_t * grid ;
int count ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2006-03-04 20:43:48 +00:00
grid = Hunk_AllocName ( sizeof ( q3lightgridinfo_t ) + count * sizeof ( * out ) , loadmodel - > name ) ;
2005-04-21 00:02:01 +00:00
grid - > lightgrid = ( dq3gridlight_t * ) ( grid + 1 ) ;
2004-08-21 01:25:48 +00:00
out = grid - > lightgrid ;
loadmodel - > lightgrid = grid ;
grid - > numlightgridelems = count ;
// lightgrid is all 8 bit
memcpy ( out , in , count * sizeof ( * out ) ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2006-03-13 05:54:12 +00:00
qboolean CModRBSP_LoadLightgrid ( lump_t * elements , lump_t * indexes )
2005-04-21 00:02:01 +00:00
{
unsigned short * iin ;
rbspgridlight_t * ein ;
unsigned short * iout ;
rbspgridlight_t * eout ;
q3lightgridinfo_t * grid ;
int ecount ;
int icount ;
int i ;
ein = ( void * ) ( mod_base + elements - > fileofs ) ;
iin = ( void * ) ( mod_base + indexes - > fileofs ) ;
if ( indexes - > filelen % sizeof ( * iin ) | | elements - > filelen % sizeof ( * ein ) )
2006-03-13 05:54:12 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , loadmodel - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
icount = indexes - > filelen / sizeof ( * iin ) ;
ecount = elements - > filelen / sizeof ( * ein ) ;
2006-03-04 20:43:48 +00:00
grid = Hunk_AllocName ( sizeof ( q3lightgridinfo_t ) + ecount * sizeof ( * eout ) + icount * sizeof ( * iout ) , loadmodel - > name ) ;
2012-07-05 19:42:36 +00:00
grid - > rbspelements = ( rbspgridlight_t * ) ( ( char * ) grid + sizeof ( q3lightgridinfo_t ) ) ;
grid - > rbspindexes = ( unsigned short * ) ( ( char * ) grid + sizeof ( q3lightgridinfo_t ) + ecount * sizeof ( * eout ) ) ;
2005-04-21 00:02:01 +00:00
eout = grid - > rbspelements ;
iout = grid - > rbspindexes ;
loadmodel - > lightgrid = grid ;
grid - > numlightgridelems = icount ;
// elements are all 8 bit
memcpy ( eout , ein , ecount * sizeof ( * eout ) ) ;
for ( i = 0 ; i < icount ; i + + )
iout [ i ] = LittleShort ( iin [ i ] ) ;
2006-03-13 05:54:12 +00:00
return true ;
2005-04-21 00:02:01 +00:00
}
2004-08-21 01:25:48 +00:00
# endif
# ifndef SERVERONLY
qbyte * ReadPCXPalette ( qbyte * buf , int len , qbyte * out ) ;
int CM_GetQ2Palette ( void )
{
2009-11-04 21:16:50 +00:00
char * f ;
2011-01-29 21:01:40 +00:00
FS_LoadFile ( " pics/colormap.pcx " , ( void * * ) & f ) ;
2004-08-21 01:25:48 +00:00
if ( ! f )
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_WARNING " Couldn't find pics/colormap.pcx \n " ) ;
2004-08-21 01:25:48 +00:00
return - 1 ;
}
if ( ! ReadPCXPalette ( f , com_filesize , d_q28to24table ) )
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_WARNING " Couldn't read pics/colormap.pcx \n " ) ;
2009-11-04 21:16:50 +00:00
FS_FreeFile ( f ) ;
2004-08-21 01:25:48 +00:00
return - 1 ;
}
2009-11-04 21:16:50 +00:00
FS_FreeFile ( f ) ;
2004-08-21 01:25:48 +00:00
2012-09-30 05:52:03 +00:00
# if 1
2004-08-21 01:25:48 +00:00
{
2007-08-21 18:42:42 +00:00
float inf ;
2004-08-21 01:25:48 +00:00
qbyte palette [ 768 ] ;
qbyte * pal ;
int i ;
pal = d_q28to24table ;
for ( i = 0 ; i < 768 ; i + + )
{
2007-08-21 18:42:42 +00:00
inf = ( ( pal [ i ] + 1 ) / 256.0 ) * 255 + 0.5 ;
2004-08-21 01:25:48 +00:00
if ( inf < 0 )
inf = 0 ;
if ( inf > 255 )
inf = 255 ;
palette [ i ] = inf ;
}
memcpy ( d_q28to24table , palette , sizeof ( palette ) ) ;
}
# endif
return 0 ;
}
# endif
void CM_OpenAllPortals ( char * ents ) //this is a compleate hack. About as compleate as possible.
{ //q2 levels contain a thingie called area portals. Basically, doors can seperate two areas and
//the engine knows when this portal is open, and weather to send ents from both sides of the door
//or not. It's not just ents, but also walls. We want to just open them by default and hope the
//progs knows how to close them.
char style [ 8 ] ;
char name [ 64 ] ;
if ( ! map_autoopenportals . value )
return ;
while ( * ents )
{
if ( * ents = = ' { ' ) //an entity
{
ents + + ;
* style = ' \0 ' ;
* name = ' \0 ' ;
while ( * ents )
{
ents = COM_Parse ( ents ) ;
if ( ! strcmp ( com_token , " classname " ) )
{
ents = COM_ParseOut ( ents , name , sizeof ( name ) ) ;
}
else if ( ! strcmp ( com_token , " style " ) )
{
ents = COM_ParseOut ( ents , style , sizeof ( style ) ) ;
}
else if ( * com_token = = ' } ' )
break ;
else
ents = COM_Parse ( ents ) ; //other field
ents + + ;
}
if ( ! strcmp ( name , " func_areaportal " ) )
{
CMQ2_SetAreaPortalState ( atoi ( style ) , true ) ;
}
}
ents + + ;
}
}
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2004-08-21 01:25:48 +00:00
void CMQ3_CalcPHS ( void )
{
int rowbytes , rowwords ;
int i , j , k , l , index ;
int bitbyte ;
2012-07-20 01:46:05 +00:00
unsigned int * dest , * src ;
2004-08-21 01:25:48 +00:00
qbyte * scan ;
int count , vcount ;
int numclusters ;
2012-07-24 00:20:45 +00:00
qboolean buggytools = false ;
2004-08-21 01:25:48 +00:00
Con_DPrintf ( " Building PHS... \n " ) ;
2012-07-23 03:42:46 +00:00
map_q3phs = Hunk_AllocName ( sizeof ( * map_q3phs ) + map_q3pvs - > rowsize * map_q3pvs - > numclusters , " phs " ) ;
2012-07-07 05:17:43 +00:00
2012-07-20 01:46:05 +00:00
rowwords = map_q3pvs - > rowsize / sizeof ( int ) ;
2004-08-21 01:25:48 +00:00
rowbytes = map_q3pvs - > rowsize ;
2012-07-23 03:42:46 +00:00
memset ( map_q3phs , 0 , sizeof ( * map_q3phs ) + map_q3pvs - > rowsize * map_q3pvs - > numclusters ) ;
2004-08-21 01:25:48 +00:00
map_q3phs - > rowsize = map_q3pvs - > rowsize ;
map_q3phs - > numclusters = numclusters = map_q3pvs - > numclusters ;
2005-05-13 10:42:48 +00:00
if ( ! numclusters )
return ;
2004-08-21 01:25:48 +00:00
vcount = 0 ;
for ( i = 0 ; i < numclusters ; i + + )
{
2009-11-04 21:16:50 +00:00
scan = CM_ClusterPVS ( sv . world . worldmodel , i , NULL , 0 ) ;
2004-08-21 01:25:48 +00:00
for ( j = 0 ; j < numclusters ; j + + )
{
if ( scan [ j > > 3 ] & ( 1 < < ( j & 7 ) ) )
{
vcount + + ;
}
}
}
count = 0 ;
scan = ( qbyte * ) map_q3pvs - > data ;
2012-07-20 01:46:05 +00:00
dest = ( unsigned int * ) ( map_q3phs - > data ) ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < numclusters ; i + + , dest + = rowwords , scan + = rowbytes )
{
memcpy ( dest , scan , rowbytes ) ;
for ( j = 0 ; j < rowbytes ; j + + )
{
bitbyte = scan [ j ] ;
if ( ! bitbyte )
continue ;
for ( k = 0 ; k < 8 ; k + + )
{
if ( ! ( bitbyte & ( 1 < < k ) ) )
continue ;
// OR this pvs row into the phs
index = ( j < < 3 ) + k ;
2012-07-23 03:42:46 +00:00
if ( index > = numclusters )
2012-07-24 00:20:45 +00:00
{
if ( ! buggytools )
Con_Printf ( " CM_CalcPHS: Bad bit(s) in PVS (%i >= %i) \n " , index , numclusters ) ; // pad bits should be 0
buggytools = true ;
}
else
{
src = ( unsigned int * ) ( map_q3pvs - > data ) + index * rowwords ;
for ( l = 0 ; l < rowwords ; l + + )
dest [ l ] | = src [ l ] ;
}
2004-08-21 01:25:48 +00:00
}
}
for ( j = 0 ; j < numclusters ; j + + )
if ( ( ( qbyte * ) dest ) [ j > > 3 ] & ( 1 < < ( j & 7 ) ) )
count + + ;
}
2011-09-03 03:49:43 +00:00
Con_DPrintf ( " Average clusters visible / hearable / total: %i / %i / %i \n "
2004-08-21 01:25:48 +00:00
, vcount / numclusters , count / numclusters , numclusters ) ;
}
2006-01-21 00:06:49 +00:00
# endif
2004-08-21 01:25:48 +00:00
2009-06-21 17:45:33 +00:00
qbyte * CM_LeafnumPVS ( model_t * model , int leafnum , qbyte * buffer , unsigned int buffersize )
2004-08-21 01:25:48 +00:00
{
2009-06-21 17:45:33 +00:00
return CM_ClusterPVS ( model , CM_LeafCluster ( model , leafnum ) , buffer , buffersize ) ;
2004-08-21 01:25:48 +00:00
}
# ifndef SERVERONLY
# define GLQ2BSP_LightPointValues GLQ1BSP_LightPointValues
# define SWQ2BSP_LightPointValues SWQ1BSP_LightPointValues
extern int r_dlightframecount ;
void Q2BSP_MarkLights ( dlight_t * light , int bit , mnode_t * node )
{
mplane_t * splitplane ;
float dist ;
msurface_t * surf ;
int i ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( node - > contents ! = - 1 )
2005-09-08 22:52:46 +00:00
{
mleaf_t * leaf = ( mleaf_t * ) node ;
msurface_t * * mark ;
2006-03-04 20:43:48 +00:00
2005-09-08 22:52:46 +00:00
i = leaf - > nummarksurfaces ;
mark = leaf - > firstmarksurface ;
while ( i - - ! = 0 )
{
surf = * mark + + ;
if ( surf - > dlightframe ! = r_dlightframecount )
{
surf - > dlightbits = 0 ;
surf - > dlightframe = r_dlightframecount ;
}
surf - > dlightbits | = bit ;
}
2005-10-01 03:09:17 +00:00
return ;
2005-09-08 22:52:46 +00:00
}
2004-08-21 01:25:48 +00:00
splitplane = node - > plane ;
dist = DotProduct ( light - > origin , splitplane - > normal ) - splitplane - > dist ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( dist > light - > radius )
{
Q2BSP_MarkLights ( light , bit , node - > children [ 0 ] ) ;
return ;
}
if ( dist < - light - > radius )
{
Q2BSP_MarkLights ( light , bit , node - > children [ 1 ] ) ;
return ;
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
// mark the polygons
surf = cl . worldmodel - > surfaces + node - > firstsurface ;
for ( i = 0 ; i < node - > numsurfaces ; i + + , surf + + )
{
if ( surf - > dlightframe ! = r_dlightframecount )
{
surf - > dlightbits = 0 ;
surf - > dlightframe = r_dlightframecount ;
}
surf - > dlightbits | = bit ;
}
Q2BSP_MarkLights ( light , bit , node - > children [ 0 ] ) ;
Q2BSP_MarkLights ( light , bit , node - > children [ 1 ] ) ;
}
# ifndef SERVERONLY
void GLR_Q2BSP_StainNode ( mnode_t * node , float * parms )
{
mplane_t * splitplane ;
float dist ;
msurface_t * surf ;
int i ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( node - > contents ! = - 1 )
2006-03-04 20:43:48 +00:00
return ;
2004-08-21 01:25:48 +00:00
splitplane = node - > plane ;
dist = DotProduct ( ( parms + 1 ) , splitplane - > normal ) - splitplane - > dist ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( dist > ( * parms ) )
{
GLR_Q2BSP_StainNode ( node - > children [ 0 ] , parms ) ;
return ;
}
if ( dist < ( - * parms ) )
{
GLR_Q2BSP_StainNode ( node - > children [ 1 ] , parms ) ;
return ;
}
// mark the polygons
surf = cl . worldmodel - > surfaces + node - > firstsurface ;
for ( i = 0 ; i < node - > numsurfaces ; i + + , surf + + )
{
if ( surf - > flags & ~ ( SURF_DONTWARP | SURF_PLANEBACK ) )
continue ;
2009-11-07 13:29:15 +00:00
Surf_StainSurf ( surf , parms ) ;
2004-08-21 01:25:48 +00:00
}
GLR_Q2BSP_StainNode ( node - > children [ 0 ] , parms ) ;
GLR_Q2BSP_StainNode ( node - > children [ 1 ] , parms ) ;
}
# endif
# endif
2006-09-17 00:59:22 +00:00
void GLQ2BSP_LightPointValues ( model_t * mod , vec3_t point , vec3_t res_diffuse , vec3_t res_ambient , vec3_t res_dir ) ;
2006-09-17 02:42:18 +00:00
void SWQ2BSP_LightPointValues ( model_t * mod , vec3_t point , vec3_t res_diffuse , vec3_t res_ambient , vec3_t res_dir ) ;
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = =
CM_LoadMap
Loads in the map and all submodels
= = = = = = = = = = = = = = = = = =
*/
2011-12-05 15:23:40 +00:00
cmodel_t * CM_LoadMap ( char * name , char * filein , qboolean clientload , unsigned * checksum )
2004-08-21 01:25:48 +00:00
{
unsigned * buf ;
int i , j ;
q2dheader_t header ;
int length ;
static unsigned last_checksum ;
2006-03-12 22:01:49 +00:00
qboolean noerrors = true ;
int start ;
2012-07-14 23:17:54 +00:00
model_t * im = loadmodel ;
2004-08-21 01:25:48 +00:00
2012-07-05 19:42:36 +00:00
void ( * buildmeshes ) ( model_t * mod , msurface_t * surf , void * cookie ) = NULL ;
void * buildcookie = NULL ;
2004-08-21 01:25:48 +00:00
// free old stuff
numplanes = 0 ;
numleafs = 0 ;
numcmodels = 0 ;
numvisibility = 0 ;
numentitychars = 0 ;
2005-07-14 01:57:34 +00:00
map_entitystring = NULL ;
2004-08-21 01:25:48 +00:00
loadmodel - > type = mod_brush ;
if ( ! name | | ! name [ 0 ] )
{
numleafs = 1 ;
numclusters = 1 ;
numareas = 1 ;
* checksum = 0 ;
return & map_cmodels [ 0 ] ; // cinematic servers won't have anything at all
}
//
// load the file
//
buf = ( unsigned * ) filein ;
length = com_filesize ;
if ( ! buf )
2006-03-12 22:01:49 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Couldn't load %s \n " , name ) ;
2006-03-12 22:01:49 +00:00
return NULL ;
}
2004-08-21 01:25:48 +00:00
last_checksum = LittleLong ( Com_BlockChecksum ( buf , length ) ) ;
* checksum = last_checksum ;
header = * ( q2dheader_t * ) ( buf ) ;
header . ident = LittleLong ( header . ident ) ;
header . version = LittleLong ( header . version ) ;
cmod_base = mod_base = ( qbyte * ) buf ;
2006-03-13 05:54:12 +00:00
start = Hunk_LowMark ( ) ;
2004-08-21 01:25:48 +00:00
2012-07-05 19:42:36 +00:00
if ( header . ident = = ( ( ' F ' < < 0 ) + ( ' B ' < < 8 ) + ( ' S ' < < 16 ) + ( ' P ' < < 24 ) ) )
{
loadmodel - > lightmaps . width = 512 ;
loadmodel - > lightmaps . height = 512 ;
}
else
{
loadmodel - > lightmaps . width = 128 ;
loadmodel - > lightmaps . height = 128 ;
}
2004-08-21 01:25:48 +00:00
switch ( header . version )
{
default :
2009-11-04 21:16:50 +00:00
Con_Printf ( CON_ERROR " Quake 2 or Quake 3 based BSP with unknown header (%s: %i should be %i or %i) \n "
2004-11-13 17:20:25 +00:00
, name , header . version , Q2BSPVERSION , Q3BSPVERSION ) ;
2006-03-12 22:01:49 +00:00
return NULL ;
2004-08-21 01:25:48 +00:00
break ;
# if 1
2012-07-05 19:42:36 +00:00
case 1 : //rbsp/fbsp
2005-04-21 00:02:01 +00:00
case Q3BSPVERSION + 1 : //rtcw
2004-08-21 01:25:48 +00:00
case Q3BSPVERSION :
mapisq3 = true ;
loadmodel - > fromgame = fg_quake3 ;
for ( i = 0 ; i < Q3LUMPS_TOTAL ; i + + )
{
2012-07-20 01:46:05 +00:00
if ( i = = RBSPLUMP_LIGHTINDEXES & & header . version ! = 1 )
{
header . lumps [ i ] . filelen = 0 ;
header . lumps [ i ] . fileofs = 0 ;
}
else
{
header . lumps [ i ] . filelen = LittleLong ( header . lumps [ i ] . filelen ) ;
header . lumps [ i ] . fileofs = LittleLong ( header . lumps [ i ] . fileofs ) ;
if ( header . lumps [ i ] . filelen & & header . lumps [ i ] . fileofs + header . lumps [ i ] . filelen > com_filesize )
{
Con_Printf ( CON_ERROR " WARNING: q3bsp %s truncated (lump %i, %i+%i > %i) \n " , name , i , header . lumps [ i ] . fileofs , header . lumps [ i ] . filelen , com_filesize ) ;
header . lumps [ i ] . filelen = com_filesize - header . lumps [ i ] . fileofs ;
if ( header . lumps [ i ] . filelen < 0 )
header . lumps [ i ] . filelen = 0 ;
}
}
2004-08-21 01:25:48 +00:00
}
/*
# ifndef SERVERONLY
GLMod_LoadVertexes ( & header . lumps [ Q3LUMP_DRAWVERTS ] ) ;
// GLMod_LoadEdges (&header.lumps[Q3LUMP_EDGES]);
// GLMod_LoadSurfedges (&header.lumps[Q3LUMP_SURFEDGES]);
GLMod_LoadLighting ( & header . lumps [ Q3LUMP_LIGHTMAPS ] ) ;
# endif
CModQ3_LoadShaders ( & header . lumps [ Q3LUMP_SHADERS ] ) ;
CModQ3_LoadPlanes ( & header . lumps [ Q3LUMP_PLANES ] ) ;
CModQ3_LoadLeafBrushes ( & header . lumps [ Q3LUMP_LEAFBRUSHES ] ) ;
CModQ3_LoadBrushes ( & header . lumps [ Q3LUMP_BRUSHES ] ) ;
CModQ3_LoadBrushSides ( & header . lumps [ Q3LUMP_BRUSHSIDES ] ) ;
# ifndef SERVERONLY
CMod_LoadTexInfo ( & header . lumps [ Q3LUMP_SHADERS ] ) ;
CMod_LoadFaces ( & header . lumps [ Q3LUMP_SURFACES ] ) ;
// GLMod_LoadMarksurfaces (&header.lumps[Q3LUMP_LEAFFACES]);
# endif
CMod_LoadVisibility ( & header . lumps [ Q3LUMP_VISIBILITY ] ) ;
CModQ3_LoadSubmodels ( & header . lumps [ Q3LUMP_MODELS ] ) ;
CModQ3_LoadLeafs ( & header . lumps [ Q3LUMP_LEAFS ] ) ;
CModQ3_LoadNodes ( & header . lumps [ Q3LUMP_NODES ] ) ;
// CMod_LoadAreas (&header.lumps[Q3LUMP_AREAS]);
// CMod_LoadAreaPortals (&header.lumps[Q3LUMP_AREAPORTALS]);
CMod_LoadEntityString ( & header . lumps [ Q3LUMP_ENTITIES ] ) ;
*/
2006-03-13 05:54:12 +00:00
map_faces = NULL ;
map_leaffaces = NULL ;
2012-02-27 12:23:15 +00:00
Q1BSPX_Setup ( loadmodel , mod_base , com_filesize , header . lumps , Q3LUMPS_TOTAL ) ;
2012-09-30 05:52:03 +00:00
mapisq3 = true ;
noerrors = noerrors & & CModQ3_LoadShaders ( & header . lumps [ Q3LUMP_SHADERS ] ) ;
noerrors = noerrors & & CModQ3_LoadPlanes ( & header . lumps [ Q3LUMP_PLANES ] ) ;
noerrors = noerrors & & CModQ3_LoadLeafBrushes ( & header . lumps [ Q3LUMP_LEAFBRUSHES ] ) ;
noerrors = noerrors & & CModQ3_LoadBrushes ( & header . lumps [ Q3LUMP_BRUSHES ] ) ;
if ( header . version = = 1 )
2004-08-21 01:25:48 +00:00
{
2012-09-30 05:52:03 +00:00
noerrors = noerrors & & CModRBSP_LoadBrushSides ( & header . lumps [ Q3LUMP_BRUSHSIDES ] ) ;
noerrors = noerrors & & CModRBSP_LoadVertexes ( & header . lumps [ Q3LUMP_DRAWVERTS ] ) ;
}
else
{
noerrors = noerrors & & CModQ3_LoadBrushSides ( & header . lumps [ Q3LUMP_BRUSHSIDES ] ) ;
noerrors = noerrors & & CModQ3_LoadVertexes ( & header . lumps [ Q3LUMP_DRAWVERTS ] ) ;
}
if ( header . version = = 1 )
noerrors = noerrors & & CModRBSP_LoadFaces ( & header . lumps [ Q3LUMP_SURFACES ] ) ;
else
noerrors = noerrors & & CModQ3_LoadFaces ( & header . lumps [ Q3LUMP_SURFACES ] ) ;
# ifndef SERVERONLY
if ( qrenderer ! = QR_NONE )
{
2005-04-21 00:02:01 +00:00
if ( header . version = = 1 )
2012-09-30 05:52:03 +00:00
noerrors = noerrors & & CModRBSP_LoadLightgrid ( & header . lumps [ Q3LUMP_LIGHTGRID ] , & header . lumps [ RBSPLUMP_LIGHTINDEXES ] ) ;
2005-04-21 00:02:01 +00:00
else
2012-09-30 05:52:03 +00:00
noerrors = noerrors & & CModQ3_LoadLightgrid ( & header . lumps [ Q3LUMP_LIGHTGRID ] ) ;
noerrors = noerrors & & CModQ3_LoadIndexes ( & header . lumps [ Q3LUMP_DRAWINDEXES ] ) ;
if ( header . version ! = Q3BSPVERSION + 1 )
noerrors = noerrors & & CModQ3_LoadFogs ( & header . lumps [ Q3LUMP_FOGS ] ) ;
else
map_numfogs = 0 ;
buildcookie = ( void * ) ( mod_base + header . lumps [ Q3LUMP_SURFACES ] . fileofs ) ;
if ( header . version = = 1 )
2005-04-21 00:02:01 +00:00
{
2012-09-30 05:52:03 +00:00
noerrors = noerrors & & CModRBSP_LoadRFaces ( & header . lumps [ Q3LUMP_SURFACES ] ) ;
buildmeshes = CModRBSP_BuildSurfMesh ;
2013-05-03 04:28:08 +00:00
loadmodel - > lightmaps . surfstyles = 4 ;
2005-04-21 00:02:01 +00:00
}
else
2004-08-21 01:25:48 +00:00
{
2012-09-30 05:52:03 +00:00
noerrors = noerrors & & CModQ3_LoadRFaces ( & header . lumps [ Q3LUMP_SURFACES ] ) ;
buildmeshes = CModQ3_BuildSurfMesh ;
2013-05-03 04:28:08 +00:00
loadmodel - > lightmaps . surfstyles = 1 ;
2012-09-30 05:52:03 +00:00
}
noerrors = noerrors & & CModQ3_LoadMarksurfaces ( & header . lumps [ Q3LUMP_LEAFSURFACES ] ) ; //fixme: duplicated loading.
2010-08-28 17:14:38 +00:00
2012-09-30 05:52:03 +00:00
/*make sure all textures have a shader*/
for ( i = 0 ; i < loadmodel - > numtextures ; i + + )
{
if ( ! loadmodel - > textures [ i ] - > shader )
loadmodel - > textures [ i ] - > shader = R_RegisterShader_Lightmap ( loadmodel - > textures [ i ] - > name ) ;
2004-08-21 01:25:48 +00:00
}
2013-03-12 23:09:25 +00:00
if ( loadmodel - > fromgame = = fg_quake3 )
{
i = header . lumps [ Q3LUMP_LIGHTMAPS ] . filelen / ( loadmodel - > lightmaps . width * loadmodel - > lightmaps . height * 3 ) ;
loadmodel - > lightmaps . deluxemapping = ! ( i & 1 ) ;
loadmodel - > lightmaps . count = max ( loadmodel - > lightmaps . count , i ) ;
for ( i = 0 ; i < loadmodel - > numsurfaces & & loadmodel - > lightmaps . deluxemapping ; i + + )
{
if ( loadmodel - > surfaces [ i ] . lightmaptexturenums [ 0 ] > = 0 & & ( loadmodel - > surfaces [ i ] . lightmaptexturenums [ 0 ] & 1 ) )
loadmodel - > lightmaps . deluxemapping = false ;
}
}
if ( noerrors )
CModQ3_LoadLighting ( & header . lumps [ Q3LUMP_LIGHTMAPS ] ) ; //fixme: duplicated loading.
2012-09-30 05:52:03 +00:00
}
2004-08-21 01:25:48 +00:00
# endif
2012-09-30 05:52:03 +00:00
noerrors = noerrors & & CModQ3_LoadLeafFaces ( & header . lumps [ Q3LUMP_LEAFSURFACES ] ) ;
noerrors = noerrors & & CModQ3_LoadLeafs ( & header . lumps [ Q3LUMP_LEAFS ] ) ;
noerrors = noerrors & & CModQ3_LoadNodes ( & header . lumps [ Q3LUMP_NODES ] ) ;
noerrors = noerrors & & CModQ3_LoadSubmodels ( & header . lumps [ Q3LUMP_MODELS ] ) ;
noerrors = noerrors & & CModQ3_LoadVisibility ( & header . lumps [ Q3LUMP_VISIBILITY ] ) ;
if ( noerrors )
CMod_LoadEntityString ( & header . lumps [ Q3LUMP_ENTITIES ] ) ;
2006-03-13 05:54:12 +00:00
2012-09-30 05:52:03 +00:00
if ( ! noerrors )
{
if ( map_faces )
BZ_Free ( map_faces ) ;
if ( map_leaffaces )
BZ_Free ( map_leaffaces ) ;
2006-03-13 05:54:12 +00:00
2012-09-30 05:52:03 +00:00
Hunk_FreeToLowMark ( start ) ;
return NULL ;
}
2004-08-21 01:25:48 +00:00
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2012-09-30 05:52:03 +00:00
loadmodel - > funcs . FatPVS = Q2BSP_FatPVS ;
loadmodel - > funcs . EdictInFatPVS = Q2BSP_EdictInFatPVS ;
loadmodel - > funcs . FindTouchedLeafs = Q2BSP_FindTouchedLeafs ;
2006-01-21 00:06:49 +00:00
# endif
2012-09-30 05:52:03 +00:00
loadmodel - > funcs . LeafPVS = CM_LeafnumPVS ;
loadmodel - > funcs . LeafnumForPoint = CM_PointLeafnum ;
2004-08-21 01:25:48 +00:00
2012-09-30 05:52:03 +00:00
# ifndef SERVERONLY
loadmodel - > funcs . LightPointValues = GLQ3_LightGrid ;
loadmodel - > funcs . StainNode = GLR_Q2BSP_StainNode ;
loadmodel - > funcs . MarkLights = Q2BSP_MarkLights ;
2004-08-21 01:25:48 +00:00
# endif
2012-09-30 05:52:03 +00:00
loadmodel - > funcs . PointContents = Q2BSP_PointContents ;
loadmodel - > funcs . NativeTrace = CM_NativeTrace ;
loadmodel - > funcs . NativeContents = CM_NativeContents ;
2004-08-21 01:25:48 +00:00
# ifndef SERVERONLY
2012-09-30 05:52:03 +00:00
//light grid info
if ( loadmodel - > lightgrid )
{
float maxs ;
q3lightgridinfo_t * lg = loadmodel - > lightgrid ;
if ( lg - > gridSize [ 0 ] < 1 | | lg - > gridSize [ 1 ] < 1 | | lg - > gridSize [ 2 ] < 1 )
2004-08-21 01:25:48 +00:00
{
2012-09-30 05:52:03 +00:00
lg - > gridSize [ 0 ] = 64 ;
lg - > gridSize [ 1 ] = 64 ;
lg - > gridSize [ 2 ] = 128 ;
2004-08-21 01:25:48 +00:00
}
2012-09-30 05:52:03 +00:00
for ( i = 0 ; i < 3 ; i + + )
2006-03-13 05:54:12 +00:00
{
2012-09-30 05:52:03 +00:00
lg - > gridMins [ i ] = lg - > gridSize [ i ] * ceil ( ( map_cmodels - > mins [ i ] + 1 ) / lg - > gridSize [ i ] ) ;
maxs = lg - > gridSize [ i ] * floor ( ( map_cmodels - > maxs [ i ] - 1 ) / lg - > gridSize [ i ] ) ;
lg - > gridBounds [ i ] = ( maxs - lg - > gridMins [ i ] ) / lg - > gridSize [ i ] + 1 ;
2006-03-13 05:54:12 +00:00
}
2012-09-30 05:52:03 +00:00
lg - > gridBounds [ 3 ] = lg - > gridBounds [ 1 ] * lg - > gridBounds [ 0 ] ;
}
2006-01-21 00:06:49 +00:00
# endif
2012-09-30 05:52:03 +00:00
if ( ! CM_CreatePatchesForLeafs ( ) ) //for clipping
{
2004-08-21 01:25:48 +00:00
BZ_Free ( map_faces ) ;
BZ_Free ( map_leaffaces ) ;
2012-09-30 05:52:03 +00:00
Hunk_FreeToLowMark ( start ) ;
2006-03-12 22:01:49 +00:00
return NULL ;
2004-08-21 01:25:48 +00:00
}
2012-09-30 05:52:03 +00:00
# ifndef CLIENTONLY
CMQ3_CalcPHS ( ) ;
# endif
// BZ_Free(map_verts);
BZ_Free ( map_faces ) ;
BZ_Free ( map_leaffaces ) ;
2004-08-21 01:25:48 +00:00
break ;
# endif
case Q2BSPVERSION :
mapisq3 = false ;
2006-04-16 07:01:06 +00:00
loadmodel - > engineflags | = MDLF_NEEDOVERBRIGHT ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < Q2HEADER_LUMPS ; i + + )
{
header . lumps [ i ] . filelen = LittleLong ( header . lumps [ i ] . filelen ) ;
header . lumps [ i ] . fileofs = LittleLong ( header . lumps [ i ] . fileofs ) ;
}
2012-02-27 12:23:15 +00:00
Q1BSPX_Setup ( loadmodel , mod_base , com_filesize , header . lumps , Q2HEADER_LUMPS ) ;
2004-08-21 01:25:48 +00:00
# ifndef SERVERONLY
if ( CM_GetQ2Palette ( ) )
memcpy ( d_q28to24table , host_basepal , 768 ) ;
# endif
switch ( qrenderer )
{
case QR_NONE : //dedicated only
2006-03-13 05:54:12 +00:00
noerrors = noerrors & & CMod_LoadSurfaces ( & header . lumps [ Q2LUMP_TEXINFO ] ) ;
noerrors = noerrors & & CMod_LoadLeafBrushes ( & header . lumps [ Q2LUMP_LEAFBRUSHES ] ) ;
noerrors = noerrors & & CMod_LoadPlanes ( & header . lumps [ Q2LUMP_PLANES ] ) ;
noerrors = noerrors & & CMod_LoadVisibility ( & header . lumps [ Q2LUMP_VISIBILITY ] ) ;
noerrors = noerrors & & CMod_LoadBrushes ( & header . lumps [ Q2LUMP_BRUSHES ] ) ;
noerrors = noerrors & & CMod_LoadBrushSides ( & header . lumps [ Q2LUMP_BRUSHSIDES ] ) ;
noerrors = noerrors & & CMod_LoadSubmodels ( & header . lumps [ Q2LUMP_MODELS ] ) ;
noerrors = noerrors & & CMod_LoadLeafs ( & header . lumps [ Q2LUMP_LEAFS ] ) ;
noerrors = noerrors & & CMod_LoadNodes ( & header . lumps [ Q2LUMP_NODES ] ) ;
noerrors = noerrors & & CMod_LoadAreas ( & header . lumps [ Q2LUMP_AREAS ] ) ;
noerrors = noerrors & & CMod_LoadAreaPortals ( & header . lumps [ Q2LUMP_AREAPORTALS ] ) ;
if ( noerrors )
CMod_LoadEntityString ( & header . lumps [ Q2LUMP_ENTITIES ] ) ;
2004-08-21 01:25:48 +00:00
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2004-08-21 01:25:48 +00:00
loadmodel - > funcs . FatPVS = Q2BSP_FatPVS ;
loadmodel - > funcs . EdictInFatPVS = Q2BSP_EdictInFatPVS ;
2010-07-11 02:22:39 +00:00
loadmodel - > funcs . FindTouchedLeafs = Q2BSP_FindTouchedLeafs ;
2006-01-21 00:06:49 +00:00
# endif
2004-08-21 01:25:48 +00:00
loadmodel - > funcs . LightPointValues = NULL ;
loadmodel - > funcs . StainNode = NULL ;
loadmodel - > funcs . MarkLights = NULL ;
loadmodel - > funcs . LeafPVS = CM_LeafnumPVS ;
2005-08-26 22:56:51 +00:00
loadmodel - > funcs . LeafnumForPoint = CM_PointLeafnum ;
loadmodel - > funcs . PointContents = Q2BSP_PointContents ;
2006-03-06 01:41:09 +00:00
loadmodel - > funcs . NativeTrace = CM_NativeTrace ;
loadmodel - > funcs . NativeContents = CM_NativeContents ;
2004-08-21 01:25:48 +00:00
break ;
2010-11-11 18:22:49 +00:00
# if defined(GLQUAKE) || defined(D3DQUAKE)
2012-09-30 05:52:03 +00:00
case QR_DIRECT3D9 :
case QR_DIRECT3D11 :
2004-08-21 01:25:48 +00:00
case QR_OPENGL :
// load into heap
# ifndef SERVERONLY
2009-11-04 21:16:50 +00:00
noerrors = noerrors & & RMod_LoadVertexes ( & header . lumps [ Q2LUMP_VERTEXES ] ) ;
2011-10-27 16:16:29 +00:00
noerrors = noerrors & & RMod_LoadEdges ( & header . lumps [ Q2LUMP_EDGES ] , false ) ;
2009-11-04 21:16:50 +00:00
noerrors = noerrors & & RMod_LoadSurfedges ( & header . lumps [ Q2LUMP_SURFEDGES ] ) ;
2006-03-12 22:01:49 +00:00
if ( noerrors )
2009-11-04 21:16:50 +00:00
RMod_LoadLighting ( & header . lumps [ Q2LUMP_LIGHTING ] ) ;
2004-08-21 01:25:48 +00:00
# endif
2006-03-13 05:54:12 +00:00
noerrors = noerrors & & CMod_LoadSurfaces ( & header . lumps [ Q2LUMP_TEXINFO ] ) ;
noerrors = noerrors & & CMod_LoadLeafBrushes ( & header . lumps [ Q2LUMP_LEAFBRUSHES ] ) ;
noerrors = noerrors & & CMod_LoadPlanes ( & header . lumps [ Q2LUMP_PLANES ] ) ;
2004-08-21 01:25:48 +00:00
# ifndef SERVERONLY
2006-03-13 05:54:12 +00:00
noerrors = noerrors & & CMod_LoadTexInfo ( & header . lumps [ Q2LUMP_TEXINFO ] ) ;
noerrors = noerrors & & CMod_LoadFaces ( & header . lumps [ Q2LUMP_FACES ] ) ;
2011-12-05 15:23:40 +00:00
noerrors = noerrors & & RMod_LoadMarksurfaces ( & header . lumps [ Q2LUMP_LEAFFACES ] , false ) ;
2004-08-21 01:25:48 +00:00
# endif
2006-03-13 05:54:12 +00:00
noerrors = noerrors & & CMod_LoadVisibility ( & header . lumps [ Q2LUMP_VISIBILITY ] ) ;
noerrors = noerrors & & CMod_LoadBrushes ( & header . lumps [ Q2LUMP_BRUSHES ] ) ;
noerrors = noerrors & & CMod_LoadBrushSides ( & header . lumps [ Q2LUMP_BRUSHSIDES ] ) ;
noerrors = noerrors & & CMod_LoadSubmodels ( & header . lumps [ Q2LUMP_MODELS ] ) ;
noerrors = noerrors & & CMod_LoadLeafs ( & header . lumps [ Q2LUMP_LEAFS ] ) ;
noerrors = noerrors & & CMod_LoadNodes ( & header . lumps [ Q2LUMP_NODES ] ) ;
noerrors = noerrors & & CMod_LoadAreas ( & header . lumps [ Q2LUMP_AREAS ] ) ;
noerrors = noerrors & & CMod_LoadAreaPortals ( & header . lumps [ Q2LUMP_AREAPORTALS ] ) ;
if ( noerrors )
CMod_LoadEntityString ( & header . lumps [ Q2LUMP_ENTITIES ] ) ;
2006-03-12 22:01:49 +00:00
if ( ! noerrors )
{
Hunk_FreeToLowMark ( start ) ;
return NULL ;
}
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2004-08-21 01:25:48 +00:00
loadmodel - > funcs . FatPVS = Q2BSP_FatPVS ;
loadmodel - > funcs . EdictInFatPVS = Q2BSP_EdictInFatPVS ;
2010-07-11 02:22:39 +00:00
loadmodel - > funcs . FindTouchedLeafs = Q2BSP_FindTouchedLeafs ;
2006-01-21 00:06:49 +00:00
# endif
2004-08-21 01:25:48 +00:00
loadmodel - > funcs . LightPointValues = GLQ2BSP_LightPointValues ;
loadmodel - > funcs . StainNode = GLR_Q2BSP_StainNode ;
loadmodel - > funcs . MarkLights = Q2BSP_MarkLights ;
loadmodel - > funcs . LeafPVS = CM_LeafnumPVS ;
2005-08-26 22:56:51 +00:00
loadmodel - > funcs . LeafnumForPoint = CM_PointLeafnum ;
loadmodel - > funcs . PointContents = Q2BSP_PointContents ;
2006-03-06 01:41:09 +00:00
loadmodel - > funcs . NativeTrace = CM_NativeTrace ;
loadmodel - > funcs . NativeContents = CM_NativeContents ;
2004-08-21 01:25:48 +00:00
break ;
# endif
default :
2007-05-25 22:16:29 +00:00
Hunk_FreeToLowMark ( start ) ;
return NULL ;
2006-03-04 20:43:48 +00:00
Sys_Error ( " Bad internal renderer on q2 map load \n " ) ;
2004-08-21 01:25:48 +00:00
}
}
# ifndef SERVERONLY
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
Mod_ParseInfoFromEntityLump ( loadmodel , loadmodel - > entities , loadname ) ; //only done for client's world model (or server if the server is loading it for client)
2004-08-21 01:25:48 +00:00
# endif
CM_InitBoxHull ( ) ;
if ( map_autoopenportals . value )
memset ( portalopen , 1 , sizeof ( portalopen ) ) ; //open them all. Used for progs that havn't got a clue.
else
memset ( portalopen , 0 , sizeof ( portalopen ) ) ; //make them start closed.
FloodAreaConnections ( ) ;
2005-09-08 22:52:46 +00:00
loadmodel - > checksum = loadmodel - > checksum2 = * checksum ;
2004-08-21 01:25:48 +00:00
2012-07-05 19:42:36 +00:00
loadmodel - > nummodelsurfaces = loadmodel - > numsurfaces ;
memset ( & loadmodel - > batches , 0 , sizeof ( loadmodel - > batches ) ) ;
loadmodel - > vbos = NULL ;
# ifndef SERVERONLY
if ( qrenderer ! = QR_NONE )
RMod_Batches_Build ( NULL , loadmodel , buildmeshes , buildcookie ) ;
# endif
2004-08-21 01:25:48 +00:00
2005-08-26 22:56:51 +00:00
loadmodel - > numsubmodels = CM_NumInlineModels ( loadmodel ) ;
2004-08-21 01:25:48 +00:00
{
model_t * mod = loadmodel ;
mod - > hulls [ 0 ] . firstclipnode = map_cmodels [ 0 ] . headnode ;
mod - > hulls [ 0 ] . available = true ;
for ( j = 1 ; j < MAX_MAP_HULLSM ; j + + )
{
mod - > hulls [ j ] . firstclipnode = map_cmodels [ 0 ] . headnode ;
mod - > hulls [ j ] . available = false ;
}
2011-12-23 03:12:29 +00:00
mod - > nummodelsurfaces = map_cmodels [ 0 ] . numsurfaces ;
2004-08-21 01:25:48 +00:00
for ( i = 1 ; i < loadmodel - > numsubmodels ; i + + )
{
2011-12-05 15:23:40 +00:00
cmodel_t * bm ;
2004-08-21 01:25:48 +00:00
char name [ 10 ] ;
sprintf ( name , " *%i " , i ) ;
loadmodel = Mod_FindName ( name ) ;
* loadmodel = * mod ;
strcpy ( loadmodel - > name , name ) ;
mod = loadmodel ;
bm = CM_InlineModel ( name ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
mod - > hulls [ 0 ] . firstclipnode = bm - > headnode ;
2010-08-28 17:14:38 +00:00
mod - > hulls [ 0 ] . available = true ;
2004-08-21 01:25:48 +00:00
mod - > nummodelsurfaces = bm - > numsurfaces ;
mod - > firstmodelsurface = bm - > firstsurface ;
for ( j = 1 ; j < MAX_MAP_HULLSM ; j + + )
{
mod - > hulls [ j ] . firstclipnode = bm - > headnode ;
mod - > hulls [ j ] . lastclipnode = mod - > numclipnodes - 1 ;
mod - > hulls [ j ] . available = false ;
}
2006-03-04 20:43:48 +00:00
2012-07-05 19:42:36 +00:00
memset ( & mod - > batches , 0 , sizeof ( mod - > batches ) ) ;
mod - > vbos = NULL ;
# ifndef SERVERONLY
if ( qrenderer ! = QR_NONE )
RMod_Batches_Build ( NULL , mod , buildmeshes , buildcookie ) ;
# endif
2004-08-21 01:25:48 +00:00
VectorCopy ( bm - > maxs , mod - > maxs ) ;
VectorCopy ( bm - > mins , mod - > mins ) ;
# ifndef SERVERONLY
mod - > radius = RadiusFromBounds ( mod - > mins , mod - > maxs ) ;
2005-03-10 03:55:18 +00:00
P_DefaultTrail ( mod ) ;
2004-08-21 01:25:48 +00:00
# endif
}
}
2012-07-14 23:17:54 +00:00
# ifdef TERRAIN
im - > terrain = Mod_LoadTerrainInfo ( im , loadname ) ;
# endif
2004-08-21 01:25:48 +00:00
return & map_cmodels [ 0 ] ;
}
/*
= = = = = = = = = = = = = = = = = =
CM_InlineModel
= = = = = = = = = = = = = = = = = =
*/
2011-12-05 15:23:40 +00:00
cmodel_t * CM_InlineModel ( char * name )
2004-08-21 01:25:48 +00:00
{
int num ;
if ( ! name )
Host_Error ( " Bad model \n " ) ;
else if ( name [ 0 ] ! = ' * ' )
Host_Error ( " Bad model \n " ) ;
num = atoi ( name + 1 ) ;
if ( num < 1 | | num > = numcmodels )
Host_Error ( " CM_InlineModel: bad number " ) ;
return & map_cmodels [ num ] ;
}
2005-08-26 22:56:51 +00:00
int CM_NumClusters ( model_t * model )
2004-08-21 01:25:48 +00:00
{
return numclusters ;
}
2005-08-26 22:56:51 +00:00
int CM_ClusterSize ( model_t * model )
2004-08-21 01:25:48 +00:00
{
2005-05-26 12:55:34 +00:00
return map_q3pvs - > rowsize ? map_q3pvs - > rowsize : MAX_MAP_LEAFS / 8 ;
2004-08-21 01:25:48 +00:00
}
2005-08-26 22:56:51 +00:00
int CM_NumInlineModels ( model_t * model )
2004-08-21 01:25:48 +00:00
{
return numcmodels ;
}
2005-08-26 22:56:51 +00:00
char * CM_EntityString ( model_t * model )
2004-08-21 01:25:48 +00:00
{
return map_entitystring ;
}
2005-08-26 22:56:51 +00:00
int CM_LeafContents ( model_t * model , int leafnum )
2004-08-21 01:25:48 +00:00
{
2012-09-30 05:52:03 +00:00
if ( leafnum < 0 | | leafnum > = model - > numleafs )
2004-08-21 01:25:48 +00:00
Host_Error ( " CM_LeafContents: bad number " ) ;
return map_leafs [ leafnum ] . contents ;
}
2005-08-26 22:56:51 +00:00
int CM_LeafCluster ( model_t * model , int leafnum )
2004-08-21 01:25:48 +00:00
{
2012-09-30 05:52:03 +00:00
if ( leafnum < 0 | | leafnum > = model - > numleafs )
2004-08-21 01:25:48 +00:00
Host_Error ( " CM_LeafCluster: bad number " ) ;
return map_leafs [ leafnum ] . cluster ;
}
2005-08-26 22:56:51 +00:00
int CM_LeafArea ( model_t * model , int leafnum )
2004-08-21 01:25:48 +00:00
{
2012-09-30 05:52:03 +00:00
if ( leafnum < 0 | | leafnum > = model - > numleafs )
2004-08-21 01:25:48 +00:00
Host_Error ( " CM_LeafArea: bad number " ) ;
return map_leafs [ leafnum ] . area ;
}
//=======================================================================
mplane_t * box_planes ;
int box_headnode ;
q2cbrush_t * box_brush ;
mleaf_t * box_leaf ;
2004-12-24 08:45:56 +00:00
model_t box_model ;
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = = =
CM_InitBoxHull
Set up the planes and nodes so that the six floats of a bounding box
can just be stored out and get a proper clipping hull structure .
= = = = = = = = = = = = = = = = = = =
*/
void CM_InitBoxHull ( void )
{
int i ;
int side ;
mnode_t * c ;
mplane_t * p ;
q2cbrushside_t * s ;
2004-12-24 08:45:56 +00:00
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2004-12-24 08:45:56 +00:00
box_model . funcs . FatPVS = Q2BSP_FatPVS ;
box_model . funcs . EdictInFatPVS = Q2BSP_EdictInFatPVS ;
2010-07-11 02:22:39 +00:00
box_model . funcs . FindTouchedLeafs = Q2BSP_FindTouchedLeafs ;
2006-01-21 00:06:49 +00:00
# endif
2004-12-24 09:10:39 +00:00
# ifndef SERVERONLY
2004-12-24 08:45:56 +00:00
box_model . funcs . MarkLights = Q2BSP_MarkLights ;
2004-12-24 09:10:39 +00:00
# endif
2004-12-24 08:45:56 +00:00
box_model . funcs . LeafPVS = CM_LeafnumPVS ;
2005-08-26 22:56:51 +00:00
box_model . funcs . LeafnumForPoint = CM_PointLeafnum ;
2006-03-10 03:53:17 +00:00
box_model . funcs . NativeContents = CM_NativeContents ;
box_model . funcs . NativeTrace = CM_NativeTrace ;
2004-12-24 08:45:56 +00:00
box_model . hulls [ 0 ] . available = true ;
2005-08-26 22:56:51 +00:00
box_model . nodes = Hunk_Alloc ( sizeof ( mnode_t ) * 6 ) ;
2004-08-21 01:25:48 +00:00
box_planes = & map_planes [ numplanes ] ;
2005-08-26 22:56:51 +00:00
if ( numbrushes + 1 > MAX_Q2MAP_BRUSHES
2004-08-21 01:25:48 +00:00
| | numleafbrushes + 1 > MAX_Q2MAP_LEAFBRUSHES
| | numbrushsides + 6 > MAX_Q2MAP_BRUSHSIDES
| | numplanes + 12 > MAX_Q2MAP_PLANES )
Host_Error ( " Not enough room for box tree " ) ;
box_brush = & map_brushes [ numbrushes ] ;
box_brush - > numsides = 6 ;
2010-03-14 14:35:56 +00:00
box_brush - > brushside = & map_brushsides [ numbrushsides ] ;
2004-08-21 01:25:48 +00:00
box_brush - > contents = Q2CONTENTS_MONSTER ;
box_leaf = & map_leafs [ numleafs ] ;
box_leaf - > contents = Q2CONTENTS_MONSTER ;
box_leaf - > firstleafbrush = numleafbrushes ;
box_leaf - > numleafbrushes = 1 ;
map_leafbrushes [ numleafbrushes ] = numbrushes ;
for ( i = 0 ; i < 6 ; i + + )
{
side = i & 1 ;
// brush sides
s = & map_brushsides [ numbrushsides + i ] ;
s - > plane = map_planes + ( numplanes + i * 2 + side ) ;
s - > surface = & nullsurface ;
// nodes
2005-08-26 22:56:51 +00:00
c = & box_model . nodes [ i ] ;
2004-08-21 01:25:48 +00:00
c - > plane = map_planes + ( numplanes + i * 2 ) ;
c - > childnum [ side ] = - 1 - emptyleaf ;
if ( i ! = 5 )
c - > childnum [ side ^ 1 ] = box_headnode + i + 1 ;
else
c - > childnum [ side ^ 1 ] = - 1 - numleafs ;
// planes
p = & box_planes [ i * 2 ] ;
p - > type = i > > 1 ;
p - > signbits = 0 ;
VectorClear ( p - > normal ) ;
p - > normal [ i > > 1 ] = 1 ;
p = & box_planes [ i * 2 + 1 ] ;
p - > type = 3 + ( i > > 1 ) ;
p - > signbits = 0 ;
VectorClear ( p - > normal ) ;
p - > normal [ i > > 1 ] = - 1 ;
2006-03-04 20:43:48 +00:00
}
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
CM_HeadnodeForBox
To keep everything totally uniform , bounding boxes are turned into small
BSP trees instead of being compared directly .
= = = = = = = = = = = = = = = = = = =
*/
2005-08-26 22:56:51 +00:00
void CM_SetTempboxSize ( vec3_t mins , vec3_t maxs )
2004-08-21 01:25:48 +00:00
{
box_planes [ 0 ] . dist = maxs [ 0 ] ;
box_planes [ 1 ] . dist = - maxs [ 0 ] ;
box_planes [ 2 ] . dist = mins [ 0 ] ;
box_planes [ 3 ] . dist = - mins [ 0 ] ;
box_planes [ 4 ] . dist = maxs [ 1 ] ;
box_planes [ 5 ] . dist = - maxs [ 1 ] ;
box_planes [ 6 ] . dist = mins [ 1 ] ;
box_planes [ 7 ] . dist = - mins [ 1 ] ;
box_planes [ 8 ] . dist = maxs [ 2 ] ;
box_planes [ 9 ] . dist = - maxs [ 2 ] ;
box_planes [ 10 ] . dist = mins [ 2 ] ;
box_planes [ 11 ] . dist = - mins [ 2 ] ;
}
2004-12-24 08:45:56 +00:00
model_t * CM_TempBoxModel ( vec3_t mins , vec3_t maxs )
{
2006-03-06 01:41:09 +00:00
if ( box_planes = = NULL )
CM_InitBoxHull ( ) ;
2005-08-26 22:56:51 +00:00
CM_SetTempboxSize ( mins , maxs ) ;
2004-12-24 08:45:56 +00:00
return & box_model ;
}
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = =
CM_PointLeafnum_r
= = = = = = = = = = = = = = = = = =
*/
2005-08-26 22:56:51 +00:00
int CM_PointLeafnum_r ( model_t * mod , vec3_t p , int num )
2004-08-21 01:25:48 +00:00
{
float d ;
mnode_t * node ;
mplane_t * plane ;
while ( num > = 0 )
{
2005-08-26 22:56:51 +00:00
node = mod - > nodes + num ;
2004-08-21 01:25:48 +00:00
plane = node - > plane ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( plane - > type < 3 )
d = p [ plane - > type ] - plane - > dist ;
else
d = DotProduct ( plane - > normal , p ) - plane - > dist ;
if ( d < 0 )
num = node - > childnum [ 1 ] ;
else
num = node - > childnum [ 0 ] ;
}
c_pointcontents + + ; // optimize counter
return - 1 - num ;
}
2005-08-26 22:56:51 +00:00
int CM_PointLeafnum ( model_t * mod , vec3_t p )
2004-08-21 01:25:48 +00:00
{
if ( ! numplanes )
return 0 ; // sound may call this without map loaded
2005-08-26 22:56:51 +00:00
return CM_PointLeafnum_r ( mod , p , 0 ) ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = =
CM_BoxLeafnums
Fills in a list of all the leafs touched
= = = = = = = = = = = = =
*/
int leaf_count , leaf_maxcount ;
int * leaf_list ;
float * leaf_mins , * leaf_maxs ;
int leaf_topnode ;
2005-08-26 22:56:51 +00:00
void CM_BoxLeafnums_r ( model_t * mod , int nodenum )
2004-08-21 01:25:48 +00:00
{
mplane_t * plane ;
mnode_t * node ;
int s ;
while ( 1 )
{
if ( nodenum < 0 )
{
if ( leaf_count > = leaf_maxcount )
{
// Com_Printf ("CM_BoxLeafnums_r: overflow\n");
return ;
}
leaf_list [ leaf_count + + ] = - 1 - nodenum ;
return ;
}
2006-03-04 20:43:48 +00:00
2005-08-26 22:56:51 +00:00
node = & mod - > nodes [ nodenum ] ;
2004-08-21 01:25:48 +00:00
plane = node - > plane ;
// s = BoxOnPlaneSide (leaf_mins, leaf_maxs, plane);
s = BOX_ON_PLANE_SIDE ( leaf_mins , leaf_maxs , plane ) ;
if ( s = = 1 )
nodenum = node - > childnum [ 0 ] ;
else if ( s = = 2 )
nodenum = node - > childnum [ 1 ] ;
else
{ // go down both
if ( leaf_topnode = = - 1 )
leaf_topnode = nodenum ;
2005-08-26 22:56:51 +00:00
CM_BoxLeafnums_r ( mod , node - > childnum [ 0 ] ) ;
2004-08-21 01:25:48 +00:00
nodenum = node - > childnum [ 1 ] ;
}
}
}
2005-08-26 22:56:51 +00:00
int CM_BoxLeafnums_headnode ( model_t * mod , vec3_t mins , vec3_t maxs , int * list , int listsize , int headnode , int * topnode )
2004-08-21 01:25:48 +00:00
{
leaf_list = list ;
leaf_count = 0 ;
leaf_maxcount = listsize ;
leaf_mins = mins ;
leaf_maxs = maxs ;
leaf_topnode = - 1 ;
2005-08-26 22:56:51 +00:00
CM_BoxLeafnums_r ( mod , headnode ) ;
2004-08-21 01:25:48 +00:00
if ( topnode )
* topnode = leaf_topnode ;
return leaf_count ;
}
2005-08-26 22:56:51 +00:00
int CM_BoxLeafnums ( model_t * mod , vec3_t mins , vec3_t maxs , int * list , int listsize , int * topnode )
2004-08-21 01:25:48 +00:00
{
2005-08-26 22:56:51 +00:00
return CM_BoxLeafnums_headnode ( mod , mins , maxs , list ,
listsize , mod - > hulls [ 0 ] . firstclipnode , topnode ) ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
CM_PointContents
= = = = = = = = = = = = = = = = = =
*/
# define PlaneDiff(point,plane) (((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) - (plane)->dist)
2005-08-26 22:56:51 +00:00
int CM_PointContents ( model_t * mod , vec3_t p )
2004-08-21 01:25:48 +00:00
{
int i , j , contents ;
mleaf_t * leaf ;
q2cbrush_t * brush ;
q2cbrushside_t * brushside ;
2005-08-26 22:56:51 +00:00
if ( ! mod ) // map not loaded
2004-08-21 01:25:48 +00:00
return 0 ;
2005-08-26 22:56:51 +00:00
i = CM_PointLeafnum_r ( mod , p , mod - > hulls [ 0 ] . firstclipnode ) ;
2004-08-21 01:25:48 +00:00
if ( ! mapisq3 )
2012-07-14 23:17:54 +00:00
contents = map_leafs [ i ] . contents ; //q2 is simple.
else
{
leaf = & map_leafs [ i ] ;
2004-08-21 01:25:48 +00:00
2012-07-14 23:17:54 +00:00
// if ( leaf->contents & CONTENTS_NODROP ) {
// contents = CONTENTS_NODROP;
// } else {
contents = 0 ;
// }
2004-08-21 01:25:48 +00:00
2012-07-14 23:17:54 +00:00
for ( i = 0 ; i < leaf - > numleafbrushes ; i + + )
{
brush = & map_brushes [ map_leafbrushes [ leaf - > firstleafbrush + i ] ] ;
2004-08-21 01:25:48 +00:00
2012-07-14 23:17:54 +00:00
// check if brush actually adds something to contents
if ( ( contents & brush - > contents ) = = brush - > contents ) {
continue ;
}
2004-08-21 01:25:48 +00:00
2012-07-14 23:17:54 +00:00
brushside = brush - > brushside ;
for ( j = 0 ; j < brush - > numsides ; j + + , brushside + + )
{
if ( PlaneDiff ( p , brushside - > plane ) > 0 )
break ;
}
2006-03-04 20:43:48 +00:00
2012-07-14 23:17:54 +00:00
if ( j = = brush - > numsides )
contents | = brush - > contents ;
2004-08-21 01:25:48 +00:00
}
}
2012-07-15 03:18:34 +00:00
# ifdef TERRAIN
2012-07-14 23:17:54 +00:00
if ( mod - > terrain )
contents | = Heightmap_PointContents ( mod , NULL , p ) ;
2012-07-15 03:18:34 +00:00
# endif
2004-08-21 01:25:48 +00:00
return contents ;
}
2010-08-28 17:14:38 +00:00
unsigned int CM_NativeContents ( struct model_s * model , int hulloverride , int frame , vec3_t axis [ 3 ] , vec3_t p , vec3_t mins , vec3_t maxs )
2006-03-06 01:41:09 +00:00
{
int contents ;
if ( ! DotProduct ( mins , mins ) & & ! DotProduct ( maxs , maxs ) )
return CM_PointContents ( model , p ) ;
if ( ! model ) // map not loaded
return 0 ;
{
int i , j , k ;
mleaf_t * leaf ;
q2cbrush_t * brush ;
q2cbrushside_t * brushside ;
vec3_t absmin , absmax ;
int leaflist [ 64 ] ;
k = CM_BoxLeafnums ( model , absmin , absmax , leaflist , 64 , NULL ) ;
contents = 0 ;
for ( k - - ; k > = 0 ; k - - )
{
leaf = & map_leafs [ leaflist [ k ] ] ;
if ( mapisq3 )
{
for ( i = 0 ; i < leaf - > numleafbrushes ; i + + )
{
brush = & map_brushes [ map_leafbrushes [ leaf - > firstleafbrush + i ] ] ;
// check if brush actually adds something to contents
if ( ( contents & brush - > contents ) = = brush - > contents ) {
continue ;
}
2011-05-15 13:23:13 +00:00
2010-03-14 14:35:56 +00:00
brushside = brush - > brushside ;
2006-03-06 01:41:09 +00:00
for ( j = 0 ; j < brush - > numsides ; j + + , brushside + + )
{
if ( PlaneDiff ( p , brushside - > plane ) > 0 )
break ;
}
2011-05-15 13:23:13 +00:00
if ( j = = brush - > numsides )
2006-03-06 01:41:09 +00:00
contents | = brush - > contents ;
}
}
else
contents | = leaf - > contents ;
}
}
return contents ;
}
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = =
CM_TransformedPointContents
Handles offseting and rotation of the end points for moving and
rotating entities
= = = = = = = = = = = = = = = = = =
*/
2005-08-26 22:56:51 +00:00
int CM_TransformedPointContents ( model_t * mod , vec3_t p , int headnode , vec3_t origin , vec3_t angles )
2004-08-21 01:25:48 +00:00
{
vec3_t p_l ;
vec3_t temp ;
vec3_t forward , right , up ;
// subtract origin offset
VectorSubtract ( p , origin , p_l ) ;
// rotate start and end into the models frame of reference
2006-03-04 20:43:48 +00:00
if ( headnode ! = box_headnode & &
2004-08-21 01:25:48 +00:00
( angles [ 0 ] | | angles [ 1 ] | | angles [ 2 ] ) )
{
AngleVectors ( angles , forward , right , up ) ;
VectorCopy ( p_l , temp ) ;
p_l [ 0 ] = DotProduct ( temp , forward ) ;
p_l [ 1 ] = - DotProduct ( temp , right ) ;
p_l [ 2 ] = DotProduct ( temp , up ) ;
}
2005-08-26 22:56:51 +00:00
return CM_PointContents ( mod , p ) ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BOX TRACING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
// 1/32 epsilon to keep floating point happy
# define DIST_EPSILON (0.03125)
vec3_t trace_start , trace_end ;
vec3_t trace_mins , trace_maxs ;
vec3_t trace_extents ;
vec3_t trace_absmins , trace_absmaxs ;
2005-05-19 02:53:03 +00:00
float trace_truefraction ;
float trace_nearfraction ;
2004-08-21 01:25:48 +00:00
trace_t trace_trace ;
int trace_contents ;
qboolean trace_ispoint ; // optimized case
/*
= = = = = = = = = = = = = = = =
CM_ClipBoxToBrush
= = = = = = = = = = = = = = = =
*/
void CM_ClipBoxToBrush ( vec3_t mins , vec3_t maxs , vec3_t p1 , vec3_t p2 ,
trace_t * trace , q2cbrush_t * brush )
{
int i , j ;
mplane_t * plane , * clipplane ;
float dist ;
float enterfrac , leavefrac ;
vec3_t ofs ;
float d1 , d2 ;
qboolean getout , startout ;
float f ;
q2cbrushside_t * side , * leadside ;
2005-05-19 02:53:03 +00:00
float nearfrac = 0 ;
2004-08-21 01:25:48 +00:00
enterfrac = - 1 ;
2005-05-19 02:53:03 +00:00
leavefrac = 2 ;
2004-08-21 01:25:48 +00:00
clipplane = NULL ;
if ( ! brush - > numsides )
return ;
c_brush_traces + + ;
getout = false ;
startout = false ;
leadside = NULL ;
for ( i = 0 ; i < brush - > numsides ; i + + )
{
2010-03-14 14:35:56 +00:00
side = brush - > brushside + i ;
2004-08-21 01:25:48 +00:00
plane = side - > plane ;
// FIXME: special case for axial
if ( ! trace_ispoint )
{ // general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for ( j = 0 ; j < 3 ; j + + )
{
if ( plane - > normal [ j ] < 0 )
ofs [ j ] = maxs [ j ] ;
else
ofs [ j ] = mins [ j ] ;
}
dist = DotProduct ( ofs , plane - > normal ) ;
dist = plane - > dist - dist ;
}
else
{ // special point case
dist = plane - > dist ;
}
d1 = DotProduct ( p1 , plane - > normal ) - dist ;
d2 = DotProduct ( p2 , plane - > normal ) - dist ;
if ( d2 > 0 )
getout = true ; // endpoint is not in solid
if ( d1 > 0 )
startout = true ;
// if completely in front of face, no intersection
if ( d1 > 0 & & d2 > = d1 )
return ;
if ( d1 < = 0 & & d2 < = 0 )
continue ;
// crosses face
if ( d1 > d2 )
{ // enter
2005-05-19 02:53:03 +00:00
f = ( d1 ) / ( d1 - d2 ) ;
2004-08-21 01:25:48 +00:00
if ( f > enterfrac )
{
enterfrac = f ;
2005-05-19 02:53:03 +00:00
nearfrac = ( d1 - DIST_EPSILON ) / ( d1 - d2 ) ;
2004-08-21 01:25:48 +00:00
clipplane = plane ;
leadside = side ;
}
}
else
{ // leave
2005-05-19 02:53:03 +00:00
f = ( d1 ) / ( d1 - d2 ) ;
2004-08-21 01:25:48 +00:00
if ( f < leavefrac )
leavefrac = f ;
}
}
if ( ! startout )
{ // original point was inside brush
trace - > startsolid = true ;
if ( ! getout )
trace - > allsolid = true ;
return ;
}
2005-05-19 02:53:03 +00:00
if ( enterfrac < = leavefrac )
2004-08-21 01:25:48 +00:00
{
2005-05-19 02:53:03 +00:00
if ( enterfrac > - 1 & & enterfrac < = trace_truefraction )
2004-08-21 01:25:48 +00:00
{
if ( enterfrac < 0 )
enterfrac = 0 ;
2005-05-19 02:53:03 +00:00
trace_nearfraction = nearfrac ;
trace_truefraction = enterfrac ;
2004-08-21 01:25:48 +00:00
trace - > plane . dist = clipplane - > dist ;
VectorCopy ( clipplane - > normal , trace - > plane . normal ) ;
trace - > surface = & ( leadside - > surface - > c ) ;
trace - > contents = brush - > contents ;
}
}
}
void CM_ClipBoxToPatch ( vec3_t mins , vec3_t maxs , vec3_t p1 , vec3_t p2 ,
trace_t * trace , q2cbrush_t * brush )
{
int i , j ;
mplane_t * plane , * clipplane ;
2005-05-19 02:53:03 +00:00
float enterfrac , leavefrac , nearfrac = 0 ;
2004-08-21 01:25:48 +00:00
vec3_t ofs ;
float d1 , d2 ;
float dist ;
qboolean startout ;
float f ;
q2cbrushside_t * side , * leadside ;
if ( ! brush - > numsides )
return ;
c_brush_traces + + ;
enterfrac = - 1 ;
2005-05-19 02:53:03 +00:00
leavefrac = 2 ;
2004-08-21 01:25:48 +00:00
clipplane = NULL ;
startout = false ;
leadside = NULL ;
for ( i = 0 ; i < brush - > numsides ; i + + )
{
2010-03-14 14:35:56 +00:00
side = brush - > brushside + i ;
2004-08-21 01:25:48 +00:00
plane = side - > plane ;
if ( ! trace_ispoint )
{ // general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for ( j = 0 ; j < 3 ; j + + )
{
if ( plane - > normal [ j ] < 0 )
ofs [ j ] = maxs [ j ] ;
else
ofs [ j ] = mins [ j ] ;
}
dist = DotProduct ( ofs , plane - > normal ) ;
dist = plane - > dist - dist ;
}
else
{ // special point case
dist = plane - > dist ;
}
d1 = DotProduct ( p1 , plane - > normal ) - dist ;
d2 = DotProduct ( p2 , plane - > normal ) - dist ;
// if completely in front of face, no intersection
if ( d1 > 0 & & d2 > = d1 )
return ;
2005-03-05 15:28:20 +00:00
if ( d1 > 0 )
startout = true ;
2004-08-21 01:25:48 +00:00
if ( d1 < = 0 & & d2 < = 0 )
continue ;
// crosses face
if ( d1 > d2 )
{ // enter
2005-05-19 02:53:03 +00:00
f = ( d1 ) / ( d1 - d2 ) ;
2004-08-21 01:25:48 +00:00
if ( f > enterfrac )
{
enterfrac = f ;
2005-05-19 02:53:03 +00:00
nearfrac = ( d1 - DIST_EPSILON ) / ( d1 - d2 ) ;
2004-08-21 01:25:48 +00:00
clipplane = plane ;
leadside = side ;
}
}
else
{ // leave
2005-05-19 02:53:03 +00:00
f = ( d1 ) / ( d1 - d2 ) ;
2004-08-21 01:25:48 +00:00
if ( f < leavefrac )
leavefrac = f ;
}
}
if ( ! startout )
2005-05-19 02:53:03 +00:00
{
trace - > startsolid = true ;
2004-08-21 01:25:48 +00:00
return ; // original point is inside the patch
2005-05-19 02:53:03 +00:00
}
2004-08-21 01:25:48 +00:00
2005-05-19 02:53:03 +00:00
if ( nearfrac < = leavefrac )
2004-08-21 01:25:48 +00:00
{
if ( leadside & & leadside - > surface
2005-05-19 02:53:03 +00:00
& & enterfrac < = trace_truefraction )
2004-08-21 01:25:48 +00:00
{
if ( enterfrac < 0 )
enterfrac = 0 ;
2005-05-19 02:53:03 +00:00
trace_truefraction = enterfrac ;
trace_nearfraction = nearfrac ;
2004-08-21 01:25:48 +00:00
trace - > plane . dist = clipplane - > dist ;
VectorCopy ( clipplane - > normal , trace - > plane . normal ) ;
trace - > surface = & leadside - > surface - > c ;
trace - > contents = brush - > contents ;
}
2005-05-19 02:53:03 +00:00
else if ( enterfrac < trace_truefraction )
leavefrac = 0 ;
2004-08-21 01:25:48 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
CM_TestBoxInBrush
= = = = = = = = = = = = = = = =
*/
void CM_TestBoxInBrush ( vec3_t mins , vec3_t maxs , vec3_t p1 ,
trace_t * trace , q2cbrush_t * brush )
{
int i , j ;
mplane_t * plane ;
float dist ;
vec3_t ofs ;
float d1 ;
q2cbrushside_t * side ;
if ( ! brush - > numsides )
return ;
for ( i = 0 ; i < brush - > numsides ; i + + )
{
2010-03-14 14:35:56 +00:00
side = brush - > brushside + i ;
2004-08-21 01:25:48 +00:00
plane = side - > plane ;
// FIXME: special case for axial
// general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for ( j = 0 ; j < 3 ; j + + )
{
if ( plane - > normal [ j ] < 0 )
ofs [ j ] = maxs [ j ] ;
else
ofs [ j ] = mins [ j ] ;
}
dist = DotProduct ( ofs , plane - > normal ) ;
dist = plane - > dist - dist ;
d1 = DotProduct ( p1 , plane - > normal ) - dist ;
// if completely in front of face, no intersection
if ( d1 > 0 )
return ;
}
// inside this brush
trace - > startsolid = trace - > allsolid = true ;
2006-02-11 18:18:55 +00:00
trace - > contents | = brush - > contents ;
2004-08-21 01:25:48 +00:00
}
void CM_TestBoxInPatch ( vec3_t mins , vec3_t maxs , vec3_t p1 ,
trace_t * trace , q2cbrush_t * brush )
{
int i , j ;
mplane_t * plane ;
vec3_t ofs ;
float dist ;
float d1 , maxdist ;
q2cbrushside_t * side ;
if ( ! brush - > numsides )
return ;
maxdist = - 9999 ;
for ( i = 0 ; i < brush - > numsides ; i + + )
{
2010-03-14 14:35:56 +00:00
side = brush - > brushside + i ;
2004-08-21 01:25:48 +00:00
plane = side - > plane ;
// general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for ( j = 0 ; j < 3 ; j + + )
{
if ( plane - > normal [ j ] < 0 )
ofs [ j ] = maxs [ j ] ;
else
ofs [ j ] = mins [ j ] ;
}
dist = DotProduct ( ofs , plane - > normal ) ;
dist = plane - > dist - dist ;
d1 = DotProduct ( p1 , plane - > normal ) - dist ;
// if completely in front of face, no intersection
if ( d1 > 0 )
return ;
if ( side - > surface & & d1 > maxdist )
maxdist = d1 ;
}
// FIXME
if ( maxdist < - 0.25 )
return ; // deep inside the patch
// inside this patch
trace - > startsolid = trace - > allsolid = true ;
trace - > contents = brush - > contents ;
}
/*
= = = = = = = = = = = = = = = =
CM_TraceToLeaf
= = = = = = = = = = = = = = = =
*/
void CM_TraceToLeaf ( int leafnum )
{
int k , j ;
int brushnum ;
mleaf_t * leaf ;
q2cbrush_t * b ;
int patchnum ;
q3cpatch_t * patch ;
leaf = & map_leafs [ leafnum ] ;
if ( ! ( leaf - > contents & trace_contents ) )
return ;
// trace line against all brushes in the leaf
for ( k = 0 ; k < leaf - > numleafbrushes ; k + + )
{
brushnum = map_leafbrushes [ leaf - > firstleafbrush + k ] ;
b = & map_brushes [ brushnum ] ;
if ( b - > checkcount = = checkcount )
continue ; // already checked this brush in another leaf
b - > checkcount = checkcount ;
if ( ! ( b - > contents & trace_contents ) )
continue ;
CM_ClipBoxToBrush ( trace_mins , trace_maxs , trace_start , trace_end , & trace_trace , b ) ;
2005-05-19 02:53:03 +00:00
if ( trace_nearfraction < = 0 )
2004-08-21 01:25:48 +00:00
return ;
}
if ( ! mapisq3 | | map_noCurves . value )
return ;
// trace line against all patches in the leaf
for ( k = 0 ; k < leaf - > numleafpatches ; k + + )
{
patchnum = map_leafpatches [ leaf - > firstleafpatch + k ] ;
patch = & map_patches [ patchnum ] ;
if ( patch - > checkcount = = checkcount )
continue ; // already checked this patch in another leaf
patch - > checkcount = checkcount ;
if ( ! ( patch - > surface - > c . value & trace_contents ) )
continue ;
if ( ! BoundsIntersect ( patch - > absmins , patch - > absmaxs , trace_absmins , trace_absmaxs ) )
continue ;
for ( j = 0 ; j < patch - > numbrushes ; j + + )
{
CM_ClipBoxToPatch ( trace_mins , trace_maxs , trace_start , trace_end , & trace_trace , & patch - > brushes [ j ] ) ;
2005-05-19 02:53:03 +00:00
if ( trace_nearfraction < = 0 )
2004-08-21 01:25:48 +00:00
return ;
}
}
}
/*
= = = = = = = = = = = = = = = =
CM_TestInLeaf
= = = = = = = = = = = = = = = =
*/
void CM_TestInLeaf ( int leafnum )
{
int k , j ;
int brushnum ;
int patchnum ;
mleaf_t * leaf ;
q2cbrush_t * b ;
q3cpatch_t * patch ;
leaf = & map_leafs [ leafnum ] ;
if ( ! ( leaf - > contents & trace_contents ) )
return ;
// trace line against all brushes in the leaf
for ( k = 0 ; k < leaf - > numleafbrushes ; k + + )
{
brushnum = map_leafbrushes [ leaf - > firstleafbrush + k ] ;
b = & map_brushes [ brushnum ] ;
if ( b - > checkcount = = checkcount )
continue ; // already checked this brush in another leaf
b - > checkcount = checkcount ;
if ( ! ( b - > contents & trace_contents ) )
continue ;
CM_TestBoxInBrush ( trace_mins , trace_maxs , trace_start , & trace_trace , b ) ;
if ( ! trace_trace . fraction )
return ;
}
if ( ! mapisq3 | | map_noCurves . value )
return ;
// trace line against all patches in the leaf
for ( k = 0 ; k < leaf - > numleafpatches ; k + + )
{
patchnum = map_leafpatches [ leaf - > firstleafpatch + k ] ;
patch = & map_patches [ patchnum ] ;
if ( patch - > checkcount = = checkcount )
continue ; // already checked this patch in another leaf
patch - > checkcount = checkcount ;
if ( ! ( patch - > surface - > c . value & trace_contents ) )
continue ;
if ( ! BoundsIntersect ( patch - > absmins , patch - > absmaxs , trace_absmins , trace_absmaxs ) )
continue ;
for ( j = 0 ; j < patch - > numbrushes ; j + + )
{
CM_TestBoxInPatch ( trace_mins , trace_maxs , trace_start , & trace_trace , & patch - > brushes [ j ] ) ;
if ( ! trace_trace . fraction )
return ;
}
}
}
/*
= = = = = = = = = = = = = = = = = =
CM_RecursiveHullCheck
= = = = = = = = = = = = = = = = = =
*/
2005-08-26 22:56:51 +00:00
void CM_RecursiveHullCheck ( model_t * mod , int num , float p1f , float p2f , vec3_t p1 , vec3_t p2 )
2004-08-21 01:25:48 +00:00
{
mnode_t * node ;
mplane_t * plane ;
float t1 , t2 , offset ;
float frac , frac2 ;
float idist ;
int i ;
vec3_t mid ;
int side ;
float midf ;
2005-05-19 02:53:03 +00:00
if ( trace_truefraction < = p1f )
2004-08-21 01:25:48 +00:00
return ; // already hit something nearer
// if < 0, we are in a leaf node
if ( num < 0 )
{
CM_TraceToLeaf ( - 1 - num ) ;
return ;
}
//
// find the point distances to the seperating plane
// and the offset for the size of the box
//
2005-08-26 22:56:51 +00:00
node = mod - > nodes + num ;
2004-08-21 01:25:48 +00:00
plane = node - > plane ;
if ( plane - > type < 3 )
{
t1 = p1 [ plane - > type ] - plane - > dist ;
t2 = p2 [ plane - > type ] - plane - > dist ;
offset = trace_extents [ plane - > type ] ;
}
else
{
t1 = DotProduct ( plane - > normal , p1 ) - plane - > dist ;
t2 = DotProduct ( plane - > normal , p2 ) - plane - > dist ;
if ( trace_ispoint )
offset = 0 ;
else
offset = fabs ( trace_extents [ 0 ] * plane - > normal [ 0 ] ) +
fabs ( trace_extents [ 1 ] * plane - > normal [ 1 ] ) +
fabs ( trace_extents [ 2 ] * plane - > normal [ 2 ] ) ;
}
#if 0
CM_RecursiveHullCheck ( node - > childnum [ 0 ] , p1f , p2f , p1 , p2 ) ;
CM_RecursiveHullCheck ( node - > childnum [ 1 ] , p1f , p2f , p1 , p2 ) ;
return ;
# endif
// see which sides we need to consider
if ( t1 > = offset & & t2 > = offset )
{
2005-08-26 22:56:51 +00:00
CM_RecursiveHullCheck ( mod , node - > childnum [ 0 ] , p1f , p2f , p1 , p2 ) ;
2004-08-21 01:25:48 +00:00
return ;
}
if ( t1 < - offset & & t2 < - offset )
{
2005-08-26 22:56:51 +00:00
CM_RecursiveHullCheck ( mod , node - > childnum [ 1 ] , p1f , p2f , p1 , p2 ) ;
2004-08-21 01:25:48 +00:00
return ;
}
// put the crosspoint DIST_EPSILON pixels on the near side
if ( t1 < t2 )
{
idist = 1.0 / ( t1 - t2 ) ;
side = 1 ;
frac2 = ( t1 + offset + DIST_EPSILON ) * idist ;
frac = ( t1 - offset + DIST_EPSILON ) * idist ;
}
else if ( t1 > t2 )
{
idist = 1.0 / ( t1 - t2 ) ;
side = 0 ;
frac2 = ( t1 - offset - DIST_EPSILON ) * idist ;
frac = ( t1 + offset + DIST_EPSILON ) * idist ;
}
else
{
side = 0 ;
frac = 1 ;
frac2 = 0 ;
}
// move up to the node
if ( frac < 0 )
frac = 0 ;
if ( frac > 1 )
frac = 1 ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
midf = p1f + ( p2f - p1f ) * frac ;
for ( i = 0 ; i < 3 ; i + + )
mid [ i ] = p1 [ i ] + frac * ( p2 [ i ] - p1 [ i ] ) ;
2005-08-26 22:56:51 +00:00
CM_RecursiveHullCheck ( mod , node - > childnum [ side ] , p1f , midf , p1 , mid ) ;
2004-08-21 01:25:48 +00:00
// go past the node
if ( frac2 < 0 )
frac2 = 0 ;
if ( frac2 > 1 )
frac2 = 1 ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
midf = p1f + ( p2f - p1f ) * frac2 ;
for ( i = 0 ; i < 3 ; i + + )
mid [ i ] = p1 [ i ] + frac2 * ( p2 [ i ] - p1 [ i ] ) ;
2005-08-26 22:56:51 +00:00
CM_RecursiveHullCheck ( mod , node - > childnum [ side ^ 1 ] , midf , p2f , mid , p2 ) ;
2004-08-21 01:25:48 +00:00
}
//======================================================================
/*
= = = = = = = = = = = = = = = = = =
CM_BoxTrace
= = = = = = = = = = = = = = = = = =
*/
2005-08-26 22:56:51 +00:00
trace_t CM_BoxTrace ( model_t * mod , vec3_t start , vec3_t end ,
2004-08-21 01:25:48 +00:00
vec3_t mins , vec3_t maxs ,
2005-08-26 22:56:51 +00:00
int brushmask )
2004-08-21 01:25:48 +00:00
{
int i ;
2004-11-20 01:03:57 +00:00
# if ADJ
2004-08-21 01:25:48 +00:00
int moved ;
2004-11-20 01:03:57 +00:00
# endif
2004-08-21 01:25:48 +00:00
vec3_t point ;
checkcount + + ; // for multi-check avoidance
c_traces + + ; // for statistics, may be zeroed
// fill in a default trace
memset ( & trace_trace , 0 , sizeof ( trace_trace ) ) ;
2005-05-19 02:53:03 +00:00
trace_truefraction = 1 ;
trace_nearfraction = 1 ;
2004-08-21 01:25:48 +00:00
trace_trace . fraction = 1 ;
trace_trace . surface = & ( nullsurface . c ) ;
2005-08-26 22:56:51 +00:00
if ( ! mod ) // map not loaded
2004-08-21 01:25:48 +00:00
return trace_trace ;
trace_contents = brushmask ;
VectorCopy ( start , trace_start ) ;
VectorCopy ( end , trace_end ) ;
VectorCopy ( mins , trace_mins ) ;
VectorCopy ( maxs , trace_maxs ) ;
// build a bounding box of the entire move (for patches)
ClearBounds ( trace_absmins , trace_absmaxs ) ;
VectorAdd ( start , trace_mins , point ) ;
AddPointToBounds ( point , trace_absmins , trace_absmaxs ) ;
VectorAdd ( start , trace_maxs , point ) ;
AddPointToBounds ( point , trace_absmins , trace_absmaxs ) ;
VectorAdd ( end , trace_mins , point ) ;
AddPointToBounds ( point , trace_absmins , trace_absmaxs ) ;
VectorAdd ( end , trace_maxs , point ) ;
AddPointToBounds ( point , trace_absmins , trace_absmaxs ) ;
//
// check for position test special case
//
if ( start [ 0 ] = = end [ 0 ] & & start [ 1 ] = = end [ 1 ] & & start [ 2 ] = = end [ 2 ] )
{
int leafs [ 1024 ] ;
int i , numleafs ;
vec3_t c1 , c2 ;
int topnode ;
2004-11-20 01:03:57 +00:00
# if ADJ
if ( - mins [ 2 ] ! = maxs [ 2 ] ) //be prepared to move the thing up to counter the different min/max
{
moved = ( trace_maxs [ 2 ] - trace_mins [ 2 ] ) / 2 ;
trace_mins [ 2 ] = - moved ;
trace_maxs [ 2 ] = moved ;
trace_extents [ 2 ] = - trace_mins [ 2 ] > trace_maxs [ 2 ] ? - trace_mins [ 2 ] : trace_maxs [ 2 ] ;
moved = ( maxs [ 2 ] - trace_maxs [ 2 ] ) ;
}
trace_start [ 2 ] + = moved ;
trace_end [ 2 ] + = moved ;
# endif
2004-08-21 01:25:48 +00:00
VectorAdd ( start , mins , c1 ) ;
VectorAdd ( start , maxs , c2 ) ;
for ( i = 0 ; i < 3 ; i + + )
{
c1 [ i ] - = 1 ;
c2 [ i ] + = 1 ;
}
2005-08-26 22:56:51 +00:00
numleafs = CM_BoxLeafnums_headnode ( mod , c1 , c2 , leafs , sizeof ( leafs ) / sizeof ( leafs [ 0 ] ) , mod - > hulls [ 0 ] . firstclipnode , & topnode ) ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < numleafs ; i + + )
{
CM_TestInLeaf ( leafs [ i ] ) ;
if ( trace_trace . allsolid )
break ;
}
VectorCopy ( start , trace_trace . endpos ) ;
2004-11-20 01:03:57 +00:00
# if ADJ
trace_trace . endpos [ 2 ] - = moved ;
# endif
2004-08-21 01:25:48 +00:00
return trace_trace ;
}
2004-11-20 01:03:57 +00:00
# if ADJ
2004-08-21 01:25:48 +00:00
moved = 0 ;
2004-11-20 01:03:57 +00:00
# endif
2004-08-21 01:25:48 +00:00
//
// check for point special case
//
if ( trace_mins [ 0 ] = = 0 & & trace_mins [ 1 ] = = 0 & & trace_mins [ 2 ] = = 0
& & trace_maxs [ 0 ] = = 0 & & trace_maxs [ 1 ] = = 0 & & trace_maxs [ 2 ] = = 0 )
{
trace_ispoint = true ;
VectorClear ( trace_extents ) ;
}
else
{
trace_ispoint = false ;
2005-05-19 02:53:03 +00:00
trace_extents [ 0 ] = - trace_mins [ 0 ] > trace_maxs [ 0 ] ? - trace_mins [ 0 ] : trace_maxs [ 0 ] + 1 ;
trace_extents [ 1 ] = - trace_mins [ 1 ] > trace_maxs [ 1 ] ? - trace_mins [ 1 ] : trace_maxs [ 1 ] + 1 ;
trace_extents [ 2 ] = - trace_mins [ 2 ] > trace_maxs [ 2 ] ? - trace_mins [ 2 ] : trace_maxs [ 2 ] + 1 ;
2004-11-20 01:03:57 +00:00
# if ADJ
2004-08-21 01:25:48 +00:00
if ( - mins [ 2 ] ! = maxs [ 2 ] ) //be prepared to move the thing up to counter the different min/max
{
moved = ( trace_maxs [ 2 ] - trace_mins [ 2 ] ) / 2 ;
trace_mins [ 2 ] = - moved ;
trace_maxs [ 2 ] = moved ;
trace_extents [ 2 ] = - trace_mins [ 2 ] > trace_maxs [ 2 ] ? - trace_mins [ 2 ] : trace_maxs [ 2 ] ;
moved = ( maxs [ 2 ] - trace_maxs [ 2 ] ) ;
}
trace_start [ 2 ] + = moved ;
trace_end [ 2 ] + = moved ;
2004-11-20 01:03:57 +00:00
# endif
2004-08-21 01:25:48 +00:00
}
//
// general sweeping through world
//
2005-08-26 22:56:51 +00:00
CM_RecursiveHullCheck ( mod , mod - > hulls [ 0 ] . firstclipnode , 0 , 1 , trace_start , trace_end ) ;
2004-08-21 01:25:48 +00:00
2005-05-19 02:53:03 +00:00
if ( trace_nearfraction = = 1 )
2004-08-21 01:25:48 +00:00
{
2005-05-19 02:53:03 +00:00
trace_trace . fraction = 1 ;
2004-08-21 01:25:48 +00:00
VectorCopy ( trace_end , trace_trace . endpos ) ;
}
else
{
2005-05-19 02:53:03 +00:00
if ( trace_nearfraction < 0 )
trace_nearfraction = 0 ;
trace_trace . fraction = trace_nearfraction ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < 3 ; i + + )
trace_trace . endpos [ i ] = trace_start [ i ] + trace_trace . fraction * ( trace_end [ i ] - trace_start [ i ] ) ;
}
2004-11-20 01:03:57 +00:00
# if ADJ
2004-08-21 01:25:48 +00:00
trace_trace . endpos [ 2 ] - = moved ;
2004-11-20 01:03:57 +00:00
# endif
2004-08-21 01:25:48 +00:00
return trace_trace ;
}
2010-08-28 17:14:38 +00:00
qboolean CM_NativeTrace ( model_t * model , int forcehullnum , int frame , vec3_t axis [ 3 ] , vec3_t start , vec3_t end , vec3_t mins , vec3_t maxs , unsigned int contents , trace_t * trace )
2006-03-06 01:41:09 +00:00
{
2012-07-23 02:34:20 +00:00
if ( axis )
{
vec3_t start_l ;
vec3_t end_l ;
start_l [ 0 ] = DotProduct ( start , axis [ 0 ] ) ;
start_l [ 1 ] = DotProduct ( start , axis [ 1 ] ) ;
start_l [ 2 ] = DotProduct ( start , axis [ 2 ] ) ;
end_l [ 0 ] = DotProduct ( end , axis [ 0 ] ) ;
end_l [ 1 ] = DotProduct ( end , axis [ 1 ] ) ;
end_l [ 2 ] = DotProduct ( end , axis [ 2 ] ) ;
* trace = CM_BoxTrace ( model , start_l , end_l , mins , maxs , contents ) ;
2012-07-15 03:18:34 +00:00
# ifdef TERRAIN
2012-07-23 02:34:20 +00:00
if ( model - > terrain )
{
trace_t hmt ;
Heightmap_Trace ( model , forcehullnum , frame , NULL , start , end , mins , maxs , contents , & hmt ) ;
if ( hmt . fraction < trace - > fraction )
* trace = hmt ;
}
# endif
if ( trace - > fraction = = 1 )
{
VectorCopy ( end , trace - > endpos ) ;
}
else
{
vec3_t iaxis [ 3 ] ;
vec3_t norm ;
Matrix3x3_RM_Invert_Simple ( ( void * ) axis , iaxis ) ;
VectorCopy ( trace - > plane . normal , norm ) ;
trace - > plane . normal [ 0 ] = DotProduct ( norm , iaxis [ 0 ] ) ;
trace - > plane . normal [ 1 ] = DotProduct ( norm , iaxis [ 1 ] ) ;
trace - > plane . normal [ 2 ] = DotProduct ( norm , iaxis [ 2 ] ) ;
/*just interpolate it, its easier than inverse matrix rotations*/
VectorInterpolate ( start , trace - > fraction , end , trace - > endpos ) ;
}
2012-07-14 23:17:54 +00:00
}
2012-07-23 02:34:20 +00:00
else
{
* trace = CM_BoxTrace ( model , start , end , mins , maxs , contents ) ;
# ifdef TERRAIN
if ( model - > terrain )
{
trace_t hmt ;
Heightmap_Trace ( model , forcehullnum , frame , NULL , start , end , mins , maxs , contents , & hmt ) ;
if ( hmt . fraction < trace - > fraction )
* trace = hmt ;
}
2012-07-15 03:18:34 +00:00
# endif
2012-07-23 02:34:20 +00:00
}
2006-03-06 01:41:09 +00:00
return trace - > fraction ! = 1 ;
}
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = =
CM_TransformedBoxTrace
Handles offseting and rotation of the end points for moving and
rotating entities
= = = = = = = = = = = = = = = = = =
*/
2004-09-13 04:16:52 +00:00
# ifdef _MSC_VER
2007-10-05 19:26:05 +00:00
# pragma warning(disable : 4748)
2004-08-21 01:25:48 +00:00
# pragma optimize( "", off )
# endif
2005-08-26 22:56:51 +00:00
trace_t CM_TransformedBoxTrace ( model_t * mod , vec3_t start , vec3_t end ,
2004-08-21 01:25:48 +00:00
vec3_t mins , vec3_t maxs ,
2005-08-26 22:56:51 +00:00
int brushmask ,
2004-08-21 01:25:48 +00:00
vec3_t origin , vec3_t angles )
{
2007-10-06 13:19:10 +00:00
# ifdef _MSC_VER
# pragma warning(default : 4748)
# endif
2004-08-21 01:25:48 +00:00
trace_t trace ;
vec3_t start_l , end_l ;
vec3_t a ;
vec3_t forward , right , up ;
vec3_t temp ;
qboolean rotated ;
// subtract origin offset
VectorSubtract ( start , origin , start_l ) ;
VectorSubtract ( end , origin , end_l ) ;
// rotate start and end into the models frame of reference
2006-03-04 20:43:48 +00:00
if ( mod ! = & box_model & &
2004-08-21 01:25:48 +00:00
( angles [ 0 ] | | angles [ 1 ] | | angles [ 2 ] ) )
rotated = true ;
else
rotated = false ;
if ( rotated )
{
AngleVectors ( angles , forward , right , up ) ;
VectorCopy ( start_l , temp ) ;
start_l [ 0 ] = DotProduct ( temp , forward ) ;
start_l [ 1 ] = - DotProduct ( temp , right ) ;
start_l [ 2 ] = DotProduct ( temp , up ) ;
VectorCopy ( end_l , temp ) ;
end_l [ 0 ] = DotProduct ( temp , forward ) ;
end_l [ 1 ] = - DotProduct ( temp , right ) ;
end_l [ 2 ] = DotProduct ( temp , up ) ;
}
// sweep the box through the model
2005-08-26 22:56:51 +00:00
trace = CM_BoxTrace ( mod , start_l , end_l , mins , maxs , brushmask ) ;
2004-08-21 01:25:48 +00:00
if ( rotated & & trace . fraction ! = 1.0 )
{
// FIXME: figure out how to do this with existing angles
VectorNegate ( angles , a ) ;
AngleVectors ( a , forward , right , up ) ;
VectorCopy ( trace . plane . normal , temp ) ;
trace . plane . normal [ 0 ] = DotProduct ( temp , forward ) ;
trace . plane . normal [ 1 ] = - DotProduct ( temp , right ) ;
trace . plane . normal [ 2 ] = DotProduct ( temp , up ) ;
2005-05-26 12:55:34 +00:00
}
2004-08-21 01:25:48 +00:00
2005-05-26 12:55:34 +00:00
if ( trace . fraction = = 1 )
{
VectorCopy ( end , trace . endpos ) ;
}
else
{
trace . endpos [ 0 ] = start [ 0 ] + trace . fraction * ( end [ 0 ] - start [ 0 ] ) ;
trace . endpos [ 1 ] = start [ 1 ] + trace . fraction * ( end [ 1 ] - start [ 1 ] ) ;
trace . endpos [ 2 ] = start [ 2 ] + trace . fraction * ( end [ 2 ] - start [ 2 ] ) ;
2004-12-15 19:48:47 +00:00
}
2004-08-21 01:25:48 +00:00
return trace ;
}
2004-09-13 04:16:52 +00:00
# ifdef _MSC_VER
2004-08-21 01:25:48 +00:00
# pragma optimize( "", on )
# endif
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
PVS / PHS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = =
CM_DecompressVis
= = = = = = = = = = = = = = = = = = =
*/
/*
qbyte * Mod_Q2DecompressVis ( qbyte * in , model_t * model )
{
static qbyte decompressed [ MAX_MAP_LEAFS / 8 ] ;
int c ;
qbyte * out ;
int row ;
2006-03-04 20:43:48 +00:00
row = ( model - > vis - > numclusters + 7 ) > > 3 ;
2004-08-21 01:25:48 +00:00
out = decompressed ;
if ( ! in )
{ // no vis info, so make all visible
while ( row )
{
* out + + = 0xff ;
row - - ;
}
2006-03-04 20:43:48 +00:00
return decompressed ;
2004-08-21 01:25:48 +00:00
}
do
{
if ( * in )
{
* out + + = * in + + ;
continue ;
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
c = in [ 1 ] ;
in + = 2 ;
while ( c )
{
* out + + = 0 ;
c - - ;
}
} while ( out - decompressed < row ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
return decompressed ;
}
# define DVIS_PVS 0
# define DVIS_PHS 1
qbyte * Mod_ClusterPVS ( int cluster , model_t * model )
{
if ( cluster = = - 1 | | ! model - > vis )
return mod_novis ;
return Mod_Q2DecompressVis ( ( qbyte * ) model - > vis + model - > vis - > bitofs [ cluster ] [ DVIS_PVS ] ,
model ) ;
}
*/
void CM_DecompressVis ( qbyte * in , qbyte * out )
{
int c ;
qbyte * out_p ;
int row ;
2006-03-04 20:43:48 +00:00
row = ( numclusters + 7 ) > > 3 ;
2004-08-21 01:25:48 +00:00
out_p = out ;
if ( ! in | | ! numvisibility )
{ // no vis info, so make all visible
while ( row )
{
* out_p + + = 0xff ;
row - - ;
}
2006-03-04 20:43:48 +00:00
return ;
2004-08-21 01:25:48 +00:00
}
do
{
if ( * in )
{
* out_p + + = * in + + ;
continue ;
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
c = in [ 1 ] ;
in + = 2 ;
if ( ( out_p - out ) + c > row )
{
c = row - ( out_p - out ) ;
Con_DPrintf ( " warning: Vis decompression overrun \n " ) ;
}
while ( c )
{
* out_p + + = 0 ;
c - - ;
}
} while ( out_p - out < row ) ;
}
2005-05-26 12:55:34 +00:00
qbyte pvsrow [ MAX_MAP_LEAFS / 8 ] ;
qbyte phsrow [ MAX_MAP_LEAFS / 8 ] ;
2004-08-21 01:25:48 +00:00
2009-06-21 17:45:33 +00:00
qbyte * CM_ClusterPVS ( model_t * mod , int cluster , qbyte * buffer , unsigned int buffersize )
2004-08-21 01:25:48 +00:00
{
if ( ! buffer )
2009-06-21 17:45:33 +00:00
{
2004-08-21 01:25:48 +00:00
buffer = pvsrow ;
2009-06-21 17:45:33 +00:00
buffersize = sizeof ( pvsrow ) ;
}
if ( buffersize < ( numclusters + 7 ) > > 3 )
Sys_Error ( " CM_ClusterPVS with too small a buffer \n " ) ;
2004-08-21 01:25:48 +00:00
if ( mapisq3 )
{
if ( cluster ! = - 1 & & map_q3pvs - > numclusters )
{
return ( qbyte * ) map_q3pvs - > data + cluster * map_q3pvs - > rowsize ;
}
else
{
memset ( buffer , 0 , ( numclusters + 7 ) > > 3 ) ;
return buffer ;
}
}
if ( cluster = = - 1 )
memset ( buffer , 0 , ( numclusters + 7 ) > > 3 ) ;
else
2012-08-02 03:44:04 +00:00
CM_DecompressVis ( ( ( qbyte * ) map_q2vis ) + map_q2vis - > bitofs [ cluster ] [ DVIS_PVS ] , buffer ) ;
2004-08-21 01:25:48 +00:00
return buffer ;
}
2005-08-26 22:56:51 +00:00
qbyte * CM_ClusterPHS ( model_t * mod , int cluster )
2004-08-21 01:25:48 +00:00
{
if ( mapisq3 ) //phs not working yet.
{
if ( cluster ! = - 1 & & map_q3phs - > numclusters )
{
return ( qbyte * ) map_q3phs - > data + cluster * map_q3phs - > rowsize ;
}
else
{
memset ( phsrow , 0 , ( numclusters + 7 ) > > 3 ) ;
return phsrow ;
}
}
if ( cluster = = - 1 )
memset ( phsrow , 0 , ( numclusters + 7 ) > > 3 ) ;
else
2012-08-02 03:44:04 +00:00
CM_DecompressVis ( ( ( qbyte * ) map_q2vis ) + map_q2vis - > bitofs [ cluster ] [ DVIS_PHS ] , phsrow ) ;
2004-08-21 01:25:48 +00:00
return phsrow ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
AREAPORTALS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void FloodArea_r ( q2carea_t * area , int floodnum )
{
int i ;
q2dareaportal_t * p ;
if ( area - > floodvalid = = floodvalid )
{
if ( area - > floodnum = = floodnum )
return ;
Host_Error ( " FloodArea_r: reflooded " ) ;
}
area - > floodnum = floodnum ;
area - > floodvalid = floodvalid ;
p = & map_areaportals [ area - > firstareaportal ] ;
for ( i = 0 ; i < area - > numareaportals ; i + + , p + + )
{
if ( portalopen [ p - > portalnum ] )
FloodArea_r ( & map_q2areas [ p - > otherarea ] , floodnum ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = =
FloodAreaConnections
= = = = = = = = = = = = = = = = = = = =
*/
void FloodAreaConnections ( void )
{
int i , j ;
q2carea_t * area ;
int floodnum ;
if ( mapisq3 )
{
// area 0 is not used
for ( i = 1 ; i < numareas ; i + + )
{
for ( j = 1 ; j < numareas ; j + + ) {
map_q3areas [ i ] . numareaportals [ j ] = ( j = = i ) ;
}
}
return ;
}
// all current floods are now invalid
floodvalid + + ;
floodnum = 0 ;
// area 0 is not used
for ( i = 1 ; i < numareas ; i + + )
{
area = & map_q2areas [ i ] ;
if ( area - > floodvalid = = floodvalid )
continue ; // already flooded into
floodnum + + ;
FloodArea_r ( area , floodnum ) ;
}
}
2005-03-18 06:13:36 +00:00
void VARGS CMQ2_SetAreaPortalState ( int portalnum , qboolean open )
2004-08-21 01:25:48 +00:00
{
if ( mapisq3 )
Host_Error ( " CMQ2_SetAreaPortalState on q3 map " ) ;
if ( portalnum > numareaportals )
Host_Error ( " areaportal > numareaportals " ) ;
if ( portalopen [ portalnum ] = = open )
2004-09-14 21:44:40 +00:00
return ;
2004-08-21 01:25:48 +00:00
portalopen [ portalnum ] = open ;
FloodAreaConnections ( ) ;
2004-09-14 21:44:40 +00:00
return ;
2004-08-21 01:25:48 +00:00
}
void CMQ3_SetAreaPortalState ( int area1 , int area2 , qboolean open )
{
if ( ! mapisq3 )
2006-02-11 18:18:55 +00:00
return ;
// Host_Error ("CMQ3_SetAreaPortalState on non-q3 map");
2004-08-21 01:25:48 +00:00
if ( area1 > numareas | | area2 > numareas )
Host_Error ( " CMQ3_SetAreaPortalState: area > numareas " ) ;
if ( open )
{
map_q3areas [ area1 ] . numareaportals [ area2 ] + + ;
map_q3areas [ area2 ] . numareaportals [ area1 ] + + ;
}
else
{
map_q3areas [ area1 ] . numareaportals [ area2 ] - - ;
map_q3areas [ area2 ] . numareaportals [ area1 ] - - ;
}
}
2005-08-26 22:56:51 +00:00
qboolean VARGS CM_AreasConnected ( model_t * mod , int area1 , int area2 )
2004-08-21 01:25:48 +00:00
{
if ( map_noareas . value )
return true ;
if ( area1 > numareas | | area2 > numareas )
Host_Error ( " area > numareas " ) ;
if ( mapisq3 )
{
int i ;
for ( i = 1 ; i < numareas ; i + + )
{
if ( map_q3areas [ i ] . numareaportals [ area1 ] & &
map_q3areas [ i ] . numareaportals [ area2 ] )
return true ;
}
}
else
{
if ( map_q2areas [ area1 ] . floodnum = = map_q2areas [ area2 ] . floodnum )
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = =
CM_WriteAreaBits
Writes a length qbyte followed by a bit vector of all the areas
that area in the same flood as the area parameter
This is used by the client refreshes to cull visibility
= = = = = = = = = = = = = = = = =
*/
2005-08-26 22:56:51 +00:00
int CM_WriteAreaBits ( model_t * mod , qbyte * buffer , int area )
2004-08-21 01:25:48 +00:00
{
int i ;
int floodnum ;
int bytes ;
bytes = ( numareas + 7 ) > > 3 ;
if ( map_noareas . value )
{ // for debugging, send everything
memset ( buffer , 255 , bytes ) ;
}
else
{
memset ( buffer , 0 , bytes ) ;
if ( mapisq3 )
{
for ( i = 0 ; i < numareas ; i + + )
{
2005-08-26 22:56:51 +00:00
if ( ! area | | CM_AreasConnected ( mod , i , area ) | | i = = area )
2004-08-21 01:25:48 +00:00
buffer [ i > > 3 ] | = 1 < < ( i & 7 ) ;
}
}
else
{
floodnum = map_q2areas [ area ] . floodnum ;
for ( i = 0 ; i < numareas ; i + + )
{
if ( map_q2areas [ i ] . floodnum = = floodnum | | ! area )
buffer [ i > > 3 ] | = 1 < < ( i & 7 ) ;
}
}
}
return bytes ;
}
2012-10-13 00:56:31 +00:00
# ifndef CLIENTONLY
2012-10-10 22:58:51 +00:00
void CM_InitPortalState ( void )
{
int i ;
//if we're not running q2, force all q2 portals open.
if ( svs . gametype ! = GT_QUAKE2 & & ! mapisq3 )
{
for ( i = 0 ; i < numareas ; i + + )
map_q2areas [ i ] . floodnum = 0 ;
}
}
2012-10-13 00:56:31 +00:00
# endif
2012-10-10 22:58:51 +00:00
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = = =
CM_WritePortalState
Writes the portal state to a savegame file
= = = = = = = = = = = = = = = = = = =
*/
void CM_WritePortalState ( FILE * f )
{
fwrite ( portalopen , sizeof ( portalopen ) , 1 , f ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
CM_ReadPortalState
Reads the portal state from a savegame file
and recalculates the area connections
= = = = = = = = = = = = = = = = = = =
*/
void CM_ReadPortalState ( FILE * f )
{
2011-05-15 13:23:13 +00:00
size_t result ;
result = fread ( portalopen , 1 , sizeof ( portalopen ) , f ) ; // do something with result
2011-05-30 04:32:04 +00:00
if ( result ! = sizeof ( portalopen ) )
2012-04-24 07:59:11 +00:00
Con_Printf ( " CM_ReadPortalState() fread: expected %lu, result was %u \n " , ( long unsigned int ) sizeof ( portalopen ) , ( unsigned int ) result ) ;
2011-05-30 04:32:04 +00:00
2004-08-21 01:25:48 +00:00
FloodAreaConnections ( ) ;
}
/*
= = = = = = = = = = = = =
CM_HeadnodeVisible
Returns true if any leaf under headnode has a cluster that
is potentially visible
= = = = = = = = = = = = =
*/
2005-08-26 22:56:51 +00:00
qboolean CM_HeadnodeVisible ( model_t * mod , int nodenum , qbyte * visbits )
2004-08-21 01:25:48 +00:00
{
int leafnum ;
int cluster ;
mnode_t * node ;
if ( nodenum < 0 )
{
leafnum = - 1 - nodenum ;
cluster = map_leafs [ leafnum ] . cluster ;
if ( cluster = = - 1 )
return false ;
if ( visbits [ cluster > > 3 ] & ( 1 < < ( cluster & 7 ) ) )
return true ;
return false ;
}
2005-08-26 22:56:51 +00:00
node = & mod - > nodes [ nodenum ] ;
if ( CM_HeadnodeVisible ( mod , node - > childnum [ 0 ] , visbits ) )
2004-08-21 01:25:48 +00:00
return true ;
2005-08-26 22:56:51 +00:00
return CM_HeadnodeVisible ( mod , node - > childnum [ 1 ] , visbits ) ;
2004-08-21 01:25:48 +00:00
}
2005-08-26 22:56:51 +00:00
/*
2004-08-21 01:25:48 +00:00
qboolean Q2BSP_RecursiveHullCheck ( hull_t * hull , int num , float p1f , float p2f , vec3_t p1 , vec3_t p2 , trace_t * trace )
{
trace_t ret = CM_BoxTrace ( p1 , p2 , hull - > clip_mins , hull - > clip_maxs , hull - > firstclipnode , MASK_SOLID ) ;
memcpy ( trace , & ret , sizeof ( trace_t ) ) ;
if ( ret . fraction = = 1 )
return true ;
return false ;
2005-08-26 22:56:51 +00:00
} */
2010-08-28 17:14:38 +00:00
unsigned int Q2BSP_PointContents ( model_t * mod , vec3_t axis [ 3 ] , vec3_t p )
2004-08-21 01:25:48 +00:00
{
2013-03-12 22:47:42 +00:00
int pc ;
2005-08-26 22:56:51 +00:00
pc = CM_PointContents ( mod , p ) ;
2012-01-17 07:57:46 +00:00
return pc ;
2004-08-21 01:25:48 +00:00
}
int map_checksum ;
2006-03-12 22:01:49 +00:00
qboolean Mod_LoadQ2BrushModel ( model_t * mod , void * buffer )
2004-08-21 01:25:48 +00:00
{
mod - > fromgame = fg_quake2 ;
2006-03-12 22:01:49 +00:00
return CM_LoadMap ( mod - > name , buffer , true , & map_checksum ) ! = NULL ;
2004-08-21 01:25:48 +00:00
}
void CM_Init ( void ) //register cvars.
{
# define MAPOPTIONS "Map Cvar Options"
Cvar_Register ( & map_noareas , MAPOPTIONS ) ;
Cvar_Register ( & map_noCurves , MAPOPTIONS ) ;
Cvar_Register ( & map_autoopenportals , MAPOPTIONS ) ;
2005-05-17 02:36:54 +00:00
Cvar_Register ( & r_subdivisions , MAPOPTIONS ) ;
2004-08-21 01:25:48 +00:00
}
# endif
2010-03-14 14:35:56 +00:00