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
2016-12-07 18:45:25 +00:00
# include "com_mesh.h"
2011-02-27 01:01:22 +00:00
2016-02-15 06:01:17 +00:00
//FIXME: shadowmaps should build a cache of the nearby area surfaces and flag those models as RF_NOSHADOW or something
2016-07-12 00:40:13 +00:00
//fixme: merge areas and static ents too somehow.
2016-02-15 06:01:17 +00:00
2013-07-14 12:22:51 +00:00
void Mod_SetParent ( mnode_t * node , mnode_t * parent ) ;
2016-02-10 23:23:43 +00:00
static int D3_ClusterForPoint ( 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
2016-02-15 06:01:17 +00:00
void ModD3_GenAreaVBO ( void * ctx , void * data , size_t a , size_t b )
{
model_t * sub = ctx ;
BE_GenBrushModelVBO ( sub ) ;
}
2016-07-12 00:40:13 +00:00
static void R_BuildDefaultTexnums_Doom3 ( shader_t * shader )
{
extern qboolean r_loadbumpmapping ;
extern cvar_t gl_specular ;
extern cvar_t r_fb_bmodels ;
char * h ;
char imagename [ MAX_QPATH ] ;
char mapname [ MAX_QPATH ] ;
char * subpath = NULL ;
texnums_t * tex ;
unsigned int a , aframes ;
unsigned int imageflags = 0 ;
strcpy ( imagename , shader - > name ) ;
h = strchr ( imagename , ' # ' ) ;
if ( h )
* h = 0 ;
if ( * imagename = = ' / ' | | strchr ( imagename , ' : ' ) )
{ //this is not security. this is anti-spam for the verbose security in the filesystem code.
Con_Printf ( " Warning: shader has absolute path: %s \n " , shader - > name ) ;
* imagename = 0 ;
}
tex = shader - > defaulttextures ;
aframes = max ( 1 , shader - > numdefaulttextures ) ;
//if any were specified explicitly, replicate that into all.
//this means animmap can be used, with any explicit textures overriding all.
for ( a = 1 ; a < aframes ; a + + )
{
if ( ! TEXVALID ( tex [ a ] . base ) )
tex [ a ] . base = tex [ 0 ] . base ;
if ( ! TEXVALID ( tex [ a ] . bump ) )
tex [ a ] . bump = tex [ 0 ] . bump ;
if ( ! TEXVALID ( tex [ a ] . fullbright ) )
tex [ a ] . fullbright = tex [ 0 ] . fullbright ;
if ( ! TEXVALID ( tex [ a ] . specular ) )
tex [ a ] . specular = tex [ 0 ] . specular ;
if ( ! TEXVALID ( tex [ a ] . loweroverlay ) )
tex [ a ] . loweroverlay = tex [ 0 ] . loweroverlay ;
if ( ! TEXVALID ( tex [ a ] . upperoverlay ) )
tex [ a ] . upperoverlay = tex [ 0 ] . upperoverlay ;
if ( ! TEXVALID ( tex [ a ] . reflectmask ) )
tex [ a ] . reflectmask = tex [ 0 ] . reflectmask ;
if ( ! TEXVALID ( tex [ a ] . reflectcube ) )
tex [ a ] . reflectcube = tex [ 0 ] . reflectcube ;
}
for ( a = 0 ; a < aframes ; a + + , tex + + )
{
COM_StripExtension ( tex - > mapname , mapname , sizeof ( mapname ) ) ;
if ( ! TEXVALID ( tex - > base ) )
{
/*dlights/realtime lighting needs some stuff*/
if ( ! TEXVALID ( tex - > base ) & & * tex - > mapname ) // && (shader->flags & SHADER_HASDIFFUSE))
tex - > base = R_LoadHiResTexture ( tex - > mapname , NULL , 0 ) ;
if ( ! TEXVALID ( tex - > base ) )
tex - > base = R_LoadHiResTexture ( va ( " %s_d " , imagename ) , subpath , ( * imagename = = ' { ' ) ? 0 : IF_NOALPHA ) ;
}
imageflags | = IF_LOWPRIORITY ;
COM_StripExtension ( imagename , imagename , sizeof ( imagename ) ) ;
if ( ! TEXVALID ( tex - > bump ) )
{
if ( ( shader - > flags & SHADER_HASNORMALMAP ) & & r_loadbumpmapping )
{
if ( ! TEXVALID ( tex - > bump ) & & * mapname & & ( shader - > flags & SHADER_HASNORMALMAP ) )
tex - > bump = R_LoadHiResTexture ( va ( " %s_local " , mapname ) , NULL , imageflags | IF_TRYBUMP ) ;
if ( ! TEXVALID ( tex - > bump ) )
tex - > bump = R_LoadHiResTexture ( va ( " %s_local " , imagename ) , subpath , imageflags | IF_TRYBUMP ) ;
}
}
if ( ! TEXVALID ( tex - > loweroverlay ) )
{
if ( shader - > flags & SHADER_HASTOPBOTTOM )
{
if ( ! TEXVALID ( tex - > loweroverlay ) & & * mapname )
tex - > loweroverlay = R_LoadHiResTexture ( va ( " %s_pants " , mapname ) , NULL , imageflags ) ;
if ( ! TEXVALID ( tex - > loweroverlay ) )
tex - > loweroverlay = R_LoadHiResTexture ( va ( " %s_pants " , imagename ) , subpath , imageflags ) ; /*how rude*/
}
}
if ( ! TEXVALID ( tex - > upperoverlay ) )
{
if ( shader - > flags & SHADER_HASTOPBOTTOM )
{
if ( ! TEXVALID ( tex - > upperoverlay ) & & * mapname )
tex - > upperoverlay = R_LoadHiResTexture ( va ( " %s_shirt " , mapname ) , NULL , imageflags ) ;
if ( ! TEXVALID ( tex - > upperoverlay ) )
tex - > upperoverlay = R_LoadHiResTexture ( va ( " %s_shirt " , imagename ) , subpath , imageflags ) ;
}
}
if ( ! TEXVALID ( tex - > specular ) )
{
if ( ( shader - > flags & SHADER_HASGLOSS ) & & gl_specular . value )
{
if ( ! TEXVALID ( tex - > specular ) & & * mapname )
tex - > specular = R_LoadHiResTexture ( va ( " %s_s " , mapname ) , NULL , imageflags ) ;
if ( ! TEXVALID ( tex - > specular ) )
tex - > specular = R_LoadHiResTexture ( va ( " %s_s " , imagename ) , subpath , imageflags ) ;
}
}
if ( ! TEXVALID ( tex - > fullbright ) )
{
if ( ( shader - > flags & SHADER_HASFULLBRIGHT ) & & r_fb_bmodels . value & & gl_load24bit . value )
{
if ( ! TEXVALID ( tex - > fullbright ) & & * mapname )
2016-08-25 00:12:14 +00:00
tex - > fullbright = R_LoadHiResTexture ( va ( " %s_luma:%s_glow " , mapname , mapname ) , NULL , imageflags ) ;
2016-07-12 00:40:13 +00:00
if ( ! TEXVALID ( tex - > fullbright ) )
2016-08-25 00:12:14 +00:00
tex - > fullbright = R_LoadHiResTexture ( va ( " %s_luma:%s_glow " , imagename , imagename ) , subpath , imageflags ) ;
2016-07-12 00:40:13 +00:00
}
}
}
}
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 ;
2016-07-12 00:40:13 +00:00
b [ surf ] . lmlightstyle [ 0 ] = 0 ;
b [ surf ] . lmlightstyle [ 1 ] = 255 ;
b [ surf ] . lmlightstyle [ 2 ] = 255 ;
b [ surf ] . lmlightstyle [ 3 ] = 255 ;
2011-02-27 01:01:22 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
b [ surf ] . shader = R_RegisterShader_Vertex ( token ) ;
2016-07-12 00:40:13 +00:00
R_BuildDefaultTexnums_Doom3 ( b [ surf ] . shader ) ;
2011-02-27 01:01:22 +00:00
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 ;
2016-07-12 00:40:13 +00:00
vdata = ZG_Malloc ( & sub - > memgroup , numverts * ( sizeof ( vecV_t ) + sizeof ( vec2_t ) + sizeof ( vec3_t ) * 3 + sizeof ( vec4_t ) ) + numindicies * sizeof ( index_t ) ) ;
2011-02-27 01:01:22 +00:00
2016-02-10 23:23:43 +00:00
m [ surf ] . colors4f_array [ 0 ] = ( 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 ;
2016-07-12 00:40:13 +00:00
m [ surf ] . snormals_array = ( vec3_t * ) vdata ; vdata + = sizeof ( vec3_t ) * numverts ;
m [ surf ] . tnormals_array = ( vec3_t * ) vdata ; vdata + = sizeof ( vec3_t ) * numverts ;
2011-02-27 01:01:22 +00:00
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 ;
}
2016-07-12 00:40:13 +00:00
m [ surf ] . colors4f_array [ 0 ] [ v ] [ 0 ] = 1 ;
m [ surf ] . colors4f_array [ 0 ] [ v ] [ 1 ] = 1 ;
m [ surf ] . colors4f_array [ 0 ] [ v ] [ 2 ] = 1 ;
m [ surf ] . colors4f_array [ 0 ] [ v ] [ 3 ] = 1 ;
2011-11-09 04:12:57 +00:00
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
{
2016-02-10 23:23:43 +00:00
m [ surf ] . colors4f_array [ 0 ] [ v ] [ 0 ] = atof ( token ) / 255 ;
2011-11-09 04:12:57 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
2016-02-10 23:23:43 +00:00
m [ surf ] . colors4f_array [ 0 ] [ v ] [ 1 ] = atof ( token ) / 255 ;
2011-11-09 04:12:57 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
2016-02-10 23:23:43 +00:00
m [ surf ] . colors4f_array [ 0 ] [ v ] [ 2 ] = atof ( token ) / 255 ;
2011-11-09 04:12:57 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
2016-02-10 23:23:43 +00:00
m [ surf ] . colors4f_array [ 0 ] [ v ] [ 3 ] = atof ( token ) / 255 ;
2011-11-09 04:12:57 +00:00
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 ) ;
}
2016-07-12 00:40:13 +00:00
//generate the s+t vectors according to the normals that we just parsed.
R_Generate_Mesh_ST_Vectors ( & m [ surf ] ) ;
2011-02-27 01:01:22 +00:00
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " } " ) )
return false ;
}
data = COM_ParseOut ( data , token , sizeof ( token ) ) ;
if ( strcmp ( token , " } " ) )
return false ;
2016-02-10 23:23:43 +00:00
// sub->loadstate = MLS_LOADED;
2011-02-27 01:01:22 +00:00
sub - > fromgame = fg_doom3 ;
sub - > type = mod_brush ;
2016-07-12 00:40:13 +00:00
sub - > lightmaps . surfstyles = 1 ;
2013-07-27 12:22:12 +00:00
2016-02-15 06:01:17 +00:00
COM_AddWork ( WG_MAIN , ModD3_GenAreaVBO , sub , NULL , MLS_LOADED , 0 ) ;
COM_AddWork ( WG_MAIN , Mod_ModelLoaded , sub , NULL , MLS_LOADED , 0 ) ;
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 ) ) ;
2016-07-12 00:40:13 +00:00
model - > numclusters = 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 ;
2016-02-15 06:01:17 +00:00
/*fixme: convert each portal to a 2d box, because its much much simpler than true poly clipping*/
/*fixme: use occlusion tests, with temporal coherance (draw the portal as black or something if we think its invisible)*/
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 ;
2016-02-15 06:01:17 +00:00
static qbyte visbuf [ 256 ] ;
qbyte * usevis ;
2011-02-27 01:01:22 +00:00
vec_t newbounds [ 4 ] ;
2016-02-15 06:01:17 +00:00
int area ;
entity_t ent ;
2016-02-10 23:23:43 +00:00
start = D3_ClusterForPoint ( mod , org ) ;
2011-02-27 01:01:22 +00:00
/*figure out which area we're in*/
if ( start < 0 )
{
/*outside the world, just make it all visible, and take the fps hit*/
2016-02-15 06:01:17 +00:00
memset ( visbuf , 255 , 4 ) ;
usevis = visbuf ;
2011-02-27 01:01:22 +00:00
}
else if ( r_novis . value )
2016-02-15 06:01:17 +00:00
usevis = visbuf ;
2011-02-27 01:01:22 +00:00
else
{
2016-02-15 06:01:17 +00:00
memset ( visbuf , 0 , 4 ) ;
2011-02-27 01:01:22 +00:00
/*make a bounds the size of the view*/
newbounds [ 0 ] = - 1 ;
newbounds [ 1 ] = 1 ;
newbounds [ 2 ] = - 1 ;
newbounds [ 3 ] = 1 ;
walkno + + ;
2016-02-15 06:01:17 +00:00
D3_WalkPortal ( mod , start , newbounds , visbuf ) ;
2011-02-27 01:01:22 +00:00
// Con_Printf("%x %x %x %x\n", vis[0], vis[1], vis[2], vis[3]);
2016-02-15 06:01:17 +00:00
usevis = visbuf ;
2011-02-27 01:01:22 +00:00
}
2016-02-15 06:01:17 +00:00
//now generate the various entities for that region.
memset ( & ent , 0 , sizeof ( ent ) ) ;
2011-02-27 01:01:22 +00:00
for ( area = 0 ; area < 256 * 8 ; area + + )
{
2016-02-15 06:01:17 +00:00
if ( usevis [ area > > 3 ] & ( 1u < < ( area & 7 ) ) )
2011-02-27 01:01:22 +00:00
{
2016-02-15 06:01:17 +00:00
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 ;
V_AddEntity ( & ent ) ;
2011-02-27 01:01:22 +00:00
}
}
2016-02-15 06:01:17 +00:00
return usevis ;
2011-02-27 01:01:22 +00:00
}
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
{
}
2017-06-21 01:24:25 +00:00
static qbyte * D3_ClusterPVS ( struct model_s * model , int num , pvsbuffer_t * buffer , pvsmerge_t merge )
2011-02-27 02:04:36 +00:00
{
2017-06-21 01:24:25 +00:00
memset ( buffer - > buffer , 0xff , buffer - > buffersize ) ;
return buffer - > buffer ;
2011-02-27 02:04:36 +00:00
}
2016-02-10 23:23:43 +00:00
static int D3_ClusterForPoint ( 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 ;
}
2017-06-21 01:24:25 +00:00
static unsigned int D3_FatPVS ( struct model_s * model , vec3_t org , pvsbuffer_t * pvsbuffer , 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 ;
2016-02-15 06:01:17 +00:00
// shader_t *shader;
2011-11-09 04:12:57 +00:00
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 ) ;
}
2016-12-19 13:31:05 +00:00
static qboolean D3_Trace ( struct model_s * model , int hulloverride , framestate_t * framestate , vec3_t axis [ 3 ] , vec3_t p1 , vec3_t p2 , vec3_t mins , vec3_t maxs , qboolean capsule , 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 ;
2016-02-10 23:23:43 +00:00
qboolean QDECL D3_LoadMap_CollisionMap ( model_t * mod , void * buf , size_t bufsize )
2011-02-27 01:01:22 +00:00
{
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
2016-02-15 06:01:17 +00:00
// surf->shader = R_RegisterShader_Vertex(token);
2016-07-12 00:40:13 +00:00
// R_BuildDefaultTexnums_Doom3(NULL, surf->shader);
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 ) ) ;
2016-11-25 08:14:54 +00:00
Mod_SetEntitiesString ( mod , FS_LoadMallocFile ( va ( " %s.map " , token ) , NULL ) , true ) ;
2011-02-27 01:01:22 +00:00
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 ;
2016-02-10 23:23:43 +00:00
mod - > funcs . ClusterForPoint = D3_ClusterForPoint ;
2011-02-27 01:01:22 +00:00
mod - > funcs . StainNode = D3_StainNode ;
mod - > funcs . LightPointValues = D3_LightPointValues ;
mod - > funcs . EdictInFatPVS = D3_EdictInFatPVS ;
2016-02-10 23:23:43 +00:00
mod - > funcs . ClusterPVS = D3_ClusterPVS ;
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 ) ) ;
2016-02-10 23:23:43 +00:00
buf = FS_LoadMallocFile ( va ( " %s.proc " , token ) , NULL ) ;
2011-02-27 02:04:36 +00:00
Mod_LoadMap_Proc ( mod , buf ) ;
BZ_Free ( buf ) ;
}
2011-02-27 01:01:22 +00:00
# endif
2016-02-15 06:01:17 +00:00
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