diff --git a/common/bspfile.h b/common/bspfile.h index be6642abc8..a9c79c6ab2 100644 --- a/common/bspfile.h +++ b/common/bspfile.h @@ -16,8 +16,6 @@ GNU General Public License for more details. #ifndef 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 // 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_ENTSTRING 0x200000 // 2 Mb should be enough #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_FACES 262144 // 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_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo diff --git a/common/com_model.h b/common/com_model.h index 550f3a0733..febb214c0f 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -60,26 +60,29 @@ typedef struct vec3_t position; } mvertex_t; -typedef struct +typedef struct mclipnode32_s { - int planenum; -#ifdef SUPPORT_BSP2_FORMAT - int children[2]; // negative numbers are contents -#else - short children[2]; // negative numbers are contents -#endif -} mclipnode_t; + int planenum; + int children[2]; // negative numbers are contents +} mclipnode32_t; + +typedef struct mclipnode16_s +{ + int planenum; + short children[2]; // negative numbers are contents +} mclipnode16_t; // size is matched but representation is not -typedef struct +typedef struct medge32_s { -#ifdef SUPPORT_BSP2_FORMAT unsigned int v[2]; -#else +} medge32_t; + +typedef struct medge16_s +{ unsigned short v[2]; unsigned int cachededgeoffset; -#endif -} medge_t; +} medge16_t; typedef struct texture_s { @@ -156,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; @@ -203,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 @@ -291,7 +311,11 @@ struct msurface_s typedef struct hull_s { - mclipnode_t *clipnodes; + union + { + mclipnode16_t *clipnodes16; + mclipnode32_t *clipnodes32; + }; mplane_t *planes; int firstclipnode; int lastclipnode; @@ -341,7 +365,12 @@ typedef struct model_s mvertex_t *vertexes; int numedges; - medge_t *edges; + union + { + medge16_t *edges16; + medge32_t *edges32; + }; + int numnodes; mnode_t *nodes; @@ -356,7 +385,11 @@ typedef struct model_s int *surfedges; int numclipnodes; - mclipnode_t *clipnodes; + union + { + mclipnode16_t *clipnodes16; + mclipnode32_t *clipnodes32; + }; int nummarksurfaces; msurface_t **marksurfaces; @@ -550,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 7806ad5a3e..4a9f46026c 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_render.c b/engine/client/cl_render.c index 400ed0fbec..8bb2721ed3 100644 --- a/engine/client/cl_render.c +++ b/engine/client/cl_render.c @@ -138,10 +138,7 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe switch( parm ) { case PARM_BSP2_SUPPORTED: -#ifdef SUPPORT_BSP2_FORMAT return 1; -#endif - return 0; case PARAM_GAMEPAUSED: return cl.paused; case PARM_CLIENT_INGAME: diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index e3b8b21d6b..cc2bb26df6 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/mod_dbghulls.c b/engine/client/mod_dbghulls.c index 65a1631055..6db4b46172 100644 --- a/engine/client/mod_dbghulls.c +++ b/engine/client/mod_dbghulls.c @@ -470,16 +470,16 @@ static void winding_split( winding_t *in, const mplane_t *split, winding_t **pfr * This is a stack of the clipnodes we have traversed * "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 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 ) Host_Error( "node stack overflow\n" ); - node_stack[node_stack_depth] = node; + node_stack[node_stack_depth] = nodenum; side_stack[node_stack_depth] = side; 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; + 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( node, side ); - hull_windings_r( hull, child, polys, model ); + push_node( nodenum, side ); + hull_windings_r( hull, childnum, polys, model ); pop_node(); } else { - switch( node->children[side] ) + switch( childnum ) { case CONTENTS_EMPTY: case CONTENTS_WATER: @@ -542,20 +547,25 @@ static void do_hull_recursion( hull_t *hull, mclipnode_t *node, int side, hullno } break; default: - Host_Error( "bad contents: %i\n", node->children[side] ); + Host_Error( "bad contents: %i\n", childnum ); 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 backlist = LIST_HEAD_INIT( backlist ); winding_t *w, *next, *front, *back; 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 ) { // 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++ ) { - 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 ); } @@ -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" ); } - do_hull_recursion( hull, node, 0, &frontlist, model ); - do_hull_recursion( hull, node, 1, &backlist, model ); + do_hull_recursion( hull, nodenum, 0, &frontlist, model ); + do_hull_recursion( hull, nodenum, 1, &backlist, 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 ) { - hull_windings_r( hull, hull->clipnodes + hull->firstclipnode, &head, model ); + hull_windings_r( hull, hull->firstclipnode, &head, model ); remove_paired_polys( model ); } Con_Reportf( "%i hull polys\n", model->num_polys ); diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c index ac79983ca2..fc63027e29 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 1fbf0a7ac4..a7c256acb3 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/com_strings.h b/engine/common/com_strings.h index d5b05b5cbc..d96141173a 100644 --- a/engine/common/com_strings.h +++ b/engine/common/com_strings.h @@ -72,8 +72,6 @@ GNU General Public License for more details. #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 XASH_ENGINE_NAME "Xash3D FWGS" diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index ac762533f7..9fd4bf3e82 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -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 ); @@ -864,7 +893,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 +914,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 +934,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 +979,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 +1038,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 +1104,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 @@ -1264,22 +1260,35 @@ Mod_GetFaceContents 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; - medge_t *edge; - - lindex = mod->surfedges[surfedge]; + int lindex = mod->surfedges[surfedge]; - if( lindex > 0 ) + if( bmod->version == QBSP2_VERSION ) { - edge = &mod->edges[lindex]; - return &mod->vertexes[edge->v[0]]; + if( lindex > 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 { - edge = &mod->edges[-lindex]; - return &mod->vertexes[edge->v[1]]; + if( lindex > 0 ) + { + 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[] ================= */ -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 // 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 ) Host_Error( "%s: bad edge\n", __func__ ); - if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]]; - else v = &mod->vertexes[mod->edges[-e].v[1]]; + if( bmod->version == QBSP2_VERSION ) + { + 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++ ) { @@ -1446,7 +1463,7 @@ Mod_CalcSurfaceBounds 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; mvertex_t *v; @@ -1460,8 +1477,16 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf ) if( e >= mod->numedges || e <= -mod->numedges ) Host_Error( "%s: bad edge\n", __func__ ); - if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]]; - else v = &mod->vertexes[mod->edges[-e].v[1]]; + if( bmod->version == QBSP2_VERSION ) + { + 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 ); } @@ -1473,7 +1498,7 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf ) 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; byte *facebevel; @@ -1506,8 +1531,8 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf ) { mplane_t *dest = &fb->edges[i]; - v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i ); - v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges ); + v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod ); + v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges, bmod ); VectorSubtract( v1->position, v0->position, edgevec ); CrossProduct( faceNormal, edgevec, dest->normal ); VectorNormalize( dest->normal ); @@ -1521,7 +1546,7 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf ) // compute face radius 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 ); radius = DotProduct( delta, delta ); fb->radius = Q_max( radius, fb->radius ); @@ -1533,13 +1558,15 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf ) 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 ); } /* @@ -1547,7 +1574,7 @@ static void Mod_SetParent( mnode_t *node, mnode_t *parent ) 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? 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" ); hull->lastclipnode++; - CountClipNodes_r( src, hull, src[nodenum].children[0] ); - CountClipNodes_r( src, hull, src[nodenum].children[1] ); + CountClipNodes16_r( src, hull, src[nodenum].children[0] ); + CountClipNodes16_r( src, hull, src[nodenum].children[1] ); } -/* -================== -CountClipNodes32_r -================== -*/ -static void CountClipNodes32_r( dclipnode32_t *src, hull_t *hull, int nodenum ) +static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum ) { // leaf? 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] ); } +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 ================== */ -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; - mclipnode_t *out; + dclipnode32_t *src; int i, c; // leaf? @@ -1599,13 +1633,22 @@ static int RemapClipNodes_r( dclipnode32_t *srcnodes, hull_t *hull, int nodenum src = srcnodes + nodenum; c = hull->lastclipnode; - out = &hull->clipnodes[c]; hull->lastclipnode++; - out->planenum = src->planenum; - - for( i = 0; i < 2; i++ ) - out->children[i] = RemapClipNodes_r( srcnodes, hull, src->children[i] ); + if( bmod->version == QBSP2_VERSION ) + { + mclipnode32_t *out = &hull->clipnodes32[c]; + 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; } @@ -1617,34 +1660,64 @@ Mod_MakeHull0 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; - mclipnode_t *out; - 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_t *hull = &mod->hulls[0]; + int i; hull->firstclipnode = 0; hull->lastclipnode = mod->numnodes - 1; 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->children[j] = child->contents; - else out->children[j] = child - mod->nodes; + 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; + } } } + 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 )) return; // no hull specified - CountClipNodes32_r( bmod->clipnodes_out, hull, headnode ); + CountDClipNodes_r( bmod->clipnodes_out, hull, headnode ); // 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->lastclipnode = 0; // restart counting - // remap clipnodes to 16-bit indexes - RemapClipNodes_r( bmod->clipnodes_out, hull, headnode ); + RemapClipNodes_r( bmod, bmod->clipnodes_out, hull, headnode ); // remap clipnodes to 16-bit indexes } 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]; int iCompare; fs_offset_t datasize; - byte *in; + file_t *f; + uint hdr[2]; COM_FileBase( mod->name, modelname, sizeof( modelname )); Q_snprintf( path, sizeof( path ), "maps/%s.%s", modelname, ext ); @@ -1715,49 +1792,52 @@ 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 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 ); return false; } - if( datasize <= 8 ) // header + version + datasize = FS_FileLength( f ); + + // skip header bytes + datasize -= 8; + + if( datasize != expected_size ) { - Con_Printf( S_ERROR "%s is too short\n", path ); + Con_Printf( S_ERROR "%s has mismatched size (%li should be %zu)\n", path, (long)datasize, expected_size ); goto cleanup_and_error; } - if( LittleLong( ((uint *)in)[0] ) != IDDELUXEMAPHEADER ) + if( FS_Read( f, hdr, sizeof( hdr )) != sizeof( hdr )) { - Con_Printf( S_ERROR "%s is corrupted\n", path ); + Con_Printf( S_ERROR "failed reading header from %s\n", path ); goto cleanup_and_error; } - if( LittleLong( ((uint *)in)[1] ) != DELUXEMAP_VERSION ) + if( LittleLong( hdr[0] ) != IDDELUXEMAPHEADER ) { - Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( ((uint *)in)[1] ), DELUXEMAP_VERSION ); + Con_Printf( S_ERROR "%s is corrupted\n", path ); goto cleanup_and_error; } - // skip header bytes - datasize -= 8; - - if( datasize != expected_size ) + if( LittleLong( hdr[1] ) != DELUXEMAP_VERSION ) { - Con_Printf( S_ERROR "%s has mismatched size (%li should be %zu)\n", path, (long)datasize, expected_size ); + 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 ); - memcpy( *out, in + 8, datasize ); *outsize = datasize; - Mem_Free( in ); + + FS_Read( f, *out, datasize ); + FS_Close( f ); return true; cleanup_and_error: - Mem_Free( in ); + FS_Close( f ); return false; } @@ -1772,6 +1852,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; @@ -1783,6 +1864,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 @@ -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 // 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 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 if( colored ) SetBits( mod->flags, MODEL_COLORED_LIGHTING ); + if( qbsp2 ) SetBits( mod->flags, MODEL_QBSP2 ); if( i != 0 ) { @@ -2135,15 +2223,15 @@ Mod_LoadEdges */ static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod ) { - medge_t *out; int i; - mod->edges = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( medge_t )); mod->numedges = bmod->numedges; 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++ ) { @@ -2153,7 +2241,9 @@ static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod ) } 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++ ) { @@ -2913,9 +3003,9 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod ) if( FBitSet( out->texinfo->flags, TEX_SPECIAL )) SetBits( out->flags, SURF_DRAWTILED ); - Mod_CalcSurfaceBounds( mod, out ); - Mod_CalcSurfaceExtents( mod, out ); - Mod_CreateFaceBevels( mod, out ); + Mod_CalcSurfaceBounds( mod, out, bmod ); + Mod_CalcSurfaceExtents( mod, out, bmod ); + Mod_CreateFaceBevels( mod, out, bmod ); // grab the second sample to detect colored lighting 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 ) { 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 } 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]; } +#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 @@ -3018,20 +3153,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 ); } /* @@ -3413,6 +3548,8 @@ static void Mod_LoadLighting( model_t *mod, dbspmodel_t *bmod ) break; } + Con_Reportf( "lighting: %s\n", FBitSet( mod->flags, MODEL_COLORED_LIGHTING ) ? "colored" : "monochrome" ); + // not supposed to be load ? 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 )); 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 ) { case HLBSP_VERSION: @@ -3520,6 +3650,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 ); @@ -3570,7 +3703,7 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea Mod_LoadClipnodes( mod, bmod ); // preform some post-initalization - Mod_MakeHull0( mod ); + Mod_MakeHull0( mod, bmod ); Mod_SetupSubmodels( mod, bmod ); if( isworld ) @@ -3660,15 +3793,6 @@ qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, if( 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 ) { case HLBSP_VERSION: diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 17bf52f2bd..bfdbf1d504 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -135,6 +135,8 @@ extern poolhandle_t com_studiocache; extern convar_t mod_studiocache; extern convar_t r_wadtextures; extern convar_t r_showhull; +extern const mclipnode16_t box_clipnodes16[6]; +extern const mclipnode32_t box_clipnodes32[6]; // // 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 ); 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/mod_studio.c b/engine/common/mod_studio.c index 667b8dfc88..45e50730d0 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -50,9 +50,8 @@ static matrix3x4 studio_bones[MAXSTUDIOBONES]; static uint studio_hull_hitgroup[MAXSTUDIOBONES]; static uint cache_hull_hitgroup[MAXSTUDIOBONES]; static mstudiocache_t cache_studio[STUDIO_CACHESIZE]; -static mclipnode_t studio_clipnodes[6]; -static mplane_t studio_planes[768]; -static mplane_t cache_planes[768]; +static mplane_t studio_planes[MAXSTUDIOBONES * 6]; +static mplane_t cache_planes[MAXSTUDIOBONES * 6]; // current cache state static int cache_current; @@ -66,25 +65,14 @@ Mod_InitStudioHull */ void Mod_InitStudioHull( void ) { - int i, side; + int i; if( studio_hull[0].planes != NULL ) 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++ ) { - 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].firstclipnode = 0; 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 ) { + 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 ) continue; // CS stuff diff --git a/engine/common/pm_surface.c b/engine/common/pm_surface.c index c9d7701fb4..5ae4b2d151 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 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_ 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 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_ 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 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_ 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 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con 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 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con 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 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con } // 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 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con 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/common/pm_trace.c b/engine/common/pm_trace.c index fe4b6d20db..ed36584376 100644 --- a/engine/common/pm_trace.c +++ b/engine/common/pm_trace.c @@ -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 )) static mplane_t pm_boxplanes[6]; -static mclipnode_t pm_boxclipnodes[6]; -static hull_t pm_boxhull; +static hull_t pm_boxhull; // default hullmins 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 ) { - int i, side; + int i; - pm_boxhull.clipnodes = pm_boxclipnodes; + pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16; pm_boxhull.planes = pm_boxplanes; pm_boxhull.firstclipnode = 0; pm_boxhull.lastclipnode = 5; 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].normal[i>>1] = 1.0f; 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[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; } @@ -122,10 +118,21 @@ int GAME_EXPORT PM_HullPointContents( hull_t *hull, int num, const vec3_t p ) if( !hull || !hull->planes ) // fantom bmodels? return CONTENTS_NONE; - while( num >= 0 ) + if( world.version == QBSP2_VERSION ) + { + while( num >= 0 ) + { + plane = &hull->planes[hull->clipnodes32[num].planenum]; + num = hull->clipnodes32[num].children[PlaneDiff( p, plane ) < 0]; + } + } + else { - plane = &hull->planes[hull->clipnodes[num].planenum]; - num = hull->clipnodes[num].children[PlaneDiff( p, plane ) < 0]; + while( num >= 0 ) + { + plane = &hull->planes[hull->clipnodes16[num].planenum]; + num = hull->clipnodes16[num].children[PlaneDiff( p, plane ) < 0]; + } } 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 ) { - mclipnode_t *node; + int children[2]; mplane_t *plane; float t1, t2; float frac, midf; @@ -226,21 +233,31 @@ qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec Host_Error( "%s: bad node number %i\n", __func__, num ); // find the point distances - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; + if( world.version == QBSP2_VERSION ) + { + 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 ); t2 = PlaneDiff( p2, plane ); if( t1 >= 0.0f && t2 >= 0.0f ) { - num = node->children[0]; + num = children[0]; goto loc0; } if( t1 < 0.0f && t2 < 0.0f ) { - num = node->children[1]; + num = children[1]; goto loc0; } @@ -257,14 +274,14 @@ qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec VectorLerp( p1, frac, p2, mid ); // 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; // 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 - 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 diff --git a/engine/edict.h b/engine/edict.h index d74d08b1df..d0e76715ed 100644 --- a/engine/edict.h +++ b/engine/edict.h @@ -16,11 +16,8 @@ #ifndef EDICT_H #define EDICT_H -#ifdef SUPPORT_BSP2_FORMAT -#define MAX_ENT_LEAFS 24 // Orignally was 16 -#else -#define MAX_ENT_LEAFS 48 -#endif +#define MAX_ENT_LEAFS_32 24 // Orignally was 16 +#define MAX_ENT_LEAFS_16 48 #include "progdefs.h" @@ -33,11 +30,12 @@ struct edict_s int headnode; // -1 to use normal leaf check int num_leafs; -#ifdef SUPPORT_BSP2_FORMAT - int leafnums[MAX_ENT_LEAFS]; -#else - short leafnums[MAX_ENT_LEAFS]; -#endif + union + { + int leafnums32[MAX_ENT_LEAFS_32]; + short leafnums16[MAX_ENT_LEAFS_16]; + }; + float freetime; // sv.time when the object was freed void* pvPrivateData; // Alloced and freed by engine, used by DLLs diff --git a/engine/ref_api.h b/engine/ref_api.h index b68a237018..b9d865a651 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/server.h b/engine/server/server.h index 2f145fc60f..f1e6fad0b7 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -67,6 +67,8 @@ extern int SV_UPDATE_BACKUP; #define MAX_PUSHED_ENTS 256 #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_MOVEVARS BIT( 1 ) #define FCL_SKIP_NET_MESSAGE BIT( 2 ) diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 0b1c46f06f..99a903b2ed 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 @@ -4300,6 +4329,7 @@ pfnCheckVisibility static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset ) { int i, leafnum; + qboolean large_leafs = FBitSet( sv.worldmodel->flags, MODEL_QBSP2 ); if( !SV_IsValidEdict( ent )) return 0; @@ -4315,17 +4345,28 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset ) // check individual leafs for( i = 0; i < ent->num_leafs; i++ ) { - if( CHECKVISBIT( pset, ent->leafnums[i] )) - return 1; // visible passed by leaf + if( large_leafs ) + { + 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; } 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( 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 - 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; - ((edict_t *)ent)->num_leafs = (ent->num_leafs + 1) % MAX_ENT_LEAFS; + if( large_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 } diff --git a/engine/server/sv_world.c b/engine/server/sv_world.c index 81d57a28fa..805331ea02 100644 --- a/engine/server/sv_world.c +++ b/engine/server/sv_world.c @@ -40,9 +40,8 @@ HULL BOXES =============================================================================== */ -static hull_t box_hull; -static mclipnode_t box_clipnodes[6]; -static mplane_t box_planes[6]; +static hull_t box_hull; +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 ) { - int i, side; + int i; - box_hull.clipnodes = box_clipnodes; + box_hull.clipnodes16 = (mclipnode16_t *)box_clipnodes16; box_hull.planes = box_planes; box_hull.firstclipnode = 0; box_hull.lastclipnode = 5; 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].normal[i>>1] = 1; 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[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; } @@ -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; 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 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, // 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 { 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++; } 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 ); if(( sides == 3 ) && ( *headnode == -1 )) - *headnode = node - sv.worldmodel->nodes; + *headnode = node - mod->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, 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 )) { - 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->headnode = ent->v.aiment->headnode; } @@ -662,11 +663,11 @@ void GAME_EXPORT SV_LinkEdict( edict_t *ent, qboolean touch_triggers ) headnode = -1; 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->headnode = headnode; } @@ -1518,6 +1519,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 ) @@ -1527,25 +1530,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; @@ -1596,7 +1603,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 d16955970c..deaae78601 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 8ba5da3e37..40c0825033 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 1a307233a6..d05887d398 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 5d27e55a99..8ebbc13023 100644 --- a/ref/gl/gl_rsurf.c +++ b/ref/gl/gl_rsurf.c @@ -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 ) { const int lindex = mod->surfedges[fa->firstedge + i]; - const medge_t *pedges = mod->edges; - if( lindex > 0 ) - VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec ); + if( FBitSet( mod->flags, MODEL_QBSP2 )) + { + 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 - 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 ) @@ -3306,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 @@ -3360,10 +3376,14 @@ static void R_RecursiveWorldNode( mnode_t *node, uint clipflags ) 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; @@ -3382,7 +3402,7 @@ static void R_RecursiveWorldNode( mnode_t *node, uint clipflags ) } // recurse down the back side - node = node->children[!side]; + node = children[!side]; goto loc0; } @@ -3458,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 @@ -3491,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 ) @@ -3510,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 4bc794aa72..074f7e190a 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 ); } } } @@ -356,13 +355,13 @@ void R_DrawSolidClippedSubmodelPolygons( model_t *pmodel, mnode_t *topnode ) mplane_t *pplane; mvertex_t bverts[MAX_BMODEL_VERTS]; bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; - medge_t *pedge, *pedges; + medge16_t *pedge, *pedges; // FIXME: use bounding-box-based frustum clipping info? psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; numsurfaces = pmodel->nummodelsurfaces; - pedges = pmodel->edges; + pedges = pmodel->edges16; 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 // 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 e853a23fd9..7877a153da 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; + + firstsurface = node_firstsurface( node, model ); + numsurfaces = node_numsurfaces( node, model ); - surf = model->surfaces + node->firstsurface; + surf = model->surfaces + firstsurface; - for( i = 0; i < node->numsurfaces; i++, surf++ ) + 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 1f1158469f..3d6892d796 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_local.h b/ref/soft/r_local.h index 687aa0b1f1..772e1c88a3 100644 --- a/ref/soft/r_local.h +++ b/ref/soft/r_local.h @@ -933,7 +933,7 @@ typedef struct edge_s unsigned short surfs[2]; struct edge_s *nextremove; float nearzi; - medge_t *owner; + medge16_t *owner; } edge_t; diff --git a/ref/soft/r_main.c b/ref/soft/r_main.c index dd1c6c3f19..345928854b 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 ); } } @@ -1392,6 +1393,12 @@ void GAME_EXPORT R_NewMap( void ) R_ClearDecals(); // clear all level decals 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; if( r_cnumsurfs <= MINSURFACES ) diff --git a/ref/soft/r_rast.c b/ref/soft/r_rast.c index 339ff0d7cf..3dff5d9475 100644 --- a/ref/soft/r_rast.c +++ b/ref/soft/r_rast.c @@ -37,7 +37,7 @@ int c_faceclip; // numbe clipplane_t *entity_clipplanes; clipplane_t world_clipplanes[16]; -medge_t *r_pedge; +medge16_t *r_pedge; qboolean r_leftclipped, r_rightclipped; static qboolean makeleftedge, makerightedge; @@ -68,7 +68,7 @@ msurface_t *r_skyfaces; mplane_t r_skyplanes[6]; mtexinfo_t r_skytexinfo[6]; mvertex_t *r_skyverts; -medge_t *r_skyedges; +medge16_t *r_skyedges; int *r_skysurfedges; // I just copied this data from a box map... @@ -438,7 +438,7 @@ void R_RenderFace( msurface_t *fa, int clipflags ) mplane_t *pplane; float distinv; vec3_t p_normal; - medge_t *pedges, tedge; + medge16_t *pedges, tedge; clipplane_t *pclip; // 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_nearzionly = false; makeleftedge = makerightedge = false; - pedges = RI.currentmodel->edges; + pedges = RI.currentmodel->edges16; r_lastvertvalid = false; for( i = 0; i < fa->numedges; i++ ) @@ -560,7 +560,7 @@ void R_RenderFace( msurface_t *fa, int clipflags ) else { // 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 ) > r_pedge->cachededgeoffset ) && (((edge_t *)((uintptr_t)r_edges @@ -651,7 +651,7 @@ void R_RenderBmodelFace( bedge_t *pedges, msurface_t *psurf ) mplane_t *pplane; float distinv; vec3_t p_normal; - medge_t tedge; + medge16_t tedge; clipplane_t *pclip; /*if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) diff --git a/wscript b/wscript index 5f0e1977eb..da6c9d475f 100644 --- a/wscript +++ b/wscript @@ -91,7 +91,7 @@ SUBDIRS = [ 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('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('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), @@ -148,9 +148,6 @@ def options(opt): 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') - 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, 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_FUZZER = conf.options.ENABLE_FUZZER 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) # disable game_launch compiling on platform where it's not needed