2016-07-12 00:40:13 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
// r_surf.c: surface-related refresh code
# include "quakedef.h"
# ifndef SERVERONLY
# include "glquake.h"
# include "shader.h"
# include "renderque.h"
# include "com_mesh.h"
# include <math.h>
# if (defined(GLQUAKE) || defined(VKQUAKE)) && defined(MULTITHREAD)
# define THREADEDWORLD
# endif
2017-10-13 17:50:28 +00:00
# ifdef BEF_PUSHDEPTH
qboolean r_pushdepth ;
# endif
2016-07-12 00:40:13 +00:00
extern cvar_t r_ambient ;
static vec3_t modelorg ; /*set before recursively entering the visible surface finder*/
model_t * currentmodel ;
uploadfmt_t lightmap_fmt ; //bgra32, rgba32, rgb24, lum8
int lightmap_bytes ; // 1, 3 or 4
size_t maxblocksize ;
vec3_t * blocknormals ;
unsigned * blocklights ;
lightmapinfo_t * * lightmap ;
int numlightmaps ;
2018-03-04 14:41:16 +00:00
static const float rgb9e5tab [ 32 ] = { //multipliers for the 9-bit mantissa, according to the biased mantissa
//aka: pow(2, biasedexponent - bias-bits) where bias is 15 and bits is 9
1.0 / ( 1 < < 24 ) , 1.0 / ( 1 < < 23 ) , 1.0 / ( 1 < < 22 ) , 1.0 / ( 1 < < 21 ) , 1.0 / ( 1 < < 20 ) , 1.0 / ( 1 < < 19 ) , 1.0 / ( 1 < < 18 ) , 1.0 / ( 1 < < 17 ) ,
1.0 / ( 1 < < 16 ) , 1.0 / ( 1 < < 15 ) , 1.0 / ( 1 < < 14 ) , 1.0 / ( 1 < < 13 ) , 1.0 / ( 1 < < 12 ) , 1.0 / ( 1 < < 11 ) , 1.0 / ( 1 < < 10 ) , 1.0 / ( 1 < < 9 ) ,
1.0 / ( 1 < < 8 ) , 1.0 / ( 1 < < 7 ) , 1.0 / ( 1 < < 6 ) , 1.0 / ( 1 < < 5 ) , 1.0 / ( 1 < < 4 ) , 1.0 / ( 1 < < 3 ) , 1.0 / ( 1 < < 2 ) , 1.0 / ( 1 < < 1 ) ,
1.0 , 1.0 * ( 1 < < 1 ) , 1.0 * ( 1 < < 2 ) , 1.0 * ( 1 < < 3 ) , 1.0 * ( 1 < < 4 ) , 1.0 * ( 1 < < 5 ) , 1.0 * ( 1 < < 6 ) , 1.0 * ( 1 < < 7 ) ,
} ;
2016-07-12 00:40:13 +00:00
extern mleaf_t * r_vischain ; // linked list of visible leafs
extern cvar_t r_stains ;
extern cvar_t r_loadlits ;
extern cvar_t r_stainfadetime ;
extern cvar_t r_stainfadeammount ;
2018-03-04 14:41:16 +00:00
extern cvar_t r_lightmap_nearest ;
extern cvar_t r_lightmap_format ;
2016-07-12 00:40:13 +00:00
static int lightmap_shift ;
int Surf_LightmapShift ( model_t * model )
{
extern cvar_t gl_overbright_all , gl_overbright ;
if ( gl_overbright_all . ival | | ( model - > engineflags & MDLF_NEEDOVERBRIGHT ) )
lightmap_shift = bound ( 0 , gl_overbright . ival , 2 ) ;
else
lightmap_shift = 0 ;
return lightmap_shift ;
}
void QDECL Surf_RebuildLightmap_Callback ( struct cvar_s * var , char * oldvalue )
{
Mod_RebuildLightmaps ( ) ;
}
//radius, x y z, r g b
void Surf_StainSurf ( msurface_t * surf , float * parms )
{
int sd , td ;
float dist , rad , minlight ;
float change ;
vec3_t impact , local ;
int s , t ;
int i ;
int smax , tmax ;
float amm ;
int lim ;
mtexinfo_t * tex ;
stmap * stainbase ;
lightmapinfo_t * lm ;
lim = 255 - ( r_stains . value * 255 ) ;
# define stain(x) \
change = stainbase [ ( s ) * 3 + x ] + amm * parms [ 4 + x ] ; \
stainbase [ ( s ) * 3 + x ] = bound ( lim , change , 255 ) ;
if ( surf - > lightmaptexturenums [ 0 ] < 0 )
return ;
lm = lightmap [ surf - > lightmaptexturenums [ 0 ] ] ;
smax = ( surf - > extents [ 0 ] > > surf - > lmshift ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > surf - > lmshift ) + 1 ;
tex = surf - > texinfo ;
stainbase = lm - > stainmaps ;
stainbase + = ( surf - > light_t [ 0 ] * lm - > width + surf - > light_s [ 0 ] ) * 3 ;
rad = * parms ;
dist = DotProduct ( ( parms + 1 ) , surf - > plane - > normal ) - surf - > plane - > dist ;
rad - = fabs ( dist ) ;
minlight = 0 ;
if ( rad < minlight ) //not hit
return ;
minlight = rad - minlight ;
for ( i = 0 ; i < 3 ; i + + )
{
impact [ i ] = ( parms + 1 ) [ i ] - surf - > plane - > normal [ i ] * dist ;
}
local [ 0 ] = DotProduct ( impact , tex - > vecs [ 0 ] ) + tex - > vecs [ 0 ] [ 3 ] ;
local [ 1 ] = DotProduct ( impact , tex - > vecs [ 1 ] ) + tex - > vecs [ 1 ] [ 3 ] ;
local [ 0 ] - = surf - > texturemins [ 0 ] ;
local [ 1 ] - = surf - > texturemins [ 1 ] ;
for ( t = 0 ; t < tmax ; t + + )
{
td = local [ 1 ] - ( t < < surf - > lmshift ) ;
if ( td < 0 )
td = - td ;
for ( s = 0 ; s < smax ; s + + )
{
sd = local [ 0 ] - ( s < < surf - > lmshift ) ;
if ( sd < 0 )
sd = - sd ;
if ( sd > td )
dist = sd + ( td > > 1 ) ;
else
dist = td + ( sd > > 1 ) ;
if ( dist < minlight )
{
amm = ( rad - dist ) ;
stain ( 0 ) ;
stain ( 1 ) ;
stain ( 2 ) ;
surf - > stained = true ;
}
}
stainbase + = 3 * lm - > width ;
}
if ( surf - > stained )
surf - > cached_dlight = - 1 ;
}
//combination of R_AddDynamicLights and R_MarkLights
/*
static void Surf_StainNode ( mnode_t * node , float * parms )
{
mplane_t * splitplane ;
float dist ;
msurface_t * surf ;
int i ;
if ( node - > contents < 0 )
return ;
splitplane = node - > plane ;
dist = DotProduct ( ( parms + 1 ) , splitplane - > normal ) - splitplane - > dist ;
if ( dist > ( * parms ) )
{
Surf_StainNode ( node - > children [ 0 ] , parms ) ;
return ;
}
if ( dist < ( - * parms ) )
{
Surf_StainNode ( node - > children [ 1 ] , parms ) ;
return ;
}
// mark the polygons
surf = cl . worldmodel - > surfaces + node - > firstsurface ;
for ( i = 0 ; i < node - > numsurfaces ; i + + , surf + + )
{
if ( surf - > flags & ~ ( SURF_DONTWARP | SURF_PLANEBACK ) )
continue ;
Surf_StainSurf ( surf , parms ) ;
}
Surf_StainNode ( node - > children [ 0 ] , parms ) ;
Surf_StainNode ( node - > children [ 1 ] , parms ) ;
}
*/
void Surf_AddStain ( vec3_t org , float red , float green , float blue , float radius )
{
physent_t * pe ;
int i ;
float parms [ 7 ] ;
if ( ! cl . worldmodel | | cl . worldmodel - > loadstate ! = MLS_LOADED | | r_stains . value < = 0 )
return ;
parms [ 0 ] = radius ;
parms [ 1 ] = org [ 0 ] ;
parms [ 2 ] = org [ 1 ] ;
parms [ 3 ] = org [ 2 ] ;
parms [ 4 ] = red ;
parms [ 5 ] = green ;
parms [ 6 ] = blue ;
cl . worldmodel - > funcs . StainNode ( cl . worldmodel - > rootnode , parms ) ;
//now stain inline bsp models other than world.
for ( i = 1 ; i < pmove . numphysent ; i + + ) //0 is world...
{
pe = & pmove . physents [ i ] ;
if ( pe - > model & & pe - > model - > surfaces = = cl . worldmodel - > surfaces & & pe - > model - > loadstate = = MLS_LOADED )
{
parms [ 1 ] = org [ 0 ] - pe - > origin [ 0 ] ;
parms [ 2 ] = org [ 1 ] - pe - > origin [ 1 ] ;
parms [ 3 ] = org [ 2 ] - pe - > origin [ 2 ] ;
if ( pe - > angles [ 0 ] | | pe - > angles [ 1 ] | | pe - > angles [ 2 ] )
{
vec3_t f , r , u , temp ;
AngleVectors ( pe - > angles , f , r , u ) ;
VectorCopy ( ( parms + 1 ) , temp ) ;
parms [ 1 ] = DotProduct ( temp , f ) ;
parms [ 2 ] = - DotProduct ( temp , r ) ;
parms [ 3 ] = DotProduct ( temp , u ) ;
}
pe - > model - > funcs . StainNode ( pe - > model - > rootnode , parms ) ;
}
}
}
void Surf_WipeStains ( void )
{
int i ;
for ( i = 0 ; i < numlightmaps ; i + + )
{
if ( ! lightmap [ i ] )
break ;
memset ( lightmap [ i ] - > stainmaps , 255 , lightmap [ i ] - > width * lightmap [ i ] - > height * 3 * sizeof ( stmap ) ) ;
}
}
void Surf_LessenStains ( void )
{
int i ;
msurface_t * surf ;
int smax , tmax ;
int s , t ;
stmap * stain ;
int stride ;
int ammount ;
int limit ;
lightmapinfo_t * lm ;
static float time ;
2017-03-27 22:57:54 +00:00
if ( ! r_stains . value | | ! r_stainfadeammount . value )
2016-07-12 00:40:13 +00:00
return ;
time + = host_frametime ;
if ( time < r_stainfadetime . value )
return ;
time - = r_stainfadetime . value ;
ammount = r_stainfadeammount . value ;
limit = 255 - ammount ;
surf = cl . worldmodel - > surfaces ;
for ( i = 0 ; i < cl . worldmodel - > numsurfaces ; i + + , surf + + )
{
if ( surf - > stained )
{
lm = lightmap [ surf - > lightmaptexturenums [ 0 ] ] ;
surf - > cached_dlight = - 1 ; //nice hack here...
smax = ( surf - > extents [ 0 ] > > surf - > lmshift ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > surf - > lmshift ) + 1 ;
stain = lm - > stainmaps ;
stain + = ( surf - > light_t [ 0 ] * lm - > width + surf - > light_s [ 0 ] ) * 3 ;
stride = ( lm - > width - smax ) * 3 ;
surf - > stained = false ;
smax * = 3 ;
for ( t = 0 ; t < tmax ; t + + , stain + = stride )
{
for ( s = 0 ; s < smax ; s + + )
{
if ( * stain < limit ) //eventually decay to 255
{
* stain + = ammount ;
surf - > stained = true ;
}
else //reset to 255
* stain = 255 ;
stain + + ;
}
}
}
}
}
/*
= = = = = = = = = = = = = = =
R_AddDynamicLights
= = = = = = = = = = = = = = =
*/
static void Surf_AddDynamicLights ( msurface_t * surf )
{
int lnum ;
int sd , td ;
float dist , rad , minlight ;
vec3_t impact , local ;
int s , t ;
int i ;
int smax , tmax ;
mtexinfo_t * tex ;
float a ;
unsigned * bl ;
smax = ( surf - > extents [ 0 ] > > surf - > lmshift ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > surf - > lmshift ) + 1 ;
tex = surf - > texinfo ;
for ( lnum = rtlights_first ; lnum < RTL_FIRST ; lnum + + )
{
if ( ! ( surf - > dlightbits & ( 1 < < lnum ) ) )
continue ; // not lit by this light
if ( ! ( cl_dlights [ lnum ] . flags & LFLAG_LIGHTMAP ) )
continue ;
rad = cl_dlights [ lnum ] . radius ;
dist = DotProduct ( cl_dlights [ lnum ] . origin , surf - > plane - > normal ) -
surf - > plane - > dist ;
rad - = fabs ( dist ) ;
minlight = cl_dlights [ lnum ] . minlight ;
if ( rad < minlight )
continue ;
minlight = rad - minlight ;
for ( i = 0 ; i < 3 ; i + + )
{
impact [ i ] = cl_dlights [ lnum ] . origin [ i ] -
surf - > plane - > normal [ i ] * dist ;
}
local [ 0 ] = DotProduct ( impact , tex - > vecs [ 0 ] ) + tex - > vecs [ 0 ] [ 3 ] ;
local [ 1 ] = DotProduct ( impact , tex - > vecs [ 1 ] ) + tex - > vecs [ 1 ] [ 3 ] ;
local [ 0 ] - = surf - > texturemins [ 0 ] ;
local [ 1 ] - = surf - > texturemins [ 1 ] ;
a = 256 * ( cl_dlights [ lnum ] . color [ 0 ] * NTSC_RED + cl_dlights [ lnum ] . color [ 1 ] * NTSC_GREEN + cl_dlights [ lnum ] . color [ 2 ] * NTSC_BLUE ) ;
bl = blocklights ;
for ( t = 0 ; t < tmax ; t + + )
{
td = local [ 1 ] - ( t < < surf - > lmshift ) ;
if ( td < 0 )
td = - td ;
for ( s = 0 ; s < smax ; s + + )
{
sd = local [ 0 ] - ( s < < surf - > lmshift ) ;
if ( sd < 0 )
sd = - sd ;
if ( sd > td )
dist = sd + ( td > > 1 ) ;
else
dist = td + ( sd > > 1 ) ;
if ( dist < minlight )
bl [ 0 ] + = ( rad - dist ) * a ;
bl + + ;
}
}
}
}
// warning: <20> Surf_AddDynamicLightNorms<6D> defined but not used
/*
static void Surf_AddDynamicLightNorms ( msurface_t * surf )
{
int lnum ;
int sd , td ;
float dist , rad , minlight ;
vec3_t impact , local ;
int s , t ;
int i ;
int smax , tmax ;
mtexinfo_t * tex ;
float a ;
smax = ( surf - > extents [ 0 ] > > 4 ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > 4 ) + 1 ;
tex = surf - > texinfo ;
for ( lnum = rtlights_first ; lnum < RTL_FIRST ; lnum + + )
{
if ( ! ( surf - > dlightbits & ( 1 < < lnum ) ) )
continue ; // not lit by this light
if ( ! ( cl_dlights [ lnum ] . flags & LFLAG_ALLOW_LMHACK ) )
continue ;
rad = cl_dlights [ lnum ] . radius ;
dist = DotProduct ( cl_dlights [ lnum ] . origin , surf - > plane - > normal ) -
surf - > plane - > dist ;
rad - = fabs ( dist ) ;
minlight = cl_dlights [ lnum ] . minlight ;
if ( rad < minlight )
continue ;
minlight = rad - minlight ;
for ( i = 0 ; i < 3 ; i + + )
{
impact [ i ] = cl_dlights [ lnum ] . origin [ i ] -
surf - > plane - > normal [ i ] * dist ;
}
local [ 0 ] = DotProduct ( impact , tex - > vecs [ 0 ] ) + tex - > vecs [ 0 ] [ 3 ] ;
local [ 1 ] = DotProduct ( impact , tex - > vecs [ 1 ] ) + tex - > vecs [ 1 ] [ 3 ] ;
local [ 0 ] - = surf - > texturemins [ 0 ] ;
local [ 1 ] - = surf - > texturemins [ 1 ] ;
a = 256 * ( cl_dlights [ lnum ] . color [ 0 ] * NTSC_RED + cl_dlights [ lnum ] . color [ 1 ] * NTSC_GREEN + cl_dlights [ lnum ] . color [ 2 ] * NTSC_BLUE ) ;
for ( t = 0 ; t < tmax ; t + + )
{
td = local [ 1 ] - t * surf - > lmscale ;
if ( td < 0 )
td = - td ;
for ( s = 0 ; s < smax ; s + + )
{
sd = local [ 0 ] - s * surf - > lmscale ;
if ( sd < 0 )
sd = - sd ;
if ( sd > td )
dist = sd + ( td > > 1 ) ;
else
dist = td + ( sd > > 1 ) ;
if ( dist < minlight )
{
// blocknormals[t*smax + s][0] -= (rad - dist)*(impact[0]-local[0])/8192.0;
// blocknormals[t*smax + s][1] -= (rad - dist)*(impact[1]-local[1])/8192.0;
blocknormals [ t * smax + s ] [ 2 ] + = 0.5 * blocknormals [ t * smax + s ] [ 2 ] * ( rad - dist ) / 256 ;
}
}
}
}
}
*/
# ifdef PEXT_LIGHTSTYLECOL
static void Surf_AddDynamicLightsColours ( msurface_t * surf )
{
int lnum ;
int sd , td ;
float dist , rad , minlight ;
vec3_t impact , local ;
int s , t ;
int i ;
int smax , tmax ;
mtexinfo_t * tex ;
// float temp;
float r , g , b ;
unsigned * bl ;
vec3_t lightofs ;
smax = ( surf - > extents [ 0 ] > > surf - > lmshift ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > surf - > lmshift ) + 1 ;
tex = surf - > texinfo ;
for ( lnum = rtlights_first ; lnum < RTL_FIRST ; lnum + + )
{
if ( ! ( surf - > dlightbits & ( 1 < < lnum ) ) )
continue ; // not lit by this light
rad = cl_dlights [ lnum ] . radius ;
VectorSubtract ( cl_dlights [ lnum ] . origin , currententity - > origin , lightofs ) ;
2017-07-31 17:15:37 +00:00
dist = DotProduct ( lightofs , surf - > plane - > normal ) - surf - > plane - > dist ;
2016-07-12 00:40:13 +00:00
rad - = fabs ( dist ) ;
minlight = cl_dlights [ lnum ] . minlight ;
if ( rad < minlight )
continue ;
minlight = rad - minlight ;
for ( i = 0 ; i < 3 ; i + + )
{
impact [ i ] = lightofs [ i ] -
surf - > plane - > normal [ i ] * dist ;
}
local [ 0 ] = DotProduct ( impact , tex - > vecs [ 0 ] ) + tex - > vecs [ 0 ] [ 3 ] ;
local [ 1 ] = DotProduct ( impact , tex - > vecs [ 1 ] ) + tex - > vecs [ 1 ] [ 3 ] ;
local [ 0 ] - = surf - > texturemins [ 0 ] ;
local [ 1 ] - = surf - > texturemins [ 1 ] ;
2017-07-04 05:07:51 +00:00
if ( r_dynamic . ival = = 2 )
2018-01-03 04:40:06 +00:00
r = g = b = 256 ;
2017-07-04 05:07:51 +00:00
else
{
r = cl_dlights [ lnum ] . color [ 0 ] * 128 ;
g = cl_dlights [ lnum ] . color [ 1 ] * 128 ;
b = cl_dlights [ lnum ] . color [ 2 ] * 128 ;
}
2016-07-12 00:40:13 +00:00
2017-07-31 17:15:37 +00:00
bl = blocklights ;
if ( r < 0 | | g < 0 | | b < 0 )
2016-07-12 00:40:13 +00:00
{
for ( t = 0 ; t < tmax ; t + + )
{
2017-07-31 17:15:37 +00:00
td = local [ 1 ] - ( t < < surf - > lmshift ) ;
2016-07-12 00:40:13 +00:00
if ( td < 0 )
td = - td ;
for ( s = 0 ; s < smax ; s + + )
{
2017-07-31 17:15:37 +00:00
sd = local [ 0 ] - ( s < < surf - > lmshift ) ;
2016-07-12 00:40:13 +00:00
if ( sd < 0 )
sd = - sd ;
if ( sd > td )
dist = sd + ( td > > 1 ) ;
else
dist = td + ( sd > > 1 ) ;
if ( dist < minlight )
{
2017-07-31 17:15:37 +00:00
i = bl [ 0 ] + ( rad - dist ) * r ;
bl [ 0 ] = ( i < 0 ) ? 0 : i ;
i = bl [ 1 ] + ( rad - dist ) * g ;
bl [ 1 ] = ( i < 0 ) ? 0 : i ;
i = bl [ 2 ] + ( rad - dist ) * b ;
bl [ 2 ] = ( i < 0 ) ? 0 : i ;
2016-07-12 00:40:13 +00:00
}
2017-07-31 17:15:37 +00:00
bl + = 3 ;
2016-07-12 00:40:13 +00:00
}
}
}
else
2017-07-31 17:15:37 +00:00
{
2016-07-12 00:40:13 +00:00
for ( t = 0 ; t < tmax ; t + + )
{
td = local [ 1 ] - ( t < < surf - > lmshift ) ;
if ( td < 0 )
td = - td ;
for ( s = 0 ; s < smax ; s + + )
{
sd = local [ 0 ] - ( s < < surf - > lmshift ) ;
if ( sd < 0 )
sd = - sd ;
if ( sd > td )
dist = sd + ( td > > 1 ) ;
else
dist = td + ( sd > > 1 ) ;
if ( dist < minlight )
{
bl [ 0 ] + = ( rad - dist ) * r ;
bl [ 1 ] + = ( rad - dist ) * g ;
bl [ 2 ] + = ( rad - dist ) * b ;
}
bl + = 3 ;
}
}
}
}
}
# endif
static void Surf_BuildDeluxMap ( model_t * wmodel , msurface_t * surf , qbyte * dest , unsigned int lmwidth , vec3_t * blocknormals )
{
int smax , tmax ;
int i , j , size ;
qbyte * lightmap ;
qbyte * deluxmap ;
unsigned scale ;
int maps ;
float intensity ;
vec_t * bnorm ;
vec3_t temp ;
int stride = lmwidth * lightmap_bytes ;
if ( ! dest )
return ;
smax = ( surf - > extents [ 0 ] > > surf - > lmshift ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > surf - > lmshift ) + 1 ;
size = smax * tmax ;
lightmap = surf - > samples ;
// set to full bright if no light data
if ( ! wmodel - > deluxdata )
{
for ( i = 0 ; i < size ; i + + )
{
blocknormals [ i ] [ 0 ] = 0.9 ; //surf->orientation[2][0];
blocknormals [ i ] [ 1 ] = 0.8 ; //surf->orientation[2][1];
blocknormals [ i ] [ 2 ] = 1 ; //surf->orientation[2][2];
}
goto store ;
}
// clear to no light
for ( i = 0 ; i < size ; i + + )
{
blocknormals [ i ] [ 0 ] = 0 ;
blocknormals [ i ] [ 1 ] = 0 ;
blocknormals [ i ] [ 2 ] = 0 ;
}
// add all the lightmaps
if ( lightmap )
{
2018-03-04 14:41:16 +00:00
switch ( wmodel - > lightmaps . fmt )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
case LM_E5BGR9 :
2016-07-12 00:40:13 +00:00
deluxmap = surf - > samples - wmodel - > lightdata + wmodel - > deluxdata ;
2018-03-04 14:41:16 +00:00
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
for ( i = 0 ; i < size ; i + + )
{
unsigned lm = ( ( unsigned int * ) lightmap ) [ i ] ;
intensity = max3 ( ( ( lm > > 0 ) & 0x1ff ) , ( ( lm > > 9 ) & 0x1ff ) , ( ( lm > > 18 ) & 0x1ff ) ) * scale * ( rgb9e5tab [ lm > > 27 ] * ( 1 < < 7 ) ) ;
blocknormals [ i ] [ 0 ] + = intensity * ( deluxmap [ i * 3 + 0 ] - 127 ) ;
blocknormals [ i ] [ 1 ] + = intensity * ( deluxmap [ i * 3 + 1 ] - 127 ) ;
blocknormals [ i ] [ 2 ] + = intensity * ( deluxmap [ i * 3 + 2 ] - 127 ) ;
}
lightmap + = size * 4 ; // skip to next lightmap
deluxmap + = size * 3 ;
}
break ;
case LM_RGB8 :
deluxmap = surf - > samples - wmodel - > lightdata + wmodel - > deluxdata ;
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
for ( i = 0 ; i < size ; i + + )
{
intensity = ( lightmap [ i * 3 ] + lightmap [ i * 3 + 1 ] + lightmap [ i * 3 + 2 ] ) * scale ;
blocknormals [ i ] [ 0 ] + = intensity * ( deluxmap [ i * 3 + 0 ] - 127 ) ;
blocknormals [ i ] [ 1 ] + = intensity * ( deluxmap [ i * 3 + 1 ] - 127 ) ;
blocknormals [ i ] [ 2 ] + = intensity * ( deluxmap [ i * 3 + 2 ] - 127 ) ;
}
lightmap + = size * 3 ; // skip to next lightmap
deluxmap + = size * 3 ;
}
2018-03-04 14:41:16 +00:00
break ;
case LM_L8 :
2016-07-12 00:40:13 +00:00
deluxmap = ( surf - > samples - wmodel - > lightdata ) * 3 + wmodel - > deluxdata ;
2018-03-04 14:41:16 +00:00
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
for ( i = 0 ; i < size ; i + + )
{
intensity = ( lightmap [ i ] ) * scale ;
blocknormals [ i ] [ 0 ] + = intensity * ( deluxmap [ i * 3 + 0 ] - 127 ) ;
blocknormals [ i ] [ 1 ] + = intensity * ( deluxmap [ i * 3 + 1 ] - 127 ) ;
blocknormals [ i ] [ 2 ] + = intensity * ( deluxmap [ i * 3 + 2 ] - 127 ) ;
}
lightmap + = size ; // skip to next lightmap
deluxmap + = size * 3 ;
}
2018-03-04 14:41:16 +00:00
break ;
2016-07-12 00:40:13 +00:00
}
}
store :
// add all the dynamic lights
// if (surf->dlightframe == r_framecount)
// GLR_AddDynamicLightNorms (surf);
// bound, invert, and shift
stride - = smax * lightmap_bytes ;
bnorm = blocknormals [ 0 ] ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
temp [ 0 ] = bnorm [ 0 ] ;
temp [ 1 ] = bnorm [ 1 ] ;
temp [ 2 ] = bnorm [ 2 ] ; //half the effect? so we emulate light's scalecos of 0.5
VectorNormalize ( temp ) ;
dest [ 2 ] = ( temp [ 0 ] + 1 ) / 2 * 255 ;
dest [ 1 ] = ( temp [ 1 ] + 1 ) / 2 * 255 ;
dest [ 0 ] = ( temp [ 2 ] + 1 ) / 2 * 255 ;
dest + = lightmap_bytes ;
bnorm + = 3 ;
}
}
}
2018-03-04 14:41:16 +00:00
static unsigned int Surf_PackE5BRG9 ( int r , int g , int b , int shift )
{ //5 bits exponent, 3*9 bits of mantissa. no sign bit.
int e = 0 ;
float m = max ( max ( r , g ) , b ) / ( float ) ( 1 < < shift ) ;
float scale ;
if ( m > = 0.5 )
{ //positive exponent
while ( m > = ( 1 < < ( e ) ) & & e < 30 - 15 ) //don't do nans.
e + + ;
}
else
{ //negative exponent...
while ( m < 1 / ( 1 < < - e ) & & e > - 15 ) //don't do denormals.
e - - ;
}
scale = pow ( 2 , e - 9 ) ;
scale * = ( 1 < < shift ) ;
r = bound ( 0 , r / scale + 0.5 , 0x1ff ) ;
g = bound ( 0 , g / scale + 0.5 , 0x1ff ) ;
b = bound ( 0 , b / scale + 0.5 , 0x1ff ) ;
return ( ( e + 15 ) < < 27 ) | ( b < < 18 ) | ( g < < 9 ) | r ;
}
static unsigned short Surf_GenHalf ( float val )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
union
{
float f ;
unsigned int u ;
} u = { val } ;
int e = 0 ;
int m ;
e = ( ( u . u > > 23 ) & 0xff ) - 127 ;
if ( e < - 15 )
return 0 ; //too small exponent, treat it as a 0 denormal
if ( e > 15 )
m = 0 ; //infinity instead of a nan
else
m = ( u . u & ( ( 1 < < 23 ) - 1 ) ) > > 13 ;
return ( ( e + 15 ) < < 10 ) | m ;
}
static void Surf_PackRGB16F ( void * result , int r , int g , int b , int one )
{
#if 0
//bulldozer+ or skylake+ supposedly. which means I can't test it, which means I can't enable it.
__v4sf rgba = ( __v4sf ) { r , g , b , one } / ( float ) one ;
union
{
__v8hi v ;
__v4hi i ;
} tmp ;
//vcvtps2ph writes either a 64bit mem location, or the lower half of an xmm register. unfortunately ts still an xmm register, and that's 128bit.
//the __vXhi weirdness is because half-floats just don't work anywhere but conversions so __vXhf would cause all sorts of compiler errors, is the theory
tmp . v = __builtin_ia32_vcvtps2ph ( rgba , 1 ) ;
* ( __v4hi * ) result = tmp . i ;
# else
( ( unsigned short * ) result ) [ 0 ] = Surf_GenHalf ( r / ( float ) one ) ;
( ( unsigned short * ) result ) [ 1 ] = Surf_GenHalf ( g / ( float ) one ) ;
( ( unsigned short * ) result ) [ 2 ] = Surf_GenHalf ( b / ( float ) one ) ;
( ( unsigned short * ) result ) [ 3 ] = Surf_GenHalf ( 1.0 ) ; //0x0f<<10; //a standard ieee float should have all but the lead bit set of its exponent, and its mantissa 0.
# endif
}
static void Surf_PackRGB32F ( void * result , int r , int g , int b , int one )
{
( ( float * ) result ) [ 0 ] = r / ( float ) one ;
( ( float * ) result ) [ 1 ] = g / ( float ) one ;
( ( float * ) result ) [ 2 ] = b / ( float ) one ;
( ( float * ) result ) [ 3 ] = 1.0 ;
}
2016-07-12 00:40:13 +00:00
/*any sane compiler will inline and split this, removing the stainsrc stuff
just unpacks the internal lightmap block into texture info ready for upload
merges stains and oversaturates overbrights .
*/
2018-03-04 14:41:16 +00:00
static void Surf_StoreLightmap_RGB ( qbyte * dest , unsigned int * bl , int smax , int tmax , unsigned int shift , stmap * stainsrc , unsigned int lmwidth )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
int r , g , b , m ;
2016-07-12 00:40:13 +00:00
unsigned int i , j ;
int stride ;
2018-03-04 14:41:16 +00:00
switch ( lightmap_fmt )
{
default :
Sys_Error ( " Bad lightmap_fmt \n " ) ;
break ;
case PTI_A2BGR10 :
stride = ( lmwidth - smax ) < < 2 ;
shift - = 2 ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 1023 )
{
r * = 1023.0 / m ;
g * = 1023.0 / m ;
b * = 1023.0 / m ;
}
* ( unsigned int * ) dest = ( 3 < < 30 ) | ( ( b & 0x3ff ) < < 20 ) | ( ( g & 0x3ff ) < < 10 ) | ( r & 0x3ff ) ;
dest + = 4 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
case PTI_E5BGR9 :
stride = ( lmwidth - smax ) < < 2 ;
//5bit shared exponent, with bias of 15.
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + ;
g = * bl + + ;
b = * bl + + ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
* ( unsigned int * ) dest = Surf_PackE5BRG9 ( r , g , b , shift + 8 ) ;
dest + = 4 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
case PTI_RGBA16F :
stride = ( lmwidth - smax ) < < 3 ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + ;
g = * bl + + ;
b = * bl + + ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
Surf_PackRGB16F ( dest , r , g , b , 1 < < ( shift + 8 ) ) ;
dest + = 8 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
case PTI_RGBA32F :
stride = ( lmwidth - smax ) < < 4 ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + ;
g = * bl + + ;
b = * bl + + ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
Surf_PackRGB32F ( dest , r , g , b , 1 < < ( shift + 8 ) ) ;
dest + = sizeof ( float ) * 4 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
case PTI_RGBX8 :
case PTI_RGBA8 :
stride = ( lmwidth - smax ) < < 2 ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 255 )
{
r * = 255.0 / m ;
g * = 255.0 / m ;
b * = 255.0 / m ;
}
dest [ 0 ] = r ;
dest [ 1 ] = g ;
dest [ 2 ] = b ;
dest [ 3 ] = 255 ;
dest + = 4 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
case PTI_BGRX8 :
case PTI_BGRA8 :
stride = ( lmwidth - smax ) < < 2 ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 255 )
{
r * = 255.0 / m ;
g * = 255.0 / m ;
b * = 255.0 / m ;
}
dest [ 0 ] = b ;
dest [ 1 ] = g ;
dest [ 2 ] = r ;
dest [ 3 ] = 255 ;
dest + = 4 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
/*
case PTI_BGRX8 :
case PTI_BGRA8 :
stride = ( lmwidth - smax ) < < 2 ;
bl = blocklights ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
if ( r > 255 )
dest [ 2 ] = 255 ;
else if ( r < 0 )
dest [ 2 ] = 0 ;
else
dest [ 2 ] = r ;
if ( g > 255 )
dest [ 1 ] = 255 ;
else if ( g < 0 )
dest [ 1 ] = 0 ;
else
dest [ 1 ] = g ;
if ( b > 255 )
dest [ 0 ] = 255 ;
else if ( b < 0 )
dest [ 0 ] = 0 ;
else
dest [ 0 ] = b ;
dest [ 3 ] = 255 ;
dest + = 4 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
*/
case PTI_RGB565 :
stride = ( lmwidth - smax ) < < 1 ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 255 )
{
r * = 255.0 / m ;
g * = 255.0 / m ;
b * = 255.0 / m ;
}
* ( unsigned short * ) dest = ( b > > 3 ) | ( ( g > > 2 ) < < 5 ) | ( ( r > > 3 ) < < 11 ) ;
dest + = 2 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
case PTI_RGBA4444 :
stride = ( lmwidth - smax ) < < 1 ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 255 )
{
r * = 255.0 / m ;
g * = 255.0 / m ;
b * = 255.0 / m ;
}
* ( unsigned short * ) dest = ( ( r > > 4 ) < < 12 ) | ( ( g > > 4 ) < < 8 ) | ( ( b > > 4 ) < < 4 ) | 0x000f ;
dest + = 2 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
case PTI_RGBA5551 :
stride = ( lmwidth - smax ) < < 1 ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 255 )
{
r * = 255.0 / m ;
g * = 255.0 / m ;
b * = 255.0 / m ;
}
* ( unsigned short * ) dest = ( ( r > > 3 ) < < 11 ) | ( ( g > > 3 ) < < 6 ) | ( ( b > > 3 ) < < 1 ) | 0x0001 ;
dest + = 2 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
case PTI_ARGB4444 :
stride = ( lmwidth - smax ) < < 1 ;
2016-07-12 00:40:13 +00:00
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 255 )
{
r * = 255.0 / m ;
g * = 255.0 / m ;
b * = 255.0 / m ;
}
2018-03-04 14:41:16 +00:00
* ( unsigned short * ) dest = 0xf000 | ( ( r > > 4 ) < < 8 ) | ( ( g > > 4 ) < < 4 ) | ( ( b > > 4 ) < < 0 ) ;
dest + = 2 ;
2016-07-12 00:40:13 +00:00
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
2018-03-04 14:41:16 +00:00
case PTI_ARGB1555 :
stride = ( lmwidth - smax ) < < 1 ;
2016-07-12 00:40:13 +00:00
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
2018-03-04 14:41:16 +00:00
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 255 )
{
r * = 255.0 / m ;
g * = 255.0 / m ;
b * = 255.0 / m ;
}
2016-07-12 00:40:13 +00:00
2018-03-04 14:41:16 +00:00
* ( unsigned short * ) dest = 0x8000 | ( ( r > > 3 ) < < 10 ) | ( ( g > > 3 ) < < 5 ) | ( ( b > > 3 ) < < 0 ) ;
dest + = 2 ;
2016-07-12 00:40:13 +00:00
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
2018-03-04 14:41:16 +00:00
case PTI_RGB8 :
2016-07-12 00:40:13 +00:00
stride = lmwidth * 3 - ( smax * 3 ) ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
r = * bl + + > > shift ;
g = * bl + + > > shift ;
b = * bl + + > > shift ;
if ( stainsrc ) // merge in stain
{
r = ( 127 + r * ( * stainsrc + + ) ) > > 8 ;
g = ( 127 + g * ( * stainsrc + + ) ) > > 8 ;
b = ( 127 + b * ( * stainsrc + + ) ) > > 8 ;
}
// quake 2 method, scale highest down to
// maintain hue
m = max ( max ( r , g ) , b ) ;
if ( m > 255 )
{
r * = 255.0 / m ;
g * = 255.0 / m ;
b * = 255.0 / m ;
}
dest [ 0 ] = r ;
dest [ 1 ] = g ;
dest [ 2 ] = b ;
dest + = 3 ;
}
if ( stainsrc )
stainsrc + = ( lmwidth - smax ) * 3 ;
}
break ;
2018-03-04 14:41:16 +00:00
}
}
static void Surf_StoreLightmap_Grey ( qbyte * dest , unsigned int * bl , int smax , int tmax , unsigned int shift , stmap * stainsrc , unsigned int lmwidth )
{
int t ;
unsigned int i , j ;
for ( i = 0 ; i < tmax ; i + + , dest + = lmwidth )
{
for ( j = 0 ; j < smax ; j + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
t = * bl + + ;
t > > = shift ;
if ( t > 255 )
t = 255 ;
dest [ j ] = t ;
2016-07-12 00:40:13 +00:00
}
}
}
/*
= = = = = = = = = = = = = = =
R_BuildLightMap
Combine and scale multiple lightmaps into the 8.8 format in blocklights
= = = = = = = = = = = = = = =
*/
2018-03-04 14:41:16 +00:00
static void Surf_BuildLightMap ( model_t * currentmodel , msurface_t * surf , qbyte * dest , qbyte * deluxdest , stmap * stainsrc , int shift , int ambient , unsigned int lmwidth , int * d_lightstylevalue )
2016-07-12 00:40:13 +00:00
{
int smax , tmax ;
int t ;
2018-03-04 14:41:16 +00:00
int i ;
2016-07-12 00:40:13 +00:00
size_t size ;
qbyte * lightmap ;
2018-03-04 14:41:16 +00:00
unsigned scalergb [ 3 ] ;
2016-07-12 00:40:13 +00:00
unsigned scale ;
int maps ;
unsigned * bl ;
shift + = 7 ; // increase to base value
surf - > cached_dlight = ( surf - > dlightframe = = r_framecount ) ;
smax = ( surf - > extents [ 0 ] > > surf - > lmshift ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > surf - > lmshift ) + 1 ;
size = ( size_t ) smax * tmax ;
lightmap = surf - > samples ;
if ( size > maxblocksize )
{ //fixme: fill in?
2018-03-04 14:41:16 +00:00
//Threading: this should not be a problem, all surfaces should have been built from the main thead at map load so it should have maxed it there.
2016-07-12 00:40:13 +00:00
BZ_Free ( blocklights ) ;
BZ_Free ( blocknormals ) ;
maxblocksize = size ;
blocknormals = BZ_Malloc ( maxblocksize * sizeof ( * blocknormals ) ) ; //already a vector
blocklights = BZ_Malloc ( maxblocksize * 3 * sizeof ( * blocklights ) ) ;
}
if ( currentmodel - > deluxdata )
Surf_BuildDeluxMap ( currentmodel , surf , deluxdest , lmwidth , blocknormals ) ;
2018-03-04 14:41:16 +00:00
if ( lightmap_fmt ! = PTI_L8 )
2016-07-12 00:40:13 +00:00
{
// set to full bright if no light data
if ( ambient < 0 )
{
t = ( - 1 - ambient ) * 255 ;
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = t ;
}
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS ; maps + + )
{
surf - > cached_light [ maps ] = - 1 - ambient ;
surf - > cached_colour [ maps ] = 0xff ;
}
}
else if ( r_fullbright . value > 0 ) //not qw
{
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = r_fullbright . value * 255 * 256 ;
}
}
else if ( ! currentmodel - > lightdata )
{
/*fullbright if map is not lit. but not overbright*/
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = 128 * 256 ;
}
}
else if ( ! surf - > samples )
{
/*no samples, but map is otherwise lit = pure black*/
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = 0 ;
}
surf - > cached_light [ 0 ] = 0 ;
surf - > cached_colour [ 0 ] = 0 ;
}
else
{
// clear to no light
t = ambient ;
if ( t = = 0 )
memset ( blocklights , 0 , size * 3 * sizeof ( * bl ) ) ;
else
{
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = t ;
}
}
// add all the lightmaps
if ( lightmap )
{
2018-03-04 14:41:16 +00:00
if ( currentmodel - > fromgame = = fg_quake3 )
Sys_Error ( " Surf_BuildLightMap: q3bsp " ) ;
switch ( currentmodel - > lightmaps . fmt )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
case LM_E5BGR9 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
surf - > cached_light [ maps ] = scale = d_lightstylevalue [ surf - > styles [ maps ] ] ; // 8.8 fraction
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
if ( scale )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
VectorScale ( cl_lightstyle [ surf - > styles [ maps ] ] . colours , scale , scalergb ) ;
for ( i = 0 ; i < size ; i + + )
{
unsigned int l = ( ( unsigned int * ) lightmap ) [ i ] ;
float e = rgb9e5tab [ l > > 27 ] * ( 1 < < 7 ) ;
blocklights [ i * 3 + 0 ] + = scalergb [ 0 ] * e * ( ( l > > 0 ) & 0x1ff ) ;
blocklights [ i * 3 + 1 ] + = scalergb [ 1 ] * e * ( ( l > > 9 ) & 0x1ff ) ;
blocklights [ i * 3 + 2 ] + = scalergb [ 2 ] * e * ( ( l > > 18 ) & 0x1ff ) ;
}
2016-07-12 00:40:13 +00:00
}
2018-03-04 14:41:16 +00:00
lightmap + = size * 4 ; // skip to next lightmap
2016-07-12 00:40:13 +00:00
}
2018-03-04 14:41:16 +00:00
break ;
case LM_RGB8 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
surf - > cached_light [ maps ] = scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
2016-07-12 00:40:13 +00:00
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
if ( scale )
{
2018-03-04 14:41:16 +00:00
VectorScale ( cl_lightstyle [ surf - > styles [ maps ] ] . colours , scale , scalergb ) ;
bl = blocklights ;
for ( i = 0 ; i < size ; i + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
* bl + + + = * lightmap + + * scalergb [ 0 ] ;
* bl + + + = * lightmap + + * scalergb [ 1 ] ;
* bl + + + = * lightmap + + * scalergb [ 2 ] ;
2016-07-12 00:40:13 +00:00
}
}
else
lightmap + = size * 3 ; // skip to next lightmap
}
2018-03-04 14:41:16 +00:00
break ;
case LM_L8 :
2016-07-12 00:40:13 +00:00
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ;
maps + + )
{
2018-03-04 14:41:16 +00:00
surf - > cached_light [ maps ] = scale = d_lightstylevalue [ surf - > styles [ maps ] ] ; // 8.8 fraction
2016-07-12 00:40:13 +00:00
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
2018-03-04 14:41:16 +00:00
if ( scale )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
VectorScale ( cl_lightstyle [ surf - > styles [ maps ] ] . colours , scale , scalergb ) ;
2016-07-12 00:40:13 +00:00
bl = blocklights ;
for ( i = 0 ; i < size ; i + + )
{
2018-03-04 14:41:16 +00:00
* bl + + + = * lightmap * scalergb [ 0 ] ;
* bl + + + = * lightmap * scalergb [ 1 ] ;
* bl + + + = * lightmap * scalergb [ 2 ] ;
2016-07-12 00:40:13 +00:00
lightmap + + ;
}
}
else
lightmap + = size ; // skip to next lightmap
}
2018-03-04 14:41:16 +00:00
break ;
}
2016-07-12 00:40:13 +00:00
}
}
// add all the dynamic lights
if ( surf - > dlightframe = = r_framecount )
Surf_AddDynamicLightsColours ( surf ) ;
if ( ! r_stains . value | | ! surf - > stained )
stainsrc = NULL ;
2018-03-04 14:41:16 +00:00
Surf_StoreLightmap_RGB ( dest , blocklights , smax , tmax , shift , stainsrc , lmwidth ) ;
2016-07-12 00:40:13 +00:00
}
else
{
2018-03-04 14:41:16 +00:00
// set to full bright if no light data
if ( r_fullbright . ival | | ! currentmodel - > lightdata )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
for ( i = 0 ; i < size ; i + + )
2016-07-12 00:40:13 +00:00
blocklights [ i ] = 255 * 256 ;
surf - > cached_light [ 0 ] = d_lightstylevalue [ 0 ] ;
surf - > cached_colour [ 0 ] = cl_lightstyle [ 0 ] . colourkey ;
}
2018-03-04 14:41:16 +00:00
//surfaces with no light data on lit maps are black
else if ( ! surf - > samples )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
for ( i = 0 ; i < size * 3 ; i + + )
blocklights [ i ] = 0 ;
surf - > cached_light [ 0 ] = d_lightstylevalue [ 0 ] ;
surf - > cached_colour [ 0 ] = cl_lightstyle [ 0 ] . colourkey ;
2016-07-12 00:40:13 +00:00
}
else
{
// clear to no light
for ( i = 0 ; i < size ; i + + )
blocklights [ i ] = 0 ;
// add all the lightmaps
if ( lightmap )
{
2018-03-04 14:41:16 +00:00
switch ( currentmodel - > lightmaps . fmt )
{
case LM_E5BGR9 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
for ( i = 0 ; i < size ; i + + )
{
unsigned int lm = ( ( unsigned int * ) lightmap ) [ i ] ;
blocklights [ i ] + = max3 ( ( ( lm > > 0 ) & 0x1ff ) , ( ( lm > > 9 ) & 0x1ff ) , ( ( lm > > 18 ) & 0x1ff ) ) * scale * ( rgb9e5tab [ lm > > 27 ] * ( 1 < < 7 ) ) ;
}
lightmap + = size * 4 ; // skip to next lightmap
}
break ;
case LM_RGB8 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
2016-07-12 00:40:13 +00:00
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
for ( i = 0 ; i < size ; i + + )
2018-03-04 14:41:16 +00:00
blocklights [ i ] + = max3 ( lightmap [ i * 3 ] , lightmap [ i * 3 + 1 ] , lightmap [ i * 3 + 2 ] ) * scale ;
2016-07-12 00:40:13 +00:00
lightmap + = size * 3 ; // skip to next lightmap
}
2018-03-04 14:41:16 +00:00
break ;
case LM_L8 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
for ( i = 0 ; i < size ; i + + )
blocklights [ i ] + = lightmap [ i ] * scale ;
lightmap + = size ; // skip to next lightmap
}
2018-03-04 14:41:16 +00:00
break ;
}
2016-07-12 00:40:13 +00:00
}
// add all the dynamic lights
if ( surf - > dlightframe = = r_framecount )
Surf_AddDynamicLights ( surf ) ;
}
2018-03-04 14:41:16 +00:00
Surf_StoreLightmap_Grey ( dest , blocklights , smax , tmax , shift , stainsrc , lmwidth ) ;
2016-07-12 00:40:13 +00:00
}
}
2017-02-19 00:15:42 +00:00
# if defined(THREADEDWORLD) && (defined(Q1BSPS)||defined(Q2BSPS))
2016-07-12 00:40:13 +00:00
static void Surf_BuildLightMap_Worker ( model_t * wmodel , msurface_t * surf , qbyte * dest , qbyte * deluxdest , stmap * stainsrc , int shift , int ambient , unsigned int lmwidth , int * d_lightstylevalue )
{
int smax , tmax ;
int t ;
int i , j ;
size_t size ;
qbyte * lightmap ;
2018-03-04 14:41:16 +00:00
unsigned scalergb [ 3 ] ;
2016-07-12 00:40:13 +00:00
unsigned scale ;
int maps ;
unsigned * bl ;
static size_t maxblocksize ;
static vec3_t * blocknormals ;
static unsigned int * blocklights ;
//int stride = LMBLOCK_WIDTH*lightmap_bytes; //warning: unused variable <20> stride<64>
shift + = 7 ; // increase to base value
surf - > cached_dlight = false ;
smax = ( surf - > extents [ 0 ] > > surf - > lmshift ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > surf - > lmshift ) + 1 ;
size = ( size_t ) smax * tmax ;
lightmap = surf - > samples ;
if ( size > maxblocksize )
{ //fixme: fill in?
maxblocksize = size ;
blocknormals = BZ_Realloc ( blocknormals , maxblocksize * sizeof ( * blocknormals ) ) ; //already a vector
blocklights = BZ_Realloc ( blocklights , maxblocksize * 3 * sizeof ( * blocklights ) ) ;
}
if ( wmodel - > deluxdata )
Surf_BuildDeluxMap ( wmodel , surf , deluxdest , lmwidth , blocknormals ) ;
2018-03-04 14:41:16 +00:00
if ( lightmap_fmt ! = PTI_L8 )
2016-07-12 00:40:13 +00:00
{
// set to full bright if no light data
if ( ambient < 0 )
{
t = ( - 1 - ambient ) * 255 ;
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = t ;
}
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS ; maps + + )
{
surf - > cached_light [ maps ] = - 1 - ambient ;
surf - > cached_colour [ maps ] = 0xff ;
}
}
else if ( r_fullbright . value > 0 ) //not qw
{
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = r_fullbright . value * 255 * 256 ;
}
}
else if ( ! wmodel - > lightdata )
{
/*fullbright if map is not lit. but not overbright*/
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = 128 * 256 ;
}
}
else if ( ! surf - > samples )
{
/*no samples, but map is otherwise lit = pure black*/
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = 0 ;
}
surf - > cached_light [ 0 ] = 0 ;
surf - > cached_colour [ 0 ] = 0 ;
}
else
{
// clear to no light
t = ambient ;
if ( t = = 0 )
memset ( blocklights , 0 , size * 3 * sizeof ( * bl ) ) ;
else
{
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = t ;
}
}
// add all the lightmaps
if ( lightmap )
{
if ( wmodel - > fromgame = = fg_quake3 ) //rgb
{
/*q3 lightmaps are meant to be pre-built
this code is misguided , and ought never be executed anyway .
*/
bl = blocklights ;
for ( i = 0 ; i < tmax ; i + + )
{
for ( j = 0 ; j < smax ; j + + )
{
bl [ 0 ] = 255 * lightmap [ ( i * lmwidth + j ) * 3 ] ;
bl [ 1 ] = 255 * lightmap [ ( i * lmwidth + j ) * 3 + 1 ] ;
bl [ 2 ] = 255 * lightmap [ ( i * lmwidth + j ) * 3 + 2 ] ;
bl + = 3 ;
}
}
}
2018-03-04 14:41:16 +00:00
else switch ( cl . worldmodel - > lightmaps . fmt )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
case LM_E5BGR9 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
surf - > cached_light [ maps ] = scale = d_lightstylevalue [ surf - > styles [ maps ] ] ; // 8.8 fraction
2016-07-12 00:40:13 +00:00
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
if ( scale )
{
2018-03-04 14:41:16 +00:00
VectorScale ( cl_lightstyle [ surf - > styles [ maps ] ] . colours , scale , scalergb ) ;
for ( i = 0 ; i < size ; i + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
unsigned int l = ( ( unsigned int * ) lightmap ) [ i ] ;
float e = rgb9e5tab [ l > > 27 ] * ( 1 < < 7 ) ;
blocklights [ i * 3 + 0 ] + = scalergb [ 0 ] * e * ( ( l > > 0 ) & 0x1ff ) ;
blocklights [ i * 3 + 1 ] + = scalergb [ 1 ] * e * ( ( l > > 9 ) & 0x1ff ) ;
blocklights [ i * 3 + 2 ] + = scalergb [ 2 ] * e * ( ( l > > 18 ) & 0x1ff ) ;
2016-07-12 00:40:13 +00:00
}
2018-03-04 14:41:16 +00:00
}
lightmap + = size * 4 ; // skip to next lightmap
}
break ;
case LM_RGB8 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
{
surf - > cached_light [ maps ] = scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
if ( scale )
{
VectorScale ( cl_lightstyle [ surf - > styles [ maps ] ] . colours , scale , scalergb ) ;
bl = blocklights ;
for ( i = 0 ; i < size ; i + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
* bl + + + = * lightmap + + * scalergb [ 0 ] ;
* bl + + + = * lightmap + + * scalergb [ 1 ] ;
* bl + + + = * lightmap + + * scalergb [ 2 ] ;
2016-07-12 00:40:13 +00:00
}
}
else
lightmap + = size * 3 ; // skip to next lightmap
}
2018-03-04 14:41:16 +00:00
break ;
case LM_L8 :
2016-07-12 00:40:13 +00:00
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ;
maps + + )
{
2018-03-04 14:41:16 +00:00
surf - > cached_light [ maps ] = scale = d_lightstylevalue [ surf - > styles [ maps ] ] ; // 8.8 fraction
2016-07-12 00:40:13 +00:00
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
2018-03-04 14:41:16 +00:00
if ( scale )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
VectorScale ( cl_lightstyle [ surf - > styles [ maps ] ] . colours , scale , scalergb ) ;
2016-07-12 00:40:13 +00:00
bl = blocklights ;
for ( i = 0 ; i < size ; i + + )
{
2018-03-04 14:41:16 +00:00
* bl + + + = * lightmap * scalergb [ 0 ] ;
* bl + + + = * lightmap * scalergb [ 1 ] ;
* bl + + + = * lightmap * scalergb [ 2 ] ;
2016-07-12 00:40:13 +00:00
lightmap + + ;
}
}
else
lightmap + = size ; // skip to next lightmap
}
2018-03-04 14:41:16 +00:00
break ;
}
2016-07-12 00:40:13 +00:00
}
}
if ( ! r_stains . value | | ! surf - > stained )
stainsrc = NULL ;
2018-03-04 14:41:16 +00:00
Surf_StoreLightmap_RGB ( dest , blocklights , smax , tmax , shift , stainsrc , lmwidth ) ;
2016-07-12 00:40:13 +00:00
}
else
{
// set to full bright if no light data
if ( ! surf - > samples | | ! wmodel - > lightdata )
{
for ( i = 0 ; i < size * 3 ; i + + )
{
blocklights [ i ] = 255 * 256 ;
}
surf - > cached_light [ 0 ] = d_lightstylevalue [ 0 ] ;
surf - > cached_colour [ 0 ] = cl_lightstyle [ 0 ] . colourkey ;
}
else if ( r_fullbright . ival )
{
for ( i = 0 ; i < size ; i + + )
blocklights [ i ] = 255 * 256 ;
}
else
{
// clear to no light
for ( i = 0 ; i < size ; i + + )
blocklights [ i ] = 0 ;
// add all the lightmaps
if ( lightmap )
{
2018-03-04 14:41:16 +00:00
switch ( cl . worldmodel - > lightmaps . fmt )
{
case LM_E5BGR9 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
for ( i = 0 ; i < size ; i + + )
{
unsigned int lm = ( ( unsigned int * ) lightmap ) [ i ] ;
blocklights [ i ] + = max3 ( ( ( lm > > 0 ) & 0x1ff ) , ( ( lm > > 9 ) & 0x1ff ) , ( ( lm > > 18 ) & 0x1ff ) ) * scale * ( rgb9e5tab [ lm > > 27 ] * ( 1 < < 7 ) ) ;
}
lightmap + = size * 4 ; // skip to next lightmap
}
break ;
case LM_RGB8 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
2016-07-12 00:40:13 +00:00
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
for ( i = 0 ; i < size ; i + + )
2018-03-04 14:41:16 +00:00
blocklights [ i ] + = max3 ( lightmap [ i * 3 ] , lightmap [ i * 3 + 1 ] , lightmap [ i * 3 + 2 ] ) * scale ;
2016-07-12 00:40:13 +00:00
lightmap + = size * 3 ; // skip to next lightmap
}
2018-03-04 14:41:16 +00:00
break ;
case LM_L8 :
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & surf - > styles [ maps ] ! = 255 ; maps + + )
2016-07-12 00:40:13 +00:00
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
surf - > cached_colour [ maps ] = cl_lightstyle [ surf - > styles [ maps ] ] . colourkey ;
for ( i = 0 ; i < size ; i + + )
blocklights [ i ] + = lightmap [ i ] * scale ;
lightmap + = size ; // skip to next lightmap
}
2018-03-04 14:41:16 +00:00
break ;
}
2016-07-12 00:40:13 +00:00
}
}
2018-03-04 14:41:16 +00:00
Surf_StoreLightmap_Grey ( dest , blocklights , smax , tmax , shift , stainsrc , lmwidth ) ;
2016-07-12 00:40:13 +00:00
}
}
# endif
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BRUSH MODELS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = =
R_RenderDynamicLightmaps
Multitexture
= = = = = = = = = = = = = = = =
*/
void Surf_RenderDynamicLightmaps ( msurface_t * fa )
{
qbyte * base , * luxbase ;
stmap * stainbase ;
int maps ;
glRect_t * theRect ;
int smax , tmax ;
lightmapinfo_t * lm , * dlm ;
//surfaces without lightmaps
if ( fa - > lightmaptexturenums [ 0 ] < 0 | | ! lightmap )
return ;
// check for lightmap modification
if ( ! fa - > samples )
{
if ( fa - > cached_light [ 0 ] ! = 0
| | fa - > cached_colour [ 0 ] ! = 0 )
goto dynamic ;
}
else
{
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & fa - > styles [ maps ] ! = 255 ;
maps + + )
if ( d_lightstylevalue [ fa - > styles [ maps ] ] ! = fa - > cached_light [ maps ]
| | cl_lightstyle [ fa - > styles [ maps ] ] . colourkey ! = fa - > cached_colour [ maps ] )
goto dynamic ;
}
if ( fa - > dlightframe = = r_framecount // dynamic this frame
| | fa - > cached_dlight ) // dynamic previously
{
RSpeedLocals ( ) ;
dynamic :
RSpeedRemark ( ) ;
# ifdef _DEBUG
if ( ( unsigned ) fa - > lightmaptexturenums [ 0 ] > = numlightmaps )
Sys_Error ( " Invalid lightmap index \n " ) ;
# endif
lm = lightmap [ fa - > lightmaptexturenums [ 0 ] ] ;
lm - > modified = true ;
smax = ( fa - > extents [ 0 ] > > fa - > lmshift ) + 1 ;
tmax = ( fa - > extents [ 1 ] > > fa - > lmshift ) + 1 ;
theRect = & lm - > rectchange ;
if ( theRect - > t > fa - > light_t [ 0 ] )
theRect - > t = fa - > light_t [ 0 ] ;
if ( theRect - > b < fa - > light_t [ 0 ] + tmax )
theRect - > b = fa - > light_t [ 0 ] + tmax ;
if ( theRect - > l > fa - > light_s [ 0 ] )
theRect - > l = fa - > light_s [ 0 ] ;
if ( theRect - > r < fa - > light_s [ 0 ] + smax )
theRect - > r = fa - > light_s [ 0 ] + smax ;
if ( lm - > hasdeluxe )
{
dlm = lightmap [ fa - > lightmaptexturenums [ 0 ] + 1 ] ;
dlm - > modified = true ;
theRect = & dlm - > rectchange ;
if ( theRect - > t > fa - > light_t [ 0 ] )
theRect - > t = fa - > light_t [ 0 ] ;
if ( theRect - > b < fa - > light_t [ 0 ] + tmax )
theRect - > b = fa - > light_t [ 0 ] + tmax ;
if ( theRect - > l > fa - > light_s [ 0 ] )
theRect - > l = fa - > light_s [ 0 ] ;
if ( theRect - > r < fa - > light_s [ 0 ] + smax )
theRect - > r = fa - > light_s [ 0 ] + smax ;
luxbase = dlm - > lightmaps ;
luxbase + = ( fa - > light_t [ 0 ] * dlm - > width + fa - > light_s [ 0 ] ) * lightmap_bytes ;
}
else
luxbase = NULL ;
base = lm - > lightmaps ;
base + = ( fa - > light_t [ 0 ] * lm - > width + fa - > light_s [ 0 ] ) * lightmap_bytes ;
stainbase = lm - > stainmaps ;
stainbase + = ( fa - > light_t [ 0 ] * lm - > width + fa - > light_s [ 0 ] ) * 3 ;
2018-03-04 14:41:16 +00:00
Surf_BuildLightMap ( currentmodel , fa , base , luxbase , stainbase , lightmap_shift , r_ambient . value * 255 , lm - > width , d_lightstylevalue ) ;
2016-07-12 00:40:13 +00:00
RSpeedEnd ( RSPEED_DYNAMIC ) ;
}
}
2017-02-19 00:15:42 +00:00
# if defined(THREADEDWORLD) && (defined(Q1BSPS)||defined(Q2BSPS))
2016-07-12 00:40:13 +00:00
static void Surf_RenderDynamicLightmaps_Worker ( model_t * wmodel , msurface_t * fa , int * d_lightstylevalue )
{
qbyte * base , * luxbase ;
stmap * stainbase ;
int maps ;
glRect_t * lmr , * dlmr = NULL ;
int smax , tmax ;
lightmapinfo_t * lm , * dlm = NULL ;
//surfaces without lightmaps
if ( fa - > lightmaptexturenums [ 0 ] < 0 | | ! lightmap )
return ;
// check for lightmap modification
if ( ! fa - > samples )
{
if ( fa - > cached_light [ 0 ] ! = 0
| | fa - > cached_colour [ 0 ] ! = 0 )
goto dynamic ;
}
else
{
for ( maps = 0 ; maps < MAXQ1LIGHTMAPS & & fa - > styles [ maps ] ! = 255 ;
maps + + )
if ( d_lightstylevalue [ fa - > styles [ maps ] ] ! = fa - > cached_light [ maps ]
| | cl_lightstyle [ fa - > styles [ maps ] ] . colourkey ! = fa - > cached_colour [ maps ] )
goto dynamic ;
}
return ;
dynamic :
# ifdef _DEBUG
if ( ( unsigned ) fa - > lightmaptexturenums [ 0 ] > = numlightmaps )
Sys_Error ( " Invalid lightmap index \n " ) ;
# endif
lm = lightmap [ fa - > lightmaptexturenums [ 0 ] ] ;
smax = ( fa - > extents [ 0 ] > > fa - > lmshift ) + 1 ;
tmax = ( fa - > extents [ 1 ] > > fa - > lmshift ) + 1 ;
lmr = & lm - > rectchange ;
if ( lm - > hasdeluxe )
{
dlm = lightmap [ fa - > lightmaptexturenums [ 0 ] + 1 ] ;
dlmr = & dlm - > rectchange ;
luxbase = dlm - > lightmaps ;
luxbase + = ( fa - > light_t [ 0 ] * dlm - > width + fa - > light_s [ 0 ] ) * lightmap_bytes ;
}
else
luxbase = NULL ;
base = lm - > lightmaps ;
base + = ( fa - > light_t [ 0 ] * lm - > width + fa - > light_s [ 0 ] ) * lightmap_bytes ;
stainbase = lm - > stainmaps ;
stainbase + = ( fa - > light_t [ 0 ] * lm - > width + fa - > light_s [ 0 ] ) * 3 ;
Surf_BuildLightMap_Worker ( wmodel , fa , base , luxbase , stainbase , lightmap_shift , r_ambient . value * 255 , lm - > width , d_lightstylevalue ) ;
if ( dlm )
{
if ( dlmr - > t > fa - > light_t [ 0 ] )
dlmr - > t = fa - > light_t [ 0 ] ;
if ( dlmr - > b < fa - > light_t [ 0 ] + tmax )
dlmr - > b = fa - > light_t [ 0 ] + tmax ;
if ( dlmr - > l > fa - > light_s [ 0 ] )
dlmr - > l = fa - > light_s [ 0 ] ;
if ( dlmr - > r < fa - > light_s [ 0 ] + smax )
dlmr - > r = fa - > light_s [ 0 ] + smax ;
dlm - > modified = true ;
}
if ( lmr - > t > fa - > light_t [ 0 ] )
lmr - > t = fa - > light_t [ 0 ] ;
if ( lmr - > b < fa - > light_t [ 0 ] + tmax )
lmr - > b = fa - > light_t [ 0 ] + tmax ;
if ( lmr - > l > fa - > light_s [ 0 ] )
lmr - > l = fa - > light_s [ 0 ] ;
if ( lmr - > r < fa - > light_s [ 0 ] + smax )
lmr - > r = fa - > light_s [ 0 ] + smax ;
lm - > modified = true ;
}
# endif //THREADEDWORLD
void Surf_RenderAmbientLightmaps ( msurface_t * fa , int ambient )
{
qbyte * base , * luxbase ;
stmap * stainbase ;
glRect_t * theRect ;
int smax , tmax ;
lightmapinfo_t * lm , * dlm ;
if ( ! fa - > mesh )
return ;
//surfaces without lightmaps
if ( fa - > lightmaptexturenums [ 0 ] < 0 )
return ;
if ( fa - > cached_light [ 0 ] ! = ambient | | fa - > cached_colour [ 0 ] ! = 0xff )
goto dynamic ;
if ( fa - > dlightframe = = r_framecount // dynamic this frame
| | fa - > cached_dlight ) // dynamic previously
{
RSpeedLocals ( ) ;
dynamic :
RSpeedRemark ( ) ;
lm = lightmap [ fa - > lightmaptexturenums [ 0 ] ] ;
lm - > modified = true ;
smax = ( fa - > extents [ 0 ] > > fa - > lmshift ) + 1 ;
tmax = ( fa - > extents [ 1 ] > > fa - > lmshift ) + 1 ;
theRect = & lm - > rectchange ;
if ( theRect - > t > fa - > light_t [ 0 ] )
theRect - > t = fa - > light_t [ 0 ] ;
if ( theRect - > l > fa - > light_s [ 0 ] )
theRect - > l = fa - > light_s [ 0 ] ;
if ( theRect - > r < fa - > light_s [ 0 ] + smax )
theRect - > r = fa - > light_s [ 0 ] + smax ;
if ( theRect - > b < fa - > light_t [ 0 ] + tmax )
theRect - > b = fa - > light_t [ 0 ] + tmax ;
if ( lm - > hasdeluxe )
{
dlm = lightmap [ fa - > lightmaptexturenums [ 0 ] + 1 ] ;
lm - > modified = true ;
theRect = & lm - > rectchange ;
if ( theRect - > t > fa - > light_t [ 0 ] )
theRect - > t = fa - > light_t [ 0 ] ;
if ( theRect - > l > fa - > light_s [ 0 ] )
theRect - > l = fa - > light_s [ 0 ] ;
if ( theRect - > r < fa - > light_s [ 0 ] + smax )
theRect - > r = fa - > light_s [ 0 ] + smax ;
if ( theRect - > b < fa - > light_t [ 0 ] + tmax )
theRect - > b = fa - > light_t [ 0 ] + tmax ;
luxbase = dlm - > lightmaps ;
luxbase + = ( fa - > light_t [ 0 ] * dlm - > width + fa - > light_s [ 0 ] ) * lightmap_bytes ;
}
else
luxbase = NULL ;
base = lm - > lightmaps ;
base + = ( fa - > light_t [ 0 ] * lm - > width + fa - > light_s [ 0 ] ) * lightmap_bytes ;
stainbase = lm - > stainmaps ;
stainbase + = ( fa - > light_t [ 0 ] * lm - > width + fa - > light_s [ 0 ] ) * 3 ;
2018-03-04 14:41:16 +00:00
Surf_BuildLightMap ( currentmodel , fa , base , luxbase , stainbase , lightmap_shift , - 1 - ambient , lm - > width , d_lightstylevalue ) ;
2016-07-12 00:40:13 +00:00
RSpeedEnd ( RSPEED_DYNAMIC ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
WORLD MODEL
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
#if 0
static qbyte * R_MarkLeafSurfaces_Q1 ( void )
{
qbyte * vis ;
mleaf_t * leaf ;
int i , j ;
msurface_t * surf ;
int shift ;
vis = R_CalcVis_Q1 ( ) ;
for ( i = 0 ; i < cl . worldmodel - > numvisleafs ; i + + )
{
if ( vis [ i > > 3 ] & ( 1 < < ( i & 7 ) ) )
{
leaf = ( mleaf_t * ) & cl . worldmodel - > leafs [ i + 1 ] ;
if ( R_CullBox ( leaf - > minmaxs , leaf - > minmaxs + 3 ) )
continue ;
leaf - > visframe = r_visframecount ;
for ( j = 0 ; j < leaf - > nummarksurfaces ; j + + )
{
surf = leaf - > firstmarksurface [ j ] ;
if ( surf - > visframe = = r_visframecount )
continue ;
surf - > visframe = r_visframecount ;
* surf - > mark = surf ;
}
}
}
{
texture_t * tex ;
shift = Surf_LightmapShift ( cl . worldmodel ) ;
for ( i = 0 ; i < cl . worldmodel - > numtextures ; i + + )
{
tex = cl . worldmodel - > textures [ i ] ;
if ( ! tex )
continue ;
for ( j = 0 ; j < tex - > vbo . meshcount ; j + + )
{
surf = tex - > vbo . meshlist [ j ] ;
if ( surf )
{
Surf_RenderDynamicLightmaps ( surf ) ;
tex - > vbo . meshlist [ j ] = NULL ;
surf - > sbatch - > mesh [ surf - > sbatch - > meshes + + ] = surf - > mesh ;
}
}
}
}
return vis ;
}
# endif
/*
static qbyte * Surf_MaskVis ( qbyte * src , qbyte * dest )
{
int i ;
if ( cl . worldmodel - > leafs [ i ] . ma
}
*/
qbyte * frustumvis ;
2017-02-19 00:15:42 +00:00
# ifdef Q1BSPS
2016-07-12 00:40:13 +00:00
/*
= = = = = = = = = = = = = = = =
R_RecursiveWorldNode
= = = = = = = = = = = = = = = =
*/
static void Surf_RecursiveWorldNode ( mnode_t * node , unsigned int clipflags )
{
int c , side , clipped ;
mplane_t * plane , * clipplane ;
msurface_t * surf , * * mark ;
mleaf_t * pleaf ;
double dot ;
start :
if ( node - > contents = = Q1CONTENTS_SOLID )
return ; // solid
if ( node - > visframe ! = r_visframecount )
return ;
for ( c = 0 , clipplane = r_refdef . frustum ; c < r_refdef . frustum_numworldplanes ; c + + , clipplane + + )
{
if ( ! ( clipflags & ( 1 < < c ) ) )
continue ; // don't need to clip against it
clipped = BOX_ON_PLANE_SIDE ( node - > minmaxs , node - > minmaxs + 3 , clipplane ) ;
if ( clipped = = 2 )
return ;
else if ( clipped = = 1 )
clipflags - = ( 1 < < c ) ; // node is entirely on screen
}
// if a leaf node, draw stuff
if ( node - > contents < 0 )
{
pleaf = ( mleaf_t * ) node ;
c = ( pleaf - cl . worldmodel - > leafs ) - 1 ;
frustumvis [ c > > 3 ] | = 1 < < ( c & 7 ) ;
mark = pleaf - > firstmarksurface ;
c = pleaf - > nummarksurfaces ;
if ( c )
{
do
{
( * mark + + ) - > visframe = r_framecount ;
} while ( - - c ) ;
}
return ;
}
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
plane = node - > plane ;
switch ( plane - > type )
{
case PLANE_X :
dot = modelorg [ 0 ] - plane - > dist ;
break ;
case PLANE_Y :
dot = modelorg [ 1 ] - plane - > dist ;
break ;
case PLANE_Z :
dot = modelorg [ 2 ] - plane - > dist ;
break ;
default :
dot = DotProduct ( modelorg , plane - > normal ) - plane - > dist ;
break ;
}
if ( dot > = 0 )
side = 0 ;
else
side = 1 ;
// recurse down the children, front side first
Surf_RecursiveWorldNode ( node - > children [ side ] , clipflags ) ;
// draw stuff
2017-01-13 00:39:50 +00:00
c = node - > numsurfaces ;
2016-07-12 00:40:13 +00:00
if ( c )
{
surf = cl . worldmodel - > surfaces + node - > firstsurface ;
if ( dot < 0 - BACKFACE_EPSILON )
side = SURF_PLANEBACK ;
else if ( dot > BACKFACE_EPSILON )
side = 0 ;
{
for ( ; c ; c - - , surf + + )
{
if ( surf - > visframe ! = r_framecount )
continue ;
if ( ( ( dot < 0 ) ^ ! ! ( surf - > flags & SURF_PLANEBACK ) ) )
continue ; // wrong side
Surf_RenderDynamicLightmaps ( surf ) ;
surf - > sbatch - > mesh [ surf - > sbatch - > meshes + + ] = surf - > mesh ;
}
}
}
// recurse down the back side
//GLR_RecursiveWorldNode (node->children[!side], clipflags);
node = node - > children [ ! side ] ;
goto start ;
}
static void Surf_OrthoRecursiveWorldNode ( mnode_t * node , unsigned int clipflags )
{
//when rendering as ortho the front and back sides are technically equal. the only culling comes from frustum culling.
int c , clipped ;
mplane_t * clipplane ;
msurface_t * surf , * * mark ;
mleaf_t * pleaf ;
if ( node - > contents = = Q1CONTENTS_SOLID )
return ; // solid
if ( node - > visframe ! = r_visframecount )
return ;
for ( c = 0 , clipplane = r_refdef . frustum ; c < r_refdef . frustum_numworldplanes ; c + + , clipplane + + )
{
if ( ! ( clipflags & ( 1 < < c ) ) )
continue ; // don't need to clip against it
clipped = BOX_ON_PLANE_SIDE ( node - > minmaxs , node - > minmaxs + 3 , clipplane ) ;
if ( clipped = = 2 )
return ;
else if ( clipped = = 1 )
clipflags - = ( 1 < < c ) ; // node is entirely on screen
}
// if a leaf node, draw stuff
if ( node - > contents < 0 )
{
pleaf = ( mleaf_t * ) node ;
mark = pleaf - > firstmarksurface ;
c = pleaf - > nummarksurfaces ;
if ( c )
{
do
{
( * mark + + ) - > visframe = r_framecount ;
} while ( - - c ) ;
}
return ;
}
// recurse down the children
Surf_OrthoRecursiveWorldNode ( node - > children [ 0 ] , clipflags ) ;
Surf_OrthoRecursiveWorldNode ( node - > children [ 1 ] , clipflags ) ;
// draw stuff
c = node - > numsurfaces ;
if ( c )
{
surf = cl . worldmodel - > surfaces + node - > firstsurface ;
for ( ; c ; c - - , surf + + )
{
if ( surf - > visframe ! = r_framecount )
continue ;
Surf_RenderDynamicLightmaps ( surf ) ;
surf - > sbatch - > mesh [ surf - > sbatch - > meshes + + ] = surf - > mesh ;
}
}
return ;
}
2017-02-19 00:15:42 +00:00
# endif
2016-07-12 00:40:13 +00:00
# ifdef Q2BSPS
static void Surf_RecursiveQ2WorldNode ( mnode_t * node )
{
int c , side ;
mplane_t * plane ;
msurface_t * surf , * * mark ;
mleaf_t * pleaf ;
double dot ;
int sidebit ;
if ( node - > contents = = Q2CONTENTS_SOLID )
return ; // solid
if ( node - > visframe ! = r_visframecount )
return ;
if ( R_CullBox ( node - > minmaxs , node - > minmaxs + 3 ) )
return ;
// if a leaf node, draw stuff
if ( node - > contents ! = - 1 )
{
pleaf = ( mleaf_t * ) node ;
// check for door connected areas
if ( ! ( r_refdef . areabits [ pleaf - > area > > 3 ] & ( 1 < < ( pleaf - > area & 7 ) ) ) )
return ; // not visible
c = pleaf - > cluster ;
if ( c > = 0 )
frustumvis [ c > > 3 ] | = 1 < < ( c & 7 ) ;
mark = pleaf - > firstmarksurface ;
c = pleaf - > nummarksurfaces ;
if ( c )
{
do
{
( * mark ) - > visframe = r_framecount ;
mark + + ;
} while ( - - c ) ;
}
return ;
}
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
plane = node - > plane ;
switch ( plane - > type )
{
case PLANE_X :
dot = modelorg [ 0 ] - plane - > dist ;
break ;
case PLANE_Y :
dot = modelorg [ 1 ] - plane - > dist ;
break ;
case PLANE_Z :
dot = modelorg [ 2 ] - plane - > dist ;
break ;
default :
dot = DotProduct ( modelorg , plane - > normal ) - plane - > dist ;
break ;
}
if ( dot > = 0 )
{
side = 0 ;
sidebit = 0 ;
}
else
{
side = 1 ;
sidebit = SURF_PLANEBACK ;
}
// recurse down the children, front side first
Surf_RecursiveQ2WorldNode ( node - > children [ side ] ) ;
// draw stuff
for ( c = node - > numsurfaces , surf = currentmodel - > surfaces + node - > firstsurface ; c ; c - - , surf + + )
{
if ( surf - > visframe ! = r_framecount )
continue ;
if ( ( surf - > flags & SURF_PLANEBACK ) ! = sidebit )
continue ; // wrong side
surf - > visframe = 0 ; //r_framecount+1;//-1;
Surf_RenderDynamicLightmaps ( surf ) ;
surf - > sbatch - > mesh [ surf - > sbatch - > meshes + + ] = surf - > mesh ;
}
// recurse down the back side
Surf_RecursiveQ2WorldNode ( node - > children [ ! side ] ) ;
}
# endif
# ifdef Q3BSPS
#if 0
static void Surf_LeafWorldNode ( void )
{
int i ;
int clipflags ;
msurface_t * * mark , * surf ;
mleaf_t * pleaf ;
int clipped ;
mplane_t * clipplane ;
for ( pleaf = r_vischain ; pleaf ; pleaf = pleaf - > vischain )
{
// check for door connected areas
// if (areabits)
{
// if (!(areabits[pleaf->area>>3] & (1<<(pleaf->area&7))))
// {
// continue; // not visible
// }
}
clipflags = 15 ; // 1 | 2 | 4 | 8
// if (!r_nocull->value)
{
for ( i = 0 , clipplane = frustum ; i < FRUSTUMPLANES ; i + + , clipplane + + )
{
clipped = BoxOnPlaneSide ( pleaf - > minmaxs , pleaf - > minmaxs + 3 , clipplane ) ;
if ( clipped = = 2 )
{
break ;
}
else if ( clipped = = 1 )
{
clipflags & = ~ ( 1 < < i ) ; // node is entirely on screen
}
}
if ( i ! = FRUSTUMPLANES )
{
continue ;
}
}
i = pleaf - > nummarksurfaces ;
mark = pleaf - > firstmarksurface ;
do
{
surf = * mark + + ;
if ( surf - > visframe ! = r_framecount ) //sufraces exist in multiple leafs.
{
surf - > visframe = r_framecount ;
if ( surf - > mark )
* surf - > mark = surf ;
}
} while ( - - i ) ;
// c_world_leafs++;
}
{
int j ;
texture_t * tex ;
for ( i = 0 ; i < cl . worldmodel - > numtextures ; i + + )
{
tex = cl . worldmodel - > textures [ i ] ;
if ( ! tex )
continue ;
for ( j = 0 ; j < tex - > vbo . meshcount ; j + + )
{
surf = tex - > vbo . meshlist [ j ] ;
if ( surf )
{
tex - > vbo . meshlist [ j ] = NULL ;
surf - > sbatch - > mesh [ surf - > sbatch - > meshes + + ] = surf - > mesh ;
}
}
}
}
}
# endif
static void Surf_RecursiveQ3WorldNode ( mnode_t * node , unsigned int clipflags )
{
int c , side , clipped ;
mplane_t * plane , * clipplane ;
msurface_t * surf , * * mark ;
mleaf_t * pleaf ;
double dot ;
start :
if ( node - > visframe ! = r_visframecount )
return ;
for ( c = 0 , clipplane = r_refdef . frustum ; c < r_refdef . frustum_numworldplanes ; c + + , clipplane + + )
{
if ( ! ( clipflags & ( 1 < < c ) ) )
continue ; // don't need to clip against it
clipped = BOX_ON_PLANE_SIDE ( node - > minmaxs , node - > minmaxs + 3 , clipplane ) ;
if ( clipped = = 2 )
return ;
else if ( clipped = = 1 )
clipflags - = ( 1 < < c ) ; // node is entirely on screen
}
// if a leaf node, draw stuff
if ( node - > contents ! = - 1 )
{
pleaf = ( mleaf_t * ) node ;
if ( ! ( r_refdef . areabits [ pleaf - > area > > 3 ] & ( 1 < < ( pleaf - > area & 7 ) ) ) )
return ; // not visible
c = pleaf - > cluster ;
if ( c > = 0 )
frustumvis [ c > > 3 ] | = 1 < < ( c & 7 ) ;
mark = pleaf - > firstmarksurface ;
for ( c = pleaf - > nummarksurfaces ; c ; c - - )
{
surf = * mark + + ;
if ( surf - > visframe = = r_framecount )
continue ;
surf - > visframe = r_framecount ;
// if (((dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)))
// continue; // wrong side
surf - > sbatch - > mesh [ surf - > sbatch - > meshes + + ] = surf - > mesh ;
}
return ;
}
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
plane = node - > plane ;
switch ( plane - > type )
{
case PLANE_X :
dot = modelorg [ 0 ] - plane - > dist ;
break ;
case PLANE_Y :
dot = modelorg [ 1 ] - plane - > dist ;
break ;
case PLANE_Z :
dot = modelorg [ 2 ] - plane - > dist ;
break ;
default :
dot = DotProduct ( modelorg , plane - > normal ) - plane - > dist ;
break ;
}
if ( dot > = 0 )
side = 0 ;
else
side = 1 ;
// recurse down the children, front side first
Surf_RecursiveQ3WorldNode ( node - > children [ side ] , clipflags ) ;
// q3 nodes contain no drawables
// recurse down the back side
//GLR_RecursiveWorldNode (node->children[!side], clipflags);
node = node - > children [ ! side ] ;
goto start ;
}
# endif
static void Surf_PushChains ( batch_t * * batches )
{
batch_t * batch ;
int i ;
if ( r_refdef . recurse = = R_MAX_RECURSE )
Sys_Error ( " Recursed too deep \n " ) ;
if ( ! r_refdef . recurse )
{
for ( i = 0 ; i < SHADER_SORT_COUNT ; i + + )
for ( batch = batches [ i ] ; batch ; batch = batch - > next )
{
batch - > firstmesh = 0 ;
}
}
# if R_MAX_RECURSE > 2
else if ( r_refdef . recurse > 1 )
{
for ( i = 0 ; i < SHADER_SORT_COUNT ; i + + )
for ( batch = batches [ i ] ; batch ; batch = batch - > next )
{
batch - > recursefirst [ r_refdef . recurse ] = batch - > firstmesh ;
batch - > firstmesh = batch - > meshes ;
}
}
# endif
else
{
for ( i = 0 ; i < SHADER_SORT_COUNT ; i + + )
for ( batch = batches [ i ] ; batch ; batch = batch - > next )
{
batch - > firstmesh = batch - > meshes ;
}
}
}
static void Surf_PopChains ( batch_t * * batches )
{
batch_t * batch ;
int i ;
if ( ! r_refdef . recurse )
{
for ( i = 0 ; i < SHADER_SORT_COUNT ; i + + )
for ( batch = batches [ i ] ; batch ; batch = batch - > next )
{
batch - > meshes = 0 ;
}
}
# if R_MAX_RECURSE > 2
else if ( r_refdef . recurse > 1 )
{
for ( i = 0 ; i < SHADER_SORT_COUNT ; i + + )
for ( batch = batches [ i ] ; batch ; batch = batch - > next )
{
batch - > meshes = batch - > firstmesh ;
batch - > firstmesh = batch - > recursefirst [ r_refdef . recurse ] ;
}
}
# endif
else
{
for ( i = 0 ; i < SHADER_SORT_COUNT ; i + + )
for ( batch = batches [ i ] ; batch ; batch = batch - > next )
{
batch - > meshes = batch - > firstmesh ;
batch - > firstmesh = 0 ;
}
}
}
//most of this is a direct copy from gl
void Surf_SetupFrame ( void )
{
mleaf_t * leaf ;
vec3_t temp , pvsorg ;
2016-12-07 18:45:25 +00:00
int viewcontents ;
2016-07-12 00:40:13 +00:00
if ( ! cl . worldmodel | | ( ! cl . worldmodel - > nodes & & cl . worldmodel - > type ! = mod_heightmap ) )
r_refdef . flags | = RDF_NOWORLDMODEL ;
R_AnimateLight ( ) ;
r_framecount + + ;
if ( r_refdef . recurse )
{
VectorCopy ( r_refdef . pvsorigin , pvsorg ) ;
}
else
{
VectorCopy ( r_refdef . vieworg , pvsorg ) ;
R_UpdateHDR ( r_refdef . vieworg ) ;
}
2016-12-07 18:45:25 +00:00
viewcontents = 0 ;
2016-07-12 00:40:13 +00:00
if ( r_refdef . flags & RDF_NOWORLDMODEL )
{
}
else if ( ! cl . worldmodel | | cl . worldmodel - > loadstate ! = MLS_LOADED | | cl . worldmodel - > fromgame = = fg_doom3 )
{
2017-07-28 01:49:25 +00:00
r_viewcluster = - 1 ;
r_viewcluster2 = - 1 ;
2016-07-12 00:40:13 +00:00
}
2017-10-31 22:52:58 +00:00
# if defined(Q2BSPS) || defined(Q3BSPS)
2016-07-12 00:40:13 +00:00
else if ( cl . worldmodel - > fromgame = = fg_quake2 | | cl . worldmodel - > fromgame = = fg_quake3 )
{
leaf = Mod_PointInLeaf ( cl . worldmodel , pvsorg ) ;
2016-12-07 18:45:25 +00:00
viewcontents = cl . worldmodel - > funcs . PointContents ( cl . worldmodel , NULL , pvsorg ) ;
2016-07-12 00:40:13 +00:00
r_viewcluster = r_viewcluster2 = leaf - > cluster ;
// check above and below so crossing solid water doesn't draw wrong
if ( ! leaf - > contents )
{ // look down a bit
vec3_t temp ;
VectorCopy ( pvsorg , temp ) ;
temp [ 2 ] - = 16 ;
leaf = Mod_PointInLeaf ( cl . worldmodel , temp ) ;
if ( ! ( leaf - > contents & Q2CONTENTS_SOLID ) & &
( leaf - > cluster ! = r_viewcluster2 ) )
r_viewcluster2 = leaf - > cluster ;
}
else
{ // look up a bit
vec3_t temp ;
VectorCopy ( pvsorg , temp ) ;
temp [ 2 ] + = 16 ;
leaf = Mod_PointInLeaf ( cl . worldmodel , temp ) ;
if ( ! ( leaf - > contents & Q2CONTENTS_SOLID ) & &
( leaf - > cluster ! = r_viewcluster2 ) )
r_viewcluster2 = leaf - > cluster ;
}
}
# endif
else
{
2017-07-28 01:49:25 +00:00
leaf = Mod_PointInLeaf ( cl . worldmodel , pvsorg ) ;
r_viewcluster = ( leaf - cl . worldmodel - > leafs ) - 1 ;
r_viewcluster2 = - 1 ;
if ( leaf )
2016-07-12 00:40:13 +00:00
{
2017-07-28 01:49:25 +00:00
switch ( leaf - > contents )
2016-07-12 00:40:13 +00:00
{
case Q1CONTENTS_WATER :
2016-12-07 18:45:25 +00:00
viewcontents | = FTECONTENTS_WATER ;
2016-07-12 00:40:13 +00:00
break ;
case Q1CONTENTS_LAVA :
2016-12-07 18:45:25 +00:00
viewcontents | = FTECONTENTS_LAVA ;
2016-07-12 00:40:13 +00:00
break ;
case Q1CONTENTS_SLIME :
2016-12-07 18:45:25 +00:00
viewcontents | = FTECONTENTS_SLIME ;
2016-07-12 00:40:13 +00:00
break ;
case Q1CONTENTS_SKY :
2016-12-07 18:45:25 +00:00
viewcontents | = FTECONTENTS_SKY ;
2016-07-12 00:40:13 +00:00
break ;
case Q1CONTENTS_SOLID :
2016-12-07 18:45:25 +00:00
viewcontents | = FTECONTENTS_SOLID ;
2016-07-12 00:40:13 +00:00
break ;
case Q1CONTENTS_LADDER :
2016-12-07 18:45:25 +00:00
viewcontents | = FTECONTENTS_LADDER ;
2016-07-12 00:40:13 +00:00
break ;
}
2017-07-28 01:49:25 +00:00
if ( leaf - > contents = = Q1CONTENTS_EMPTY )
{ //look down a bit
VectorCopy ( pvsorg , temp ) ;
temp [ 2 ] - = 16 ;
leaf = Mod_PointInLeaf ( cl . worldmodel , temp ) ;
if ( leaf - > contents < = Q1CONTENTS_WATER & & leaf - > contents > = Q1CONTENTS_LAVA )
r_viewcluster2 = ( leaf - cl . worldmodel - > leafs ) - 1 ;
}
else if ( leaf - > contents < = Q1CONTENTS_WATER & & leaf - > contents > = Q1CONTENTS_LAVA )
{ //in water, look up a bit.
VectorCopy ( pvsorg , temp ) ;
temp [ 2 ] + = 16 ;
leaf = Mod_PointInLeaf ( cl . worldmodel , temp ) ;
if ( leaf - > contents = = Q1CONTENTS_EMPTY )
r_viewcluster2 = ( leaf - cl . worldmodel - > leafs ) - 1 ;
}
2016-07-12 00:40:13 +00:00
}
}
# ifdef TERRAIN
if ( ! ( r_refdef . flags & RDF_NOWORLDMODEL ) & & cl . worldmodel & & cl . worldmodel - > terrain )
{
2016-12-07 18:45:25 +00:00
viewcontents | = Heightmap_PointContents ( cl . worldmodel , NULL , pvsorg ) ;
2016-07-12 00:40:13 +00:00
}
# endif
/*pick up any extra water entities*/
{
vec3_t t1 , t2 ;
VectorCopy ( pmove . player_mins , t1 ) ;
VectorCopy ( pmove . player_maxs , t2 ) ;
VectorClear ( pmove . player_maxs ) ;
VectorClear ( pmove . player_mins ) ;
2016-12-07 18:45:25 +00:00
viewcontents | = PM_ExtraBoxContents ( pvsorg ) ;
2016-07-12 00:40:13 +00:00
VectorCopy ( t1 , pmove . player_mins ) ;
VectorCopy ( t2 , pmove . player_maxs ) ;
}
2016-12-07 18:45:25 +00:00
if ( ! r_refdef . recurse )
{
r_viewcontents = viewcontents ;
if ( ! r_secondaryview )
V_SetContentsColor ( viewcontents ) ;
}
2016-07-12 00:40:13 +00:00
if ( r_refdef . playerview - > audio . defaulted )
{
//first scene is the 'main' scene and audio defaults to that (unless overridden later in the frame)
r_refdef . playerview - > audio . defaulted = false ;
r_refdef . playerview - > audio . entnum = r_refdef . playerview - > viewentity ;
VectorCopy ( r_refdef . vieworg , r_refdef . playerview - > audio . origin ) ;
AngleVectors ( r_refdef . viewangles , r_refdef . playerview - > audio . forward , r_refdef . playerview - > audio . right , r_refdef . playerview - > audio . up ) ;
if ( r_viewcontents & FTECONTENTS_FLUID )
r_refdef . playerview - > audio . reverbtype = 1 ;
else
r_refdef . playerview - > audio . reverbtype = 0 ;
VectorCopy ( r_refdef . playerview - > simvel , r_refdef . playerview - > audio . velocity ) ;
}
}
/*
static mesh_t * surfbatchmeshes [ 256 ] ;
static void Surf_BuildBrushBatch ( batch_t * batch )
{
model_t * model = batch - > ent - > model ;
unsigned int i ;
batch - > mesh = surfbatchmeshes ;
batch - > meshes = batch - > surf_count ;
for ( i = 0 ; i < batch - > surf_count ; i + + )
{
surfbatchmeshes [ i ] = model - > surfaces [ batch - > surf_first + i ] . mesh ;
}
}
*/
void Surf_GenBrushBatches ( batch_t * * batches , entity_t * ent )
{
int i ;
msurface_t * s ;
batch_t * ob ;
model_t * model ;
batch_t * b ;
unsigned int bef ;
model = ent - > model ;
if ( R_CullEntityBox ( ent , model - > mins , model - > maxs ) )
return ;
# ifdef RTLIGHTS
if ( BE_LightCullModel ( ent - > origin , model ) )
return ;
# endif
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if ( model - > fromgame ! = fg_quake3 & & model - > fromgame ! = fg_doom3 & & lightmap )
{
int k ;
currententity = ent ;
currentmodel = ent - > model ;
if ( model - > nummodelsurfaces ! = 0 & & r_dynamic . ival > 0 )
{
for ( k = rtlights_first ; k < RTL_FIRST ; k + + )
{
if ( ! cl_dlights [ k ] . radius )
continue ;
if ( ! ( cl_dlights [ k ] . flags & LFLAG_LIGHTMAP ) )
continue ;
model - > funcs . MarkLights ( & cl_dlights [ k ] , 1 < < k , model - > rootnode ) ;
}
}
Surf_LightmapShift ( model ) ;
2017-02-19 00:15:42 +00:00
# ifdef HEXEN2
2016-07-12 00:40:13 +00:00
if ( ( ent - > drawflags & MLS_MASK ) = = MLS_ABSLIGHT )
{
//update lightmaps.
for ( s = model - > surfaces + model - > firstmodelsurface , i = 0 ; i < model - > nummodelsurfaces ; i + + , s + + )
Surf_RenderAmbientLightmaps ( s , ent - > abslight ) ;
}
else if ( ent - > drawflags & DRF_TRANSLUCENT )
{
//update lightmaps.
for ( s = model - > surfaces + model - > firstmodelsurface , i = 0 ; i < model - > nummodelsurfaces ; i + + , s + + )
Surf_RenderAmbientLightmaps ( s , 255 ) ;
}
else
2017-02-19 00:15:42 +00:00
# endif
2016-07-12 00:40:13 +00:00
{
//update lightmaps.
for ( s = model - > surfaces + model - > firstmodelsurface , i = 0 ; i < model - > nummodelsurfaces ; i + + , s + + )
Surf_RenderDynamicLightmaps ( s ) ;
}
currententity = NULL ;
}
2017-10-13 17:50:28 +00:00
# ifdef BEF_PUSHDEPTH
if ( r_pushdepth )
bef = BEF_PUSHDEPTH ;
else
bef = 0 ;
# else
bef = 0 ;
# endif
2016-07-12 00:40:13 +00:00
if ( ent - > flags & RF_ADDITIVE )
bef | = BEF_FORCEADDITIVE ;
2017-02-19 00:15:42 +00:00
# ifdef HEXEN2
2016-07-12 00:40:13 +00:00
else if ( ( ent - > drawflags & DRF_TRANSLUCENT ) & & r_wateralpha . value ! = 1 )
{
bef | = BEF_FORCETRANSPARENT ;
ent - > shaderRGBAf [ 3 ] = r_wateralpha . value ;
}
2017-02-19 00:15:42 +00:00
# endif
2016-07-12 00:40:13 +00:00
else if ( ( ent - > flags & RF_TRANSLUCENT ) & & cls . protocol ! = CP_QUAKE3 )
bef | = BEF_FORCETRANSPARENT ;
if ( ent - > flags & RF_NODEPTHTEST )
bef | = BEF_FORCENODEPTH ;
if ( ent - > flags & RF_NOSHADOW )
bef | = BEF_NOSHADOWS ;
for ( i = 0 ; i < SHADER_SORT_COUNT ; i + + )
for ( ob = model - > batches [ i ] ; ob ; ob = ob - > next )
{
b = BE_GetTempBatch ( ) ;
if ( ! b )
continue ;
* b = * ob ;
// if (b->texture)
// b->shader = R_TextureAnimation(ent->framestate.g[FS_REG].frame[0], b->texture)->shader;
b - > meshes = b - > maxmeshes ;
b - > ent = ent ;
b - > flags = bef ;
if ( b - > buildmeshes )
b - > buildmeshes ( b ) ;
if ( ! b - > shader )
b - > shader = R_TextureAnimation ( ent - > framestate . g [ FS_REG ] . frame [ 0 ] , b - > texture ) - > shader ;
if ( bef & BEF_FORCEADDITIVE )
{
b - > next = batches [ SHADER_SORT_ADDITIVE ] ;
batches [ SHADER_SORT_ADDITIVE ] = b ;
}
else if ( bef & BEF_FORCETRANSPARENT )
{
b - > next = batches [ SHADER_SORT_BLEND ] ;
batches [ SHADER_SORT_BLEND ] = b ;
}
else
{
b - > next = batches [ b - > shader - > sort ] ;
batches [ b - > shader - > sort ] = b ;
}
}
}
# ifdef THREADEDWORLD
struct webostate_s
{
char dbgid [ 12 ] ;
model_t * wmodel ;
2016-08-25 00:12:14 +00:00
int cluster [ 2 ] ;
2017-06-21 01:24:25 +00:00
pvsbuffer_t pvs ;
2016-07-12 00:40:13 +00:00
vboarray_t ebo ;
void * ebomem ;
size_t idxcount ;
int numbatches ;
int lightstylevalues [ MAX_LIGHTSTYLES ] ; //when using workers that only reprocessing lighting at 10fps, things get too ugly when things go out of sync
batch_t * rbatches [ SHADER_SORT_COUNT ] ;
struct wesbatch_s
{
size_t numidx ;
size_t maxidx ;
index_t * idxbuffer ;
batch_t b ;
mesh_t m ;
mesh_t * pm ;
vbo_t vbo ;
} batches [ 1 ] ;
} ;
static struct webostate_s * webostate ;
static struct webostate_s * webogenerating ;
static int webogeneratingstate ; //1 if generating, 0 if not, for waiting for sync.
static void R_DestroyWorldEBO ( struct webostate_s * es )
{
if ( ! es )
return ;
# ifdef GLQUAKE
if ( qrenderer = = QR_OPENGL )
qglDeleteBuffersARB ( 1 , & es - > ebo . gl . vbo ) ;
# endif
# ifdef VKQUAKE
if ( qrenderer = = QR_VULKAN )
BE_VBO_Destroy ( & es - > ebo , es - > ebomem ) ;
# endif
BZ_Free ( es ) ;
}
void R_GeneratedWorldEBO ( void * ctx , void * data , size_t a_ , size_t b_ )
{
size_t idxcount ;
unsigned int i ;
model_t * mod ;
batch_t * b , * batch ;
mesh_t * m ;
int sortid ;
R_DestroyWorldEBO ( webostate ) ;
webostate = ctx ;
webogenerating = NULL ;
webogeneratingstate = 0 ;
mod = webostate - > wmodel ;
for ( i = 0 , idxcount = 0 ; i < webostate - > numbatches ; i + + )
idxcount + = webostate - > batches [ i ] . numidx ;
# ifdef GLQUAKE
if ( qrenderer = = QR_OPENGL )
{
GL_DeselectVAO ( ) ;
webostate - > ebo . gl . addr = NULL ;
qglGenBuffersARB ( 1 , & webostate - > ebo . gl . vbo ) ;
GL_SelectEBO ( webostate - > ebo . gl . vbo ) ;
qglBufferDataARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , idxcount * sizeof ( index_t ) , NULL , GL_STATIC_DRAW_ARB ) ;
for ( i = 0 , idxcount = 0 ; i < webostate - > numbatches ; i + + )
{
qglBufferSubDataARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , idxcount * sizeof ( index_t ) , webostate - > batches [ i ] . numidx * sizeof ( index_t ) , webostate - > batches [ i ] . idxbuffer ) ;
BZ_Free ( webostate - > batches [ i ] . idxbuffer ) ;
webostate - > batches [ i ] . idxbuffer = ( index_t * ) NULL + idxcount ;
idxcount + = webostate - > batches [ i ] . numidx ;
}
}
# endif
# ifdef VKQUAKE
if ( qrenderer = = QR_VULKAN )
{ //this malloc is stupid.
//with vulkan we really should be doing this on the worker instead, at least the staging part.
index_t * indexes = malloc ( sizeof ( * indexes ) * idxcount ) ;
webostate - > ebo . vk . offs = 0 ;
for ( i = 0 , idxcount = 0 ; i < webostate - > numbatches ; i + + )
{
memcpy ( indexes + idxcount , webostate - > batches [ i ] . idxbuffer , webostate - > batches [ i ] . numidx * sizeof ( index_t ) ) ;
BZ_Free ( webostate - > batches [ i ] . idxbuffer ) ;
webostate - > batches [ i ] . idxbuffer = ( index_t * ) NULL + idxcount ;
idxcount + = webostate - > batches [ i ] . numidx ;
}
2016-08-25 00:12:14 +00:00
if ( idxcount )
BE_VBO_Finish ( NULL , indexes , sizeof ( * indexes ) * idxcount , & webostate - > ebo , NULL , & webostate - > ebomem ) ;
else
{
memset ( & webostate - > ebo , 0 , sizeof ( webostate - > ebo ) ) ;
webostate - > ebomem = NULL ;
}
2016-07-12 00:40:13 +00:00
free ( indexes ) ;
}
# endif
//should be doing this on the worker, but whatever
for ( i = 0 , sortid = 0 ; sortid < SHADER_SORT_COUNT ; sortid + + )
{
webostate - > rbatches [ sortid ] = NULL ;
for ( batch = mod - > batches [ sortid ] ; batch ! = NULL ; batch = batch - > next , i + + )
{
if ( ! webostate - > batches [ i ] . numidx )
continue ;
2016-08-25 00:12:14 +00:00
if ( batch - > shader - > flags & SHADER_NODRAW )
continue ;
2016-07-12 00:40:13 +00:00
m = & webostate - > batches [ i ] . m ;
webostate - > batches [ i ] . pm = m ;
b = & webostate - > batches [ i ] . b ;
memcpy ( b , batch , sizeof ( * b ) ) ;
memset ( m , 0 , sizeof ( * m ) ) ;
2016-08-25 00:12:14 +00:00
if ( b - > shader - > flags & SHADER_NEEDSARRAYS )
{
if ( b - > shader - > flags & SHADER_SKY )
continue ;
b - > shader = R_RegisterShader_Vertex ( " unsupported " ) ;
}
2016-07-12 00:40:13 +00:00
m - > numvertexes = webostate - > batches [ i ] . b . vbo - > vertcount ;
b - > mesh = & webostate - > batches [ i ] . pm ;
b - > meshes = 1 ;
m - > numindexes = webostate - > batches [ i ] . numidx ;
m - > vbofirstelement = webostate - > batches [ i ] . idxbuffer - ( index_t * ) NULL ;
m - > vbofirstvert = 0 ;
m - > indexes = NULL ;
b - > vbo = & webostate - > batches [ i ] . vbo ;
* b - > vbo = * batch - > vbo ;
b - > vbo - > indicies = webostate - > ebo ;
b - > vbo - > vao = 0 ;
b - > next = webostate - > rbatches [ sortid ] ;
webostate - > rbatches [ sortid ] = b ;
}
}
}
2017-02-19 00:15:42 +00:00
# ifdef Q1BSPS
2016-08-25 00:12:14 +00:00
static void Surf_SimpleWorld_Q1BSP ( struct webostate_s * es , qbyte * pvs )
2016-07-12 00:40:13 +00:00
{
mleaf_t * leaf ;
msurface_t * surf , * * mark , * * end ;
mesh_t * mesh ;
model_t * wmodel = es - > wmodel ;
2016-08-25 00:12:14 +00:00
int l = wmodel - > numclusters ;
int fc = - r_framecount ;
for ( leaf = wmodel - > leafs + l ; l - - > 0 ; leaf - - )
2016-07-12 00:40:13 +00:00
{
if ( ( pvs [ l > > 3 ] & ( 1u < < ( l & 7 ) ) ) & & leaf - > nummarksurfaces )
{
mark = leaf - > firstmarksurface ;
end = mark + leaf - > nummarksurfaces ;
while ( mark < end )
{
surf = * mark + + ;
if ( surf - > visframe ! = fc )
{
int i ;
struct wesbatch_s * eb ;
surf - > visframe = fc ;
Surf_RenderDynamicLightmaps_Worker ( wmodel , surf , es - > lightstylevalues ) ;
mesh = surf - > mesh ;
eb = & es - > batches [ surf - > sbatch - > ebobatch ] ;
if ( eb - > maxidx < eb - > numidx + mesh - > numindexes )
{
//FIXME: pre-allocate
eb - > maxidx = eb - > numidx + surf - > mesh - > numindexes + 512 ;
eb - > idxbuffer = BZ_Realloc ( eb - > idxbuffer , eb - > maxidx * sizeof ( index_t ) ) ;
}
for ( i = 0 ; i < mesh - > numindexes ; i + + )
eb - > idxbuffer [ eb - > numidx + i ] = mesh - > indexes [ i ] + mesh - > vbofirstvert ;
eb - > numidx + = mesh - > numindexes ;
}
}
}
}
}
2017-02-19 00:15:42 +00:00
# endif
# if defined(Q2BSPS) || defined(Q3BSPS)
2016-08-25 00:12:14 +00:00
static void Surf_SimpleWorld_Q3BSP ( struct webostate_s * es , qbyte * pvs )
{
mleaf_t * leaf ;
msurface_t * surf , * * mark , * * end ;
mesh_t * mesh ;
model_t * wmodel = es - > wmodel ;
int l = wmodel - > numleafs ; //is this doing submodels too?
int c ;
int fc = - r_framecount ;
for ( leaf = wmodel - > leafs ; l - - > 0 ; leaf + + )
{
c = leaf - > cluster ;
if ( c < 0 )
continue ; //o.O
if ( ( pvs [ c > > 3 ] & ( 1u < < ( c & 7 ) ) ) & & leaf - > nummarksurfaces )
{
mark = leaf - > firstmarksurface ;
end = mark + leaf - > nummarksurfaces ;
while ( mark < end )
{
surf = * mark + + ;
if ( surf - > visframe ! = fc )
{
int i ;
struct wesbatch_s * eb ;
surf - > visframe = fc ;
mesh = surf - > mesh ;
eb = & es - > batches [ surf - > sbatch - > ebobatch ] ;
if ( eb - > maxidx < eb - > numidx + mesh - > numindexes )
{
//FIXME: pre-allocate
eb - > maxidx = eb - > numidx + surf - > mesh - > numindexes + 512 ;
eb - > idxbuffer = BZ_Realloc ( eb - > idxbuffer , eb - > maxidx * sizeof ( index_t ) ) ;
}
for ( i = 0 ; i < mesh - > numindexes ; i + + )
eb - > idxbuffer [ eb - > numidx + i ] = mesh - > indexes [ i ] + mesh - > vbofirstvert ;
eb - > numidx + = mesh - > numindexes ;
}
}
}
}
}
# endif
2016-07-12 00:40:13 +00:00
void R_GenWorldEBO ( void * ctx , void * data , size_t a , size_t b )
{
int i ;
struct webostate_s * es = ctx ;
qbyte * pvs ;
es - > numbatches = es - > wmodel - > numbatches ;
for ( i = 0 ; i < es - > numbatches ; i + + )
{
es - > batches [ i ] . numidx = 0 ;
es - > batches [ i ] . maxidx = 0 ;
es - > batches [ i ] . idxbuffer = NULL ;
}
2017-07-28 01:49:25 +00:00
//maybe we should just use fatpvs instead, and wait for completion when outside?
if ( es - > cluster [ 1 ] ! = - 1 & & es - > cluster [ 0 ] ! = es - > cluster [ 1 ] )
{ //view is near to a water boundary. this implies the water crosses the near clip plane. we need both leafs.
pvs = es - > wmodel - > funcs . ClusterPVS ( es - > wmodel , es - > cluster [ 0 ] , & es - > pvs , PVM_REPLACE ) ;
pvs = es - > wmodel - > funcs . ClusterPVS ( es - > wmodel , es - > cluster [ 1 ] , & es - > pvs , PVM_MERGE ) ;
}
else
pvs = es - > wmodel - > funcs . ClusterPVS ( es - > wmodel , es - > cluster [ 0 ] , & es - > pvs , PVM_FAST ) ;
2017-02-19 00:15:42 +00:00
# if defined(Q2BSPS) || defined(Q3BSPS)
2016-08-25 00:12:14 +00:00
if ( es - > wmodel - > fromgame = = fg_quake2 | | es - > wmodel - > fromgame = = fg_quake3 )
Surf_SimpleWorld_Q3BSP ( es , pvs ) ;
else
# endif
2017-01-13 00:39:50 +00:00
# ifdef Q1BSPS
if ( es - > wmodel - > fromgame = = fg_quake | | es - > wmodel - > fromgame = = fg_halflife )
2016-08-25 00:12:14 +00:00
Surf_SimpleWorld_Q1BSP ( es , pvs ) ;
2017-01-13 00:39:50 +00:00
else
# endif
{
//panic
}
2016-07-12 00:40:13 +00:00
COM_AddWork ( WG_MAIN , R_GeneratedWorldEBO , es , NULL , 0 , 0 ) ;
}
# endif
/*
= = = = = = = = = = = = =
R_DrawWorld
= = = = = = = = = = = = =
*/
2017-11-30 17:59:11 +00:00
static pvsbuffer_t surf_frustumvis [ R_MAX_RECURSE ] ;
2016-07-12 00:40:13 +00:00
void Surf_DrawWorld ( void )
{
//surfvis vs entvis - the key difference is that surfvis is surfaces while entvis is volume. though surfvis should be frustum culled also for lighting. entvis doesn't care.
qbyte * surfvis , * entvis ;
RSpeedLocals ( ) ;
if ( r_refdef . flags & RDF_NOWORLDMODEL )
{
r_refdef . flags | = RDF_NOWORLDMODEL ;
2016-11-20 20:52:41 +00:00
r_refdef . scenevis = NULL ;
BE_DrawWorld ( NULL ) ;
2016-07-12 00:40:13 +00:00
return ;
}
if ( ! cl . worldmodel | | cl . worldmodel - > loadstate ! = MLS_LOADED )
{
/*Don't act as a wallhack*/
return ;
}
currentmodel = cl . worldmodel ;
currententity = & r_worldentity ;
{
RSpeedRemark ( ) ;
2017-01-13 00:39:50 +00:00
Surf_LightmapShift ( currentmodel ) ;
2016-07-12 00:40:13 +00:00
# ifdef THREADEDWORLD
2017-01-13 00:39:50 +00:00
if ( ( r_dynamic . ival < 0 | | currentmodel - > numbatches ) & & ! r_refdef . recurse & & currentmodel - > type = = mod_brush )
2016-07-12 00:40:13 +00:00
{
2017-01-13 00:39:50 +00:00
if ( webostate & & webostate - > wmodel ! = currentmodel )
2016-07-12 00:40:13 +00:00
{
R_DestroyWorldEBO ( webostate ) ;
webostate = NULL ;
}
2016-08-25 00:12:14 +00:00
if ( qrenderer ! = QR_OPENGL & & qrenderer ! = QR_VULKAN )
;
2017-01-13 00:39:50 +00:00
# ifdef Q1BSPS
else if ( currentmodel - > fromgame = = fg_quake | | currentmodel - > fromgame = = fg_halflife )
2016-08-25 00:12:14 +00:00
{
int i = MAX_LIGHTSTYLES ;
if ( webostate & & ! webogenerating )
for ( i = 0 ; i < MAX_LIGHTSTYLES ; i + + )
{
if ( webostate - > lightstylevalues [ i ] ! = d_lightstylevalue [ i ] )
break ;
}
2017-07-28 01:49:25 +00:00
if ( webostate & & webostate - > cluster [ 0 ] = = r_viewcluster & & webostate - > cluster [ 1 ] = = r_viewcluster2 & & i = = MAX_LIGHTSTYLES )
2016-07-12 00:40:13 +00:00
{
}
2016-08-25 00:12:14 +00:00
else
{
if ( ! webogenerating )
{
int i ;
2017-01-13 00:39:50 +00:00
if ( ! currentmodel - > numbatches )
2016-08-25 00:12:14 +00:00
{
int sortid ;
batch_t * batch ;
2017-01-13 00:39:50 +00:00
currentmodel - > numbatches = 0 ;
2016-08-25 00:12:14 +00:00
for ( sortid = 0 ; sortid < SHADER_SORT_COUNT ; sortid + + )
2017-01-13 00:39:50 +00:00
for ( batch = currentmodel - > batches [ sortid ] ; batch ! = NULL ; batch = batch - > next )
2016-08-25 00:12:14 +00:00
{
2017-01-13 00:39:50 +00:00
batch - > ebobatch = currentmodel - > numbatches ;
currentmodel - > numbatches + + ;
2016-08-25 00:12:14 +00:00
}
}
webogeneratingstate = true ;
2017-06-21 01:24:25 +00:00
webogenerating = BZ_Malloc ( sizeof ( * webogenerating ) + sizeof ( webogenerating - > batches [ 0 ] ) * ( currentmodel - > numbatches - 1 ) + currentmodel - > pvsbytes ) ;
2017-01-13 00:39:50 +00:00
webogenerating - > wmodel = currentmodel ;
2017-07-28 01:49:25 +00:00
webogenerating - > cluster [ 0 ] = r_viewcluster ;
webogenerating - > cluster [ 1 ] = r_viewcluster2 ;
2017-06-21 01:24:25 +00:00
webogenerating - > pvs . buffer = ( qbyte * ) ( webogenerating + 1 ) + sizeof ( webogenerating - > batches [ 0 ] ) * ( currentmodel - > numbatches - 1 ) ;
webogenerating - > pvs . buffersize = currentmodel - > pvsbytes ;
2016-08-25 00:12:14 +00:00
for ( i = 0 ; i < MAX_LIGHTSTYLES ; i + + )
webogenerating - > lightstylevalues [ i ] = d_lightstylevalue [ i ] ;
Q_strncpyz ( webogenerating - > dbgid , " webostate " , sizeof ( webogenerating - > dbgid ) ) ;
COM_AddWork ( WG_LOADER , R_GenWorldEBO , webogenerating , NULL , 0 , 0 ) ;
}
}
2016-07-12 00:40:13 +00:00
}
2017-01-13 00:39:50 +00:00
# endif
# ifdef Q3BSPS
else if ( currentmodel - > fromgame = = fg_quake3 )
2016-07-12 00:40:13 +00:00
{
2016-08-25 00:12:14 +00:00
if ( webostate & & webostate - > cluster [ 0 ] = = r_viewcluster & & webostate - > cluster [ 1 ] = = r_viewcluster2 )
2016-07-12 00:40:13 +00:00
{
2016-08-25 00:12:14 +00:00
}
else
{
if ( ! webogenerating )
2016-07-12 00:40:13 +00:00
{
2017-01-13 00:39:50 +00:00
if ( ! currentmodel - > numbatches )
2016-08-25 00:12:14 +00:00
{
int sortid ;
batch_t * batch ;
2017-01-13 00:39:50 +00:00
currentmodel - > numbatches = 0 ;
2016-08-25 00:12:14 +00:00
for ( sortid = 0 ; sortid < SHADER_SORT_COUNT ; sortid + + )
2017-01-13 00:39:50 +00:00
for ( batch = currentmodel - > batches [ sortid ] ; batch ! = NULL ; batch = batch - > next )
2016-08-25 00:12:14 +00:00
{
2017-01-13 00:39:50 +00:00
batch - > ebobatch = currentmodel - > numbatches ;
currentmodel - > numbatches + + ;
2016-08-25 00:12:14 +00:00
}
}
webogeneratingstate = true ;
2017-06-21 01:24:25 +00:00
webogenerating = BZ_Malloc ( sizeof ( * webogenerating ) + sizeof ( webogenerating - > batches [ 0 ] ) * ( currentmodel - > numbatches - 1 ) + currentmodel - > pvsbytes ) ;
2017-01-13 00:39:50 +00:00
webogenerating - > wmodel = currentmodel ;
2016-08-25 00:12:14 +00:00
webogenerating - > cluster [ 0 ] = r_viewcluster ;
webogenerating - > cluster [ 1 ] = r_viewcluster2 ;
2017-06-21 01:24:25 +00:00
webogenerating - > pvs . buffer = ( qbyte * ) ( webogenerating + 1 ) + sizeof ( webogenerating - > batches [ 0 ] ) * ( currentmodel - > numbatches - 1 ) ;
webogenerating - > pvs . buffersize = currentmodel - > pvsbytes ;
2016-08-25 00:12:14 +00:00
Q_strncpyz ( webogenerating - > dbgid , " webostate " , sizeof ( webogenerating - > dbgid ) ) ;
COM_AddWork ( WG_LOADER , R_GenWorldEBO , webogenerating , NULL , 0 , 0 ) ;
2016-07-12 00:40:13 +00:00
}
}
}
2017-01-13 00:39:50 +00:00
# endif
2016-08-25 00:12:14 +00:00
2016-07-12 00:40:13 +00:00
if ( webostate )
{
2017-06-21 01:24:25 +00:00
entvis = surfvis = webostate - > pvs . buffer ;
2016-07-12 00:40:13 +00:00
RSpeedEnd ( RSPEED_WORLDNODE ) ;
CL_LinkStaticEntities ( entvis ) ;
TRACE ( ( " dbg: calling R_DrawParticles \n " ) ) ;
if ( ! r_refdef . recurse )
P_DrawParticles ( ) ;
TRACE ( ( " dbg: calling BE_DrawWorld \n " ) ) ;
2016-11-20 20:52:41 +00:00
r_refdef . scenevis = surfvis ;
BE_DrawWorld ( webostate - > rbatches ) ;
2016-07-12 00:40:13 +00:00
/*FIXME: move this away*/
2017-01-13 00:39:50 +00:00
if ( currentmodel - > fromgame = = fg_quake | | currentmodel - > fromgame = = fg_halflife )
2016-07-12 00:40:13 +00:00
Surf_LessenStains ( ) ;
return ;
}
}
# endif
2017-01-13 00:39:50 +00:00
Surf_PushChains ( currentmodel - > batches ) ;
2016-07-12 00:40:13 +00:00
2017-01-13 00:39:50 +00:00
# ifdef TERRAIN
if ( currentmodel - > type = = mod_heightmap )
{
frustumvis = NULL ;
entvis = surfvis = NULL ;
}
else
# endif
2017-02-19 00:15:42 +00:00
# if defined(Q2BSPS) || defined(Q3BSPS)
2017-01-13 00:39:50 +00:00
if ( currentmodel - > fromgame = = fg_quake2 | | currentmodel - > fromgame = = fg_quake3 )
2016-07-12 00:40:13 +00:00
{
2017-11-30 17:59:11 +00:00
pvsbuffer_t * vis = & surf_frustumvis [ r_refdef . recurse ] ;
if ( vis - > buffersize < currentmodel - > pvsbytes )
vis - > buffer = BZ_Realloc ( vis - > buffer , vis - > buffersize = currentmodel - > pvsbytes ) ;
frustumvis = vis - > buffer ;
2017-06-21 01:24:25 +00:00
memset ( frustumvis , 0 , currentmodel - > pvsbytes ) ;
2016-07-12 00:40:13 +00:00
if ( ! r_refdef . areabitsknown )
{ //generate the info each frame, as the gamecode didn't tell us what to use.
2017-01-13 00:39:50 +00:00
int leafnum = CM_PointLeafnum ( currentmodel , r_refdef . vieworg ) ;
int clientarea = CM_LeafArea ( currentmodel , leafnum ) ;
CM_WriteAreaBits ( currentmodel , r_refdef . areabits , clientarea , false ) ;
2016-07-12 00:40:13 +00:00
r_refdef . areabitsknown = true ;
}
# ifdef Q3BSPS
2017-01-13 00:39:50 +00:00
if ( currentmodel - > fromgame = = fg_quake3 )
2016-07-12 00:40:13 +00:00
{
entvis = surfvis = R_MarkLeaves_Q3 ( ) ;
2017-01-13 00:39:50 +00:00
Surf_RecursiveQ3WorldNode ( currentmodel - > nodes , ( 1 < < r_refdef . frustum_numworldplanes ) - 1 ) ;
2016-07-12 00:40:13 +00:00
//Surf_LeafWorldNode ();
}
else
# endif
2017-02-19 00:15:42 +00:00
# ifdef Q2BSPS
if ( currentmodel - > fromgame = = fg_quake2 )
2016-07-12 00:40:13 +00:00
{
entvis = surfvis = R_MarkLeaves_Q2 ( ) ;
VectorCopy ( r_refdef . vieworg , modelorg ) ;
2017-01-13 00:39:50 +00:00
Surf_RecursiveQ2WorldNode ( currentmodel - > nodes ) ;
2016-07-12 00:40:13 +00:00
}
2017-02-19 00:15:42 +00:00
else
# endif
{
entvis = surfvis = NULL ;
}
2016-07-12 00:40:13 +00:00
surfvis = frustumvis ;
}
else
# endif
# ifdef MAP_PROC
2017-01-13 00:39:50 +00:00
if ( currentmodel - > fromgame = = fg_doom3 )
2016-07-12 00:40:13 +00:00
{
2017-01-13 00:39:50 +00:00
entvis = surfvis = D3_CalcVis ( currentmodel , r_origin ) ;
2016-07-12 00:40:13 +00:00
}
else
# endif
# ifdef MAP_DOOM
if ( currentmodel - > fromgame = = fg_doom )
{
entvis = surfvis = NULL ;
R_DoomWorld ( ) ;
}
else
# endif
2017-01-13 00:39:50 +00:00
# ifdef Q1BSPS
if ( 1 )
2016-07-12 00:40:13 +00:00
{
//extern cvar_t temp1;
// if (0)//temp1.value)
// entvis = surfvis = R_MarkLeafSurfaces_Q1();
// else
{
2017-11-30 17:59:11 +00:00
pvsbuffer_t * vis = & surf_frustumvis [ r_refdef . recurse ] ;
2016-07-12 00:40:13 +00:00
entvis = R_MarkLeaves_Q1 ( false ) ;
if ( ! ( r_novis . ival & 2 ) )
VectorCopy ( r_origin , modelorg ) ;
2017-11-30 17:59:11 +00:00
if ( vis - > buffersize < currentmodel - > pvsbytes )
vis - > buffer = BZ_Realloc ( vis - > buffer , vis - > buffersize = currentmodel - > pvsbytes ) ;
frustumvis = vis - > buffer ;
2017-06-21 01:24:25 +00:00
memset ( frustumvis , 0 , currentmodel - > pvsbytes ) ;
2016-07-12 00:40:13 +00:00
if ( r_refdef . useperspective )
2017-01-13 00:39:50 +00:00
Surf_RecursiveWorldNode ( currentmodel - > nodes , 0x1f ) ;
2016-07-12 00:40:13 +00:00
else
2017-01-13 00:39:50 +00:00
Surf_OrthoRecursiveWorldNode ( currentmodel - > nodes , 0x1f ) ;
2016-07-12 00:40:13 +00:00
surfvis = frustumvis ;
}
}
2017-01-13 00:39:50 +00:00
else
# endif
{
frustumvis = NULL ;
entvis = surfvis = NULL ;
}
2016-07-12 00:40:13 +00:00
RSpeedEnd ( RSPEED_WORLDNODE ) ;
if ( ! ( r_refdef . flags & RDF_NOWORLDMODEL ) )
{
CL_LinkStaticEntities ( entvis ) ;
TRACE ( ( " dbg: calling R_DrawParticles \n " ) ) ;
if ( ! r_refdef . recurse )
P_DrawParticles ( ) ;
}
TRACE ( ( " dbg: calling BE_DrawWorld \n " ) ) ;
2016-11-20 20:52:41 +00:00
r_refdef . scenevis = surfvis ;
BE_DrawWorld ( cl . worldmodel - > batches ) ;
2016-07-12 00:40:13 +00:00
Surf_PopChains ( cl . worldmodel - > batches ) ;
/*FIXME: move this away*/
if ( cl . worldmodel - > fromgame = = fg_quake | | cl . worldmodel - > fromgame = = fg_halflife )
Surf_LessenStains ( ) ;
}
}
unsigned int Surf_CalcMemSize ( msurface_t * surf )
{
if ( surf - > mesh )
return 0 ;
if ( ! surf - > numedges )
return 0 ;
//figure out how much space this surface needs
return sizeof ( mesh_t ) +
sizeof ( index_t ) * ( surf - > numedges - 2 ) * 3 +
( sizeof ( vecV_t ) + sizeof ( vec2_t ) * 2 + sizeof ( vec3_t ) * 3 + sizeof ( vec4_t ) ) * surf - > numedges ;
}
void Surf_DeInit ( void )
{
int i ;
# ifdef THREADEDWORLD
while ( webogenerating )
COM_WorkerPartialSync ( webogenerating , & webogeneratingstate , true ) ;
R_DestroyWorldEBO ( webostate ) ;
webostate = NULL ;
# endif
for ( i = 0 ; i < numlightmaps ; i + + )
{
if ( ! lightmap [ i ] )
continue ;
if ( ! lightmap [ i ] - > external )
Image_DestroyTexture ( lightmap [ i ] - > lightmap_texture ) ;
BZ_Free ( lightmap [ i ] ) ;
lightmap [ i ] = NULL ;
}
if ( lightmap )
BZ_Free ( lightmap ) ;
2017-11-30 17:59:11 +00:00
for ( i = 0 ; i < R_MAX_RECURSE ; i + + )
Z_Free ( surf_frustumvis [ i ] . buffer ) ;
memset ( surf_frustumvis , 0 , sizeof ( surf_frustumvis ) ) ;
2017-07-28 01:49:25 +00:00
2016-07-12 00:40:13 +00:00
lightmap = NULL ;
numlightmaps = 0 ;
Alias_Shutdown ( ) ;
Shader_ResetRemaps ( ) ;
}
void Surf_Clear ( model_t * mod )
{
int i ;
vbo_t * vbo ;
// if (mod->fromgame == fg_doom3)
// return;/*they're on the hunk*/
# ifdef THREADEDWORLD
while ( webogenerating )
COM_WorkerPartialSync ( webogenerating , & webogeneratingstate , true ) ;
if ( webostate & & webostate - > wmodel = = mod )
{
R_DestroyWorldEBO ( webostate ) ;
webostate = NULL ;
}
# endif
while ( mod - > vbos )
{
vbo = mod - > vbos ;
mod - > vbos = vbo - > next ;
2017-11-30 17:59:11 +00:00
BE_ClearVBO ( vbo , false ) ;
2016-07-12 00:40:13 +00:00
}
if ( ! mod - > submodelof )
{
for ( i = 0 ; i < mod - > numtextures ; i + + )
{
R_UnloadShader ( mod - > textures [ i ] - > shader ) ;
mod - > textures [ i ] - > shader = NULL ;
}
}
mod - > numtextures = 0 ;
BZ_Free ( mod - > shadowbatches ) ;
mod - > numshadowbatches = 0 ;
mod - > shadowbatches = NULL ;
# ifdef RTLIGHTS
Sh_PurgeShadowMeshes ( ) ;
# endif
BZ_Free ( blocklights ) ;
BZ_Free ( blocknormals ) ;
blocklights = NULL ;
blocknormals = NULL ;
maxblocksize = 0 ;
}
2018-03-04 14:41:16 +00:00
uploadfmt_t Surf_NameToFormat ( const char * nam )
{
static uploadfmt_t tab [ ] = { PTI_L8 , PTI_RGB8 , PTI_BGRA8 , PTI_A2BGR10 , PTI_E5BGR9 , PTI_RGBA16F , PTI_RGBA32F , PTI_RGB565 , PTI_RGBA4444 , PTI_RGBA5551 } ;
int idx = atoi ( nam ) - 1 ;
if ( idx > = 0 & & idx < countof ( tab ) )
return tab [ idx ] ;
if ( ! Q_strcasecmp ( nam , " e5bgr9 " ) | | ! Q_strcasecmp ( nam , " rgb9e5 " ) )
return PTI_E5BGR9 ;
if ( ! Q_strcasecmp ( nam , " a2bgr10 " ) | | ! Q_strcasecmp ( nam , " rgb10a2 " ) | | ! Q_strcasecmp ( nam , " rgb10 " ) )
return PTI_A2BGR10 ;
if ( ! Q_strcasecmp ( nam , " rgba32f " ) )
return PTI_RGBA32F ;
if ( ! Q_strcasecmp ( nam , " rgba16f " ) )
return PTI_RGBA16F ;
// if (!Q_strcasecmp(nam, "rgba8s"))
// return PTI_RGBA8_SIGNED;
if ( ! Q_strcasecmp ( nam , " rgb565 " ) | | ! Q_strcasecmp ( nam , " rgb5 " ) )
return PTI_RGB565 ;
if ( ! Q_strcasecmp ( nam , " rgba4444 " ) | | ! Q_strcasecmp ( nam , " rgba4 " ) )
return PTI_RGBA4444 ;
if ( ! Q_strcasecmp ( nam , " rgba5551 " ) | | ! Q_strcasecmp ( nam , " rgba51 " ) )
return PTI_RGBA5551 ;
if ( ! Q_strcasecmp ( nam , " argb4444 " ) )
return PTI_ARGB4444 ;
if ( ! Q_strcasecmp ( nam , " argb1555 " ) )
return PTI_ARGB1555 ;
if ( ! Q_strcasecmp ( nam , " rgbx8 " ) | | ! Q_strcasecmp ( nam , " bgrx8 " ) | | ! Q_strcasecmp ( nam , " rgba8 " ) | | ! Q_strcasecmp ( nam , " bgra8 " ) )
return PTI_BGRX8 ;
if ( ! Q_strcasecmp ( nam , " rgb8 " ) | | ! Q_strcasecmp ( nam , " bgr8 " ) )
return PTI_RGB8 ;
if ( ! Q_strcasecmp ( nam , " l8 " ) )
return PTI_L8 ;
if ( * nam )
Con_Printf ( " Unknown lightmap format: %s \n " , nam ) ;
return TF_INVALID ;
}
2016-07-12 00:40:13 +00:00
//pick fastest mode for lightmap data
void Surf_LightmapMode ( void )
{
2018-03-04 14:41:16 +00:00
lightmap_fmt = Surf_NameToFormat ( r_lightmap_format . string ) ;
if ( ! sh_config . texfmt [ lightmap_fmt ] )
2016-07-12 00:40:13 +00:00
{
2018-03-04 14:41:16 +00:00
qboolean hdr = ( vid . flags & VID_SRGBAWARE ) , rgb = false ;
if ( lightmap_fmt ! = TF_INVALID )
Con_Printf ( " lightmap format %s not supported by renderer \n " , r_lightmap_format . string ) ;
if ( cl . worldmodel )
{
switch ( cl . worldmodel - > lightmaps . fmt )
{
case LM_E5BGR9 :
hdr = rgb = true ;
break ;
case LM_RGB8 :
rgb = true ;
break ;
case LM_L8 :
break ;
}
if ( cl . worldmodel - > deluxdata )
rgb = true ;
}
if ( sh_config . texfmt [ PTI_E5BGR9 ] & & hdr )
lightmap_fmt = PTI_E5BGR9 ;
else if ( sh_config . texfmt [ PTI_RGBA16F ] & & hdr )
lightmap_fmt = PTI_RGBA16F ;
else if ( sh_config . texfmt [ PTI_RGBA32F ] & & hdr )
lightmap_fmt = PTI_RGBA32F ;
else if ( sh_config . texfmt [ PTI_A2BGR10 ] & & rgb )
lightmap_fmt = PTI_A2BGR10 ;
else if ( sh_config . texfmt [ PTI_L8 ] & & ! rgb )
lightmap_fmt = PTI_L8 ;
else if ( sh_config . texfmt [ PTI_BGRX8 ] )
lightmap_fmt = PTI_BGRX8 ;
else if ( sh_config . texfmt [ PTI_RGB8 ] )
lightmap_fmt = PTI_RGB8 ;
2016-07-12 00:40:13 +00:00
else
2018-03-04 14:41:16 +00:00
lightmap_fmt = PTI_RGBX8 ;
2016-07-12 00:40:13 +00:00
}
2017-05-28 15:42:32 +00:00
2018-03-04 14:41:16 +00:00
Con_DPrintf ( " Using lightmap format %s \n " , Image_FormatName ( lightmap_fmt ) ) ;
2017-05-28 15:42:32 +00:00
switch ( lightmap_fmt )
{
2018-03-04 14:41:16 +00:00
case PTI_RGBA32F :
lightmap_bytes = 4 * sizeof ( float ) ;
break ;
case PTI_RGBA16F :
lightmap_bytes = 4 * sizeof ( short ) ;
break ;
2017-05-28 15:42:32 +00:00
default :
2018-03-04 14:41:16 +00:00
case PTI_A2BGR10 :
case PTI_E5BGR9 :
case PTI_RGBA8 :
case PTI_RGBX8 :
case PTI_BGRA8 :
case PTI_BGRX8 :
lightmap_bytes = 4 * sizeof ( qbyte ) ;
2017-05-28 15:42:32 +00:00
break ;
2018-03-04 14:41:16 +00:00
case PTI_RGB8 :
case PTI_BGR8 :
lightmap_bytes = 3 * sizeof ( qbyte ) ;
2017-05-28 15:42:32 +00:00
break ;
2018-03-04 14:41:16 +00:00
case PTI_RGB565 :
case PTI_RGBA4444 :
case PTI_RGBA5551 :
case PTI_ARGB4444 :
case PTI_ARGB1555 :
lightmap_bytes = sizeof ( short ) ;
break ;
case PTI_L8 :
lightmap_bytes = 1 * sizeof ( qbyte ) ;
2017-05-28 15:42:32 +00:00
break ;
}
2016-07-12 00:40:13 +00:00
}
//needs to be followed by a BE_UploadAllLightmaps at some point
int Surf_NewLightmaps ( int count , int width , int height , qboolean deluxe )
{
int first = numlightmaps ;
int i ;
if ( ! count )
return - 1 ;
if ( deluxe & & ( count & 1 ) )
{
deluxe = false ;
Con_Print ( " WARNING: Deluxemapping with odd number of lightmaps \n " ) ;
}
2017-05-28 15:42:32 +00:00
Sys_LockMutex ( com_resourcemutex ) ;
2016-07-12 00:40:13 +00:00
i = numlightmaps + count ;
lightmap = BZ_Realloc ( lightmap , sizeof ( * lightmap ) * ( i ) ) ;
while ( i > first )
{
i - - ;
if ( deluxe & & ( ( i - numlightmaps ) & 1 ) )
{
2018-03-04 14:41:16 +00:00
lightmap [ i ] = Z_Malloc ( sizeof ( * lightmap [ i ] ) + ( sizeof ( qbyte ) * lightmap_bytes ) * width * height ) ;
2016-07-12 00:40:13 +00:00
lightmap [ i ] - > width = width ;
lightmap [ i ] - > height = height ;
lightmap [ i ] - > lightmaps = ( qbyte * ) ( lightmap [ i ] + 1 ) ;
lightmap [ i ] - > stainmaps = NULL ;
lightmap [ i ] - > hasdeluxe = false ;
}
else
{
2018-03-04 14:41:16 +00:00
lightmap [ i ] = Z_Malloc ( sizeof ( * lightmap [ i ] ) + ( sizeof ( qbyte ) * lightmap_bytes + sizeof ( stmap ) * 3 ) * width * height ) ;
2016-07-12 00:40:13 +00:00
lightmap [ i ] - > width = width ;
lightmap [ i ] - > height = height ;
lightmap [ i ] - > lightmaps = ( qbyte * ) ( lightmap [ i ] + 1 ) ;
2018-03-04 14:41:16 +00:00
lightmap [ i ] - > stainmaps = ( stmap * ) ( lightmap [ i ] - > lightmaps + lightmap_bytes * width * height ) ;
2016-07-12 00:40:13 +00:00
lightmap [ i ] - > hasdeluxe = deluxe ;
}
lightmap [ i ] - > rectchange . l = 0 ;
lightmap [ i ] - > rectchange . t = 0 ;
lightmap [ i ] - > rectchange . b = lightmap [ i ] - > height ;
lightmap [ i ] - > rectchange . r = lightmap [ i ] - > width ;
lightmap [ i ] - > lightmap_texture = r_nulltex ;
lightmap [ i ] - > modified = true ;
// lightmap[i]->shader = NULL;
lightmap [ i ] - > external = false ;
// reset stainmap since it now starts at 255
if ( lightmap [ i ] - > stainmaps )
memset ( lightmap [ i ] - > stainmaps , 255 , width * height * 3 * sizeof ( stmap ) ) ;
}
numlightmaps + = count ;
2017-05-28 15:42:32 +00:00
Sys_UnlockMutex ( com_resourcemutex ) ;
2016-07-12 00:40:13 +00:00
return first ;
}
int Surf_NewExternalLightmaps ( int count , char * filepattern , qboolean deluxe )
{
int first = numlightmaps ;
int i ;
char nname [ MAX_QPATH ] ;
qboolean odd = ( count & 1 ) & & deluxe ;
if ( ! count )
return - 1 ;
if ( odd )
count + + ;
i = numlightmaps + count ;
lightmap = BZ_Realloc ( lightmap , sizeof ( * lightmap ) * ( i ) ) ;
while ( i > first )
{
i - - ;
lightmap [ i ] = Z_Malloc ( sizeof ( * lightmap [ i ] ) ) ;
lightmap [ i ] - > width = 0 ;
lightmap [ i ] - > height = 0 ;
lightmap [ i ] - > lightmaps = NULL ;
lightmap [ i ] - > stainmaps = NULL ;
lightmap [ i ] - > modified = false ;
lightmap [ i ] - > external = true ;
2017-08-29 02:29:06 +00:00
lightmap [ i ] - > hasdeluxe = ( deluxe & & ! ( ( i - numlightmaps ) & 1 ) ) ;
2016-07-12 00:40:13 +00:00
Q_snprintfz ( nname , sizeof ( nname ) , filepattern , i - numlightmaps ) ;
2018-03-04 14:41:16 +00:00
TEXASSIGN ( lightmap [ i ] - > lightmap_texture , R_LoadHiResTexture ( nname , NULL , ( r_lightmap_nearest . ival ? IF_NEAREST : IF_LINEAR ) | IF_NOMIPMAP ) ) ;
2016-07-12 00:40:13 +00:00
if ( lightmap [ i ] - > lightmap_texture - > status = = TEX_LOADING )
COM_WorkerPartialSync ( lightmap [ i ] - > lightmap_texture , & lightmap [ i ] - > lightmap_texture - > status , TEX_LOADING ) ;
lightmap [ i ] - > width = lightmap [ i ] - > lightmap_texture - > width ;
lightmap [ i ] - > height = lightmap [ i ] - > lightmap_texture - > height ;
}
if ( odd )
{
i = numlightmaps + count - 1 ;
if ( ! TEXVALID ( lightmap [ i ] - > lightmap_texture ) )
{ //FIXME: no deluxemaps after all...
Z_Free ( lightmap [ i ] ) ;
lightmap [ i ] = NULL ;
count - - ;
}
}
numlightmaps + = count ;
return first ;
}
void Surf_BuildModelLightmaps ( model_t * m )
{
2016-10-22 07:06:51 +00:00
int i ;
2016-07-12 00:40:13 +00:00
int shift ;
msurface_t * surf ;
batch_t * batch ;
int sortid ;
int newfirst ;
if ( m - > loadstate ! = MLS_LOADED )
return ;
if ( ! lightmap_bytes )
return ;
# ifdef TERRAIN
//easiest way to deal with heightmap lightmaps is to just purge the entire thing.
if ( m - > terrain )
Terr_PurgeTerrainModel ( m , false , false ) ; //FIXME: cop out. middle arg should be 'true'.
# endif
if ( m - > type ! = mod_brush )
return ;
if ( ! m - > lightmaps . count )
return ;
currentmodel = m ;
shift = Surf_LightmapShift ( currentmodel ) ;
if ( m - > submodelof & & m - > fromgame = = fg_quake3 ) //FIXME: should be all bsp formats
{
if ( m - > submodelof - > loadstate ! = MLS_LOADED )
return ;
2018-01-22 19:18:04 +00:00
newfirst = m - > submodelof - > lightmaps . first ;
2016-07-12 00:40:13 +00:00
}
else
{
if ( ! m - > lightdata & & m - > lightmaps . count & & m - > fromgame = = fg_quake3 )
{
char pattern [ MAX_QPATH ] ;
COM_StripAllExtensions ( m - > name , pattern , sizeof ( pattern ) ) ;
Q_strncatz ( pattern , " /lm_%04u.tga " , sizeof ( pattern ) ) ;
newfirst = Surf_NewExternalLightmaps ( m - > lightmaps . count , pattern , m - > lightmaps . deluxemapping ) ;
m - > lightmaps . count = numlightmaps - newfirst ;
}
else
newfirst = Surf_NewLightmaps ( m - > lightmaps . count , m - > lightmaps . width , m - > lightmaps . height , m - > lightmaps . deluxemapping ) ;
}
//fixup batch lightmaps
for ( sortid = 0 ; sortid < SHADER_SORT_COUNT ; sortid + + )
for ( batch = m - > batches [ sortid ] ; batch ! = NULL ; batch = batch - > next )
{
for ( i = 0 ; i < MAXRLIGHTMAPS ; i + + )
{
if ( batch - > lightmap [ i ] < 0 )
continue ;
batch - > lightmap [ i ] = batch - > lightmap [ i ] - m - > lightmaps . first + newfirst ;
}
}
if ( m - > fromgame = = fg_quake3 )
{
int j ;
2017-10-31 22:52:58 +00:00
unsigned char * src , * stop ;
2016-07-12 00:40:13 +00:00
unsigned char * dst ;
2017-07-12 08:15:27 +00:00
//fixup surface lightmaps, and paint
for ( i = 0 ; i < m - > nummodelsurfaces ; i + + )
{
surf = m - > surfaces + i + m - > firstmodelsurface ;
for ( j = 0 ; j < MAXRLIGHTMAPS ; j + + )
{
if ( surf - > lightmaptexturenums [ j ] < m - > lightmaps . first )
{
surf - > lightmaptexturenums [ j ] = - 1 ;
continue ;
}
if ( surf - > lightmaptexturenums [ j ] > = m - > lightmaps . first + m - > lightmaps . count )
{
surf - > lightmaptexturenums [ j ] = - 1 ;
continue ;
}
surf - > lightmaptexturenums [ j ] = surf - > lightmaptexturenums [ 0 ] - m - > lightmaps . first + newfirst ;
}
}
2016-07-12 00:40:13 +00:00
if ( ! m - > submodelof )
for ( i = 0 ; i < m - > lightmaps . count ; i + + )
{
if ( lightmap [ newfirst + i ] - > external )
continue ;
dst = lightmap [ newfirst + i ] - > lightmaps ;
src = m - > lightdata + i * m - > lightmaps . width * m - > lightmaps . height * 3 ;
2017-10-31 22:52:58 +00:00
stop = m - > lightdata + ( i + 1 ) * m - > lightmaps . width * m - > lightmaps . height * 3 ;
if ( stop - m - > lightdata > m - > lightdatasize )
stop = m - > lightdata + m - > lightdatasize ;
2016-07-12 00:40:13 +00:00
if ( m - > lightdata )
{
2017-05-28 15:42:32 +00:00
switch ( lightmap_fmt )
2016-07-12 00:40:13 +00:00
{
2017-05-28 15:42:32 +00:00
default :
Sys_Error ( " Bad lightmap_fmt \n " ) ;
break ;
2018-03-04 14:41:16 +00:00
case PTI_A2BGR10 :
for ( ; src < stop ; dst + = 4 , src + = 3 )
* ( unsigned int * ) dst = ( 0x3 < < 30 ) | ( src [ 2 ] < < 22 ) | ( src [ 1 ] < < 12 ) | ( src [ 0 ] < < 2 ) ;
break ;
case PTI_E5BGR9 :
for ( ; src < stop ; dst + = 4 , src + = 3 )
* ( unsigned int * ) dst = Surf_PackE5BRG9 ( src [ 0 ] , src [ 1 ] , src [ 2 ] , 8 ) ;
break ;
case PTI_BGRA8 :
case PTI_BGRX8 :
2017-10-31 22:52:58 +00:00
for ( ; src < stop ; dst + = 4 , src + = 3 )
2016-07-12 00:40:13 +00:00
{
dst [ 0 ] = src [ 2 ] ;
dst [ 1 ] = src [ 1 ] ;
dst [ 2 ] = src [ 0 ] ;
dst [ 3 ] = 255 ;
}
2017-05-28 15:42:32 +00:00
break ;
/*case TF_RGBA32:
2017-10-31 22:52:58 +00:00
for ( ; src < stop ; dst + = 4 , src + = 3 )
2016-07-12 00:40:13 +00:00
{
dst [ 0 ] = src [ 0 ] ;
dst [ 1 ] = src [ 1 ] ;
dst [ 2 ] = src [ 2 ] ;
dst [ 3 ] = 255 ;
}
2017-05-28 15:42:32 +00:00
break ;
case TF_BGR24 :
2017-10-31 22:52:58 +00:00
for ( ; src < stop ; dst + = 3 , src + = 3 )
2016-07-12 00:40:13 +00:00
{
dst [ 0 ] = src [ 2 ] ;
dst [ 1 ] = src [ 1 ] ;
dst [ 2 ] = src [ 0 ] ;
}
2017-05-28 15:42:32 +00:00
break ; */
case TF_RGB24 :
2017-10-31 22:52:58 +00:00
for ( ; src < stop ; dst + = 3 , src + = 3 )
2016-07-12 00:40:13 +00:00
{
dst [ 0 ] = src [ 0 ] ;
dst [ 1 ] = src [ 1 ] ;
dst [ 2 ] = src [ 2 ] ;
}
2017-05-28 15:42:32 +00:00
break ;
2018-03-04 14:41:16 +00:00
case PTI_L8 :
for ( ; src < stop ; dst + = 1 , src + = 3 )
{
dst [ 0 ] = max ( max ( src [ 0 ] , src [ 1 ] ) , src [ 2 ] ) ;
}
break ;
2016-07-12 00:40:13 +00:00
}
}
}
}
else
{
int j ;
lightmapinfo_t * lm , * dlm ;
qbyte * deluxemap ;
// if (*m->name == '*')
// {
// if (!cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED)
// return;
// }
//fixup surface lightmaps, and paint
for ( i = 0 ; i < m - > nummodelsurfaces ; i + + )
{
surf = m - > surfaces + i + m - > firstmodelsurface ;
for ( j = 0 ; j < MAXRLIGHTMAPS ; j + + )
{
if ( surf - > lightmaptexturenums [ j ] < m - > lightmaps . first )
{
surf - > lightmaptexturenums [ j ] = - 1 ;
continue ;
}
if ( surf - > lightmaptexturenums [ j ] > = m - > lightmaps . first + m - > lightmaps . count )
{
surf - > lightmaptexturenums [ j ] = - 1 ;
continue ;
}
surf - > lightmaptexturenums [ j ] = surf - > lightmaptexturenums [ 0 ] - m - > lightmaps . first + newfirst ;
lm = lightmap [ surf - > lightmaptexturenums [ j ] ] ;
if ( lm - > hasdeluxe )
{
dlm = lightmap [ surf - > lightmaptexturenums [ j ] + 1 ] ;
deluxemap = dlm - > lightmaps + ( surf - > light_t [ j ] * dlm - > width + surf - > light_s [ j ] ) * lightmap_bytes ;
}
else
deluxemap = NULL ;
2018-03-04 14:41:16 +00:00
Surf_BuildLightMap ( currentmodel , surf ,
2016-07-12 00:40:13 +00:00
lm - > lightmaps + ( surf - > light_t [ j ] * lm - > width + surf - > light_s [ j ] ) * lightmap_bytes ,
deluxemap ,
lm - > stainmaps + ( surf - > light_t [ j ] * lm - > width + surf - > light_s [ j ] ) * 3 ,
2018-03-04 14:41:16 +00:00
shift , r_ambient . value * 255 , lm - > width , d_lightstylevalue ) ;
2016-07-12 00:40:13 +00:00
}
}
}
m - > lightmaps . first = newfirst ;
}
void Surf_ClearLightmaps ( void )
{
lightmap_bytes = 0 ;
# ifdef THREADEDWORLD
while ( webogenerating )
COM_WorkerPartialSync ( webogenerating , & webogeneratingstate , true ) ;
R_DestroyWorldEBO ( webostate ) ;
webostate = NULL ;
# endif
}
/*
= = = = = = = = = = = = = = = = = =
GL_BuildLightmaps
Builds the lightmap texture
with all the surfaces from all brush models
Groups surfaces into their respective batches ( based on the lightmap number ) .
= = = = = = = = = = = = = = = = = =
*/
void Surf_BuildLightmaps ( void )
{
int i ;
model_t * m ;
extern model_t * mod_known ;
extern int mod_numknown ;
//make sure the lightstyle values are correct.
R_AnimateLight ( ) ;
r_framecount = 1 ; // no dlightcache
while ( numlightmaps > 0 )
{
numlightmaps - - ;
if ( ! lightmap [ numlightmaps ] )
continue ;
if ( ! lightmap [ numlightmaps ] - > external )
Image_DestroyTexture ( lightmap [ numlightmaps ] - > lightmap_texture ) ;
BZ_Free ( lightmap [ numlightmaps ] ) ;
lightmap [ numlightmaps ] = NULL ;
}
Surf_LightmapMode ( ) ;
r_oldviewcluster = - 1 ;
r_oldviewcluster2 = - 1 ;
//FIXME: unload stuff that's no longer relevant somehow.
for ( i = 0 ; i < mod_numknown ; i + + )
{
m = & mod_known [ i ] ;
if ( m - > loadstate ! = MLS_LOADED )
continue ;
Surf_BuildModelLightmaps ( m ) ;
}
BE_UploadAllLightmaps ( ) ;
}
/*
= = = = = = = = = = = = = = =
Surf_NewMap
= = = = = = = = = = = = = = =
*/
void Surf_NewMap ( void )
{
char namebuf [ MAX_QPATH ] ;
extern cvar_t host_mapname ;
2017-10-13 17:50:28 +00:00
# ifdef BEF_PUSHDEPTH
extern cvar_t r_polygonoffset_submodel_maps ;
char * s ;
# endif
2016-07-12 00:40:13 +00:00
int i ;
memset ( & r_worldentity , 0 , sizeof ( r_worldentity ) ) ;
AngleVectors ( r_worldentity . angles , r_worldentity . axis [ 0 ] , r_worldentity . axis [ 1 ] , r_worldentity . axis [ 2 ] ) ;
VectorInverse ( r_worldentity . axis [ 1 ] ) ;
r_worldentity . model = cl . worldmodel ;
Vector4Set ( r_worldentity . shaderRGBAf , 1 , 1 , 1 , 1 ) ;
VectorSet ( r_worldentity . light_avg , 1 , 1 , 1 ) ;
if ( cl . worldmodel )
COM_StripExtension ( COM_SkipPath ( cl . worldmodel - > name ) , namebuf , sizeof ( namebuf ) ) ;
else
* namebuf = ' \0 ' ;
Cvar_Set ( & host_mapname , namebuf ) ;
Surf_DeInit ( ) ;
r_viewcluster = - 1 ;
r_oldviewcluster = 0 ;
r_viewcluster2 = - 1 ;
2017-07-28 01:49:25 +00:00
r_oldviewcluster2 = 0 ;
2017-10-13 17:50:28 +00:00
# ifdef BEF_PUSHDEPTH
r_pushdepth = false ;
for ( s = r_polygonoffset_submodel_maps . string ; s & & * s ; )
{
s = COM_Parse ( s ) ;
if ( * com_token )
if ( wildcmp ( com_token , namebuf ) )
{
r_pushdepth = true ;
break ;
}
}
# endif
2016-07-12 00:40:13 +00:00
2017-08-29 02:29:06 +00:00
TRACE ( ( " dbg: Surf_NewMap: clear particles \n " ) ) ;
P_ClearParticles ( ) ;
CL_RegisterParticles ( ) ;
Shader_DoReload ( ) ;
2016-07-12 00:40:13 +00:00
if ( cl . worldmodel )
{
if ( cl . worldmodel - > loadstate = = MLS_LOADING )
COM_WorkerPartialSync ( cl . worldmodel , & cl . worldmodel - > loadstate , MLS_LOADING ) ;
Mod_ParseInfoFromEntityLump ( cl . worldmodel ) ;
}
if ( ! pe )
Cvar_ForceCallback ( & r_particlesystem ) ;
R_Clutter_Purge ( ) ;
TRACE ( ( " dbg: Surf_NewMap: wiping them stains (getting the cloth out) \n " ) ) ;
Surf_WipeStains ( ) ;
TRACE ( ( " dbg: Surf_NewMap: building lightmaps \n " ) ) ;
Surf_BuildLightmaps ( ) ;
TRACE ( ( " dbg: Surf_NewMap: ui \n " ) ) ;
# ifdef VM_UI
UI_Reset ( ) ;
# endif
TRACE ( ( " dbg: Surf_NewMap: tp \n " ) ) ;
TP_NewMap ( ) ;
for ( i = 0 ; i < cl . num_statics ; i + + )
{
vec3_t mins , maxs ;
//fixme: no rotation
if ( cl_static_entities [ i ] . ent . model )
{
//unfortunately, we need to know the actual size so that we can get this right. bum.
if ( cl_static_entities [ i ] . ent . model - > loadstate = = MLS_NOTLOADED )
Mod_LoadModel ( cl_static_entities [ i ] . ent . model , MLV_WARNSYNC ) ;
if ( cl_static_entities [ i ] . ent . model - > loadstate = = MLS_LOADING )
COM_WorkerPartialSync ( cl_static_entities [ i ] . ent . model , & cl_static_entities [ i ] . ent . model - > loadstate , MLS_LOADING ) ;
VectorAdd ( cl_static_entities [ i ] . ent . origin , cl_static_entities [ i ] . ent . model - > mins , mins ) ;
VectorAdd ( cl_static_entities [ i ] . ent . origin , cl_static_entities [ i ] . ent . model - > maxs , maxs ) ;
}
else
{
VectorCopy ( mins , cl_static_entities [ i ] . ent . origin ) ;
VectorCopy ( maxs , cl_static_entities [ i ] . ent . origin ) ;
}
if ( cl . worldmodel - > funcs . FindTouchedLeafs )
cl . worldmodel - > funcs . FindTouchedLeafs ( cl . worldmodel , & cl_static_entities [ i ] . pvscache , mins , maxs ) ;
cl_static_entities [ i ] . emit = NULL ;
}
# ifdef RTLIGHTS
Sh_PreGenerateLights ( ) ;
# endif
}
void Surf_PreNewMap ( void )
{
dpp7: Treat 'dropped' c2s packets as choked when using dpp7 protocols. This is because the protocol provides no way to disambiguate, and I don't like false reports of packetloss (only reliables loss can be detected, and that's not frequent enough to be meaningful). Pings can still be determined with dpp7, for those few packets which are acked.
package manager: reworked to enable/disable plugins when downloaded, which can also be present-but-disabled.
package manager: display a confirmation prompt before applying changes. do not allow other changes to be made while applying. prompt may be skipped with 'pkg apply' in dedicated servers.
sv: downloads are no longer forced to lower case.
sv: added sv_demoAutoCompress cvar. set to 1 to directly record to *.mvd.gz
cl: properly support directly playing .mvd.gz files
menus: reworked to separate mouse and keyboard focus. mouse focus becomes keyboard focus only on mouse clicks. tooltips follow mouse cursors.
menus: cleaned up menu heirachy a little. now simpler.
server browser: changed 'hide *' filters to 'show *' instead. I felt it was more logical.
deluxmapping: changed to disabled, load, generate, like r_loadlit is.
render targets api now supports negative formats to mean nearest filtering, where filtering is part of texture state.
drawrotpic fixed, now batches and interacts with drawpic correctly.
drawline fixed, no interacts with draw* correctly, but still does not batch.
fixed saving games.
provide proper userinfo to nq clients, where supported.
qcc: catch string table overflows safely, giving errors instead of crashes. switch to 32bit statements if some over-sized function requires it.
qtv: some bigcoords support tweaks
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5073 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-03-21 05:27:07 +00:00
r_loadbumpmapping = r_deluxmapping | | r_glsl_offsetmapping . ival ;
2016-07-12 00:40:13 +00:00
# ifdef RTLIGHTS
r_loadbumpmapping | = r_shadow_realtime_world . ival | | r_shadow_realtime_dlight . ival ;
# endif
2017-07-28 01:49:25 +00:00
r_viewcluster = - 1 ;
r_oldviewcluster = - 1 ;
r_viewcluster2 = - 1 ;
r_oldviewcluster2 = - 1 ;
2017-08-29 02:29:06 +00:00
Shader_DoReload ( ) ;
2016-07-12 00:40:13 +00:00
}
static float sgn ( float a )
{
if ( a > 0.0F ) return ( 1.0F ) ;
if ( a < 0.0F ) return ( - 1.0F ) ;
return ( 0.0F ) ;
}
void R_ObliqueNearClip ( float * viewmat , mplane_t * wplane )
{
float f ;
vec4_t q , c ;
vec3_t ping , pong ;
vec4_t vplane ;
//convert world plane into view space
Matrix4x4_CM_Transform3x3 ( viewmat , wplane - > normal , vplane ) ;
VectorScale ( wplane - > normal , wplane - > dist , ping ) ;
Matrix4x4_CM_Transform3 ( viewmat , ping , pong ) ;
vplane [ 3 ] = - DotProduct ( pong , vplane ) ;
// Calculate the clip-space corner point opposite the clipping plane
// as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
// transform it into camera space by multiplying it
// by the inverse of the projection matrix
2017-12-15 06:56:40 +00:00
q [ 0 ] = ( sgn ( vplane [ 0 ] ) + r_refdef . m_projection_std [ 8 ] ) / r_refdef . m_projection_std [ 0 ] ;
q [ 1 ] = ( sgn ( vplane [ 1 ] ) + fabs ( r_refdef . m_projection_std [ 9 ] ) ) / fabs ( r_refdef . m_projection_std [ 5 ] ) ;
2016-07-12 00:40:13 +00:00
q [ 2 ] = - 1.0F ;
2017-12-15 06:56:40 +00:00
q [ 3 ] = ( 1.0F + r_refdef . m_projection_std [ 10 ] ) / r_refdef . m_projection_std [ 14 ] ;
2016-07-12 00:40:13 +00:00
// Calculate the scaled plane vector
f = 2.0F / DotProduct4 ( vplane , q ) ;
Vector4Scale ( vplane , f , c ) ;
// Replace the third row of the projection matrix
2017-12-15 06:56:40 +00:00
r_refdef . m_projection_std [ 2 ] = c [ 0 ] ;
r_refdef . m_projection_std [ 6 ] = c [ 1 ] ;
r_refdef . m_projection_std [ 10 ] = c [ 2 ] + 1.0F ;
r_refdef . m_projection_std [ 14 ] = c [ 3 ] ;
2016-07-12 00:40:13 +00:00
}
# endif