Compare commits

..

16 Commits

Author SHA1 Message Date
Alibek Omarov
98ff33d9e2 engine: mod_bmodel: rewrite .lit file loader using normal stream io functions 2025-01-09 08:02:39 +03:00
Alibek Omarov
baa8fbaaec engine: mod_bmodel: fix misleading debug message telling about monochrome lighting when .lit file is used 2025-01-09 08:02:39 +03:00
Alibek Omarov
a0b46da04b engine: consolidate all box clipnodes used in studio models, pmove and server in a single place 2025-01-09 08:02:39 +03:00
Alibek Omarov
e70ba7ad64 engine: now, remove SUPPORT_BSP2_FORMAT macro, only prevent ref_soft from loading such maps 2025-01-09 08:02:39 +03:00
Alibek Omarov
8a41be9d47 engine: server: finally, make a union for large leaf indices in edict_t so we can run bsp2 maps without recompiling 2025-01-09 08:02:39 +03:00
Alibek Omarov
47aff9e30b engine: hack mnode_t struct so we can have 24-bit face and children indices to support BSP2 format in runtime 2025-01-09 08:02:39 +03:00
Alibek Omarov
ced8744ac9 engine: split edge struct into two with 16-bit indicies and 32-bit indicies to support BSP2 format in runtime 2025-01-08 14:46:07 +03:00
Alibek Omarov
734c07ddab engine: split clipnodes struct into two with 16-bit indicies and 32-bit indicies to support BSP2 format in runtime 2025-01-08 14:46:07 +03:00
Alibek Omarov
ceb603488a engine: platform: sdl: set up our custom log output function to catch all SDL errors in engine log file 2025-01-08 10:10:45 +03:00
Alibek Omarov
80bac157eb Update SDL to 2.30.11, use GitHub links for SDL, as it might be faster on Actions virtual machines 2025-01-08 09:42:53 +03:00
Alibek Omarov
b45581c630 Documentation: gameinfo: add a note about liblist.gam and gameinfo.txt changes 2025-01-08 01:22:23 +03:00
Alibek Omarov
d4fe3d6f8a filesystem: wscript: check d_type field in struct dirent, as this is an extension and some supported ports (like psvita) don't have it 2025-01-08 01:22:23 +03:00
Alibek Omarov
1907485895 filesystem: re-enable folder check for array returned by listdirectory with dirs_only set to true
According to glibc manual, not all filesystems support it and some might return DT_UNKNOWN.
2025-01-08 01:22:23 +03:00
Alibek Omarov
cfebb3e1d6 filesystem: massively rework how scanning game directories work
* No more conversion from liblist.gam to gameinfo.txt. We are using liblist.gam directly now.
  gameinfo.txt being native format to Xash3D not only remains, it takes priority over liblist.gam.
* Quake game directories now don't receive autogenerated gameinfo.txt.
* Empty directories don't get gameinfo.txt either, finally making it easier to support HD addon folders.
* If user still wishes to generate gameinfo.txt, there is now command fs_make_gameinfo that creates
  gameinfo.txt for currently running game.
* No more creating empty folders for RoDir. They are now created on demand.
2025-01-08 01:22:23 +03:00
Alibek Omarov
f9a0057c28 wscript: fix bsp2 build bruh 2025-01-08 01:22:23 +03:00
Alibek Omarov
ceb2b0c5e4 filesystem: add utility function FS_CheckForQuakePak that parses Quake PAK file and looks for specific files in it's root
Used to properly detect Quake game dirs.
2025-01-08 01:22:23 +03:00
34 changed files with 839 additions and 434 deletions

View File

@@ -66,7 +66,7 @@ jobs:
targetos: apple targetos: apple
targetarch: amd64 targetarch: amd64
env: env:
SDL_VERSION: 2.30.10 SDL_VERSION: 2.30.11
GH_CPU_ARCH: ${{ matrix.targetarch }} GH_CPU_ARCH: ${{ matrix.targetarch }}
GH_CROSSCOMPILING: ${{ matrix.cross }} GH_CROSSCOMPILING: ${{ matrix.cross }}
steps: steps:

View File

@@ -16,8 +16,6 @@ GNU General Public License for more details.
#ifndef BSPFILE_H #ifndef BSPFILE_H
#define BSPFILE_H #define BSPFILE_H
//#define SUPPORT_BSP2_FORMAT // allow to loading Darkplaces BSP2 maps (with broke binary compatibility)
/* /*
============================================================================== ==============================================================================
@@ -65,7 +63,6 @@ BRUSH MODELS
#define MAX_MAP_CLIPNODES_BSP2 524288 #define MAX_MAP_CLIPNODES_BSP2 524288
// these limis not using by modelloader but only for displaying 'mapstats' correctly // these limis not using by modelloader but only for displaying 'mapstats' correctly
#ifdef SUPPORT_BSP2_FORMAT
#define MAX_MAP_MODELS 2048 // embedded models #define MAX_MAP_MODELS 2048 // embedded models
#define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough #define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough
#define MAX_MAP_PLANES 131072 // can be increased without problems #define MAX_MAP_PLANES 131072 // can be increased without problems
@@ -75,18 +72,6 @@ BRUSH MODELS
#define MAX_MAP_VERTS 524288 // can be increased without problems #define MAX_MAP_VERTS 524288 // can be increased without problems
#define MAX_MAP_FACES 262144 // can be increased without problems #define MAX_MAP_FACES 262144 // can be increased without problems
#define MAX_MAP_MARKSURFACES 524288 // can be increased without problems #define MAX_MAP_MARKSURFACES 524288 // can be increased without problems
#else
// increased to match PrimeXT compilers
#define MAX_MAP_MODELS 1024 // embedded models
#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough
#define MAX_MAP_PLANES 65536 // can be increased without problems
#define MAX_MAP_NODES 32767 // because negative shorts are leafs
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_HLBSP // because negative shorts are contents
#define MAX_MAP_LEAFS 32767 // signed short limit
#define MAX_MAP_VERTS 65535 // unsigned short limit
#define MAX_MAP_FACES 65535 // unsigned short limit
#define MAX_MAP_MARKSURFACES 65535 // unsigned short limit
#endif
#define MAX_MAP_ENTITIES 8192 // network limit #define MAX_MAP_ENTITIES 8192 // network limit
#define MAX_MAP_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo #define MAX_MAP_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo

View File

@@ -60,26 +60,29 @@ typedef struct
vec3_t position; vec3_t position;
} mvertex_t; } mvertex_t;
typedef struct typedef struct mclipnode32_s
{ {
int planenum; int planenum;
#ifdef SUPPORT_BSP2_FORMAT int children[2]; // negative numbers are contents
int children[2]; // negative numbers are contents } mclipnode32_t;
#else
short children[2]; // negative numbers are contents typedef struct mclipnode16_s
#endif {
} mclipnode_t; int planenum;
short children[2]; // negative numbers are contents
} mclipnode16_t;
// size is matched but representation is not // size is matched but representation is not
typedef struct typedef struct medge32_s
{ {
#ifdef SUPPORT_BSP2_FORMAT
unsigned int v[2]; unsigned int v[2];
#else } medge32_t;
typedef struct medge16_s
{
unsigned short v[2]; unsigned short v[2];
unsigned int cachededgeoffset; unsigned int cachededgeoffset;
#endif } medge16_t;
} medge_t;
typedef struct texture_s typedef struct texture_s
{ {
@@ -156,13 +159,31 @@ typedef struct mnode_s
// node specific // node specific
mplane_t *plane; mplane_t *plane;
struct mnode_s *children[2];
#ifdef SUPPORT_BSP2_FORMAT #if !XASH_64BIT
int firstsurface; union
int numsurfaces; {
struct mnode_s *children_[2];
struct
{
// the ordering is important
int child_0_leaf : 1;
int child_0_off : 23;
int firstsurface_1 : 8;
int child_1_leaf : 1;
int child_1_off : 23;
int numsurfaces_1 : 8;
};
};
unsigned short firstsurface_0;
unsigned short numsurfaces_0;
#else #else
unsigned short firstsurface; // in 64-bit ABI this struct has 4 more bytes of padding, let's use it!
unsigned short numsurfaces; struct mnode_s *children_[2];
unsigned short firstsurface_0;
unsigned short numsurfaces_0;
unsigned short firstsurface_1;
unsigned short numsurfaces_1;
#endif #endif
} mnode_t; } mnode_t;
@@ -203,7 +224,6 @@ typedef struct mleaf_s
int nummarksurfaces; int nummarksurfaces;
int cluster; // helper to acess to uncompressed visdata int cluster; // helper to acess to uncompressed visdata
byte ambient_sound_level[NUM_AMBIENTS]; byte ambient_sound_level[NUM_AMBIENTS];
} mleaf_t; } mleaf_t;
// surface extradata // surface extradata
@@ -291,7 +311,11 @@ struct msurface_s
typedef struct hull_s typedef struct hull_s
{ {
mclipnode_t *clipnodes; union
{
mclipnode16_t *clipnodes16;
mclipnode32_t *clipnodes32;
};
mplane_t *planes; mplane_t *planes;
int firstclipnode; int firstclipnode;
int lastclipnode; int lastclipnode;
@@ -341,7 +365,12 @@ typedef struct model_s
mvertex_t *vertexes; mvertex_t *vertexes;
int numedges; int numedges;
medge_t *edges; union
{
medge16_t *edges16;
medge32_t *edges32;
};
int numnodes; int numnodes;
mnode_t *nodes; mnode_t *nodes;
@@ -356,7 +385,11 @@ typedef struct model_s
int *surfedges; int *surfedges;
int numclipnodes; int numclipnodes;
mclipnode_t *clipnodes; union
{
mclipnode16_t *clipnodes16;
mclipnode32_t *clipnodes32;
};
int nummarksurfaces; int nummarksurfaces;
msurface_t **marksurfaces; msurface_t **marksurfaces;
@@ -550,16 +583,68 @@ typedef struct
#define ANIM_CYCLE 2 #define ANIM_CYCLE 2
#define MOD_FRAMES 20 #define MOD_FRAMES 20
#define MAX_DEMOS 32 #define MAX_DEMOS 32
#define MAX_MOVIES 8 #define MAX_MOVIES 8
#define MAX_CDTRACKS 32 #define MAX_CDTRACKS 32
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client) #define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
#define MAX_REQUESTS 64 #define MAX_REQUESTS 64
STATIC_CHECK_SIZEOF( mnode_t, 52, 72 );
STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 ); STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 );
STATIC_CHECK_SIZEOF( decal_t, 60, 88 ); STATIC_CHECK_SIZEOF( decal_t, 60, 88 );
STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 ); STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 );
// model flags (stored in model_t->flags)
#define MODEL_QBSP2 BIT( 28 ) // uses 32-bit types
// access functions
static inline mnode_t *node_child( const mnode_t *n, int side, const model_t *mod )
{
#if !XASH_64BIT
if( unlikely( mod->flags & MODEL_QBSP2 )) // MODEL_QBSP2
{
if( side == 0 )
{
if( n->child_0_leaf )
return (mnode_t *)(mod->leafs + n->child_0_off);
else
return (mnode_t *)(mod->nodes + n->child_0_off);
}
else
{
if( n->child_1_leaf )
return (mnode_t *)(mod->leafs + n->child_1_off);
else
return (mnode_t *)(mod->nodes + n->child_1_off);
}
}
return n->children_[side];
#else
return n->children_[side];
#endif
}
static inline void node_children( mnode_t *children[2], const mnode_t *n, const model_t *mod )
{
children[0] = node_child( n, 0, mod );
children[1] = node_child( n, 1, mod );
}
static inline int node_firstsurface( const mnode_t *n, const model_t *mod )
{
if( mod->flags & MODEL_QBSP2 )
return n->firstsurface_0 + ( n->firstsurface_1 << 16 );
else
return n->firstsurface_0;
}
static inline int node_numsurfaces( const mnode_t *n, const model_t *mod )
{
if( mod->flags & MODEL_QBSP2 )
return n->numsurfaces_0 + ( n->numsurfaces_1 << 16 );
else
return n->numsurfaces_0;
}
#endif//COM_MODEL_H #endif//COM_MODEL_H

View File

@@ -127,8 +127,10 @@ static void R_SplitEntityOnNode( mnode_t *node )
} }
// recurse down the contacted sides // recurse down the contacted sides
if( sides & 1 ) R_SplitEntityOnNode( node->children[0] ); if( sides & 1 )
if( sides & 2 ) R_SplitEntityOnNode( node->children[1] ); R_SplitEntityOnNode( node_child( node, 0, cl.worldmodel ));
if( sides & 2 )
R_SplitEntityOnNode( node_child( node, 1, cl.worldmodel ));
} }
/* /*

View File

@@ -138,10 +138,7 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
switch( parm ) switch( parm )
{ {
case PARM_BSP2_SUPPORTED: case PARM_BSP2_SUPPORTED:
#ifdef SUPPORT_BSP2_FORMAT
return 1; return 1;
#endif
return 0;
case PARAM_GAMEPAUSED: case PARAM_GAMEPAUSED:
return cl.paused; return cl.paused;
case PARM_CLIENT_INGAME: case PARM_CLIENT_INGAME:

View File

@@ -466,8 +466,8 @@ static void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int show
R_DrawNodeConnection( x, y, x + scale, y + scale ); R_DrawNodeConnection( x, y, x + scale, y + scale );
} }
R_ShowTree_r( node->children[1], x - scale, y + scale, downScale, shownodes, viewleaf ); R_ShowTree_r( node_child( node, 1, cl.worldmodel ), x - scale, y + scale, downScale, shownodes, viewleaf );
R_ShowTree_r( node->children[0], x + scale, y + scale, downScale, shownodes, viewleaf ); R_ShowTree_r( node_child( node, 0, cl.worldmodel ), x + scale, y + scale, downScale, shownodes, viewleaf );
world.recursion_level--; world.recursion_level--;
} }
@@ -482,7 +482,7 @@ static void R_ShowTree( void )
return; return;
world.recursion_level = 0; world.recursion_level = 0;
viewleaf = Mod_PointInLeaf( refState.vieworg, cl.worldmodel->nodes ); viewleaf = Mod_PointInLeaf( refState.vieworg, cl.worldmodel->nodes, cl.worldmodel );
ref.dllFuncs.TriRenderMode( kRenderTransTexture ); ref.dllFuncs.TriRenderMode( kRenderTransTexture );

View File

@@ -470,16 +470,16 @@ out_free:
* This is a stack of the clipnodes we have traversed * This is a stack of the clipnodes we have traversed
* "sides" indicates which side we went down each time * "sides" indicates which side we went down each time
*/ */
static mclipnode_t *node_stack[MAX_CLIPNODE_DEPTH]; static int node_stack[MAX_CLIPNODE_DEPTH];
static int side_stack[MAX_CLIPNODE_DEPTH]; static int side_stack[MAX_CLIPNODE_DEPTH];
static uint node_stack_depth; static uint node_stack_depth;
static void push_node( mclipnode_t *node, int side ) static void push_node( int nodenum, int side )
{ {
if( node_stack_depth == MAX_CLIPNODE_DEPTH ) if( node_stack_depth == MAX_CLIPNODE_DEPTH )
Host_Error( "node stack overflow\n" ); Host_Error( "node stack overflow\n" );
node_stack[node_stack_depth] = node; node_stack[node_stack_depth] = nodenum;
side_stack[node_stack_depth] = side; side_stack[node_stack_depth] = side;
node_stack_depth++; node_stack_depth++;
} }
@@ -502,22 +502,27 @@ static void free_hull_polys( hullnode_t *hull_polys )
} }
} }
static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys, hull_model_t *model ); static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_model_t *model );
static void do_hull_recursion( hull_t *hull, mclipnode_t *node, int side, hullnode_t *polys, hull_model_t *model ) static void do_hull_recursion( hull_t *hull, int nodenum, int side, hullnode_t *polys, hull_model_t *model )
{ {
winding_t *w, *next; winding_t *w, *next;
int childnum;
if( node->children[side] >= 0 ) if( world.version == QBSP2_VERSION )
childnum = hull->clipnodes32[nodenum].children[side];
else
childnum = hull->clipnodes16[nodenum].children[side];
if( childnum >= 0 )
{ {
mclipnode_t *child = hull->clipnodes + node->children[side]; push_node( nodenum, side );
push_node( node, side ); hull_windings_r( hull, childnum, polys, model );
hull_windings_r( hull, child, polys, model );
pop_node(); pop_node();
} }
else else
{ {
switch( node->children[side] ) switch( childnum )
{ {
case CONTENTS_EMPTY: case CONTENTS_EMPTY:
case CONTENTS_WATER: case CONTENTS_WATER:
@@ -542,20 +547,25 @@ static void do_hull_recursion( hull_t *hull, mclipnode_t *node, int side, hullno
} }
break; break;
default: default:
Host_Error( "bad contents: %i\n", node->children[side] ); Host_Error( "bad contents: %i\n", childnum );
break; break;
} }
} }
} }
static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys, hull_model_t *model ) static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_model_t *model )
{ {
mplane_t *plane = hull->planes + node->planenum; mplane_t *plane;
hullnode_t frontlist = LIST_HEAD_INIT( frontlist ); hullnode_t frontlist = LIST_HEAD_INIT( frontlist );
hullnode_t backlist = LIST_HEAD_INIT( backlist ); hullnode_t backlist = LIST_HEAD_INIT( backlist );
winding_t *w, *next, *front, *back; winding_t *w, *next, *front, *back;
int i; int i;
if( world.version == QBSP2_VERSION )
plane = hull->planes + hull->clipnodes32[nodenum].planenum;
else
plane = hull->planes + hull->clipnodes16[nodenum].planenum;
list_for_each_entry_safe( w, next, polys, chain ) list_for_each_entry_safe( w, next, polys, chain )
{ {
// PARANIOA - PAIR CHECK // PARANIOA - PAIR CHECK
@@ -601,7 +611,13 @@ static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys,
for( i = 0; w && i < node_stack_depth; i++ ) for( i = 0; w && i < node_stack_depth; i++ )
{ {
mplane_t *p = hull->planes + node_stack[i]->planenum; mplane_t *p;
if( world.version == QBSP2_VERSION )
p = hull->planes + hull->clipnodes32[node_stack[i]].planenum;
else
p = hull->planes + hull->clipnodes16[node_stack[i]].planenum;
w = winding_clip( w, p, false, side_stack[i], 0.00001 ); w = winding_clip( w, p, false, side_stack[i], 0.00001 );
} }
@@ -625,8 +641,8 @@ static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys,
Con_Printf( S_WARN "new winding was clipped away!\n" ); Con_Printf( S_WARN "new winding was clipped away!\n" );
} }
do_hull_recursion( hull, node, 0, &frontlist, model ); do_hull_recursion( hull, nodenum, 0, &frontlist, model );
do_hull_recursion( hull, node, 1, &backlist, model ); do_hull_recursion( hull, nodenum, 1, &backlist, model );
} }
static void remove_paired_polys( hull_model_t *model ) static void remove_paired_polys( hull_model_t *model )
@@ -655,7 +671,7 @@ static void make_hull_windings( hull_t *hull, hull_model_t *model )
if( hull->planes != NULL ) if( hull->planes != NULL )
{ {
hull_windings_r( hull, hull->clipnodes + hull->firstclipnode, &head, model ); hull_windings_r( hull, hull->firstclipnode, &head, model );
remove_paired_polys( model ); remove_paired_polys( model );
} }
Con_Reportf( "%i hull polys\n", model->num_polys ); Con_Reportf( "%i hull polys\n", model->num_polys );

