diff --git a/common/com_model.h b/common/com_model.h index 550f3a07..8539eb03 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -60,15 +60,17 @@ 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 @@ -291,7 +293,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; @@ -356,7 +362,11 @@ typedef struct model_s int *surfedges; int numclipnodes; - mclipnode_t *clipnodes; + union + { + mclipnode16_t *clipnodes16; + mclipnode32_t *clipnodes32; + }; int nummarksurfaces; msurface_t **marksurfaces; diff --git a/engine/client/mod_dbghulls.c b/engine/client/mod_dbghulls.c index 65a16310..6db4b461 100644 --- a/engine/client/mod_dbghulls.c +++ b/engine/client/mod_dbghulls.c @@ -470,16 +470,16 @@ out_free: * 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/common/mod_bmodel.c b/engine/common/mod_bmodel.c index ac762533..03534e7f 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -1547,7 +1547,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 +1556,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 +1573,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 +1606,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 +1633,62 @@ 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 = in->children[j]; + + 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 = in->children[j]; + + if( child->contents < 0 ) + out->children[j] = child->contents; + else out->children[j] = child - mod->nodes; + } + } + } + } /* @@ -1688,15 +1732,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 ) @@ -1795,7 +1842,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++ ) @@ -3570,7 +3620,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 ) diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index 667b8dfc..3dab6472 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -50,7 +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 mclipnode16_t studio_clipnodes16[6]; +static mclipnode32_t studio_clipnodes32[6]; static mplane_t studio_planes[768]; static mplane_t cache_planes[768]; @@ -73,18 +74,29 @@ void Mod_InitStudioHull( void ) for( i = 0; i < 6; i++ ) { - studio_clipnodes[i].planenum = i; + studio_clipnodes16[i].planenum = i; + studio_clipnodes32[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; + studio_clipnodes16[i].children[side] = CONTENTS_EMPTY; + studio_clipnodes32[i].children[side] = CONTENTS_EMPTY; + + if( i != 5 ) + { + studio_clipnodes16[i].children[side^1] = i + 1; + studio_clipnodes32[i].children[side^1] = i + 1; + } + else + { + studio_clipnodes16[i].children[side^1] = CONTENTS_SOLID; + studio_clipnodes32[i].children[side^1] = CONTENTS_SOLID; + } } for( i = 0; i < MAXSTUDIOBONES; i++ ) { - studio_hull[i].clipnodes = studio_clipnodes; + studio_hull[i].clipnodes16 = studio_clipnodes16; studio_hull[i].planes = &studio_planes[i*6]; studio_hull[i].firstclipnode = 0; studio_hull[i].lastclipnode = 5; @@ -270,6 +282,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 = studio_clipnodes32; + else + studio_hull[i].clipnodes16 = studio_clipnodes16; + if( bSkipShield && i == 21 ) continue; // CS stuff diff --git a/engine/common/pm_trace.c b/engine/common/pm_trace.c index fe4b6d20..ff237e64 100644 --- a/engine/common/pm_trace.c +++ b/engine/common/pm_trace.c @@ -25,8 +25,9 @@ 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 mclipnode16_t pm_boxclipnodes16[6]; +static mclipnode32_t pm_boxclipnodes32[6]; +static hull_t pm_boxhull; // default hullmins static const vec3_t pm_hullmins[MAX_MAP_HULLS] = @@ -67,20 +68,31 @@ void PM_InitBoxHull( void ) { int i, side; - pm_boxhull.clipnodes = pm_boxclipnodes; + pm_boxhull.clipnodes16 = pm_boxclipnodes16; pm_boxhull.planes = pm_boxplanes; pm_boxhull.firstclipnode = 0; pm_boxhull.lastclipnode = 5; for( i = 0; i < 6; i++ ) { - pm_boxclipnodes[i].planenum = i; + pm_boxclipnodes16[i].planenum = i; + pm_boxclipnodes32[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_boxclipnodes16[i].children[side] = CONTENTS_EMPTY; + pm_boxclipnodes32[i].children[side] = CONTENTS_EMPTY; + + if( i != 5 ) + { + pm_boxclipnodes16[i].children[side^1] = i + 1; + pm_boxclipnodes32[i].children[side^1] = i + 1; + } + else + { + pm_boxclipnodes16[i].children[side^1] = CONTENTS_SOLID; + pm_boxclipnodes32[i].children[side^1] = i + 1; + } pm_boxplanes[i].type = i>>1; pm_boxplanes[i].normal[i>>1] = 1.0f; @@ -106,6 +118,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 = pm_boxclipnodes32; + else + pm_boxhull.clipnodes16 = pm_boxclipnodes16; + return &pm_boxhull; } @@ -122,10 +139,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 ) { - plane = &hull->planes[hull->clipnodes[num].planenum]; - num = hull->clipnodes[num].children[PlaneDiff( p, plane ) < 0]; + while( num >= 0 ) + { + plane = &hull->planes[hull->clipnodes32[num].planenum]; + num = hull->clipnodes32[num].children[PlaneDiff( p, plane ) < 0]; + } + } + else + { + while( num >= 0 ) + { + plane = &hull->planes[hull->clipnodes16[num].planenum]; + num = hull->clipnodes16[num].children[PlaneDiff( p, plane ) < 0]; + } } return num; } @@ -193,7 +221,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 +254,31 @@ loc0: 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 +295,14 @@ loc0: 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/server/sv_world.c b/engine/server/sv_world.c index 81d57a28..8e4ff22a 100644 --- a/engine/server/sv_world.c +++ b/engine/server/sv_world.c @@ -40,9 +40,10 @@ 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 mclipnode16_t box_clipnodes16[6]; +static mclipnode32_t box_clipnodes32[6]; +static mplane_t box_planes[6]; /* =================== @@ -56,20 +57,31 @@ static void SV_InitBoxHull( void ) { int i, side; - box_hull.clipnodes = box_clipnodes; + box_hull.clipnodes16 = 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; + box_clipnodes16[i].planenum = i; + box_clipnodes32[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_clipnodes16[i].children[side] = CONTENTS_EMPTY; + box_clipnodes32[i].children[side] = CONTENTS_EMPTY; + + if( i != 5 ) + { + box_clipnodes16[i].children[side^1] = i + 1; + box_clipnodes32[i].children[side^1] = i + 1; + } + else + { + box_clipnodes16[i].children[side^1] = CONTENTS_SOLID; + box_clipnodes32[i].children[side^1] = CONTENTS_SOLID; + } box_planes[i].type = i>>1; box_planes[i].normal[i>>1] = 1; @@ -167,6 +179,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 = box_clipnodes32; + else + box_hull.clipnodes16 = box_clipnodes16; + return &box_hull; }