2004-08-21 01:25:48 +00:00
# include "quakedef.h"
2009-11-04 21:16:50 +00:00
# include "pr_common.h"
2004-08-21 01:25:48 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Physics functions ( common )
*/
2010-07-12 22:46:37 +00:00
void Q1BSP_CheckHullNodes ( hull_t * hull )
{
int num , c ;
dclipnode_t * node ;
for ( num = hull - > firstclipnode ; num < hull - > lastclipnode ; num + + )
{
node = hull - > clipnodes + num ;
for ( c = 0 ; c < 2 ; c + + )
if ( node - > children [ c ] > = 0 )
if ( node - > children [ c ] < hull - > firstclipnode | | node - > children [ c ] > hull - > lastclipnode )
Sys_Error ( " Q1BSP_CheckHull: bad node number " ) ;
}
}
2004-08-21 01:25:48 +00:00
# if !id386
/*
= = = = = = = = = = = = = = = = = =
SV_HullPointContents
= = = = = = = = = = = = = = = = = =
*/
static int Q1_HullPointContents ( hull_t * hull , int num , vec3_t p )
{
float d ;
dclipnode_t * node ;
mplane_t * plane ;
while ( num > = 0 )
{
node = hull - > clipnodes + num ;
plane = hull - > planes + node - > planenum ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( plane - > type < 3 )
d = p [ plane - > type ] - plane - > dist ;
else
d = DotProduct ( plane - > normal , p ) - plane - > dist ;
if ( d < 0 )
num = node - > children [ 1 ] ;
else
num = node - > children [ 0 ] ;
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
return num ;
}
# else
int VARGS Q1_HullPointContents ( hull_t * hull , int num , vec3_t p ) ;
# endif // !id386
# define DIST_EPSILON (0.03125)
2010-07-13 09:49:38 +00:00
#if 0
2010-07-12 22:46:37 +00:00
enum
{
rht_solid ,
rht_empty ,
rht_impact
} ;
vec3_t rht_start , rht_end ;
static int Q1BSP_RecursiveHullTrace ( hull_t * hull , int num , float p1f , float p2f , vec3_t p1 , vec3_t p2 , trace_t * trace )
{
dclipnode_t * node ;
mplane_t * plane ;
float t1 , t2 ;
vec3_t mid ;
int side ;
float midf ;
int rht ;
reenter :
if ( num < 0 )
{
/*hit a leaf*/
if ( num = = Q1CONTENTS_SOLID )
{
if ( trace - > allsolid )
trace - > startsolid = true ;
return rht_solid ;
}
else
{
trace - > allsolid = false ;
if ( num = = Q1CONTENTS_EMPTY )
trace - > inopen = true ;
else
trace - > inwater = true ;
return rht_empty ;
}
}
/*its a node*/
/*get the node info*/
node = hull - > clipnodes + num ;
plane = hull - > planes + node - > planenum ;
if ( plane - > type < 3 )
{
t1 = p1 [ plane - > type ] - plane - > dist ;
t2 = p2 [ plane - > type ] - plane - > dist ;
}
else
{
t1 = DotProduct ( plane - > normal , p1 ) - plane - > dist ;
t2 = DotProduct ( plane - > normal , p2 ) - plane - > dist ;
}
/*if its completely on one side, resume on that side*/
if ( t1 > = 0 & & t2 > = 0 )
{
//return Q1BSP_RecursiveHullTrace (hull, node->children[0], p1f, p2f, p1, p2, trace);
num = node - > children [ 0 ] ;
goto reenter ;
}
if ( t1 < 0 & & t2 < 0 )
{
//return Q1BSP_RecursiveHullTrace (hull, node->children[1], p1f, p2f, p1, p2, trace);
num = node - > children [ 1 ] ;
goto reenter ;
}
if ( plane - > type < 3 )
{
t1 = rht_start [ plane - > type ] - plane - > dist ;
t2 = rht_end [ plane - > type ] - plane - > dist ;
}
else
{
t1 = DotProduct ( plane - > normal , rht_start ) - plane - > dist ;
t2 = DotProduct ( plane - > normal , rht_end ) - plane - > dist ;
}
side = t1 < 0 ;
midf = t1 / ( t1 - t2 ) ;
if ( midf < p1f ) midf = p1f ;
if ( midf > p2f ) midf = p2f ;
VectorInterpolate ( rht_start , midf , rht_end , mid ) ;
rht = Q1BSP_RecursiveHullTrace ( hull , node - > children [ side ] , p1f , midf , p1 , mid , trace ) ;
if ( rht ! = rht_empty )
return rht ;
rht = Q1BSP_RecursiveHullTrace ( hull , node - > children [ side ^ 1 ] , midf , p2f , mid , p2 , trace ) ;
if ( rht ! = rht_solid )
return rht ;
trace - > fraction = midf ;
if ( side )
{
/*we impacted the back of the node, so flip the plane*/
trace - > plane . dist = - plane - > dist ;
VectorNegate ( plane - > normal , trace - > plane . normal ) ;
midf = ( t1 + DIST_EPSILON ) / ( t1 - t2 ) ;
}
else
{
/*we impacted the front of the node*/
trace - > plane . dist = plane - > dist ;
VectorCopy ( plane - > normal , trace - > plane . normal ) ;
midf = ( t1 - DIST_EPSILON ) / ( t1 - t2 ) ;
}
VectorCopy ( mid , trace - > endpos ) ;
VectorInterpolate ( rht_start , midf , rht_end , trace - > endpos ) ;
return rht_impact ;
}
qboolean Q1BSP_RecursiveHullCheck ( hull_t * hull , int num , float p1f , float p2f , vec3_t p1 , vec3_t p2 , trace_t * trace )
{
if ( VectorEquals ( p1 , p2 ) )
{
/*points cannot cross planes, so do it faster*/
switch ( Q1_HullPointContents ( hull , num , p1 ) )
{
case Q1CONTENTS_SOLID :
trace - > startsolid = true ;
break ;
case Q1CONTENTS_EMPTY :
trace - > allsolid = false ;
trace - > inopen = true ;
break ;
default :
trace - > allsolid = false ;
trace - > inwater = true ;
break ;
}
return true ;
}
else
{
VectorCopy ( p1 , rht_start ) ;
VectorCopy ( p2 , rht_end ) ;
return Q1BSP_RecursiveHullTrace ( hull , num , p1f , p2f , p1 , p2 , trace ) ! = rht_impact ;
}
}
# else
2004-08-21 01:25:48 +00:00
qboolean Q1BSP_RecursiveHullCheck ( hull_t * hull , int num , float p1f , float p2f , vec3_t p1 , vec3_t p2 , trace_t * trace )
{
dclipnode_t * node ;
mplane_t * plane ;
float t1 , t2 ;
float frac ;
int i ;
vec3_t mid ;
int side ;
float midf ;
// check for empty
if ( num < 0 )
{
if ( num ! = Q1CONTENTS_SOLID )
{
trace - > allsolid = false ;
if ( num = = Q1CONTENTS_EMPTY )
trace - > inopen = true ;
else
trace - > inwater = true ;
}
else
trace - > startsolid = true ;
return true ; // empty
}
//
// find the point distances
//
node = hull - > clipnodes + num ;
plane = hull - > planes + node - > planenum ;
if ( plane - > type < 3 )
{
t1 = p1 [ plane - > type ] - plane - > dist ;
t2 = p2 [ plane - > type ] - plane - > dist ;
}
else
{
t1 = DotProduct ( plane - > normal , p1 ) - plane - > dist ;
t2 = DotProduct ( plane - > normal , p2 ) - plane - > dist ;
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
# if 1
if ( t1 > = 0 & & t2 > = 0 )
return Q1BSP_RecursiveHullCheck ( hull , node - > children [ 0 ] , p1f , p2f , p1 , p2 , trace ) ;
if ( t1 < 0 & & t2 < 0 )
return Q1BSP_RecursiveHullCheck ( hull , node - > children [ 1 ] , p1f , p2f , p1 , p2 , trace ) ;
# else
if ( ( t1 > = DIST_EPSILON & & t2 > = DIST_EPSILON ) | | ( t2 > t1 & & t1 > = 0 ) )
return Q1BSP_RecursiveHullCheck ( hull , node - > children [ 0 ] , p1f , p2f , p1 , p2 , trace ) ;
if ( ( t1 < = - DIST_EPSILON & & t2 < = - DIST_EPSILON ) | | ( t2 < t1 & & t1 < = 0 ) )
return Q1BSP_RecursiveHullCheck ( hull , node - > children [ 1 ] , p1f , p2f , p1 , p2 , trace ) ;
# endif
// put the crosspoint DIST_EPSILON pixels on the near side
if ( t1 < 0 )
frac = ( t1 + DIST_EPSILON ) / ( t1 - t2 ) ;
else
frac = ( t1 - DIST_EPSILON ) / ( t1 - t2 ) ;
if ( frac < 0 )
frac = 0 ;
if ( frac > 1 )
frac = 1 ;
midf = p1f + ( p2f - p1f ) * frac ;
for ( i = 0 ; i < 3 ; i + + )
mid [ i ] = p1 [ i ] + frac * ( p2 [ i ] - p1 [ i ] ) ;
side = ( t1 < 0 ) ;
// move up to the node
if ( ! Q1BSP_RecursiveHullCheck ( hull , node - > children [ side ] , p1f , midf , p1 , mid , trace ) )
return false ;
# ifdef PARANOID
if ( Q1BSP_RecursiveHullCheck ( sv_hullmodel , mid , node - > children [ side ] )
= = Q1CONTENTS_SOLID )
{
Con_Printf ( " mid PointInHullSolid \n " ) ;
return false ;
}
# endif
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( Q1_HullPointContents ( hull , node - > children [ side ^ 1 ] , mid )
! = Q1CONTENTS_SOLID )
// go past the node
return Q1BSP_RecursiveHullCheck ( hull , node - > children [ side ^ 1 ] , midf , p2f , mid , p2 , trace ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( trace - > allsolid )
return false ; // never got out of the solid area
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
//==================
// the other side of the node is solid, this is the impact point
//==================
if ( ! side )
{
VectorCopy ( plane - > normal , trace - > plane . normal ) ;
trace - > plane . dist = plane - > dist ;
}
else
{
2006-05-29 04:50:24 +00:00
VectorNegate ( plane - > normal , trace - > plane . normal ) ;
2004-08-21 01:25:48 +00:00
trace - > plane . dist = - plane - > dist ;
}
while ( Q1_HullPointContents ( hull , hull - > firstclipnode , mid )
= = Q1CONTENTS_SOLID )
{ // shouldn't really happen, but does occasionally
2008-05-25 22:23:43 +00:00
if ( ! ( frac < 10000000 ) & & ! ( frac > - 10000000 ) )
{
trace - > fraction = 0 ;
VectorClear ( trace - > endpos ) ;
Con_Printf ( " nan in traceline \n " ) ;
return false ;
}
2004-08-21 01:25:48 +00:00
frac - = 0.1 ;
if ( frac < 0 )
{
trace - > fraction = midf ;
VectorCopy ( mid , trace - > endpos ) ;
Con_DPrintf ( " backup past 0 \n " ) ;
return false ;
}
midf = p1f + ( p2f - p1f ) * frac ;
for ( i = 0 ; i < 3 ; i + + )
mid [ i ] = p1 [ i ] + frac * ( p2 [ i ] - p1 [ i ] ) ;
}
trace - > fraction = midf ;
VectorCopy ( mid , trace - > endpos ) ;
return false ;
}
2010-07-12 22:46:37 +00:00
# endif
2004-08-21 01:25:48 +00:00
int Q1BSP_HullPointContents ( hull_t * hull , vec3_t p )
{
switch ( Q1_HullPointContents ( hull , hull - > firstclipnode , p ) )
{
case Q1CONTENTS_EMPTY :
return FTECONTENTS_EMPTY ;
case Q1CONTENTS_SOLID :
return FTECONTENTS_SOLID ;
case Q1CONTENTS_WATER :
return FTECONTENTS_WATER ;
case Q1CONTENTS_SLIME :
return FTECONTENTS_SLIME ;
case Q1CONTENTS_LAVA :
return FTECONTENTS_LAVA ;
case Q1CONTENTS_SKY :
return FTECONTENTS_SKY ;
default :
Sys_Error ( " Q1_PointContents: Unknown contents type " ) ;
return FTECONTENTS_SOLID ;
}
}
2010-08-28 17:14:38 +00:00
unsigned int Q1BSP_PointContents ( model_t * model , vec3_t axis [ 3 ] , vec3_t point )
2005-08-26 22:56:51 +00:00
{
2010-08-28 17:14:38 +00:00
if ( axis )
{
vec3_t transformed ;
transformed [ 0 ] = DotProduct ( point , axis [ 0 ] ) ;
transformed [ 1 ] = DotProduct ( point , axis [ 1 ] ) ;
transformed [ 2 ] = DotProduct ( point , axis [ 2 ] ) ;
return Q1BSP_HullPointContents ( & model - > hulls [ 0 ] , transformed ) ;
}
2005-08-26 22:56:51 +00:00
return Q1BSP_HullPointContents ( & model - > hulls [ 0 ] , point ) ;
2004-08-21 01:25:48 +00:00
}
2010-08-28 17:14:38 +00:00
qboolean Q1BSP_Trace ( model_t * model , int forcehullnum , int frame , vec3_t axis [ 3 ] , vec3_t start , vec3_t end , vec3_t mins , vec3_t maxs , trace_t * trace )
2005-07-16 00:53:08 +00:00
{
hull_t * hull ;
vec3_t size ;
vec3_t start_l , end_l ;
vec3_t offset ;
memset ( trace , 0 , sizeof ( trace_t ) ) ;
trace - > fraction = 1 ;
trace - > allsolid = true ;
VectorSubtract ( maxs , mins , size ) ;
if ( forcehullnum > = 1 & & forcehullnum < = MAX_MAP_HULLSM & & model - > hulls [ forcehullnum - 1 ] . available )
hull = & model - > hulls [ forcehullnum - 1 ] ;
else
{
if ( model - > hulls [ 5 ] . available )
{ //choose based on hexen2 sizes.
if ( size [ 0 ] < 3 ) // Point
hull = & model - > hulls [ 0 ] ;
2010-08-18 21:59:06 +00:00
else if ( size [ 0 ] < = 8 & & model - > hulls [ 4 ] . available )
hull = & model - > hulls [ 4 ] ; //Pentacles
2005-07-16 00:53:08 +00:00
else if ( size [ 0 ] < = 32 & & size [ 2 ] < = 28 ) // Half Player
hull = & model - > hulls [ 3 ] ;
else if ( size [ 0 ] < = 32 ) // Full Player
hull = & model - > hulls [ 1 ] ;
else // Golumn
hull = & model - > hulls [ 5 ] ;
}
else
{
if ( size [ 0 ] < 3 | | ! model - > hulls [ 1 ] . available )
hull = & model - > hulls [ 0 ] ;
else if ( size [ 0 ] < = 32 )
{
if ( size [ 2 ] < 54 & & model - > hulls [ 3 ] . available )
hull = & model - > hulls [ 3 ] ; // 32x32x36 (half-life's crouch)
else
hull = & model - > hulls [ 1 ] ;
}
else
hull = & model - > hulls [ 2 ] ;
}
}
// calculate an offset value to center the origin
VectorSubtract ( hull - > clip_mins , mins , offset ) ;
2010-08-28 17:14:38 +00:00
if ( axis )
2005-07-16 00:53:08 +00:00
{
2010-08-28 17:14:38 +00:00
vec3_t tmp ;
VectorSubtract ( start , offset , tmp ) ;
start_l [ 0 ] = DotProduct ( tmp , axis [ 0 ] ) ;
start_l [ 1 ] = DotProduct ( tmp , axis [ 1 ] ) ;
start_l [ 2 ] = DotProduct ( tmp , axis [ 2 ] ) ;
VectorSubtract ( end , offset , tmp ) ;
end_l [ 0 ] = DotProduct ( tmp , axis [ 0 ] ) ;
end_l [ 1 ] = DotProduct ( tmp , axis [ 1 ] ) ;
end_l [ 2 ] = DotProduct ( tmp , axis [ 2 ] ) ;
Q1BSP_RecursiveHullCheck ( hull , hull - > firstclipnode , 0 , 1 , start_l , end_l , trace ) ;
if ( trace - > fraction = = 1 )
{
VectorCopy ( end , trace - > endpos ) ;
}
else
{
vec3_t iaxis [ 3 ] ;
vec3_t norm ;
Matrix3_Invert_Simple ( axis , iaxis ) ;
VectorCopy ( trace - > plane . normal , norm ) ;
trace - > plane . normal [ 0 ] = DotProduct ( norm , iaxis [ 0 ] ) ;
trace - > plane . normal [ 1 ] = DotProduct ( norm , iaxis [ 1 ] ) ;
trace - > plane . normal [ 2 ] = DotProduct ( norm , iaxis [ 2 ] ) ;
/*just interpolate it, its easier than inverse matrix rotations*/
VectorInterpolate ( start , trace - > fraction , end , trace - > endpos ) ;
}
2005-07-16 00:53:08 +00:00
}
else
{
2010-08-28 17:14:38 +00:00
VectorSubtract ( start , offset , start_l ) ;
VectorSubtract ( end , offset , end_l ) ;
Q1BSP_RecursiveHullCheck ( hull , hull - > firstclipnode , 0 , 1 , start_l , end_l , trace ) ;
if ( trace - > fraction = = 1 )
{
VectorCopy ( end , trace - > endpos ) ;
}
else
{
VectorAdd ( trace - > endpos , offset , trace - > endpos ) ;
}
2005-07-16 00:53:08 +00:00
}
return trace - > fraction ! = 1 ;
}
2004-08-21 01:25:48 +00:00
/*
Physics functions ( common )
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Rendering functions ( Client only )
*/
# ifndef SERVERONLY
extern int r_dlightframecount ;
//goes through the nodes marking the surfaces near the dynamic light as lit.
void Q1BSP_MarkLights ( dlight_t * light , int bit , mnode_t * node )
{
mplane_t * splitplane ;
float dist ;
msurface_t * surf ;
int i ;
2006-03-04 20:43:48 +00:00
2009-07-14 15:13:12 +00:00
float l , maxdist ;
int j , s , t ;
vec3_t impact ;
2004-08-21 01:25:48 +00:00
if ( node - > contents < 0 )
2006-03-04 20:43:48 +00:00
return ;
2004-08-21 01:25:48 +00:00
splitplane = node - > plane ;
2009-07-14 15:13:12 +00:00
if ( splitplane - > type < 3 )
dist = light - > origin [ splitplane - > type ] - splitplane - > dist ;
else
dist = DotProduct ( light - > origin , splitplane - > normal ) - splitplane - > dist ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( dist > light - > radius )
{
Q1BSP_MarkLights ( light , bit , node - > children [ 0 ] ) ;
return ;
}
if ( dist < - light - > radius )
{
Q1BSP_MarkLights ( light , bit , node - > children [ 1 ] ) ;
return ;
}
2006-03-04 20:43:48 +00:00
2009-07-14 15:13:12 +00:00
maxdist = light - > radius * light - > radius ;
2004-08-21 01:25:48 +00:00
// mark the polygons
2005-10-16 04:03:13 +00:00
surf = currentmodel - > surfaces + node - > firstsurface ;
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < node - > numsurfaces ; i + + , surf + + )
{
2009-07-14 15:13:12 +00:00
//Yeah, you can blame LordHavoc for this alternate code here.
for ( j = 0 ; j < 3 ; j + + )
impact [ j ] = light - > origin [ j ] - surf - > plane - > normal [ j ] * dist ;
// clamp center of light to corner and check brightness
l = DotProduct ( impact , surf - > texinfo - > vecs [ 0 ] ) + surf - > texinfo - > vecs [ 0 ] [ 3 ] - surf - > texturemins [ 0 ] ;
s = l + 0.5 ; if ( s < 0 ) s = 0 ; else if ( s > surf - > extents [ 0 ] ) s = surf - > extents [ 0 ] ;
s = l - s ;
l = DotProduct ( impact , surf - > texinfo - > vecs [ 1 ] ) + surf - > texinfo - > vecs [ 1 ] [ 3 ] - surf - > texturemins [ 1 ] ;
t = l + 0.5 ; if ( t < 0 ) t = 0 ; else if ( t > surf - > extents [ 1 ] ) t = surf - > extents [ 1 ] ;
t = l - t ;
// compare to minimum light
if ( ( s * s + t * t + dist * dist ) < maxdist )
2004-08-21 01:25:48 +00:00
{
2009-07-14 15:13:12 +00:00
if ( surf - > dlightframe ! = r_dlightframecount )
{
surf - > dlightbits = bit ;
surf - > dlightframe = r_dlightframecount ;
}
else
surf - > dlightbits | = bit ;
2004-08-21 01:25:48 +00:00
}
}
Q1BSP_MarkLights ( light , bit , node - > children [ 0 ] ) ;
Q1BSP_MarkLights ( light , bit , node - > children [ 1 ] ) ;
}
2005-05-13 10:42:48 +00:00
# define MAXFRAGMENTTRIS 256
vec3_t decalfragmentverts [ MAXFRAGMENTTRIS * 3 ] ;
typedef struct {
vec3_t center ;
vec3_t normal ;
2005-09-08 22:52:46 +00:00
// vec3_t tangent1;
// vec3_t tangent2;
2005-05-13 10:42:48 +00:00
vec3_t planenorm [ 6 ] ;
float planedist [ 6 ] ;
2005-09-08 22:52:46 +00:00
int numplanes ;
2005-05-13 10:42:48 +00:00
vec_t radius ;
int numtris ;
} fragmentdecal_t ;
//#define SHOWCLIPS
//#define FRAGMENTASTRIANGLES //works, but produces more fragments.
# ifdef FRAGMENTASTRIANGLES
//if the triangle is clipped away, go recursive if there are tris left.
void Fragment_ClipTriToPlane ( int trinum , float * plane , float planedist , fragmentdecal_t * dec )
{
float * point [ 3 ] ;
float dotv [ 3 ] ;
vec3_t impact1 , impact2 ;
float t ;
int i , i2 , i3 ;
int clippedverts = 0 ;
for ( i = 0 ; i < 3 ; i + + )
{
point [ i ] = decalfragmentverts [ trinum * 3 + i ] ;
dotv [ i ] = DotProduct ( point [ i ] , plane ) - planedist ;
clippedverts + = dotv [ i ] < 0 ;
}
//if they're all clipped away, scrap the tri
switch ( clippedverts )
{
case 0 :
return ; //plane does not clip the triangle.
case 1 : //split into 3, disregard the clipped vert
for ( i = 0 ; i < 3 ; i + + )
{
if ( dotv [ i ] < 0 )
{ //This is the vertex that's getting clipped.
if ( dotv [ i ] > - DIST_EPSILON )
return ; //it's only over the line by a tiny ammount.
i2 = ( i + 1 ) % 3 ;
i3 = ( i + 2 ) % 3 ;
if ( dotv [ i2 ] < DIST_EPSILON )
return ;
if ( dotv [ i3 ] < DIST_EPSILON )
return ;
//work out where the two lines impact the plane
t = ( dotv [ i ] ) / ( dotv [ i ] - dotv [ i2 ] ) ;
VectorInterpolate ( point [ i ] , t , point [ i2 ] , impact1 ) ;
t = ( dotv [ i ] ) / ( dotv [ i ] - dotv [ i3 ] ) ;
VectorInterpolate ( point [ i ] , t , point [ i3 ] , impact2 ) ;
# ifdef SHOWCLIPS
if ( dec - > numtris ! = MAXFRAGMENTTRIS )
{
VectorCopy ( impact2 , decalfragmentverts [ dec - > numtris * 3 + 0 ] ) ;
VectorCopy ( decalfragmentverts [ trinum * 3 + i ] , decalfragmentverts [ dec - > numtris * 3 + 1 ] ) ;
VectorCopy ( impact1 , decalfragmentverts [ dec - > numtris * 3 + 2 ] ) ;
dec - > numtris + + ;
}
# endif
//shrink the tri, putting the impact into the killed vertex.
VectorCopy ( impact2 , point [ i ] ) ;
if ( dec - > numtris = = MAXFRAGMENTTRIS )
return ; //:(
//build the second tri
VectorCopy ( impact1 , decalfragmentverts [ dec - > numtris * 3 + 0 ] ) ;
VectorCopy ( decalfragmentverts [ trinum * 3 + i2 ] , decalfragmentverts [ dec - > numtris * 3 + 1 ] ) ;
VectorCopy ( impact2 , decalfragmentverts [ dec - > numtris * 3 + 2 ] ) ;
dec - > numtris + + ;
return ;
}
}
Sys_Error ( " Fragment_ClipTriToPlane: Clipped vertex not founc \n " ) ;
return ; //can't handle it
case 2 : //split into 3, disregarding both the clipped.
for ( i = 0 ; i < 3 ; i + + )
{
if ( ! ( dotv [ i ] < 0 ) )
{ //This is the vertex that's staying.
if ( dotv [ i ] < DIST_EPSILON )
break ; //only just inside
i2 = ( i + 1 ) % 3 ;
i3 = ( i + 2 ) % 3 ;
//work out where the two lines impact the plane
t = ( dotv [ i ] ) / ( dotv [ i ] - dotv [ i2 ] ) ;
VectorInterpolate ( point [ i ] , t , point [ i2 ] , impact1 ) ;
t = ( dotv [ i ] ) / ( dotv [ i ] - dotv [ i3 ] ) ;
VectorInterpolate ( point [ i ] , t , point [ i3 ] , impact2 ) ;
//shrink the tri, putting the impact into the killed vertex.
# ifdef SHOWCLIPS
if ( dec - > numtris ! = MAXFRAGMENTTRIS )
{
VectorCopy ( impact1 , decalfragmentverts [ dec - > numtris * 3 + 0 ] ) ;
VectorCopy ( point [ i2 ] , decalfragmentverts [ dec - > numtris * 3 + 1 ] ) ;
VectorCopy ( point [ i3 ] , decalfragmentverts [ dec - > numtris * 3 + 2 ] ) ;
dec - > numtris + + ;
}
if ( dec - > numtris ! = MAXFRAGMENTTRIS )
{
VectorCopy ( impact1 , decalfragmentverts [ dec - > numtris * 3 + 0 ] ) ;
VectorCopy ( point [ i3 ] , decalfragmentverts [ dec - > numtris * 3 + 1 ] ) ;
VectorCopy ( impact2 , decalfragmentverts [ dec - > numtris * 3 + 2 ] ) ;
dec - > numtris + + ;
}
# endif
VectorCopy ( impact1 , point [ i2 ] ) ;
VectorCopy ( impact2 , point [ i3 ] ) ;
return ;
}
}
case 3 : //scrap it
//fill the verts with the verts of the last and go recursive (due to the nature of Fragment_ClipTriangle, which doesn't actually know if we clip them away)
# ifndef SHOWCLIPS
dec - > numtris - - ;
VectorCopy ( decalfragmentverts [ dec - > numtris * 3 + 0 ] , decalfragmentverts [ trinum * 3 + 0 ] ) ;
VectorCopy ( decalfragmentverts [ dec - > numtris * 3 + 1 ] , decalfragmentverts [ trinum * 3 + 1 ] ) ;
VectorCopy ( decalfragmentverts [ dec - > numtris * 3 + 2 ] , decalfragmentverts [ trinum * 3 + 2 ] ) ;
if ( trinum < dec - > numtris )
Fragment_ClipTriToPlane ( trinum , plane , planedist , dec ) ;
# endif
return ;
}
}
void Fragment_ClipTriangle ( fragmentdecal_t * dec , float * a , float * b , float * c )
{
//emit the triangle, and clip it's fragments.
int start , i ;
int p ;
if ( dec - > numtris = = MAXFRAGMENTTRIS )
return ; //:(
start = dec - > numtris ;
VectorCopy ( a , decalfragmentverts [ dec - > numtris * 3 + 0 ] ) ;
VectorCopy ( b , decalfragmentverts [ dec - > numtris * 3 + 1 ] ) ;
VectorCopy ( c , decalfragmentverts [ dec - > numtris * 3 + 2 ] ) ;
dec - > numtris + + ;
//clip all the fragments to all of the planes.
//This will produce a quad if the source triangle was big enough.
for ( p = 0 ; p < 6 ; p + + )
{
for ( i = start ; i < dec - > numtris ; i + + )
Fragment_ClipTriToPlane ( i , dec - > planenorm [ p ] , dec - > plantdist [ p ] , dec ) ;
}
}
# else
2009-10-06 00:33:54 +00:00
# define MAXFRAGMENTVERTS 360
2005-05-13 10:42:48 +00:00
int Fragment_ClipPolyToPlane ( float * inverts , float * outverts , int incount , float * plane , float planedist )
{
2010-07-11 02:22:39 +00:00
# define C 4
2009-10-06 00:33:54 +00:00
float dotv [ MAXFRAGMENTVERTS + 1 ] ;
char keep [ MAXFRAGMENTVERTS + 1 ] ;
# define KEEP_KILL 0
# define KEEP_KEEP 1
# define KEEP_BORDER 2
int i ;
2005-05-13 10:42:48 +00:00
int outcount = 0 ;
int clippedcount = 0 ;
2009-10-06 00:33:54 +00:00
float d , * p1 , * p2 , * out ;
2005-09-08 22:52:46 +00:00
# define FRAG_EPSILON 0.5
2005-05-13 10:42:48 +00:00
for ( i = 0 ; i < incount ; i + + )
{
2010-07-11 02:22:39 +00:00
dotv [ i ] = DotProduct ( ( inverts + i * C ) , plane ) - planedist ;
2005-09-08 22:52:46 +00:00
if ( dotv [ i ] < - FRAG_EPSILON )
2005-05-13 10:42:48 +00:00
{
2009-10-06 00:33:54 +00:00
keep [ i ] = KEEP_KILL ;
clippedcount + + ;
2005-05-13 10:42:48 +00:00
}
2009-10-06 00:33:54 +00:00
else if ( dotv [ i ] > FRAG_EPSILON )
keep [ i ] = KEEP_KEEP ;
else
keep [ i ] = KEEP_BORDER ;
2005-05-13 10:42:48 +00:00
}
2009-10-06 00:33:54 +00:00
dotv [ i ] = dotv [ 0 ] ;
keep [ i ] = keep [ 0 ] ;
2005-05-13 10:42:48 +00:00
if ( clippedcount = = incount )
return 0 ; //all were clipped
if ( clippedcount = = 0 )
2005-09-08 22:52:46 +00:00
{ //none were clipped
2010-07-11 02:22:39 +00:00
for ( i = 0 ; i < incount ; i + + )
VectorCopy ( ( inverts + i * C ) , ( outverts + i * C ) ) ;
2005-05-13 10:42:48 +00:00
return incount ;
}
2009-10-06 00:33:54 +00:00
for ( i = 0 ; i < incount ; i + + )
2005-05-13 10:42:48 +00:00
{
2010-07-11 02:22:39 +00:00
p1 = inverts + i * C ;
2009-10-06 00:33:54 +00:00
if ( keep [ i ] = = KEEP_BORDER )
2005-05-13 10:42:48 +00:00
{
2010-07-11 02:22:39 +00:00
out = outverts + outcount + + * C ;
2009-10-06 00:33:54 +00:00
VectorCopy ( p1 , out ) ;
continue ;
2005-05-13 10:42:48 +00:00
}
2009-10-06 00:33:54 +00:00
if ( keep [ i ] = = KEEP_KEEP )
{
2010-07-11 02:22:39 +00:00
out = outverts + outcount + + * C ;
2009-10-06 00:33:54 +00:00
VectorCopy ( p1 , out ) ;
2005-05-13 10:42:48 +00:00
}
2009-10-06 00:33:54 +00:00
if ( keep [ i + 1 ] = = KEEP_BORDER | | keep [ i ] = = keep [ i + 1 ] )
continue ;
2010-07-11 02:22:39 +00:00
p2 = inverts + ( ( i + 1 ) % incount ) * C ;
2009-10-06 00:33:54 +00:00
d = dotv [ i ] - dotv [ i + 1 ] ;
if ( d )
d = dotv [ i ] / d ;
2010-07-11 02:22:39 +00:00
out = outverts + outcount + + * C ;
2009-10-06 00:33:54 +00:00
VectorInterpolate ( p1 , d , p2 , out ) ;
2005-05-13 10:42:48 +00:00
}
return outcount ;
}
2009-10-06 00:33:54 +00:00
void Fragment_ClipPoly ( fragmentdecal_t * dec , int numverts , float * inverts )
2005-05-13 10:42:48 +00:00
{
//emit the triangle, and clip it's fragments.
int p ;
2010-07-11 02:22:39 +00:00
float verts [ MAXFRAGMENTVERTS * C ] ;
float verts2 [ MAXFRAGMENTVERTS * C ] ;
2005-09-08 22:52:46 +00:00
float * cverts ;
int flip ;
2005-05-13 10:42:48 +00:00
2009-10-06 00:33:54 +00:00
if ( numverts > MAXFRAGMENTTRIS )
return ;
2005-05-13 10:42:48 +00:00
if ( dec - > numtris = = MAXFRAGMENTTRIS )
return ; //don't bother
2009-10-06 00:33:54 +00:00
//clip to the first plane specially, so we don't have extra copys
numverts = Fragment_ClipPolyToPlane ( inverts , verts , numverts , dec - > planenorm [ 0 ] , dec - > planedist [ 0 ] ) ;
2005-05-13 10:42:48 +00:00
//clip the triangle to the 6 planes.
2005-09-08 22:52:46 +00:00
flip = 0 ;
2009-10-06 00:33:54 +00:00
for ( p = 1 ; p < dec - > numplanes ; p + + )
2005-05-13 10:42:48 +00:00
{
2005-09-08 22:52:46 +00:00
flip ^ = 1 ;
if ( flip )
numverts = Fragment_ClipPolyToPlane ( verts , verts2 , numverts , dec - > planenorm [ p ] , dec - > planedist [ p ] ) ;
else
numverts = Fragment_ClipPolyToPlane ( verts2 , verts , numverts , dec - > planenorm [ p ] , dec - > planedist [ p ] ) ;
2005-05-13 10:42:48 +00:00
if ( numverts < 3 ) //totally clipped.
return ;
}
2005-09-08 22:52:46 +00:00
if ( flip )
cverts = verts2 ;
else
cverts = verts ;
2005-05-13 10:42:48 +00:00
//decompose the resultant polygon into triangles.
while ( numverts > 2 )
{
if ( dec - > numtris = = MAXFRAGMENTTRIS )
return ;
numverts - - ;
2010-07-11 02:22:39 +00:00
VectorCopy ( ( cverts + C * 0 ) , decalfragmentverts [ dec - > numtris * 3 + 0 ] ) ;
VectorCopy ( ( cverts + C * ( numverts - 1 ) ) , decalfragmentverts [ dec - > numtris * 3 + 1 ] ) ;
VectorCopy ( ( cverts + C * numverts ) , decalfragmentverts [ dec - > numtris * 3 + 2 ] ) ;
2005-05-13 10:42:48 +00:00
dec - > numtris + + ;
}
}
# endif
//this could be inlined, but I'm lazy.
2005-09-08 22:52:46 +00:00
void Fragment_Mesh ( fragmentdecal_t * dec , mesh_t * mesh )
2005-05-13 10:42:48 +00:00
{
int i ;
2010-07-11 02:22:39 +00:00
vecV_t verts [ 3 ] ;
2009-10-06 00:33:54 +00:00
/*if its a triangle fan/poly/quad then we can just submit the entire thing without generating extra fragments*/
2009-11-04 21:16:50 +00:00
if ( mesh - > istrifan )
2009-10-06 00:33:54 +00:00
{
Fragment_ClipPoly ( dec , mesh - > numvertexes , mesh - > xyz_array [ 0 ] ) ;
return ;
}
2009-11-04 21:16:50 +00:00
//Fixme: optimise q3 patches (quad strips with bends between each strip)
2005-05-13 10:42:48 +00:00
2009-10-06 00:33:54 +00:00
/*otherwise it goes in and out in weird places*/
2005-05-13 10:42:48 +00:00
for ( i = 0 ; i < mesh - > numindexes ; i + = 3 )
{
if ( dec - > numtris = = MAXFRAGMENTTRIS )
break ;
2009-10-06 00:33:54 +00:00
VectorCopy ( mesh - > xyz_array [ mesh - > indexes [ i + 0 ] ] , verts [ 0 ] ) ;
VectorCopy ( mesh - > xyz_array [ mesh - > indexes [ i + 1 ] ] , verts [ 1 ] ) ;
VectorCopy ( mesh - > xyz_array [ mesh - > indexes [ i + 2 ] ] , verts [ 2 ] ) ;
Fragment_ClipPoly ( dec , 3 , verts [ 0 ] ) ;
2005-05-13 10:42:48 +00:00
}
}
void Q1BSP_ClipDecalToNodes ( fragmentdecal_t * dec , mnode_t * node )
{
mplane_t * splitplane ;
float dist ;
msurface_t * surf ;
int i ;
2006-03-04 20:43:48 +00:00
2005-05-13 10:42:48 +00:00
if ( node - > contents < 0 )
2006-03-04 20:43:48 +00:00
return ;
2005-05-13 10:42:48 +00:00
splitplane = node - > plane ;
dist = DotProduct ( dec - > center , splitplane - > normal ) - splitplane - > dist ;
if ( dist > dec - > radius )
{
Q1BSP_ClipDecalToNodes ( dec , node - > children [ 0 ] ) ;
return ;
}
if ( dist < - dec - > radius )
{
Q1BSP_ClipDecalToNodes ( dec , node - > children [ 1 ] ) ;
return ;
}
// mark the polygons
surf = cl . worldmodel - > surfaces + node - > firstsurface ;
for ( i = 0 ; i < node - > numsurfaces ; i + + , surf + + )
{
2005-06-04 04:20:20 +00:00
if ( surf - > flags & SURF_PLANEBACK )
{
2005-09-07 01:05:27 +00:00
if ( - DotProduct ( surf - > plane - > normal , dec - > normal ) > - 0.5 )
2005-06-04 04:20:20 +00:00
continue ;
}
else
{
2005-09-07 01:05:27 +00:00
if ( DotProduct ( surf - > plane - > normal , dec - > normal ) > - 0.5 )
2005-06-04 04:20:20 +00:00
continue ;
}
2005-09-08 22:52:46 +00:00
Fragment_Mesh ( dec , surf - > mesh ) ;
2005-05-13 10:42:48 +00:00
}
Q1BSP_ClipDecalToNodes ( dec , node - > children [ 0 ] ) ;
Q1BSP_ClipDecalToNodes ( dec , node - > children [ 1 ] ) ;
}
2009-11-04 21:16:50 +00:00
# ifdef RTLIGHTS
extern int sh_shadowframe ;
# else
static int sh_shadowframe ;
# endif
# ifdef Q3BSPS
2009-10-06 00:33:54 +00:00
void Q3BSP_ClipDecalToNodes ( fragmentdecal_t * dec , mnode_t * node )
{
mplane_t * splitplane ;
float dist ;
msurface_t * * msurf ;
msurface_t * surf ;
mleaf_t * leaf ;
int i ;
if ( node - > contents ! = - 1 )
{
leaf = ( mleaf_t * ) node ;
// mark the polygons
msurf = leaf - > firstmarksurface ;
for ( i = 0 ; i < leaf - > nummarksurfaces ; i + + , msurf + + )
{
surf = * msurf ;
2009-11-04 21:16:50 +00:00
//only check each surface once. it can appear in multiple leafs.
if ( surf - > shadowframe = = sh_shadowframe )
continue ;
surf - > shadowframe = sh_shadowframe ;
2009-10-06 00:33:54 +00:00
Fragment_Mesh ( dec , surf - > mesh ) ;
}
return ;
}
splitplane = node - > plane ;
dist = DotProduct ( dec - > center , splitplane - > normal ) - splitplane - > dist ;
if ( dist > dec - > radius )
{
Q3BSP_ClipDecalToNodes ( dec , node - > children [ 0 ] ) ;
return ;
}
if ( dist < - dec - > radius )
{
Q3BSP_ClipDecalToNodes ( dec , node - > children [ 1 ] ) ;
return ;
}
Q3BSP_ClipDecalToNodes ( dec , node - > children [ 0 ] ) ;
Q3BSP_ClipDecalToNodes ( dec , node - > children [ 1 ] ) ;
}
2009-11-04 21:16:50 +00:00
# endif
2009-10-06 00:33:54 +00:00
2005-09-08 22:52:46 +00:00
int Q1BSP_ClipDecal ( vec3_t center , vec3_t normal , vec3_t tangent1 , vec3_t tangent2 , float size , float * * out )
2005-05-13 10:42:48 +00:00
{ //quad marks a full, independant quad
int p ;
fragmentdecal_t dec ;
VectorCopy ( center , dec . center ) ;
VectorCopy ( normal , dec . normal ) ;
dec . radius = size / 2 ;
dec . numtris = 0 ;
2005-09-08 22:52:46 +00:00
VectorCopy ( tangent1 , dec . planenorm [ 0 ] ) ;
VectorNegate ( tangent1 , dec . planenorm [ 1 ] ) ;
VectorCopy ( tangent2 , dec . planenorm [ 2 ] ) ;
VectorNegate ( tangent2 , dec . planenorm [ 3 ] ) ;
2005-05-13 10:42:48 +00:00
VectorCopy ( dec . normal , dec . planenorm [ 4 ] ) ;
VectorNegate ( dec . normal , dec . planenorm [ 5 ] ) ;
for ( p = 0 ; p < 6 ; p + + )
dec . planedist [ p ] = - ( dec . radius - DotProduct ( dec . center , dec . planenorm [ p ] ) ) ;
2005-09-08 22:52:46 +00:00
dec . numplanes = 6 ;
2005-05-13 10:42:48 +00:00
2009-11-04 21:16:50 +00:00
sh_shadowframe + + ;
if ( cl . worldmodel - > fromgame = = fg_quake )
2009-10-06 00:33:54 +00:00
Q1BSP_ClipDecalToNodes ( & dec , cl . worldmodel - > nodes ) ;
2009-11-04 21:16:50 +00:00
# ifdef Q3BSPS
else if ( cl . worldmodel - > fromgame = = fg_quake3 )
Q3BSP_ClipDecalToNodes ( & dec , cl . worldmodel - > nodes ) ;
# endif
2005-05-13 10:42:48 +00:00
* out = ( float * ) decalfragmentverts ;
return dec . numtris ;
}
//This is spike's testing function, and is only usable by gl. :)
2006-02-11 14:51:36 +00:00
/*
2009-10-06 00:33:54 +00:00
# include "glquake.h"
2005-05-13 10:42:48 +00:00
void Q1BSP_TestClipDecal ( void )
{
int i ;
int numtris ;
vec3_t fwd ;
vec3_t start ;
2009-10-06 00:33:54 +00:00
vec3_t center , normal , tangent , tangent2 ;
2005-05-13 10:42:48 +00:00
float * verts ;
if ( cls . state ! = ca_active )
return ;
2009-10-06 00:33:54 +00:00
VectorCopy ( r_origin , start ) ;
// start[2]+=22;
2005-05-13 10:42:48 +00:00
VectorMA ( start , 10000 , vpn , fwd ) ;
2009-10-06 00:33:54 +00:00
if ( ! TraceLineN ( start , fwd , center , normal ) )
{
VectorCopy ( start , center ) ;
normal [ 0 ] = 0 ;
normal [ 1 ] = 0 ;
normal [ 2 ] = 1 ;
}
2005-05-13 10:42:48 +00:00
CrossProduct ( fwd , normal , tangent ) ;
VectorNormalize ( tangent ) ;
2009-10-06 00:33:54 +00:00
CrossProduct ( normal , tangent , tangent2 ) ;
numtris = Q1BSP_ClipDecal ( center , normal , tangent , tangent2 , 128 , & verts ) ;
PPL_RevertToKnownState ( ) ;
2005-05-13 10:42:48 +00:00
qglDisable ( GL_TEXTURE_2D ) ;
qglDisable ( GL_BLEND ) ;
2009-10-06 00:33:54 +00:00
qglDisable ( GL_ALPHA_TEST ) ;
2005-05-13 10:42:48 +00:00
qglDisable ( GL_DEPTH_TEST ) ;
qglColor3f ( 1 , 0 , 0 ) ;
qglShadeModel ( GL_SMOOTH ) ;
qglBegin ( GL_TRIANGLES ) ;
for ( i = 0 ; i < numtris ; i + + )
{
qglVertex3fv ( verts + i * 9 + 0 ) ;
qglVertex3fv ( verts + i * 9 + 3 ) ;
qglVertex3fv ( verts + i * 9 + 6 ) ;
}
qglEnd ( ) ;
qglColor3f ( 1 , 1 , 1 ) ;
qglBegin ( GL_LINES ) ;
for ( i = 0 ; i < numtris ; i + + )
{
qglVertex3fv ( verts + i * 9 + 0 ) ;
qglVertex3fv ( verts + i * 9 + 3 ) ;
qglVertex3fv ( verts + i * 9 + 3 ) ;
qglVertex3fv ( verts + i * 9 + 6 ) ;
qglVertex3fv ( verts + i * 9 + 6 ) ;
qglVertex3fv ( verts + i * 9 + 0 ) ;
}
qglVertex3fv ( center ) ;
VectorMA ( center , 10 , normal , fwd ) ;
qglVertex3fv ( fwd ) ;
qglColor3f ( 0 , 1 , 0 ) ;
qglVertex3fv ( center ) ;
VectorMA ( center , 10 , tangent , fwd ) ;
qglVertex3fv ( fwd ) ;
qglColor3f ( 0 , 0 , 1 ) ;
qglVertex3fv ( center ) ;
CrossProduct ( tangent , normal , fwd ) ;
VectorMA ( center , 10 , fwd , fwd ) ;
qglVertex3fv ( fwd ) ;
qglColor3f ( 1 , 1 , 1 ) ;
qglEnd ( ) ;
qglEnable ( GL_TEXTURE_2D ) ;
qglEnable ( GL_DEPTH_TEST ) ;
2009-10-06 00:33:54 +00:00
PPL_RevertToKnownState ( ) ;
2005-05-13 10:42:48 +00:00
}
2006-02-11 14:51:36 +00:00
*/
2005-05-13 10:42:48 +00:00
2004-08-21 01:25:48 +00:00
# endif
/*
Rendering functions ( Client only )
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Server only functions
*/
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-21 01:25:48 +00:00
//does the recursive work of Q1BSP_FatPVS
2009-06-21 17:45:33 +00:00
void SV_Q1BSP_AddToFatPVS ( model_t * mod , vec3_t org , mnode_t * node , qbyte * buffer , unsigned int buffersize )
2004-08-21 01:25:48 +00:00
{
int i ;
qbyte * pvs ;
mplane_t * plane ;
float d ;
while ( 1 )
{
// if this is a leaf, accumulate the pvs bits
if ( node - > contents < 0 )
{
if ( node - > contents ! = Q1CONTENTS_SOLID )
{
2009-07-11 20:56:09 +00:00
pvs = Q1BSP_LeafPVS ( mod , ( mleaf_t * ) node , NULL , 0 ) ;
2009-06-21 17:45:33 +00:00
for ( i = 0 ; i < buffersize ; i + + )
buffer [ i ] | = pvs [ i ] ;
2004-08-21 01:25:48 +00:00
}
return ;
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
plane = node - > plane ;
d = DotProduct ( org , plane - > normal ) - plane - > dist ;
if ( d > 8 )
node = node - > children [ 0 ] ;
else if ( d < - 8 )
node = node - > children [ 1 ] ;
else
{ // go down both
2009-06-21 17:45:33 +00:00
SV_Q1BSP_AddToFatPVS ( mod , org , node - > children [ 0 ] , buffer , buffersize ) ;
2004-08-21 01:25:48 +00:00
node = node - > children [ 1 ] ;
}
}
}
/*
= = = = = = = = = = = = =
Q1BSP_FatPVS
Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
given point .
= = = = = = = = = = = = =
*/
2009-06-23 21:49:44 +00:00
unsigned int Q1BSP_FatPVS ( model_t * mod , vec3_t org , qbyte * pvsbuffer , unsigned int buffersize , qboolean add )
2004-08-21 01:25:48 +00:00
{
2009-06-21 17:45:33 +00:00
unsigned int fatbytes = ( mod - > numleafs + 31 ) > > 3 ;
if ( fatbytes > buffersize )
Sys_Error ( " map had too much pvs data (too many leaves) \n " ) ; ;
2004-08-21 01:25:48 +00:00
if ( ! add )
2009-06-21 17:45:33 +00:00
Q_memset ( pvsbuffer , 0 , fatbytes ) ;
SV_Q1BSP_AddToFatPVS ( mod , org , mod - > nodes , pvsbuffer , fatbytes ) ;
2009-06-23 21:49:44 +00:00
return fatbytes ;
2004-08-21 01:25:48 +00:00
}
2011-01-29 19:53:38 +00:00
# endif
2010-07-11 02:22:39 +00:00
qboolean Q1BSP_EdictInFatPVS ( model_t * mod , struct pvscache_s * ent , qbyte * pvs )
2004-08-21 01:25:48 +00:00
{
int i ;
2005-05-13 10:42:48 +00:00
if ( ent - > num_leafs = = MAX_ENT_LEAFS + 1 )
return true ; //it's in too many leafs for us to cope with. Just trivially accept it.
2004-08-21 01:25:48 +00:00
for ( i = 0 ; i < ent - > num_leafs ; i + + )
2009-06-21 17:45:33 +00:00
if ( pvs [ ent - > leafnums [ i ] > > 3 ] & ( 1 < < ( ent - > leafnums [ i ] & 7 ) ) )
2004-08-21 01:25:48 +00:00
return true ; //we might be able to see this one.
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
return false ; //none of this ents leafs were visible, so neither is the ent.
}
/*
= = = = = = = = = = = = = = =
SV_FindTouchedLeafs
Links the edict to the right leafs so we can get it ' s potential visability .
= = = = = = = = = = = = = = =
*/
2010-07-11 02:22:39 +00:00
void Q1BSP_RFindTouchedLeafs ( model_t * wm , struct pvscache_s * ent , mnode_t * node , float * mins , float * maxs )
2004-08-21 01:25:48 +00:00
{
mplane_t * splitplane ;
mleaf_t * leaf ;
int sides ;
int leafnum ;
if ( node - > contents = = Q1CONTENTS_SOLID )
return ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
// add an efrag if the node is a leaf
if ( node - > contents < 0 )
{
2005-05-13 10:42:48 +00:00
if ( ent - > num_leafs > = MAX_ENT_LEAFS )
{
ent - > num_leafs = MAX_ENT_LEAFS + 1 ; //too many. mark it as such so we can trivially accept huge mega-big brush models.
2004-08-21 01:25:48 +00:00
return ;
2005-05-13 10:42:48 +00:00
}
2004-08-21 01:25:48 +00:00
leaf = ( mleaf_t * ) node ;
2010-07-11 02:22:39 +00:00
leafnum = leaf - wm - > leafs - 1 ;
2004-08-21 01:25:48 +00:00
ent - > leafnums [ ent - > num_leafs ] = leafnum ;
2006-03-04 20:43:48 +00:00
ent - > num_leafs + + ;
2004-08-21 01:25:48 +00:00
return ;
}
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
// NODE_MIXED
splitplane = node - > plane ;
2009-03-03 01:52:30 +00:00
sides = BOX_ON_PLANE_SIDE ( mins , maxs , splitplane ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
// recurse down the contacted sides
if ( sides & 1 )
2010-07-11 02:22:39 +00:00
Q1BSP_RFindTouchedLeafs ( wm , ent , node - > children [ 0 ] , mins , maxs ) ;
2006-03-04 20:43:48 +00:00
2004-08-21 01:25:48 +00:00
if ( sides & 2 )
2010-07-11 02:22:39 +00:00
Q1BSP_RFindTouchedLeafs ( wm , ent , node - > children [ 1 ] , mins , maxs ) ;
2004-08-21 01:25:48 +00:00
}
2010-07-11 02:22:39 +00:00
void Q1BSP_FindTouchedLeafs ( model_t * mod , struct pvscache_s * ent , float * mins , float * maxs )
2004-08-21 01:25:48 +00:00
{
ent - > num_leafs = 0 ;
2010-07-11 02:22:39 +00:00
if ( mins & & maxs )
Q1BSP_RFindTouchedLeafs ( mod , ent , mod - > nodes , mins , maxs ) ;
2004-08-21 01:25:48 +00:00
}
2005-08-26 22:56:51 +00:00
2004-08-21 01:25:48 +00:00
/*
Server only functions
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2005-08-26 22:56:51 +00:00
PVS type stuff
*/
/*
= = = = = = = = = = = = = = = = = = =
Mod_DecompressVis
= = = = = = = = = = = = = = = = = = =
*/
2009-07-11 20:56:09 +00:00
qbyte * Q1BSP_DecompressVis ( qbyte * in , model_t * model , qbyte * decompressed , unsigned int buffersize )
2005-08-26 22:56:51 +00:00
{
int c ;
qbyte * out ;
int row ;
2006-03-04 20:43:48 +00:00
row = ( model - > numleafs + 7 ) > > 3 ;
2005-08-26 22:56:51 +00:00
out = decompressed ;
2009-07-11 20:56:09 +00:00
if ( buffersize < row )
row = buffersize ;
2005-08-26 22:56:51 +00:00
#if 0
memcpy ( out , in , row ) ;
# else
if ( ! in )
{ // no vis info, so make all visible
while ( row )
{
* out + + = 0xff ;
row - - ;
}
2006-03-04 20:43:48 +00:00
return decompressed ;
2005-08-26 22:56:51 +00:00
}
do
{
if ( * in )
{
* out + + = * in + + ;
continue ;
}
2006-03-04 20:43:48 +00:00
2005-08-26 22:56:51 +00:00
c = in [ 1 ] ;
in + = 2 ;
while ( c )
{
* out + + = 0 ;
c - - ;
}
} while ( out - decompressed < row ) ;
# endif
2006-03-04 20:43:48 +00:00
2005-08-26 22:56:51 +00:00
return decompressed ;
}
static qbyte mod_novis [ MAX_MAP_LEAFS / 8 ] ;
2009-07-11 20:56:09 +00:00
qbyte * Q1BSP_LeafPVS ( model_t * model , mleaf_t * leaf , qbyte * buffer , unsigned int buffersize )
2005-08-26 22:56:51 +00:00
{
static qbyte decompressed [ MAX_MAP_LEAFS / 8 ] ;
if ( leaf = = model - > leafs )
return mod_novis ;
if ( ! buffer )
2009-07-11 20:56:09 +00:00
{
2005-08-26 22:56:51 +00:00
buffer = decompressed ;
2009-07-11 20:56:09 +00:00
buffersize = sizeof ( decompressed ) ;
}
2005-08-26 22:56:51 +00:00
2009-07-11 20:56:09 +00:00
return Q1BSP_DecompressVis ( leaf - > compressed_vis , model , buffer , buffersize ) ;
2005-08-26 22:56:51 +00:00
}
2009-07-11 20:56:09 +00:00
qbyte * Q1BSP_LeafnumPVS ( model_t * model , int leafnum , qbyte * buffer , unsigned int buffersize )
2005-08-26 22:56:51 +00:00
{
2009-07-11 20:56:09 +00:00
return Q1BSP_LeafPVS ( model , model - > leafs + leafnum , buffer , buffersize ) ;
2005-08-26 22:56:51 +00:00
}
//returns the leaf number, which is used as a bit index into the pvs.
int Q1BSP_LeafnumForPoint ( model_t * model , vec3_t p )
{
mnode_t * node ;
float d ;
mplane_t * plane ;
2006-03-04 20:43:48 +00:00
2005-08-26 22:56:51 +00:00
if ( ! model )
2006-03-04 20:43:48 +00:00
{
2005-08-26 22:56:51 +00:00
Sys_Error ( " Mod_PointInLeaf: bad model " ) ;
}
if ( ! model - > nodes )
return 0 ;
node = model - > nodes ;
while ( 1 )
{
if ( node - > contents < 0 )
return ( mleaf_t * ) node - model - > leafs ;
plane = node - > plane ;
d = DotProduct ( p , plane - > normal ) - plane - > dist ;
if ( d > 0 )
node = node - > children [ 0 ] ;
else
node = node - > children [ 1 ] ;
}
2006-03-04 20:43:48 +00:00
2005-08-26 22:56:51 +00:00
return 0 ; // never reached
}
mleaf_t * Q1BSP_LeafForPoint ( model_t * model , vec3_t p )
{
return model - > leafs + Q1BSP_LeafnumForPoint ( model , p ) ;
}
/*
PVS type stuff
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Init stuff
2004-08-21 01:25:48 +00:00
*/
2005-08-26 22:56:51 +00:00
void Q1BSP_Init ( void )
{
memset ( mod_novis , 0xff , sizeof ( mod_novis ) ) ;
}
//sets up the functions a server needs.
//fills in bspfuncs_t
void Q1BSP_SetModelFuncs ( model_t * mod )
{
# ifndef CLIENTONLY
mod - > funcs . FatPVS = Q1BSP_FatPVS ;
2011-01-29 19:53:38 +00:00
# endif
2005-08-26 22:56:51 +00:00
mod - > funcs . EdictInFatPVS = Q1BSP_EdictInFatPVS ;
2010-07-11 02:22:39 +00:00
mod - > funcs . FindTouchedLeafs = Q1BSP_FindTouchedLeafs ;
2005-08-26 22:56:51 +00:00
mod - > funcs . LightPointValues = NULL ;
mod - > funcs . StainNode = NULL ;
mod - > funcs . MarkLights = NULL ;
mod - > funcs . LeafnumForPoint = Q1BSP_LeafnumForPoint ;
mod - > funcs . LeafPVS = Q1BSP_LeafnumPVS ;
mod - > funcs . Trace = Q1BSP_Trace ;
mod - > funcs . PointContents = Q1BSP_PointContents ;
2006-03-04 20:43:48 +00:00
}