View File

@@ -300,6 +300,12 @@ static qboolean R_Init_Video_( const int type )
return R_Init_Video( type ); return R_Init_Video( type );
} }
static mleaf_t *pfnMod_PointInLeaf( const vec3_t p, mnode_t *node )
{
// FIXME: get rid of this on next RefAPI update
return Mod_PointInLeaf( p, node, cl.models[1] );
}
static const ref_api_t gEngfuncs = static const ref_api_t gEngfuncs =
{ {
pfnEngineGetParm, pfnEngineGetParm,
@@ -340,7 +346,7 @@ static const ref_api_t gEngfuncs =
Mod_SampleSizeForFace, Mod_SampleSizeForFace,
Mod_BoxVisible, Mod_BoxVisible,
Mod_PointInLeaf, pfnMod_PointInLeaf,
R_DrawWorldHull, R_DrawWorldHull,
R_DrawModelHull, R_DrawModelHull,

View File

@@ -996,7 +996,7 @@ static void S_UpdateAmbientSounds( void )
// calc ambient sound levels // calc ambient sound levels
if( !cl.worldmodel ) return; if( !cl.worldmodel ) return;
leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes ); leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes, cl.worldmodel );
if( !leaf || !s_ambient_level.value ) if( !leaf || !s_ambient_level.value )
{ {

View File

@@ -72,8 +72,6 @@ GNU General Public License for more details.
#define CVAR_GLCONFIG_DESCRIPTION "enable or disable %s" #define CVAR_GLCONFIG_DESCRIPTION "enable or disable %s"
#define DEFAULT_BSP_BUILD_ERROR "%s can't be loaded in this build. Please rebuild engine with enabled SUPPORT_BSP2_FORMAT\n"
#define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest" #define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest"
#define XASH_ENGINE_NAME "Xash3D FWGS" #define XASH_ENGINE_NAME "Xash3D FWGS"

View File

@@ -385,6 +385,35 @@ static const mlumpinfo_t extlumps[EXTRA_LUMPS] =
}, },
}; };
#define BOX_CLIPNODES_INITIALIZER \
{ \
.planenum = 0, \
.children = { CONTENTS_EMPTY, 1 }, \
}, \
{ \
.planenum = 1, \
.children = { 2, CONTENTS_EMPTY }, \
}, \
{ \
.planenum = 2, \
.children = { CONTENTS_EMPTY, 3 }, \
}, \
{ \
.planenum = 3, \
.children = { 4, CONTENTS_EMPTY }, \
}, \
{ \
.planenum = 4, \
.children = { CONTENTS_EMPTY, 5 }, \
}, \
{ \
.planenum = 5, \
.children = { CONTENTS_SOLID, CONTENTS_EMPTY }, \
}, \
const mclipnode16_t box_clipnodes16[6] = { BOX_CLIPNODES_INITIALIZER };
const mclipnode32_t box_clipnodes32[6] = { BOX_CLIPNODES_INITIALIZER };
/* /*
=============================================================================== ===============================================================================
@@ -856,7 +885,7 @@ Mod_PointInLeaf
================== ==================
*/ */
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node ) mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod )
{ {
Assert( node != NULL ); Assert( node != NULL );
@@ -864,7 +893,7 @@ mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node )
{ {
if( node->contents < 0 ) if( node->contents < 0 )
return (mleaf_t *)node; return (mleaf_t *)node;
node = node->children[PlaneDiff( p, node->plane ) <= 0]; node = node_child( node, PlaneDiff( p, node->plane ) <= 0, mod );
} }
// never reached // never reached
@@ -885,7 +914,7 @@ byte *Mod_GetPVSForPoint( const vec3_t p )
ASSERT( worldmodel != NULL ); ASSERT( worldmodel != NULL );
leaf = Mod_PointInLeaf( p, worldmodel->nodes ); leaf = Mod_PointInLeaf( p, worldmodel->nodes, worldmodel );
if( leaf && leaf->cluster >= 0 ) if( leaf && leaf->cluster >= 0 )
return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes ); return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes );
@@ -905,14 +934,14 @@ static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *v
float d = PlaneDiff( org, node->plane ); float d = PlaneDiff( org, node->plane );
if( d > radius ) if( d > radius )
node = node->children[0]; node = node_child( node, 0, worldmodel );
else if( d < -radius ) else if( d < -radius )
node = node->children[1]; node = node_child( node, 1, worldmodel );
else else
{ {
// go down both sides // go down both sides
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node->children[0], phs ); Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node_child( node, 0, worldmodel ), phs );
node = node->children[1]; node = node_child( node, 1, worldmodel );
} }
} }
@@ -950,7 +979,7 @@ int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, q
ASSERT( worldmodel != NULL ); ASSERT( worldmodel != NULL );
leaf = Mod_PointInLeaf( org, worldmodel->nodes ); leaf = Mod_PointInLeaf( org, worldmodel->nodes, worldmodel );
bytes = Q_min( bytes, visbytes ); bytes = Q_min( bytes, visbytes );
// enable full visibility for some reasons // enable full visibility for some reasons
@@ -1009,20 +1038,16 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
sides = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, node->plane ); sides = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, node->plane );
if( sides == 1 ) if( sides == 1 )
{ node = node_child( node, 0, worldmodel );
node = node->children[0];
}
else if( sides == 2 ) else if( sides == 2 )
{ node = node_child( node, 1, worldmodel );
node = node->children[1];
}
else else
{ {
// go down both // go down both
if( ll->topnode == -1 ) if( ll->topnode == -1 )
ll->topnode = node - worldmodel->nodes; ll->topnode = node - worldmodel->nodes;
Mod_BoxLeafnums_r( ll, node->children[0] ); Mod_BoxLeafnums_r( ll, node_child( node, 0, worldmodel ));
node = node->children[1]; node = node_child( node, 1, worldmodel );
} }
} }
} }
@@ -1079,35 +1104,6 @@ qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbi
return false; return false;
} }
/*
=============
Mod_HeadnodeVisible
=============
*/
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf )
{
if( !node || node->contents == CONTENTS_SOLID )
return false;
if( node->contents < 0 )
{
if( !CHECKVISBIT( visbits, ((mleaf_t *)node)->cluster ))
return false;
if( lastleaf )
*lastleaf = ((mleaf_t *)node)->cluster;
return true;
}
if( Mod_HeadnodeVisible( node->children[0], visbits, lastleaf ))
return true;
if( Mod_HeadnodeVisible( node->children[1], visbits, lastleaf ))
return true;
return false;
}
/* /*
================= =================
Mod_FindModelOrigin Mod_FindModelOrigin
@@ -1264,22 +1260,35 @@ Mod_GetFaceContents
determine face contents by name determine face contents by name
================== ==================
*/ */
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge ) static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge, const dbspmodel_t *bmod )
{ {
int lindex; int lindex = mod->surfedges[surfedge];
medge_t *edge;
lindex = mod->surfedges[surfedge]; if( bmod->version == QBSP2_VERSION )
if( lindex > 0 )
{ {
edge = &mod->edges[lindex]; if( lindex > 0 )
return &mod->vertexes[edge->v[0]]; {
medge32_t *edge = &mod->edges32[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
medge32_t *edge = &mod->edges32[-lindex];
return &mod->vertexes[edge->v[1]];
}
} }
else else
{ {
edge = &mod->edges[-lindex]; if( lindex > 0 )
return &mod->vertexes[edge->v[1]]; {
medge16_t *edge = &mod->edges16[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
medge16_t *edge = &mod->edges16[-lindex];
return &mod->vertexes[edge->v[1]];
}
} }
} }
@@ -1364,7 +1373,7 @@ Mod_CalcSurfaceExtents
Fills in surf->texturemins[] and surf->extents[] Fills in surf->texturemins[] and surf->extents[]
================= =================
*/ */
static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf ) static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
{ {
// this place is VERY critical to precision // this place is VERY critical to precision
// keep it as float, don't use double, because it causes issues with lightmap // keep it as float, don't use double, because it causes issues with lightmap
@@ -1391,8 +1400,16 @@ static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf )
if( e >= mod->numedges || e <= -mod->numedges ) if( e >= mod->numedges || e <= -mod->numedges )
Host_Error( "%s: bad edge\n", __func__ ); Host_Error( "%s: bad edge\n", __func__ );
if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]]; if( bmod->version == QBSP2_VERSION )
else v = &mod->vertexes[mod->edges[-e].v[1]]; {
if( e >= 0 ) v = &mod->vertexes[mod->edges32[e].v[0]];
else v = &mod->vertexes[mod->edges32[-e].v[1]];
}
else
{
if( e >= 0 ) v = &mod->vertexes[mod->edges16[e].v[0]];
else v = &mod->vertexes[mod->edges16[-e].v[1]];
}
for( j = 0; j < 2; j++ ) for( j = 0; j < 2; j++ )
{ {
@@ -1446,7 +1463,7 @@ Mod_CalcSurfaceBounds
fills in surf->mins and surf->maxs fills in surf->mins and surf->maxs
================= =================
*/ */
static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf ) static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
{ {
int i, e; int i, e;
mvertex_t *v; mvertex_t *v;
@@ -1460,8 +1477,16 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf )
if( e >= mod->numedges || e <= -mod->numedges ) if( e >= mod->numedges || e <= -mod->numedges )
Host_Error( "%s: bad edge\n", __func__ ); Host_Error( "%s: bad edge\n", __func__ );
if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]]; if( bmod->version == QBSP2_VERSION )
else v = &mod->vertexes[mod->edges[-e].v[1]]; {
if( e >= 0 ) v = &mod->vertexes[mod->edges32[e].v[0]];
else v = &mod->vertexes[mod->edges32[-e].v[1]];
}
else
{
if( e >= 0 ) v = &mod->vertexes[mod->edges16[e].v[0]];
else v = &mod->vertexes[mod->edges16[-e].v[1]];
}
AddPointToBounds( v->position, surf->info->mins, surf->info->maxs ); AddPointToBounds( v->position, surf->info->mins, surf->info->maxs );
} }
@@ -1473,7 +1498,7 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf )
Mod_CreateFaceBevels Mod_CreateFaceBevels
================= =================
*/ */
static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf ) static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
{ {
vec3_t delta, edgevec; vec3_t delta, edgevec;
byte *facebevel; byte *facebevel;
@@ -1506,8 +1531,8 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
{ {
mplane_t *dest = &fb->edges[i]; mplane_t *dest = &fb->edges[i];
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i ); v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod );
v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges ); v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges, bmod );
VectorSubtract( v1->position, v0->position, edgevec ); VectorSubtract( v1->position, v0->position, edgevec );
CrossProduct( faceNormal, edgevec, dest->normal ); CrossProduct( faceNormal, edgevec, dest->normal );
VectorNormalize( dest->normal ); VectorNormalize( dest->normal );
@@ -1521,7 +1546,7 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
// compute face radius // compute face radius
for( i = 0; i < surf->numedges; i++ ) for( i = 0; i < surf->numedges; i++ )
{ {
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i ); v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod );
VectorSubtract( v0->position, fb->origin, delta ); VectorSubtract( v0->position, fb->origin, delta );
radius = DotProduct( delta, delta ); radius = DotProduct( delta, delta );
fb->radius = Q_max( radius, fb->radius ); fb->radius = Q_max( radius, fb->radius );
@@ -1533,13 +1558,15 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
Mod_SetParent Mod_SetParent
================= =================
*/ */
static void Mod_SetParent( mnode_t *node, mnode_t *parent ) static void Mod_SetParent( model_t *mod, mnode_t *node, mnode_t *parent )
{ {
node->parent = parent; node->parent = parent;
if( node->contents < 0 ) return; // it's leaf if( node->contents < 0 )
Mod_SetParent( node->children[0], node ); return; // it's leaf
Mod_SetParent( node->children[1], node );
Mod_SetParent( mod, node_child( node, 0, mod ), node );
Mod_SetParent( mod, node_child( node, 1, mod ), node );
} }
/* /*
@@ -1547,7 +1574,7 @@ static void Mod_SetParent( mnode_t *node, mnode_t *parent )
CountClipNodes_r CountClipNodes_r
================== ==================
*/ */
static void CountClipNodes_r( mclipnode_t *src, hull_t *hull, int nodenum ) static void CountClipNodes16_r( mclipnode16_t *src, hull_t *hull, int nodenum )
{ {
// leaf? // leaf?
if( nodenum < 0 ) return; if( nodenum < 0 ) return;
@@ -1556,16 +1583,11 @@ static void CountClipNodes_r( mclipnode_t *src, hull_t *hull, int nodenum )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" ); Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
hull->lastclipnode++; hull->lastclipnode++;
CountClipNodes_r( src, hull, src[nodenum].children[0] ); CountClipNodes16_r( src, hull, src[nodenum].children[0] );
CountClipNodes_r( src, hull, src[nodenum].children[1] ); CountClipNodes16_r( src, hull, src[nodenum].children[1] );
} }
/* static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum )
==================
CountClipNodes32_r
==================
*/
static void CountClipNodes32_r( dclipnode32_t *src, hull_t *hull, int nodenum )
{ {
// leaf? // leaf?
if( nodenum < 0 ) return; if( nodenum < 0 ) return;
@@ -1578,15 +1600,27 @@ static void CountClipNodes32_r( dclipnode32_t *src, hull_t *hull, int nodenum )
CountClipNodes32_r( src, hull, src[nodenum].children[1] ); CountClipNodes32_r( src, hull, src[nodenum].children[1] );
} }
static void CountDClipNodes_r( dclipnode32_t *src, hull_t *hull, int nodenum )
{
// leaf?
if( nodenum < 0 ) return;
if( hull->lastclipnode == MAX_MAP_CLIPNODES )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
hull->lastclipnode++;
CountDClipNodes_r( src, hull, src[nodenum].children[0] );
CountDClipNodes_r( src, hull, src[nodenum].children[1] );
}
/* /*
================== ==================
RemapClipNodes_r RemapClipNodes_r
================== ==================
*/ */
static int RemapClipNodes_r( dclipnode32_t *srcnodes, hull_t *hull, int nodenum ) static int RemapClipNodes_r( dbspmodel_t *bmod, dclipnode32_t *srcnodes, hull_t *hull, int nodenum )
{ {
dclipnode32_t *src; dclipnode32_t *src;
mclipnode_t *out;
int i, c; int i, c;
// leaf? // leaf?
@@ -1599,13 +1633,22 @@ static int RemapClipNodes_r( dclipnode32_t *srcnodes, hull_t *hull, int nodenum
src = srcnodes + nodenum; src = srcnodes + nodenum;
c = hull->lastclipnode; c = hull->lastclipnode;
out = &hull->clipnodes[c];
hull->lastclipnode++; hull->lastclipnode++;
out->planenum = src->planenum; if( bmod->version == QBSP2_VERSION )
{
for( i = 0; i < 2; i++ ) mclipnode32_t *out = &hull->clipnodes32[c];
out->children[i] = RemapClipNodes_r( srcnodes, hull, src->children[i] ); out->planenum = src->planenum;
for( i = 0; i < 2; i++ )
out->children[i] = RemapClipNodes_r( bmod, srcnodes, hull, src->children[i] );
}
else
{
mclipnode16_t *out = &hull->clipnodes16[c];
out->planenum = src->planenum;
for( i = 0; i < 2; i++ )
out->children[i] = RemapClipNodes_r( bmod, srcnodes, hull, src->children[i] );
}
return c; return c;
} }
@@ -1617,34 +1660,64 @@ Mod_MakeHull0
Duplicate the drawing hull structure as a clipping hull Duplicate the drawing hull structure as a clipping hull
================= =================
*/ */
static void Mod_MakeHull0( model_t *mod ) static void Mod_MakeHull0( model_t *mod, const dbspmodel_t *bmod )
{ {
mnode_t *in, *child; hull_t *hull = &mod->hulls[0];
mclipnode_t *out; int i;
hull_t *hull;
int i, j;
hull = &mod->hulls[0];
hull->clipnodes = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *out ));
in = mod->nodes;
hull->firstclipnode = 0; hull->firstclipnode = 0;
hull->lastclipnode = mod->numnodes - 1; hull->lastclipnode = mod->numnodes - 1;
hull->planes = mod->planes; hull->planes = mod->planes;
for( i = 0; i < mod->numnodes; i++, out++, in++ ) if( bmod->version == QBSP2_VERSION )
{ {
out->planenum = in->plane - mod->planes; mclipnode32_t *out;
mnode_t *in = mod->nodes;
for( j = 0; j < 2; j++ ) hull->clipnodes32 = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *hull->clipnodes32 ));
for( i = 0; i < mod->numnodes; i++, out++, in++ )
{ {
child = in->children[j]; int j;
if( child->contents < 0 ) out->planenum = in->plane - mod->planes;
out->children[j] = child->contents;
else out->children[j] = child - mod->nodes; for( j = 0; j < 2; j++ )
{
mnode_t *child = node_child( in, j, mod );
if( child->contents < 0 )
out->children[j] = child->contents;
else
out->children[j] = child - mod->nodes;
}
} }
} }
else
{
mclipnode16_t *out;
mnode_t *in = mod->nodes;
hull->clipnodes16 = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *hull->clipnodes16 ));
for( i = 0; i < mod->numnodes; i++, out++, in++ )
{
int j;
out->planenum = in->plane - mod->planes;
for( j = 0; j < 2; j++ )
{
mnode_t *child = node_child( in, j, mod );
if( child->contents < 0 )
out->children[j] = child->contents;
else
out->children[j] = child - mod->nodes;
}
}
}
} }
/* /*
@@ -1688,15 +1761,18 @@ static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, poolhandle_t mempool
if( VectorIsNull( hull->clip_mins ) && VectorIsNull( hull->clip_maxs )) if( VectorIsNull( hull->clip_mins ) && VectorIsNull( hull->clip_maxs ))
return; // no hull specified return; // no hull specified
CountClipNodes32_r( bmod->clipnodes_out, hull, headnode ); CountDClipNodes_r( bmod->clipnodes_out, hull, headnode );
// fit array to real count // fit array to real count
hull->clipnodes = (mclipnode_t *)Mem_Malloc( mempool, sizeof( mclipnode_t ) * hull->lastclipnode ); if( bmod->version == QBSP2_VERSION )
hull->clipnodes32 = Mem_Malloc( mempool, sizeof( *hull->clipnodes32 ) * hull->lastclipnode );
else
hull->clipnodes16 = Mem_Malloc( mempool, sizeof( *hull->clipnodes16 ) * hull->lastclipnode );
hull->planes = mod->planes; // share planes hull->planes = mod->planes; // share planes
hull->lastclipnode = 0; // restart counting hull->lastclipnode = 0; // restart counting
// remap clipnodes to 16-bit indexes RemapClipNodes_r( bmod, bmod->clipnodes_out, hull, headnode ); // remap clipnodes to 16-bit indexes
RemapClipNodes_r( bmod->clipnodes_out, hull, headnode );
} }
static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_size, color24 **out, size_t *outsize ) static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_size, color24 **out, size_t *outsize )
@@ -1704,7 +1780,8 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
char modelname[64], path[64]; char modelname[64], path[64];
int iCompare; int iCompare;
fs_offset_t datasize; fs_offset_t datasize;
byte *in; file_t *f;
uint hdr[2];
COM_FileBase( mod->name, modelname, sizeof( modelname )); COM_FileBase( mod->name, modelname, sizeof( modelname ));
Q_snprintf( path, sizeof( path ), "maps/%s.%s", modelname, ext ); Q_snprintf( path, sizeof( path ), "maps/%s.%s", modelname, ext );
@@ -1715,31 +1792,15 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
if( iCompare < 0 ) // this may happens if level-designer used -onlyents key for hlcsg if( iCompare < 0 ) // this may happens if level-designer used -onlyents key for hlcsg
Con_Printf( S_WARN "%s probably is out of date\n", path ); Con_Printf( S_WARN "%s probably is out of date\n", path );
in = FS_LoadFile( path, &datasize, false ); f = FS_Open( path, "rb", false );
if( !in ) if( !f )
{ {
Con_Printf( S_ERROR "couldn't load %s\n", path ); Con_Printf( S_ERROR "couldn't load %s\n", path );
return false; return false;
} }
if( datasize <= 8 ) // header + version datasize = FS_FileLength( f );
{
Con_Printf( S_ERROR "%s is too short\n", path );
goto cleanup_and_error;
}
if( LittleLong( ((uint *)in)[0] ) != IDDELUXEMAPHEADER )
{
Con_Printf( S_ERROR "%s is corrupted\n", path );
goto cleanup_and_error;
}
if( LittleLong( ((uint *)in)[1] ) != DELUXEMAP_VERSION )
{
Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( ((uint *)in)[1] ), DELUXEMAP_VERSION );
goto cleanup_and_error;
}
// skip header bytes // skip header bytes
datasize -= 8; datasize -= 8;
@@ -1750,14 +1811,33 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
goto cleanup_and_error; goto cleanup_and_error;
} }
if( FS_Read( f, hdr, sizeof( hdr )) != sizeof( hdr ))
{
Con_Printf( S_ERROR "failed reading header from %s\n", path );
goto cleanup_and_error;
}
if( LittleLong( hdr[0] ) != IDDELUXEMAPHEADER )
{
Con_Printf( S_ERROR "%s is corrupted\n", path );
goto cleanup_and_error;
}
if( LittleLong( hdr[1] ) != DELUXEMAP_VERSION )
{
Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( hdr[1] ), DELUXEMAP_VERSION );
goto cleanup_and_error;
}
*out = Mem_Malloc( mod->mempool, datasize ); *out = Mem_Malloc( mod->mempool, datasize );
memcpy( *out, in + 8, datasize );
*outsize = datasize; *outsize = datasize;
Mem_Free( in );
FS_Read( f, *out, datasize );
FS_Close( f );
return true; return true;
cleanup_and_error: cleanup_and_error:
Mem_Free( in ); FS_Close( f );
return false; return false;
} }
@@ -1772,6 +1852,7 @@ for embedded submodels
static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod ) static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
{ {
qboolean colored = false; qboolean colored = false;
qboolean qbsp2 = false;
poolhandle_t mempool; poolhandle_t mempool;
char *ents; char *ents;
dmodel_t *bm; dmodel_t *bm;
@@ -1783,6 +1864,9 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
if( FBitSet( mod->flags, MODEL_COLORED_LIGHTING )) if( FBitSet( mod->flags, MODEL_COLORED_LIGHTING ))
colored = true; colored = true;
if( FBitSet( mod->flags, MODEL_QBSP2 ))
qbsp2 = true;
mod->numframes = 2; // regular and alternate animation mod->numframes = 2; // regular and alternate animation
// set up the submodels // set up the submodels
@@ -1795,7 +1879,10 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
mod->hulls[0].lastclipnode = bm->headnode[0]; // need to be real count mod->hulls[0].lastclipnode = bm->headnode[0]; // need to be real count
// counting a real number of clipnodes per each submodel // counting a real number of clipnodes per each submodel
CountClipNodes_r( mod->hulls[0].clipnodes, &mod->hulls[0], bm->headnode[0] ); if( bmod->version == QBSP2_VERSION )
CountClipNodes32_r( mod->hulls[0].clipnodes32, &mod->hulls[0], bm->headnode[0] );
else
CountClipNodes16_r( mod->hulls[0].clipnodes16, &mod->hulls[0], bm->headnode[0] );
// but hulls1-3 is build individually for a each given submodel // but hulls1-3 is build individually for a each given submodel
for( j = 1; j < MAX_MAP_HULLS; j++ ) for( j = 1; j < MAX_MAP_HULLS; j++ )
@@ -1813,6 +1900,7 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
// this bit will be shared between all the submodels include worldmodel // this bit will be shared between all the submodels include worldmodel
if( colored ) SetBits( mod->flags, MODEL_COLORED_LIGHTING ); if( colored ) SetBits( mod->flags, MODEL_COLORED_LIGHTING );
if( qbsp2 ) SetBits( mod->flags, MODEL_QBSP2 );
if( i != 0 ) if( i != 0 )
{ {
@@ -2135,15 +2223,15 @@ Mod_LoadEdges
*/ */
static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod ) static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod )
{ {
medge_t *out;
int i; int i;
mod->edges = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( medge_t ));
mod->numedges = bmod->numedges; mod->numedges = bmod->numedges;
if( bmod->version == QBSP2_VERSION ) if( bmod->version == QBSP2_VERSION )
{ {
dedge32_t *in = (dedge32_t *)bmod->edges32; dedge32_t *in = bmod->edges32;
medge32_t *out;
mod->edges32 = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( *out ));
for( i = 0; i < bmod->numedges; i++, in++, out++ ) for( i = 0; i < bmod->numedges; i++, in++, out++ )
{ {
@@ -2153,7 +2241,9 @@ static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod )
} }
else else
{ {
dedge_t *in = (dedge_t *)bmod->edges; dedge_t *in = bmod->edges;
medge16_t *out;
mod->edges16 = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( *out ));
for( i = 0; i < bmod->numedges; i++, in++, out++ ) for( i = 0; i < bmod->numedges; i++, in++, out++ )
{ {
@@ -2913,9 +3003,9 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod )
if( FBitSet( out->texinfo->flags, TEX_SPECIAL )) if( FBitSet( out->texinfo->flags, TEX_SPECIAL ))
SetBits( out->flags, SURF_DRAWTILED ); SetBits( out->flags, SURF_DRAWTILED );
Mod_CalcSurfaceBounds( mod, out ); Mod_CalcSurfaceBounds( mod, out, bmod );
Mod_CalcSurfaceExtents( mod, out ); Mod_CalcSurfaceExtents( mod, out, bmod );
Mod_CreateFaceBevels( mod, out ); Mod_CreateFaceBevels( mod, out, bmod );
// grab the second sample to detect colored lighting // grab the second sample to detect colored lighting
if( test_lightsize > 0 && lightofs != -1 ) if( test_lightsize > 0 && lightofs != -1 )
@@ -2962,7 +3052,6 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod )
if( samples == 1 || samples == 3 ) if( samples == 1 || samples == 3 )
{ {
bmod->lightmap_samples = (int)samples; bmod->lightmap_samples = (int)samples;
Con_Reportf( "lighting: %s\n", (bmod->lightmap_samples == 1) ? "monochrome" : "colored" );
bmod->lightmap_samples = Q_max( bmod->lightmap_samples, 1 ); // avoid division by zero bmod->lightmap_samples = Q_max( bmod->lightmap_samples, 1 ); // avoid division by zero
} }
else Con_DPrintf( S_WARN "lighting invalid samplecount: %g, defaulting to %i\n", samples, bmod->lightmap_samples ); else Con_DPrintf( S_WARN "lighting invalid samplecount: %g, defaulting to %i\n", samples, bmod->lightmap_samples );
@@ -2994,16 +3083,62 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod )
out->minmaxs[j+3] = in->maxs[j]; out->minmaxs[j+3] = in->maxs[j];
} }
#if !XASH_64BIT
if( in->firstface >= BIT( 24 ))
{
Host_Error( "%s: face index limit exceeded on node %i\n", __func__, i );
return;
}
if( in->numfaces >= BIT( 24 ))
{
Host_Error( "%s: face count limit exceeded on node %i\n", __func__, i );
return;
}
#endif
p = in->planenum; p = in->planenum;
out->plane = mod->planes + p; out->plane = mod->planes + p;
out->firstsurface = in->firstface; out->firstsurface_0 = in->firstface & 0xFFFF;
out->numsurfaces = in->numfaces; out->numsurfaces_0 = in->numfaces & 0xFFFF;
out->firstsurface_1 = in->firstface >> 16;
out->numsurfaces_1 = in->numfaces >> 16;
for( j = 0; j < 2; j++ ) for( j = 0; j < 2; j++ )
{ {
p = in->children[j]; p = in->children[j];
if( p >= 0 ) out->children[j] = mod->nodes + p; #if XASH_64BIT
else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p )); if( p >= 0 ) out->children_[j] = mod->nodes + p;
else out->children_[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
#else
if( j == 0 )
{
if( p >= 0 )
{
out->child_0_leaf = 0;
out->child_0_off = p;
}
else
{
out->child_0_leaf = 1;
out->child_0_off = -1 - p;
}
}
else
{
if( p >= 0 )
{
out->child_1_leaf = 0;
out->child_1_off = p;
}
else
{
out->child_1_leaf = 1;
out->child_1_off = -1 - p;
}
}
#endif
} }
} }
else else
@@ -3018,20 +3153,20 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod )
p = in->planenum; p = in->planenum;
out->plane = mod->planes + p; out->plane = mod->planes + p;
out->firstsurface = in->firstface; out->firstsurface_0 = in->firstface;
out->numsurfaces = in->numfaces; out->numsurfaces_0 = in->numfaces;
for( j = 0; j < 2; j++ ) for( j = 0; j < 2; j++ )
{ {
p = in->children[j]; p = in->children[j];
if( p >= 0 ) out->children[j] = mod->nodes + p; if( p >= 0 ) out->children_[j] = mod->nodes + p;
else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p )); else out->children_[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
} }
} }
} }
// sets nodes and leafs // sets nodes and leafs
Mod_SetParent( mod->nodes, NULL ); Mod_SetParent( mod, mod->nodes, NULL );
} }
/* /*
@@ -3413,6 +3548,8 @@ static void Mod_LoadLighting( model_t *mod, dbspmodel_t *bmod )
break; break;
} }
Con_Reportf( "lighting: %s\n", FBitSet( mod->flags, MODEL_COLORED_LIGHTING ) ? "colored" : "monochrome" );
// not supposed to be load ? // not supposed to be load ?
if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA )) if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA ))
{ {
@@ -3491,13 +3628,6 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
Q_strncpy( loadstat.name, mod->name, sizeof( loadstat.name )); Q_strncpy( loadstat.name, mod->name, sizeof( loadstat.name ));
wadvalue[0] = '\0'; wadvalue[0] = '\0';
#ifndef SUPPORT_BSP2_FORMAT
if( header->version == QBSP2_VERSION )
{
Con_Printf( S_ERROR DEFAULT_BSP_BUILD_ERROR, mod->name );
return false;
}
#endif
switch( header->version ) switch( header->version )
{ {
case HLBSP_VERSION: case HLBSP_VERSION:
@@ -3520,6 +3650,9 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
// everything else // everything else
srclumps[0].lumpnumber = LUMP_ENTITIES; srclumps[0].lumpnumber = LUMP_ENTITIES;
srclumps[1].lumpnumber = LUMP_PLANES; srclumps[1].lumpnumber = LUMP_PLANES;
if( header->version == QBSP2_VERSION )
SetBits( mod->flags, MODEL_QBSP2 );
break; break;
default: default:
Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, header->version, HLBSP_VERSION ); Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, header->version, HLBSP_VERSION );
@@ -3570,7 +3703,7 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
Mod_LoadClipnodes( mod, bmod ); Mod_LoadClipnodes( mod, bmod );
// preform some post-initalization // preform some post-initalization
Mod_MakeHull0( mod ); Mod_MakeHull0( mod, bmod );
Mod_SetupSubmodels( mod, bmod ); Mod_SetupSubmodels( mod, bmod );
if( isworld ) if( isworld )
@@ -3660,15 +3793,6 @@ qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base,
if( silent ) if( silent )
SetBits( flags, LUMP_SILENT ); SetBits( flags, LUMP_SILENT );
#ifndef SUPPORT_BSP2_FORMAT
if( header->version == QBSP2_VERSION )
{
if( !FBitSet( flags, LUMP_SILENT ))
Con_Printf( S_ERROR DEFAULT_BSP_BUILD_ERROR, name );
return false;
}
#endif
switch( header->version ) switch( header->version )
{ {
case HLBSP_VERSION: case HLBSP_VERSION:

View File

@@ -135,6 +135,8 @@ extern poolhandle_t com_studiocache;
extern convar_t mod_studiocache; extern convar_t mod_studiocache;
extern convar_t r_wadtextures; extern convar_t r_wadtextures;
extern convar_t r_showhull; extern convar_t r_showhull;
extern const mclipnode16_t box_clipnodes16[6];
extern const mclipnode32_t box_clipnodes32[6];
// //
// model.c // model.c
@@ -167,13 +169,12 @@ void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
// //
void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded ); void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded );
qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities ); qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities );
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf );
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean false ); int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean false );
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits ); qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize ); int Mod_CheckLump( const char *filename, const int lump, int *lumpsize );
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize ); int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );
int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize ); int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize );
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node ); mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod );
int Mod_SampleSizeForFace( const msurface_t *surf ); int Mod_SampleSizeForFace( const msurface_t *surf );
byte *Mod_GetPVSForPoint( const vec3_t p ); byte *Mod_GetPVSForPoint( const vec3_t p );
void Mod_UnloadBrushModel( model_t *mod ); void Mod_UnloadBrushModel( model_t *mod );

View File

@@ -50,9 +50,8 @@ static matrix3x4 studio_bones[MAXSTUDIOBONES];
static uint studio_hull_hitgroup[MAXSTUDIOBONES]; static uint studio_hull_hitgroup[MAXSTUDIOBONES];
static uint cache_hull_hitgroup[MAXSTUDIOBONES]; static uint cache_hull_hitgroup[MAXSTUDIOBONES];
static mstudiocache_t cache_studio[STUDIO_CACHESIZE]; static mstudiocache_t cache_studio[STUDIO_CACHESIZE];
static mclipnode_t studio_clipnodes[6]; static mplane_t studio_planes[MAXSTUDIOBONES * 6];
static mplane_t studio_planes[768]; static mplane_t cache_planes[MAXSTUDIOBONES * 6];
static mplane_t cache_planes[768];
// current cache state // current cache state
static int cache_current; static int cache_current;
@@ -66,25 +65,14 @@ Mod_InitStudioHull
*/ */
void Mod_InitStudioHull( void ) void Mod_InitStudioHull( void )
{ {
int i, side; int i;
if( studio_hull[0].planes != NULL ) if( studio_hull[0].planes != NULL )
return; // already initailized return; // already initailized
for( i = 0; i < 6; i++ )
{
studio_clipnodes[i].planenum = i;
side = i & 1;
studio_clipnodes[i].children[side] = CONTENTS_EMPTY;
if( i != 5 ) studio_clipnodes[i].children[side^1] = i + 1;
else studio_clipnodes[i].children[side^1] = CONTENTS_SOLID;
}
for( i = 0; i < MAXSTUDIOBONES; i++ ) for( i = 0; i < MAXSTUDIOBONES; i++ )
{ {
studio_hull[i].clipnodes = studio_clipnodes; studio_hull[i].clipnodes16 = (mclipnode16_t *)box_clipnodes16;
studio_hull[i].planes = &studio_planes[i*6]; studio_hull[i].planes = &studio_planes[i*6];
studio_hull[i].firstclipnode = 0; studio_hull[i].firstclipnode = 0;
studio_hull[i].lastclipnode = 5; studio_hull[i].lastclipnode = 5;
@@ -270,6 +258,11 @@ hull_t *Mod_HullForStudio( model_t *model, float frame, int sequence, vec3_t ang
for( i = j = 0; i < mod_studiohdr->numhitboxes; i++, j += 6 ) for( i = j = 0; i < mod_studiohdr->numhitboxes; i++, j += 6 )
{ {
if( world.version == QBSP2_VERSION )
studio_hull[i].clipnodes32 = (mclipnode32_t *)box_clipnodes32;
else
studio_hull[i].clipnodes16 = (mclipnode16_t *)box_clipnodes16;
if( bSkipShield && i == 21 ) if( bSkipShield && i == 21 )
continue; // CS stuff continue; // CS stuff

View File

@@ -112,6 +112,9 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_
int i, side; int i, side;
msurface_t *surf; msurface_t *surf;
vec3_t mid; vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0: loc0:
if( node->contents < 0 ) if( node->contents < 0 )
return NULL; return NULL;
@@ -119,15 +122,17 @@ loc0:
t1 = PlaneDiff( p1, node->plane ); t1 = PlaneDiff( p1, node->plane );
t2 = PlaneDiff( p2, node->plane ); t2 = PlaneDiff( p2, node->plane );
node_children( children, node, mod );
if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON ) if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON )
{ {
node = node->children[0]; node = children[0];
goto loc0; goto loc0;
} }
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON ) if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
{ {
node = node->children[1]; node = children[1];
goto loc0; goto loc0;
} }
@@ -137,13 +142,15 @@ loc0:
VectorLerp( p1, frac, p2, mid ); VectorLerp( p1, frac, p2, mid );
if(( surf = PM_RecursiveSurfCheck( mod, node->children[side], p1, mid )) != NULL ) if(( surf = PM_RecursiveSurfCheck( mod, children[side], p1, mid )) != NULL )
return surf; return surf;
// walk through real faces // walk through real faces
for( i = 0; i < node->numsurfaces; i++ ) numsurfaces = node_numsurfaces( node, mod );
firstsurface = node_firstsurface( node, mod );
for( i = 0; i < numsurfaces; i++ )
{ {
msurface_t *surf = &mod->surfaces[node->firstsurface + i]; msurface_t *surf = &mod->surfaces[firstsurface + i];
mextrasurf_t *info = surf->info; mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel; mfacebevel_t *fb = info->bevel;
int j, contents; int j, contents;
@@ -172,7 +179,7 @@ loc0:
return NULL; // through the fence return NULL; // through the fence
} }
return PM_RecursiveSurfCheck( mod, node->children[side^1], mid, p2 ); return PM_RecursiveSurfCheck( mod, children[side^1], mid, p2 );
} }
/* /*
@@ -227,6 +234,9 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con
float frac, midf; float frac, midf;
int i, r, side; int i, r, side;
vec3_t mid; vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0: loc0:
if( node->contents < 0 ) if( node->contents < 0 )
{ {
@@ -242,15 +252,17 @@ loc0:
front = PlaneDiff( start, node->plane ); front = PlaneDiff( start, node->plane );
back = PlaneDiff( stop, node->plane ); back = PlaneDiff( stop, node->plane );
node_children( children, node, mod );
if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON ) if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON )
{ {
node = node->children[0]; node = children[0];
goto loc0; goto loc0;
} }
if( front < FRAC_EPSILON && back < FRAC_EPSILON ) if( front < FRAC_EPSILON && back < FRAC_EPSILON )
{ {
node = node->children[1]; node = children[1];
goto loc0; goto loc0;
} }
@@ -261,7 +273,7 @@ loc0:
VectorLerp( start, frac, stop, mid ); VectorLerp( start, frac, stop, mid );
midf = p1f + ( p2f - p1f ) * frac; midf = p1f + ( p2f - p1f ) * frac;
r = PM_TestLine_r( mod, node->children[side], p1f, midf, start, mid, trace ); r = PM_TestLine_r( mod, children[side], p1f, midf, start, mid, trace );
if( r != CONTENTS_EMPTY ) if( r != CONTENTS_EMPTY )
{ {
@@ -272,9 +284,11 @@ loc0:
} }
// walk through real faces // walk through real faces
for( i = 0; i < node->numsurfaces; i++ ) numsurfaces = node_numsurfaces( node, mod );
firstsurface = node_firstsurface( node, mod );
for( i = 0; i < numsurfaces; i++ )
{ {
msurface_t *surf = &mod->surfaces[node->firstsurface + i]; msurface_t *surf = &mod->surfaces[firstsurface + i];
mextrasurf_t *info = surf->info; mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel; mfacebevel_t *fb = info->bevel;
int j, contents; int j, contents;
@@ -308,7 +322,7 @@ loc0:
return contents; return contents;
} }
return PM_TestLine_r( mod, node->children[!side], midf, p2f, mid, stop, trace ); return PM_TestLine_r( mod, children[!side], midf, p2f, mid, stop, trace );
} }
int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags ) int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags )

View File

@@ -25,8 +25,7 @@ GNU General Public License for more details.
#define PM_AllowHitBoxTrace( model, hull ) ( model && model->type == mod_studio && ( FBitSet( model->flags, STUDIO_TRACE_HITBOX ) || hull == 2 )) #define PM_AllowHitBoxTrace( model, hull ) ( model && model->type == mod_studio && ( FBitSet( model->flags, STUDIO_TRACE_HITBOX ) || hull == 2 ))
static mplane_t pm_boxplanes[6]; static mplane_t pm_boxplanes[6];
static mclipnode_t pm_boxclipnodes[6]; static hull_t pm_boxhull;
static hull_t pm_boxhull;
// default hullmins // default hullmins
static const vec3_t pm_hullmins[MAX_MAP_HULLS] = static const vec3_t pm_hullmins[MAX_MAP_HULLS] =
@@ -65,23 +64,15 @@ can just be stored out and get a proper hull_t structure.
*/ */
void PM_InitBoxHull( void ) void PM_InitBoxHull( void )
{ {
int i, side; int i;
pm_boxhull.clipnodes = pm_boxclipnodes; pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
pm_boxhull.planes = pm_boxplanes; pm_boxhull.planes = pm_boxplanes;
pm_boxhull.firstclipnode = 0; pm_boxhull.firstclipnode = 0;
pm_boxhull.lastclipnode = 5; pm_boxhull.lastclipnode = 5;
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
pm_boxclipnodes[i].planenum = i;
side = i & 1;
pm_boxclipnodes[i].children[side] = CONTENTS_EMPTY;
if( i != 5 ) pm_boxclipnodes[i].children[side^1] = i + 1;
else pm_boxclipnodes[i].children[side^1] = CONTENTS_SOLID;
pm_boxplanes[i].type = i>>1; pm_boxplanes[i].type = i>>1;
pm_boxplanes[i].normal[i>>1] = 1.0f; pm_boxplanes[i].normal[i>>1] = 1.0f;
pm_boxplanes[i].signbits = 0; pm_boxplanes[i].signbits = 0;
@@ -106,6 +97,11 @@ static hull_t *PM_HullForBox( const vec3_t mins, const vec3_t maxs )
pm_boxplanes[4].dist = maxs[2]; pm_boxplanes[4].dist = maxs[2];
pm_boxplanes[5].dist = mins[2]; pm_boxplanes[5].dist = mins[2];
if( world.version == QBSP2_VERSION )
pm_boxhull.clipnodes32 = (mclipnode32_t *)box_clipnodes32;
else
pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
return &pm_boxhull; return &pm_boxhull;
} }
@@ -122,10 +118,21 @@ int GAME_EXPORT PM_HullPointContents( hull_t *hull, int num, const vec3_t p )
if( !hull || !hull->planes ) // fantom bmodels? if( !hull || !hull->planes ) // fantom bmodels?
return CONTENTS_NONE; return CONTENTS_NONE;
while( num >= 0 ) if( world.version == QBSP2_VERSION )
{ {
plane = &hull->planes[hull->clipnodes[num].planenum]; while( num >= 0 )
num = hull->clipnodes[num].children[PlaneDiff( p, plane ) < 0]; {
plane = &hull->planes[hull->clipnodes32[num].planenum];
num = hull->clipnodes32[num].children[PlaneDiff( p, plane ) < 0];
}
}
else
{
while( num >= 0 )
{
plane = &hull->planes[hull->clipnodes16[num].planenum];
num = hull->clipnodes16[num].children[PlaneDiff( p, plane ) < 0];
}
} }
return num; return num;
} }
@@ -193,7 +200,7 @@ PM_RecursiveHullCheck
*/ */
qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace ) qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace )
{ {
mclipnode_t *node; int children[2];
mplane_t *plane; mplane_t *plane;
float t1, t2; float t1, t2;
float frac, midf; float frac, midf;
@@ -226,21 +233,31 @@ loc0:
Host_Error( "%s: bad node number %i\n", __func__, num ); Host_Error( "%s: bad node number %i\n", __func__, num );
// find the point distances // find the point distances
node = hull->clipnodes + num; if( world.version == QBSP2_VERSION )
plane = hull->planes + node->planenum; {
children[0] = hull->clipnodes32[num].children[0];
children[1] = hull->clipnodes32[num].children[1];
plane = hull->planes + hull->clipnodes32[num].planenum;
}
else
{
children[0] = hull->clipnodes16[num].children[0];
children[1] = hull->clipnodes16[num].children[1];
plane = hull->planes + hull->clipnodes16[num].planenum;
}
t1 = PlaneDiff( p1, plane ); t1 = PlaneDiff( p1, plane );
t2 = PlaneDiff( p2, plane ); t2 = PlaneDiff( p2, plane );
if( t1 >= 0.0f && t2 >= 0.0f ) if( t1 >= 0.0f && t2 >= 0.0f )
{ {
num = node->children[0]; num = children[0];
goto loc0; goto loc0;
} }
if( t1 < 0.0f && t2 < 0.0f ) if( t1 < 0.0f && t2 < 0.0f )
{ {
num = node->children[1]; num = children[1];
goto loc0; goto loc0;
} }
@@ -257,14 +274,14 @@ loc0:
VectorLerp( p1, frac, p2, mid ); VectorLerp( p1, frac, p2, mid );
// move up to the node // move up to the node
if( !PM_RecursiveHullCheck( hull, node->children[side], p1f, midf, p1, mid, trace )) if( !PM_RecursiveHullCheck( hull, children[side], p1f, midf, p1, mid, trace ))
return false; return false;
// this recursion can not be optimized because mid would need to be duplicated on a stack // this recursion can not be optimized because mid would need to be duplicated on a stack
if( PM_HullPointContents( hull, node->children[side^1], mid ) != CONTENTS_SOLID ) if( PM_HullPointContents( hull, children[side^1], mid ) != CONTENTS_SOLID )
{ {
// go past the node // go past the node
return PM_RecursiveHullCheck( hull, node->children[side^1], midf, p2f, mid, p2, trace ); return PM_RecursiveHullCheck( hull, children[side^1], midf, p2f, mid, p2, trace );
} }
// never got out of the solid area // never got out of the solid area

View File

@@ -16,11 +16,8 @@
#ifndef EDICT_H #ifndef EDICT_H
#define EDICT_H #define EDICT_H
#ifdef SUPPORT_BSP2_FORMAT #define MAX_ENT_LEAFS_32 24 // Orignally was 16
#define MAX_ENT_LEAFS 24 // Orignally was 16 #define MAX_ENT_LEAFS_16 48
#else
#define MAX_ENT_LEAFS 48
#endif
#include "progdefs.h" #include "progdefs.h"
@@ -33,11 +30,12 @@ struct edict_s
int headnode; // -1 to use normal leaf check int headnode; // -1 to use normal leaf check
int num_leafs; int num_leafs;
#ifdef SUPPORT_BSP2_FORMAT union
int leafnums[MAX_ENT_LEAFS]; {
#else int leafnums32[MAX_ENT_LEAFS_32];
short leafnums[MAX_ENT_LEAFS]; short leafnums16[MAX_ENT_LEAFS_16];
#endif };
float freetime; // sv.time when the object was freed float freetime; // sv.time when the object was freed
void* pvPrivateData; // Alloced and freed by engine, used by DLLs void* pvPrivateData; // Alloced and freed by engine, used by DLLs

View File

@@ -41,8 +41,54 @@ void Platform_MessageBox( const char *title, const char *message, qboolean paren
} }
#endif // XASH_MESSAGEBOX == MSGBOX_SDL #endif // XASH_MESSAGEBOX == MSGBOX_SDL
static const char *SDLash_CategoryToString( int category )
{
switch( category )
{
case SDL_LOG_CATEGORY_APPLICATION: return "App";
case SDL_LOG_CATEGORY_ERROR: return "Error";
case SDL_LOG_CATEGORY_ASSERT: return "Assert";
case SDL_LOG_CATEGORY_SYSTEM: return "System";
case SDL_LOG_CATEGORY_AUDIO: return "Audio";
case SDL_LOG_CATEGORY_VIDEO: return "Video";
case SDL_LOG_CATEGORY_RENDER: return "Render";
case SDL_LOG_CATEGORY_INPUT: return "Input";
case SDL_LOG_CATEGORY_TEST: return "Test";
default: return "Unknown";
}
}
static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_LogPriority priority, const char *message )
{
switch( priority )
{
case SDL_LOG_PRIORITY_CRITICAL:
case SDL_LOG_PRIORITY_ERROR:
Con_Printf( S_ERROR S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
case SDL_LOG_PRIORITY_WARN:
Con_DPrintf( S_WARN S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
case SDL_LOG_PRIORITY_INFO:
Con_Reportf( S_NOTE S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
default:
Con_Reportf( S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
break;
}
}
void SDLash_Init( void ) void SDLash_Init( void )
{ {
SDL_LogSetOutputFunction( SDLash_LogOutputFunction, NULL );
if( host_developer.value >= 2 )
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_VERBOSE );
else if( host_developer.value >= 1 )
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_WARN );
else
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_ERROR );
#ifndef SDL_INIT_EVENTS #ifndef SDL_INIT_EVENTS
#define SDL_INIT_EVENTS 0 #define SDL_INIT_EVENTS 0
#endif #endif

View File

@@ -80,6 +80,7 @@ GNU General Public License for more details.
#define MODEL_LIQUID BIT( 2 ) // model has only point hull #define MODEL_LIQUID BIT( 2 ) // model has only point hull
#define MODEL_TRANSPARENT BIT( 3 ) // have transparent surfaces #define MODEL_TRANSPARENT BIT( 3 ) // have transparent surfaces
#define MODEL_COLORED_LIGHTING BIT( 4 ) // lightmaps stored as RGB #define MODEL_COLORED_LIGHTING BIT( 4 ) // lightmaps stored as RGB
#define MODEL_WORLD BIT( 29 ) // it's a worldmodel #define MODEL_WORLD BIT( 29 ) // it's a worldmodel
#define MODEL_CLIENT BIT( 30 ) // client sprite #define MODEL_CLIENT BIT( 30 ) // client sprite

View File

@@ -67,6 +67,8 @@ extern int SV_UPDATE_BACKUP;
#define MAX_PUSHED_ENTS 256 #define MAX_PUSHED_ENTS 256
#define MAX_VIEWENTS 128 #define MAX_VIEWENTS 128
#define MAX_ENT_LEAFS( ext ) (( ext ) ? MAX_ENT_LEAFS_32 : MAX_ENT_LEAFS_16 )
#define FCL_RESEND_USERINFO BIT( 0 ) #define FCL_RESEND_USERINFO BIT( 0 )
#define FCL_RESEND_MOVEVARS BIT( 1 ) #define FCL_RESEND_MOVEVARS BIT( 1 )
#define FCL_SKIP_NET_MESSAGE BIT( 2 ) #define FCL_SKIP_NET_MESSAGE BIT( 2 )

View File

@@ -328,7 +328,7 @@ static qboolean SV_CheckClientVisiblity( sv_client_t *cl, const byte *mask )
else else
VectorCopy( cl->edict->v.origin, vieworg ); VectorCopy( cl->edict->v.origin, vieworg );
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes ); leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes, sv.worldmodel );
if( CHECKVISBIT( mask, leaf->cluster )) if( CHECKVISBIT( mask, leaf->cluster ))
return true; // visible from player view or camera view return true; // visible from player view or camera view
@@ -342,7 +342,7 @@ static qboolean SV_CheckClientVisiblity( sv_client_t *cl, const byte *mask )
continue; continue;
VectorAdd( view->v.origin, view->v.view_ofs, vieworg ); VectorAdd( view->v.origin, view->v.view_ofs, vieworg );
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes ); leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes, sv.worldmodel );
if( CHECKVISBIT( mask, leaf->cluster )) if( CHECKVISBIT( mask, leaf->cluster ))
return true; // visible from portal camera view return true; // visible from portal camera view
@@ -1732,7 +1732,7 @@ static edict_t* GAME_EXPORT pfnFindClientInPVS( edict_t *pEdict )
VectorAdd( pEdict->v.origin, pEdict->v.view_ofs, view ); VectorAdd( pEdict->v.origin, pEdict->v.view_ofs, view );
} }
leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes ); leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes, sv.worldmodel );
if( CHECKVISBIT( clientpvs, leaf->cluster )) if( CHECKVISBIT( clientpvs, leaf->cluster ))
return pClient; // client which currently in PVS return pClient; // client which currently in PVS
@@ -4291,6 +4291,35 @@ static byte *GAME_EXPORT pfnSetFatPAS( const float *org )
return fatphs; return fatphs;
} }
/*
=============
Mod_HeadnodeVisible
=============
*/
static qboolean Mod_HeadnodeVisible( model_t *mod, mnode_t *node, const byte *visbits, int *lastleaf )
{
if( !node || node->contents == CONTENTS_SOLID )
return false;
if( node->contents < 0 )
{
if( !CHECKVISBIT( visbits, ((mleaf_t *)node)->cluster ))
return false;
if( lastleaf )
*lastleaf = ((mleaf_t *)node)->cluster;
return true;
}
if( Mod_HeadnodeVisible( mod, node_child( node, 0, mod ), visbits, lastleaf ))
return true;
if( Mod_HeadnodeVisible( mod, node_child( node, 1, mod ), visbits, lastleaf ))
return true;
return false;
}
/* /*
============= =============
pfnCheckVisibility pfnCheckVisibility
@@ -4300,6 +4329,7 @@ pfnCheckVisibility
static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset ) static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
{ {
int i, leafnum; int i, leafnum;
qboolean large_leafs = FBitSet( sv.worldmodel->flags, MODEL_QBSP2 );
if( !SV_IsValidEdict( ent )) if( !SV_IsValidEdict( ent ))
return 0; return 0;
@@ -4315,17 +4345,28 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
// check individual leafs // check individual leafs
for( i = 0; i < ent->num_leafs; i++ ) for( i = 0; i < ent->num_leafs; i++ )
{ {
if( CHECKVISBIT( pset, ent->leafnums[i] )) if( large_leafs )
return 1; // visible passed by leaf {
if( CHECKVISBIT( pset, ent->leafnums32[i] ))
return 1; // visible passed by leaf
}
else
{
if( CHECKVISBIT( pset, ent->leafnums16[i] ))
return 1; // visible passed by leaf
}
} }
return 0; return 0;
} }
else else
{ {
for( i = 0; i < MAX_ENT_LEAFS; i++ ) for( i = 0; i < MAX_ENT_LEAFS( large_leafs ); i++ )
{ {
leafnum = ent->leafnums[i]; if( large_leafs )
leafnum = ent->leafnums32[i];
else
leafnum = ent->leafnums16[i];
if( leafnum == -1 ) break; if( leafnum == -1 ) break;
if( CHECKVISBIT( pset, leafnum )) if( CHECKVISBIT( pset, leafnum ))
@@ -4333,11 +4374,15 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
} }
// too many leafs for individual check, go by headnode // too many leafs for individual check, go by headnode
if( !Mod_HeadnodeVisible( &sv.worldmodel->nodes[ent->headnode], pset, &leafnum )) if( !Mod_HeadnodeVisible( sv.worldmodel, &sv.worldmodel->nodes[ent->headnode], pset, &leafnum ))
return 0; return 0;
((edict_t *)ent)->leafnums[ent->num_leafs] = leafnum; if( large_leafs )
((edict_t *)ent)->num_leafs = (ent->num_leafs + 1) % MAX_ENT_LEAFS; ((edict_t *)ent)->leafnums32[ent->num_leafs] = leafnum;
else
((edict_t *)ent)->leafnums16[ent->num_leafs] = leafnum;
((edict_t *)ent)->num_leafs = (ent->num_leafs + 1) % MAX_ENT_LEAFS( large_leafs );
return 2; // visible passed by headnode return 2; // visible passed by headnode
} }

View File

@@ -40,9 +40,8 @@ HULL BOXES
=============================================================================== ===============================================================================
*/ */
static hull_t box_hull; static hull_t box_hull;
static mclipnode_t box_clipnodes[6]; static mplane_t box_planes[6];
static mplane_t box_planes[6];
/* /*
=================== ===================
@@ -54,23 +53,15 @@ can just be stored out and get a proper hull_t structure.
*/ */
static void SV_InitBoxHull( void ) static void SV_InitBoxHull( void )
{ {
int i, side; int i;
box_hull.clipnodes = box_clipnodes; box_hull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
box_hull.planes = box_planes; box_hull.planes = box_planes;
box_hull.firstclipnode = 0; box_hull.firstclipnode = 0;
box_hull.lastclipnode = 5; box_hull.lastclipnode = 5;
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
box_clipnodes[i].planenum = i;
side = i & 1;
box_clipnodes[i].children[side] = CONTENTS_EMPTY;
if( i != 5 ) box_clipnodes[i].children[side^1] = i + 1;
else box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
box_planes[i].type = i>>1; box_planes[i].type = i>>1;
box_planes[i].normal[i>>1] = 1; box_planes[i].normal[i>>1] = 1;
box_planes[i].signbits = 0; box_planes[i].signbits = 0;
@@ -167,6 +158,11 @@ static hull_t *SV_HullForBox( const vec3_t mins, const vec3_t maxs )
box_planes[4].dist = maxs[2]; box_planes[4].dist = maxs[2];
box_planes[5].dist = mins[2]; box_planes[5].dist = mins[2];
if( world.version == QBSP2_VERSION )
box_hull.clipnodes32 = (mclipnode32_t *)box_clipnodes32;
else
box_hull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
return &box_hull; return &box_hull;
} }
@@ -594,7 +590,7 @@ SV_FindTouchedLeafs
=============== ===============
*/ */
static void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode ) static void SV_FindTouchedLeafs( edict_t *ent, model_t *mod, mnode_t *node, int *headnode )
{ {
int sides; int sides;
mleaf_t *leaf; mleaf_t *leaf;
@@ -605,16 +601,19 @@ static void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
// add an efrag if the node is a leaf // add an efrag if the node is a leaf
if( node->contents < 0 ) if( node->contents < 0 )
{ {
if( ent->num_leafs > ( MAX_ENT_LEAFS - 1 )) if( ent->num_leafs > MAX_ENT_LEAFS( FBitSet( mod->flags, MODEL_QBSP2 )))
{ {
// continue counting leafs, // continue counting leafs,
// so we know how many it's overrun // so we know how many it's overrun
ent->num_leafs = (MAX_ENT_LEAFS + 1); ent->num_leafs = (MAX_ENT_LEAFS( FBitSet( mod->flags, MODEL_QBSP2 )) + 1);
} }
else else
{ {
leaf = (mleaf_t *)node; leaf = (mleaf_t *)node;
ent->leafnums[ent->num_leafs] = leaf->cluster; if( FBitSet( mod->flags, MODEL_QBSP2 ))
ent->leafnums32[ent->num_leafs] = leaf->cluster;
else
ent->leafnums16[ent->num_leafs] = leaf->cluster;
ent->num_leafs++; ent->num_leafs++;
} }
return; return;
@@ -624,11 +623,13 @@ static void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
sides = BOX_ON_PLANE_SIDE( ent->v.absmin, ent->v.absmax, node->plane ); sides = BOX_ON_PLANE_SIDE( ent->v.absmin, ent->v.absmax, node->plane );
if(( sides == 3 ) && ( *headnode == -1 )) if(( sides == 3 ) && ( *headnode == -1 ))
*headnode = node - sv.worldmodel->nodes; *headnode = node - mod->nodes;
// recurse down the contacted sides // recurse down the contacted sides
if( sides & 1 ) SV_FindTouchedLeafs( ent, node->children[0], headnode ); if( sides & 1 )
if( sides & 2 ) SV_FindTouchedLeafs( ent, node->children[1], headnode ); SV_FindTouchedLeafs( ent, mod, node_child( node, 0, mod ), headnode );
if( sides & 2 )
SV_FindTouchedLeafs( ent, mod, node_child( node, 1, mod ), headnode );
} }
/* /*
@@ -650,7 +651,7 @@ void GAME_EXPORT SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
if( ent->v.movetype == MOVETYPE_FOLLOW && SV_IsValidEdict( ent->v.aiment )) if( ent->v.movetype == MOVETYPE_FOLLOW && SV_IsValidEdict( ent->v.aiment ))
{ {
memcpy( ent->leafnums, ent->v.aiment->leafnums, sizeof( ent->leafnums )); memcpy( ent->leafnums32, ent->v.aiment->leafnums32, sizeof( ent->leafnums32 ));
ent->num_leafs = ent->v.aiment->num_leafs; ent->num_leafs = ent->v.aiment->num_leafs;
ent->headnode = ent->v.aiment->headnode; ent->headnode = ent->v.aiment->headnode;
} }
@@ -662,11 +663,11 @@ void GAME_EXPORT SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
headnode = -1; headnode = -1;
if( ent->v.modelindex ) if( ent->v.modelindex )
SV_FindTouchedLeafs( ent, sv.worldmodel->nodes, &headnode ); SV_FindTouchedLeafs( ent, sv.worldmodel, sv.worldmodel->nodes, &headnode );
if( ent->num_leafs > MAX_ENT_LEAFS ) if( ent->num_leafs > MAX_ENT_LEAFS( FBitSet( sv.worldmodel->flags, MODEL_QBSP2 )))
{ {
memset( ent->leafnums, -1, sizeof( ent->leafnums )); memset( ent->leafnums32, -1, sizeof( ent->leafnums32 ));
ent->num_leafs = 0; // so we use headnode instead ent->num_leafs = 0; // so we use headnode instead
ent->headnode = headnode; ent->headnode = headnode;
} }
@@ -1518,6 +1519,8 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
float front, back, frac; float front, back, frac;
int i, side; int i, side;
vec3_t mid; vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
// didn't hit anything // didn't hit anything
if( !node || node->contents < 0 ) if( !node || node->contents < 0 )
@@ -1527,25 +1530,29 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
front = PlaneDiff( start, node->plane ); front = PlaneDiff( start, node->plane );
back = PlaneDiff( end, node->plane ); back = PlaneDiff( end, node->plane );
node_children( children, node, model );
side = front < 0.0f; side = front < 0.0f;
if(( back < 0.0f ) == side ) if(( back < 0.0f ) == side )
return SV_RecursiveLightPoint( model, node->children[side], start, end, point_color ); return SV_RecursiveLightPoint( model, children[side], start, end, point_color );
frac = front / ( front - back ); frac = front / ( front - back );
VectorLerp( start, frac, end, mid ); VectorLerp( start, frac, end, mid );
// co down front side // co down front side
if( SV_RecursiveLightPoint( model, node->children[side], start, mid, point_color )) if( SV_RecursiveLightPoint( model, children[side], start, mid, point_color ))
return true; // hit something return true; // hit something
if(( back < 0.0f ) == side ) if(( back < 0.0f ) == side )
return false; // didn't hit anything return false; // didn't hit anything
// check for impact on this node // check for impact on this node
for( i = 0; i < node->numsurfaces; i++ ) numsurfaces = node_numsurfaces( node, model );
firstsurface = node_firstsurface( node, model );
for( i = 0; i < numsurfaces; i++ )
{ {
const msurface_t *surf = &model->surfaces[node->firstsurface + i]; const msurface_t *surf = &model->surfaces[firstsurface + i];
const mextrasurf_t *info = surf->info; const mextrasurf_t *info = surf->info;
int smax, tmax, map, size; int smax, tmax, map, size;
int sample_size; int sample_size;
@@ -1596,7 +1603,7 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
} }
// go down back side // go down back side
return SV_RecursiveLightPoint( model, node->children[!side], mid, end, point_color ); return SV_RecursiveLightPoint( model, children[!side], mid, end, point_color );
} }
/* /*

View File

@@ -670,10 +670,14 @@ static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *dec
// iterate over all surfaces in the node // iterate over all surfaces in the node
msurface_t *surf; msurface_t *surf;
int i; int i;
int firstsurface, numsurfaces;
surf = model->surfaces + node->firstsurface; firstsurface = node_firstsurface( node, model );
numsurfaces = node_numsurfaces( node, model );
for( i = 0; i < node->numsurfaces; i++, surf++ ) surf = model->surfaces + firstsurface;
for( i = 0; i < numsurfaces; i++, surf++ )
{ {
// never apply decals on the water or sky surfaces // never apply decals on the water or sky surfaces
if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY|SURF_CONVEYOR)) if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY|SURF_CONVEYOR))
@@ -695,6 +699,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
{ {
mplane_t *splitplane; mplane_t *splitplane;
float dist; float dist;
mnode_t *children[2];
Assert( node != NULL ); Assert( node != NULL );
@@ -706,6 +711,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
splitplane = node->plane; splitplane = node->plane;
dist = DotProduct( decalinfo->m_Position, splitplane->normal ) - splitplane->dist; dist = DotProduct( decalinfo->m_Position, splitplane->normal ) - splitplane->dist;
node_children( children, node, model );
// This is arbitrarily set to 10 right now. In an ideal world we'd have the // This is arbitrarily set to 10 right now. In an ideal world we'd have the
// exact surface but we don't so, this tells me which planes are "sort of // exact surface but we don't so, this tells me which planes are "sort of
@@ -717,19 +723,19 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
// have a surface normal // have a surface normal
if( dist > decalinfo->m_Size ) if( dist > decalinfo->m_Size )
{ {
R_DecalNode( model, node->children[0], decalinfo ); R_DecalNode( model, children[0], decalinfo );
} }
else if( dist < -decalinfo->m_Size ) else if( dist < -decalinfo->m_Size )
{ {
R_DecalNode( model, node->children[1], decalinfo ); R_DecalNode( model, children[1], decalinfo );
} }
else else
{ {
if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE ) if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE )
R_DecalNodeSurfaces( model, node, decalinfo ); R_DecalNodeSurfaces( model, node, decalinfo );
R_DecalNode( model, node->children[0], decalinfo ); R_DecalNode( model, children[0], decalinfo );
R_DecalNode( model, node->children[1], decalinfo ); R_DecalNode( model, children[1], decalinfo );
} }
} }

View File

@@ -104,27 +104,33 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
float dist; float dist;
msurface_t *surf; msurface_t *surf;
int i; int i;
mnode_t *children[2];
int firstsurface, numsurfaces;
if( !node || node->contents < 0 ) if( !node || node->contents < 0 )
return; return;
dist = PlaneDiff( light->origin, node->plane ); dist = PlaneDiff( light->origin, node->plane );
node_children( children, node, RI.currentmodel );
firstsurface = node_firstsurface( node, RI.currentmodel );
numsurfaces = node_numsurfaces( node, RI.currentmodel );
if( dist > light->radius ) if( dist > light->radius )
{ {
R_MarkLights( light, bit, node->children[0] ); R_MarkLights( light, bit, children[0] );
return; return;
} }
if( dist < -light->radius ) if( dist < -light->radius )
{ {
R_MarkLights( light, bit, node->children[1] ); R_MarkLights( light, bit, children[1] );
return; return;
} }
// mark the polygons // mark the polygons
surf = RI.currentmodel->surfaces + node->firstsurface; surf = RI.currentmodel->surfaces + firstsurface;
for( i = 0; i < node->numsurfaces; i++, surf++ ) for( i = 0; i < numsurfaces; i++, surf++ )
{ {
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius )) if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
continue; // no intersection continue; // no intersection
@@ -137,8 +143,8 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
surf->dlightbits |= bit; surf->dlightbits |= bit;
} }
R_MarkLights( light, bit, node->children[0] ); R_MarkLights( light, bit, children[0] );
R_MarkLights( light, bit, node->children[1] ); R_MarkLights( light, bit, children[1] );
} }
/* /*
@@ -202,6 +208,8 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
mtexinfo_t *tex; mtexinfo_t *tex;
matrix3x4 tbn; matrix3x4 tbn;
vec3_t mid; vec3_t mid;
mnode_t *children[2];
int firstsurface, numsurfaces;
// didn't hit anything // didn't hit anything
if( !node || node->contents < 0 ) if( !node || node->contents < 0 )
@@ -210,13 +218,17 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
return false; return false;
} }
node_children( children, node, model );
firstsurface = node_firstsurface( node, model );
numsurfaces = node_numsurfaces( node, model );
// calculate mid point // calculate mid point
front = PlaneDiff( start, node->plane ); front = PlaneDiff( start, node->plane );
back = PlaneDiff( end, node->plane ); back = PlaneDiff( end, node->plane );
side = front < 0; side = front < 0;
if(( back < 0 ) == side ) if(( back < 0 ) == side )
return R_RecursiveLightPoint( model, node->children[side], p1f, p2f, cv, start, end ); return R_RecursiveLightPoint( model, children[side], p1f, p2f, cv, start, end );
frac = front / ( front - back ); frac = front / ( front - back );
@@ -224,7 +236,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
midf = p1f + ( p2f - p1f ) * frac; midf = p1f + ( p2f - p1f ) * frac;
// co down front side // co down front side
if( R_RecursiveLightPoint( model, node->children[side], p1f, midf, cv, start, mid )) if( R_RecursiveLightPoint( model, children[side], p1f, midf, cv, start, mid ))
return true; // hit something return true; // hit something
if(( back < 0 ) == side ) if(( back < 0 ) == side )
@@ -234,10 +246,10 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
} }
// check for impact on this node // check for impact on this node
surf = model->surfaces + node->firstsurface; surf = model->surfaces + firstsurface;
VectorCopy( mid, g_trace_lightspot ); VectorCopy( mid, g_trace_lightspot );
for( i = 0; i < node->numsurfaces; i++, surf++ ) for( i = 0; i < numsurfaces; i++, surf++ )
{ {
int smax, tmax; int smax, tmax;
@@ -326,7 +338,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
} }
// go down back side // go down back side
return R_RecursiveLightPoint( model, node->children[!side], midf, p2f, cv, mid, end ); return R_RecursiveLightPoint( model, children[!side], midf, p2f, cv, mid, end );
} }
/* /*

View File

@@ -600,6 +600,7 @@ watertexture to grab fog values from it
static gl_texture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down ) static gl_texture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down )
{ {
gl_texture_t *tex = NULL; gl_texture_t *tex = NULL;
mnode_t *children[2];
// assure the initial node is not null // assure the initial node is not null
// we could check it here, but we would rather check it // we could check it here, but we would rather check it
@@ -637,15 +638,17 @@ static gl_texture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mno
// this is a regular node // this is a regular node
// traverse children // traverse children
if( node->children[0] && ( node->children[0] != ignore )) node_children( children, node, WORLDMODEL );
if( children[0] && ( children[0] != ignore ))
{ {
tex = R_RecursiveFindWaterTexture( node->children[0], node, true ); tex = R_RecursiveFindWaterTexture( children[0], node, true );
if( tex ) return tex; if( tex ) return tex;
} }
if( node->children[1] && ( node->children[1] != ignore )) if( children[1] && ( children[1] != ignore ))
{ {
tex = R_RecursiveFindWaterTexture( node->children[1], node, true ); tex = R_RecursiveFindWaterTexture( children[1], node, true );
if( tex ) return tex; if( tex ) return tex;
} }

View File

@@ -125,12 +125,25 @@ static void R_TextureCoord( const vec3_t v, const msurface_t *surf, vec2_t coord
static void R_GetEdgePosition( const model_t *mod, const msurface_t *fa, int i, vec3_t vec ) static void R_GetEdgePosition( const model_t *mod, const msurface_t *fa, int i, vec3_t vec )
{ {
const int lindex = mod->surfedges[fa->firstedge + i]; const int lindex = mod->surfedges[fa->firstedge + i];
const medge_t *pedges = mod->edges;
if( lindex > 0 ) if( FBitSet( mod->flags, MODEL_QBSP2 ))
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec ); {
const medge32_t *pedges = mod->edges32;
if( lindex > 0 )
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec );
else
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec );
}
else else
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec ); {
const medge16_t *pedges = mod->edges16;
if( lindex > 0 )
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec );
else
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec );
}
} }
static void BoundPoly( int numverts, float *verts, vec3_t mins, vec3_t maxs ) static void BoundPoly( int numverts, float *verts, vec3_t mins, vec3_t maxs )
@@ -3306,6 +3319,9 @@ static void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
mleaf_t *pleaf; mleaf_t *pleaf;
int c, side; int c, side;
float dot; float dot;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0: loc0:
if( node->contents == CONTENTS_SOLID ) if( node->contents == CONTENTS_SOLID )
return; // hit a solid leaf return; // hit a solid leaf
@@ -3360,10 +3376,14 @@ loc0:
side = (dot >= 0.0f) ? 0 : 1; side = (dot >= 0.0f) ? 0 : 1;
// recurse down the children, front side first // recurse down the children, front side first
R_RecursiveWorldNode( node->children[side], clipflags ); node_children( children, node, WORLDMODEL );
R_RecursiveWorldNode( children[side], clipflags );
firstsurface = node_firstsurface( node, WORLDMODEL );
numsurfaces = node_numsurfaces( node, WORLDMODEL );
// draw stuff // draw stuff
for( c = node->numsurfaces, surf = WORLDMODEL->surfaces + node->firstsurface; c; c--, surf++ ) for( c = numsurfaces, surf = WORLDMODEL->surfaces + firstsurface; c; c--, surf++ )
{ {
if( R_CullSurface( surf, &RI.frustum, clipflags )) if( R_CullSurface( surf, &RI.frustum, clipflags ))
continue; continue;
@@ -3382,7 +3402,7 @@ loc0:
} }
// recurse down the back side // recurse down the back side
node = node->children[!side]; node = children[!side];
goto loc0; goto loc0;
} }
@@ -3458,6 +3478,9 @@ static void R_DrawWorldTopView( mnode_t *node, uint clipflags )
do do
{ {
mnode_t *children[2];
int numsurfaces, firstsurface;
if( node->contents == CONTENTS_SOLID ) if( node->contents == CONTENTS_SOLID )
return; // hit a solid leaf return; // hit a solid leaf
@@ -3491,7 +3514,10 @@ static void R_DrawWorldTopView( mnode_t *node, uint clipflags )
} }
// draw stuff // draw stuff
for( c = node->numsurfaces, surf = WORLDMODEL->surfaces + node->firstsurface; c; c--, surf++ ) numsurfaces = node_numsurfaces( node, WORLDMODEL );
firstsurface = node_firstsurface( node, WORLDMODEL );
for( c = numsurfaces, surf = WORLDMODEL->surfaces + firstsurface; c; c--, surf++ )
{ {
// don't process the same surface twice // don't process the same surface twice
if( surf->visframe == tr.framecount ) if( surf->visframe == tr.framecount )
@@ -3510,9 +3536,9 @@ static void R_DrawWorldTopView( mnode_t *node, uint clipflags )
} }
// recurse down both children, we don't care the order... // recurse down both children, we don't care the order...
R_DrawWorldTopView( node->children[0], clipflags ); node_children( children, node, WORLDMODEL );
node = node->children[1]; R_DrawWorldTopView( children[0], clipflags );
node = children[1];
} while( node ); } while( node );
} }

View File

@@ -175,7 +175,7 @@ void R_RotateBmodel( void )
R_RecursiveClipBPoly R_RecursiveClipBPoly
================ ================
*/ */
static void R_RecursiveClipBPoly( bedge_t *pedges, mnode_t *pnode, msurface_t *psurf ) static void R_RecursiveClipBPoly( model_t *mod, bedge_t *pedges, mnode_t *pnode, msurface_t *psurf )
{ {
bedge_t *psideedges[2], *pnextedge, *ptedge; bedge_t *psideedges[2], *pnextedge, *ptedge;
int i, side, lastside; int i, side, lastside;
@@ -316,7 +316,7 @@ static void R_RecursiveClipBPoly( bedge_t *pedges, mnode_t *pnode, msurface_t *p
{ {
// draw if we've reached a non-solid leaf, done if all that's left is a // draw if we've reached a non-solid leaf, done if all that's left is a
// solid leaf, and continue down the tree if it's not a leaf // solid leaf, and continue down the tree if it's not a leaf
pn = pnode->children[i]; pn = node_child( pnode, i, mod );
// we're done with this branch if the node or leaf isn't in the PVS // we're done with this branch if the node or leaf isn't in the PVS
if( pn->visframe == tr.visframecount ) if( pn->visframe == tr.visframecount )
@@ -332,8 +332,7 @@ static void R_RecursiveClipBPoly( bedge_t *pedges, mnode_t *pnode, msurface_t *p
} }
else else
{ {
R_RecursiveClipBPoly( psideedges[i], pnode->children[i], R_RecursiveClipBPoly( mod, psideedges[i], pn, psurf );
psurf );
} }
} }
} }
@@ -356,13 +355,13 @@ void R_DrawSolidClippedSubmodelPolygons( model_t *pmodel, mnode_t *topnode )
mplane_t *pplane; mplane_t *pplane;
mvertex_t bverts[MAX_BMODEL_VERTS]; mvertex_t bverts[MAX_BMODEL_VERTS];
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
medge_t *pedge, *pedges; medge16_t *pedge, *pedges;
// FIXME: use bounding-box-based frustum clipping info? // FIXME: use bounding-box-based frustum clipping info?
psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces; numsurfaces = pmodel->nummodelsurfaces;
pedges = pmodel->edges; pedges = pmodel->edges16;
for( i = 0; i < numsurfaces; i++, psurf++ ) for( i = 0; i < numsurfaces; i++, psurf++ )
{ {
@@ -419,7 +418,7 @@ void R_DrawSolidClippedSubmodelPolygons( model_t *pmodel, mnode_t *topnode )
pbedge[j - 1].pnext = NULL; // mark end of edges pbedge[j - 1].pnext = NULL; // mark end of edges
// if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) ) // if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) )
R_RecursiveClipBPoly( pbedge, topnode, psurf ); R_RecursiveClipBPoly( pmodel, pbedge, topnode, psurf );
// else // else
// R_RenderBmodelFace( pbedge, psurf ); // R_RenderBmodelFace( pbedge, psurf );
} }
@@ -566,6 +565,9 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags )
} }
else else
{ {
mnode_t *children[2];
int firstsurface;
// node is just a decision point, so go down the apropriate sides // node is just a decision point, so go down the apropriate sides
// find which side of the node we are on // find which side of the node we are on
@@ -593,14 +595,16 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags )
side = 1; side = 1;
// recurse down the children, front side first // recurse down the children, front side first
R_RecursiveWorldNode( node->children[side], clipflags ); node_children( children, node, WORLDMODEL );
R_RecursiveWorldNode( children[side], clipflags );
// draw stuff // draw stuff
c = node->numsurfaces; c = node_numsurfaces( node, WORLDMODEL );
firstsurface = node_firstsurface( node, WORLDMODEL );
if( c ) if( c )
{ {
surf = WORLDMODEL->surfaces + node->firstsurface; surf = WORLDMODEL->surfaces + firstsurface;
if( dot < -BACKFACE_EPSILON ) if( dot < -BACKFACE_EPSILON )
{ {
@@ -636,7 +640,7 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags )
} }
// recurse down the back side // recurse down the back side
R_RecursiveWorldNode( node->children[!side], clipflags ); R_RecursiveWorldNode( children[!side], clipflags );
} }
} }

