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
2013-06-23 02:17:02 +00:00
# ifdef _WIN32
# include <malloc.h>
# else
# include <alloca.h>
# endif
2013-12-17 22:45:37 +00:00
# define MAX_Q3MAP_INDICES 0x8000000 //just a sanity limit
# define MAX_Q3MAP_VERTEXES 0x800000 //just a sanity limit
2014-12-11 16:26:26 +00:00
//#define MAX_CM_PATCH_VERTS (4096)
//#define MAX_CM_FACES (MAX_Q2MAP_FACES)
# ifdef FTE_TARGET_WEB
# define MAX_CM_PATCHES (0x1000) //fixme
# else
# define MAX_CM_PATCHES (0x10000) //fixme
# endif
//#define MAX_CM_LEAFFACES (MAX_Q2MAP_LEAFFACES)
2004-08-21 01:25:48 +00:00
# define MAX_CM_AREAS MAX_Q2MAP_AREAS
2014-05-10 13:42:13 +00:00
//#define Q3SURF_NODAMAGE 0x00000001
//#define Q3SURF_SLICK 0x00000002
//#define Q3SURF_SKY 0x00000004
//#define Q3SURF_LADDER 0x00000008
//#define Q3SURF_NOIMPACT 0x00000010
//#define Q3SURF_NOMARKS 0x00000020
//#define Q3SURF_FLESH 0x00000040
# define Q3SURF_NODRAW 0x00000080 // don't generate a drawsurface at all
//#define Q3SURF_HINT 0x00000100
# define Q3SURF_SKIP 0x00000200 // completely ignore, allowing non-closed brushes
//#define Q3SURF_NOLIGHTMAP 0x00000400
//#define Q3SURF_POINTLIGHT 0x00000800
//#define Q3SURF_METALSTEPS 0x00001000
//#define Q3SURF_NOSTEPS 0x00002000
# define Q3SURF_NONSOLID 0x00004000 // don't collide against curves with this set
//#define Q3SURF_LIGHTFILTER 0x00008000
//#define Q3SURF_ALPHASHADOW 0x00010000
//#define Q3SURF_NODLIGHT 0x00020000
//#define Q3SURF_DUST 0x00040000
cvar_t q3bsp_surf_meshcollision_flag = CVARD ( " q3bsp_surf_meshcollision_flag " , " 0x80000000 " , " The surfaceparm flag(s) that enables q3bsp trisoup collision " ) ;
cvar_t q3bsp_surf_meshcollision_force = CVARD ( " q3bsp_surf_meshcollision_force " , " 0 " , " Force mesh-based collisions on all q3bsp trisoup surfaces. " ) ;
2004-08-21 01:25:48 +00:00
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)
2014-10-05 20:04:11 +00:00
qboolean Mod_LoadVertexes ( model_t * loadmodel , qbyte * mod_base , lump_t * l ) ;
2015-03-03 00:14:43 +00:00
qboolean Mod_LoadVertexNormals ( model_t * loadmodel , qbyte * mod_base , lump_t * l ) ;
2014-10-05 20:04:11 +00:00
qboolean Mod_LoadEdges ( model_t * loadmodel , qbyte * mod_base , lump_t * l , qboolean lm ) ;
qboolean Mod_LoadMarksurfaces ( model_t * loadmodel , qbyte * mod_base , lump_t * l , qboolean lm ) ;
qboolean Mod_LoadSurfedges ( model_t * loadmodel , qbyte * mod_base , lump_t * l ) ;
2015-03-03 00:14:43 +00:00
void Mod_LoadLighting ( model_t * loadmodel , qbyte * mod_base , lump_t * l , qboolean interleaveddeluxe ) ;
2004-08-21 01:25:48 +00:00
2014-09-17 03:04:08 +00:00
static 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 , qboolean capsule , unsigned int contents , trace_t * trace ) ;
2014-05-10 13:42:13 +00:00
static 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 ) ;
static unsigned int Q2BSP_PointContents ( model_t * mod , vec3_t axis [ 3 ] , vec3_t p ) ;
2014-05-23 02:02:51 +00:00
static int CM_PointCluster ( model_t * mod , vec3_t p ) ;
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 ) ;
}
2014-10-05 20:04:11 +00:00
void CalcSurfaceExtents ( model_t * mod , msurface_t * s )
2004-08-21 01:25:48 +00:00
{
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 + + )
{
2014-10-05 20:04:11 +00:00
e = mod - > surfedges [ s - > firstedge + i ] ;
2004-08-21 01:25:48 +00:00
if ( e > = 0 )
2014-10-05 20:04:11 +00:00
v = & mod - > vertexes [ mod - > edges [ e ] . v [ 0 ] ] ;
2004-08-21 01:25:48 +00:00
else
2014-10-05 20:04:11 +00:00
v = & mod - > vertexes [ mod - > 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
{
2015-03-03 00:14:43 +00:00
bmins [ i ] = floor ( mins [ i ] / ( 1 < < s - > lmshift ) ) ;
bmaxs [ i ] = ceil ( maxs [ i ] / ( 1 < < s - > lmshift ) ) ;
2004-08-21 01:25:48 +00:00
2015-03-03 00:14:43 +00:00
s - > texturemins [ i ] = bmins [ i ] < < s - > lmshift ;
s - > extents [ i ] = ( bmaxs [ i ] - bmins [ i ] ) < < s - > lmshift ;
2004-08-21 01:25:48 +00:00
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 )
{
2013-06-30 00:58:49 +00:00
mins [ 0 ] = mins [ 1 ] = mins [ 2 ] = 999999999 ;
maxs [ 0 ] = maxs [ 1 ] = maxs [ 2 ] = - 999999999 ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
void Mod_SortShaders ( model_t * mod )
2010-07-11 02:22:39 +00:00
{
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
2014-10-05 20:04:11 +00:00
for ( i = 0 ; i < mod - > numtextures ; i + + )
2010-07-11 02:22:39 +00:00
{
2014-10-05 20:04:11 +00:00
for ( j = i + 1 ; j < mod - > numtextures ; j + + )
2010-07-11 02:22:39 +00:00
{
2014-10-05 20:04:11 +00:00
if ( ( mod - > textures [ i ] - > shader & & mod - > textures [ j ] - > shader ) & & ( mod - > textures [ j ] - > shader - > sort < mod - > textures [ i ] - > shader - > sort ) )
2010-07-11 02:22:39 +00:00
{
2014-10-05 20:04:11 +00:00
textemp = mod - > textures [ j ] ;
mod - > textures [ j ] = mod - > textures [ i ] ;
mod - > textures [ i ] = textemp ;
2010-07-11 02:22:39 +00:00
}
}
}
}
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 qbyte * mod_base ;
2014-09-17 03:04:08 +00:00
# define capsuledist(dist,plane,mins,maxs) \
case shape_iscapsule : \
dist = DotProduct ( trace_up , plane - > normal ) ; \
dist = dist * ( trace_capsulesize [ ( dist < 0 ) ? 1 : 2 ] ) - trace_capsulesize [ 0 ] ; \
dist = plane - > dist - dist ; \
break ;
2004-08-21 01:25:48 +00:00
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 {
2013-06-26 19:47:33 +00:00
char shader [ 64 ] ;
2011-12-05 15:23:40 +00:00
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 ;
2014-05-10 13:42:13 +00:00
typedef struct
{
vec3_t absmins , absmaxs ;
vecV_t * xyz_array ;
size_t numverts ;
index_t * indicies ;
size_t numincidies ;
q2mapsurface_t * surface ;
int checkcount ; // to avoid repeated testings
} q3cmesh_t ;
2004-08-21 01:25:48 +00:00
typedef struct
{
int facetype ;
int numverts ;
int firstvert ;
int shadernum ;
2014-05-10 13:42:13 +00:00
union
{
struct
{
int cp [ 2 ] ;
} patch ;
struct
{
int firstindex ;
int numindicies ;
} soup ;
} ;
2004-08-21 01:25:48 +00:00
} 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
2014-05-10 13:42:13 +00:00
mnode_t * headnode ;
mleaf_t * headleaf ;
2011-12-05 15:23:40 +00:00
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 ;
2015-02-02 08:01:53 +00:00
typedef struct cminfo_s
{
int numbrushsides ;
q2cbrushside_t * brushsides ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
q2mapsurface_t * surfaces ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
int numleafbrushes ;
q2cbrush_t * leafbrushes [ MAX_Q2MAP_LEAFBRUSHES ] ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
int numcmodels ;
cmodel_t * cmodels ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
int numbrushes ;
q2cbrush_t * brushes ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
int numvisibility ;
q2dvis_t * q2vis ;
q3dvis_t * q3pvs ;
q3dvis_t * q3phs ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
int numareas ;
q2carea_t q2areas [ MAX_Q2MAP_AREAS ] ;
q3carea_t q3areas [ MAX_CM_AREAS ] ;
int numareaportals ;
q2dareaportal_t areaportals [ MAX_Q2MAP_AREAPORTALS ] ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
//list of mesh surfaces within the leaf
q3cmesh_t cmeshes [ MAX_CM_PATCHES ] ;
int numcmeshes ;
int * leafcmeshes ;
int numleafcmeshes ;
int maxleafcmeshes ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
//FIXME: remove the below
//(deprecated) patch collisions
q3cpatch_t patches [ MAX_CM_PATCHES ] ;
int numpatches ;
int * leafpatches ;
int numleafpatches ;
int maxleafpatches ;
//FIXME: remove the above
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
int floodvalid ;
qbyte portalopen [ MAX_Q2MAP_AREAPORTALS ] ; //memset will work if it's a qbyte, really it should be a qboolean
2014-05-10 13:42:13 +00:00
2015-02-02 08:01:53 +00:00
int mapisq3 ;
} cminfo_t ;
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
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 ) ;
2015-03-03 00:14:43 +00:00
cvar_t map_autoopenportals = CVARD ( " map_autoopenportals " , " 0 " , " When set to 1, force-opens all area portals. Normally these start closed and are opened by doors when they move, but this requires the gamecode to signal this. " ) ; //1 for lack of mod support.
2006-02-11 02:09:43 +00:00
cvar_t r_subdivisions = SCVAR ( " r_subdivisions " , " 2 " ) ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
static int CM_NumInlineModels ( model_t * model ) ;
static cmodel_t * CM_InlineModel ( model_t * model , char * name ) ;
2004-08-21 01:25:48 +00:00
void CM_InitBoxHull ( void ) ;
2015-02-02 08:01:53 +00:00
static void FloodAreaConnections ( cminfo_t * prv ) ;
2004-08-21 01:25:48 +00:00
2011-12-05 15:23:40 +00:00
static int numvertexes ;
2015-02-02 08:01:53 +00:00
static vecV_t * map_verts ; //3points
2011-12-05 15:23:40 +00:00
static vec2_t * map_vertstmexcoords ;
2013-10-08 14:28:11 +00:00
static vec2_t * map_vertlstmexcoords [ MAXRLIGHTMAPS ] ;
static vec4_t * map_colors4f_array [ MAXRLIGHTMAPS ] ;
2011-12-05 15:23:40 +00:00
static vec3_t * map_normals_array ;
2014-01-13 02:42:25 +00:00
//static vec3_t *map_svector_array;
//static vec3_t *map_tvector_array;
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
2015-02-02 08:01:53 +00:00
q3cface_t * map_faces ;
static int numfaces ;
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 ;
}
2013-08-06 02:19:06 +00:00
if ( fabs ( normal [ i ] + 1 ) < PLANE_NORMAL_EPSILON )
2010-03-14 14:35:56 +00:00
{
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
*/
2014-10-05 20:04:11 +00:00
static void CM_CreatePatch ( model_t * loadmodel , 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 ;
2013-07-14 12:22:51 +00:00
data = ZG_Malloc ( & loadmodel - > memgroup , patch - > numfacets * sizeof ( q2cbrush_t ) + totalsides * ( sizeof ( q2cbrushside_t ) + sizeof ( mplane_t ) ) ) ;
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
= = = = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
qboolean CM_CreatePatchesForLeafs ( model_t * loadmodel , cminfo_t * prv )
2004-08-21 01:25:48 +00:00
{
int i , j , k ;
mleaf_t * leaf ;
q3cface_t * face ;
q2mapsurface_t * surf ;
q3cpatch_t * patch ;
2014-05-10 13:42:13 +00:00
q3cmesh_t * cmesh ;
2013-06-23 02:17:02 +00:00
int * checkout = alloca ( sizeof ( int ) * numfaces ) ;
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
if ( map_noCurves . ival )
return true ;
2013-06-23 02:17:02 +00:00
memset ( checkout , - 1 , sizeof ( int ) * numfaces ) ;
2004-08-21 01:25:48 +00:00
2014-05-10 13:42:13 +00:00
for ( i = 0 , leaf = loadmodel - > leafs ; i < loadmodel - > numleafs ; i + + , leaf + + )
2004-08-21 01:25:48 +00:00
{
leaf - > numleafpatches = 0 ;
2015-02-02 08:01:53 +00:00
leaf - > firstleafpatch = prv - > numleafpatches ;
2014-05-10 13:42:13 +00:00
leaf - > numleafcmeshes = 0 ;
2015-02-02 08:01:53 +00:00
leaf - > firstleafcmesh = prv - > numleafcmeshes ;
2004-08-21 01:25:48 +00:00
2010-03-14 14:35:56 +00:00
if ( leaf - > cluster = = - 1 )
2004-08-21 01:25:48 +00:00
continue ;
2014-05-10 13:42:13 +00:00
for ( j = 0 ; j < leaf - > nummarksurfaces ; j + + )
2004-08-21 01:25:48 +00:00
{
2014-05-10 13:42:13 +00:00
k = leaf - > firstmarksurface [ j ] - loadmodel - > surfaces ;
2013-06-23 02:17:02 +00:00
if ( k > = numfaces )
{
Con_Printf ( CON_ERROR " CM_CreatePatchesForLeafs: corrupt map \n " ) ;
break ;
}
2004-08-21 01:25:48 +00:00
face = & map_faces [ k ] ;
2014-05-10 13:42:13 +00:00
if ( face - > numverts < = 0 )
2004-08-21 01:25:48 +00:00
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 ;
2015-02-02 08:01:53 +00:00
surf = & prv - > surfaces [ face - > shadernum ] ;
2014-05-10 13:42:13 +00:00
if ( ! surf - > c . value ) //surface has no contents value, so can't ever block anything.
2004-08-21 01:25:48 +00:00
continue ;
2014-05-10 13:42:13 +00:00
switch ( face - > facetype )
2006-03-13 05:54:12 +00:00
{
2014-05-10 13:42:13 +00:00
case MST_TRIANGLE_SOUP :
if ( ! face - > soup . numindicies )
continue ;
//only enable mesh collisions if its meant to be enabled.
//we haven't parsed any shaders, so we depend upon the stuff that the bsp compiler left lying around.
if ( ! ( surf - > c . flags & q3bsp_surf_meshcollision_flag . ival ) & & ! q3bsp_surf_meshcollision_force . ival )
continue ;
2015-02-02 08:01:53 +00:00
if ( prv - > numleafcmeshes > = prv - > maxleafcmeshes )
2014-05-10 13:42:13 +00:00
{
2015-02-02 08:01:53 +00:00
prv - > maxleafcmeshes * = 2 ;
prv - > maxleafcmeshes + = 16 ;
if ( prv - > numleafcmeshes > prv - > maxleafcmeshes )
2014-05-10 13:42:13 +00:00
{ //detect overflow
Con_Printf ( CON_ERROR " CM_CreateCMeshesForLeafs: map is insanely huge! \n " ) ;
return false ;
}
2015-02-02 08:01:53 +00:00
prv - > leafcmeshes = realloc ( prv - > leafcmeshes , sizeof ( * prv - > leafcmeshes ) * prv - > maxleafcmeshes ) ;
2013-06-23 02:17:02 +00:00
}
2004-08-21 01:25:48 +00:00
2014-05-10 13:42:13 +00:00
// the patch was already built
if ( checkout [ k ] ! = - 1 )
2006-03-13 05:54:12 +00:00
{
2015-02-02 08:01:53 +00:00
prv - > leafcmeshes [ prv - > numleafcmeshes ] = checkout [ k ] ;
cmesh = & prv - > cmeshes [ checkout [ k ] ] ;
2006-03-13 05:54:12 +00:00
}
2014-05-10 13:42:13 +00:00
else
{
2015-02-02 08:01:53 +00:00
if ( prv - > numcmeshes > = MAX_CM_PATCHES )
2014-05-10 13:42:13 +00:00
{
Con_Printf ( CON_ERROR " CM_CreatePatchesForLeafs: map has too many patches \n " ) ;
return false ;
}
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
cmesh = & prv - > cmeshes [ prv - > numcmeshes ] ;
prv - > leafcmeshes [ prv - > numleafcmeshes ] = prv - > numcmeshes ;
checkout [ k ] = prv - > numcmeshes + + ;
2004-08-21 01:25:48 +00:00
2014-05-10 13:42:13 +00:00
//gcc warns without this cast
cmesh - > surface = surf ;
cmesh - > numverts = face - > numverts ;
cmesh - > numincidies = face - > soup . numindicies ;
cmesh - > xyz_array = ZG_Malloc ( & loadmodel - > memgroup , cmesh - > numverts * sizeof ( * cmesh - > xyz_array ) + cmesh - > numincidies * sizeof ( * cmesh - > indicies ) ) ;
cmesh - > indicies = ( index_t * ) ( cmesh - > xyz_array + cmesh - > numverts ) ;
2004-08-21 01:25:48 +00:00
2014-05-10 13:42:13 +00:00
VectorCopy ( map_verts [ face - > firstvert + 0 ] , cmesh - > xyz_array [ 0 ] ) ;
VectorCopy ( cmesh - > xyz_array [ 0 ] , cmesh - > absmaxs ) ;
VectorCopy ( cmesh - > xyz_array [ 0 ] , cmesh - > absmins ) ;
for ( k = 1 ; k < cmesh - > numverts ; k + + )
{
VectorCopy ( map_verts [ face - > firstvert + k ] , cmesh - > xyz_array [ k ] ) ;
AddPointToBounds ( cmesh - > xyz_array [ k ] , cmesh - > absmins , cmesh - > absmaxs ) ;
}
for ( k = 0 ; k < cmesh - > numincidies ; k + + )
cmesh - > indicies [ k ] = map_surfindexes [ face - > soup . firstindex + k ] ;
}
leaf - > contents | = surf - > c . value ;
leaf - > numleafcmeshes + + ;
2015-02-02 08:01:53 +00:00
prv - > numleafcmeshes + + ;
2014-05-10 13:42:13 +00:00
break ;
case MST_PATCH :
if ( face - > patch . cp [ 0 ] < = 0 | | face - > patch . cp [ 1 ] < = 0 )
continue ;
if ( ! surf - > c . value | | ( surf - > c . flags & Q3SURF_NONSOLID ) )
continue ;
2015-02-02 08:01:53 +00:00
if ( prv - > numleafpatches > = prv - > maxleafpatches )
2014-05-10 13:42:13 +00:00
{
2015-02-02 08:01:53 +00:00
prv - > maxleafpatches * = 2 ;
prv - > maxleafpatches + = 16 ;
if ( prv - > numleafpatches > prv - > maxleafpatches )
2014-05-10 13:42:13 +00:00
{ //detect overflow
Con_Printf ( CON_ERROR " CM_CreatePatchesForLeafs: map is insanely huge! \n " ) ;
return false ;
}
2015-02-02 08:01:53 +00:00
prv - > leafpatches = realloc ( prv - > leafpatches , sizeof ( * prv - > leafpatches ) * prv - > maxleafpatches ) ;
2014-05-10 13:42:13 +00:00
}
// the patch was already built
if ( checkout [ k ] ! = - 1 )
{
2015-02-02 08:01:53 +00:00
prv - > leafpatches [ prv - > numleafpatches ] = checkout [ k ] ;
patch = & prv - > patches [ checkout [ k ] ] ;
2014-05-10 13:42:13 +00:00
}
else
{
2015-02-02 08:01:53 +00:00
if ( prv - > numpatches > = MAX_CM_PATCHES )
2014-05-10 13:42:13 +00:00
{
Con_Printf ( CON_ERROR " CM_CreatePatchesForLeafs: map has too many patches \n " ) ;
return false ;
}
2015-02-02 08:01:53 +00:00
patch = & prv - > patches [ prv - > numpatches ] ;
prv - > leafpatches [ prv - > numleafpatches ] = prv - > numpatches ;
checkout [ k ] = prv - > numpatches + + ;
2004-08-21 01:25:48 +00:00
2014-05-10 13:42:13 +00:00
//gcc warns without this cast
2014-10-05 20:04:11 +00:00
CM_CreatePatch ( loadmodel , patch , surf , ( const vec_t * ) ( map_verts + face - > firstvert ) , face - > patch . cp ) ;
2014-05-10 13:42:13 +00:00
}
leaf - > contents | = patch - > surface - > c . value ;
leaf - > numleafpatches + + ;
2015-02-02 08:01:53 +00:00
prv - > numleafpatches + + ;
2014-05-10 13:42:13 +00:00
break ;
}
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
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
MAP LOADING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = =
CMod_LoadSubmodels
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadSubmodels ( model_t * loadmodel , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) loadmodel - > meshinfo ;
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 ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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 ;
}
2013-08-21 07:14:39 +00:00
if ( count > SANITY_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
2015-02-02 08:01:53 +00:00
out = prv - > cmodels = ZG_Malloc ( & loadmodel - > memgroup , count * sizeof ( * prv - > cmodels ) ) ;
prv - > numcmodels = count ;
2004-08-21 01:25:48 +00:00
2013-08-21 07:14:39 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
2004-08-21 01:25:48 +00:00
{
for ( j = 0 ; j < 3 ; j + + )
{ // spread the mins / maxs by a pixel
out - > mins [ j ] = LittleFloat ( in - > mins [ j ] ) - 1 ;
out - > maxs [ j ] = LittleFloat ( in - > maxs [ j ] ) + 1 ;
out - > origin [ j ] = LittleFloat ( in - > origin [ j ] ) ;
}
2014-05-10 13:42:13 +00:00
out - > headnode = loadmodel - > nodes + LittleLong ( in - > headnode ) ;
2004-08-21 01:25:48 +00:00
out - > firstsurface = LittleLong ( in - > firstface ) ;
out - > numsurfaces = LittleLong ( in - > numfaces ) ;
}
2006-03-13 05:54:12 +00:00
2015-02-02 08:01:53 +00:00
AddPointToBounds ( prv - > cmodels [ 0 ] . mins , loadmodel - > mins , loadmodel - > maxs ) ;
AddPointToBounds ( prv - > cmodels [ 0 ] . maxs , loadmodel - > mins , loadmodel - > maxs ) ;
2013-03-12 23:12:30 +00:00
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadSurfaces
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadSurfaces ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
q2texinfo_t * in ;
q2mapsurface_t * out ;
int i , count ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2014-10-05 20:04:11 +00:00
mod - > numtexinfo = count ;
2015-02-02 08:01:53 +00:00
out = prv - > surfaces = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * prv - > 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
2015-03-03 00:14:43 +00:00
texture_t * Mod_LoadWall ( model_t * loadmodel , char * mapname , char * texname , char * shadername , unsigned int imageflags )
2004-08-21 01:25:48 +00:00
{
2015-03-03 00:14:43 +00:00
char name [ MAX_QPATH ] ;
2011-03-02 03:43:38 +00:00
q2miptex_t replacementwal ;
2004-08-21 01:25:48 +00:00
texture_t * tex ;
q2miptex_t * wal ;
2015-03-03 00:14:43 +00:00
image_t * base ;
2004-08-21 01:25:48 +00:00
2015-03-03 00:14:43 +00:00
Q_snprintfz ( name , sizeof ( name ) , " textures/%s.wal " , texname ) ;
wal = ( void * ) FS_LoadMallocFile ( texname , NULL ) ;
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
wal = & replacementwal ;
memset ( wal , 0 , sizeof ( * wal ) ) ;
2015-03-03 00:14:43 +00:00
Q_strncpyz ( wal - > name , texname , sizeof ( wal - > name ) ) ;
2014-10-05 20:04:11 +00:00
wal - > width = 64 ;
wal - > height = 64 ;
2008-11-09 22:29:28 +00:00
}
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 ) ;
2013-07-14 12:22:51 +00:00
tex = ZG_Malloc ( & loadmodel - > memgroup , sizeof ( texture_t ) ) ;
2004-08-21 01:25:48 +00:00
2009-11-04 21:16:50 +00:00
tex - > width = wal - > width ;
tex - > height = wal - > height ;
2004-08-21 01:25:48 +00:00
2015-03-03 00:14:43 +00:00
if ( ! tex - > width | | ! tex - > height | | wal = = & replacementwal )
{
imageflags | = IF_LOADNOW ; //make sure the size is known BEFORE it returns.
if ( wal - > offsets [ 0 ] )
base = R_LoadReplacementTexture ( wal - > name , " bmodels " , imageflags , ( qbyte * ) wal + wal - > offsets [ 0 ] , wal - > width , wal - > height , TF_SOLID8 ) ;
else
base = R_LoadReplacementTexture ( wal - > name , " bmodels " , imageflags , NULL , 0 , 0 , TF_INVALID ) ;
}
2014-10-05 20:04:11 +00:00
else
2015-03-03 00:14:43 +00:00
base = NULL ;
2014-10-05 20:04:11 +00:00
if ( wal = = & replacementwal )
2004-08-21 01:25:48 +00:00
{
2015-03-03 00:14:43 +00:00
if ( base )
2011-03-02 03:43:38 +00:00
{
2015-03-03 00:14:43 +00:00
if ( base - > status = = TEX_LOADED | | base - > status = = TEX_LOADING )
{
tex - > width = base - > width ;
tex - > height = base - > height ;
}
2011-03-02 03:43:38 +00:00
}
2015-03-03 00:14:43 +00:00
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
else
2011-03-02 03:43:38 +00:00
BZ_Free ( wal ) ;
2004-08-21 01:25:48 +00:00
return tex ;
}
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadTexInfo ( model_t * mod , qbyte * mod_base , lump_t * l , char * mapname ) //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
int texcount ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2014-10-05 20:04:11 +00:00
Con_Printf ( " MOD_LoadBmodel: funny lump size in %s \n " , mod - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * out ) ) ;
2006-03-04 20:43:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > textures = ZG_Malloc ( & mod - > memgroup , sizeof ( texture_t * ) * count ) ;
2004-08-21 01:25:48 +00:00
texcount = 0 ;
2014-10-05 20:04:11 +00:00
mod - > texinfo = out ;
mod - > numtexinfo = count ;
2004-08-21 01:25:48 +00:00
2015-03-03 00:14:43 +00:00
if ( in [ 0 ] . nexttexinfo ! = - 1 )
{
for ( i = 1 ; i < count & & in [ i ] . nexttexinfo = = in [ 0 ] . nexttexinfo ; i + + )
;
if ( i = = count )
{
Con_Printf ( " WARNING: invalid texture animations in \" %s \" \n " , mod - > name ) ;
for ( i = 0 ; i < count ; i + + )
in [ i ] . nexttexinfo = - 1 ;
}
}
2004-08-21 01:25:48 +00:00
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 ] ) ;
2015-03-03 00:14:43 +00:00
out - > vecscale [ 0 ] = 1.0 / Length ( out - > vecs [ 0 ] ) ;
out - > vecscale [ 1 ] = 1.0 / Length ( out - > vecs [ 1 ] ) ;
2004-08-21 01:25:48 +00:00
2010-07-11 02:22:39 +00:00
if ( out - > flags & TI_SKY )
2015-03-03 00:14:43 +00:00
Q_snprintfz ( sname , sizeof ( sname ) , " sky/%s " , in - > texture ) ;
else if ( out - > flags & ( TI_WARP | TI_FLOWING ) )
Q_snprintfz ( sname , sizeof ( sname ) , " warp/%s " , in - > texture ) ;
else if ( out - > flags & ( TI_TRANS33 | TI_TRANS66 ) )
Q_snprintfz ( sname , sizeof ( sname ) , " trans/%s " , in - > texture ) ;
2010-07-11 02:22:39 +00:00
else
2015-03-03 00:14:43 +00:00
Q_snprintfz ( sname , sizeof ( sname ) , " wall/%s " , in - > texture ) ;
if ( out - > flags & TI_FLOWING )
Q_strncatz ( sname , " #FLOW " , sizeof ( sname ) ) ;
if ( out - > flags & TI_TRANS66 )
Q_strncatz ( sname , " #ALPHA=0.66 " , sizeof ( sname ) ) ;
else if ( out - > flags & TI_TRANS33 )
Q_strncatz ( sname , " #ALPHA=0.33 " , sizeof ( sname ) ) ;
else if ( out - > flags & ( TI_WARP | TI_FLOWING ) )
Q_strncatz ( sname , " #ALPHA=1 " , sizeof ( sname ) ) ;
if ( in - > nexttexinfo ! = - 1 ) //used to ensure non-looping and looping don't conflict and get confused.
Q_strncatz ( sname , " #ANIMLOOP " , sizeof ( sname ) ) ;
2013-12-02 14:30:30 +00:00
//in q2, 'TEX_SPECIAL' is TI_LIGHT, and that conflicts.
out - > flags & = ~ TI_LIGHT ;
2015-03-03 00:14:43 +00:00
if ( out - > flags & ( TI_SKY | TI_TRANS33 | TI_TRANS66 | TI_WARP | TI_FLOWING ) )
2013-12-02 14:30:30 +00:00
out - > flags | = TEX_SPECIAL ;
2010-07-11 02:22:39 +00:00
//compact the textures.
2004-08-21 01:25:48 +00:00
for ( j = 0 ; j < texcount ; j + + )
{
2014-10-05 20:04:11 +00:00
if ( ! strcmp ( sname , mod - > textures [ j ] - > name ) )
2004-08-21 01:25:48 +00:00
{
2014-10-05 20:04:11 +00:00
out - > texture = mod - > textures [ j ] ;
2004-08-21 01:25:48 +00:00
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 ' ;
}
2015-03-03 00:14:43 +00:00
out - > texture = Mod_LoadWall ( mod , mapname , in - > texture , sname , ( out - > flags & TEX_SPECIAL ) ? 0 : IF_NOALPHA ) ;
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
{
2014-10-05 20:04:11 +00:00
out - > texture = ZG_Malloc ( & mod - > memgroup , sizeof ( texture_t ) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2 ) ;
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
2014-10-05 20:04:11 +00:00
mod - > textures [ texcount + + ] = out - > texture ;
2004-08-21 01:25:48 +00:00
}
2013-12-02 14:30:30 +00:00
2015-03-03 00:14:43 +00:00
// if (in->nexttexinfo != -1)
// {
// Con_DPrintf("FIXME: %s should animate to %s\n", in->texture, (in->nexttexinfo+(q2texinfo_t *)(mod_base + l->fileofs))->texture);
// }
2013-12-02 14:30:30 +00:00
}
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
out = mod - > texinfo ;
2013-12-02 14:30:30 +00:00
for ( i = 0 ; i < count ; i + + )
{
if ( in [ i ] . nexttexinfo > = 0 & & in [ i ] . nexttexinfo < count )
out [ i ] . texture - > anim_next = out [ in [ i ] . nexttexinfo ] . texture ;
}
for ( i = 0 ; i < count ; i + + )
{
texture_t * tex ;
if ( ! out [ i ] . texture - > anim_next )
continue ;
out [ i ] . texture - > anim_total = 1 ;
2015-03-03 00:14:43 +00:00
for ( tex = out [ i ] . texture - > anim_next ; tex & & tex ! = out [ i ] . texture & & out [ i ] . texture - > anim_total < 100 ; tex = tex - > anim_next )
2013-12-02 14:30:30 +00:00
out [ i ] . texture - > anim_total + + ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
mod - > numtextures = texcount ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
Mod_SortShaders ( mod ) ;
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
2015-03-03 00:14:43 +00:00
qboolean CModQ2_LoadFaces ( model_t * mod , qbyte * mod_base , lump_t * l , qboolean lightofsisdouble )
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 ;
2015-03-03 00:14:43 +00:00
unsigned short lmshift , lmscale ;
char buf [ 64 ] ;
lmscale = atoi ( Mod_ParseWorldspawnKey ( mod - > entities , " lightmap_scale " , buf , sizeof ( buf ) ) ) ;
if ( ! lmscale )
lmshift = LMSHIFT_DEFAULT ;
else
{
for ( lmshift = 0 ; lmscale > 1 ; lmshift + + )
lmscale > > = 1 ;
}
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
if ( l - > filelen % sizeof ( * in ) )
2006-03-13 05:54:12 +00:00
{
2014-10-05 20:04:11 +00:00
Con_Printf ( " MOD_LoadBmodel: funny lump size in %s \n " , mod - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , ( count + 6 ) * sizeof ( * out ) ) ; //spare for skybox
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > surfaces = out ;
mod - > numsurfaces = count ;
2004-08-21 01:25:48 +00:00
for ( surfnum = 0 ; surfnum < count ; surfnum + + , in + + , out + + )
{
out - > firstedge = LittleLong ( in - > firstedge ) ;
2015-03-03 00:14:43 +00:00
out - > numedges = ( unsigned short ) LittleShort ( in - > numedges ) ;
2004-08-21 01:25:48 +00:00
out - > flags = 0 ;
2015-03-03 00:14:43 +00:00
planenum = ( unsigned short ) LittleShort ( in - > planenum ) ;
side = ( unsigned short ) LittleShort ( in - > side ) ;
2004-08-21 01:25:48 +00:00
if ( side )
2006-03-04 20:43:48 +00:00
out - > flags | = SURF_PLANEBACK ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
out - > plane = mod - > planes + planenum ;
2004-08-21 01:25:48 +00:00
2015-03-03 00:14:43 +00:00
ti = ( unsigned short ) LittleShort ( in - > texinfo ) ;
2014-10-05 20:04:11 +00:00
if ( ti < 0 | | ti > = mod - > 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 ;
}
2014-10-05 20:04:11 +00:00
out - > texinfo = mod - > texinfo + ti ;
2004-08-21 01:25:48 +00:00
# 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
2015-03-03 00:14:43 +00:00
out - > lmshift = lmshift ;
2014-10-05 20:04:11 +00:00
CalcSurfaceExtents ( mod , out ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
// lighting info
2013-10-08 14:28:11 +00:00
for ( i = 0 ; i < MAXQ1LIGHTMAPS ; i + + )
2004-08-21 01:25:48 +00:00
out - > styles [ i ] = in - > styles [ i ] ;
i = LittleLong ( in - > lightofs ) ;
if ( i = = - 1 )
out - > samples = NULL ;
2015-03-03 00:14:43 +00:00
else if ( lightofsisdouble )
out - > samples = mod - > lightdata + ( i / 2 ) ;
2004-08-21 01:25:48 +00:00
else
2014-10-05 20:04:11 +00:00
out - > samples = mod - > 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
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadNodes ( model_t * mod , qbyte * mod_base , 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
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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 ;
}
2013-06-23 02:17:02 +00:00
if ( count > SANITY_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
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , sizeof ( mnode_t ) * count ) ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > nodes = out ;
mod - > 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 ] ) ;
}
2014-10-05 20:04:11 +00:00
out - > plane = mod - > planes + LittleLong ( in - > planenum ) ;
2004-08-21 01:25:48 +00:00
2015-03-03 00:14:43 +00:00
out - > firstsurface = ( unsigned short ) LittleShort ( in - > firstface ) ;
out - > numsurfaces = ( unsigned short ) LittleShort ( in - > numfaces ) ;
2004-08-21 01:25:48 +00:00
out - > contents = - 1 ; // differentiate from leafs
for ( j = 0 ; j < 2 ; j + + )
{
child = LittleLong ( in - > children [ j ] ) ;
out - > childnum [ j ] = child ;
if ( child < 0 )
2014-10-05 20:04:11 +00:00
out - > children [ j ] = ( mnode_t * ) ( mod - > leafs + - 1 - child ) ;
2004-08-21 01:25:48 +00:00
else
2014-10-05 20:04:11 +00:00
out - > children [ j ] = mod - > nodes + child ;
2004-08-21 01:25:48 +00:00
}
}
2014-10-05 20:04:11 +00:00
CMod_SetParent ( mod - > 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
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadBrushes ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
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
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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 ) ;
2013-06-23 02:17:02 +00:00
if ( count > SANITY_MAX_MAP_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
2015-02-02 08:01:53 +00:00
prv - > brushes = ZG_Malloc ( & mod - > memgroup , sizeof ( * out ) * ( count + 1 ) ) ;
2013-06-23 02:17:02 +00:00
2015-02-02 08:01:53 +00:00
out = prv - > brushes ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
prv - > numbrushes = count ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , out + + , in + + )
{
2010-03-14 14:35:56 +00:00
//FIXME: missing bounds checks
2015-02-02 08:01:53 +00:00
out - > brushside = & prv - > 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
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadLeafs ( model_t * mod , qbyte * mod_base , 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
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2014-05-10 13:42:13 +00:00
if ( count > MAX_MAP_LEAFS )
2006-03-13 05:54:12 +00:00
{
2014-02-11 17:51:29 +00:00
Con_Printf ( CON_ERROR " Map has too many leafs \n " ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , sizeof ( * out ) * ( count + 1 ) ) ;
2015-02-02 08:01:53 +00:00
mod - > numclusters = 0 ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > leafs = out ;
mod - > numleafs = count ;
2004-08-21 01:25:48 +00:00
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
2015-03-03 00:14:43 +00:00
out - > area = ( unsigned short ) 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
2014-10-05 20:04:11 +00:00
out - > firstmarksurface = mod - > 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
2015-02-02 08:01:53 +00:00
if ( out - > cluster > = mod - > numclusters )
mod - > numclusters = out - > cluster + 1 ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
out = mod - > leafs ;
2004-08-21 01:25:48 +00:00
2014-05-10 13:42:13 +00:00
if ( out [ 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
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadPlanes
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadPlanes ( model_t * mod , qbyte * mod_base , 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
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2014-02-11 17:51:29 +00:00
if ( count > = SANITY_MAX_MAP_PLANES )
2006-03-13 05:54:12 +00:00
{
2014-02-11 17:51:29 +00:00
Con_Printf ( CON_ERROR " Map has too many planes (%i) \n " , count ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > planes = out = ZG_Malloc ( & mod - > memgroup , sizeof ( * out ) * count ) ;
mod - > numplanes = count ;
2004-08-21 01:25:48 +00:00
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
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadLeafBrushes ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
int i ;
2014-05-10 13:42:13 +00:00
q2cbrush_t * * out ;
2004-08-21 01:25:48 +00:00
unsigned short * in ;
int count ;
2006-03-04 20:43:48 +00:00
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2015-02-02 08:01:53 +00:00
out = prv - > leafbrushes ;
prv - > numleafbrushes = count ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
2015-02-02 08:01:53 +00:00
* out = prv - > brushes + ( unsigned short ) ( short ) LittleShort ( * in ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadBrushSides
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadBrushSides ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2015-03-03 00:14:43 +00:00
unsigned int i , j ;
2004-08-21 01:25:48 +00:00
q2cbrushside_t * out ;
q2dbrushside_t * in ;
int count ;
int num ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2014-02-11 17:51:29 +00:00
if ( count > SANITY_MAX_MAP_BRUSHSIDES )
2006-03-13 05:54:12 +00:00
{
2014-02-11 17:51:29 +00:00
Con_Printf ( CON_ERROR " Map has too many brushsides (%i) \n " , count ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
out = prv - > brushsides = ZG_Malloc ( & mod - > memgroup , sizeof ( * out ) * count ) ;
prv - > numbrushsides = count ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
2015-03-03 00:14:43 +00:00
num = ( unsigned short ) LittleShort ( in - > planenum ) ;
2014-10-05 20:04:11 +00:00
out - > plane = & mod - > planes [ num ] ;
2015-03-03 00:14:43 +00:00
j = ( unsigned short ) LittleShort ( in - > texinfo ) ;
2014-10-05 20:04:11 +00:00
if ( j > = mod - > numtexinfo )
2015-03-03 00:14:43 +00:00
out - > surface = & nullsurface ;
else
out - > surface = & prv - > surfaces [ j ] ;
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
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadAreas
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadAreas ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
int i ;
q2carea_t * out ;
q2darea_t * in ;
int count ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2015-02-02 08:01:53 +00:00
out = prv - > q2areas ;
prv - > numareas = count ;
2004-08-21 01:25:48 +00:00
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
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadAreaPortals ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
int i ;
q2dareaportal_t * out ;
q2dareaportal_t * in ;
int count ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2015-02-02 08:01:53 +00:00
out = prv - > areaportals ;
prv - > numareaportals = count ;
2004-08-21 01:25:48 +00:00
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
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ2_LoadVisibility ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
int i ;
2015-02-02 08:01:53 +00:00
prv - > 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
2015-02-02 08:01:53 +00:00
prv - > q2vis = ZG_Malloc ( & mod - > memgroup , l - > filelen ) ;
memcpy ( prv - > q2vis , mod_base + l - > fileofs , l - > filelen ) ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
mod - > vis = prv - > q2vis ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
prv - > q2vis - > numclusters = LittleLong ( prv - > q2vis - > numclusters ) ;
for ( i = 0 ; i < prv - > q2vis - > numclusters ; i + + )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
prv - > q2vis - > bitofs [ i ] [ 0 ] = LittleLong ( prv - > q2vis - > bitofs [ i ] [ 0 ] ) ;
prv - > q2vis - > bitofs [ i ] [ 1 ] = LittleLong ( prv - > q2vis - > bitofs [ i ] [ 1 ] ) ;
2004-08-21 01:25:48 +00:00
}
2015-02-02 08:01:53 +00:00
mod - > numclusters = prv - > q2vis - > numclusters ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CMod_LoadEntityString
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
void CMod_LoadEntityString ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
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
2014-10-05 20:04:11 +00:00
mod - > entities = ZG_Malloc ( & mod - > memgroup , l - > filelen + 1 ) ;
memcpy ( mod - > entities , mod_base + l - > fileofs , l - > filelen ) ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
# ifdef Q3BSPS
qboolean CModQ3_LoadMarksurfaces ( model_t * loadmodel , qbyte * mod_base , 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 ) ;
2013-07-14 12:22:51 +00:00
out = ZG_Malloc ( & loadmodel - > memgroup , count * sizeof ( * out ) ) ;
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
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadSubmodels ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
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 ;
2014-05-10 13:42:13 +00:00
q2cbrush_t * * leafbrush ;
2004-08-21 01:25:48 +00:00
mleaf_t * bleaf ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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 ;
}
2013-08-21 07:14:39 +00:00
if ( count > SANITY_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
2015-02-02 08:01:53 +00:00
out = prv - > cmodels = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * prv - > cmodels ) ) ;
prv - > numcmodels = count ;
2004-08-21 01:25:48 +00:00
2014-05-10 13:42:13 +00:00
if ( count > 1 )
2014-10-05 20:04:11 +00:00
bleaf = ZG_Malloc ( & mod - > memgroup , ( count - 1 ) * sizeof ( * bleaf ) ) ;
2014-05-10 13:42:13 +00:00
else
bleaf = NULL ;
2015-02-02 08:01:53 +00:00
prv - > mapisq3 = true ;
2004-08-21 01:25:48 +00:00
2013-08-21 07:14:39 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
2004-08-21 01:25:48 +00:00
{
for ( j = 0 ; j < 3 ; j + + )
{ // spread the mins / maxs by a pixel
out - > mins [ j ] = LittleFloat ( in - > mins [ j ] ) - 1 ;
out - > maxs [ j ] = LittleFloat ( in - > maxs [ j ] ) + 1 ;
out - > origin [ j ] = ( 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 )
2014-05-10 13:42:13 +00:00
{
2014-10-05 20:04:11 +00:00
out - > headnode = mod - > nodes ;
2014-05-10 13:42:13 +00:00
out - > headleaf = NULL ;
}
2004-08-21 01:25:48 +00:00
else
{
2014-05-10 13:42:13 +00:00
//create a new leaf to hold the brushes and be directly clipped
out - > headleaf = bleaf ;
out - > headnode = NULL ;
2004-08-21 01:25:48 +00:00
// out->firstbrush = LittleLong(in->firstbrush);
// out->num_brushes = LittleLong(in->num_brushes);
bleaf - > numleafbrushes = LittleLong ( in - > num_brushes ) ;
2015-02-02 08:01:53 +00:00
bleaf - > firstleafbrush = prv - > numleafbrushes ;
2004-08-21 01:25:48 +00:00
bleaf - > contents = 0 ;
2015-02-02 08:01:53 +00:00
leafbrush = & prv - > leafbrushes [ prv - > numleafbrushes ] ;
2012-11-27 03:23:19 +00:00
for ( j = 0 ; j < bleaf - > numleafbrushes ; j + + , leafbrush + + )
{
2015-02-02 08:01:53 +00:00
* leafbrush = prv - > brushes + LittleLong ( in - > firstbrush ) + j ;
2014-05-10 13:42:13 +00:00
bleaf - > contents | = ( * leafbrush ) - > contents ;
2004-08-21 01:25:48 +00:00
}
2015-02-02 08:01:53 +00:00
prv - > numleafbrushes + = bleaf - > numleafbrushes ;
2014-05-10 13:42:13 +00:00
bleaf + + ;
2004-08-21 01:25:48 +00:00
}
//submodels
}
2005-08-07 18:08:13 +00:00
2015-02-02 08:01:53 +00:00
AddPointToBounds ( prv - > cmodels [ 0 ] . mins , mod - > mins , mod - > maxs ) ;
AddPointToBounds ( prv - > cmodels [ 0 ] . maxs , mod - > mins , mod - > maxs ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadShaders ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
dq3shader_t * in ;
q2mapsurface_t * out ;
int i , count ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2014-10-05 20:04:11 +00:00
mod - > numtexinfo = count ;
2015-02-02 08:01:53 +00:00
out = prv - > surfaces = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * out ) ) ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > texinfo = ZG_Malloc ( & mod - > memgroup , sizeof ( mtexinfo_t ) * ( count * 2 + 1 ) ) ; //+1 is 'noshader' for flares.
mod - > numtextures = count * 2 + 1 ;
mod - > textures = ZG_Malloc ( & mod - > memgroup , sizeof ( texture_t * ) * ( count * 2 + 1 ) ) ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
2014-10-05 20:04:11 +00:00
mod - > texinfo [ i ] . texture = ZG_Malloc ( & mod - > memgroup , sizeof ( texture_t ) ) ;
Q_strncpyz ( mod - > texinfo [ i ] . texture - > name , in - > shadername , sizeof ( mod - > texinfo [ i ] . texture - > name ) ) ;
mod - > textures [ i ] = mod - > texinfo [ i ] . texture ;
2004-08-21 01:25:48 +00:00
out - > c . flags = LittleLong ( in - > surfflags ) ;
out - > c . value = LittleLong ( in - > contents ) ;
}
2014-10-05 20:04:11 +00:00
for ( i = 0 , in - = count ; i < count ; i + + , in + + )
{
mod - > texinfo [ i + count ] . texture = ZG_Malloc ( & mod - > memgroup , sizeof ( texture_t ) ) ;
Q_strncpyz ( mod - > texinfo [ i + count ] . texture - > name , in - > shadername , sizeof ( mod - > texinfo [ i + count ] . texture - > name ) ) ;
mod - > textures [ i + count ] = mod - > texinfo [ i + count ] . texture ;
}
//and for flares, which are not supported at this time.
mod - > texinfo [ count * 2 ] . texture = ZG_Malloc ( & mod - > memgroup , sizeof ( texture_t ) ) ;
Q_strncpyz ( mod - > texinfo [ count * 2 ] . texture - > name , " noshader " , sizeof ( mod - > texinfo [ count * 2 ] . texture - > name ) ) ;
mod - > textures [ count * 2 ] = mod - > texinfo [ count * 2 ] . texture ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadVertexes ( model_t * mod , qbyte * mod_base , 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 ;
2014-01-13 02:42:25 +00:00
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
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * out ) ) ;
stout = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * stout ) ) ;
lmout = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * lmout ) ) ;
cout = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * cout ) ) ;
nout = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * nout ) ) ;
// sout = ZG_Malloc(&mod->memgroup, count*sizeof(*nout));
// tout = ZG_Malloc(&mod->memgroup, count*sizeof(*nout));
2004-08-21 01:25:48 +00:00
map_verts = out ;
map_vertstmexcoords = stout ;
2013-10-08 14:28:11 +00:00
for ( i = 0 ; i < MAXRLIGHTMAPS ; i + + )
2013-08-27 13:18:09 +00:00
{
map_vertlstmexcoords [ i ] = lmout ;
map_colors4f_array [ i ] = cout ;
}
2004-10-26 15:30:13 +00:00
map_normals_array = nout ;
2014-01-13 02:42:25 +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
}
2014-10-05 20:04:11 +00:00
qboolean CModRBSP_LoadVertexes ( model_t * mod , qbyte * mod_base , 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 ;
2014-01-13 02:42:25 +00:00
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
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2005-04-21 00:02:01 +00:00
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
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * out ) ) ;
stout = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * stout ) ) ;
lmout = ZG_Malloc ( & mod - > memgroup , MAXRLIGHTMAPS * count * sizeof ( * lmout ) ) ;
cout = ZG_Malloc ( & mod - > memgroup , MAXRLIGHTMAPS * count * sizeof ( * cout ) ) ;
nout = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * nout ) ) ;
// sout = ZG_Malloc(&mod->memgroup, count*sizeof(*sout));
// tout = ZG_Malloc(&mod->memgroup, count*sizeof(*tout));
2005-04-21 00:02:01 +00:00
map_verts = out ;
map_vertstmexcoords = stout ;
2013-10-08 14:28:11 +00:00
for ( sty = 0 ; sty < MAXRLIGHTMAPS ; sty + + )
2013-08-27 13:18:09 +00:00
{
2012-07-05 19:42:36 +00:00
map_vertlstmexcoords [ sty ] = lmout + sty * count ;
2013-08-27 13:18:09 +00:00
map_colors4f_array [ sty ] = cout + sty * count ;
}
2005-04-21 00:02:01 +00:00
map_normals_array = nout ;
2014-01-13 02:42:25 +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 ] ) ;
2013-10-08 14:28:11 +00:00
for ( sty = 0 ; sty < MAXRLIGHTMAPS ; sty + + )
2012-07-05 19:42:36 +00:00
map_vertlstmexcoords [ sty ] [ i ] [ j ] = LittleFloat ( ( ( float * ) in - > texcoords ) [ j + 2 * ( sty + 1 ) ] ) ;
2005-04-21 00:02:01 +00:00
}
2013-10-08 14:28:11 +00:00
for ( sty = 0 ; sty < MAXRLIGHTMAPS ; sty + + )
2005-04-21 00:02:01 +00:00
{
2013-08-27 13:18:09 +00:00
for ( j = 0 ; j < 4 ; j + + )
{
map_colors4f_array [ sty ] [ i ] [ j ] = in - > color [ sty ] [ j ] / 255.0f ;
}
2005-04-21 00:02:01 +00:00
}
}
2006-03-13 05:54:12 +00:00
return true ;
2005-04-21 00:02:01 +00:00
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadIndexes ( model_t * loadmodel , qbyte * mod_base , 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
{
2013-07-14 12:22:51 +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
2013-07-14 12:22:51 +00:00
out = ZG_Malloc ( & loadmodel - > memgroup , count * sizeof ( * out ) ) ;
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
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadFaces ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
q3dface_t * in ;
q3cface_t * out ;
int i , count ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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 ) ;
2013-06-23 02:17:02 +00:00
if ( count > SANITY_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 ) ;
2014-05-10 13:42:13 +00:00
if ( out - > facetype = = MST_PATCH )
{
out - > patch . cp [ 0 ] = LittleLong ( in - > patchwidth ) ;
out - > patch . cp [ 1 ] = LittleLong ( in - > patchheight ) ;
}
else
{
out - > soup . firstindex = LittleLong ( in - > firstindex ) ;
out - > soup . numindicies = LittleLong ( in - > num_indexes ) ;
}
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
mod - > numsurfaces = i ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
qboolean CModRBSP_LoadFaces ( model_t * mod , qbyte * mod_base , lump_t * l )
2005-04-21 00:02:01 +00:00
{
rbspface_t * in ;
q3cface_t * out ;
int i , count ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2005-04-21 00:02:01 +00:00
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 ) ;
2013-06-23 02:17:02 +00:00
if ( count > SANITY_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 ) ;
2014-05-10 13:42:13 +00:00
if ( out - > facetype = = MST_PATCH )
{
out - > patch . cp [ 0 ] = LittleLong ( in - > patchwidth ) ;
out - > patch . cp [ 1 ] = LittleLong ( in - > patchheight ) ;
}
else
{
out - > soup . firstindex = LittleLong ( in - > firstindex ) ;
out - > soup . numindicies = LittleLong ( in - > num_indexes ) ;
}
2005-04-21 00:02:01 +00:00
}
2014-10-05 20:04:11 +00:00
mod - > 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
= = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadFogs ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-10-19 16:10:14 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
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
{
2014-10-05 20:04:11 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , mod - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-10-19 16:10:14 +00:00
count = l - > filelen / sizeof ( * in ) ;
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * out ) ) ;
2004-10-19 16:10:14 +00:00
2014-10-05 20:04:11 +00:00
mod - > fogs = out ;
mod - > numfogs = count ;
2004-10-19 16:10:14 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
if ( LittleLong ( in - > visibleSide ) = = - 1 )
{
continue ;
}
2015-02-02 08:01:53 +00:00
brush = prv - > 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 ;
2014-10-05 20:04:11 +00:00
Q_strncpyz ( out - > shadername , in - > shader , sizeof ( out - > shadername ) ) ;
2004-10-19 16:10:14 +00:00
out - > numplanes = brush - > numsides ;
2014-10-05 20:04:11 +00:00
out - > planes = ZG_Malloc ( & mod - > memgroup , out - > numplanes * sizeof ( cplane_t * ) ) ;
2004-10-19 16:10:14 +00:00
for ( j = 0 ; j < out - > numplanes ; j + + )
{
out - > planes [ j ] = brushsides [ j ] . plane ;
}
}
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
2014-10-05 20:04:11 +00:00
mfog_t * Mod_FogForOrigin ( model_t * wmodel , vec3_t org )
2005-05-26 12:55:34 +00:00
{
int i , j ;
2014-10-05 20:04:11 +00:00
mfog_t * ret ;
2005-05-26 12:55:34 +00:00
float dot ;
2014-10-05 20:04:11 +00:00
if ( ! wmodel | | wmodel - > loadstate ! = MLS_LOADED )
2005-05-26 12:55:34 +00:00
return NULL ;
2014-10-05 20:04:11 +00:00
for ( i = 0 , ret = wmodel - > fogs ; i < wmodel - > numfogs ; i + + , ret + + )
2005-05-26 12:55:34 +00:00
{
2014-10-05 20:04:11 +00:00
if ( ! ret - > shader )
2005-05-26 12:55:34 +00:00
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 ) ) ;
2013-10-08 14:28:11 +00:00
for ( sty = 0 ; sty < MAXRLIGHTMAPS ; sty + + )
2013-08-27 13:18:09 +00:00
{
if ( mesh - > colors4f_array [ sty ] )
Patch_Evaluate ( map_colors4f_array [ sty ] [ firstvert ] , patch_cp , step , mesh - > colors4f_array [ sty ] [ 0 ] , 4 ) ;
}
2010-05-01 22:47:47 +00:00
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 ) ;
2013-10-08 14:28:11 +00:00
for ( sty = 0 ; sty < MAXRLIGHTMAPS ; sty + + )
2012-07-05 19:42:36 +00:00
{
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
}
2014-10-05 20:04:11 +00:00
void CModRBSP_BuildSurfMesh ( model_t * mod , msurface_t * out , builddata_t * bd )
2012-07-05 19:42:36 +00:00
{
2014-10-05 20:04:11 +00:00
rbspface_t * in = ( rbspface_t * ) ( bd + 1 ) ;
int idx = ( out - mod - > surfaces ) - mod - > firstmodelsurface ;
2012-07-05 19:42:36 +00:00
int sty ;
in + = idx ;
if ( LittleLong ( in - > facetype ) = = MST_PATCH )
{
2014-10-05 20:04:11 +00:00
GL_CreateMeshForPatch ( mod , out - > mesh , LittleLong ( in - > patchwidth ) , LittleLong ( in - > patchheight ) , LittleLong ( in - > num_vertices ) , LittleLong ( in - > firstvertex ) ) ;
2012-07-05 19:42:36 +00:00
}
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 ] ) ;
2013-10-08 14:28:11 +00:00
for ( sty = 0 ; sty < MAXRLIGHTMAPS ; sty + + )
2012-07-05 19:42:36 +00:00
{
Vector2Copy ( map_vertlstmexcoords [ sty ] [ fv + i ] , out - > mesh - > lmst_array [ sty ] [ i ] ) ;
2013-08-27 13:18:09 +00:00
Vector4Copy ( map_colors4f_array [ sty ] [ fv + i ] , out - > mesh - > colors4f_array [ sty ] [ i ] ) ;
2012-07-05 19:42:36 +00:00
}
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
}
2014-10-05 20:04:11 +00:00
void CModQ3_BuildSurfMesh ( model_t * mod , msurface_t * out , builddata_t * bd )
2012-07-05 19:42:36 +00:00
{
2014-10-05 20:04:11 +00:00
q3dface_t * in = ( q3dface_t * ) ( bd + 1 ) ;
int idx = ( out - mod - > surfaces ) - mod - > firstmodelsurface ;
2012-07-05 19:42:36 +00:00
in + = idx ;
if ( LittleLong ( in - > facetype ) = = MST_PATCH )
{
2014-10-05 20:04:11 +00:00
GL_CreateMeshForPatch ( mod , out - > mesh , LittleLong ( in - > patchwidth ) , LittleLong ( in - > patchheight ) , LittleLong ( in - > num_vertices ) , LittleLong ( in - > firstvertex ) ) ;
2012-07-05 19:42:36 +00:00
}
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 ] ) ;
2013-08-27 13:18:09 +00:00
Vector4Copy ( map_colors4f_array [ 0 ] [ fv + i ] , out - > mesh - > colors4f_array [ 0 ] [ i ] ) ;
2012-07-05 19:42:36 +00:00
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
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadRFaces ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2014-10-05 20:04:11 +00:00
extern cvar_t r_vertexlight ;
2004-08-21 01:25:48 +00:00
q3dface_t * in ;
msurface_t * out ;
mplane_t * pl ;
2014-10-05 20:04:11 +00:00
int facetype ;
2004-08-21 01:25:48 +00:00
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
{
2014-10-05 20:04:11 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , mod - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
count = l - > filelen / sizeof ( * in ) ;
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * out ) ) ;
pl = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * pl ) ) ; //create a new array of planes for speed.
mesh = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * mesh ) ) ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > surfaces = out ;
mod - > numsurfaces = count ;
2004-08-21 01:25:48 +00:00
for ( surfnum = 0 ; surfnum < count ; surfnum + + , out + + , in + + , pl + + )
{
out - > plane = pl ;
2014-10-05 20:04:11 +00:00
facetype = LittleLong ( in - > facetype ) ;
out - > texinfo = mod - > texinfo + LittleLong ( in - > shadernum ) ;
if ( in - > facetype = = MST_FLARE )
out - > texinfo = mod - > texinfo + mod - > numtexinfo * 2 ;
else if ( in - > facetype = = MST_TRIANGLE_SOUP | | r_vertexlight . value )
out - > texinfo + = mod - > numtexinfo ; //soup/vertex light uses a different version of the same shader (with all the lightmaps collapsed)
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 ;
2013-10-08 14:28:11 +00:00
for ( sty = 1 ; sty < MAXRLIGHTMAPS ; sty + + )
2012-07-05 19:42:36 +00:00
{
out - > styles [ sty ] = 255 ;
out - > lightmaptexturenums [ sty ] = - 1 ;
}
2015-03-03 00:14:43 +00:00
out - > lmshift = LMSHIFT_DEFAULT ;
out - > extents [ 0 ] = ( LittleLong ( in - > lightmap_width ) - 1 ) < < out - > lmshift ;
out - > extents [ 1 ] = ( LittleLong ( in - > lightmap_height ) - 1 ) < < out - > lmshift ;
2011-07-30 14:14:56 +00:00
out - > samples = NULL ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
if ( mod - > lightmaps . count < out - > lightmaptexturenums [ 0 ] + 1 )
mod - > lightmaps . count = out - > lightmaptexturenums [ 0 ] + 1 ;
2012-07-05 19:42:36 +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 ) ;
}
2004-10-19 16:10:14 +00:00
2015-02-02 08:01:53 +00:00
if ( prv - > surfaces [ LittleLong ( in - > shadernum ) ] . c . value = = 0 | | prv - > 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 ;
2014-10-05 20:04:11 +00:00
if ( mod - > 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
2014-10-05 20:04:11 +00:00
if ( LittleLong ( in - > fognum ) = = - 1 | | ! mod - > numfogs )
2004-10-19 16:10:14 +00:00
out - > fog = NULL ;
else
2014-10-05 20:04:11 +00:00
out - > fog = mod - > fogs + LittleLong ( in - > fognum ) ;
2009-11-04 21:16:50 +00:00
2015-02-02 08:01:53 +00:00
if ( prv - > 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
}
2014-10-05 20:04:11 +00:00
else if ( 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
}
2014-10-05 20:04:11 +00:00
else if ( facetype = = MST_PLANAR | | 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
2014-10-05 20:04:11 +00:00
Mod_SortShaders ( mod ) ;
2006-03-13 05:54:12 +00:00
return true ;
2005-04-21 00:02:01 +00:00
}
2014-10-05 20:04:11 +00:00
qboolean CModRBSP_LoadRFaces ( model_t * mod , qbyte * mod_base , lump_t * l )
2005-04-21 00:02:01 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2014-10-05 20:04:11 +00:00
extern cvar_t r_vertexlight ;
2005-04-21 00:02:01 +00:00
rbspface_t * in ;
msurface_t * out ;
mplane_t * pl ;
2014-10-05 20:04:11 +00:00
int facetype ;
2005-04-21 00:02:01 +00:00
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
{
2014-10-05 20:04:11 +00:00
Con_Printf ( CON_ERROR " MOD_LoadBmodel: funny lump size in %s \n " , mod - > name ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
count = l - > filelen / sizeof ( * in ) ;
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * out ) ) ;
pl = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * pl ) ) ; //create a new array of planes for speed.
mesh = ZG_Malloc ( & mod - > memgroup , count * sizeof ( * mesh ) ) ;
2005-04-21 00:02:01 +00:00
2014-10-05 20:04:11 +00:00
mod - > surfaces = out ;
mod - > numsurfaces = count ;
2005-04-21 00:02:01 +00:00
for ( surfnum = 0 ; surfnum < count ; surfnum + + , out + + , in + + , pl + + )
{
out - > plane = pl ;
2014-10-05 20:04:11 +00:00
facetype = LittleLong ( in - > facetype ) ;
out - > texinfo = mod - > texinfo + LittleLong ( in - > shadernum ) ;
if ( facetype = = MST_FLARE )
out - > texinfo = mod - > texinfo + mod - > numtexinfo * 2 ;
else if ( facetype = = MST_TRIANGLE_SOUP | | r_vertexlight . value )
out - > texinfo + = mod - > numtexinfo ; //soup/vertex light uses a different version of the same shader (with all the lightmaps collapsed)
2013-10-08 14:28:11 +00:00
for ( j = 0 ; j < 4 & & j < MAXRLIGHTMAPS ; j + + )
2012-07-05 19:42:36 +00:00
{
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 ] ;
2014-10-05 20:04:11 +00:00
if ( mod - > lightmaps . count < out - > lightmaptexturenums [ j ] + 1 )
mod - > lightmaps . count = out - > lightmaptexturenums [ j ] + 1 ;
2012-07-05 19:42:36 +00:00
}
2015-03-03 00:14:43 +00:00
out - > lmshift = LMSHIFT_DEFAULT ;
out - > extents [ 0 ] = ( LittleLong ( in - > lightmap_width ) - 1 ) < < out - > lmshift ;
out - > extents [ 1 ] = ( LittleLong ( in - > lightmap_height ) - 1 ) < < out - > lmshift ;
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
2015-02-02 08:01:53 +00:00
if ( prv - > surfaces [ in - > shadernum ] . c . value = = 0 | | prv - > surfaces [ in - > shadernum ] . c . value & Q3CONTENTS_TRANSLUCENT )
2005-04-21 00:02:01 +00:00
//q3dm10's thingie is 0
out - > flags | = SURF_DRAWALPHA ;
2014-10-05 20:04:11 +00:00
if ( mod - > texinfo [ in - > shadernum ] . flags & TI_SKY )
2005-04-21 00:02:01 +00:00
out - > flags | = SURF_DRAWSKY ;
2014-10-05 20:04:11 +00:00
if ( in - > fognum < 0 | | in - > fognum > = mod - > numfogs )
2005-04-21 00:02:01 +00:00
out - > fog = NULL ;
else
2014-10-05 20:04:11 +00:00
out - > fog = mod - > fogs + in - > fognum ;
2012-07-05 19:42:36 +00:00
2015-02-02 08:01:53 +00:00
if ( prv - > 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
}
2014-10-05 20:04:11 +00:00
else if ( 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
}
2014-10-05 20:04:11 +00:00
else if ( facetype = = MST_PLANAR | | 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
2014-10-05 20:04:11 +00:00
Mod_SortShaders ( mod ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
# endif
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadNodes ( model_t * loadmodel , qbyte * mod_base , 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 ) ;
2013-07-14 12:22:51 +00:00
out = ZG_Malloc ( & loadmodel - > memgroup , count * sizeof ( * out ) ) ;
2004-08-21 01:25:48 +00:00
2013-06-23 02:17:02 +00:00
if ( count > SANITY_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 ] ) ;
}
2013-06-30 00:58:49 +00:00
AddPointToBounds ( out - > minmaxs , loadmodel - > mins , loadmodel - > maxs ) ;
AddPointToBounds ( out - > minmaxs + 3 , loadmodel - > mins , loadmodel - > maxs ) ;
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
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadBrushes ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
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
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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 ) ;
2013-06-23 02:17:02 +00:00
if ( count > SANITY_MAX_MAP_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
2015-02-02 08:01:53 +00:00
prv - > brushes = ZG_Malloc ( & mod - > memgroup , sizeof ( * out ) * ( count + 1 ) ) ;
2013-06-23 02:17:02 +00:00
2015-02-02 08:01:53 +00:00
out = prv - > brushes ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
prv - > numbrushes = count ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , out + + , in + + )
{
shaderref = LittleLong ( in - > shadernum ) ;
2015-02-02 08:01:53 +00:00
out - > contents = prv - > surfaces [ shaderref ] . c . value ;
out - > brushside = & prv - > 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
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadLeafs ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
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
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2014-10-05 20:04:11 +00:00
out = ZG_Malloc ( & mod - > memgroup , sizeof ( * out ) * ( count + 1 ) ) ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > leafs = out ;
mod - > numleafs = count ;
2004-08-21 01:25:48 +00:00
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
}
2014-05-10 13:42:13 +00:00
out - > cluster = LittleLong ( in - > cluster ) ;
2014-06-12 23:08:42 +00:00
out - > area = LittleLong ( in - > area ) ;
2014-05-10 13:42:13 +00:00
// out->firstleafface = LittleLong(in->firstleafsurface);
// out->numleaffaces = LittleLong(in->num_leafsurfaces);
2004-08-21 01:25:48 +00:00
out - > contents = 0 ;
2014-05-10 13:42:13 +00:00
out - > firstleafbrush = LittleLong ( in - > firstleafbrush ) ;
out - > numleafbrushes = LittleLong ( in - > num_leafbrushes ) ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
out - > firstmarksurface = mod - > marksurfaces + LittleLong ( in - > firstleafsurface ) ;
2004-08-21 01:25:48 +00:00
out - > nummarksurfaces = LittleLong ( in - > num_leafsurfaces ) ;
if ( out - > minmaxs [ 0 ] > out - > minmaxs [ 3 + 0 ] | | out - > minmaxs [ 1 ] > out - > minmaxs [ 3 + 1 ] | |
2014-05-10 13:42:13 +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 ;
}
2014-05-10 13:42:13 +00:00
for ( j = 0 ; j < out - > numleafbrushes ; j + + )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
brush = prv - > leafbrushes [ out - > firstleafbrush + j ] ;
2004-08-21 01:25:48 +00:00
out - > contents | = brush - > contents ;
}
2015-02-02 08:01:53 +00:00
if ( out - > area > = prv - > numareas )
2006-03-13 05:54:12 +00:00
{
2015-02-02 08:01:53 +00:00
prv - > numareas = out - > area + 1 ;
2006-03-13 05:54:12 +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
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadPlanes ( model_t * loadmodel , qbyte * mod_base , 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 ) ;
2014-02-11 17:51:29 +00:00
if ( count > SANITY_MAX_MAP_PLANES )
2006-03-13 05:54:12 +00:00
{
2014-02-11 17:51:29 +00:00
Con_Printf ( CON_ERROR " Too many planes on map (%i) \n " , count ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-05-26 12:55:34 +00:00
2014-02-11 17:51:29 +00:00
loadmodel - > planes = out = ZG_Malloc ( & loadmodel - > memgroup , sizeof ( * out ) * count ) ;
2004-08-21 01:25:48 +00:00
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
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadLeafBrushes ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
int i ;
2014-05-10 13:42:13 +00:00
q2cbrush_t * * out ;
2004-08-21 01:25:48 +00:00
int * in ;
int count ;
2006-03-04 20:43:48 +00:00
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2015-02-02 08:01:53 +00:00
out = prv - > leafbrushes ;
prv - > numleafbrushes = count ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
2015-02-02 08:01:53 +00:00
* out = prv - > brushes + LittleLong ( * in ) ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadBrushSides ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
int i , j ;
q2cbrushside_t * out ;
q3dbrushside_t * in ;
int count ;
int num ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2004-08-21 01:25:48 +00:00
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
2014-02-11 17:51:29 +00:00
if ( count > SANITY_MAX_MAP_BRUSHSIDES )
2006-03-13 05:54:12 +00:00
{
2014-02-11 17:51:29 +00:00
Con_Printf ( CON_ERROR " Map has too many brushsides (%i) \n " , count ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
out = prv - > brushsides = ZG_Malloc ( & mod - > memgroup , sizeof ( * out ) * count ) ;
prv - > numbrushsides = count ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
num = LittleLong ( in - > planenum ) ;
2014-10-05 20:04:11 +00:00
out - > plane = & mod - > planes [ num ] ;
2004-08-21 01:25:48 +00:00
j = LittleLong ( in - > texinfo ) ;
2014-10-05 20:04:11 +00:00
if ( j > = mod - > 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 ;
}
2015-02-02 08:01:53 +00:00
out - > surface = & prv - > surfaces [ j ] ;
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
}
2014-10-05 20:04:11 +00:00
qboolean CModRBSP_LoadBrushSides ( model_t * mod , qbyte * mod_base , lump_t * l )
2005-04-21 00:02:01 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2005-04-21 00:02:01 +00:00
int i , j ;
q2cbrushside_t * out ;
rbspbrushside_t * in ;
int count ;
int num ;
2014-10-05 20:04:11 +00:00
in = ( void * ) ( mod_base + l - > fileofs ) ;
2005-04-21 00:02:01 +00:00
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
2014-02-11 17:51:29 +00:00
if ( count > SANITY_MAX_MAP_BRUSHSIDES )
2006-03-13 05:54:12 +00:00
{
2014-02-11 17:51:29 +00:00
Con_Printf ( CON_ERROR " Map has too many brushsides (%i) \n " , count ) ;
2006-03-13 05:54:12 +00:00
return false ;
}
2005-04-21 00:02:01 +00:00
2015-02-02 08:01:53 +00:00
out = prv - > brushsides = ZG_Malloc ( & mod - > memgroup , sizeof ( * out ) * count ) ;
prv - > numbrushsides = count ;
2005-04-21 00:02:01 +00:00
for ( i = 0 ; i < count ; i + + , in + + , out + + )
{
num = LittleLong ( in - > planenum ) ;
2014-10-05 20:04:11 +00:00
out - > plane = & mod - > planes [ num ] ;
2005-04-21 00:02:01 +00:00
j = LittleLong ( in - > texinfo ) ;
2014-10-05 20:04:11 +00:00
if ( j > = mod - > 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 ;
}
2015-02-02 08:01:53 +00:00
out - > surface = & prv - > surfaces [ j ] ;
2005-04-21 00:02:01 +00:00
}
2006-03-13 05:54:12 +00:00
return true ;
2005-04-21 00:02:01 +00:00
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadVisibility ( model_t * mod , qbyte * mod_base , lump_t * l )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
unsigned int numclusters ;
2005-05-26 12:55:34 +00:00
if ( l - > filelen = = 0 )
{
int i ;
numclusters = 0 ;
2014-10-05 20:04:11 +00:00
for ( i = 0 ; i < mod - > numleafs ; i + + )
if ( numclusters < = mod - > leafs [ i ] . cluster )
numclusters = mod - > 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
2015-02-02 08:01:53 +00:00
prv - > q3pvs = ZG_Malloc ( & mod - > memgroup , sizeof ( * prv - > q3pvs ) + ( numclusters + 7 ) / 8 * numclusters ) ;
memset ( prv - > q3pvs , 0xff , sizeof ( * prv - > q3pvs ) + ( numclusters + 7 ) / 8 * numclusters ) ;
prv - > q3pvs - > numclusters = numclusters ;
prv - > numvisibility = 0 ;
prv - > q3pvs - > rowsize = ( prv - > q3pvs - > numclusters + 7 ) / 8 ;
2005-05-26 12:55:34 +00:00
}
else
{
2015-02-02 08:01:53 +00:00
prv - > numvisibility = l - > filelen ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
prv - > q3pvs = ZG_Malloc ( & mod - > memgroup , l - > filelen ) ;
mod - > vis = ( q2dvis_t * ) prv - > q3pvs ;
memcpy ( prv - > q3pvs , mod_base + l - > fileofs , l - > filelen ) ;
2005-05-26 12:55:34 +00:00
2015-02-02 08:01:53 +00:00
numclusters = prv - > q3pvs - > numclusters = LittleLong ( prv - > q3pvs - > numclusters ) ;
prv - > q3pvs - > rowsize = LittleLong ( prv - > q3pvs - > rowsize ) ;
2005-05-26 12:55:34 +00:00
}
2014-10-05 20:04:11 +00:00
mod - > numclusters = numclusters ;
2006-03-13 05:54:12 +00:00
return true ;
2004-08-21 01:25:48 +00:00
}
# ifndef SERVERONLY
2014-10-05 20:04:11 +00:00
void CModQ3_LoadLighting ( model_t * loadmodel , qbyte * mod_base , lump_t * l )
2013-03-12 23:09:25 +00:00
{
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 ) ) ) ;
2013-10-08 14:28:11 +00:00
if ( ! samples )
return ;
2013-03-12 23:09:25 +00:00
loadmodel - > engineflags | = MDLF_RGBLIGHTING ;
2013-07-14 12:22:51 +00:00
loadmodel - > lightdata = out = ZG_Malloc ( & loadmodel - > memgroup , samples ) ;
2013-03-12 23:09:25 +00:00
//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 ) ;
}
}
}
2014-10-05 20:04:11 +00:00
qboolean CModQ3_LoadLightgrid ( model_t * loadmodel , qbyte * mod_base , 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 ) ;
2013-07-14 12:22:51 +00:00
grid = ZG_Malloc ( & loadmodel - > memgroup , sizeof ( q3lightgridinfo_t ) + count * sizeof ( * out ) ) ;
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
}
2014-10-05 20:04:11 +00:00
qboolean CModRBSP_LoadLightgrid ( model_t * loadmodel , qbyte * mod_base , 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 ) ;
2013-07-14 12:22:51 +00:00
grid = ZG_Malloc ( & loadmodel - > memgroup , sizeof ( q3lightgridinfo_t ) + ecount * sizeof ( * eout ) + icount * sizeof ( * iout ) ) ;
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
2014-10-05 20:04:11 +00:00
# endif
2004-08-21 01:25:48 +00:00
# ifndef SERVERONLY
qbyte * ReadPCXPalette ( qbyte * buf , int len , qbyte * out ) ;
int CM_GetQ2Palette ( void )
{
2009-11-04 21:16:50 +00:00
char * f ;
2014-10-05 20:04:11 +00:00
size_t sz ;
sz = 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 ;
}
2014-10-05 20:04:11 +00:00
if ( ! ReadPCXPalette ( f , sz , d_q28to24table ) )
2004-08-21 01:25:48 +00:00
{
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
2015-02-02 08:01:53 +00:00
void CM_OpenAllPortals ( model_t * mod , char * ents ) //this is a compleate hack. About as compleate as possible.
2004-08-21 01:25:48 +00:00
{ //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 " ) )
{
2015-02-02 08:01:53 +00:00
CMQ2_SetAreaPortalState ( mod , atoi ( style ) , true ) ;
2004-08-21 01:25:48 +00:00
}
}
ents + + ;
}
}
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2014-10-05 20:04:11 +00:00
void CMQ3_CalcPHS ( model_t * mod )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
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 " ) ;
2015-02-02 08:01:53 +00:00
prv - > q3phs = ZG_Malloc ( & mod - > memgroup , sizeof ( * prv - > q3phs ) + prv - > q3pvs - > rowsize * prv - > q3pvs - > numclusters ) ;
2012-07-07 05:17:43 +00:00
2015-02-02 08:01:53 +00:00
rowwords = prv - > q3pvs - > rowsize / sizeof ( int ) ;
rowbytes = prv - > q3pvs - > rowsize ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
memset ( prv - > q3phs , 0 , sizeof ( * prv - > q3phs ) + prv - > q3pvs - > rowsize * prv - > q3pvs - > numclusters ) ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
prv - > q3phs - > rowsize = prv - > q3pvs - > rowsize ;
prv - > q3phs - > numclusters = numclusters = prv - > 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 + + )
{
2014-10-05 20:04:11 +00:00
scan = CM_ClusterPVS ( mod , 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 ;
2015-02-02 08:01:53 +00:00
scan = ( qbyte * ) prv - > q3pvs - > data ;
dest = ( unsigned int * ) ( prv - > 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
{
2015-02-02 08:01:53 +00:00
src = ( unsigned int * ) ( prv - > q3pvs - > data ) + index * rowwords ;
2012-07-24 00:20:45 +00:00
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
2014-05-23 02:02:51 +00:00
/*
2014-05-10 13:42:13 +00:00
static 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
}
2014-05-23 02:02:51 +00:00
*/
2004-08-21 01:25:48 +00:00
# ifndef SERVERONLY
# define GLQ2BSP_LightPointValues GLQ1BSP_LightPointValues
extern int r_dlightframecount ;
2014-05-10 13:42:13 +00:00
static void Q2BSP_MarkLights ( dlight_t * light , int bit , mnode_t * node )
2004-08-21 01:25:48 +00:00
{
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
2014-05-10 13:42:13 +00:00
static void GLR_Q2BSP_StainNode ( mnode_t * node , float * parms )
2004-08-21 01:25:48 +00:00
{
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 ) ;
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = =
CM_LoadMap
Loads in the map and all submodels
= = = = = = = = = = = = = = = = = =
*/
2014-10-05 20:04:11 +00:00
static cmodel_t * CM_LoadMap ( model_t * mod , qbyte * filein , size_t filelen , qboolean clientload , unsigned * checksum )
2004-08-21 01:25:48 +00:00
{
unsigned * buf ;
2014-05-10 13:42:13 +00:00
int i ;
2004-08-21 01:25:48 +00:00
q2dheader_t header ;
int length ;
static unsigned last_checksum ;
2006-03-12 22:01:49 +00:00
qboolean noerrors = true ;
2014-10-05 20:04:11 +00:00
model_t * wmod = mod ;
char loadname [ 32 ] ;
qbyte * mod_base = ( qbyte * ) filein ;
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 ;
2014-10-05 20:04:11 +00:00
qbyte * facedata = NULL ;
unsigned int facesize = 0 ;
2015-02-02 08:01:53 +00:00
cminfo_t * prv ;
2014-10-05 20:04:11 +00:00
COM_FileBase ( mod - > name , loadname , sizeof ( loadname ) ) ;
2012-07-05 19:42:36 +00:00
2004-08-21 01:25:48 +00:00
// free old stuff
2015-02-02 08:01:53 +00:00
mod - > meshinfo = prv = ZG_Malloc ( & mod - > memgroup , sizeof ( * prv ) ) ;
prv - > numcmodels = 0 ;
prv - > numvisibility = 0 ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > type = mod_brush ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
if ( ! mod - > name [ 0 ] )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
prv - > cmodels = ZG_Malloc ( & mod - > memgroup , 1 * sizeof ( * prv - > cmodels ) ) ;
2014-10-05 20:04:11 +00:00
mod - > leafs = ZG_Malloc ( & mod - > memgroup , 1 * sizeof ( * mod - > leafs ) ) ;
2015-02-02 08:01:53 +00:00
prv - > numcmodels = 1 ;
prv - > numareas = 1 ;
2004-08-21 01:25:48 +00:00
* checksum = 0 ;
2015-02-02 08:01:53 +00:00
prv - > cmodels [ 0 ] . headnode = ( mnode_t * ) mod - > leafs ; //directly start with the empty leaf
return & prv - > cmodels [ 0 ] ; // cinematic servers won't have anything at all
2004-08-21 01:25:48 +00:00
}
//
// load the file
//
buf = ( unsigned * ) filein ;
2014-10-05 20:04:11 +00:00
length = filelen ;
2004-08-21 01:25:48 +00:00
if ( ! buf )
2006-03-12 22:01:49 +00:00
{
2014-10-05 20:04:11 +00:00
Con_Printf ( CON_ERROR " Couldn't load %s \n " , mod - > 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 ) ;
2014-10-05 20:04:11 +00:00
ClearBounds ( mod - > mins , mod - > maxs ) ;
2013-06-30 00:58:49 +00:00
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 "
2015-03-03 00:14:43 +00:00
, mod - > name , header . version , BSPVERSION_Q2 , BSPVERSION_Q3 ) ;
2006-03-12 22:01:49 +00:00
return NULL ;
2004-08-21 01:25:48 +00:00
break ;
2014-05-10 13:42:13 +00:00
# ifdef Q3BSPS
2015-03-03 00:14:43 +00:00
case BSPVERSION_RBSP : //rbsp/fbsp
case BSPVERSION_RTCW : //rtcw
case BSPVERSION_Q3 :
if ( header . ident = = ( ( ' F ' < < 0 ) + ( ' B ' < < 8 ) + ( ' S ' < < 16 ) + ( ' P ' < < 24 ) ) )
{
mod - > lightmaps . width = 512 ;
mod - > lightmaps . height = 512 ;
}
else
{
mod - > lightmaps . width = 128 ;
mod - > lightmaps . height = 128 ;
}
2015-02-02 08:01:53 +00:00
prv - > mapisq3 = true ;
2014-10-05 20:04:11 +00:00
mod - > fromgame = fg_quake3 ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < Q3LUMPS_TOTAL ; i + + )
{
2015-03-03 00:14:43 +00:00
if ( i = = RBSPLUMP_LIGHTINDEXES & & header . version ! = BSPVERSION_RBSP )
2012-07-20 01:46:05 +00:00
{
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 ) ;
2014-10-05 20:04:11 +00:00
if ( header . lumps [ i ] . filelen & & header . lumps [ i ] . fileofs + header . lumps [ i ] . filelen > filelen )
2012-07-20 01:46:05 +00:00
{
2014-10-05 20:04:11 +00:00
Con_Printf ( CON_ERROR " WARNING: q3bsp %s truncated (lump %i, %i+%i > %i) \n " , mod - > name , i , header . lumps [ i ] . fileofs , header . lumps [ i ] . filelen , filelen ) ;
header . lumps [ i ] . filelen = filelen - header . lumps [ i ] . fileofs ;
2012-07-20 01:46:05 +00:00
if ( header . lumps [ i ] . filelen < 0 )
header . lumps [ i ] . filelen = 0 ;
}
}
2004-08-21 01:25:48 +00:00
}
/*
# ifndef SERVERONLY
2014-10-05 20:04:11 +00:00
GLMod_LoadVertexes ( mod , cmod_base , & header . lumps [ Q3LUMP_DRAWVERTS ] ) ;
// GLMod_LoadEdges (mod, cmod_base, &header.lumps[Q3LUMP_EDGES]);
// GLMod_LoadSurfedges (mod, cmod_base, &header.lumps[Q3LUMP_SURFEDGES]);
GLMod_LoadLighting ( mod , cmod_base , & header . lumps [ Q3LUMP_LIGHTMAPS ] ) ;
2004-08-21 01:25:48 +00:00
# endif
2014-10-05 20:04:11 +00:00
CModQ3_LoadShaders ( mod , cmod_base , & header . lumps [ Q3LUMP_SHADERS ] ) ;
CModQ3_LoadPlanes ( mod , cmod_base , & header . lumps [ Q3LUMP_PLANES ] ) ;
CModQ3_LoadLeafBrushes ( mod , cmod_base , & header . lumps [ Q3LUMP_LEAFBRUSHES ] ) ;
CModQ3_LoadBrushes ( mod , cmod_base , & header . lumps [ Q3LUMP_BRUSHES ] ) ;
CModQ3_LoadBrushSides ( mod , cmod_base , & header . lumps [ Q3LUMP_BRUSHSIDES ] ) ;
2004-08-21 01:25:48 +00:00
# ifndef SERVERONLY
2014-10-05 20:04:11 +00:00
CMod_LoadTexInfo ( mod , cmod_base , & header . lumps [ Q3LUMP_SHADERS ] ) ;
CMod_LoadFaces ( mod , cmod_base , & header . lumps [ Q3LUMP_SURFACES ] ) ;
// GLMod_LoadMarksurfaces (mod, cmod_base, &header.lumps[Q3LUMP_LEAFFACES]);
2004-08-21 01:25:48 +00:00
# endif
2014-10-05 20:04:11 +00:00
CMod_LoadVisibility ( mod , cmod_base , & header . lumps [ Q3LUMP_VISIBILITY ] ) ;
CModQ3_LoadSubmodels ( mod , cmod_base , & header . lumps [ Q3LUMP_MODELS ] ) ;
CModQ3_LoadLeafs ( mod , cmod_base , & header . lumps [ Q3LUMP_LEAFS ] ) ;
CModQ3_LoadNodes ( mod , cmod_base , & header . lumps [ Q3LUMP_NODES ] ) ;
// CMod_LoadAreas (mod, cmod_base, &header.lumps[Q3LUMP_AREAS]);
// CMod_LoadAreaPortals (mod, cmod_base, &header.lumps[Q3LUMP_AREAPORTALS]);
CMod_LoadEntityString ( mod , cmod_base , & header . lumps [ Q3LUMP_ENTITIES ] ) ;
2004-08-21 01:25:48 +00:00
*/
2006-03-13 05:54:12 +00:00
map_faces = NULL ;
2014-10-05 20:04:11 +00:00
Q1BSPX_Setup ( mod , mod_base , filelen , header . lumps , Q3LUMPS_TOTAL ) ;
2012-02-27 12:23:15 +00:00
2015-02-02 08:01:53 +00:00
prv - > mapisq3 = true ;
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ3_LoadShaders ( mod , mod_base , & header . lumps [ Q3LUMP_SHADERS ] ) ;
noerrors = noerrors & & CModQ3_LoadPlanes ( mod , mod_base , & header . lumps [ Q3LUMP_PLANES ] ) ;
2015-03-03 00:14:43 +00:00
if ( header . version = = BSPVERSION_RBSP )
2004-08-21 01:25:48 +00:00
{
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModRBSP_LoadBrushSides ( mod , mod_base , & header . lumps [ Q3LUMP_BRUSHSIDES ] ) ;
noerrors = noerrors & & CModRBSP_LoadVertexes ( mod , mod_base , & header . lumps [ Q3LUMP_DRAWVERTS ] ) ;
2012-09-30 05:52:03 +00:00
}
else
{
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ3_LoadBrushSides ( mod , mod_base , & header . lumps [ Q3LUMP_BRUSHSIDES ] ) ;
noerrors = noerrors & & CModQ3_LoadVertexes ( mod , mod_base , & header . lumps [ Q3LUMP_DRAWVERTS ] ) ;
2012-09-30 05:52:03 +00:00
}
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ3_LoadBrushes ( mod , mod_base , & header . lumps [ Q3LUMP_BRUSHES ] ) ;
noerrors = noerrors & & CModQ3_LoadLeafBrushes ( mod , mod_base , & header . lumps [ Q3LUMP_LEAFBRUSHES ] ) ;
2012-09-30 05:52:03 +00:00
if ( header . version = = 1 )
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModRBSP_LoadFaces ( mod , mod_base , & header . lumps [ Q3LUMP_SURFACES ] ) ;
2012-09-30 05:52:03 +00:00
else
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ3_LoadFaces ( mod , mod_base , & header . lumps [ Q3LUMP_SURFACES ] ) ;
2012-09-30 05:52:03 +00:00
# ifndef SERVERONLY
if ( qrenderer ! = QR_NONE )
{
2015-03-03 00:14:43 +00:00
if ( header . version = = BSPVERSION_RBSP )
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModRBSP_LoadLightgrid ( mod , mod_base , & header . lumps [ Q3LUMP_LIGHTGRID ] , & header . lumps [ RBSPLUMP_LIGHTINDEXES ] ) ;
2005-04-21 00:02:01 +00:00
else
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ3_LoadLightgrid ( mod , mod_base , & header . lumps [ Q3LUMP_LIGHTGRID ] ) ;
noerrors = noerrors & & CModQ3_LoadIndexes ( mod , mod_base , & header . lumps [ Q3LUMP_DRAWINDEXES ] ) ;
2012-09-30 05:52:03 +00:00
2015-03-03 00:14:43 +00:00
if ( header . version ! = BSPVERSION_RTCW )
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ3_LoadFogs ( mod , mod_base , & header . lumps [ Q3LUMP_FOGS ] ) ;
2012-09-30 05:52:03 +00:00
else
2014-10-05 20:04:11 +00:00
mod - > numfogs = 0 ;
2012-09-30 05:52:03 +00:00
2014-10-05 20:04:11 +00:00
facedata = ( void * ) ( mod_base + header . lumps [ Q3LUMP_SURFACES ] . fileofs ) ;
2015-03-03 00:14:43 +00:00
if ( header . version = = BSPVERSION_RBSP )
2005-04-21 00:02:01 +00:00
{
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModRBSP_LoadRFaces ( mod , mod_base , & header . lumps [ Q3LUMP_SURFACES ] ) ;
2012-09-30 05:52:03 +00:00
buildmeshes = CModRBSP_BuildSurfMesh ;
2014-10-05 20:04:11 +00:00
facesize = sizeof ( rbspface_t ) ;
mod - > lightmaps . surfstyles = 4 ;
2005-04-21 00:02:01 +00:00
}
else
2004-08-21 01:25:48 +00:00
{
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ3_LoadRFaces ( mod , mod_base , & header . lumps [ Q3LUMP_SURFACES ] ) ;
2012-09-30 05:52:03 +00:00
buildmeshes = CModQ3_BuildSurfMesh ;
2014-10-05 20:04:11 +00:00
facesize = sizeof ( q3dface_t ) ;
mod - > lightmaps . surfstyles = 1 ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
if ( noerrors & & mod - > fromgame = = fg_quake3 )
2013-03-12 23:09:25 +00:00
{
2014-10-05 20:04:11 +00:00
i = header . lumps [ Q3LUMP_LIGHTMAPS ] . filelen / ( mod - > lightmaps . width * mod - > lightmaps . height * 3 ) ;
mod - > lightmaps . deluxemapping = ! ( i & 1 ) ;
mod - > lightmaps . count = max ( mod - > lightmaps . count , i ) ;
2013-03-12 23:09:25 +00:00
2014-10-05 20:04:11 +00:00
for ( i = 0 ; i < mod - > numsurfaces & & mod - > lightmaps . deluxemapping ; i + + )
2013-03-12 23:09:25 +00:00
{
2014-10-05 20:04:11 +00:00
if ( mod - > surfaces [ i ] . lightmaptexturenums [ 0 ] > = 0 & & ( mod - > surfaces [ i ] . lightmaptexturenums [ 0 ] & 1 ) )
mod - > lightmaps . deluxemapping = false ;
2013-03-12 23:09:25 +00:00
}
}
if ( noerrors )
2014-10-05 20:04:11 +00:00
CModQ3_LoadLighting ( mod , mod_base , & header . lumps [ Q3LUMP_LIGHTMAPS ] ) ; //fixme: duplicated loading.
2012-09-30 05:52:03 +00:00
}
2004-08-21 01:25:48 +00:00
# endif
2014-12-23 15:26:42 +00:00
noerrors = noerrors & & CModQ3_LoadMarksurfaces ( mod , mod_base , & header . lumps [ Q3LUMP_LEAFSURFACES ] ) ; noerrors = noerrors & & CModQ3_LoadLeafs ( mod , mod_base , & header . lumps [ Q3LUMP_LEAFS ] ) ;
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ3_LoadNodes ( mod , mod_base , & header . lumps [ Q3LUMP_NODES ] ) ;
noerrors = noerrors & & CModQ3_LoadSubmodels ( mod , mod_base , & header . lumps [ Q3LUMP_MODELS ] ) ;
noerrors = noerrors & & CModQ3_LoadVisibility ( mod , mod_base , & header . lumps [ Q3LUMP_VISIBILITY ] ) ;
2012-09-30 05:52:03 +00:00
if ( noerrors )
2014-10-05 20:04:11 +00:00
CMod_LoadEntityString ( mod , mod_base , & 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 ) ;
return NULL ;
}
2004-08-21 01:25:48 +00:00
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2014-10-05 20:04:11 +00:00
mod - > funcs . FatPVS = Q2BSP_FatPVS ;
mod - > funcs . EdictInFatPVS = Q2BSP_EdictInFatPVS ;
mod - > funcs . FindTouchedLeafs = Q2BSP_FindTouchedLeafs ;
2006-01-21 00:06:49 +00:00
# endif
2014-10-05 20:04:11 +00:00
mod - > funcs . ClusterPVS = CM_ClusterPVS ;
mod - > funcs . ClusterForPoint = CM_PointCluster ;
2004-08-21 01:25:48 +00:00
2012-09-30 05:52:03 +00:00
# ifndef SERVERONLY
2014-10-05 20:04:11 +00:00
mod - > funcs . LightPointValues = GLQ3_LightGrid ;
mod - > funcs . StainNode = GLR_Q2BSP_StainNode ;
mod - > funcs . MarkLights = Q2BSP_MarkLights ;
2004-08-21 01:25:48 +00:00
# endif
2014-10-05 20:04:11 +00:00
mod - > funcs . PointContents = Q2BSP_PointContents ;
mod - > funcs . NativeTrace = CM_NativeTrace ;
mod - > 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
2014-10-05 20:04:11 +00:00
if ( mod - > lightgrid )
2012-09-30 05:52:03 +00:00
{
float maxs ;
2014-10-05 20:04:11 +00:00
q3lightgridinfo_t * lg = mod - > lightgrid ;
2012-09-30 05:52:03 +00:00
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
{
2015-02-02 08:01:53 +00:00
lg - > gridMins [ i ] = lg - > gridSize [ i ] * ceil ( ( prv - > cmodels - > mins [ i ] + 1 ) / lg - > gridSize [ i ] ) ;
maxs = lg - > gridSize [ i ] * floor ( ( prv - > cmodels - > maxs [ i ] - 1 ) / lg - > gridSize [ i ] ) ;
2012-09-30 05:52:03 +00:00
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
2015-02-02 08:01:53 +00:00
if ( ! CM_CreatePatchesForLeafs ( mod , prv ) ) //for clipping
2012-09-30 05:52:03 +00:00
{
2004-08-21 01:25:48 +00:00
BZ_Free ( map_faces ) ;
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
2014-10-05 20:04:11 +00:00
CMQ3_CalcPHS ( mod ) ;
2012-09-30 05:52:03 +00:00
# endif
// BZ_Free(map_verts);
BZ_Free ( map_faces ) ;
2004-08-21 01:25:48 +00:00
break ;
# endif
2015-03-03 00:14:43 +00:00
case BSPVERSION_Q2 :
case BSPVERSION_Q2W :
mod - > lightmaps . width = LMBLOCK_SIZE_MAX ;
mod - > lightmaps . height = LMBLOCK_SIZE_MAX ;
2015-02-02 08:01:53 +00:00
prv - > mapisq3 = false ;
2014-10-05 20:04:11 +00:00
mod - > 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 ) ;
}
2015-03-03 00:14:43 +00:00
if ( header . version = = BSPVERSION_Q2W )
{
header . lumps [ i ] . filelen = LittleLong ( header . lumps [ i ] . filelen ) ;
header . lumps [ i ] . fileofs = LittleLong ( header . lumps [ i ] . fileofs ) ;
i + + ;
}
Q1BSPX_Setup ( mod , mod_base , filelen , header . lumps , i ) ;
2012-02-27 12:23:15 +00:00
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
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ2_LoadSurfaces ( mod , mod_base , & header . lumps [ Q2LUMP_TEXINFO ] ) ;
noerrors = noerrors & & CModQ2_LoadPlanes ( mod , mod_base , & header . lumps [ Q2LUMP_PLANES ] ) ;
noerrors = noerrors & & CModQ2_LoadVisibility ( mod , mod_base , & header . lumps [ Q2LUMP_VISIBILITY ] ) ;
noerrors = noerrors & & CModQ2_LoadBrushSides ( mod , mod_base , & header . lumps [ Q2LUMP_BRUSHSIDES ] ) ;
noerrors = noerrors & & CModQ2_LoadBrushes ( mod , mod_base , & header . lumps [ Q2LUMP_BRUSHES ] ) ;
noerrors = noerrors & & CModQ2_LoadLeafBrushes ( mod , mod_base , & header . lumps [ Q2LUMP_LEAFBRUSHES ] ) ;
noerrors = noerrors & & CModQ2_LoadLeafs ( mod , mod_base , & header . lumps [ Q2LUMP_LEAFS ] ) ;
noerrors = noerrors & & CModQ2_LoadNodes ( mod , mod_base , & header . lumps [ Q2LUMP_NODES ] ) ;
noerrors = noerrors & & CModQ2_LoadSubmodels ( mod , mod_base , & header . lumps [ Q2LUMP_MODELS ] ) ;
noerrors = noerrors & & CModQ2_LoadAreas ( mod , mod_base , & header . lumps [ Q2LUMP_AREAS ] ) ;
noerrors = noerrors & & CModQ2_LoadAreaPortals ( mod , mod_base , & header . lumps [ Q2LUMP_AREAPORTALS ] ) ;
2006-03-13 05:54:12 +00:00
if ( noerrors )
2014-10-05 20:04:11 +00:00
CMod_LoadEntityString ( mod , mod_base , & header . lumps [ Q2LUMP_ENTITIES ] ) ;
2004-08-21 01:25:48 +00:00
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2014-10-05 20:04:11 +00:00
mod - > funcs . FatPVS = Q2BSP_FatPVS ;
mod - > funcs . EdictInFatPVS = Q2BSP_EdictInFatPVS ;
mod - > funcs . FindTouchedLeafs = Q2BSP_FindTouchedLeafs ;
2006-01-21 00:06:49 +00:00
# endif
2014-10-05 20:04:11 +00:00
mod - > funcs . LightPointValues = NULL ;
mod - > funcs . StainNode = NULL ;
mod - > funcs . MarkLights = NULL ;
mod - > funcs . ClusterPVS = CM_ClusterPVS ;
mod - > funcs . ClusterForPoint = CM_PointCluster ;
mod - > funcs . PointContents = Q2BSP_PointContents ;
mod - > funcs . NativeTrace = CM_NativeTrace ;
mod - > funcs . NativeContents = CM_NativeContents ;
2004-08-21 01:25:48 +00:00
break ;
2015-03-03 00:14:43 +00:00
# ifndef SERVERONLY
default :
2004-08-21 01:25:48 +00:00
// load into heap
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & Mod_LoadVertexes ( mod , mod_base , & header . lumps [ Q2LUMP_VERTEXES ] ) ;
2015-03-03 00:14:43 +00:00
if ( header . version = = BSPVERSION_Q2W )
/*noerrors = noerrors &&*/ Mod_LoadVertexNormals ( mod , mod_base , & header . lumps [ 19 ] ) ;
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & Mod_LoadEdges ( mod , mod_base , & header . lumps [ Q2LUMP_EDGES ] , false ) ;
noerrors = noerrors & & Mod_LoadSurfedges ( mod , mod_base , & header . lumps [ Q2LUMP_SURFEDGES ] ) ;
2006-03-12 22:01:49 +00:00
if ( noerrors )
2015-03-03 00:14:43 +00:00
Mod_LoadLighting ( mod , mod_base , & header . lumps [ Q2LUMP_LIGHTING ] , header . version = = BSPVERSION_Q2W ) ;
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & CModQ2_LoadSurfaces ( mod , mod_base , & header . lumps [ Q2LUMP_TEXINFO ] ) ;
noerrors = noerrors & & CModQ2_LoadPlanes ( mod , mod_base , & header . lumps [ Q2LUMP_PLANES ] ) ;
noerrors = noerrors & & CModQ2_LoadTexInfo ( mod , mod_base , & header . lumps [ Q2LUMP_TEXINFO ] , loadname ) ;
2015-03-03 00:14:43 +00:00
if ( noerrors )
CMod_LoadEntityString ( mod , mod_base , & header . lumps [ Q2LUMP_ENTITIES ] ) ;
noerrors = noerrors & & CModQ2_LoadFaces ( mod , mod_base , & header . lumps [ Q2LUMP_FACES ] , header . version = = BSPVERSION_Q2W ) ;
2014-10-05 20:04:11 +00:00
noerrors = noerrors & & Mod_LoadMarksurfaces ( mod , mod_base , & header . lumps [ Q2LUMP_LEAFFACES ] , false ) ;
noerrors = noerrors & & CModQ2_LoadVisibility ( mod , mod_base , & header . lumps [ Q2LUMP_VISIBILITY ] ) ;
noerrors = noerrors & & CModQ2_LoadBrushSides ( mod , mod_base , & header . lumps [ Q2LUMP_BRUSHSIDES ] ) ;
noerrors = noerrors & & CModQ2_LoadBrushes ( mod , mod_base , & header . lumps [ Q2LUMP_BRUSHES ] ) ;
noerrors = noerrors & & CModQ2_LoadLeafBrushes ( mod , mod_base , & header . lumps [ Q2LUMP_LEAFBRUSHES ] ) ;
noerrors = noerrors & & CModQ2_LoadLeafs ( mod , mod_base , & header . lumps [ Q2LUMP_LEAFS ] ) ;
noerrors = noerrors & & CModQ2_LoadNodes ( mod , mod_base , & header . lumps [ Q2LUMP_NODES ] ) ;
noerrors = noerrors & & CModQ2_LoadSubmodels ( mod , mod_base , & header . lumps [ Q2LUMP_MODELS ] ) ;
noerrors = noerrors & & CModQ2_LoadAreas ( mod , mod_base , & header . lumps [ Q2LUMP_AREAS ] ) ;
noerrors = noerrors & & CModQ2_LoadAreaPortals ( mod , mod_base , & header . lumps [ Q2LUMP_AREAPORTALS ] ) ;
2006-03-12 22:01:49 +00:00
if ( ! noerrors )
{
return NULL ;
}
2006-01-21 00:06:49 +00:00
# ifndef CLIENTONLY
2014-10-05 20:04:11 +00:00
mod - > funcs . FatPVS = Q2BSP_FatPVS ;
mod - > funcs . EdictInFatPVS = Q2BSP_EdictInFatPVS ;
mod - > funcs . FindTouchedLeafs = Q2BSP_FindTouchedLeafs ;
2006-01-21 00:06:49 +00:00
# endif
2014-10-05 20:04:11 +00:00
mod - > funcs . LightPointValues = GLQ2BSP_LightPointValues ;
mod - > funcs . StainNode = GLR_Q2BSP_StainNode ;
mod - > funcs . MarkLights = Q2BSP_MarkLights ;
mod - > funcs . ClusterPVS = CM_ClusterPVS ;
mod - > funcs . ClusterForPoint = CM_PointCluster ;
mod - > funcs . PointContents = Q2BSP_PointContents ;
mod - > funcs . NativeTrace = CM_NativeTrace ;
mod - > funcs . NativeContents = CM_NativeContents ;
2004-08-21 01:25:48 +00:00
break ;
# endif
}
}
CM_InitBoxHull ( ) ;
if ( map_autoopenportals . value )
2015-02-02 08:01:53 +00:00
memset ( prv - > portalopen , 1 , sizeof ( prv - > portalopen ) ) ; //open them all. Used for progs that havn't got a clue.
2004-08-21 01:25:48 +00:00
else
2015-02-02 08:01:53 +00:00
memset ( prv - > portalopen , 0 , sizeof ( prv - > portalopen ) ) ; //make them start closed.
FloodAreaConnections ( prv ) ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > checksum = mod - > checksum2 = * checksum ;
mod - > nummodelsurfaces = mod - > numsurfaces ;
memset ( & mod - > batches , 0 , sizeof ( mod - > batches ) ) ;
mod - > vbos = NULL ;
mod - > numsubmodels = CM_NumInlineModels ( mod ) ;
2015-02-02 08:01:53 +00:00
mod - > hulls [ 0 ] . firstclipnode = prv - > cmodels [ 0 ] . headnode - mod - > nodes ;
mod - > rootnode = prv - > cmodels [ 0 ] . headnode ;
mod - > nummodelsurfaces = prv - > cmodels [ 0 ] . numsurfaces ;
2004-08-21 01:25:48 +00:00
2012-07-05 19:42:36 +00:00
# ifndef SERVERONLY
if ( qrenderer ! = QR_NONE )
2014-10-05 20:04:11 +00:00
{
builddata_t * bd = NULL ;
if ( buildmeshes )
{
bd = BZ_Malloc ( sizeof ( * bd ) + facesize * mod - > nummodelsurfaces ) ;
bd - > buildfunc = buildmeshes ;
memcpy ( bd + 1 , facedata + mod - > firstmodelsurface * facesize , facesize * mod - > nummodelsurfaces ) ;
}
COM_AddWork ( 0 , ModBrush_LoadGLStuff , mod , bd , 0 , 0 ) ;
}
2012-07-05 19:42:36 +00:00
# endif
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
for ( i = 1 ; i < mod - > numsubmodels ; i + + )
2004-08-21 01:25:48 +00:00
{
2014-10-05 20:04:11 +00:00
cmodel_t * bm ;
2011-12-23 03:12:29 +00:00
2014-10-05 20:04:11 +00:00
char name [ MAX_QPATH ] ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
Q_snprintfz ( name , sizeof ( name ) , " *%i:%s " , i , wmod - > name ) ;
mod = Mod_FindName ( name ) ;
* mod = * wmod ;
Q_strncpyz ( mod - > name , name , sizeof ( mod - > name ) ) ;
memset ( & mod - > memgroup , 0 , sizeof ( mod - > memgroup ) ) ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
bm = CM_InlineModel ( wmod , name ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
mod - > hulls [ 0 ] . firstclipnode = - 1 ; //no nodes,
if ( bm - > headleaf )
{
mod - > leafs = bm - > headleaf ;
mod - > nodes = NULL ;
mod - > hulls [ 0 ] . firstclipnode = - 1 ; //make it refer directly to the first leaf, for things that still use numbers.
mod - > rootnode = ( mnode_t * ) bm - > headleaf ;
}
else
{
mod - > leafs = wmod - > leafs ;
mod - > nodes = wmod - > nodes ;
mod - > hulls [ 0 ] . firstclipnode = bm - > headnode - mod - > nodes ; //determine the correct node index
mod - > rootnode = bm - > headnode ;
}
mod - > nummodelsurfaces = bm - > numsurfaces ;
mod - > firstmodelsurface = bm - > firstsurface ;
2006-03-04 20:43:48 +00:00
2014-10-05 20:04:11 +00:00
memset ( & mod - > batches , 0 , sizeof ( mod - > batches ) ) ;
mod - > vbos = NULL ;
2012-07-05 19:42:36 +00:00
2014-10-05 20:04:11 +00:00
VectorCopy ( bm - > maxs , mod - > maxs ) ;
VectorCopy ( bm - > mins , mod - > mins ) ;
2004-08-21 01:25:48 +00:00
# ifndef SERVERONLY
2014-10-05 20:04:11 +00:00
mod - > radius = RadiusFromBounds ( mod - > mins , mod - > maxs ) ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
if ( qrenderer ! = QR_NONE )
{
builddata_t * bd = NULL ;
if ( buildmeshes )
{
bd = BZ_Malloc ( sizeof ( * bd ) + facesize * mod - > nummodelsurfaces ) ;
bd - > buildfunc = buildmeshes ;
memcpy ( bd + 1 , facedata + mod - > firstmodelsurface * facesize , facesize * mod - > nummodelsurfaces ) ;
}
COM_AddWork ( 0 , ModBrush_LoadGLStuff , mod , bd , i , 0 ) ;
2004-08-21 01:25:48 +00:00
}
2014-10-05 20:04:11 +00:00
# endif
COM_AddWork ( 0 , Mod_ModelLoaded , mod , NULL , MLS_LOADED , 0 ) ;
2004-08-21 01:25:48 +00:00
}
2012-07-14 23:17:54 +00:00
# ifdef TERRAIN
2014-10-05 20:04:11 +00:00
mod - > terrain = Mod_LoadTerrainInfo ( mod , loadname , false ) ;
2012-07-14 23:17:54 +00:00
# endif
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
return & prv - > cmodels [ 0 ] ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
CM_InlineModel
= = = = = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
static cmodel_t * CM_InlineModel ( model_t * model , char * name )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) model - > meshinfo ;
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 ) ;
2015-02-02 08:01:53 +00:00
if ( num < 1 | | num > = prv - > numcmodels )
2004-08-21 01:25:48 +00:00
Host_Error ( " CM_InlineModel: bad number " ) ;
2015-02-02 08:01:53 +00:00
return & prv - > cmodels [ num ] ;
2004-08-21 01:25:48 +00:00
}
2005-08-26 22:56:51 +00:00
int CM_NumClusters ( model_t * model )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
return model - > numclusters ;
2004-08-21 01:25:48 +00:00
}
2005-08-26 22:56:51 +00:00
int CM_ClusterSize ( model_t * model )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) model - > meshinfo ;
return prv - > q3pvs - > rowsize ? prv - > q3pvs - > rowsize : MAX_MAP_LEAFS / 8 ;
2004-08-21 01:25:48 +00:00
}
2015-02-02 08:01:53 +00:00
static int CM_NumInlineModels ( model_t * model )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) model - > meshinfo ;
return prv - > numcmodels ;
2004-08-21 01:25:48 +00:00
}
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 " ) ;
2014-05-10 13:42:13 +00:00
return model - > leafs [ leafnum ] . contents ;
2004-08-21 01:25:48 +00:00
}
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 " ) ;
2014-05-10 13:42:13 +00:00
return model - > leafs [ leafnum ] . cluster ;
2004-08-21 01:25:48 +00:00
}
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 " ) ;
2014-05-10 13:42:13 +00:00
return model - > leafs [ leafnum ] . area ;
2004-08-21 01:25:48 +00:00
}
//=======================================================================
2015-02-02 08:01:53 +00:00
# define PlaneDiff(point,plane) (((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) - (plane)->dist)
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
mplane_t box_planes [ 6 ] ;
model_t box_model ;
q2cbrush_t box_brush ;
q2cbrushside_t box_sides [ 6 ] ;
static qboolean BM_NativeTrace ( model_t * model , int forcehullnum , int frame , vec3_t axis [ 3 ] , vec3_t start , vec3_t end , vec3_t mins , vec3_t maxs , qboolean capsule , unsigned int contents , trace_t * trace ) ;
static unsigned int BM_NativeContents ( struct model_s * model , int hulloverride , int frame , vec3_t axis [ 3 ] , vec3_t p , vec3_t mins , vec3_t maxs )
{
unsigned int j ;
q2cbrushside_t * brushside = box_sides ;
for ( j = 0 ; j < 6 ; j + + , brushside + + )
{
if ( PlaneDiff ( p , brushside - > plane ) > 0 )
return 0 ;
}
return FTECONTENTS_BODY ;
}
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 ;
mplane_t * p ;
q2cbrushside_t * s ;
2015-02-02 08:01:53 +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
2014-05-23 02:02:51 +00:00
box_model . funcs . ClusterPVS = CM_ClusterPVS ;
box_model . funcs . ClusterForPoint = CM_PointCluster ;
2015-02-02 08:01:53 +00:00
*/
box_model . funcs . NativeContents = BM_NativeContents ;
box_model . funcs . NativeTrace = BM_NativeTrace ;
2014-10-05 20:04:11 +00:00
box_model . loadstate = MLS_LOADED ;
2014-05-10 13:42:13 +00:00
2015-02-02 08:01:53 +00:00
box_brush . contents = FTECONTENTS_BODY ;
box_brush . numsides = 6 ;
box_brush . brushside = box_sides ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < 6 ; i + + )
{
side = i & 1 ;
// brush sides
2015-02-02 08:01:53 +00:00
s = & box_sides [ i ] ;
2014-02-11 17:51:29 +00:00
s - > plane = box_planes + ( i * 2 + side ) ;
2004-08-21 01:25:48 +00:00
s - > surface = & nullsurface ;
// 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
= = = = = = = = = = = = = = = = = =
*/
2014-05-23 02:02:51 +00:00
static 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 ] ;
}
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
{
2014-10-05 20:04:11 +00:00
if ( ! mod | | mod - > loadstate ! = MLS_LOADED )
2004-08-21 01:25:48 +00:00
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
}
2014-05-23 02:02:51 +00:00
static int CM_PointCluster ( model_t * mod , vec3_t p )
{
2014-10-05 20:04:11 +00:00
if ( ! mod | | mod - > loadstate ! = MLS_LOADED )
2014-05-23 02:02:51 +00:00
return 0 ; // sound may call this without map loaded
return CM_LeafCluster ( mod , 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
= = = = = = = = = = = = = = = = = =
*/
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
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
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
2014-10-05 20:04:11 +00:00
if ( mod - > fromgame = = fg_quake2 )
2014-05-10 13:42:13 +00:00
contents = mod - > leafs [ i ] . contents ; //q2 is simple.
2012-07-14 23:17:54 +00:00
else
{
2014-05-10 13:42:13 +00:00
leaf = & mod - > 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 + + )
{
2015-02-02 08:01:53 +00:00
brush = prv - > 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
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) model - > meshinfo ;
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 - - )
{
2014-05-10 13:42:13 +00:00
leaf = & model - > leafs [ leaflist [ k ] ] ;
2014-10-05 20:04:11 +00:00
if ( model - > fromgame ! = fg_quake2 )
{ //q3 is more complex
2006-03-06 01:41:09 +00:00
for ( i = 0 ; i < leaf - > numleafbrushes ; i + + )
{
2015-02-02 08:01:53 +00:00
brush = prv - > leafbrushes [ leaf - > firstleafbrush + i ] ;
2006-03-06 01:41:09 +00:00
// 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 ;
}
}
2014-10-05 20:04:11 +00:00
else //q2 is simple
2006-03-06 01:41:09 +00:00
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
2015-02-02 08:01:53 +00:00
if ( angles [ 0 ] | | angles [ 1 ] | | angles [ 2 ] )
2004-08-21 01:25:48 +00:00
{
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)
2014-05-10 13:42:13 +00:00
static vec3_t trace_start , trace_end ;
static vec3_t trace_mins , trace_maxs ;
static vec3_t trace_extents ;
static vec3_t trace_absmins , trace_absmaxs ;
2014-09-17 03:04:08 +00:00
static vec3_t trace_up ; //capsule points upwards in this direction
static vec3_t trace_capsulesize ; //radius, up, down
2014-05-10 13:42:13 +00:00
static float trace_truefraction ;
static float trace_nearfraction ;
2004-08-21 01:25:48 +00:00
2014-05-10 13:42:13 +00:00
static trace_t trace_trace ;
static int trace_contents ;
2014-09-17 03:04:08 +00:00
static enum
{
shape_isbox ,
shape_iscapsule ,
shape_ispoint
} trace_shape ; // optimized case
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = =
CM_ClipBoxToBrush
= = = = = = = = = = = = = = = =
*/
2014-05-10 13:42:13 +00:00
static void CM_ClipBoxToBrush ( vec3_t mins , vec3_t maxs , vec3_t p1 , vec3_t p2 ,
2004-08-21 01:25:48 +00:00
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 ;
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 ;
2014-09-17 03:04:08 +00:00
switch ( trace_shape )
{
default :
case shape_isbox : // general box case
2004-08-21 01:25:48 +00:00
// 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 ;
2014-09-17 03:04:08 +00:00
break ;
capsuledist ( dist , plane , mins , maxs )
case shape_ispoint : // special point case
2004-08-21 01:25:48 +00:00
dist = plane - > dist ;
2014-09-17 03:04:08 +00:00
break ;
2004-08-21 01:25:48 +00:00
}
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 ;
}
}
}
2014-05-10 13:42:13 +00:00
static void CM_ClipBoxToPlanes ( vec3_t trmins , vec3_t trmaxs , vec3_t p1 , vec3_t p2 , trace_t * trace , vec3_t plmins , vec3_t plmaxs , mplane_t * plane , int numplanes , q2csurface_t * surf )
{
int i , j ;
mplane_t * clipplane ;
float dist ;
float enterfrac , leavefrac ;
vec3_t ofs ;
float d1 , d2 ;
qboolean getout , startout ;
float f ;
// q2cbrushside_t *side, *leadside;
static mplane_t bboxplanes [ 6 ] = //we change the dist, but nothing else
{
2014-08-15 02:20:41 +00:00
{ { 1 , 0 , 0 } } ,
{ { 0 , 1 , 0 } } ,
{ { 0 , 0 , 1 } } ,
{ { - 1 , 0 , 0 } } ,
{ { 0 , - 1 , 0 } } ,
{ { 0 , 0 , - 1 } } ,
2014-05-10 13:42:13 +00:00
} ;
float nearfrac = 0 ;
enterfrac = - 1 ;
leavefrac = 2 ;
clipplane = NULL ;
getout = false ;
startout = false ;
// leadside = NULL;
for ( i = 0 ; i < numplanes ; i + + , plane + + )
{
2014-09-17 03:04:08 +00:00
switch ( trace_shape )
{
default :
case shape_isbox : // general box case
2014-05-10 13:42:13 +00:00
// push the plane out apropriately for mins/maxs
2014-09-17 03:04:08 +00:00
// FIXME: special case for axial
2014-05-10 13:42:13 +00:00
// FIXME: use signbits into 8 way lookup for each mins/maxs
for ( j = 0 ; j < 3 ; j + + )
{
if ( plane - > normal [ j ] < 0 )
ofs [ j ] = trmaxs [ j ] ;
else
ofs [ j ] = trmins [ j ] ;
}
dist = DotProduct ( ofs , plane - > normal ) ;
dist = plane - > dist - dist ;
2014-09-17 03:04:08 +00:00
break ;
capsuledist ( dist , plane , trmins , trmaxs )
case shape_ispoint : // special point case
2014-05-10 13:42:13 +00:00
dist = plane - > dist ;
2014-09-17 03:04:08 +00:00
break ;
2014-05-10 13:42:13 +00:00
}
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
f = ( d1 ) / ( d1 - d2 ) ;
if ( f > enterfrac )
{
enterfrac = f ;
nearfrac = ( d1 - DIST_EPSILON ) / ( d1 - d2 ) ;
clipplane = plane ;
// leadside = side;
}
}
else
{ // leave
f = ( d1 ) / ( d1 - d2 ) ;
if ( f < leavefrac )
leavefrac = f ;
}
}
//bevel the brush axially (to match the player's bbox), in case that wasn't already done
for ( i = 0 , plane = bboxplanes ; i < 6 ; i + + , plane + + )
{
if ( i < 3 )
{ //positive normal
dist = trmins [ i ] ;
plane - > dist = plmaxs [ i ] ;
dist = plane - > dist - dist ;
d1 = p1 [ i ] - dist ;
d2 = p2 [ i ] - dist ;
}
else
{ //negative normal
j = i - 3 ;
dist = - trmaxs [ j ] ;
plane - > dist = - plmins [ j ] ;
dist = plane - > dist - dist ;
d1 = - p1 [ j ] - dist ;
d2 = - p2 [ j ] - 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
f = ( d1 ) / ( d1 - d2 ) ;
if ( f > enterfrac )
{
enterfrac = f ;
nearfrac = ( d1 - DIST_EPSILON ) / ( d1 - d2 ) ;
clipplane = plane ;
// leadside = side;
}
}
else
{ // leave
f = ( d1 ) / ( d1 - d2 ) ;
if ( f < leavefrac )
leavefrac = f ;
}
}
if ( ! startout )
{ // original point was inside brush
trace - > startsolid = true ;
if ( ! getout )
trace - > allsolid = true ;
return ;
}
if ( enterfrac < = leavefrac )
{
if ( enterfrac > - 1 & & enterfrac < = trace_truefraction )
{
if ( enterfrac < 0 )
enterfrac = 0 ;
trace_nearfraction = nearfrac ;
trace_truefraction = enterfrac ;
trace - > plane . dist = clipplane - > dist ;
VectorCopy ( clipplane - > normal , trace - > plane . normal ) ;
trace - > surface = surf ;
trace - > contents = surf - > value ;
}
}
}
static void Mod_Trace_Trisoup_ ( vecV_t * posedata , index_t * indexes , size_t numindexes , vec3_t start , vec3_t end , vec3_t mins , vec3_t maxs , trace_t * trace , q2csurface_t * surf )
{
size_t i ;
int j ;
float * p1 , * p2 , * p3 ;
vec3_t edge1 , edge2 , edge3 ;
mplane_t planes [ 5 ] ;
vec3_t tmins , tmaxs ;
for ( i = 0 ; i < numindexes ; i + = 3 )
{
p1 = posedata [ indexes [ i + 0 ] ] ;
p2 = posedata [ indexes [ i + 1 ] ] ;
p3 = posedata [ indexes [ i + 2 ] ] ;
//determine the triangle extents, and skip the triangle if we're completely out of bounds
for ( j = 0 ; j < 3 ; j + + )
{
tmins [ j ] = p1 [ j ] ;
if ( tmins [ j ] > p2 [ j ] )
tmins [ j ] = p2 [ j ] ;
if ( tmins [ j ] > p3 [ j ] )
tmins [ j ] = p3 [ j ] ;
if ( trace_absmaxs [ j ] + ( 1 / 8.f ) < tmins [ j ] )
break ;
tmaxs [ j ] = p1 [ j ] ;
if ( tmaxs [ j ] < p2 [ j ] )
tmaxs [ j ] = p2 [ j ] ;
if ( tmaxs [ j ] < p3 [ j ] )
tmaxs [ j ] = p3 [ j ] ;
if ( trace_absmins [ j ] - ( 1 / 8.f ) > tmaxs [ j ] )
break ;
}
//skip any triangles which are completely outside the trace bounds
if ( j < 3 )
continue ;
VectorSubtract ( p1 , p2 , edge1 ) ;
VectorSubtract ( p3 , p2 , edge2 ) ;
VectorSubtract ( p1 , p3 , edge3 ) ;
CrossProduct ( edge1 , edge2 , planes [ 0 ] . normal ) ;
VectorNormalize ( planes [ 0 ] . normal ) ;
planes [ 0 ] . dist = DotProduct ( p1 , planes [ 0 ] . normal ) ;
VectorNegate ( planes [ 0 ] . normal , planes [ 1 ] . normal ) ;
planes [ 1 ] . dist = - planes [ 0 ] . dist + 4 ;
//determine edges
//FIXME: use adjacency info
CrossProduct ( edge1 , planes [ 0 ] . normal , planes [ 2 ] . normal ) ;
VectorNormalize ( planes [ 2 ] . normal ) ;
planes [ 2 ] . dist = DotProduct ( p2 , planes [ 2 ] . normal ) ;
CrossProduct ( planes [ 0 ] . normal , edge2 , planes [ 3 ] . normal ) ;
VectorNormalize ( planes [ 3 ] . normal ) ;
planes [ 3 ] . dist = DotProduct ( p3 , planes [ 3 ] . normal ) ;
CrossProduct ( planes [ 0 ] . normal , edge3 , planes [ 4 ] . normal ) ;
VectorNormalize ( planes [ 4 ] . normal ) ;
planes [ 4 ] . dist = DotProduct ( p1 , planes [ 4 ] . normal ) ;
CM_ClipBoxToPlanes ( mins , maxs , start , end , trace , tmins , tmaxs , planes , 5 , surf ) ;
}
}
static void CM_ClipBoxToMesh ( vec3_t mins , vec3_t maxs , vec3_t p1 , vec3_t p2 , trace_t * trace , mesh_t * mesh )
{
trace_truefraction = trace - > truefraction ;
trace_nearfraction = trace - > fraction ;
Mod_Trace_Trisoup_ ( mesh - > xyz_array , mesh - > indexes , mesh - > numindexes , p1 , p2 , mins , maxs , trace , & nullsurface . c ) ;
trace - > truefraction = trace_truefraction ;
trace - > fraction = trace_nearfraction ;
}
static void CM_ClipBoxToPatch ( vec3_t mins , vec3_t maxs , vec3_t p1 , vec3_t p2 ,
2004-08-21 01:25:48 +00:00
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 ;
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 ;
2014-09-17 03:04:08 +00:00
// push the plane out apropriately for mins/maxs
switch ( trace_shape )
{
default :
case shape_isbox : // general box case
2004-08-21 01:25:48 +00:00
// 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 ;
2014-09-17 03:04:08 +00:00
break ;
capsuledist ( dist , plane , mins , maxs )
case shape_ispoint : // special point case
2004-08-21 01:25:48 +00:00
dist = plane - > dist ;
2014-09-17 03:04:08 +00:00
break ;
2004-08-21 01:25:48 +00:00
}
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
= = = = = = = = = = = = = = = =
*/
2014-05-10 13:42:13 +00:00
static void CM_TestBoxInBrush ( vec3_t mins , vec3_t maxs , vec3_t p1 ,
2004-08-21 01:25:48 +00:00
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 ;
2014-09-17 03:04:08 +00:00
switch ( trace_shape )
{
default :
case shape_isbox : // general box case
2004-08-21 01:25:48 +00:00
2014-09-17 03:04:08 +00:00
// push the plane out apropriately for mins/maxs
2004-08-21 01:25:48 +00:00
2014-09-17 03:04:08 +00:00
// 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 ;
break ;
capsuledist ( dist , plane , mins , maxs )
case shape_ispoint :
dist = plane - > dist ;
break ;
2004-08-21 01:25:48 +00:00
}
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
}
2014-05-10 13:42:13 +00:00
static void CM_TestBoxInPatch ( vec3_t mins , vec3_t maxs , vec3_t p1 ,
2004-08-21 01:25:48 +00:00
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 ;
2014-09-17 03:04:08 +00:00
switch ( trace_shape )
{
default :
case shape_isbox :
// general box case
2004-08-21 01:25:48 +00:00
2014-09-17 03:04:08 +00:00
// push the plane out apropriately for mins/maxs
2004-08-21 01:25:48 +00:00
2014-09-17 03:04:08 +00:00
// 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 ] ;
}
2004-08-21 01:25:48 +00:00
2014-09-17 03:04:08 +00:00
dist = DotProduct ( ofs , plane - > normal ) ;
dist = plane - > dist - dist ;
break ;
capsuledist ( dist , plane , mins , maxs )
case shape_ispoint :
dist = plane - > dist ;
break ;
}
2004-08-21 01:25:48 +00:00
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
= = = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
static void CM_TraceToLeaf ( cminfo_t * prv , mleaf_t * leaf )
2004-08-21 01:25:48 +00:00
{
int k , j ;
q2cbrush_t * b ;
int patchnum ;
q3cpatch_t * patch ;
2014-05-10 13:42:13 +00:00
q3cmesh_t * cmesh ;
2004-08-21 01:25:48 +00:00
if ( ! ( leaf - > contents & trace_contents ) )
return ;
// trace line against all brushes in the leaf
for ( k = 0 ; k < leaf - > numleafbrushes ; k + + )
{
2015-02-02 08:01:53 +00:00
b = prv - > leafbrushes [ leaf - > firstleafbrush + k ] ;
2004-08-21 01:25:48 +00:00
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 ;
}
2015-02-02 08:01:53 +00:00
if ( ! prv - > mapisq3 | | map_noCurves . value )
2004-08-21 01:25:48 +00:00
return ;
// trace line against all patches in the leaf
for ( k = 0 ; k < leaf - > numleafpatches ; k + + )
{
2015-02-02 08:01:53 +00:00
patchnum = prv - > leafpatches [ leaf - > firstleafpatch + k ] ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
patch = & prv - > patches [ patchnum ] ;
2004-08-21 01:25:48 +00:00
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 ;
}
}
2014-05-10 13:42:13 +00:00
for ( k = 0 ; k < leaf - > numleafcmeshes ; k + + )
{
2015-02-02 08:01:53 +00:00
patchnum = prv - > leafcmeshes [ leaf - > firstleafcmesh + k ] ;
cmesh = & prv - > cmeshes [ patchnum ] ;
2014-05-10 13:42:13 +00:00
if ( cmesh - > checkcount = = checkcount )
continue ; // already checked this patch in another leaf
cmesh - > checkcount = checkcount ;
if ( ! ( cmesh - > surface - > c . value & trace_contents ) )
continue ;
if ( ! BoundsIntersect ( cmesh - > absmins , cmesh - > absmaxs , trace_absmins , trace_absmaxs ) )
continue ;
Mod_Trace_Trisoup_ ( cmesh - > xyz_array , cmesh - > indicies , cmesh - > numincidies , trace_start , trace_end , trace_mins , trace_maxs , & trace_trace , & cmesh - > surface - > c ) ;
if ( trace_nearfraction < = 0 )
return ;
}
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = =
CM_TestInLeaf
= = = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
static void CM_TestInLeaf ( cminfo_t * prv , mleaf_t * leaf )
2004-08-21 01:25:48 +00:00
{
int k , j ;
int patchnum ;
q2cbrush_t * b ;
2014-05-10 13:42:13 +00:00
q3cmesh_t * cmesh ;
2004-08-21 01:25:48 +00:00
q3cpatch_t * patch ;
if ( ! ( leaf - > contents & trace_contents ) )
return ;
// trace line against all brushes in the leaf
for ( k = 0 ; k < leaf - > numleafbrushes ; k + + )
{
2015-02-02 08:01:53 +00:00
b = prv - > leafbrushes [ leaf - > firstleafbrush + k ] ;
2004-08-21 01:25:48 +00:00
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 ;
}
2015-02-02 08:01:53 +00:00
if ( ! prv - > mapisq3 | | map_noCurves . value )
2004-08-21 01:25:48 +00:00
return ;
// trace line against all patches in the leaf
for ( k = 0 ; k < leaf - > numleafpatches ; k + + )
{
2015-02-02 08:01:53 +00:00
patchnum = prv - > leafpatches [ leaf - > firstleafpatch + k ] ;
2004-08-21 01:25:48 +00:00
2015-02-02 08:01:53 +00:00
patch = & prv - > patches [ patchnum ] ;
2004-08-21 01:25:48 +00:00
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 ;
}
}
2014-05-10 13:42:13 +00:00
for ( k = 0 ; k < leaf - > numleafcmeshes ; k + + )
{
2015-02-02 08:01:53 +00:00
patchnum = prv - > leafcmeshes [ leaf - > firstleafcmesh + k ] ;
cmesh = & prv - > cmeshes [ patchnum ] ;
2014-05-10 13:42:13 +00:00
if ( cmesh - > checkcount = = checkcount )
continue ; // already checked this patch in another leaf
cmesh - > checkcount = checkcount ;
if ( ! ( cmesh - > surface - > c . value & trace_contents ) )
continue ;
if ( ! BoundsIntersect ( cmesh - > absmins , cmesh - > absmaxs , trace_absmins , trace_absmaxs ) )
continue ;
Mod_Trace_Trisoup_ ( cmesh - > xyz_array , cmesh - > indicies , cmesh - > numincidies , trace_start , trace_end , trace_mins , trace_maxs , & trace_trace , & cmesh - > surface - > c ) ;
if ( trace_nearfraction < = 0 )
return ;
}
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
CM_RecursiveHullCheck
= = = = = = = = = = = = = = = = = =
*/
2014-05-10 13:42:13 +00:00
static 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 )
{
2015-02-02 08:01:53 +00:00
CM_TraceToLeaf ( mod - > meshinfo , & mod - > leafs [ - 1 - num ] ) ;
2004-08-21 01:25:48 +00:00
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 ;
2014-09-17 03:04:08 +00:00
if ( trace_shape = = shape_ispoint )
2004-08-21 01:25:48 +00:00
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
= = = = = = = = = = = = = = = = = =
*/
2014-05-10 13:42:13 +00:00
static trace_t CM_BoxTrace ( model_t * mod , vec3_t start , vec3_t end ,
2014-09-17 03:04:08 +00:00
vec3_t mins , vec3_t maxs , qboolean capsule ,
2005-08-26 22:56:51 +00:00
int brushmask )
2004-08-21 01:25:48 +00:00
{
int i ;
vec3_t point ;
checkcount + + ; // for multi-check avoidance
// 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 ;
2014-05-10 13:42:13 +00:00
trace_trace . truefraction = 1 ;
2004-08-21 01:25:48 +00:00
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 ) ;
2014-09-17 03:04:08 +00:00
//determine the type of trace that we're going to use, and the max extents
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_shape = shape_ispoint ;
VectorSet ( trace_extents , 1 / 32.0 , 1 / 32.0 , 1 / 32.0 ) ;
//acedemic
AddPointToBounds ( start , trace_absmins , trace_absmaxs ) ;
AddPointToBounds ( end , trace_absmins , trace_absmaxs ) ;
}
else if ( capsule )
{
float ext ;
trace_shape = shape_iscapsule ;
//determine the capsule sizes
trace_capsulesize [ 0 ] = ( ( maxs [ 0 ] - mins [ 0 ] ) + ( maxs [ 1 ] - mins [ 1 ] ) ) / 4.0 ;
trace_capsulesize [ 1 ] = maxs [ 2 ] ;
trace_capsulesize [ 2 ] = mins [ 2 ] ;
ext = ( trace_capsulesize [ 1 ] > - trace_capsulesize [ 2 ] ) ? trace_capsulesize [ 1 ] : - trace_capsulesize [ 2 ] ;
trace_capsulesize [ 1 ] - = trace_capsulesize [ 0 ] ;
trace_capsulesize [ 2 ] + = trace_capsulesize [ 0 ] ;
trace_extents [ 0 ] = ext + 1 ;
trace_extents [ 1 ] = ext + 1 ;
trace_extents [ 2 ] = ext + 1 ;
//determine the total range
VectorSubtract ( start , trace_extents , point ) ;
AddPointToBounds ( point , trace_absmins , trace_absmaxs ) ;
VectorAdd ( start , trace_extents , point ) ;
AddPointToBounds ( point , trace_absmins , trace_absmaxs ) ;
VectorSubtract ( end , trace_extents , point ) ;
AddPointToBounds ( point , trace_absmins , trace_absmaxs ) ;
VectorAdd ( end , trace_extents , point ) ;
AddPointToBounds ( point , trace_absmins , trace_absmaxs ) ;
}
else
{
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 ) ;
trace_shape = shape_isbox ;
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 ;
}
#if 0
2014-05-10 13:42:13 +00:00
if ( 0 )
{ //treat *ALL* tests against the actual geometry instead of using any brushes.
//also ignores the bsp etc. not fast. testing only.
2014-06-24 03:02:32 +00:00
trace_ispoint = trace_mins [ 0 ] = = 0 & & trace_mins [ 1 ] = = 0 & & trace_mins [ 2 ] = = 0
2014-09-17 03:04:08 +00:00
& & trace_maxs [ 0 ] = = 0 & & trace_maxs [ 1 ] = = 0 & & trace_maxs [ 2 ] = = 0 ;
2014-06-24 03:02:32 +00:00
2014-05-10 13:42:13 +00:00
for ( i = 0 ; i < mod - > numsurfaces ; i + + )
{
CM_ClipBoxToMesh ( trace_mins , trace_maxs , trace_start , trace_end , & trace_trace , mod - > surfaces [ i ] . mesh ) ;
}
}
else
if ( 0 )
{
2014-09-17 03:04:08 +00:00
trace_ispoint = trace_mins [ 0 ] = = 0 & & trace_mins [ 1 ] = = 0 & & trace_mins [ 2 ] = = 0
& & trace_maxs [ 0 ] = = 0 & & trace_maxs [ 1 ] = = 0 & & trace_maxs [ 2 ] = = 0 ;
2014-06-24 03:02:32 +00:00
2014-05-10 13:42:13 +00:00
for ( i = 0 ; i < mod - > numleafs ; i + + )
CM_TraceToLeaf ( & mod - > leafs [ i ] ) ;
}
else
2014-09-17 03:04:08 +00:00
# endif
2004-08-21 01:25:48 +00:00
//
// 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 ;
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 + + )
{
2015-02-02 08:01:53 +00:00
CM_TestInLeaf ( mod - > meshinfo , & mod - > leafs [ leafs [ i ] ] ) ;
2004-08-21 01:25:48 +00:00
if ( trace_trace . allsolid )
break ;
}
VectorCopy ( start , trace_trace . endpos ) ;
return trace_trace ;
}
//
2014-05-10 13:42:13 +00:00
// general aabb trace
//
2004-08-21 01:25:48 +00:00
else
{
2014-05-10 13:42:13 +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 ] ) ;
}
return trace_trace ;
}
2015-02-02 08:01:53 +00:00
static qboolean BM_NativeTrace ( model_t * model , int forcehullnum , int frame , vec3_t axis [ 3 ] , vec3_t start , vec3_t end , vec3_t mins , vec3_t maxs , qboolean capsule , unsigned int contents , trace_t * trace )
{
int i ;
memset ( trace , 0 , sizeof ( * trace ) ) ;
trace_truefraction = 1 ;
trace_nearfraction = 1 ;
trace - > fraction = 1 ;
trace - > truefraction = 1 ;
trace - > surface = & ( nullsurface . c ) ;
if ( contents & FTECONTENTS_BODY )
{
2015-02-09 03:37:41 +00:00
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_shape = shape_ispoint ;
else if ( capsule )
trace_shape = shape_iscapsule ;
else
trace_shape = shape_isbox ;
2015-02-02 08:01:53 +00:00
trace_contents = contents ;
VectorCopy ( start , trace_start ) ;
VectorCopy ( end , trace_end ) ;
VectorCopy ( mins , trace_mins ) ;
VectorCopy ( maxs , trace_maxs ) ;
CM_ClipBoxToBrush ( trace_mins , trace_maxs , trace_start , trace_end , trace , & box_brush ) ;
}
if ( trace_nearfraction = = 1 )
{
2015-02-09 03:37:41 +00:00
trace - > fraction = 1 ;
VectorCopy ( trace_end , trace - > endpos ) ;
2015-02-02 08:01:53 +00:00
}
else
{
if ( trace_nearfraction < 0 )
trace_nearfraction = 0 ;
2015-02-09 03:37:41 +00:00
trace - > fraction = trace_nearfraction ;
trace - > truefraction = trace_truefraction ;
2015-02-02 08:01:53 +00:00
for ( i = 0 ; i < 3 ; i + + )
2015-02-09 03:37:41 +00:00
trace - > endpos [ i ] = trace_start [ i ] + trace - > fraction * ( trace_end [ i ] - trace_start [ i ] ) ;
2015-02-02 08:01:53 +00:00
}
return trace - > fraction ! = 1 ;
}
2014-09-17 03:04:08 +00:00
static 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 , qboolean capsule , 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 ] ) ;
2014-09-17 03:04:08 +00:00
VectorSet ( trace_up , axis [ 0 ] [ 2 ] , - axis [ 1 ] [ 2 ] , axis [ 2 ] [ 2 ] ) ;
* trace = CM_BoxTrace ( model , start_l , end_l , mins , maxs , capsule , 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 ;
2014-09-17 03:04:08 +00:00
Heightmap_Trace ( model , forcehullnum , frame , NULL , start , end , mins , maxs , capsule , contents , & hmt ) ;
2012-07-23 02:34:20 +00:00
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
{
2014-09-17 03:04:08 +00:00
VectorSet ( trace_up , 0 , 0 , 1 ) ;
* trace = CM_BoxTrace ( model , start , end , mins , maxs , capsule , contents ) ;
2012-07-23 02:34:20 +00:00
# ifdef TERRAIN
if ( model - > terrain )
{
trace_t hmt ;
2014-09-17 03:04:08 +00:00
Heightmap_Trace ( model , forcehullnum , frame , NULL , start , end , mins , maxs , capsule , contents , & hmt ) ;
2012-07-23 02:34:20 +00:00
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 ;
2014-09-17 03:04:08 +00:00
qboolean capsule = false ;
2004-08-21 01:25:48 +00:00
// 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 ) ;
2014-09-17 03:04:08 +00:00
VectorSet ( trace_up , forward [ 2 ] , - right [ 2 ] , up [ 2 ] ) ;
}
else
{
VectorSet ( trace_up , 0 , 0 , 1 ) ;
2004-08-21 01:25:48 +00:00
}
// sweep the box through the model
2014-09-17 03:04:08 +00:00
trace = CM_BoxTrace ( mod , start_l , end_l , mins , maxs , capsule , 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 ) ;
}
*/
2015-02-02 08:01:53 +00:00
static void CM_DecompressVis ( model_t * mod , qbyte * in , qbyte * out )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
int c ;
qbyte * out_p ;
int row ;
2015-02-02 08:01:53 +00:00
row = ( mod - > numclusters + 7 ) > > 3 ;
2004-08-21 01:25:48 +00:00
out_p = out ;
2015-02-02 08:01:53 +00:00
if ( ! in | | ! prv - > numvisibility )
2004-08-21 01:25:48 +00:00
{ // 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 ) ;
}
2013-10-08 14:28:11 +00:00
static qbyte pvsrow [ MAX_MAP_LEAFS / 8 ] ;
static 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
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
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 ) ;
}
2015-02-02 08:01:53 +00:00
if ( buffersize < ( mod - > numclusters + 7 ) > > 3 )
2009-06-21 17:45:33 +00:00
Sys_Error ( " CM_ClusterPVS with too small a buffer \n " ) ;
2004-08-21 01:25:48 +00:00
2014-10-05 20:04:11 +00:00
if ( mod - > fromgame ! = fg_quake2 )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
if ( cluster ! = - 1 & & prv - > q3pvs - > numclusters )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
return ( qbyte * ) prv - > q3pvs - > data + cluster * prv - > q3pvs - > rowsize ;
2004-08-21 01:25:48 +00:00
}
else
{
2015-02-02 08:01:53 +00:00
memset ( buffer , 0 , ( mod - > numclusters + 7 ) > > 3 ) ;
2004-08-21 01:25:48 +00:00
return buffer ;
}
}
if ( cluster = = - 1 )
2015-02-02 08:01:53 +00:00
memset ( buffer , 0 , ( mod - > numclusters + 7 ) > > 3 ) ;
2004-08-21 01:25:48 +00:00
else
2015-02-02 08:01:53 +00:00
CM_DecompressVis ( mod , ( ( qbyte * ) prv - > q2vis ) + prv - > 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
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2014-10-05 20:04:11 +00:00
if ( mod - > fromgame ! = fg_quake2 )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
if ( cluster ! = - 1 & & prv - > q3phs - > numclusters )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
return ( qbyte * ) prv - > q3phs - > data + cluster * prv - > q3phs - > rowsize ;
2004-08-21 01:25:48 +00:00
}
else
{
2015-02-02 08:01:53 +00:00
memset ( phsrow , 0 , ( mod - > numclusters + 7 ) > > 3 ) ;
2004-08-21 01:25:48 +00:00
return phsrow ;
}
}
if ( cluster = = - 1 )
2015-02-02 08:01:53 +00:00
memset ( phsrow , 0 , ( mod - > numclusters + 7 ) > > 3 ) ;
2004-08-21 01:25:48 +00:00
else
2015-02-02 08:01:53 +00:00
CM_DecompressVis ( mod , ( ( qbyte * ) prv - > q2vis ) + prv - > q2vis - > bitofs [ cluster ] [ DVIS_PHS ] , phsrow ) ;
2004-08-21 01:25:48 +00:00
return phsrow ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
AREAPORTALS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
static void FloodArea_r ( cminfo_t * prv , q2carea_t * area , int floodnum )
2004-08-21 01:25:48 +00:00
{
int i ;
2015-02-02 08:01:53 +00:00
if ( area - > floodvalid = = prv - > floodvalid )
2004-08-21 01:25:48 +00:00
{
if ( area - > floodnum = = floodnum )
return ;
2015-03-03 00:14:43 +00:00
Con_Printf ( " FloodArea_r: reflooded \n " ) ;
return ;
2004-08-21 01:25:48 +00:00
}
area - > floodnum = floodnum ;
2015-02-02 08:01:53 +00:00
area - > floodvalid = prv - > floodvalid ;
if ( prv - > mapisq3 )
2014-06-02 16:50:40 +00:00
{
2015-02-02 08:01:53 +00:00
for ( i = 0 ; i < prv - > numareas ; i + + )
2014-06-02 16:50:40 +00:00
{
2015-02-02 08:01:53 +00:00
if ( prv - > q3areas [ area - prv - > q2areas ] . numareaportals [ i ] > 0 )
FloodArea_r ( prv , & prv - > q2areas [ i ] , floodnum ) ;
2014-06-02 16:50:40 +00:00
}
}
else
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
q2dareaportal_t * p = & prv - > areaportals [ area - > firstareaportal ] ;
2014-06-02 16:50:40 +00:00
for ( i = 0 ; i < area - > numareaportals ; i + + , p + + )
{
2015-02-02 08:01:53 +00:00
if ( prv - > portalopen [ p - > portalnum ] )
FloodArea_r ( prv , & prv - > q2areas [ p - > otherarea ] , floodnum ) ;
2014-06-02 16:50:40 +00:00
}
2004-08-21 01:25:48 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = =
FloodAreaConnections
= = = = = = = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
static void FloodAreaConnections ( cminfo_t * prv )
2004-08-21 01:25:48 +00:00
{
2014-06-02 16:50:40 +00:00
int i ;
2004-08-21 01:25:48 +00:00
q2carea_t * area ;
int floodnum ;
// all current floods are now invalid
2015-02-02 08:01:53 +00:00
prv - > floodvalid + + ;
2004-08-21 01:25:48 +00:00
floodnum = 0 ;
// area 0 is not used
2015-02-02 08:01:53 +00:00
for ( i = 0 ; i < prv - > numareas ; i + + )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
area = & prv - > q2areas [ i ] ;
if ( area - > floodvalid = = prv - > floodvalid )
2004-08-21 01:25:48 +00:00
continue ; // already flooded into
floodnum + + ;
2015-02-02 08:01:53 +00:00
FloodArea_r ( prv , area , floodnum ) ;
2004-08-21 01:25:48 +00:00
}
}
2015-02-02 08:01:53 +00:00
void CMQ2_SetAreaPortalState ( model_t * mod , unsigned int portalnum , qboolean open )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv ;
if ( ! mod )
return ;
prv = ( cminfo_t * ) mod - > meshinfo ;
if ( prv - > mapisq3 )
2014-05-30 18:04:51 +00:00
return ;
2015-02-02 08:01:53 +00:00
if ( portalnum > prv - > numareaportals )
2004-08-21 01:25:48 +00:00
Host_Error ( " areaportal > numareaportals " ) ;
2015-02-02 08:01:53 +00:00
if ( prv - > portalopen [ portalnum ] = = open )
2004-09-14 21:44:40 +00:00
return ;
2015-02-02 08:01:53 +00:00
prv - > portalopen [ portalnum ] = open ;
FloodAreaConnections ( prv ) ;
2004-08-21 01:25:48 +00:00
2004-09-14 21:44:40 +00:00
return ;
2004-08-21 01:25:48 +00:00
}
2015-02-02 08:01:53 +00:00
void CMQ3_SetAreaPortalState ( model_t * mod , unsigned int area1 , unsigned int area2 , qboolean open )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
if ( ! prv - > 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
2015-02-02 08:01:53 +00:00
if ( area1 > = prv - > numareas | | area2 > = prv - > numareas )
2004-08-21 01:25:48 +00:00
Host_Error ( " CMQ3_SetAreaPortalState: area > numareas " ) ;
if ( open )
{
2015-02-02 08:01:53 +00:00
prv - > q3areas [ area1 ] . numareaportals [ area2 ] + + ;
prv - > q3areas [ area2 ] . numareaportals [ area1 ] + + ;
2004-08-21 01:25:48 +00:00
}
else
{
2015-02-02 08:01:53 +00:00
prv - > q3areas [ area1 ] . numareaportals [ area2 ] - - ;
prv - > q3areas [ area2 ] . numareaportals [ area1 ] - - ;
2004-08-21 01:25:48 +00:00
}
2014-06-02 16:50:40 +00:00
2015-02-02 08:01:53 +00:00
FloodAreaConnections ( prv ) ;
2004-08-21 01:25:48 +00:00
}
2014-06-02 16:50:40 +00:00
qboolean VARGS CM_AreasConnected ( model_t * mod , unsigned int area1 , unsigned int area2 )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
if ( map_noareas . value )
return true ;
2014-06-12 23:08:42 +00:00
if ( area1 = = ~ 0 | | area2 = = ~ 0 )
return area1 = = area2 ;
2015-02-02 08:01:53 +00:00
if ( area1 > prv - > numareas | | area2 > prv - > numareas )
2004-08-21 01:25:48 +00:00
Host_Error ( " area > numareas " ) ;
2015-02-02 08:01:53 +00:00
if ( prv - > q2areas [ area1 ] . floodnum = = prv - > q2areas [ area2 ] . floodnum )
2014-06-02 16:50:40 +00:00
return true ;
2004-08-21 01:25:48 +00:00
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
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2004-08-21 01:25:48 +00:00
int i ;
int floodnum ;
int bytes ;
2015-02-02 08:01:53 +00:00
bytes = ( prv - > numareas + 7 ) > > 3 ;
2004-08-21 01:25:48 +00:00
if ( map_noareas . value )
{ // for debugging, send everything
memset ( buffer , 255 , bytes ) ;
}
else
{
memset ( buffer , 0 , bytes ) ;
2015-02-02 08:01:53 +00:00
floodnum = prv - > q2areas [ area ] . floodnum ;
for ( i = 0 ; i < prv - > numareas ; i + + )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
if ( prv - > q2areas [ i ] . floodnum = = floodnum | | ! area )
2014-06-02 16:50:40 +00:00
buffer [ i > > 3 ] | = 1 < < ( i & 7 ) ;
2004-08-21 01:25:48 +00:00
}
}
return bytes ;
}
/*
= = = = = = = = = = = = = = = = = = =
CM_WritePortalState
Writes the portal state to a savegame file
= = = = = = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
void CM_WritePortalState ( model_t * mod , vfsfile_t * f )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
VFS_WRITE ( f , prv - > portalopen , sizeof ( prv - > portalopen ) ) ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
CM_ReadPortalState
Reads the portal state from a savegame file
and recalculates the area connections
= = = = = = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
void CM_ReadPortalState ( model_t * mod , vfsfile_t * f )
2004-08-21 01:25:48 +00:00
{
2015-02-02 08:01:53 +00:00
cminfo_t * prv = ( cminfo_t * ) mod - > meshinfo ;
2011-05-15 13:23:13 +00:00
size_t result ;
2015-02-02 08:01:53 +00:00
result = VFS_READ ( f , prv - > portalopen , sizeof ( prv - > portalopen ) ) ; // do something with result
2011-05-30 04:32:04 +00:00
2015-02-02 08:01:53 +00:00
if ( result ! = sizeof ( prv - > portalopen ) )
Con_Printf ( " CM_ReadPortalState() fread: expected %u, result was %u \n " , ( unsigned int ) sizeof ( prv - > portalopen ) , ( unsigned int ) result ) ;
2011-05-30 04:32:04 +00:00
2015-02-02 08:01:53 +00:00
FloodAreaConnections ( prv ) ;
2004-08-21 01:25:48 +00:00
}
/*
= = = = = = = = = = = = =
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 ;
2014-05-10 13:42:13 +00:00
cluster = mod - > leafs [ leafnum ] . cluster ;
2004-08-21 01:25:48 +00:00
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
}
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 ;
2014-10-05 20:04:11 +00:00
qboolean QDECL Mod_LoadQ2BrushModel ( model_t * mod , void * buffer , size_t fsize )
2004-08-21 01:25:48 +00:00
{
mod - > fromgame = fg_quake2 ;
2014-10-05 20:04:11 +00:00
return CM_LoadMap ( mod , buffer , fsize , 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 ) ;
2014-05-10 13:42:13 +00:00
Cvar_Register ( & q3bsp_surf_meshcollision_flag , MAPOPTIONS ) ;
Cvar_Register ( & q3bsp_surf_meshcollision_force , MAPOPTIONS ) ;
2005-05-17 02:36:54 +00:00
Cvar_Register ( & r_subdivisions , MAPOPTIONS ) ;
2004-08-21 01:25:48 +00:00
}
2014-03-30 08:55:06 +00:00
void CM_Shutdown ( void )
{
}
2004-08-21 01:25:48 +00:00
# endif