/* 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]; 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 ================= */ float RB_CalcGlowColor (renderparms_t parms) { float *table, rad, out=1.0f; if (parms.glow.type > -1) { 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]; out = max(min(out, 1.0f), 0.0f); // clamp } return out; } /* ================= RB_ModifyTextureCoords borrowed from EGL & Q2E ================= */ void RB_ModifyTextureCoords (float *inArray, float *inVerts, int numVerts, renderparms_t parms) { int i; float t1, t2, sint, cost, rad; float *tcArray, *vertArray, *table; if (parms.translate_x != 0.0f) for (tcArray=inArray, i=0; i -1) { 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]; t1 = (t1) ? 1.0 / t1 : 1.0; t2 = 0.5 - 0.5 * t1; for (tcArray=inArray, i=0; i -1) { table = RB_TableForFunc(&parms.turb); t1 = parms.turb.params[2] + parms.turb.params[3] * r_newrefdef.time; for (tcArray=inArray, vertArray=inVerts, i=0; i 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; 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); RB_DrawArrays(polyMode); rb_vertex = rb_index = 0; } /* ================= RB_DrawArrays ================= */ void RB_DrawArrays (GLenum polyMode) { if (rb_vertex == 0 || rb_index == 0) // nothing to render return; GL_LockArrays (rb_vertex); if (gl_config.drawRangeElements) qglDrawRangeElementsEXT(polyMode, 0, rb_vertex, rb_index, GL_UNSIGNED_INT, indexArray); else qglDrawElements(polyMode, rb_index, GL_UNSIGNED_INT, indexArray); GL_UnlockArrays (); } /* ============= RB_DrawMeshTris Re-draws a mesh in outline mode ============= */ void RB_DrawMeshTris (GLenum polyMode, int numTMUs) { int i; if (!r_showtris->value) return; if (r_showtris->value == 1) GL_Disable(GL_DEPTH_TEST); qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE); for (i=0; ivalue == 1) GL_Enable(GL_DEPTH_TEST); }