View File

@@ -679,23 +679,24 @@ static void R_DecalSurface( msurface_t *surf, decalinfo_t *decalinfo )
static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *decalinfo ) static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
{ {
// iterate over all surfaces in the node // iterate over all surfaces in the node
msurface_t *surf; msurface_t *surf;
int i; int i;
int firstsurface, numsurfaces;
surf = model->surfaces + node->firstsurface; firstsurface = node_firstsurface( node, model );
numsurfaces = node_numsurfaces( node, model );
for( i = 0; i < node->numsurfaces; i++, surf++ ) surf = model->surfaces + firstsurface;
for( i = 0; i < numsurfaces; i++, surf++ )
{ {
// never apply decals on the water or sky surfaces // never apply decals on the water or sky surfaces
if( surf->flags & ( SURF_DRAWTURB | SURF_DRAWSKY | SURF_CONVEYOR )) if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY|SURF_CONVEYOR))
continue; continue;
// we can implement alpha testing without stencil
// if( surf->flags & SURF_TRANSPARENT && !glState.stencilEnabled )
// continue;
R_DecalSurface( surf, decalinfo ); R_DecalSurface( surf, decalinfo );
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -707,6 +708,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
{ {
mplane_t *splitplane; mplane_t *splitplane;
float dist; float dist;
mnode_t *children[2];
Assert( node != NULL ); Assert( node != NULL );
@@ -718,6 +720,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
splitplane = node->plane; splitplane = node->plane;
dist = DotProduct( decalinfo->m_Position, splitplane->normal ) - splitplane->dist; dist = DotProduct( decalinfo->m_Position, splitplane->normal ) - splitplane->dist;
node_children( children, node, model );
// This is arbitrarily set to 10 right now. In an ideal world we'd have the // This is arbitrarily set to 10 right now. In an ideal world we'd have the
// exact surface but we don't so, this tells me which planes are "sort of // exact surface but we don't so, this tells me which planes are "sort of
@@ -729,19 +732,19 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
// have a surface normal // have a surface normal
if( dist > decalinfo->m_Size ) if( dist > decalinfo->m_Size )
{ {
R_DecalNode( model, node->children[0], decalinfo ); R_DecalNode( model, children[0], decalinfo );
} }
else if( dist < -decalinfo->m_Size ) else if( dist < -decalinfo->m_Size )
{ {
R_DecalNode( model, node->children[1], decalinfo ); R_DecalNode( model, children[1], decalinfo );
} }
else else
{ {
if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE ) if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE )
R_DecalNodeSurfaces( model, node, decalinfo ); R_DecalNodeSurfaces( model, node, decalinfo );
R_DecalNode( model, node->children[0], decalinfo ); R_DecalNode( model, children[0], decalinfo );
R_DecalNode( model, node->children[1], decalinfo ); R_DecalNode( model, children[1], decalinfo );
} }
} }

