From 6bf20c78f5b69d40bcc4931df93d29198435ab67 Mon Sep 17 00:00:00 2001 From: zakk Date: Fri, 26 Aug 2005 17:39:27 +0000 Subject: newlines fixed git-svn-id: svn://svn.icculus.org/quake3/trunk@6 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/renderer/tr_sky.c | 1690 ++++++++++++++++++++++++------------------------ 1 file changed, 845 insertions(+), 845 deletions(-) (limited to 'code/renderer/tr_sky.c') diff --git a/code/renderer/tr_sky.c b/code/renderer/tr_sky.c index 0f8aa24..1f92378 100755 --- a/code/renderer/tr_sky.c +++ b/code/renderer/tr_sky.c @@ -1,845 +1,845 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_sky.c -#include "tr_local.h" - -#define SKY_SUBDIVISIONS 8 -#define HALF_SKY_SUBDIVISIONS (SKY_SUBDIVISIONS/2) - -static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; -static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; - -/* -=================================================================================== - -POLYGON TO BOX SIDE PROJECTION - -=================================================================================== -*/ - -static vec3_t sky_clip[6] = -{ - {1,1,0}, - {1,-1,0}, - {0,-1,1}, - {0,1,1}, - {1,0,1}, - {-1,0,1} -}; - -static float sky_mins[2][6], sky_maxs[2][6]; -static float sky_min, sky_max; - -/* -================ -AddSkyPolygon -================ -*/ -static void AddSkyPolygon (int nump, vec3_t vecs) -{ - int i,j; - vec3_t v, av; - float s, t, dv; - int axis; - float *vp; - // s = [0]/[2], t = [1]/[2] - static int vec_to_st[6][3] = - { - {-2,3,1}, - {2,3,-1}, - - {1,3,2}, - {-1,3,-2}, - - {-2,-1,3}, - {-2,1,-3} - - // {-1,2,3}, - // {1,2,-3} - }; - - // decide which face it maps to - VectorCopy (vec3_origin, v); - for (i=0, vp=vecs ; i av[1] && av[0] > av[2]) - { - if (v[0] < 0) - axis = 1; - else - axis = 0; - } - else if (av[1] > av[2] && av[1] > av[0]) - { - if (v[1] < 0) - axis = 3; - else - axis = 2; - } - else - { - if (v[2] < 0) - axis = 5; - else - axis = 4; - } - - // project new texture coords - for (i=0 ; i 0) - dv = vecs[j - 1]; - else - dv = -vecs[-j - 1]; - if (dv < 0.001) - continue; // don't divide by zero - j = vec_to_st[axis][0]; - if (j < 0) - s = -vecs[-j -1] / dv; - else - s = vecs[j-1] / dv; - j = vec_to_st[axis][1]; - if (j < 0) - t = -vecs[-j -1] / dv; - else - t = vecs[j-1] / dv; - - if (s < sky_mins[0][axis]) - sky_mins[0][axis] = s; - if (t < sky_mins[1][axis]) - sky_mins[1][axis] = t; - if (s > sky_maxs[0][axis]) - sky_maxs[0][axis] = s; - if (t > sky_maxs[1][axis]) - sky_maxs[1][axis] = t; - } -} - -#define ON_EPSILON 0.1f // point on plane side epsilon -#define MAX_CLIP_VERTS 64 -/* -================ -ClipSkyPolygon -================ -*/ -static void ClipSkyPolygon (int nump, vec3_t vecs, int stage) -{ - float *norm; - float *v; - qboolean front, back; - float d, e; - float dists[MAX_CLIP_VERTS]; - int sides[MAX_CLIP_VERTS]; - vec3_t newv[2][MAX_CLIP_VERTS]; - int newc[2]; - int i, j; - - if (nump > MAX_CLIP_VERTS-2) - ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS"); - if (stage == 6) - { // fully clipped, so draw it - AddSkyPolygon (nump, vecs); - return; - } - - front = back = qfalse; - norm = sky_clip[stage]; - for (i=0, v = vecs ; i ON_EPSILON) - { - front = qtrue; - sides[i] = SIDE_FRONT; - } - else if (d < -ON_EPSILON) - { - back = qtrue; - sides[i] = SIDE_BACK; - } - else - sides[i] = SIDE_ON; - dists[i] = d; - } - - if (!front || !back) - { // not clipped - ClipSkyPolygon (nump, vecs, stage+1); - return; - } - - // clip it - sides[i] = sides[0]; - dists[i] = dists[0]; - VectorCopy (vecs, (vecs+(i*3)) ); - newc[0] = newc[1] = 0; - - for (i=0, v = vecs ; inumIndexes; i += 3 ) - { - for (j = 0 ; j < 3 ; j++) - { - VectorSubtract( input->xyz[input->indexes[i+j]], - backEnd.viewParms.or.origin, - p[j] ); - } - ClipSkyPolygon( 3, p[0], 0 ); - } -} - -/* -=================================================================================== - -CLOUD VERTEX GENERATION - -=================================================================================== -*/ - -/* -** MakeSkyVec -** -** Parms: s, t range from -1 to 1 -*/ -static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXYZ ) -{ - // 1 = s, 2 = t, 3 = 2048 - static int st_to_vec[6][3] = - { - {3,-1,2}, - {-3,1,2}, - - {1,3,2}, - {-1,-3,2}, - - {-2,-1,3}, // 0 degrees yaw, look straight up - {2,-1,-3} // look straight down - }; - - vec3_t b; - int j, k; - float boxSize; - - boxSize = backEnd.viewParms.zFar / 1.75; // div sqrt(3) - b[0] = s*boxSize; - b[1] = t*boxSize; - b[2] = boxSize; - - for (j=0 ; j<3 ; j++) - { - k = st_to_vec[axis][j]; - if (k < 0) - { - outXYZ[j] = -b[-k - 1]; - } - else - { - outXYZ[j] = b[k - 1]; - } - } - - // avoid bilerp seam - s = (s+1)*0.5; - t = (t+1)*0.5; - if (s < sky_min) - { - s = sky_min; - } - else if (s > sky_max) - { - s = sky_max; - } - - if (t < sky_min) - { - t = sky_min; - } - else if (t > sky_max) - { - t = sky_max; - } - - t = 1.0 - t; - - - if ( outSt ) - { - outSt[0] = s; - outSt[1] = t; - } -} - -static int sky_texorder[6] = {0,2,1,3,4,5}; -static vec3_t s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; -static float s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; - -static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] ) -{ - int s, t; - - GL_Bind( image ); - - for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) - { - qglBegin( GL_TRIANGLE_STRIP ); - - for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) - { - qglTexCoord2fv( s_skyTexCoords[t][s] ); - qglVertex3fv( s_skyPoints[t][s] ); - - qglTexCoord2fv( s_skyTexCoords[t+1][s] ); - qglVertex3fv( s_skyPoints[t+1][s] ); - } - - qglEnd(); - } -} - -static void DrawSkyBox( shader_t *shader ) -{ - int i; - - sky_min = 0; - sky_max = 1; - - Com_Memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) ); - - for (i=0 ; i<6 ; i++) - { - int sky_mins_subd[2], sky_maxs_subd[2]; - int s, t; - - sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - - if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) || - ( sky_mins[1][i] >= sky_maxs[1][i] ) ) - { - continue; - } - - sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS; - sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS; - sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS; - sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS; - - if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS; - if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS; - - if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS; - if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; - - // - // iterate through the subdivisions - // - for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) - { - for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) - { - MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - i, - s_skyTexCoords[t][s], - s_skyPoints[t][s] ); - } - } - - DrawSkySide( shader->sky.outerbox[sky_texorder[i]], - sky_mins_subd, - sky_maxs_subd ); - } - -} - -static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes ) -{ - int s, t; - int vertexStart = tess.numVertexes; - int tHeight, sWidth; - - tHeight = maxs[1] - mins[1] + 1; - sWidth = maxs[0] - mins[0] + 1; - - for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) - { - for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) - { - VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0]; - tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1]; - - tess.numVertexes++; - - if ( tess.numVertexes >= SHADER_MAX_VERTEXES ) - { - ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()\n" ); - } - } - } - - // only add indexes for one pass, otherwise it would draw multiple times for each pass - if ( addIndexes ) { - for ( t = 0; t < tHeight-1; t++ ) - { - for ( s = 0; s < sWidth-1; s++ ) - { - tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth ); - tess.numIndexes++; - tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); - tess.numIndexes++; - tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); - tess.numIndexes++; - - tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); - tess.numIndexes++; - tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth ); - tess.numIndexes++; - tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); - tess.numIndexes++; - } - } - } -} - -static void FillCloudBox( const shader_t *shader, int stage ) -{ - int i; - - for ( i =0; i < 6; i++ ) - { - int sky_mins_subd[2], sky_maxs_subd[2]; - int s, t; - float MIN_T; - - if ( 1 ) // FIXME? shader->sky.fullClouds ) - { - MIN_T = -HALF_SKY_SUBDIVISIONS; - - // still don't want to draw the bottom, even if fullClouds - if ( i == 5 ) - continue; - } - else - { - switch( i ) - { - case 0: - case 1: - case 2: - case 3: - MIN_T = -1; - break; - case 5: - // don't draw clouds beneath you - continue; - case 4: // top - default: - MIN_T = -HALF_SKY_SUBDIVISIONS; - break; - } - } - - sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - - if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) || - ( sky_mins[1][i] >= sky_maxs[1][i] ) ) - { - continue; - } - - sky_mins_subd[0] = myftol( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ); - sky_mins_subd[1] = myftol( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ); - sky_maxs_subd[0] = myftol( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ); - sky_maxs_subd[1] = myftol( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ); - - if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS; - if ( sky_mins_subd[1] < MIN_T ) - sky_mins_subd[1] = MIN_T; - else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS; - - if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS; - if ( sky_maxs_subd[1] < MIN_T ) - sky_maxs_subd[1] = MIN_T; - else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; - - // - // iterate through the subdivisions - // - for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) - { - for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) - { - MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - i, - NULL, - s_skyPoints[t][s] ); - - s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0]; - s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1]; - } - } - - // only add indexes for first stage - FillCloudySkySide( sky_mins_subd, sky_maxs_subd, ( stage == 0 ) ); - } -} - -/* -** R_BuildCloudData -*/ -void R_BuildCloudData( shaderCommands_t *input ) -{ - int i; - shader_t *shader; - - shader = input->shader; - - assert( shader->isSky ); - - sky_min = 1.0 / 256.0f; // FIXME: not correct? - sky_max = 255.0 / 256.0f; - - // set up for drawing - tess.numIndexes = 0; - tess.numVertexes = 0; - - if ( input->shader->sky.cloudHeight ) - { - for ( i = 0; i < MAX_SHADER_STAGES; i++ ) - { - if ( !tess.xstages[i] ) { - break; - } - FillCloudBox( input->shader, i ); - } - } -} - -/* -** R_InitSkyTexCoords -** Called when a sky shader is parsed -*/ -#define SQR( a ) ((a)*(a)) -void R_InitSkyTexCoords( float heightCloud ) -{ - int i, s, t; - float radiusWorld = 4096; - float p; - float sRad, tRad; - vec3_t skyVec; - vec3_t v; - - // init zfar so MakeSkyVec works even though - // a world hasn't been bounded - backEnd.viewParms.zFar = 1024; - - for ( i = 0; i < 6; i++ ) - { - for ( t = 0; t <= SKY_SUBDIVISIONS; t++ ) - { - for ( s = 0; s <= SKY_SUBDIVISIONS; s++ ) - { - // compute vector from view origin to sky side integral point - MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - i, - NULL, - skyVec ); - - // compute parametric value 'p' that intersects with cloud layer - p = ( 1.0f / ( 2 * DotProduct( skyVec, skyVec ) ) ) * - ( -2 * skyVec[2] * radiusWorld + - 2 * sqrt( SQR( skyVec[2] ) * SQR( radiusWorld ) + - 2 * SQR( skyVec[0] ) * radiusWorld * heightCloud + - SQR( skyVec[0] ) * SQR( heightCloud ) + - 2 * SQR( skyVec[1] ) * radiusWorld * heightCloud + - SQR( skyVec[1] ) * SQR( heightCloud ) + - 2 * SQR( skyVec[2] ) * radiusWorld * heightCloud + - SQR( skyVec[2] ) * SQR( heightCloud ) ) ); - - s_cloudTexP[i][t][s] = p; - - // compute intersection point based on p - VectorScale( skyVec, p, v ); - v[2] += radiusWorld; - - // compute vector from world origin to intersection point 'v' - VectorNormalize( v ); - - sRad = Q_acos( v[0] ); - tRad = Q_acos( v[1] ); - - s_cloudTexCoords[i][t][s][0] = sRad; - s_cloudTexCoords[i][t][s][1] = tRad; - } - } - } -} - -//====================================================================================== - -/* -** RB_DrawSun -*/ -void RB_DrawSun( void ) { - float size; - float dist; - vec3_t origin, vec1, vec2; - vec3_t temp; - - if ( !backEnd.skyRenderedThisView ) { - return; - } - if ( !r_drawSun->integer ) { - return; - } - qglLoadMatrixf( backEnd.viewParms.world.modelMatrix ); - qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); - - dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3) - size = dist * 0.4; - - VectorScale( tr.sunDirection, dist, origin ); - PerpendicularVector( vec1, tr.sunDirection ); - CrossProduct( tr.sunDirection, vec1, vec2 ); - - VectorScale( vec1, size, vec1 ); - VectorScale( vec2, size, vec2 ); - - // farthest depth range - qglDepthRange( 1.0, 1.0 ); - - // FIXME: use quad stamp - RB_BeginSurface( tr.sunShader, tess.fogNum ); - VectorCopy( origin, temp ); - VectorSubtract( temp, vec1, temp ); - VectorSubtract( temp, vec2, temp ); - VectorCopy( temp, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = 255; - tess.vertexColors[tess.numVertexes][1] = 255; - tess.vertexColors[tess.numVertexes][2] = 255; - tess.numVertexes++; - - VectorCopy( origin, temp ); - VectorAdd( temp, vec1, temp ); - VectorSubtract( temp, vec2, temp ); - VectorCopy( temp, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = 255; - tess.vertexColors[tess.numVertexes][1] = 255; - tess.vertexColors[tess.numVertexes][2] = 255; - tess.numVertexes++; - - VectorCopy( origin, temp ); - VectorAdd( temp, vec1, temp ); - VectorAdd( temp, vec2, temp ); - VectorCopy( temp, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 1; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = 255; - tess.vertexColors[tess.numVertexes][1] = 255; - tess.vertexColors[tess.numVertexes][2] = 255; - tess.numVertexes++; - - VectorCopy( origin, temp ); - VectorSubtract( temp, vec1, temp ); - VectorAdd( temp, vec2, temp ); - VectorCopy( temp, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 1; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = 255; - tess.vertexColors[tess.numVertexes][1] = 255; - tess.vertexColors[tess.numVertexes][2] = 255; - tess.numVertexes++; - - tess.indexes[tess.numIndexes++] = 0; - tess.indexes[tess.numIndexes++] = 1; - tess.indexes[tess.numIndexes++] = 2; - tess.indexes[tess.numIndexes++] = 0; - tess.indexes[tess.numIndexes++] = 2; - tess.indexes[tess.numIndexes++] = 3; - - RB_EndSurface(); - - // back to normal depth range - qglDepthRange( 0.0, 1.0 ); -} - - - - -/* -================ -RB_StageIteratorSky - -All of the visible sky triangles are in tess - -Other things could be stuck in here, like birds in the sky, etc -================ -*/ -void RB_StageIteratorSky( void ) { - if ( r_fastsky->integer ) { - return; - } - - // go through all the polygons and project them onto - // the sky box to see which blocks on each side need - // to be drawn - RB_ClipSkyPolygons( &tess ); - - // r_showsky will let all the sky blocks be drawn in - // front of everything to allow developers to see how - // much sky is getting sucked in - if ( r_showsky->integer ) { - qglDepthRange( 0.0, 0.0 ); - } else { - qglDepthRange( 1.0, 1.0 ); - } - - // draw the outer skybox - if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { - qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); - - qglPushMatrix (); - GL_State( 0 ); - qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); - - DrawSkyBox( tess.shader ); - - qglPopMatrix(); - } - - // generate the vertexes for all the clouds, which will be drawn - // by the generic shader routine - R_BuildCloudData( &tess ); - - RB_StageIteratorGeneric(); - - // draw the inner skybox - - - // back to normal depth range - qglDepthRange( 0.0, 1.0 ); - - // note that sky was drawn so we will draw a sun later - backEnd.skyRenderedThisView = qtrue; -} - +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code 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. + +Quake III Arena source code 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 Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// tr_sky.c +#include "tr_local.h" + +#define SKY_SUBDIVISIONS 8 +#define HALF_SKY_SUBDIVISIONS (SKY_SUBDIVISIONS/2) + +static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; +static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; + +/* +=================================================================================== + +POLYGON TO BOX SIDE PROJECTION + +=================================================================================== +*/ + +static vec3_t sky_clip[6] = +{ + {1,1,0}, + {1,-1,0}, + {0,-1,1}, + {0,1,1}, + {1,0,1}, + {-1,0,1} +}; + +static float sky_mins[2][6], sky_maxs[2][6]; +static float sky_min, sky_max; + +/* +================ +AddSkyPolygon +================ +*/ +static void AddSkyPolygon (int nump, vec3_t vecs) +{ + int i,j; + vec3_t v, av; + float s, t, dv; + int axis; + float *vp; + // s = [0]/[2], t = [1]/[2] + static int vec_to_st[6][3] = + { + {-2,3,1}, + {2,3,-1}, + + {1,3,2}, + {-1,3,-2}, + + {-2,-1,3}, + {-2,1,-3} + + // {-1,2,3}, + // {1,2,-3} + }; + + // decide which face it maps to + VectorCopy (vec3_origin, v); + for (i=0, vp=vecs ; i av[1] && av[0] > av[2]) + { + if (v[0] < 0) + axis = 1; + else + axis = 0; + } + else if (av[1] > av[2] && av[1] > av[0]) + { + if (v[1] < 0) + axis = 3; + else + axis = 2; + } + else + { + if (v[2] < 0) + axis = 5; + else + axis = 4; + } + + // project new texture coords + for (i=0 ; i 0) + dv = vecs[j - 1]; + else + dv = -vecs[-j - 1]; + if (dv < 0.001) + continue; // don't divide by zero + j = vec_to_st[axis][0]; + if (j < 0) + s = -vecs[-j -1] / dv; + else + s = vecs[j-1] / dv; + j = vec_to_st[axis][1]; + if (j < 0) + t = -vecs[-j -1] / dv; + else + t = vecs[j-1] / dv; + + if (s < sky_mins[0][axis]) + sky_mins[0][axis] = s; + if (t < sky_mins[1][axis]) + sky_mins[1][axis] = t; + if (s > sky_maxs[0][axis]) + sky_maxs[0][axis] = s; + if (t > sky_maxs[1][axis]) + sky_maxs[1][axis] = t; + } +} + +#define ON_EPSILON 0.1f // point on plane side epsilon +#define MAX_CLIP_VERTS 64 +/* +================ +ClipSkyPolygon +================ +*/ +static void ClipSkyPolygon (int nump, vec3_t vecs, int stage) +{ + float *norm; + float *v; + qboolean front, back; + float d, e; + float dists[MAX_CLIP_VERTS]; + int sides[MAX_CLIP_VERTS]; + vec3_t newv[2][MAX_CLIP_VERTS]; + int newc[2]; + int i, j; + + if (nump > MAX_CLIP_VERTS-2) + ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS"); + if (stage == 6) + { // fully clipped, so draw it + AddSkyPolygon (nump, vecs); + return; + } + + front = back = qfalse; + norm = sky_clip[stage]; + for (i=0, v = vecs ; i ON_EPSILON) + { + front = qtrue; + sides[i] = SIDE_FRONT; + } + else if (d < -ON_EPSILON) + { + back = qtrue; + sides[i] = SIDE_BACK; + } + else + sides[i] = SIDE_ON; + dists[i] = d; + } + + if (!front || !back) + { // not clipped + ClipSkyPolygon (nump, vecs, stage+1); + return; + } + + // clip it + sides[i] = sides[0]; + dists[i] = dists[0]; + VectorCopy (vecs, (vecs+(i*3)) ); + newc[0] = newc[1] = 0; + + for (i=0, v = vecs ; inumIndexes; i += 3 ) + { + for (j = 0 ; j < 3 ; j++) + { + VectorSubtract( input->xyz[input->indexes[i+j]], + backEnd.viewParms.or.origin, + p[j] ); + } + ClipSkyPolygon( 3, p[0], 0 ); + } +} + +/* +=================================================================================== + +CLOUD VERTEX GENERATION + +=================================================================================== +*/ + +/* +** MakeSkyVec +** +** Parms: s, t range from -1 to 1 +*/ +static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXYZ ) +{ + // 1 = s, 2 = t, 3 = 2048 + static int st_to_vec[6][3] = + { + {3,-1,2}, + {-3,1,2}, + + {1,3,2}, + {-1,-3,2}, + + {-2,-1,3}, // 0 degrees yaw, look straight up + {2,-1,-3} // look straight down + }; + + vec3_t b; + int j, k; + float boxSize; + + boxSize = backEnd.viewParms.zFar / 1.75; // div sqrt(3) + b[0] = s*boxSize; + b[1] = t*boxSize; + b[2] = boxSize; + + for (j=0 ; j<3 ; j++) + { + k = st_to_vec[axis][j]; + if (k < 0) + { + outXYZ[j] = -b[-k - 1]; + } + else + { + outXYZ[j] = b[k - 1]; + } + } + + // avoid bilerp seam + s = (s+1)*0.5; + t = (t+1)*0.5; + if (s < sky_min) + { + s = sky_min; + } + else if (s > sky_max) + { + s = sky_max; + } + + if (t < sky_min) + { + t = sky_min; + } + else if (t > sky_max) + { + t = sky_max; + } + + t = 1.0 - t; + + + if ( outSt ) + { + outSt[0] = s; + outSt[1] = t; + } +} + +static int sky_texorder[6] = {0,2,1,3,4,5}; +static vec3_t s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; +static float s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; + +static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] ) +{ + int s, t; + + GL_Bind( image ); + + for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) + { + qglBegin( GL_TRIANGLE_STRIP ); + + for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) + { + qglTexCoord2fv( s_skyTexCoords[t][s] ); + qglVertex3fv( s_skyPoints[t][s] ); + + qglTexCoord2fv( s_skyTexCoords[t+1][s] ); + qglVertex3fv( s_skyPoints[t+1][s] ); + } + + qglEnd(); + } +} + +static void DrawSkyBox( shader_t *shader ) +{ + int i; + + sky_min = 0; + sky_max = 1; + + Com_Memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) ); + + for (i=0 ; i<6 ; i++) + { + int sky_mins_subd[2], sky_maxs_subd[2]; + int s, t; + + sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + + if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) || + ( sky_mins[1][i] >= sky_maxs[1][i] ) ) + { + continue; + } + + sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS; + sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS; + sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS; + sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS; + + if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS ) + sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS; + else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS ) + sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS; + if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS ) + sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS; + else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS ) + sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS; + + if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS ) + sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS; + else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS ) + sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS; + if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS ) + sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS; + else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) + sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; + + // + // iterate through the subdivisions + // + for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) + { + for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) + { + MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + i, + s_skyTexCoords[t][s], + s_skyPoints[t][s] ); + } + } + + DrawSkySide( shader->sky.outerbox[sky_texorder[i]], + sky_mins_subd, + sky_maxs_subd ); + } + +} + +static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes ) +{ + int s, t; + int vertexStart = tess.numVertexes; + int tHeight, sWidth; + + tHeight = maxs[1] - mins[1] + 1; + sWidth = maxs[0] - mins[0] + 1; + + for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) + { + for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) + { + VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] ); + tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0]; + tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1]; + + tess.numVertexes++; + + if ( tess.numVertexes >= SHADER_MAX_VERTEXES ) + { + ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()\n" ); + } + } + } + + // only add indexes for one pass, otherwise it would draw multiple times for each pass + if ( addIndexes ) { + for ( t = 0; t < tHeight-1; t++ ) + { + for ( s = 0; s < sWidth-1; s++ ) + { + tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth ); + tess.numIndexes++; + tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); + tess.numIndexes++; + tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); + tess.numIndexes++; + + tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); + tess.numIndexes++; + tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth ); + tess.numIndexes++; + tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); + tess.numIndexes++; + } + } + } +} + +static void FillCloudBox( const shader_t *shader, int stage ) +{ + int i; + + for ( i =0; i < 6; i++ ) + { + int sky_mins_subd[2], sky_maxs_subd[2]; + int s, t; + float MIN_T; + + if ( 1 ) // FIXME? shader->sky.fullClouds ) + { + MIN_T = -HALF_SKY_SUBDIVISIONS; + + // still don't want to draw the bottom, even if fullClouds + if ( i == 5 ) + continue; + } + else + { + switch( i ) + { + case 0: + case 1: + case 2: + case 3: + MIN_T = -1; + break; + case 5: + // don't draw clouds beneath you + continue; + case 4: // top + default: + MIN_T = -HALF_SKY_SUBDIVISIONS; + break; + } + } + + sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + + if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) || + ( sky_mins[1][i] >= sky_maxs[1][i] ) ) + { + continue; + } + + sky_mins_subd[0] = myftol( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ); + sky_mins_subd[1] = myftol( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ); + sky_maxs_subd[0] = myftol( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ); + sky_maxs_subd[1] = myftol( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ); + + if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS ) + sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS; + else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS ) + sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS; + if ( sky_mins_subd[1] < MIN_T ) + sky_mins_subd[1] = MIN_T; + else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS ) + sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS; + + if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS ) + sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS; + else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS ) + sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS; + if ( sky_maxs_subd[1] < MIN_T ) + sky_maxs_subd[1] = MIN_T; + else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) + sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; + + // + // iterate through the subdivisions + // + for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) + { + for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) + { + MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + i, + NULL, + s_skyPoints[t][s] ); + + s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0]; + s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1]; + } + } + + // only add indexes for first stage + FillCloudySkySide( sky_mins_subd, sky_maxs_subd, ( stage == 0 ) ); + } +} + +/* +** R_BuildCloudData +*/ +void R_BuildCloudData( shaderCommands_t *input ) +{ + int i; + shader_t *shader; + + shader = input->shader; + + assert( shader->isSky ); + + sky_min = 1.0 / 256.0f; // FIXME: not correct? + sky_max = 255.0 / 256.0f; + + // set up for drawing + tess.numIndexes = 0; + tess.numVertexes = 0; + + if ( input->shader->sky.cloudHeight ) + { + for ( i = 0; i < MAX_SHADER_STAGES; i++ ) + { + if ( !tess.xstages[i] ) { + break; + } + FillCloudBox( input->shader, i ); + } + } +} + +/* +** R_InitSkyTexCoords +** Called when a sky shader is parsed +*/ +#define SQR( a ) ((a)*(a)) +void R_InitSkyTexCoords( float heightCloud ) +{ + int i, s, t; + float radiusWorld = 4096; + float p; + float sRad, tRad; + vec3_t skyVec; + vec3_t v; + + // init zfar so MakeSkyVec works even though + // a world hasn't been bounded + backEnd.viewParms.zFar = 1024; + + for ( i = 0; i < 6; i++ ) + { + for ( t = 0; t <= SKY_SUBDIVISIONS; t++ ) + { + for ( s = 0; s <= SKY_SUBDIVISIONS; s++ ) + { + // compute vector from view origin to sky side integral point + MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + i, + NULL, + skyVec ); + + // compute parametric value 'p' that intersects with cloud layer + p = ( 1.0f / ( 2 * DotProduct( skyVec, skyVec ) ) ) * + ( -2 * skyVec[2] * radiusWorld + + 2 * sqrt( SQR( skyVec[2] ) * SQR( radiusWorld ) + + 2 * SQR( skyVec[0] ) * radiusWorld * heightCloud + + SQR( skyVec[0] ) * SQR( heightCloud ) + + 2 * SQR( skyVec[1] ) * radiusWorld * heightCloud + + SQR( skyVec[1] ) * SQR( heightCloud ) + + 2 * SQR( skyVec[2] ) * radiusWorld * heightCloud + + SQR( skyVec[2] ) * SQR( heightCloud ) ) ); + + s_cloudTexP[i][t][s] = p; + + // compute intersection point based on p + VectorScale( skyVec, p, v ); + v[2] += radiusWorld; + + // compute vector from world origin to intersection point 'v' + VectorNormalize( v ); + + sRad = Q_acos( v[0] ); + tRad = Q_acos( v[1] ); + + s_cloudTexCoords[i][t][s][0] = sRad; + s_cloudTexCoords[i][t][s][1] = tRad; + } + } + } +} + +//====================================================================================== + +/* +** RB_DrawSun +*/ +void RB_DrawSun( void ) { + float size; + float dist; + vec3_t origin, vec1, vec2; + vec3_t temp; + + if ( !backEnd.skyRenderedThisView ) { + return; + } + if ( !r_drawSun->integer ) { + return; + } + qglLoadMatrixf( backEnd.viewParms.world.modelMatrix ); + qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); + + dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3) + size = dist * 0.4; + + VectorScale( tr.sunDirection, dist, origin ); + PerpendicularVector( vec1, tr.sunDirection ); + CrossProduct( tr.sunDirection, vec1, vec2 ); + + VectorScale( vec1, size, vec1 ); + VectorScale( vec2, size, vec2 ); + + // farthest depth range + qglDepthRange( 1.0, 1.0 ); + + // FIXME: use quad stamp + RB_BeginSurface( tr.sunShader, tess.fogNum ); + VectorCopy( origin, temp ); + VectorSubtract( temp, vec1, temp ); + VectorSubtract( temp, vec2, temp ); + VectorCopy( temp, tess.xyz[tess.numVertexes] ); + tess.texCoords[tess.numVertexes][0][0] = 0; + tess.texCoords[tess.numVertexes][0][1] = 0; + tess.vertexColors[tess.numVertexes][0] = 255; + tess.vertexColors[tess.numVertexes][1] = 255; + tess.vertexColors[tess.numVertexes][2] = 255; + tess.numVertexes++; + + VectorCopy( origin, temp ); + VectorAdd( temp, vec1, temp ); + VectorSubtract( temp, vec2, temp ); + VectorCopy( temp, tess.xyz[tess.numVertexes] ); + tess.texCoords[tess.numVertexes][0][0] = 0; + tess.texCoords[tess.numVertexes][0][1] = 1; + tess.vertexColors[tess.numVertexes][0] = 255; + tess.vertexColors[tess.numVertexes][1] = 255; + tess.vertexColors[tess.numVertexes][2] = 255; + tess.numVertexes++; + + VectorCopy( origin, temp ); + VectorAdd( temp, vec1, temp ); + VectorAdd( temp, vec2, temp ); + VectorCopy( temp, tess.xyz[tess.numVertexes] ); + tess.texCoords[tess.numVertexes][0][0] = 1; + tess.texCoords[tess.numVertexes][0][1] = 1; + tess.vertexColors[tess.numVertexes][0] = 255; + tess.vertexColors[tess.numVertexes][1] = 255; + tess.vertexColors[tess.numVertexes][2] = 255; + tess.numVertexes++; + + VectorCopy( origin, temp ); + VectorSubtract( temp, vec1, temp ); + VectorAdd( temp, vec2, temp ); + VectorCopy( temp, tess.xyz[tess.numVertexes] ); + tess.texCoords[tess.numVertexes][0][0] = 1; + tess.texCoords[tess.numVertexes][0][1] = 0; + tess.vertexColors[tess.numVertexes][0] = 255; + tess.vertexColors[tess.numVertexes][1] = 255; + tess.vertexColors[tess.numVertexes][2] = 255; + tess.numVertexes++; + + tess.indexes[tess.numIndexes++] = 0; + tess.indexes[tess.numIndexes++] = 1; + tess.indexes[tess.numIndexes++] = 2; + tess.indexes[tess.numIndexes++] = 0; + tess.indexes[tess.numIndexes++] = 2; + tess.indexes[tess.numIndexes++] = 3; + + RB_EndSurface(); + + // back to normal depth range + qglDepthRange( 0.0, 1.0 ); +} + + + + +/* +================ +RB_StageIteratorSky + +All of the visible sky triangles are in tess + +Other things could be stuck in here, like birds in the sky, etc +================ +*/ +void RB_StageIteratorSky( void ) { + if ( r_fastsky->integer ) { + return; + } + + // go through all the polygons and project them onto + // the sky box to see which blocks on each side need + // to be drawn + RB_ClipSkyPolygons( &tess ); + + // r_showsky will let all the sky blocks be drawn in + // front of everything to allow developers to see how + // much sky is getting sucked in + if ( r_showsky->integer ) { + qglDepthRange( 0.0, 0.0 ); + } else { + qglDepthRange( 1.0, 1.0 ); + } + + // draw the outer skybox + if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { + qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); + + qglPushMatrix (); + GL_State( 0 ); + qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); + + DrawSkyBox( tess.shader ); + + qglPopMatrix(); + } + + // generate the vertexes for all the clouds, which will be drawn + // by the generic shader routine + R_BuildCloudData( &tess ); + + RB_StageIteratorGeneric(); + + // draw the inner skybox + + + // back to normal depth range + qglDepthRange( 0.0, 1.0 ); + + // note that sky was drawn so we will draw a sun later + backEnd.skyRenderedThisView = qtrue; +} + -- cgit v1.2.3