2019-03-13 19:20:07 +00:00
/*
Copyright ( C ) 1997 - 2001 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_backend.c: array and texture coord handling for protoshaders
# include "r_local.h"
# define TABLE_SIZE 1024
# define TABLE_MASK 1023
static float rb_sinTable [ TABLE_SIZE ] ;
static float rb_triangleTable [ TABLE_SIZE ] ;
static float rb_squareTable [ TABLE_SIZE ] ;
static float rb_sawtoothTable [ TABLE_SIZE ] ;
static float rb_inverseSawtoothTable [ TABLE_SIZE ] ;
static float rb_noiseTable [ TABLE_SIZE ] ;
// vertex arrays
unsigned indexArray [ MAX_INDICES ] ;
float texCoordArray [ MAX_TEXTURE_UNITS ] [ MAX_VERTICES ] [ 2 ] ;
float vertexArray [ MAX_VERTICES ] [ 3 ] ;
float colorArray [ MAX_VERTICES ] [ 4 ] ;
float inTexCoordArray [ MAX_VERTICES ] [ 2 ] ;
2020-02-23 19:07:48 +00:00
float celTexCoordArray [ MAX_VERTICES ] [ 2 ] ; // for cel shading
2019-03-13 19:20:07 +00:00
unsigned rb_vertex , rb_index ;
/*
= = = = = = = = = = = = = = = = =
RB_BuildTables
= = = = = = = = = = = = = = = = =
*/
static void RB_BuildTables ( void )
{
int i ;
float f ;
for ( i = 0 ; i < TABLE_SIZE ; i + + )
{
f = ( float ) i / ( float ) TABLE_SIZE ;
rb_sinTable [ i ] = sin ( f * M_PI2 ) ;
if ( f < 0.25 )
rb_triangleTable [ i ] = 4.0 * f ;
else if ( f < 0.75 )
rb_triangleTable [ i ] = 2.0 - 4.0 * f ;
else
rb_triangleTable [ i ] = ( f - 0.75 ) * 4.0 - 1.0 ;
if ( f < 0.5 )
rb_squareTable [ i ] = 1.0 ;
else
rb_squareTable [ i ] = - 1.0 ;
rb_sawtoothTable [ i ] = f ;
rb_inverseSawtoothTable [ i ] = 1.0 - f ;
rb_noiseTable [ i ] = crand ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
RB_TableForFunc
= = = = = = = = = = = = = = = = =
*/
static float * RB_TableForFunc ( const waveFunc_t * func )
{
switch ( func - > type )
{
case WAVEFORM_SIN :
return rb_sinTable ;
case WAVEFORM_TRIANGLE :
return rb_triangleTable ;
case WAVEFORM_SQUARE :
return rb_squareTable ;
case WAVEFORM_SAWTOOTH :
return rb_sawtoothTable ;
case WAVEFORM_INVERSESAWTOOTH :
return rb_inverseSawtoothTable ;
case WAVEFORM_NOISE :
return rb_noiseTable ;
}
VID_Error ( ERR_DROP , " RB_TableForFunc: unknown waveform type %i " , func - > type ) ;
return rb_sinTable ;
}
/*
= = = = = = = = = = = = = = = = =
RB_InitBackend
= = = = = = = = = = = = = = = = =
*/
void RB_InitBackend ( void )
{
// Build waveform tables
RB_BuildTables ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
RB_CalcGlowColor
= = = = = = = = = = = = = = = = =
*/
2020-02-23 19:07:48 +00:00
float RB_CalcGlowColor ( renderparms_t * parms )
2019-03-13 19:20:07 +00:00
{
float * table , rad , out = 1.0f ;
2020-02-23 19:07:48 +00:00
if ( ! parms ) return 0.0f ;
if ( parms - > glow . type > - 1 )
2019-03-13 19:20:07 +00:00
{
2020-02-23 19:07:48 +00:00
table = RB_TableForFunc ( & parms - > glow ) ;
rad = parms - > glow . params [ 2 ] + parms - > glow . params [ 3 ] * r_newrefdef . time ;
out = table [ ( ( int ) ( rad * TABLE_SIZE ) ) & TABLE_MASK ] * parms - > glow . params [ 1 ] + parms - > glow . params [ 0 ] ;
2019-03-13 19:20:07 +00:00
out = max ( min ( out , 1.0f ) , 0.0f ) ; // clamp
}
return out ;
}
/*
= = = = = = = = = = = = = = = = =
RB_ModifyTextureCoords
borrowed from EGL & Q2E
= = = = = = = = = = = = = = = = =
*/
2020-02-23 19:07:48 +00:00
void RB_ModifyTextureCoords ( float * inArray , float * inVerts , int numVerts , renderparms_t * parms )
2019-03-13 19:20:07 +00:00
{
int i ;
float t1 , t2 , sint , cost , rad ;
float * tcArray , * vertArray , * table ;
2020-02-23 19:07:48 +00:00
if ( ! inArray | | ! inVerts | | ! parms )
return ;
if ( parms - > translate_x ! = 0.0f )
2019-03-13 19:20:07 +00:00
for ( tcArray = inArray , i = 0 ; i < numVerts ; i + + , tcArray + = 2 )
2020-02-23 19:07:48 +00:00
tcArray [ 0 ] + = parms - > translate_x ;
if ( parms - > translate_y ! = 0.0f )
2019-03-13 19:20:07 +00:00
for ( tcArray = inArray , i = 0 ; i < numVerts ; i + + , tcArray + = 2 )
2020-02-23 19:07:48 +00:00
tcArray [ 1 ] + = parms - > translate_y ;
2019-03-13 19:20:07 +00:00
2020-02-23 19:07:48 +00:00
if ( parms - > rotate ! = 0.0f )
2019-03-13 19:20:07 +00:00
{
2020-02-23 19:07:48 +00:00
rad = - DEG2RAD ( parms - > rotate * r_newrefdef . time ) ;
2019-03-13 19:20:07 +00:00
sint = sin ( rad ) ;
cost = cos ( rad ) ;
for ( tcArray = inArray , i = 0 ; i < numVerts ; i + + , tcArray + = 2 ) {
t1 = tcArray [ 0 ] ;
t2 = tcArray [ 1 ] ;
tcArray [ 0 ] = cost * ( t1 - 0.5 ) - sint * ( t2 - 0.5 ) + 0.5 ;
tcArray [ 1 ] = cost * ( t2 - 0.5 ) + sint * ( t1 - 0.5 ) + 0.5 ;
}
}
2020-02-23 19:07:48 +00:00
if ( parms - > stretch . type > - 1 )
2019-03-13 19:20:07 +00:00
{
2020-02-23 19:07:48 +00:00
table = RB_TableForFunc ( & parms - > stretch ) ;
rad = parms - > stretch . params [ 2 ] + parms - > stretch . params [ 3 ] * r_newrefdef . time ;
t1 = table [ ( ( int ) ( rad * TABLE_SIZE ) ) & TABLE_MASK ] * parms - > stretch . params [ 1 ] + parms - > stretch . params [ 0 ] ;
2019-03-13 19:20:07 +00:00
t1 = ( t1 ) ? 1.0 / t1 : 1.0 ;
t2 = 0.5 - 0.5 * t1 ;
for ( tcArray = inArray , i = 0 ; i < numVerts ; i + + , tcArray + = 2 ) {
tcArray [ 0 ] = tcArray [ 0 ] * t1 + t2 ;
tcArray [ 1 ] = tcArray [ 1 ] * t1 + t2 ;
}
}
2020-02-23 19:07:48 +00:00
if ( parms - > scale_x ! = 1.0f )
2019-03-13 19:20:07 +00:00
for ( tcArray = inArray , i = 0 ; i < numVerts ; i + + , tcArray + = 2 )
2020-02-23 19:07:48 +00:00
tcArray [ 0 ] = tcArray [ 0 ] / parms - > scale_x ;
if ( parms - > scale_y ! = 1.0f )
2019-03-13 19:20:07 +00:00
for ( tcArray = inArray , i = 0 ; i < numVerts ; i + + , tcArray + = 2 )
2020-02-23 19:07:48 +00:00
tcArray [ 1 ] = tcArray [ 1 ] / parms - > scale_y ;
2019-03-13 19:20:07 +00:00
2020-02-23 19:07:48 +00:00
if ( parms - > turb . type > - 1 )
2019-03-13 19:20:07 +00:00
{
2020-02-23 19:07:48 +00:00
table = RB_TableForFunc ( & parms - > turb ) ;
t1 = parms - > turb . params [ 2 ] + parms - > turb . params [ 3 ] * r_newrefdef . time ;
2019-03-13 19:20:07 +00:00
for ( tcArray = inArray , vertArray = inVerts , i = 0 ; i < numVerts ; i + + , tcArray + = 2 , vertArray + = 3 ) {
2020-02-23 19:07:48 +00:00
tcArray [ 0 ] + = ( table [ ( ( int ) ( ( ( vertArray [ 0 ] + vertArray [ 2 ] ) * 1.0 / 128 * 0.125 + t1 ) * TABLE_SIZE ) ) & TABLE_MASK ] * parms - > turb . params [ 1 ] + parms - > turb . params [ 0 ] ) ;
tcArray [ 1 ] + = ( table [ ( ( int ) ( ( ( vertArray [ 1 ] ) * 1.0 / 128 * 0.125 + t1 ) * TABLE_SIZE ) ) & TABLE_MASK ] * parms - > turb . params [ 1 ] + parms - > turb . params [ 0 ] ) ;
2019-03-13 19:20:07 +00:00
}
}
2020-02-23 19:07:48 +00:00
if ( parms - > scroll_x ! = 0.0f )
2019-03-13 19:20:07 +00:00
for ( tcArray = inArray , i = 0 ; i < numVerts ; i + + , tcArray + = 2 )
2020-02-23 19:07:48 +00:00
tcArray [ 0 ] + = r_newrefdef . time * parms - > scroll_x ;
if ( parms - > scroll_y ! = 0.0f )
2019-03-13 19:20:07 +00:00
for ( tcArray = inArray , i = 0 ; i < numVerts ; i + + , tcArray + = 2 )
2020-02-23 19:07:48 +00:00
tcArray [ 1 ] + = r_newrefdef . time * parms - > scroll_y ;
2019-03-13 19:20:07 +00:00
}
/*
= = = = = = = = = = = = = = = = =
RB_CheckArrayOverflow
= = = = = = = = = = = = = = = = =
*/
qboolean RB_CheckArrayOverflow ( int numVerts , int numIndex )
{
if ( rb_vertex = = 0 | | rb_index = = 0 ) return false ; // nothing to purge
if ( numVerts > MAX_VERTICES | | numIndex > MAX_INDICES )
Com_Error ( ERR_DROP , " RB_CheckArrayOverflow: %i > MAX_VERTICES or %i > MAX_INDICES " , numVerts , numIndex ) ;
if ( rb_vertex + numVerts < = MAX_VERTICES & & rb_index + numIndex < = MAX_INDICES )
return false ;
// VID_Printf(PRINT_DEVELOPER, "RB_CheckArrayOverflow: purging %i verts and %i indices to prevent overflow from %i, %i more\n", rb_vertex, rb_index, numVerts, numIndex);
return true ;
}
/*
= = = = = = = = = = = = = = = = =
RB_DrawArrays
= = = = = = = = = = = = = = = = =
*/
void RB_DrawArrays ( void )
{
if ( rb_vertex = = 0 | | rb_index = = 0 ) // nothing to render
return ;
GL_LockArrays ( rb_vertex ) ;
if ( glConfig . drawRangeElements )
qglDrawRangeElementsEXT ( GL_TRIANGLES , 0 , rb_vertex , rb_index , GL_UNSIGNED_INT , indexArray ) ;
else
qglDrawElements ( GL_TRIANGLES , rb_index , GL_UNSIGNED_INT , indexArray ) ;
GL_UnlockArrays ( ) ;
}
/*
= = = = = = = = = = = = =
RB_DrawMeshTris
Re - draws a mesh in outline mode
= = = = = = = = = = = = =
*/
void RB_DrawMeshTris ( void )
{
int i , numTMUs = 0 ;
2020-03-20 03:37:01 +00:00
if ( ! r_showtris - > integer )
2019-03-13 19:20:07 +00:00
return ;
2020-03-20 03:37:01 +00:00
if ( r_showtris - > integer = = 1 )
2019-03-13 19:20:07 +00:00
GL_Disable ( GL_DEPTH_TEST ) ;
qglPolygonMode ( GL_FRONT_AND_BACK , GL_LINE ) ;
for ( i = 0 ; i < glConfig . max_texunits ; i + + )
if ( glState . activetmu [ i ] )
{ numTMUs + + ; GL_DisableTexture ( i ) ; }
qglDisableClientState ( GL_COLOR_ARRAY ) ;
qglColor4f ( 1.0 , 1.0 , 1.0 , 1.0 ) ;
RB_DrawArrays ( ) ;
qglEnableClientState ( GL_COLOR_ARRAY ) ;
for ( i = 0 ; i < numTMUs ; i + + )
GL_EnableTexture ( i ) ;
qglPolygonMode ( GL_FRONT_AND_BACK , GL_FILL ) ;
2020-03-20 03:37:01 +00:00
if ( r_showtris - > integer = = 1 )
2019-03-13 19:20:07 +00:00
GL_Enable ( GL_DEPTH_TEST ) ;
}
/*
= = = = = = = = = = = = = = = = =
RB_RenderMeshGeneric
= = = = = = = = = = = = = = = = =
*/
void RB_RenderMeshGeneric ( qboolean drawTris )
{
RB_DrawArrays ( ) ;
if ( drawTris )
RB_DrawMeshTris ( ) ;
rb_vertex = rb_index = 0 ;
}