View File

@@ -104,44 +104,50 @@ R_MarkLights
*/ */
void R_MarkLights( dlight_t *light, int bit, mnode_t *node ) void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
{ {
float dist; float dist;
msurface_t *surf; msurface_t *surf;
int i; int i;
mnode_t *children[2];
int firstsurface, numsurfaces;
if( !node || node->contents < 0 ) if( !node || node->contents < 0 )
return; return;
dist = PlaneDiff( light->origin, node->plane ); dist = PlaneDiff( light->origin, node->plane );
node_children( children, node, RI.currentmodel );
firstsurface = node_firstsurface( node, RI.currentmodel );
numsurfaces = node_numsurfaces( node, RI.currentmodel );
if( dist > light->radius ) if( dist > light->radius )
{ {
R_MarkLights( light, bit, node->children[0] ); R_MarkLights( light, bit, children[0] );
return; return;
} }
if( dist < -light->radius ) if( dist < -light->radius )
{ {
R_MarkLights( light, bit, node->children[1] ); R_MarkLights( light, bit, children[1] );
return; return;
} }
// mark the polygons // mark the polygons
surf = RI.currentmodel->surfaces + node->firstsurface; surf = RI.currentmodel->surfaces + firstsurface;
for( i = 0; i < node->numsurfaces; i++, surf++ ) for( i = 0; i < numsurfaces; i++, surf++ )
{ {
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius )) if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
continue; // no intersection continue; // no intersection
if( surf->dlightframe != tr.framecount ) // tr.dlightframecount ) if( surf->dlightframe != tr.dlightframecount )
{ {
surf->dlightbits = 0; surf->dlightbits = 0;
surf->dlightframe = tr.framecount; // tr.dlightframecount; surf->dlightframe = tr.dlightframecount;
} }
surf->dlightbits |= bit; surf->dlightbits |= bit;
} }
R_MarkLights( light, bit, node->children[0] ); R_MarkLights( light, bit, children[0] );
R_MarkLights( light, bit, node->children[1] ); R_MarkLights( light, bit, children[1] );
} }
/* /*
@@ -205,6 +211,8 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
mtexinfo_t *tex; mtexinfo_t *tex;
matrix3x4 tbn; matrix3x4 tbn;
vec3_t mid; vec3_t mid;
mnode_t *children[2];
int firstsurface, numsurfaces;
// didn't hit anything // didn't hit anything
if( !node || node->contents < 0 ) if( !node || node->contents < 0 )
@@ -213,13 +221,17 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
return false; return false;
} }
node_children( children, node, model );
firstsurface = node_firstsurface( node, model );
numsurfaces = node_numsurfaces( node, model );
// calculate mid point // calculate mid point
front = PlaneDiff( start, node->plane ); front = PlaneDiff( start, node->plane );
back = PlaneDiff( end, node->plane ); back = PlaneDiff( end, node->plane );
side = front < 0; side = front < 0;
if(( back < 0 ) == side ) if(( back < 0 ) == side )
return R_RecursiveLightPoint( model, node->children[side], p1f, p2f, cv, start, end ); return R_RecursiveLightPoint( model, children[side], p1f, p2f, cv, start, end );
frac = front / ( front - back ); frac = front / ( front - back );
@@ -227,7 +239,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
midf = p1f + ( p2f - p1f ) * frac; midf = p1f + ( p2f - p1f ) * frac;
// co down front side // co down front side
if( R_RecursiveLightPoint( model, node->children[side], p1f, midf, cv, start, mid )) if( R_RecursiveLightPoint( model, children[side], p1f, midf, cv, start, mid ))
return true; // hit something return true; // hit something
if(( back < 0 ) == side ) if(( back < 0 ) == side )
@@ -237,10 +249,10 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
} }
// check for impact on this node // check for impact on this node
surf = model->surfaces + node->firstsurface; surf = model->surfaces + firstsurface;
VectorCopy( mid, g_trace_lightspot ); VectorCopy( mid, g_trace_lightspot );
for( i = 0; i < node->numsurfaces; i++, surf++ ) for( i = 0; i < numsurfaces; i++, surf++ )
{ {
int smax, tmax; int smax, tmax;
@@ -330,7 +342,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
} }
// go down back side // go down back side
return R_RecursiveLightPoint( model, node->children[!side], midf, p2f, cv, mid, end ); return R_RecursiveLightPoint( model, children[!side], midf, p2f, cv, mid, end );
} }
/* /*

View File

@@ -933,7 +933,7 @@ typedef struct edge_s
unsigned short surfs[2]; unsigned short surfs[2];
struct edge_s *nextremove; struct edge_s *nextremove;
float nearzi; float nearzi;
medge_t *owner; medge16_t *owner;
} edge_t; } edge_t;

View File

@@ -524,6 +524,7 @@ watertexture to grab fog values from it
static image_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down ) static image_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down )
{ {
image_t *tex = NULL; image_t *tex = NULL;
mnode_t *children[2];
// assure the initial node is not null // assure the initial node is not null
// we could check it here, but we would rather check it // we could check it here, but we would rather check it
@@ -561,18 +562,18 @@ static image_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t
// this is a regular node // this is a regular node
// traverse children // traverse children
if( node->children[0] && ( node->children[0] != ignore )) node_children( children, node, WORLDMODEL );
if( children[0] && ( children[0] != ignore ))
{ {
tex = R_RecursiveFindWaterTexture( node->children[0], node, true ); tex = R_RecursiveFindWaterTexture( children[0], node, true );
if( tex ) if( tex ) return tex;
return tex;
} }
if( node->children[1] && ( node->children[1] != ignore )) if( children[1] && ( children[1] != ignore ))
{ {
tex = R_RecursiveFindWaterTexture( node->children[1], node, true ); tex = R_RecursiveFindWaterTexture( children[1], node, true );
if( tex ) if( tex ) return tex;
return tex;
} }
// for down recursion, return immediately // for down recursion, return immediately
@@ -796,9 +797,9 @@ static mnode_t *R_FindTopnode( vec3_t mins, vec3_t maxs )
// not split yet; recurse down the contacted side // not split yet; recurse down the contacted side
if( sides & 1 ) if( sides & 1 )
node = node->children[0]; node = node_child( node, 0, WORLDMODEL );
else else
node = node->children[1]; node = node_child( node, 1, WORLDMODEL );
} }
} }
@@ -1392,6 +1393,12 @@ void GAME_EXPORT R_NewMap( void )
R_ClearDecals(); // clear all level decals R_ClearDecals(); // clear all level decals
R_StudioResetPlayerModels(); R_StudioResetPlayerModels();
if( FBitSet( world->flags, MODEL_QBSP2 ))
{
gEngfuncs.Host_Error( "Sorry, ref_soft can't load maps in BSP2 format.\n" );
return;
}
r_cnumsurfs = sw_maxsurfs.value; r_cnumsurfs = sw_maxsurfs.value;
if( r_cnumsurfs <= MINSURFACES ) if( r_cnumsurfs <= MINSURFACES )

View File

@@ -37,7 +37,7 @@ int c_faceclip; // numbe
clipplane_t *entity_clipplanes; clipplane_t *entity_clipplanes;
clipplane_t world_clipplanes[16]; clipplane_t world_clipplanes[16];
medge_t *r_pedge; medge16_t *r_pedge;
qboolean r_leftclipped, r_rightclipped; qboolean r_leftclipped, r_rightclipped;
static qboolean makeleftedge, makerightedge; static qboolean makeleftedge, makerightedge;
@@ -68,7 +68,7 @@ msurface_t *r_skyfaces;
mplane_t r_skyplanes[6]; mplane_t r_skyplanes[6];
mtexinfo_t r_skytexinfo[6]; mtexinfo_t r_skytexinfo[6];
mvertex_t *r_skyverts; mvertex_t *r_skyverts;
medge_t *r_skyedges; medge16_t *r_skyedges;
int *r_skysurfedges; int *r_skysurfedges;
// I just copied this data from a box map... // I just copied this data from a box map...
@@ -438,7 +438,7 @@ void R_RenderFace( msurface_t *fa, int clipflags )
mplane_t *pplane; mplane_t *pplane;
float distinv; float distinv;
vec3_t p_normal; vec3_t p_normal;
medge_t *pedges, tedge; medge16_t *pedges, tedge;
clipplane_t *pclip; clipplane_t *pclip;
// translucent surfaces are not drawn by the edge renderer // translucent surfaces are not drawn by the edge renderer
@@ -490,7 +490,7 @@ void R_RenderFace( msurface_t *fa, int clipflags )
r_nearzi = 0; r_nearzi = 0;
r_nearzionly = false; r_nearzionly = false;
makeleftedge = makerightedge = false; makeleftedge = makerightedge = false;
pedges = RI.currentmodel->edges; pedges = RI.currentmodel->edges16;
r_lastvertvalid = false; r_lastvertvalid = false;
for( i = 0; i < fa->numedges; i++ ) for( i = 0; i < fa->numedges; i++ )
@@ -560,7 +560,7 @@ void R_RenderFace( msurface_t *fa, int clipflags )
else else
{ {
// it's cached if the cached edge is valid and is owned // it's cached if the cached edge is valid and is owned
// by this medge_t // by this medge16_t
if((((uintptr_t)edge_p - (uintptr_t)r_edges ) if((((uintptr_t)edge_p - (uintptr_t)r_edges )
> r_pedge->cachededgeoffset ) > r_pedge->cachededgeoffset )
&& (((edge_t *)((uintptr_t)r_edges && (((edge_t *)((uintptr_t)r_edges
@@ -651,7 +651,7 @@ void R_RenderBmodelFace( bedge_t *pedges, msurface_t *psurf )
mplane_t *pplane; mplane_t *pplane;
float distinv; float distinv;
vec3_t p_normal; vec3_t p_normal;
medge_t tedge; medge16_t tedge;
clipplane_t *pclip; clipplane_t *pclip;
/*if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) /*if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))

View File

@@ -2,7 +2,7 @@
cd $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE
wget http://libsdl.org/release/SDL2-$SDL_VERSION.dmg -O SDL2.dmg wget https://github.com/libsdl-org/SDL/releases/download/release-$SDL_VERSION/SDL2-$SDL_VERSION.dmg -O SDL2.dmg
hdiutil mount SDL2.dmg hdiutil mount SDL2.dmg
sudo cp -vr /Volumes/SDL2/SDL2.framework /Library/Frameworks sudo cp -vr /Volumes/SDL2/SDL2.framework /Library/Frameworks

View File

@@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
curl http://libsdl.org/release/SDL2-devel-$SDL_VERSION-VC.zip -o SDL2.zip curl -L https://github.com/libsdl-org/SDL/releases/download/release-$SDL_VERSION/SDL2-devel-$SDL_VERSION-VC.zip -o SDL2.zip
unzip -q SDL2.zip unzip -q SDL2.zip
mv SDL2-$SDL_VERSION SDL2_VC mv SDL2-$SDL_VERSION SDL2_VC

View File

@@ -91,7 +91,7 @@ SUBDIRS = [
Subproject('3rdparty/gl-wes-v2', lambda x: not x.env.DEDICATED and x.env.GLWES), Subproject('3rdparty/gl-wes-v2', lambda x: not x.env.DEDICATED and x.env.GLWES),
Subproject('3rdparty/gl4es', lambda x: not x.env.DEDICATED and x.env.GL4ES), Subproject('3rdparty/gl4es', lambda x: not x.env.DEDICATED and x.env.GL4ES),
Subproject('ref/gl', lambda x: not x.env.DEDICATED and (x.env.GL or x.env.NANOGL or x.env.GLWES or x.env.GL4ES)), Subproject('ref/gl', lambda x: not x.env.DEDICATED and (x.env.GL or x.env.NANOGL or x.env.GLWES or x.env.GL4ES)),
Subproject('ref/soft', lambda x: not x.env.DEDICATED and not x.env.SUPPORT_BSP2_FORMAT and x.env.SOFT), Subproject('ref/soft', lambda x: not x.env.DEDICATED and x.env.SOFT),
Subproject('ref/null', lambda x: not x.env.DEDICATED and x.env.NULL), Subproject('ref/null', lambda x: not x.env.DEDICATED and x.env.NULL),
Subproject('3rdparty/bzip2', lambda x: not x.env.DEDICATED and not x.env.HAVE_SYSTEM_BZ2), Subproject('3rdparty/bzip2', lambda x: not x.env.DEDICATED and not x.env.HAVE_SYSTEM_BZ2),
Subproject('3rdparty/opus', lambda x: not x.env.DEDICATED and not x.env.HAVE_SYSTEM_OPUS), Subproject('3rdparty/opus', lambda x: not x.env.DEDICATED and not x.env.HAVE_SYSTEM_OPUS),
@@ -148,9 +148,6 @@ def options(opt):
grp.add_option('--enable-bundled-deps', action = 'store_true', dest = 'BUILD_BUNDLED_DEPS', default = False, grp.add_option('--enable-bundled-deps', action = 'store_true', dest = 'BUILD_BUNDLED_DEPS', default = False,
help = 'prefer to build bundled dependencies (like opus) instead of relying on system provided') help = 'prefer to build bundled dependencies (like opus) instead of relying on system provided')
grp.add_option('--enable-bsp2', action = 'store_true', dest = 'SUPPORT_BSP2_FORMAT', default = False,
help = 'build engine and renderers with BSP2 map support(recommended for Quake, breaks compatibility!) [default: %(default)s]')
grp.add_option('--enable-hl25-extended-structs', action = 'store_true', dest = 'SUPPORT_HL25_EXTENDED_STRUCTS', default = False, grp.add_option('--enable-hl25-extended-structs', action = 'store_true', dest = 'SUPPORT_HL25_EXTENDED_STRUCTS', default = False,
help = 'build engine and renderers with HL25 extended structs compatibility (might be required for some mods) [default: %(default)s]') help = 'build engine and renderers with HL25 extended structs compatibility (might be required for some mods) [default: %(default)s]')
@@ -395,9 +392,7 @@ def configure(conf):
conf.env.ENABLE_XAR = conf.options.ENABLE_XAR conf.env.ENABLE_XAR = conf.options.ENABLE_XAR
conf.env.ENABLE_FUZZER = conf.options.ENABLE_FUZZER conf.env.ENABLE_FUZZER = conf.options.ENABLE_FUZZER
conf.env.DEDICATED = conf.options.DEDICATED conf.env.DEDICATED = conf.options.DEDICATED
conf.env.SUPPORT_BSP2_FORMAT = conf.options.SUPPORT_BSP2_FORMAT
conf.define_cond('SUPPORT_BSP2_FORMAT', conf.options.SUPPORT_BSP2_FORMAT)
conf.define_cond('SUPPORT_HL25_EXTENDED_STRUCTS', conf.options.SUPPORT_HL25_EXTENDED_STRUCTS) conf.define_cond('SUPPORT_HL25_EXTENDED_STRUCTS', conf.options.SUPPORT_HL25_EXTENDED_STRUCTS)
# disable game_launch compiling on platform where it's not needed # disable game_launch compiling on platform where it's not needed