2019-11-24 20:45:15 -08:00
/*
Copyright ( C ) 1996 - 2001 Id Software , Inc .
Copyright ( C ) 2002 - 2009 John Fitzgibbons and others
Copyright ( C ) 2007 - 2008 Kristian Duske
Copyright ( C ) 2010 - 2014 QuakeSpasm developers
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_brush.c: brush model rendering. renamed from r_surf.c
2019-12-02 07:07:37 -08:00
# include "q_defs.h"
2019-11-24 20:45:15 -08:00
extern cvar_t gl_fullbrights , r_drawflat , gl_overbright , r_oldwater ; //johnfitz
extern cvar_t gl_zfix ; // QuakeSpasm z-fighting fix
2019-11-25 17:40:18 -08:00
int32_t gl_lightmap_format ;
int32_t lightmap_bytes ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
# define BLOCK_WIDTH 128
# define BLOCK_HEIGHT 128
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
gltexture_t * lightmap_textures [ MAX_LIGHTMAPS ] ; //johnfitz -- changed to an array
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
unsigned blocklights [ BLOCK_WIDTH * BLOCK_HEIGHT * 3 ] ; //johnfitz -- was 18*18, added lit support (*3) and loosened surface extents maximum (BLOCK_WIDTH*BLOCK_HEIGHT)
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
typedef struct glRect_s
{
uint8_t l , t , w , h ;
2019-11-24 20:45:15 -08:00
} glRect_t ;
2019-11-25 17:40:18 -08:00
glpoly_t * lightmap_polys [ MAX_LIGHTMAPS ] ;
bool lightmap_modified [ MAX_LIGHTMAPS ] ;
glRect_t lightmap_rectchange [ MAX_LIGHTMAPS ] ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
int32_t allocated [ MAX_LIGHTMAPS ] [ BLOCK_WIDTH ] ;
int32_t last_lightmap_allocated ; //ericw -- optimization: remember the index of the last lightmap AllocBlock stored a surf in
2019-11-24 20:45:15 -08:00
// the lightmap texture data needs to be kept in
// main memory so texsubimage can update properly
2019-11-25 17:40:18 -08:00
byte lightmaps [ 4 * MAX_LIGHTMAPS * BLOCK_WIDTH * BLOCK_HEIGHT ] ;
2019-11-24 20:45:15 -08:00
/*
= = = = = = = = = = = = = = =
R_TextureAnimation - - johnfitz - - added " frame " param to eliminate use of " currententity " global
Returns the proper texture for a given time and base texture
= = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
texture_t * R_TextureAnimation ( texture_t * base , int32_t frame )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t relative ;
int32_t count ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if ( frame )
if ( base - > alternate_anims )
2019-11-24 20:45:15 -08:00
base = base - > alternate_anims ;
2019-11-25 17:40:18 -08:00
if ( ! base - > anim_total )
2019-11-24 20:45:15 -08:00
return base ;
2019-11-25 17:40:18 -08:00
relative = ( int32_t ) ( cl . time * 10 ) % base - > anim_total ;
2019-11-24 20:45:15 -08:00
count = 0 ;
2019-11-25 17:40:18 -08:00
while ( base - > anim_min > relative | | base - > anim_max < = relative )
2019-11-24 20:45:15 -08:00
{
base = base - > anim_next ;
2019-11-25 17:40:18 -08:00
if ( ! base )
Sys_Error ( " R_TextureAnimation: broken cycle " ) ;
if ( + + count > 100 )
Sys_Error ( " R_TextureAnimation: infinite cycle " ) ;
2019-11-24 20:45:15 -08:00
}
return base ;
}
/*
= = = = = = = = = = = = = = = =
DrawGLPoly
= = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void DrawGLPoly ( glpoly_t * p )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
float * v ;
int32_t i ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
glBegin ( GL_POLYGON ) ;
2019-11-24 20:45:15 -08:00
v = p - > verts [ 0 ] ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < p - > numverts ; i + + , v + = VERTEXSIZE )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
glTexCoord2f ( v [ 3 ] , v [ 4 ] ) ;
glVertex3fv ( v ) ;
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
glEnd ( ) ;
2019-11-24 20:45:15 -08:00
}
/*
= = = = = = = = = = = = = = = =
DrawGLTriangleFan - - johnfitz - - like DrawGLPoly but for r_showtris
= = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void DrawGLTriangleFan ( glpoly_t * p )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
float * v ;
int32_t i ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
glBegin ( GL_TRIANGLE_FAN ) ;
2019-11-24 20:45:15 -08:00
v = p - > verts [ 0 ] ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < p - > numverts ; i + + , v + = VERTEXSIZE )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
glVertex3fv ( v ) ;
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
glEnd ( ) ;
2019-11-24 20:45:15 -08:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2019-11-25 17:40:18 -08:00
BRUSH MODELS
2019-11-24 20:45:15 -08:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = =
R_DrawBrushModel
= = = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void R_DrawBrushModel ( entity_t * e )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t i , k ;
msurface_t * psurf ;
float dot ;
mplane_t * pplane ;
qmodel_t * clmodel ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if ( R_CullModelForEntity ( e ) )
2019-11-24 20:45:15 -08:00
return ;
currententity = e ;
clmodel = e - > model ;
2019-11-25 17:40:18 -08:00
VectorSubtract ( r_refdef . vieworg , e - > origin , modelorg ) ;
if ( e - > angles [ 0 ] | | e - > angles [ 1 ] | | e - > angles [ 2 ] )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
vec3_t temp ;
vec3_t forward , right , up ;
VectorCopy ( modelorg , temp ) ;
AngleVectors ( e - > angles , forward , right , up ) ;
modelorg [ 0 ] = DotProduct ( temp , forward ) ;
modelorg [ 1 ] = - DotProduct ( temp , right ) ;
modelorg [ 2 ] = DotProduct ( temp , up ) ;
2019-11-24 20:45:15 -08:00
}
psurf = & clmodel - > surfaces [ clmodel - > firstmodelsurface ] ;
// calculate dynamic lighting for bmodel if it's not an
// instanced model
2019-11-25 17:40:18 -08:00
if ( clmodel - > firstmodelsurface ! = 0 & & ! gl_flashblend . value )
2019-11-24 20:45:15 -08:00
{
2019-11-25 19:00:40 -08:00
for ( k = 0 ; k < cl_max_dlights ; k + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( ( cl_dlights [ k ] . die < cl . time ) | |
( ! cl_dlights [ k ] . radius ) )
2019-11-24 20:45:15 -08:00
continue ;
2019-11-25 17:40:18 -08:00
R_MarkLights ( & cl_dlights [ k ] , k ,
clmodel - > nodes + clmodel - > hulls [ 0 ] . firstclipnode ) ;
2019-11-24 20:45:15 -08:00
}
}
2019-11-25 17:40:18 -08:00
glPushMatrix ( ) ;
2019-12-02 07:19:02 -08:00
e - > angles [ 0 ] = - e - > angles [ 0 ] ; // stupid bug
2019-11-25 17:40:18 -08:00
if ( gl_zfix . value )
2019-11-24 20:45:15 -08:00
{
e - > origin [ 0 ] - = DIST_EPSILON ;
e - > origin [ 1 ] - = DIST_EPSILON ;
e - > origin [ 2 ] - = DIST_EPSILON ;
}
2019-11-25 17:40:18 -08:00
R_RotateForEntity ( e - > origin , e - > angles ) ;
if ( gl_zfix . value )
2019-11-24 20:45:15 -08:00
{
e - > origin [ 0 ] + = DIST_EPSILON ;
e - > origin [ 1 ] + = DIST_EPSILON ;
e - > origin [ 2 ] + = DIST_EPSILON ;
}
2019-12-02 07:19:02 -08:00
e - > angles [ 0 ] = - e - > angles [ 0 ] ; // stupid bug
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
R_ClearTextureChains ( clmodel , chain_model ) ;
for ( i = 0 ; i < clmodel - > nummodelsurfaces ; i + + , psurf + + )
2019-11-24 20:45:15 -08:00
{
pplane = psurf - > plane ;
2019-11-25 17:40:18 -08:00
dot = DotProduct ( modelorg , pplane - > normal ) - pplane - > dist ;
if ( ( ( psurf - > flags & SURF_PLANEBACK ) & & ( dot < - BACKFACE_EPSILON ) ) | |
( ! ( psurf - > flags & SURF_PLANEBACK ) & & ( dot > BACKFACE_EPSILON ) ) )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
R_ChainSurface ( psurf , chain_model ) ;
2019-11-24 20:45:15 -08:00
rs_brushpolys + + ;
}
}
2019-11-25 17:40:18 -08:00
R_DrawTextureChains ( clmodel , e , chain_model ) ;
R_DrawTextureChains_Water ( clmodel , e , chain_model ) ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
glPopMatrix ( ) ;
2019-11-24 20:45:15 -08:00
}
/*
= = = = = = = = = = = = = = = = =
R_DrawBrushModel_ShowTris - - johnfitz
= = = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void R_DrawBrushModel_ShowTris ( entity_t * e )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t i ;
msurface_t * psurf ;
float dot ;
mplane_t * pplane ;
qmodel_t * clmodel ;
glpoly_t * p ;
if ( R_CullModelForEntity ( e ) )
2019-11-24 20:45:15 -08:00
return ;
currententity = e ;
clmodel = e - > model ;
2019-11-25 17:40:18 -08:00
VectorSubtract ( r_refdef . vieworg , e - > origin , modelorg ) ;
if ( e - > angles [ 0 ] | | e - > angles [ 1 ] | | e - > angles [ 2 ] )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
vec3_t temp ;
vec3_t forward , right , up ;
VectorCopy ( modelorg , temp ) ;
AngleVectors ( e - > angles , forward , right , up ) ;
modelorg [ 0 ] = DotProduct ( temp , forward ) ;
modelorg [ 1 ] = - DotProduct ( temp , right ) ;
modelorg [ 2 ] = DotProduct ( temp , up ) ;
2019-11-24 20:45:15 -08:00
}
psurf = & clmodel - > surfaces [ clmodel - > firstmodelsurface ] ;
2019-11-25 17:40:18 -08:00
glPushMatrix ( ) ;
2019-12-02 07:19:02 -08:00
e - > angles [ 0 ] = - e - > angles [ 0 ] ; // stupid bug
2019-11-25 17:40:18 -08:00
R_RotateForEntity ( e - > origin , e - > angles ) ;
2019-12-02 07:19:02 -08:00
e - > angles [ 0 ] = - e - > angles [ 0 ] ; // stupid bug
2019-11-24 20:45:15 -08:00
//
// draw it
//
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < clmodel - > nummodelsurfaces ; i + + , psurf + + )
2019-11-24 20:45:15 -08:00
{
pplane = psurf - > plane ;
2019-11-25 17:40:18 -08:00
dot = DotProduct ( modelorg , pplane - > normal ) - pplane - > dist ;
if ( ( ( psurf - > flags & SURF_PLANEBACK ) & & ( dot < - BACKFACE_EPSILON ) ) | |
( ! ( psurf - > flags & SURF_PLANEBACK ) & & ( dot > BACKFACE_EPSILON ) ) )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( ( psurf - > flags & SURF_DRAWTURB ) & & r_oldwater . value )
for ( p = psurf - > polys - > next ; p ; p = p - > next )
DrawGLTriangleFan ( p ) ;
2019-11-24 20:45:15 -08:00
else
2019-11-25 17:40:18 -08:00
DrawGLTriangleFan ( psurf - > polys ) ;
2019-11-24 20:45:15 -08:00
}
}
2019-11-25 17:40:18 -08:00
glPopMatrix ( ) ;
2019-11-24 20:45:15 -08:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2019-11-25 17:40:18 -08:00
LIGHTMAPS
2019-11-24 20:45:15 -08:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = =
R_RenderDynamicLightmaps
called during rendering
= = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void R_RenderDynamicLightmaps ( msurface_t * fa )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
byte * base ;
int32_t maps ;
2019-11-24 20:45:15 -08:00
glRect_t * theRect ;
2019-11-25 16:49:58 -08:00
int32_t smax , tmax ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if ( fa - > flags & SURF_DRAWTILED ) //johnfitz -- not a lightmapped surface
2019-11-24 20:45:15 -08:00
return ;
// add to lightmap chain
fa - > polys - > chain = lightmap_polys [ fa - > lightmaptexturenum ] ;
lightmap_polys [ fa - > lightmaptexturenum ] = fa - > polys ;
// check for lightmap modification
2019-11-25 17:40:18 -08:00
for ( maps = 0 ; maps < MAXLIGHTMAPS & & fa - > styles [ maps ] ! = 255 ; maps + + )
if ( d_lightstylevalue [ fa - > styles [ maps ] ] ! = fa - > cached_light [ maps ] )
2019-11-24 20:45:15 -08:00
goto dynamic ;
2019-11-25 17:40:18 -08:00
if ( fa - > dlightframe = = r_framecount // dynamic this frame
| | fa - > cached_dlight ) // dynamic previously
2019-11-24 20:45:15 -08:00
{
dynamic :
2019-11-25 17:40:18 -08:00
if ( r_dynamic . value )
2019-11-24 20:45:15 -08:00
{
lightmap_modified [ fa - > lightmaptexturenum ] = true ;
theRect = & lightmap_rectchange [ fa - > lightmaptexturenum ] ;
2019-11-25 17:40:18 -08:00
if ( fa - > light_t < theRect - > t )
{
if ( theRect - > h )
2019-11-24 20:45:15 -08:00
theRect - > h + = theRect - > t - fa - > light_t ;
theRect - > t = fa - > light_t ;
}
2019-11-25 17:40:18 -08:00
if ( fa - > light_s < theRect - > l )
{
if ( theRect - > w )
2019-11-24 20:45:15 -08:00
theRect - > w + = theRect - > l - fa - > light_s ;
theRect - > l = fa - > light_s ;
}
2019-11-25 17:40:18 -08:00
smax = ( fa - > extents [ 0 ] > > 4 ) + 1 ;
tmax = ( fa - > extents [ 1 ] > > 4 ) + 1 ;
if ( ( theRect - > w + theRect - > l ) < ( fa - > light_s + smax ) )
theRect - > w = ( fa - > light_s - theRect - > l ) + smax ;
if ( ( theRect - > h + theRect - > t ) < ( fa - > light_t + tmax ) )
theRect - > h = ( fa - > light_t - theRect - > t ) + tmax ;
base = lightmaps + fa - > lightmaptexturenum * lightmap_bytes * BLOCK_WIDTH * BLOCK_HEIGHT ;
2019-11-24 20:45:15 -08:00
base + = fa - > light_t * BLOCK_WIDTH * lightmap_bytes + fa - > light_s * lightmap_bytes ;
2019-11-25 17:40:18 -08:00
R_BuildLightMap ( fa , base , BLOCK_WIDTH * lightmap_bytes ) ;
2019-11-24 20:45:15 -08:00
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
AllocBlock - - returns a texture number and the position inside it
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
int32_t AllocBlock ( int32_t w , int32_t h , int32_t * x , int32_t * y )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t i , j ;
int32_t best , best2 ;
int32_t texnum ;
2019-11-24 20:45:15 -08:00
// ericw -- rather than searching starting at lightmap 0 every time,
// start at the last lightmap we allocated a surface in.
// This makes AllocBlock much faster on large levels (can shave off 3+ seconds
// of load time on a level with 180 lightmaps), at a cost of not quite packing
// lightmaps as tightly vs. not doing this (uses ~5% more lightmaps)
2019-11-25 17:40:18 -08:00
for ( texnum = last_lightmap_allocated ; texnum < MAX_LIGHTMAPS ; texnum + + , last_lightmap_allocated + + )
2019-11-24 20:45:15 -08:00
{
best = BLOCK_HEIGHT ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < BLOCK_WIDTH - w ; i + + )
2019-11-24 20:45:15 -08:00
{
best2 = 0 ;
2019-11-25 17:40:18 -08:00
for ( j = 0 ; j < w ; j + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( allocated [ texnum ] [ i + j ] > = best )
2019-11-24 20:45:15 -08:00
break ;
2019-11-25 17:40:18 -08:00
if ( allocated [ texnum ] [ i + j ] > best2 )
best2 = allocated [ texnum ] [ i + j ] ;
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
if ( j = = w )
{
// this is a valid spot
2019-11-24 20:45:15 -08:00
* x = i ;
* y = best = best2 ;
}
}
2019-11-25 17:40:18 -08:00
if ( best + h > BLOCK_HEIGHT )
2019-11-24 20:45:15 -08:00
continue ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < w ; i + + )
2019-11-24 20:45:15 -08:00
allocated [ texnum ] [ * x + i ] = best + h ;
return texnum ;
}
2019-11-25 17:40:18 -08:00
Sys_Error ( " AllocBlock: full " ) ;
2019-11-24 20:45:15 -08:00
return 0 ; //johnfitz -- shut up compiler
}
2019-11-25 17:40:18 -08:00
mvertex_t * r_pcurrentvertbase ;
qmodel_t * currentmodel ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
int32_t nColinElim ;
2019-11-24 20:45:15 -08:00
/*
= = = = = = = = = = = = = = = = = = = = = = = =
GL_CreateSurfaceLightmap
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void GL_CreateSurfaceLightmap ( msurface_t * surf )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t smax , tmax ;
byte * base ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
smax = ( surf - > extents [ 0 ] > > 4 ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > 4 ) + 1 ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
surf - > lightmaptexturenum = AllocBlock ( smax , tmax , & surf - > light_s , & surf - > light_t ) ;
base = lightmaps + surf - > lightmaptexturenum * lightmap_bytes * BLOCK_WIDTH * BLOCK_HEIGHT ;
2019-11-24 20:45:15 -08:00
base + = ( surf - > light_t * BLOCK_WIDTH + surf - > light_s ) * lightmap_bytes ;
2019-11-25 17:40:18 -08:00
R_BuildLightMap ( surf , base , BLOCK_WIDTH * lightmap_bytes ) ;
2019-11-24 20:45:15 -08:00
}
/*
= = = = = = = = = = = = = = = =
BuildSurfaceDisplayList - - called at level load time
= = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void BuildSurfaceDisplayList ( msurface_t * fa )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t i , lindex , lnumverts ;
medge_t * pedges , * r_pedge ;
float * vec ;
float s , t ;
glpoly_t * poly ;
2019-11-24 20:45:15 -08:00
// reconstruct the polygon
pedges = currentmodel - > edges ;
lnumverts = fa - > numedges ;
//
// draw texture
//
2019-12-04 04:24:35 -08:00
poly = Hunk_AllocName ( sizeof ( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof ( float ) , __func__ ) ;
2019-11-24 20:45:15 -08:00
poly - > next = fa - > polys ;
fa - > polys = poly ;
poly - > numverts = lnumverts ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < lnumverts ; i + + )
2019-11-24 20:45:15 -08:00
{
lindex = currentmodel - > surfedges [ fa - > firstedge + i ] ;
2019-11-25 17:40:18 -08:00
if ( lindex > 0 )
2019-11-24 20:45:15 -08:00
{
r_pedge = & pedges [ lindex ] ;
vec = r_pcurrentvertbase [ r_pedge - > v [ 0 ] ] . position ;
}
else
{
r_pedge = & pedges [ - lindex ] ;
vec = r_pcurrentvertbase [ r_pedge - > v [ 1 ] ] . position ;
}
2019-11-25 17:40:18 -08:00
s = DotProduct ( vec , fa - > texinfo - > vecs [ 0 ] ) + fa - > texinfo - > vecs [ 0 ] [ 3 ] ;
2019-11-24 20:45:15 -08:00
s / = fa - > texinfo - > texture - > width ;
2019-11-25 17:40:18 -08:00
t = DotProduct ( vec , fa - > texinfo - > vecs [ 1 ] ) + fa - > texinfo - > vecs [ 1 ] [ 3 ] ;
2019-11-24 20:45:15 -08:00
t / = fa - > texinfo - > texture - > height ;
2019-11-25 17:40:18 -08:00
VectorCopy ( vec , poly - > verts [ i ] ) ;
2019-11-24 20:45:15 -08:00
poly - > verts [ i ] [ 3 ] = s ;
poly - > verts [ i ] [ 4 ] = t ;
//
// lightmap texture coordinates
//
2019-11-25 17:40:18 -08:00
s = DotProduct ( vec , fa - > texinfo - > vecs [ 0 ] ) + fa - > texinfo - > vecs [ 0 ] [ 3 ] ;
2019-11-24 20:45:15 -08:00
s - = fa - > texturemins [ 0 ] ;
2019-11-25 17:40:18 -08:00
s + = fa - > light_s * 16 ;
2019-11-24 20:45:15 -08:00
s + = 8 ;
2019-11-25 17:40:18 -08:00
s / = BLOCK_WIDTH * 16 ; //fa->texinfo->texture->width;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
t = DotProduct ( vec , fa - > texinfo - > vecs [ 1 ] ) + fa - > texinfo - > vecs [ 1 ] [ 3 ] ;
2019-11-24 20:45:15 -08:00
t - = fa - > texturemins [ 1 ] ;
2019-11-25 17:40:18 -08:00
t + = fa - > light_t * 16 ;
2019-11-24 20:45:15 -08:00
t + = 8 ;
2019-11-25 17:40:18 -08:00
t / = BLOCK_HEIGHT * 16 ; //fa->texinfo->texture->height;
2019-11-24 20:45:15 -08:00
poly - > verts [ i ] [ 5 ] = s ;
poly - > verts [ i ] [ 6 ] = t ;
}
//johnfitz -- removed gl_keeptjunctions code
poly - > numverts = lnumverts ;
}
/*
= = = = = = = = = = = = = = = = = =
GL_BuildLightmaps - - called at level load time
Builds the lightmap texture
with all the surfaces from all brush models
= = = = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void GL_BuildLightmaps ( void )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
char name [ 16 ] ;
byte * data ;
int32_t i , j ;
qmodel_t * m ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
memset ( allocated , 0 , sizeof ( allocated ) ) ;
2019-11-24 20:45:15 -08:00
last_lightmap_allocated = 0 ;
r_framecount = 1 ; // no dlightcache
//johnfitz -- null out array (the gltexture objects themselves were already freed by Mod_ClearAll)
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < MAX_LIGHTMAPS ; i + + )
2019-11-24 20:45:15 -08:00
lightmap_textures [ i ] = NULL ;
//johnfitz
gl_lightmap_format = GL_RGBA ; //FIXME: hardcoded for now!
2019-11-25 17:40:18 -08:00
switch ( gl_lightmap_format )
2019-11-24 20:45:15 -08:00
{
case GL_RGBA :
lightmap_bytes = 4 ;
break ;
case GL_BGRA :
lightmap_bytes = 4 ;
break ;
default :
2019-11-25 17:40:18 -08:00
Sys_Error ( " GL_BuildLightmaps: bad lightmap format " ) ;
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
for ( j = 1 ; j < MAX_MODELS ; j + + )
2019-11-24 20:45:15 -08:00
{
m = cl . model_precache [ j ] ;
2019-11-25 17:40:18 -08:00
if ( ! m )
2019-11-24 20:45:15 -08:00
break ;
2019-11-25 17:40:18 -08:00
if ( m - > name [ 0 ] = = ' * ' )
2019-11-24 20:45:15 -08:00
continue ;
r_pcurrentvertbase = m - > vertexes ;
currentmodel = m ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < m - > numsurfaces ; i + + )
2019-11-24 20:45:15 -08:00
{
//johnfitz -- rewritten to use SURF_DRAWTILED instead of the sky/water flags
2019-11-25 17:40:18 -08:00
if ( m - > surfaces [ i ] . flags & SURF_DRAWTILED )
2019-11-24 20:45:15 -08:00
continue ;
2019-11-25 17:40:18 -08:00
GL_CreateSurfaceLightmap ( m - > surfaces + i ) ;
BuildSurfaceDisplayList ( m - > surfaces + i ) ;
2019-11-24 20:45:15 -08:00
//johnfitz
}
}
//
// upload all lightmaps that were filled
//
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < MAX_LIGHTMAPS ; i + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( ! allocated [ i ] [ 0 ] )
break ; // no more used
2019-11-24 20:45:15 -08:00
lightmap_modified [ i ] = false ;
lightmap_rectchange [ i ] . l = BLOCK_WIDTH ;
lightmap_rectchange [ i ] . t = BLOCK_HEIGHT ;
lightmap_rectchange [ i ] . w = 0 ;
lightmap_rectchange [ i ] . h = 0 ;
//johnfitz -- use texture manager
2019-12-08 12:35:56 -08:00
sprintf ( name , " lightmap%03 " PRIi32 , i ) ;
2019-11-25 17:40:18 -08:00
data = lightmaps + i * BLOCK_WIDTH * BLOCK_HEIGHT * lightmap_bytes ;
2019-12-08 12:35:56 -08:00
lightmap_textures [ i ] = TexMgr_LoadImage ( cl . worldmodel , name , BLOCK_WIDTH , BLOCK_HEIGHT , SRC_LIGHTMAP , data , " " , ( src_offset_t ) data , TEXPREF_LINEAR | TEXPREF_NOPICMIP ) ;
2019-11-24 20:45:15 -08:00
//johnfitz
}
//johnfitz -- warn about exceeding old limits
2019-11-25 17:40:18 -08:00
if ( i > = 64 )
Con_DWarning ( " % " PRIi32 " lightmaps exceeds standard limit of 64 (max = % " PRIi32 " ). \n " , i , MAX_LIGHTMAPS ) ;
2019-11-24 20:45:15 -08:00
//johnfitz
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2019-11-25 17:40:18 -08:00
VBO support
2019-11-24 20:45:15 -08:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
GLuint gl_bmodel_vbo = 0 ;
2019-11-25 17:40:18 -08:00
void GL_DeleteBModelVertexBuffer ( void )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( ! ( gl_vbo_able & & gl_mtexable & & gl_max_texture_units > = 3 ) )
2019-11-24 20:45:15 -08:00
return ;
2019-11-25 17:40:18 -08:00
GL_DeleteBuffersFunc ( 1 , & gl_bmodel_vbo ) ;
2019-11-24 20:45:15 -08:00
gl_bmodel_vbo = 0 ;
2019-11-25 17:40:18 -08:00
GL_ClearBufferBindings ( ) ;
2019-11-24 20:45:15 -08:00
}
/*
= = = = = = = = = = = = = = = = = =
GL_BuildBModelVertexBuffer
Deletes gl_bmodel_vbo if it already exists , then rebuilds it with all
surfaces from world + all brush models
= = = = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void GL_BuildBModelVertexBuffer ( void )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
uint32_t numverts , varray_bytes , varray_index ;
int32_t i , j ;
qmodel_t * m ;
float * varray ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if ( ! ( gl_vbo_able & & gl_mtexable & & gl_max_texture_units > = 3 ) )
2019-11-24 20:45:15 -08:00
return ;
// ask GL for a name for our VBO
2019-11-25 17:40:18 -08:00
GL_DeleteBuffersFunc ( 1 , & gl_bmodel_vbo ) ;
GL_GenBuffersFunc ( 1 , & gl_bmodel_vbo ) ;
2019-11-25 17:29:41 -08:00
2019-11-24 20:45:15 -08:00
// count all verts in all models
numverts = 0 ;
2019-11-25 17:40:18 -08:00
for ( j = 1 ; j < MAX_MODELS ; j + + )
2019-11-24 20:45:15 -08:00
{
m = cl . model_precache [ j ] ;
2019-11-25 17:40:18 -08:00
if ( ! m | | m - > name [ 0 ] = = ' * ' | | m - > type ! = mod_brush )
2019-11-24 20:45:15 -08:00
continue ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < m - > numsurfaces ; i + + )
2019-11-24 20:45:15 -08:00
{
numverts + = m - > surfaces [ i ] . numedges ;
}
}
2019-11-25 17:29:41 -08:00
2019-11-24 20:45:15 -08:00
// build vertex array
varray_bytes = VERTEXSIZE * sizeof ( float ) * numverts ;
2019-11-25 17:40:18 -08:00
varray = ( float * ) malloc ( varray_bytes ) ;
2019-11-24 20:45:15 -08:00
varray_index = 0 ;
2019-11-25 17:29:41 -08:00
2019-11-25 17:40:18 -08:00
for ( j = 1 ; j < MAX_MODELS ; j + + )
2019-11-24 20:45:15 -08:00
{
m = cl . model_precache [ j ] ;
2019-11-25 17:40:18 -08:00
if ( ! m | | m - > name [ 0 ] = = ' * ' | | m - > type ! = mod_brush )
2019-11-24 20:45:15 -08:00
continue ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < m - > numsurfaces ; i + + )
2019-11-24 20:45:15 -08:00
{
msurface_t * s = & m - > surfaces [ i ] ;
s - > vbo_firstvert = varray_index ;
2019-11-25 17:40:18 -08:00
memcpy ( & varray [ VERTEXSIZE * varray_index ] , s - > polys - > verts , VERTEXSIZE * sizeof ( float ) * s - > numedges ) ;
2019-11-24 20:45:15 -08:00
varray_index + = s - > numedges ;
}
}
// upload to GPU
2019-11-25 17:40:18 -08:00
GL_BindBufferFunc ( GL_ARRAY_BUFFER , gl_bmodel_vbo ) ;
GL_BufferDataFunc ( GL_ARRAY_BUFFER , varray_bytes , varray , GL_STATIC_DRAW ) ;
free ( varray ) ;
2019-11-25 17:29:41 -08:00
2019-11-24 20:45:15 -08:00
// invalidate the cached bindings
2019-11-25 17:40:18 -08:00
GL_ClearBufferBindings ( ) ;
2019-11-24 20:45:15 -08:00
}
/*
= = = = = = = = = = = = = = =
R_AddDynamicLights
= = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void R_AddDynamicLights ( msurface_t * surf )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t lnum ;
int32_t sd , td ;
float dist , rad , minlight ;
vec3_t impact , local ;
int32_t s , t ;
int32_t i ;
int32_t smax , tmax ;
mtexinfo_t * tex ;
2019-11-24 20:45:15 -08:00
//johnfitz -- lit support via lordhavoc
2019-11-25 17:40:18 -08:00
float cred , cgreen , cblue , brightness ;
unsigned * bl ;
2019-11-24 20:45:15 -08:00
//johnfitz
2019-11-25 17:40:18 -08:00
smax = ( surf - > extents [ 0 ] > > 4 ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > 4 ) + 1 ;
2019-11-24 20:45:15 -08:00
tex = surf - > texinfo ;
2019-11-25 19:00:40 -08:00
for ( lnum = 0 ; lnum < cl_max_dlights ; lnum + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( ! ( surf - > dlightbits [ lnum > > 5 ] & ( 1U < < ( lnum & 31 ) ) ) )
continue ; // not lit by this light
2019-11-24 20:45:15 -08:00
rad = cl_dlights [ lnum ] . radius ;
2019-11-25 17:40:18 -08:00
dist = DotProduct ( cl_dlights [ lnum ] . origin , surf - > plane - > normal ) -
surf - > plane - > dist ;
2019-11-24 20:45:15 -08:00
rad - = fabs ( dist ) ;
minlight = cl_dlights [ lnum ] . minlight ;
2019-11-25 17:40:18 -08:00
if ( rad < minlight )
2019-11-24 20:45:15 -08:00
continue ;
minlight = rad - minlight ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < 3 ; i + + )
2019-11-24 20:45:15 -08:00
{
impact [ i ] = cl_dlights [ lnum ] . origin [ i ] -
2019-11-25 17:40:18 -08:00
surf - > plane - > normal [ i ] * dist ;
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
local [ 0 ] = DotProduct ( impact , tex - > vecs [ 0 ] ) + tex - > vecs [ 0 ] [ 3 ] ;
local [ 1 ] = DotProduct ( impact , tex - > vecs [ 1 ] ) + tex - > vecs [ 1 ] [ 3 ] ;
2019-11-24 20:45:15 -08:00
local [ 0 ] - = surf - > texturemins [ 0 ] ;
local [ 1 ] - = surf - > texturemins [ 1 ] ;
//johnfitz -- lit support via lordhavoc
bl = blocklights ;
cred = cl_dlights [ lnum ] . color [ 0 ] * 256.0f ;
cgreen = cl_dlights [ lnum ] . color [ 1 ] * 256.0f ;
cblue = cl_dlights [ lnum ] . color [ 2 ] * 256.0f ;
//johnfitz
2019-11-25 17:40:18 -08:00
for ( t = 0 ; t < tmax ; t + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
td = local [ 1 ] - t * 16 ;
if ( td < 0 )
2019-11-24 20:45:15 -08:00
td = - td ;
2019-11-25 17:40:18 -08:00
for ( s = 0 ; s < smax ; s + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
sd = local [ 0 ] - s * 16 ;
if ( sd < 0 )
2019-11-24 20:45:15 -08:00
sd = - sd ;
2019-11-25 17:40:18 -08:00
if ( sd > td )
dist = sd + ( td > > 1 ) ;
2019-11-24 20:45:15 -08:00
else
2019-11-25 17:40:18 -08:00
dist = td + ( sd > > 1 ) ;
if ( dist < minlight )
//johnfitz -- lit support via lordhavoc
2019-11-24 20:45:15 -08:00
{
brightness = rad - dist ;
2019-11-25 17:40:18 -08:00
bl [ 0 ] + = ( int32_t ) ( brightness * cred ) ;
bl [ 1 ] + = ( int32_t ) ( brightness * cgreen ) ;
bl [ 2 ] + = ( int32_t ) ( brightness * cblue ) ;
2019-11-24 20:45:15 -08:00
}
bl + = 3 ;
//johnfitz
}
}
}
}
/*
= = = = = = = = = = = = = = =
R_BuildLightMap - - johnfitz - - revised for lit support via lordhavoc
Combine and scale multiple lightmaps into the 8.8 format in blocklights
= = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void R_BuildLightMap ( msurface_t * surf , byte * dest , int32_t stride )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t smax , tmax ;
int32_t r , g , b ;
int32_t i , j , size ;
byte * lightmap ;
unsigned scale ;
int32_t maps ;
unsigned * bl ;
2019-11-24 20:45:15 -08:00
surf - > cached_dlight = ( surf - > dlightframe = = r_framecount ) ;
2019-11-25 17:40:18 -08:00
smax = ( surf - > extents [ 0 ] > > 4 ) + 1 ;
tmax = ( surf - > extents [ 1 ] > > 4 ) + 1 ;
size = smax * tmax ;
2019-11-24 20:45:15 -08:00
lightmap = surf - > samples ;
2019-11-25 17:40:18 -08:00
if ( cl . worldmodel - > lightdata )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
// clear to no light
memset ( & blocklights [ 0 ] , 0 , size * 3 * sizeof ( uint32_t ) ) ; //johnfitz -- lit support via lordhavoc
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
// add all the lightmaps
if ( lightmap )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
for ( maps = 0 ; maps < MAXLIGHTMAPS & & surf - > styles [ maps ] ! = 255 ;
maps + + )
2019-11-24 20:45:15 -08:00
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
2019-11-25 17:40:18 -08:00
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
2019-11-24 20:45:15 -08:00
//johnfitz -- lit support via lordhavoc
bl = blocklights ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < size ; i + + )
2019-11-24 20:45:15 -08:00
{
* bl + + + = * lightmap + + * scale ;
* bl + + + = * lightmap + + * scale ;
* bl + + + = * lightmap + + * scale ;
}
//johnfitz
}
}
2019-11-25 17:40:18 -08:00
// add all the dynamic lights
if ( surf - > dlightframe = = r_framecount )
R_AddDynamicLights ( surf ) ;
2019-11-24 20:45:15 -08:00
}
else
{
2019-11-25 17:40:18 -08:00
// set to full bright if no light data
memset ( & blocklights [ 0 ] , 255 , size * 3 * sizeof ( uint32_t ) ) ; //johnfitz -- lit support via lordhavoc
2019-11-24 20:45:15 -08:00
}
// bound, invert, and shift
// store:
2019-11-25 17:40:18 -08:00
switch ( gl_lightmap_format )
2019-11-24 20:45:15 -08:00
{
case GL_RGBA :
stride - = smax * 4 ;
bl = blocklights ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
for ( j = 0 ; j < smax ; j + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( gl_overbright . value )
2019-11-24 20:45:15 -08:00
{
r = * bl + + > > 8 ;
g = * bl + + > > 8 ;
b = * bl + + > > 8 ;
}
else
{
r = * bl + + > > 7 ;
g = * bl + + > > 7 ;
b = * bl + + > > 7 ;
}
2019-11-25 17:40:18 -08:00
* dest + + = ( r > 255 ) ? 255 : r ;
* dest + + = ( g > 255 ) ? 255 : g ;
* dest + + = ( b > 255 ) ? 255 : b ;
2019-11-24 20:45:15 -08:00
* dest + + = 255 ;
}
}
break ;
case GL_BGRA :
stride - = smax * 4 ;
bl = blocklights ;
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
for ( j = 0 ; j < smax ; j + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( gl_overbright . value )
2019-11-24 20:45:15 -08:00
{
r = * bl + + > > 8 ;
g = * bl + + > > 8 ;
b = * bl + + > > 8 ;
}
else
{
r = * bl + + > > 7 ;
g = * bl + + > > 7 ;
b = * bl + + > > 7 ;
}
2019-11-25 17:40:18 -08:00
* dest + + = ( b > 255 ) ? 255 : b ;
* dest + + = ( g > 255 ) ? 255 : g ;
* dest + + = ( r > 255 ) ? 255 : r ;
2019-11-24 20:45:15 -08:00
* dest + + = 255 ;
}
}
break ;
default :
2019-11-25 17:40:18 -08:00
Sys_Error ( " R_BuildLightMap: bad lightmap format " ) ;
2019-11-24 20:45:15 -08:00
}
}
/*
= = = = = = = = = = = = = = =
R_UploadLightmap - - johnfitz - - uploads the modified lightmap to opengl if necessary
assumes lightmap texture is already bound
= = = = = = = = = = = = = = =
*/
2019-11-25 16:49:58 -08:00
static void R_UploadLightmap ( int32_t lmap )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
glRect_t * theRect ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if ( ! lightmap_modified [ lmap ] )
2019-11-24 20:45:15 -08:00
return ;
lightmap_modified [ lmap ] = false ;
theRect = & lightmap_rectchange [ lmap ] ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , theRect - > t , BLOCK_WIDTH , theRect - > h , gl_lightmap_format ,
2019-11-25 17:40:18 -08:00
GL_UNSIGNED_BYTE , lightmaps + ( lmap * BLOCK_HEIGHT + theRect - > t ) * BLOCK_WIDTH * lightmap_bytes ) ;
2019-11-24 20:45:15 -08:00
theRect - > l = BLOCK_WIDTH ;
theRect - > t = BLOCK_HEIGHT ;
theRect - > h = 0 ;
theRect - > w = 0 ;
rs_dynamiclightmaps + + ;
}
2019-11-25 17:40:18 -08:00
void R_UploadLightmaps ( void )
2019-11-24 20:45:15 -08:00
{
2019-11-25 16:49:58 -08:00
int32_t lmap ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
for ( lmap = 0 ; lmap < MAX_LIGHTMAPS ; lmap + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( ! lightmap_modified [ lmap ] )
2019-11-24 20:45:15 -08:00
continue ;
2019-11-25 17:40:18 -08:00
GL_Bind ( lightmap_textures [ lmap ] ) ;
2019-11-24 20:45:15 -08:00
R_UploadLightmap ( lmap ) ;
}
}
/*
= = = = = = = = = = = = = = = =
R_RebuildAllLightmaps - - johnfitz - - called when gl_overbright gets toggled
= = = = = = = = = = = = = = = =
*/
2019-11-25 17:40:18 -08:00
void R_RebuildAllLightmaps ( void )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t i , j ;
qmodel_t * mod ;
msurface_t * fa ;
byte * base ;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if ( ! cl . worldmodel ) // is this the correct test?
2019-11-24 20:45:15 -08:00
return ;
//for each surface in each model, rebuild lightmap with new scale
2019-11-25 17:40:18 -08:00
for ( i = 1 ; i < MAX_MODELS ; i + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( ! ( mod = cl . model_precache [ i ] ) )
2019-11-24 20:45:15 -08:00
continue ;
fa = & mod - > surfaces [ mod - > firstmodelsurface ] ;
2019-11-25 17:40:18 -08:00
for ( j = 0 ; j < mod - > nummodelsurfaces ; j + + , fa + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( fa - > flags & SURF_DRAWTILED )
2019-11-24 20:45:15 -08:00
continue ;
2019-11-25 17:40:18 -08:00
base = lightmaps + fa - > lightmaptexturenum * lightmap_bytes * BLOCK_WIDTH * BLOCK_HEIGHT ;
2019-11-24 20:45:15 -08:00
base + = fa - > light_t * BLOCK_WIDTH * lightmap_bytes + fa - > light_s * lightmap_bytes ;
2019-11-25 17:40:18 -08:00
R_BuildLightMap ( fa , base , BLOCK_WIDTH * lightmap_bytes ) ;
2019-11-24 20:45:15 -08:00
}
}
//for each lightmap, upload it
2019-11-25 17:40:18 -08:00
for ( i = 0 ; i < MAX_LIGHTMAPS ; i + + )
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if ( ! allocated [ i ] [ 0 ] )
2019-11-24 20:45:15 -08:00
break ;
2019-11-25 17:40:18 -08:00
GL_Bind ( lightmap_textures [ i ] ) ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 , BLOCK_WIDTH , BLOCK_HEIGHT , gl_lightmap_format ,
GL_UNSIGNED_BYTE , lightmaps + i * BLOCK_WIDTH * BLOCK_HEIGHT * lightmap_bytes ) ;
2019-11-24 20:45:15 -08:00
}
}