2011-02-27 01:01:22 +00:00
# include "quakedef.h"
2011-03-03 13:32:27 +00:00
# ifdef MAP_PROC
2011-02-27 01:01:22 +00:00
# ifndef SERVERONLY
# include "shader.h"
# endif
2013-07-14 12:22:51 +00:00
void Mod_SetParent ( mnode_t * node , mnode_t * parent ) ;
2013-07-29 17:36:44 +00:00
static int D3_LeafnumForPoint ( struct model_s * model , vec3_t point ) ;
2011-02-27 01:01:22 +00:00
2011-02-27 02:04:36 +00:00
# ifndef SERVERONLY
2013-07-29 17:36:44 +00:00
static qboolean Mod_LoadMap_Proc ( model_t * model , char * data )
2011-02-27 01:01:22 +00:00
{
char token [ 256 ] ;
2011-11-09 04:12:57 +00:00
int ver = 0 ;
2011-02-27 01:01:22 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
2011-11-09 04:12:57 +00:00
if ( ! strcmp ( token , " mapProcFile003 " ) )
ver = 3 ;
if ( ! strcmp ( token , " PROC " ) )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
ver = atoi ( token ) ;
}
if ( ver ! = 3 & & ver ! = 4 )
2011-02-27 01:01:22 +00:00
{
Con_Printf ( " proc format not compatible %s \n " , token ) ;
return false ;
}
/*FIXME: add sanity checks*/
2011-11-09 04:12:57 +00:00
if ( ver = = 4 )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
}
2011-02-27 01:01:22 +00:00
while ( 1 )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( ! data )
break ;
else if ( ! strcmp ( token , " model " ) )
{
batch_t * b ;
2013-07-27 12:22:12 +00:00
mesh_t * m , * * ml ;
2011-02-27 01:01:22 +00:00
model_t * sub ;
float f ;
int numsurfs , surf ;
int numverts , v , j ;
int numindicies ;
char * vdata ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " { " ) )
return false ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
sub = Mod_FindName ( va ( " *%s " , token ) ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
numsurfs = atoi ( token ) ;
if ( numsurfs < 0 | | numsurfs > 10000 )
return false ;
2013-07-27 12:22:12 +00:00
if ( numsurfs )
{
b = ZG_Malloc ( & model - > memgroup , sizeof ( * b ) * numsurfs ) ;
m = ZG_Malloc ( & model - > memgroup , sizeof ( * m ) * numsurfs ) ;
ml = ZG_Malloc ( & model - > memgroup , sizeof ( * ml ) * numsurfs ) ;
}
else
{
b = NULL ;
m = NULL ;
ml = NULL ;
}
2011-02-27 01:01:22 +00:00
sub - > numsurfaces = numsurfs ;
2011-11-09 04:12:57 +00:00
//ver4 may have a 'sky' field here
vdata = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " { " ) & & strcmp ( token , " } " ) )
{
//sky = atoi(token);
data = vdata ;
}
sub - > mins [ 0 ] = 99999999 ;
sub - > mins [ 1 ] = 99999999 ;
sub - > mins [ 2 ] = 99999999 ;
sub - > maxs [ 0 ] = - 99999999 ;
sub - > maxs [ 1 ] = - 99999999 ;
sub - > maxs [ 2 ] = - 99999999 ;
2011-02-27 01:01:22 +00:00
for ( surf = 0 ; surf < numsurfs ; surf + + )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " { " ) )
break ;
if ( ! data )
return false ;
2013-07-27 12:22:12 +00:00
b [ surf ] . maxmeshes = 1 ;
b [ surf ] . mesh = & ml [ surf ] ;
ml [ surf ] = & m [ surf ] ;
2012-07-05 19:42:36 +00:00
b [ surf ] . lightmap [ 0 ] = - 1 ;
b [ surf ] . lightmap [ 1 ] = - 1 ;
b [ surf ] . lightmap [ 2 ] = - 1 ;
b [ surf ] . lightmap [ 3 ] = - 1 ;
2011-02-27 01:01:22 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
b [ surf ] . shader = R_RegisterShader_Vertex ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
numverts = atoi ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
numindicies = atoi ( token ) ;
2013-07-27 12:22:12 +00:00
b [ surf ] . next = sub - > batches [ b [ surf ] . shader - > sort ] ;
sub - > batches [ b [ surf ] . shader - > sort ] = & b [ surf ] ;
2011-02-27 01:01:22 +00:00
m [ surf ] . numvertexes = numverts ;
m [ surf ] . numindexes = numindicies ;
2013-07-14 12:22:51 +00:00
vdata = ZG_Malloc ( & model - > memgroup , numverts * ( sizeof ( vecV_t ) + sizeof ( vec2_t ) + sizeof ( vec3_t ) + sizeof ( vec4_t ) ) + numindicies * sizeof ( index_t ) ) ;
2011-02-27 01:01:22 +00:00
2011-11-09 04:12:57 +00:00
m [ surf ] . colors4f_array = ( vec4_t * ) vdata ; vdata + = sizeof ( vec4_t ) * numverts ;
2011-02-27 01:01:22 +00:00
m [ surf ] . xyz_array = ( vecV_t * ) vdata ; vdata + = sizeof ( vecV_t ) * numverts ;
m [ surf ] . st_array = ( vec2_t * ) vdata ; vdata + = sizeof ( vec2_t ) * numverts ;
m [ surf ] . normals_array = ( vec3_t * ) vdata ; vdata + = sizeof ( vec3_t ) * numverts ;
m [ surf ] . indexes = ( index_t * ) vdata ;
for ( v = 0 ; v < numverts ; v + + )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ( " ) )
return false ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . xyz_array [ v ] [ 0 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . xyz_array [ v ] [ 1 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . xyz_array [ v ] [ 2 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . st_array [ v ] [ 0 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . st_array [ v ] [ 1 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . normals_array [ v ] [ 0 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . normals_array [ v ] [ 1 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . normals_array [ v ] [ 2 ] = atof ( token ) ;
for ( j = 0 ; j < 3 ; j + + )
{
f = m [ surf ] . xyz_array [ v ] [ j ] ;
if ( f > sub - > maxs [ j ] )
sub - > maxs [ j ] = f ;
2011-11-09 04:12:57 +00:00
if ( f < sub - > mins [ j ] )
2011-02-27 01:01:22 +00:00
sub - > mins [ j ] = f ;
}
2011-11-09 04:12:57 +00:00
m [ surf ] . colors4f_array [ v ] [ 0 ] = 255 ;
m [ surf ] . colors4f_array [ v ] [ 1 ] = 255 ;
m [ surf ] . colors4f_array [ v ] [ 2 ] = 255 ;
m [ surf ] . colors4f_array [ v ] [ 3 ] = 255 ;
2011-02-27 01:01:22 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
2011-11-09 04:12:57 +00:00
/*if its not closed yet, there's an optional colour value*/
2011-02-27 01:01:22 +00:00
if ( strcmp ( token , " ) " ) )
2011-11-09 04:12:57 +00:00
{
m [ surf ] . colors4f_array [ v ] [ 0 ] = atof ( token ) / 255 ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . colors4f_array [ v ] [ 1 ] = atof ( token ) / 255 ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . colors4f_array [ v ] [ 2 ] = atof ( token ) / 255 ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . colors4f_array [ v ] [ 3 ] = atof ( token ) / 255 ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ) " ) )
return false ;
}
2011-02-27 01:01:22 +00:00
}
for ( v = 0 ; v < numindicies ; v + + )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
m [ surf ] . indexes [ v ] = atoi ( token ) ;
}
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " } " ) )
return false ;
}
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " } " ) )
return false ;
sub - > needload = false ;
sub - > fromgame = fg_doom3 ;
sub - > type = mod_brush ;
2013-07-27 12:22:12 +00:00
BE_GenBrushModelVBO ( sub ) ;
2011-02-27 01:01:22 +00:00
}
else if ( ! strcmp ( token , " shadowModel " ) )
{
int numverts , v ;
int numindexes , i ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " { " ) )
return false ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
//name
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
numverts = atoi ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
//nocaps
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
//nofrontcaps
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
numindexes = atoi ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
//planebits
for ( v = 0 ; v < numverts ; v + + )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ( " ) )
return false ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
//x
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
//y
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
//z
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ) " ) )
return false ;
}
for ( i = 0 ; i < numindexes ; i + + )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
}
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " } " ) )
return false ;
}
else if ( ! strcmp ( token , " nodes " ) )
{
int numnodes , n ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " { " ) )
return false ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
numnodes = atoi ( token ) ;
2013-07-14 12:22:51 +00:00
model - > nodes = ZG_Malloc ( & model - > memgroup , sizeof ( * model - > nodes ) * numnodes ) ;
model - > planes = ZG_Malloc ( & model - > memgroup , sizeof ( * model - > planes ) * numnodes ) ;
2011-02-27 01:01:22 +00:00
for ( n = 0 ; n < numnodes ; n + + )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ( " ) )
return false ;
model - > nodes [ n ] . plane = & model - > planes [ n ] ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
model - > planes [ n ] . normal [ 0 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
model - > planes [ n ] . normal [ 1 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
model - > planes [ n ] . normal [ 2 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
model - > planes [ n ] . dist = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ) " ) )
return false ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
model - > nodes [ n ] . childnum [ 0 ] = atoi ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
model - > nodes [ n ] . childnum [ 1 ] = atoi ( token ) ;
}
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " } " ) )
return false ;
2013-07-14 12:22:51 +00:00
Mod_SetParent ( model - > nodes , NULL ) ;
2011-02-27 01:01:22 +00:00
}
else if ( ! strcmp ( token , " interAreaPortals " ) )
{
2013-05-11 05:03:07 +00:00
//int numareas;
2011-02-27 01:01:22 +00:00
int pno , v ;
portal_t * p ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " { " ) )
return false ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
2013-05-11 05:03:07 +00:00
//numareas = atoi(token);
2011-02-27 01:01:22 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
model - > numportals = atoi ( token ) ;
2013-07-14 12:22:51 +00:00
model - > portal = p = ZG_Malloc ( & model - > memgroup , sizeof ( * p ) * model - > numportals ) ;
2011-02-27 01:01:22 +00:00
for ( pno = 0 ; pno < model - > numportals ; pno + + , p + + )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
p - > numpoints = atoi ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
p - > area [ 0 ] = atoi ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
p - > area [ 1 ] = atoi ( token ) ;
2013-07-14 12:22:51 +00:00
p - > points = ZG_Malloc ( & model - > memgroup , sizeof ( * p - > points ) * p - > numpoints ) ;
2011-02-27 01:01:22 +00:00
ClearBounds ( p - > min , p - > max ) ;
for ( v = 0 ; v < p - > numpoints ; v + + )
{
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ( " ) )
return false ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
p - > points [ v ] [ 0 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
p - > points [ v ] [ 1 ] = atof ( token ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
p - > points [ v ] [ 2 ] = atof ( token ) ;
p - > points [ v ] [ 3 ] = 1 ;
AddPointToBounds ( p - > points [ v ] , p - > min , p - > max ) ;
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ) " ) )
return false ;
}
}
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " } " ) )
return false ;
}
else
{
Con_Printf ( " unexpected token %s \n " , token ) ;
return false ;
}
}
return true ;
}
qboolean R_CullBox ( vec3_t mins , vec3_t maxs ) ;
static int walkno ;
/*convert each portal to a 2d box, because its much much simpler than true poly clipping*/
2013-07-29 17:36:44 +00:00
static void D3_WalkPortal ( model_t * mod , int start , vec_t bounds [ 4 ] , unsigned char * vis )
2011-02-27 01:01:22 +00:00
{
int i ;
portal_t * p ;
int side ;
vec_t newbounds [ 4 ] ;
vis [ start > > 3 ] | = 1 < < ( start & 7 ) ;
for ( i = 0 ; i < mod - > numportals ; i + + )
{
p = mod - > portal + i ;
if ( p - > walkno = = walkno )
continue ;
if ( p - > area [ 0 ] = = start )
side = 0 ;
else if ( p - > area [ 1 ] = = start )
side = 1 ;
else
continue ;
2011-11-09 04:12:57 +00:00
if ( R_CullBox ( p - > min , p - > max ) )
2011-02-27 01:01:22 +00:00
{
continue ;
}
p - > walkno = walkno ;
D3_WalkPortal ( mod , p - > area [ ! side ] , newbounds , vis ) ;
}
}
unsigned char * D3_CalcVis ( model_t * mod , vec3_t org )
{
int start ;
static unsigned char vis [ 256 ] ;
vec_t newbounds [ 4 ] ;
start = D3_LeafnumForPoint ( mod , org ) ;
/*figure out which area we're in*/
if ( start < 0 )
{
/*outside the world, just make it all visible, and take the fps hit*/
memset ( vis , 255 , 4 ) ;
return vis ;
}
else if ( r_novis . value )
return vis ;
else
{
memset ( vis , 0 , 4 ) ;
/*make a bounds the size of the view*/
newbounds [ 0 ] = - 1 ;
newbounds [ 1 ] = 1 ;
newbounds [ 2 ] = - 1 ;
newbounds [ 3 ] = 1 ;
walkno + + ;
D3_WalkPortal ( mod , start , newbounds , vis ) ;
// Con_Printf("%x %x %x %x\n", vis[0], vis[1], vis[2], vis[3]);
return vis ;
}
}
/*emits static entities, one for each area, which is only visible if that area is in the vis*/
void D3_GenerateAreas ( model_t * mod )
{
entity_t * ent ;
int area ;
for ( area = 0 ; area < 256 * 8 ; area + + )
{
if ( cl . num_statics = = cl_max_static_entities )
{
cl_max_static_entities + = 16 ;
cl_static_entities = BZ_Realloc ( cl_static_entities , sizeof ( * cl_static_entities ) * cl_max_static_entities ) ;
}
ent = & cl_static_entities [ cl . num_statics ] . ent ;
cl_static_entities [ cl . num_statics ] . mdlidx = 0 ;
memset ( ent , 0 , sizeof ( * ent ) ) ;
ent - > model = Mod_FindName ( va ( " *_area%i " , area ) ) ;
ent - > scale = 1 ;
AngleVectors ( ent - > angles , ent - > axis [ 0 ] , ent - > axis [ 1 ] , ent - > axis [ 2 ] ) ;
VectorInverse ( ent - > axis [ 1 ] ) ;
ent - > shaderRGBAf [ 0 ] = 1 ;
ent - > shaderRGBAf [ 1 ] = 1 ;
ent - > shaderRGBAf [ 2 ] = 1 ;
ent - > shaderRGBAf [ 3 ] = 1 ;
/*put it in that area*/
cl_static_entities [ cl . num_statics ] . pvscache . num_leafs = 1 ;
cl_static_entities [ cl . num_statics ] . pvscache . leafnums [ 0 ] = area ;
if ( ent - > model & & ! ent - > model - > needload )
cl . num_statics + + ;
else
break ;
}
}
2011-02-27 02:04:36 +00:00
# endif
//edict system as opposed to q2 game dll system.
2013-07-29 17:36:44 +00:00
static void D3_FindTouchedLeafs ( struct model_s * model , struct pvscache_s * ent , vec3_t cullmins , vec3_t cullmaxs )
2011-02-27 02:04:36 +00:00
{
}
2013-07-29 17:36:44 +00:00
static qbyte * D3_LeafPVS ( struct model_s * model , int num , qbyte * buffer , unsigned int buffersize )
2011-02-27 02:04:36 +00:00
{
2013-07-29 17:36:44 +00:00
memset ( buffer , 0xff , buffersize ) ;
2011-02-27 02:04:36 +00:00
return buffer ;
}
2013-07-29 17:36:44 +00:00
static int D3_LeafnumForPoint ( struct model_s * model , vec3_t point )
2011-02-27 02:04:36 +00:00
{
float p ;
int c ;
mnode_t * node ;
node = model - > nodes ;
while ( 1 )
{
p = DotProduct ( point , node - > plane - > normal ) + node - > plane - > dist ;
c = node - > childnum [ p < 0 ] ;
if ( c < = 0 )
return - 1 - c ;
node = model - > nodes + c ;
}
return 0 ;
}
2013-07-29 17:36:44 +00:00
static unsigned int D3_FatPVS ( struct model_s * model , vec3_t org , qbyte * pvsbuffer , unsigned int buffersize , qboolean merge )
2011-02-27 02:04:36 +00:00
{
return 0 ;
}
2013-07-29 17:36:44 +00:00
static void D3_StainNode ( struct mnode_s * node , float * parms )
2011-02-27 02:04:36 +00:00
{
}
2013-07-29 17:36:44 +00:00
static void D3_LightPointValues ( struct model_s * model , vec3_t point , vec3_t res_diffuse , vec3_t res_ambient , vec3_t res_dir )
2011-02-27 02:04:36 +00:00
{
2011-11-09 04:12:57 +00:00
/*basically require rtlighting for any light*/
2011-02-27 02:04:36 +00:00
VectorClear ( res_diffuse ) ;
VectorClear ( res_ambient ) ;
VectorClear ( res_dir ) ;
res_dir [ 2 ] = 1 ;
}
2013-07-29 17:36:44 +00:00
static qboolean D3_EdictInFatPVS ( struct model_s * model , struct pvscache_s * edict , qbyte * pvsbuffer )
2011-02-27 02:04:36 +00:00
{
2011-12-05 15:23:40 +00:00
int i ;
for ( i = 0 ; i < edict - > num_leafs ; i + + )
if ( pvsbuffer [ edict - > leafnums [ i ] > > 3 ] & ( 1u < < ( edict - > leafnums [ i ] & 7 ) ) )
2011-02-27 02:04:36 +00:00
return true ;
2011-12-05 15:23:40 +00:00
return false ;
2011-11-09 04:12:57 +00:00
}
typedef struct cm_surface_s
{
vec3_t mins , maxs ;
vec4_t plane ;
int numedges ;
vec4_t * edge ;
shader_t * shader ;
struct cm_surface_s * next ;
} cm_surface_t ;
typedef struct cm_brush_s
{
2011-12-05 15:23:40 +00:00
vec3_t mins , maxs ;
2011-11-09 04:12:57 +00:00
int numplanes ;
vec4_t * plane ;
unsigned int contents ;
struct cm_brush_s * next ;
} cm_brush_t ;
typedef struct cm_node_s
{
int axis ; /*0=x,1=y,2=z*/
float dist ;
vec3_t mins , maxs ;
struct cm_node_s * parent ;
struct cm_node_s * child [ 2 ] ;
2011-12-05 15:23:40 +00:00
cm_brush_t * brushlist ;
2011-11-09 04:12:57 +00:00
cm_surface_t * surfacelist ;
} cm_node_t ;
static struct
{
float truefraction ;
qboolean ispoint ;
vec3_t start ;
vec3_t end ;
vec3_t absmins , absmaxs ;
vec3_t szmins , szmaxs ;
vec3_t extents ;
cm_surface_t * surf ;
} traceinfo ;
# define DIST_EPSILON (0.03125)
static void D3_TraceToLeaf ( cm_node_t * leaf )
{
float diststart ;
float distend ;
float frac ;
vec3_t impactpoint ;
qboolean back ;
int i , j ;
float pdist , expand ;
vec3_t ofs ;
cm_surface_t * surf ;
for ( surf = leaf - > surfacelist ; surf ; surf = surf - > next )
{
/*lots of maths in this function, we should check the surf's bbox*/
if ( surf - > mins [ 0 ] > traceinfo . absmaxs [ 0 ] | | traceinfo . absmins [ 0 ] > surf - > maxs [ 0 ] | |
surf - > mins [ 1 ] > traceinfo . absmaxs [ 1 ] | | traceinfo . absmins [ 1 ] > surf - > maxs [ 1 ] | |
surf - > mins [ 2 ] > traceinfo . absmaxs [ 2 ] | | traceinfo . absmins [ 2 ] > surf - > maxs [ 2 ] )
continue ;
if ( ! traceinfo . ispoint )
{ // general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for ( i = 0 ; i < 3 ; i + + )
{
if ( surf - > plane [ i ] < 0 )
ofs [ i ] = traceinfo . szmaxs [ i ] ;
else
ofs [ i ] = traceinfo . szmins [ i ] ;
}
expand = DotProduct ( ofs , surf - > plane ) ;
// pdist = surf->plane[3] - expand;
}
else
{ // special point case
// pdist = surf->plane[3];
expand = 0 ;
}
diststart = DotProduct ( traceinfo . start , surf - > plane ) ;
/*started behind?*/
back = diststart < surf - > plane [ 3 ] ;
if ( diststart < = surf - > plane [ 3 ] - expand )
{
/*the trace started behind our expanded front plane*/
/*don't stop just because the point is closer than the extended plane*/
/*epsilon here please*/
if ( diststart < = surf - > plane [ 3 ] )
continue ;
distend = DotProduct ( traceinfo . end , surf - > plane ) ;
if ( distend < diststart )
frac = 0 ; /*don't let us go further into the wall*/
else
continue ;
}
else
{
distend = DotProduct ( traceinfo . end , surf - > plane ) ;
/*ended on the other side*/
if ( back )
{
if ( distend + expand > - surf - > plane [ 3 ] )
continue ;
}
else
{
if ( distend + expand > surf - > plane [ 3 ] )
continue ;
}
if ( diststart = = distend )
frac = 0 ;
else
frac = ( diststart - ( surf - > plane [ 3 ] - expand ) ) / ( diststart - distend ) ;
}
/*give up if we already found a closer plane*/
if ( frac > = traceinfo . truefraction )
continue ;
/*okay, this is where it hits this plane*/
impactpoint [ 0 ] = traceinfo . start [ 0 ] + frac * ( traceinfo . end [ 0 ] - traceinfo . start [ 0 ] ) ;
impactpoint [ 1 ] = traceinfo . start [ 1 ] + frac * ( traceinfo . end [ 1 ] - traceinfo . start [ 1 ] ) ;
impactpoint [ 2 ] = traceinfo . start [ 2 ] + frac * ( traceinfo . end [ 2 ] - traceinfo . start [ 2 ] ) ;
/*if the impact was not on the surface*/
for ( i = 0 ; i < surf - > numedges ; i + + )
{
if ( ! traceinfo . ispoint )
{ // general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for ( j = 0 ; j < 3 ; j + + )
{
if ( surf - > edge [ i ] [ j ] < 0 )
ofs [ j ] = traceinfo . szmaxs [ j ] ;
else
ofs [ j ] = traceinfo . szmins [ j ] ;
}
pdist = DotProduct ( ofs , surf - > edge [ i ] ) ;
pdist = surf - > edge [ i ] [ 3 ] - pdist ;
}
else
{ // special point case
pdist = surf - > edge [ i ] [ 3 ] ;
}
2011-12-05 15:23:40 +00:00
if ( DotProduct ( impactpoint , surf - > edge [ i ] ) > pdist )
2011-11-09 04:12:57 +00:00
{
break ;
}
}
/*if we were inside all edges, we hit the surface*/
if ( i = = surf - > numedges )
{
traceinfo . truefraction = frac ;
traceinfo . surf = surf ;
/*we can't early out. there are multiple surfs in each leaf, and they could overlap. earlying out will result in errors if we hit a further one before the nearer*/
}
}
}
/*returns the most distant node which contains the entire box*/
static cm_node_t * D3_ChildNodeForBox ( cm_node_t * node , vec3_t mins , vec3_t maxs )
{
float t1 , t2 ;
for ( ; ; )
{
2011-12-05 15:23:40 +00:00
t1 = mins [ node - > axis ] - node - > dist ;
t2 = maxs [ node - > axis ] - node - > dist ;
2011-11-09 04:12:57 +00:00
//if its completely to one side, walk down that side
if ( t1 > maxs [ node - > axis ] & & t2 > maxs [ node - > axis ] )
{
//if this is a leaf, we can't insert in a child anyway.
if ( ! node - > child [ 0 ] )
break ;
node = node - > child [ 0 ] ;
continue ;
}
if ( t1 < mins [ node - > axis ] & & t2 < mins [ node - > axis ] )
{
//if this is a leaf, we can't insert in a child anyway.
if ( ! node - > child [ 1 ] )
break ;
node = node - > child [ 1 ] ;
continue ;
}
//the box crosses this node
break ;
}
2011-12-05 15:23:40 +00:00
2011-11-09 04:12:57 +00:00
return node ;
}
static void D3_InsertClipSurface ( cm_node_t * node , cm_surface_t * surf )
{
node = D3_ChildNodeForBox ( node , surf - > mins , surf - > maxs ) ;
surf - > next = node - > surfacelist ;
node - > surfacelist = surf ;
}
2011-12-05 15:23:40 +00:00
static void D3_InsertClipBrush ( cm_node_t * node , cm_brush_t * brush )
{
node = D3_ChildNodeForBox ( node , brush - > mins , brush - > maxs ) ;
brush - > next = node - > brushlist ;
node - > brushlist = brush ;
}
2011-11-09 04:12:57 +00:00
static void D3_RecursiveSurfCheck ( cm_node_t * node , float p1f , float p2f , vec3_t p1 , vec3_t p2 )
{
float t1 , t2 , offset ;
float frac , frac2 ;
float idist ;
int i ;
vec3_t mid ;
int side ;
float midf ;
if ( traceinfo . truefraction < = p1f )
return ; // already hit something nearer
/*err, no child here*/
if ( ! node )
return ;
D3_TraceToLeaf ( node ) ;
//
// find the point distances to the seperating plane
// and the offset for the size of the box
//
t1 = p1 [ node - > axis ] - node - > dist ;
t2 = p2 [ node - > axis ] - node - > dist ;
offset = traceinfo . extents [ node - > axis ] ;
#if 0
D3_RecursiveHullCheck ( node - > childnum [ 0 ] , p1f , p2f , p1 , p2 ) ;
D3_RecursiveHullCheck ( node - > childnum [ 1 ] , p1f , p2f , p1 , p2 ) ;
return ;
# endif
// see which sides we need to consider
if ( t1 > = offset & & t2 > = offset )
{
D3_RecursiveSurfCheck ( node - > child [ 0 ] , p1f , p2f , p1 , p2 ) ;
return ;
}
if ( t1 < - offset & & t2 < - offset )
{
D3_RecursiveSurfCheck ( node - > child [ 1 ] , p1f , p2f , p1 , p2 ) ;
return ;
}
// put the crosspoint DIST_EPSILON pixels on the near side
if ( t1 < t2 )
{
idist = 1.0 / ( t1 - t2 ) ;
side = 1 ;
frac2 = ( t1 + offset + DIST_EPSILON ) * idist ;
frac = ( t1 - offset + DIST_EPSILON ) * idist ;
}
else if ( t1 > t2 )
{
idist = 1.0 / ( t1 - t2 ) ;
side = 0 ;
frac2 = ( t1 - offset - DIST_EPSILON ) * idist ;
frac = ( t1 + offset + DIST_EPSILON ) * idist ;
}
else
{
side = 0 ;
frac = 1 ;
frac2 = 0 ;
}
// move up to the node
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 ] ) ;
D3_RecursiveSurfCheck ( node - > child [ side ] , p1f , midf , p1 , mid ) ;
// go past the node
if ( frac2 < 0 )
frac2 = 0 ;
if ( frac2 > 1 )
frac2 = 1 ;
midf = p1f + ( p2f - p1f ) * frac2 ;
for ( i = 0 ; i < 3 ; i + + )
mid [ i ] = p1 [ i ] + frac2 * ( p2 [ i ] - p1 [ i ] ) ;
D3_RecursiveSurfCheck ( node - > child [ side ^ 1 ] , midf , p2f , mid , p2 ) ;
}
2013-07-29 17:36:44 +00:00
static qboolean D3_Trace ( struct model_s * model , int hulloverride , int frame , vec3_t axis [ 3 ] , vec3_t p1 , vec3_t p2 , vec3_t mins , vec3_t maxs , unsigned int hitcontentsmask , struct trace_s * trace )
2011-11-09 04:12:57 +00:00
{
int i ;
float e1 , e2 ;
traceinfo . truefraction = 1 ;
VectorCopy ( p1 , traceinfo . start ) ;
VectorCopy ( p2 , traceinfo . end ) ;
for ( i = 0 ; i < 3 ; i + + )
{
e1 = fabs ( mins [ i ] ) ;
e2 = fabs ( maxs [ i ] ) ;
traceinfo . extents [ i ] = ( ( e1 > e2 ) ? e1 : e2 ) ;
traceinfo . szmins [ i ] = mins [ i ] ;
traceinfo . szmaxs [ i ] = maxs [ i ] ;
traceinfo . absmins [ i ] = ( ( p1 [ i ] < p2 [ i ] ) ? p1 [ i ] : p2 [ i ] ) + mins [ i ] ;
traceinfo . absmaxs [ i ] = ( ( p1 [ i ] > p2 [ i ] ) ? p1 [ i ] : p2 [ i ] ) + maxs [ i ] ;
}
traceinfo . ispoint = ! traceinfo . extents [ 0 ] & & ! traceinfo . extents [ 1 ] & & ! traceinfo . extents [ 2 ] ;
traceinfo . surf = NULL ;
D3_RecursiveSurfCheck ( model - > cnodes , 0 , 1 , p1 , p2 ) ;
memset ( trace , 0 , sizeof ( * trace ) ) ;
if ( ! traceinfo . surf )
{
trace - > fraction = 1 ;
VectorCopy ( p2 , trace - > endpos ) ;
}
else
{
2011-12-05 15:23:40 +00:00
float frac ;
2011-11-09 04:12:57 +00:00
/*we now know which surface it hit. recalc the impact point, but with an epsilon this time, so we can never get too close to the surface*/
VectorCopy ( traceinfo . surf - > plane , trace - > plane . normal ) ;
if ( ! traceinfo . ispoint )
{ // general box case
vec3_t ofs ;
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for ( i = 0 ; i < 3 ; i + + )
{
if ( traceinfo . surf - > plane [ i ] < 0 )
ofs [ i ] = traceinfo . szmaxs [ i ] ;
else
ofs [ i ] = traceinfo . szmins [ i ] ;
}
e1 = DotProduct ( ofs , traceinfo . surf - > plane ) ;
trace - > plane . dist = traceinfo . surf - > plane [ 3 ] - e1 ;
}
else
{ // special point case
trace - > plane . dist = traceinfo . surf - > plane [ 3 ] ;
}
frac = traceinfo . truefraction ;
/*
diststart = DotProduct ( traceinfo . start , trace - > plane . normal ) ;
distend = DotProduct ( traceinfo . end , trace - > plane . normal ) ;
if ( diststart = = distend )
frac = 0 ;
else
{
frac = ( diststart - trace - > plane . dist ) / ( diststart - distend ) ;
if ( frac < 0 )
frac = 0 ;
else if ( frac > 1 )
frac = 1 ;
} */
/*okay, this is where it hits this plane*/
trace - > endpos [ 0 ] = traceinfo . start [ 0 ] + frac * ( traceinfo . end [ 0 ] - traceinfo . start [ 0 ] ) ;
trace - > endpos [ 1 ] = traceinfo . start [ 1 ] + frac * ( traceinfo . end [ 1 ] - traceinfo . start [ 1 ] ) ;
trace - > endpos [ 2 ] = traceinfo . start [ 2 ] + frac * ( traceinfo . end [ 2 ] - traceinfo . start [ 2 ] ) ;
trace - > fraction = frac ;
}
trace - > ent = NULL ;
2011-02-27 02:04:36 +00:00
return false ;
}
2013-07-29 17:36:44 +00:00
static unsigned int D3_PointContents ( struct model_s * model , vec3_t axis [ 3 ] , vec3_t p )
2011-11-09 04:12:57 +00:00
{
2011-12-05 15:23:40 +00:00
cm_node_t * node = model - > cnodes ;
cm_brush_t * brush ;
float t1 ;
unsigned int contents = 0 ;
int i ;
if ( axis )
{
vec3_t tmp ;
VectorCopy ( p , tmp ) ;
p [ 0 ] = DotProduct ( tmp , axis [ 0 ] ) ;
p [ 1 ] = DotProduct ( tmp , axis [ 1 ] ) ;
p [ 2 ] = DotProduct ( tmp , axis [ 2 ] ) ;
}
while ( node )
{
for ( brush = node - > brushlist ; brush ; brush = brush - > next )
{
if ( brush - > mins [ 0 ] > p [ 0 ] | | p [ 0 ] > brush - > maxs [ 0 ] | |
brush - > mins [ 1 ] > p [ 1 ] | | p [ 1 ] > brush - > maxs [ 1 ] | |
brush - > mins [ 2 ] > p [ 2 ] | | p [ 2 ] > brush - > maxs [ 2 ] )
continue ;
for ( i = 0 ; i < brush - > numplanes ; i + + )
{
if ( DotProduct ( p , brush - > plane [ i ] ) > brush - > plane [ i ] [ 3 ] )
break ;
}
if ( i = = brush - > numplanes )
contents | = brush - > contents ;
}
t1 = p [ node - > axis ] - node - > dist ;
// see which side we need to go down
if ( t1 > = 0 )
{
node = node - > child [ 0 ] ;
}
else
{
node = node - > child [ 1 ] ;
}
}
return contents ;
2011-11-09 04:12:57 +00:00
}
# define ensurenewtoken(t) buf = COM_ParseOut(buf, token, sizeof(token)); if (strcmp(token, t)) break;
2013-07-29 17:36:44 +00:00
static int D3_ParseContents ( char * str )
2011-12-05 15:23:40 +00:00
{
char * e , * n ;
unsigned int contents = 0 ;
while ( str )
{
e = strchr ( str , ' , ' ) ;
if ( e )
{
* e = 0 ;
n = e + 1 ;
}
else
n = NULL ;
if ( ! strcmp ( str , " solid " ) | | ! strcmp ( str , " opaque " ) )
contents | = FTECONTENTS_SOLID ;
else if ( ! strcmp ( str , " playerclip " ) )
contents | = FTECONTENTS_PLAYERCLIP ;
else if ( ! strcmp ( str , " monsterclip " ) )
contents | = FTECONTENTS_PLAYERCLIP ;
else
Con_Printf ( " Unknown contents type \" %s \" \n " , str ) ;
str = n ;
}
return contents ;
}
2011-11-09 04:12:57 +00:00
typedef struct
{
int v [ 2 ] ;
int fl [ 2 ] ;
} d3edge_t ;
2011-02-27 01:01:22 +00:00
qboolean D3_LoadMap_CollisionMap ( model_t * mod , char * buf )
{
2011-11-09 04:12:57 +00:00
int pedges [ 64 ] ;
cm_surface_t * surf ;
2011-12-05 15:23:40 +00:00
cm_brush_t * brush ;
2011-11-09 04:12:57 +00:00
vec3_t * verts ;
d3edge_t * edges ;
int i , j ;
2011-12-05 15:23:40 +00:00
int filever = 0 ;
2011-11-09 04:12:57 +00:00
int numverts , numedges , numpedges ;
model_t * cmod ;
2011-02-27 01:01:22 +00:00
char token [ 256 ] ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
if ( strcmp ( token , " CM " ) )
return false ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
filever = atof ( token ) ;
if ( filever ! = 1 & & filever ! = 3 )
2011-02-27 01:01:22 +00:00
return false ;
2011-11-09 04:12:57 +00:00
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
/*some number, discard*/
while ( buf )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
if ( ! strcmp ( token , " collisionModel " ) )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
if ( ! strcmp ( token , " worldMap " ) )
cmod = mod ;
else
cmod = Mod_FindName ( token ) ;
2011-12-05 15:23:40 +00:00
if ( filever = = 3 )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
/*don't know*/
}
ClearBounds ( cmod - > mins , cmod - > maxs ) ;
2011-11-09 04:12:57 +00:00
ensurenewtoken ( " { " ) ;
ensurenewtoken ( " vertices " ) ;
ensurenewtoken ( " { " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
numverts = atoi ( token ) ;
verts = malloc ( numverts * sizeof ( * verts ) ) ;
for ( i = 0 ; i < numverts ; i + + )
{
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
verts [ i ] [ 0 ] = atof ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
verts [ i ] [ 1 ] = atof ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
verts [ i ] [ 2 ] = atof ( token ) ;
ensurenewtoken ( " ) " ) ;
}
ensurenewtoken ( " } " ) ;
ensurenewtoken ( " edges " ) ;
ensurenewtoken ( " { " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
numedges = atoi ( token ) ;
edges = malloc ( numedges * sizeof ( * edges ) ) ;
for ( i = 0 ; i < numedges ; i + + )
{
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
edges [ i ] . v [ 0 ] = atoi ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
edges [ i ] . v [ 1 ] = atoi ( token ) ;
ensurenewtoken ( " ) " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
edges [ i ] . fl [ 0 ] = atoi ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
edges [ i ] . fl [ 1 ] = atoi ( token ) ;
}
ensurenewtoken ( " } " ) ;
ensurenewtoken ( " nodes " ) ;
ensurenewtoken ( " { " ) ;
2013-07-14 12:22:51 +00:00
cmod - > cnodes = ZG_Malloc ( & mod - > memgroup , sizeof ( cm_node_t ) ) ;
2011-11-09 04:12:57 +00:00
for ( ; ; )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
if ( strcmp ( token , " ( " ) )
break ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
//axis, dist
ensurenewtoken ( " ) " ) ;
}
if ( strcmp ( token , " } " ) )
break ;
ensurenewtoken ( " polygons " ) ;
2011-12-05 15:23:40 +00:00
if ( filever = = 1 )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
/*'polygonMemory', which is unusable for us*/
}
else
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
/*numPolygons*/
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
/*numPolygonEdges*/
}
2011-11-09 04:12:57 +00:00
ensurenewtoken ( " { " ) ;
for ( ; ; )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
if ( ! strcmp ( token , " } " ) )
break ;
numpedges = atoi ( token ) ;
2013-07-14 12:22:51 +00:00
surf = ZG_Malloc ( & mod - > memgroup , sizeof ( * surf ) + sizeof ( vec4_t ) * numpedges ) ;
2011-11-09 04:12:57 +00:00
surf - > numedges = numpedges ;
surf - > edge = ( vec4_t * ) ( surf + 1 ) ;
ensurenewtoken ( " ( " ) ;
for ( j = 0 ; j < numpedges ; j + + )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
pedges [ j ] = atoi ( token ) ;
}
ensurenewtoken ( " ) " ) ;
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > plane [ 0 ] = atof ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > plane [ 1 ] = atof ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > plane [ 2 ] = atof ( token ) ;
ensurenewtoken ( " ) " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > plane [ 3 ] = atof ( token ) ;
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > mins [ 0 ] = atof ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > mins [ 1 ] = atof ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > mins [ 2 ] = atof ( token ) ;
ensurenewtoken ( " ) " ) ;
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > maxs [ 0 ] = atof ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > maxs [ 1 ] = atof ( token ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
surf - > maxs [ 2 ] = atof ( token ) ;
ensurenewtoken ( " ) " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
# ifndef SERVERONLY
2011-11-09 04:12:57 +00:00
surf - > shader = R_RegisterShader_Vertex ( token ) ;
2011-12-05 15:23:40 +00:00
# endif
if ( filever = = 3 )
{
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
ensurenewtoken ( " ) " ) ;
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
ensurenewtoken ( " ) " ) ;
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
ensurenewtoken ( " ) " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
}
2011-11-09 04:12:57 +00:00
for ( j = 0 ; j < numpedges ; j + + )
{
float * v1 , * v2 ;
vec3_t dir ;
if ( pedges [ j ] < 0 )
{
v2 = verts [ edges [ - pedges [ j ] ] . v [ 0 ] ] ;
v1 = verts [ edges [ - pedges [ j ] ] . v [ 1 ] ] ;
}
else
{
v1 = verts [ edges [ pedges [ j ] ] . v [ 0 ] ] ;
v2 = verts [ edges [ pedges [ j ] ] . v [ 1 ] ] ;
}
VectorSubtract ( v1 , v2 , dir ) ;
VectorNormalize ( dir ) ;
CrossProduct ( surf - > plane , dir , surf - > edge [ j ] ) ;
surf - > edge [ j ] [ 3 ] = DotProduct ( v1 , surf - > edge [ j ] ) ;
2011-12-05 15:23:40 +00:00
surf - > edge [ j ] [ 3 ] + = DIST_EPSILON ;
2011-11-09 04:12:57 +00:00
}
D3_InsertClipSurface ( cmod - > cnodes , surf ) ;
2011-12-05 15:23:40 +00:00
AddPointToBounds ( surf - > mins , cmod - > mins , cmod - > maxs ) ;
AddPointToBounds ( surf - > maxs , cmod - > mins , cmod - > maxs ) ;
2011-11-09 04:12:57 +00:00
}
free ( verts ) ;
free ( edges ) ;
ensurenewtoken ( " brushes " ) ;
2011-12-05 15:23:40 +00:00
if ( filever = = 1 )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
/*'brushMemory', which is unusable for us*/
}
else
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
/*numBrushes */
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
/*numBrushPlanes*/
}
2011-11-09 04:12:57 +00:00
ensurenewtoken ( " { " ) ;
for ( ; ; )
{
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
if ( ! strcmp ( token , " } " ) )
break ;
j = atoi ( token ) ;
2013-07-14 12:22:51 +00:00
brush = ZG_Malloc ( & mod - > memgroup , j * sizeof ( vec4_t ) + sizeof ( * brush ) ) ;
2011-12-05 15:23:40 +00:00
brush - > numplanes = j ;
brush - > plane = ( vec4_t * ) ( brush + 1 ) ;
2011-11-09 04:12:57 +00:00
ensurenewtoken ( " { " ) ;
2011-12-05 15:23:40 +00:00
for ( i = 0 ; i < brush - > numplanes ; i + + )
2011-11-09 04:12:57 +00:00
{
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > plane [ i ] [ 0 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > plane [ i ] [ 1 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > plane [ i ] [ 2 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
ensurenewtoken ( " ) " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > plane [ i ] [ 3 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
}
ensurenewtoken ( " } " ) ;
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > mins [ 0 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > mins [ 1 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > mins [ 2 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
ensurenewtoken ( " ) " ) ;
ensurenewtoken ( " ( " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > maxs [ 0 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > maxs [ 1 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > maxs [ 2 ] = atof ( token ) ;
2011-11-09 04:12:57 +00:00
ensurenewtoken ( " ) " ) ;
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
2011-12-05 15:23:40 +00:00
brush - > contents = D3_ParseContents ( token ) ;
if ( filever = = 3 )
buf = COM_ParseOut ( buf , token , sizeof ( token ) ) ;
D3_InsertClipBrush ( cmod - > cnodes , brush ) ;
AddPointToBounds ( brush - > mins , cmod - > mins , cmod - > maxs ) ;
AddPointToBounds ( brush - > maxs , cmod - > mins , cmod - > maxs ) ;
2011-11-09 04:12:57 +00:00
}
}
else
break ;
}
2011-02-27 01:01:22 +00:00
/*load up the .map so we can get some entities (anyone going to bother making a qc mod compatible with this?)*/
COM_StripExtension ( mod - > name , token , sizeof ( token ) ) ;
mod - > entities = FS_LoadMallocFile ( va ( " %s.map " , token ) ) ;
mod - > funcs . FindTouchedLeafs = D3_FindTouchedLeafs ;
2012-01-17 07:57:46 +00:00
mod - > funcs . NativeTrace = D3_Trace ;
2011-02-27 01:01:22 +00:00
mod - > funcs . PointContents = D3_PointContents ;
mod - > funcs . FatPVS = D3_FatPVS ;
mod - > funcs . LeafnumForPoint = D3_LeafnumForPoint ;
mod - > funcs . StainNode = D3_StainNode ;
mod - > funcs . LightPointValues = D3_LightPointValues ;
mod - > funcs . EdictInFatPVS = D3_EdictInFatPVS ;
2013-07-29 17:36:44 +00:00
mod - > funcs . LeafPVS = D3_LeafPVS ;
2011-02-27 01:01:22 +00:00
mod - > fromgame = fg_doom3 ;
/*that's the physics sorted*/
# ifndef SERVERONLY
2011-02-27 02:07:49 +00:00
if ( ! isDedicated )
2011-02-27 02:04:36 +00:00
{
COM_StripExtension ( mod - > name , token , sizeof ( token ) ) ;
buf = FS_LoadMallocFile ( va ( " %s.proc " , token ) ) ;
Mod_LoadMap_Proc ( mod , buf ) ;
BZ_Free ( buf ) ;
}
2011-02-27 01:01:22 +00:00
# endif
2011-02-27 02:04:36 +00:00
return true ;
2011-03-03 13:32:27 +00:00
}
2012-01-17 07:57:46 +00:00
# endif