From 47aff9e30bb3929751c74d2c9d20381a610633c2 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Wed, 8 Jan 2025 07:35:22 +0300 Subject: [PATCH] engine: hack mnode_t struct so we can have 24-bit face and children indices to support BSP2 format in runtime --- common/com_model.h | 87 +++++++++++++++++++--- engine/client/cl_efrag.c | 6 +- engine/client/cl_view.c | 6 +- engine/client/ref_common.c | 8 +- engine/client/s_main.c | 2 +- engine/common/mod_bmodel.c | 149 ++++++++++++++++++++++--------------- engine/common/mod_local.h | 3 +- engine/common/pm_surface.c | 38 +++++++--- engine/ref_api.h | 1 + engine/server/sv_game.c | 37 ++++++++- engine/server/sv_world.c | 22 ++++-- ref/gl/gl_decals.c | 18 +++-- ref/gl/gl_rlight.c | 34 ++++++--- ref/gl/gl_rmain.c | 11 ++- ref/gl/gl_rsurf.c | 29 ++++++-- ref/soft/r_bsp.c | 22 +++--- ref/soft/r_decals.c | 29 ++++---- ref/soft/r_light.c | 46 +++++++----- ref/soft/r_main.c | 21 +++--- 19 files changed, 388 insertions(+), 181 deletions(-) diff --git a/common/com_model.h b/common/com_model.h index aea6d3fa..febb214c 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -159,13 +159,31 @@ typedef struct mnode_s // node specific mplane_t *plane; - struct mnode_s *children[2]; -#ifdef SUPPORT_BSP2_FORMAT - int firstsurface; - int numsurfaces; + +#if !XASH_64BIT + union + { + 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 - unsigned short firstsurface; - unsigned short numsurfaces; + // in 64-bit ABI this struct has 4 more bytes of padding, let's use it! + struct mnode_s *children_[2]; + unsigned short firstsurface_0; + unsigned short numsurfaces_0; + unsigned short firstsurface_1; + unsigned short numsurfaces_1; #endif } mnode_t; @@ -206,7 +224,6 @@ typedef struct mleaf_s int nummarksurfaces; int cluster; // helper to acess to uncompressed visdata byte ambient_sound_level[NUM_AMBIENTS]; - } mleaf_t; // surface extradata @@ -566,16 +583,68 @@ typedef struct #define ANIM_CYCLE 2 #define MOD_FRAMES 20 - - #define MAX_DEMOS 32 #define MAX_MOVIES 8 #define MAX_CDTRACKS 32 #define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client) #define MAX_REQUESTS 64 +STATIC_CHECK_SIZEOF( mnode_t, 52, 72 ); STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 ); STATIC_CHECK_SIZEOF( decal_t, 60, 88 ); 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 diff --git a/engine/client/cl_efrag.c b/engine/client/cl_efrag.c index 7806ad5a..4a9f4602 100644 --- a/engine/client/cl_efrag.c +++ b/engine/client/cl_efrag.c @@ -127,8 +127,10 @@ static void R_SplitEntityOnNode( mnode_t *node ) } // recurse down the contacted sides - if( sides & 1 ) R_SplitEntityOnNode( node->children[0] ); - if( sides & 2 ) R_SplitEntityOnNode( node->children[1] ); + if( sides & 1 ) + R_SplitEntityOnNode( node_child( node, 0, cl.worldmodel )); + if( sides & 2 ) + R_SplitEntityOnNode( node_child( node, 1, cl.worldmodel )); } /* diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index e3b8b21d..cc2bb26d 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -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_ShowTree_r( node->children[1], 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, 1, cl.worldmodel ), 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--; } @@ -482,7 +482,7 @@ static void R_ShowTree( void ) return; 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 ); diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c index ac79983c..fc63027e 100644 --- a/engine/client/ref_common.c +++ b/engine/client/ref_common.c @@ -300,6 +300,12 @@ static qboolean R_Init_Video_( const int 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 = { pfnEngineGetParm, @@ -340,7 +346,7 @@ static const ref_api_t gEngfuncs = Mod_SampleSizeForFace, Mod_BoxVisible, - Mod_PointInLeaf, + pfnMod_PointInLeaf, R_DrawWorldHull, R_DrawModelHull, diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 1fbf0a7a..a7c256ac 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -996,7 +996,7 @@ static void S_UpdateAmbientSounds( void ) // calc ambient sound levels 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 ) { diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index a5261928..6da7d06c 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -856,7 +856,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 ); @@ -864,7 +864,7 @@ mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node ) { if( node->contents < 0 ) return (mleaf_t *)node; - node = node->children[PlaneDiff( p, node->plane ) <= 0]; + node = node_child( node, PlaneDiff( p, node->plane ) <= 0, mod ); } // never reached @@ -885,7 +885,7 @@ byte *Mod_GetPVSForPoint( const vec3_t p ) ASSERT( worldmodel != NULL ); - leaf = Mod_PointInLeaf( p, worldmodel->nodes ); + leaf = Mod_PointInLeaf( p, worldmodel->nodes, worldmodel ); if( leaf && leaf->cluster >= 0 ) return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes ); @@ -905,14 +905,14 @@ static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *v float d = PlaneDiff( org, node->plane ); if( d > radius ) - node = node->children[0]; + node = node_child( node, 0, worldmodel ); else if( d < -radius ) - node = node->children[1]; + node = node_child( node, 1, worldmodel ); else { // go down both sides - Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node->children[0], phs ); - node = node->children[1]; + Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node_child( node, 0, worldmodel ), phs ); + node = node_child( node, 1, worldmodel ); } } @@ -950,7 +950,7 @@ int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, q ASSERT( worldmodel != NULL ); - leaf = Mod_PointInLeaf( org, worldmodel->nodes ); + leaf = Mod_PointInLeaf( org, worldmodel->nodes, worldmodel ); bytes = Q_min( bytes, visbytes ); // enable full visibility for some reasons @@ -1009,20 +1009,16 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node ) sides = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, node->plane ); if( sides == 1 ) - { - node = node->children[0]; - } + node = node_child( node, 0, worldmodel ); else if( sides == 2 ) - { - node = node->children[1]; - } + node = node_child( node, 1, worldmodel ); else { // go down both if( ll->topnode == -1 ) ll->topnode = node - worldmodel->nodes; - Mod_BoxLeafnums_r( ll, node->children[0] ); - node = node->children[1]; + Mod_BoxLeafnums_r( ll, node_child( node, 0, worldmodel )); + node = node_child( node, 1, worldmodel ); } } } @@ -1079,35 +1075,6 @@ qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbi 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 @@ -1562,13 +1529,15 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmode 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; - if( node->contents < 0 ) return; // it's leaf - Mod_SetParent( node->children[0], node ); - Mod_SetParent( node->children[1], node ); + if( node->contents < 0 ) + return; // it's leaf + + Mod_SetParent( mod, node_child( node, 0, mod ), node ); + Mod_SetParent( mod, node_child( node, 1, mod ), node ); } /* @@ -1686,11 +1655,12 @@ static void Mod_MakeHull0( model_t *mod, const dbspmodel_t *bmod ) for( j = 0; j < 2; j++ ) { - mnode_t *child = in->children[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 + out->children[j] = child - mod->nodes; } } } @@ -1709,11 +1679,12 @@ static void Mod_MakeHull0( model_t *mod, const dbspmodel_t *bmod ) for( j = 0; j < 2; j++ ) { - mnode_t *child = in->children[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 + out->children[j] = child - mod->nodes; } } } @@ -1848,6 +1819,7 @@ for embedded submodels static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod ) { qboolean colored = false; + qboolean qbsp2 = false; poolhandle_t mempool; char *ents; dmodel_t *bm; @@ -1859,6 +1831,9 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod ) if( FBitSet( mod->flags, MODEL_COLORED_LIGHTING )) colored = true; + if( FBitSet( mod->flags, MODEL_QBSP2 )) + qbsp2 = true; + mod->numframes = 2; // regular and alternate animation // set up the submodels @@ -1892,6 +1867,7 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod ) // this bit will be shared between all the submodels include worldmodel if( colored ) SetBits( mod->flags, MODEL_COLORED_LIGHTING ); + if( qbsp2 ) SetBits( mod->flags, MODEL_QBSP2 ); if( i != 0 ) { @@ -3075,16 +3051,62 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod ) 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; out->plane = mod->planes + p; - out->firstsurface = in->firstface; - out->numsurfaces = in->numfaces; + out->firstsurface_0 = in->firstface & 0xFFFF; + out->numsurfaces_0 = in->numfaces & 0xFFFF; + + out->firstsurface_1 = in->firstface >> 16; + out->numsurfaces_1 = in->numfaces >> 16; for( j = 0; j < 2; j++ ) { p = in->children[j]; - if( p >= 0 ) out->children[j] = mod->nodes + p; - else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p )); +#if XASH_64BIT + 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 @@ -3099,20 +3121,20 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod ) p = in->planenum; out->plane = mod->planes + p; - out->firstsurface = in->firstface; - out->numsurfaces = in->numfaces; + out->firstsurface_0 = in->firstface; + out->numsurfaces_0 = in->numfaces; for( j = 0; j < 2; j++ ) { p = in->children[j]; - if( p >= 0 ) out->children[j] = mod->nodes + p; - 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 )); } } } // sets nodes and leafs - Mod_SetParent( mod->nodes, NULL ); + Mod_SetParent( mod, mod->nodes, NULL ); } /* @@ -3601,6 +3623,9 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea // everything else srclumps[0].lumpnumber = LUMP_ENTITIES; srclumps[1].lumpnumber = LUMP_PLANES; + + if( header->version == QBSP2_VERSION ) + SetBits( mod->flags, MODEL_QBSP2 ); break; default: Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, header->version, HLBSP_VERSION ); diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 17bf52f2..b5dbef42 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -167,13 +167,12 @@ void Mod_LoadAliasModel( 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_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 ); 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_ReadLump( 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 ); byte *Mod_GetPVSForPoint( const vec3_t p ); void Mod_UnloadBrushModel( model_t *mod ); diff --git a/engine/common/pm_surface.c b/engine/common/pm_surface.c index c9d7701f..5ae4b2d1 100644 --- a/engine/common/pm_surface.c +++ b/engine/common/pm_surface.c @@ -112,6 +112,9 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_ int i, side; msurface_t *surf; vec3_t mid; + mnode_t *children[2]; + int numsurfaces, firstsurface; + loc0: if( node->contents < 0 ) return NULL; @@ -119,15 +122,17 @@ loc0: t1 = PlaneDiff( p1, node->plane ); t2 = PlaneDiff( p2, node->plane ); + node_children( children, node, mod ); + if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON ) { - node = node->children[0]; + node = children[0]; goto loc0; } if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON ) { - node = node->children[1]; + node = children[1]; goto loc0; } @@ -137,13 +142,15 @@ loc0: 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; // 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; mfacebevel_t *fb = info->bevel; int j, contents; @@ -172,7 +179,7 @@ loc0: 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; int i, r, side; vec3_t mid; + mnode_t *children[2]; + int numsurfaces, firstsurface; + loc0: if( node->contents < 0 ) { @@ -242,15 +252,17 @@ loc0: front = PlaneDiff( start, node->plane ); back = PlaneDiff( stop, node->plane ); + node_children( children, node, mod ); + if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON ) { - node = node->children[0]; + node = children[0]; goto loc0; } if( front < FRAC_EPSILON && back < FRAC_EPSILON ) { - node = node->children[1]; + node = children[1]; goto loc0; } @@ -261,7 +273,7 @@ loc0: VectorLerp( start, frac, stop, mid ); 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 ) { @@ -272,9 +284,11 @@ loc0: } // 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; mfacebevel_t *fb = info->bevel; int j, contents; @@ -308,7 +322,7 @@ loc0: 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 ) diff --git a/engine/ref_api.h b/engine/ref_api.h index b68a2370..b9d865a6 100644 --- a/engine/ref_api.h +++ b/engine/ref_api.h @@ -80,6 +80,7 @@ GNU General Public License for more details. #define MODEL_LIQUID BIT( 2 ) // model has only point hull #define MODEL_TRANSPARENT BIT( 3 ) // have transparent surfaces #define MODEL_COLORED_LIGHTING BIT( 4 ) // lightmaps stored as RGB + #define MODEL_WORLD BIT( 29 ) // it's a worldmodel #define MODEL_CLIENT BIT( 30 ) // client sprite diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 0b1c46f0..06e0431a 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -328,7 +328,7 @@ static qboolean SV_CheckClientVisiblity( sv_client_t *cl, const byte *mask ) else 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 )) 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; 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 )) 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 ); } - leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes ); + leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes, sv.worldmodel ); if( CHECKVISBIT( clientpvs, leaf->cluster )) return pClient; // client which currently in PVS @@ -4291,6 +4291,35 @@ static byte *GAME_EXPORT pfnSetFatPAS( const float *org ) 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 @@ -4333,7 +4362,7 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset ) } // 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; ((edict_t *)ent)->leafnums[ent->num_leafs] = leafnum; diff --git a/engine/server/sv_world.c b/engine/server/sv_world.c index 8e4ff22a..1690997e 100644 --- a/engine/server/sv_world.c +++ b/engine/server/sv_world.c @@ -644,8 +644,10 @@ static void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode ) *headnode = node - sv.worldmodel->nodes; // recurse down the contacted sides - if( sides & 1 ) SV_FindTouchedLeafs( ent, node->children[0], headnode ); - if( sides & 2 ) SV_FindTouchedLeafs( ent, node->children[1], headnode ); + if( sides & 1 ) + SV_FindTouchedLeafs( ent, node_child( node, 0, sv.worldmodel ), headnode ); + if( sides & 2 ) + SV_FindTouchedLeafs( ent, node_child( node, 1, sv.worldmodel ), headnode ); } /* @@ -1535,6 +1537,8 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec float front, back, frac; int i, side; vec3_t mid; + mnode_t *children[2]; + int numsurfaces, firstsurface; // didn't hit anything if( !node || node->contents < 0 ) @@ -1544,25 +1548,29 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec front = PlaneDiff( start, node->plane ); back = PlaneDiff( end, node->plane ); + node_children( children, node, model ); + side = front < 0.0f; 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 ); VectorLerp( start, frac, end, mid ); // 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 if(( back < 0.0f ) == side ) return false; // didn't hit anything // 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; int smax, tmax, map, size; int sample_size; @@ -1613,7 +1621,7 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec } // 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 ); } /* diff --git a/ref/gl/gl_decals.c b/ref/gl/gl_decals.c index d1695597..deaae786 100644 --- a/ref/gl/gl_decals.c +++ b/ref/gl/gl_decals.c @@ -670,10 +670,14 @@ static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *dec // iterate over all surfaces in the node msurface_t *surf; 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 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; float dist; + mnode_t *children[2]; Assert( node != NULL ); @@ -706,6 +711,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo ) splitplane = node->plane; 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 // 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 if( dist > decalinfo->m_Size ) { - R_DecalNode( model, node->children[0], decalinfo ); + R_DecalNode( model, children[0], decalinfo ); } else if( dist < -decalinfo->m_Size ) { - R_DecalNode( model, node->children[1], decalinfo ); + R_DecalNode( model, children[1], decalinfo ); } else { if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE ) R_DecalNodeSurfaces( model, node, decalinfo ); - R_DecalNode( model, node->children[0], decalinfo ); - R_DecalNode( model, node->children[1], decalinfo ); + R_DecalNode( model, children[0], decalinfo ); + R_DecalNode( model, children[1], decalinfo ); } } diff --git a/ref/gl/gl_rlight.c b/ref/gl/gl_rlight.c index 8ba5da3e..40c08250 100644 --- a/ref/gl/gl_rlight.c +++ b/ref/gl/gl_rlight.c @@ -104,27 +104,33 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node ) float dist; msurface_t *surf; int i; + mnode_t *children[2]; + int firstsurface, numsurfaces; if( !node || node->contents < 0 ) return; 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 ) { - R_MarkLights( light, bit, node->children[0] ); + R_MarkLights( light, bit, children[0] ); return; } if( dist < -light->radius ) { - R_MarkLights( light, bit, node->children[1] ); + R_MarkLights( light, bit, children[1] ); return; } // 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 )) continue; // no intersection @@ -137,8 +143,8 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node ) surf->dlightbits |= bit; } - R_MarkLights( light, bit, node->children[0] ); - R_MarkLights( light, bit, node->children[1] ); + R_MarkLights( light, bit, children[0] ); + 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; matrix3x4 tbn; vec3_t mid; + mnode_t *children[2]; + int firstsurface, numsurfaces; // didn't hit anything if( !node || node->contents < 0 ) @@ -210,13 +218,17 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, return false; } + node_children( children, node, model ); + firstsurface = node_firstsurface( node, model ); + numsurfaces = node_numsurfaces( node, model ); + // calculate mid point front = PlaneDiff( start, node->plane ); back = PlaneDiff( end, node->plane ); side = front < 0; 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 ); @@ -224,7 +236,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, midf = p1f + ( p2f - p1f ) * frac; // 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 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 - surf = model->surfaces + node->firstsurface; + surf = model->surfaces + firstsurface; VectorCopy( mid, g_trace_lightspot ); - for( i = 0; i < node->numsurfaces; i++, surf++ ) + for( i = 0; i < numsurfaces; i++, surf++ ) { int smax, tmax; @@ -326,7 +338,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, } // 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 ); } /* diff --git a/ref/gl/gl_rmain.c b/ref/gl/gl_rmain.c index 1a307233..d05887d3 100644 --- a/ref/gl/gl_rmain.c +++ b/ref/gl/gl_rmain.c @@ -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 ) { gl_texture_t *tex = NULL; + mnode_t *children[2]; // assure the initial node is not null // 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 // 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( 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; } diff --git a/ref/gl/gl_rsurf.c b/ref/gl/gl_rsurf.c index 20ea5dd8..8ebbc130 100644 --- a/ref/gl/gl_rsurf.c +++ b/ref/gl/gl_rsurf.c @@ -126,7 +126,7 @@ static void R_GetEdgePosition( const model_t *mod, const msurface_t *fa, int i, { const int lindex = mod->surfedges[fa->firstedge + i]; - if( tr.world->version == QBSP2_VERSION ) + if( FBitSet( mod->flags, MODEL_QBSP2 )) { const medge32_t *pedges = mod->edges32; @@ -3319,6 +3319,9 @@ static void R_RecursiveWorldNode( mnode_t *node, uint clipflags ) mleaf_t *pleaf; int c, side; float dot; + mnode_t *children[2]; + int numsurfaces, firstsurface; + loc0: if( node->contents == CONTENTS_SOLID ) return; // hit a solid leaf @@ -3373,10 +3376,14 @@ loc0: side = (dot >= 0.0f) ? 0 : 1; // 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 - 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 )) continue; @@ -3395,7 +3402,7 @@ loc0: } // recurse down the back side - node = node->children[!side]; + node = children[!side]; goto loc0; } @@ -3471,6 +3478,9 @@ static void R_DrawWorldTopView( mnode_t *node, uint clipflags ) do { + mnode_t *children[2]; + int numsurfaces, firstsurface; + if( node->contents == CONTENTS_SOLID ) return; // hit a solid leaf @@ -3504,7 +3514,10 @@ static void R_DrawWorldTopView( mnode_t *node, uint clipflags ) } // 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 if( surf->visframe == tr.framecount ) @@ -3523,9 +3536,9 @@ static void R_DrawWorldTopView( mnode_t *node, uint clipflags ) } // recurse down both children, we don't care the order... - R_DrawWorldTopView( node->children[0], clipflags ); - node = node->children[1]; - + node_children( children, node, WORLDMODEL ); + R_DrawWorldTopView( children[0], clipflags ); + node = children[1]; } while( node ); } diff --git a/ref/soft/r_bsp.c b/ref/soft/r_bsp.c index c3f649de..074f7e19 100644 --- a/ref/soft/r_bsp.c +++ b/ref/soft/r_bsp.c @@ -175,7 +175,7 @@ void R_RotateBmodel( void ) 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; 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 // 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 if( pn->visframe == tr.visframecount ) @@ -332,8 +332,7 @@ static void R_RecursiveClipBPoly( bedge_t *pedges, mnode_t *pnode, msurface_t *p } else { - R_RecursiveClipBPoly( psideedges[i], pnode->children[i], - psurf ); + R_RecursiveClipBPoly( mod, psideedges[i], pn, psurf ); } } } @@ -419,7 +418,7 @@ void R_DrawSolidClippedSubmodelPolygons( model_t *pmodel, mnode_t *topnode ) pbedge[j - 1].pnext = NULL; // mark end of edges // if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) ) - R_RecursiveClipBPoly( pbedge, topnode, psurf ); + R_RecursiveClipBPoly( pmodel, pbedge, topnode, psurf ); // else // R_RenderBmodelFace( pbedge, psurf ); } @@ -566,6 +565,9 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags ) } else { + mnode_t *children[2]; + int firstsurface; + // node is just a decision point, so go down the apropriate sides // find which side of the node we are on @@ -593,14 +595,16 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags ) side = 1; // 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 - c = node->numsurfaces; + c = node_numsurfaces( node, WORLDMODEL ); + firstsurface = node_firstsurface( node, WORLDMODEL ); if( c ) { - surf = WORLDMODEL->surfaces + node->firstsurface; + surf = WORLDMODEL->surfaces + firstsurface; if( dot < -BACKFACE_EPSILON ) { @@ -636,7 +640,7 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags ) } // recurse down the back side - R_RecursiveWorldNode( node->children[!side], clipflags ); + R_RecursiveWorldNode( children[!side], clipflags ); } } diff --git a/ref/soft/r_decals.c b/ref/soft/r_decals.c index e853a23f..7877a153 100644 --- a/ref/soft/r_decals.c +++ b/ref/soft/r_decals.c @@ -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 ) { // iterate over all surfaces in the node - msurface_t *surf; - int i; + msurface_t *surf; + 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 - if( surf->flags & ( SURF_DRAWTURB | SURF_DRAWSKY | SURF_CONVEYOR )) + if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY|SURF_CONVEYOR)) continue; - // we can implement alpha testing without stencil - // if( surf->flags & SURF_TRANSPARENT && !glState.stencilEnabled ) - // continue; - R_DecalSurface( surf, decalinfo ); } + } // ----------------------------------------------------------------------------- @@ -707,6 +708,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo ) { mplane_t *splitplane; float dist; + mnode_t *children[2]; Assert( node != NULL ); @@ -718,6 +720,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo ) splitplane = node->plane; 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 // 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 if( dist > decalinfo->m_Size ) { - R_DecalNode( model, node->children[0], decalinfo ); + R_DecalNode( model, children[0], decalinfo ); } else if( dist < -decalinfo->m_Size ) { - R_DecalNode( model, node->children[1], decalinfo ); + R_DecalNode( model, children[1], decalinfo ); } else { if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE ) R_DecalNodeSurfaces( model, node, decalinfo ); - R_DecalNode( model, node->children[0], decalinfo ); - R_DecalNode( model, node->children[1], decalinfo ); + R_DecalNode( model, children[0], decalinfo ); + R_DecalNode( model, children[1], decalinfo ); } } diff --git a/ref/soft/r_light.c b/ref/soft/r_light.c index 1f115846..3d6892d7 100644 --- a/ref/soft/r_light.c +++ b/ref/soft/r_light.c @@ -104,44 +104,50 @@ R_MarkLights */ void R_MarkLights( dlight_t *light, int bit, mnode_t *node ) { - float dist; - msurface_t *surf; - int i; + float dist; + msurface_t *surf; + int i; + mnode_t *children[2]; + int firstsurface, numsurfaces; if( !node || node->contents < 0 ) return; 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 ) { - R_MarkLights( light, bit, node->children[0] ); + R_MarkLights( light, bit, children[0] ); return; } if( dist < -light->radius ) { - R_MarkLights( light, bit, node->children[1] ); + R_MarkLights( light, bit, children[1] ); return; } // 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 )) - continue; // no intersection + continue; // no intersection - if( surf->dlightframe != tr.framecount ) // tr.dlightframecount ) + if( surf->dlightframe != tr.dlightframecount ) { surf->dlightbits = 0; - surf->dlightframe = tr.framecount; // tr.dlightframecount; + surf->dlightframe = tr.dlightframecount; } surf->dlightbits |= bit; } - R_MarkLights( light, bit, node->children[0] ); - R_MarkLights( light, bit, node->children[1] ); + R_MarkLights( light, bit, children[0] ); + 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; matrix3x4 tbn; vec3_t mid; + mnode_t *children[2]; + int firstsurface, numsurfaces; // didn't hit anything if( !node || node->contents < 0 ) @@ -213,13 +221,17 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, return false; } + node_children( children, node, model ); + firstsurface = node_firstsurface( node, model ); + numsurfaces = node_numsurfaces( node, model ); + // calculate mid point front = PlaneDiff( start, node->plane ); back = PlaneDiff( end, node->plane ); side = front < 0; 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 ); @@ -227,7 +239,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, midf = p1f + ( p2f - p1f ) * frac; // 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 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 - surf = model->surfaces + node->firstsurface; + surf = model->surfaces + firstsurface; VectorCopy( mid, g_trace_lightspot ); - for( i = 0; i < node->numsurfaces; i++, surf++ ) + for( i = 0; i < numsurfaces; i++, surf++ ) { int smax, tmax; @@ -330,7 +342,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, } // 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 ); } /* diff --git a/ref/soft/r_main.c b/ref/soft/r_main.c index dd1c6c3f..3ae1ba06 100644 --- a/ref/soft/r_main.c +++ b/ref/soft/r_main.c @@ -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 ) { image_t *tex = NULL; + mnode_t *children[2]; // assure the initial node is not null // 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 // 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 ); - if( tex ) - return tex; + tex = R_RecursiveFindWaterTexture( children[0], node, true ); + 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 ); - if( tex ) - return tex; + tex = R_RecursiveFindWaterTexture( children[1], node, true ); + if( tex ) return tex; } // 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 if( sides & 1 ) - node = node->children[0]; + node = node_child( node, 0, WORLDMODEL ); else - node = node->children[1]; + node = node_child( node, 1, WORLDMODEL ); } }