Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tr_sky.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // tr_sky.c
00023 #include "tr_local.h"
00024 
00025 #define SKY_SUBDIVISIONS        8
00026 #define HALF_SKY_SUBDIVISIONS   (SKY_SUBDIVISIONS/2)
00027 
00028 static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
00029 static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
00030 
00031 /*
00032 ===================================================================================
00033 
00034 POLYGON TO BOX SIDE PROJECTION
00035 
00036 ===================================================================================
00037 */
00038 
00039 static vec3_t sky_clip[6] = 
00040 {
00041     {1,1,0},
00042     {1,-1,0},
00043     {0,-1,1},
00044     {0,1,1},
00045     {1,0,1},
00046     {-1,0,1} 
00047 };
00048 
00049 static float    sky_mins[2][6], sky_maxs[2][6];
00050 static float    sky_min, sky_max;
00051 
00052 /*
00053 ================
00054 AddSkyPolygon
00055 ================
00056 */
00057 static void AddSkyPolygon (int nump, vec3_t vecs) 
00058 {
00059     int     i,j;
00060     vec3_t  v, av;
00061     float   s, t, dv;
00062     int     axis;
00063     float   *vp;
00064     // s = [0]/[2], t = [1]/[2]
00065     static int  vec_to_st[6][3] =
00066     {
00067         {-2,3,1},
00068         {2,3,-1},
00069 
00070         {1,3,2},
00071         {-1,3,-2},
00072 
00073         {-2,-1,3},
00074         {-2,1,-3}
00075 
00076     //  {-1,2,3},
00077     //  {1,2,-3}
00078     };
00079 
00080     // decide which face it maps to
00081     VectorCopy (vec3_origin, v);
00082     for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
00083     {
00084         VectorAdd (vp, v, v);
00085     }
00086     av[0] = fabs(v[0]);
00087     av[1] = fabs(v[1]);
00088     av[2] = fabs(v[2]);
00089     if (av[0] > av[1] && av[0] > av[2])
00090     {
00091         if (v[0] < 0)
00092             axis = 1;
00093         else
00094             axis = 0;
00095     }
00096     else if (av[1] > av[2] && av[1] > av[0])
00097     {
00098         if (v[1] < 0)
00099             axis = 3;
00100         else
00101             axis = 2;
00102     }
00103     else
00104     {
00105         if (v[2] < 0)
00106             axis = 5;
00107         else
00108             axis = 4;
00109     }
00110 
00111     // project new texture coords
00112     for (i=0 ; i<nump ; i++, vecs+=3)
00113     {
00114         j = vec_to_st[axis][2];
00115         if (j > 0)
00116             dv = vecs[j - 1];
00117         else
00118             dv = -vecs[-j - 1];
00119         if (dv < 0.001)
00120             continue;   // don't divide by zero
00121         j = vec_to_st[axis][0];
00122         if (j < 0)
00123             s = -vecs[-j -1] / dv;
00124         else
00125             s = vecs[j-1] / dv;
00126         j = vec_to_st[axis][1];
00127         if (j < 0)
00128             t = -vecs[-j -1] / dv;
00129         else
00130             t = vecs[j-1] / dv;
00131 
00132         if (s < sky_mins[0][axis])
00133             sky_mins[0][axis] = s;
00134         if (t < sky_mins[1][axis])
00135             sky_mins[1][axis] = t;
00136         if (s > sky_maxs[0][axis])
00137             sky_maxs[0][axis] = s;
00138         if (t > sky_maxs[1][axis])
00139             sky_maxs[1][axis] = t;
00140     }
00141 }
00142 
00143 #define ON_EPSILON      0.1f            // point on plane side epsilon
00144 #define MAX_CLIP_VERTS  64
00145 /*
00146 ================
00147 ClipSkyPolygon
00148 ================
00149 */
00150 static void ClipSkyPolygon (int nump, vec3_t vecs, int stage) 
00151 {
00152     float   *norm;
00153     float   *v;
00154     qboolean    front, back;
00155     float   d, e;
00156     float   dists[MAX_CLIP_VERTS];
00157     int     sides[MAX_CLIP_VERTS];
00158     vec3_t  newv[2][MAX_CLIP_VERTS];
00159     int     newc[2];
00160     int     i, j;
00161 
00162     if (nump > MAX_CLIP_VERTS-2)
00163         ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
00164     if (stage == 6)
00165     {   // fully clipped, so draw it
00166         AddSkyPolygon (nump, vecs);
00167         return;
00168     }
00169 
00170     front = back = qfalse;
00171     norm = sky_clip[stage];
00172     for (i=0, v = vecs ; i<nump ; i++, v+=3)
00173     {
00174         d = DotProduct (v, norm);
00175         if (d > ON_EPSILON)
00176         {
00177             front = qtrue;
00178             sides[i] = SIDE_FRONT;
00179         }
00180         else if (d < -ON_EPSILON)
00181         {
00182             back = qtrue;
00183             sides[i] = SIDE_BACK;
00184         }
00185         else
00186             sides[i] = SIDE_ON;
00187         dists[i] = d;
00188     }
00189 
00190     if (!front || !back)
00191     {   // not clipped
00192         ClipSkyPolygon (nump, vecs, stage+1);
00193         return;
00194     }
00195 
00196     // clip it
00197     sides[i] = sides[0];
00198     dists[i] = dists[0];
00199     VectorCopy (vecs, (vecs+(i*3)) );
00200     newc[0] = newc[1] = 0;
00201 
00202     for (i=0, v = vecs ; i<nump ; i++, v+=3)
00203     {
00204         switch (sides[i])
00205         {
00206         case SIDE_FRONT:
00207             VectorCopy (v, newv[0][newc[0]]);
00208             newc[0]++;
00209             break;
00210         case SIDE_BACK:
00211             VectorCopy (v, newv[1][newc[1]]);
00212             newc[1]++;
00213             break;
00214         case SIDE_ON:
00215             VectorCopy (v, newv[0][newc[0]]);
00216             newc[0]++;
00217             VectorCopy (v, newv[1][newc[1]]);
00218             newc[1]++;
00219             break;
00220         }
00221 
00222         if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
00223             continue;
00224 
00225         d = dists[i] / (dists[i] - dists[i+1]);
00226         for (j=0 ; j<3 ; j++)
00227         {
00228             e = v[j] + d*(v[j+3] - v[j]);
00229             newv[0][newc[0]][j] = e;
00230             newv[1][newc[1]][j] = e;
00231         }
00232         newc[0]++;
00233         newc[1]++;
00234     }
00235 
00236     // continue
00237     ClipSkyPolygon (newc[0], newv[0][0], stage+1);
00238     ClipSkyPolygon (newc[1], newv[1][0], stage+1);
00239 }
00240 
00241 /*
00242 ==============
00243 ClearSkyBox
00244 ==============
00245 */
00246 static void ClearSkyBox (void) {
00247     int     i;
00248 
00249     for (i=0 ; i<6 ; i++) {
00250         sky_mins[0][i] = sky_mins[1][i] = 9999;
00251         sky_maxs[0][i] = sky_maxs[1][i] = -9999;
00252     }
00253 }
00254 
00255 /*
00256 ================
00257 RB_ClipSkyPolygons
00258 ================
00259 */
00260 void RB_ClipSkyPolygons( shaderCommands_t *input )
00261 {
00262     vec3_t      p[5];   // need one extra point for clipping
00263     int         i, j;
00264 
00265     ClearSkyBox();
00266 
00267     for ( i = 0; i < input->numIndexes; i += 3 )
00268     {
00269         for (j = 0 ; j < 3 ; j++) 
00270         {
00271             VectorSubtract( input->xyz[input->indexes[i+j]],
00272                             backEnd.viewParms.or.origin, 
00273                             p[j] );
00274         }
00275         ClipSkyPolygon( 3, p[0], 0 );
00276     }
00277 }
00278 
00279 /*
00280 ===================================================================================
00281 
00282 CLOUD VERTEX GENERATION
00283 
00284 ===================================================================================
00285 */
00286 
00287 /*
00288 ** MakeSkyVec
00289 **
00290 ** Parms: s, t range from -1 to 1
00291 */
00292 static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXYZ )
00293 {
00294     // 1 = s, 2 = t, 3 = 2048
00295     static int  st_to_vec[6][3] =
00296     {
00297         {3,-1,2},
00298         {-3,1,2},
00299 
00300         {1,3,2},
00301         {-1,-3,2},
00302 
00303         {-2,-1,3},      // 0 degrees yaw, look straight up
00304         {2,-1,-3}       // look straight down
00305     };
00306 
00307     vec3_t      b;
00308     int         j, k;
00309     float   boxSize;
00310 
00311     boxSize = backEnd.viewParms.zFar / 1.75;        // div sqrt(3)
00312     b[0] = s*boxSize;
00313     b[1] = t*boxSize;
00314     b[2] = boxSize;
00315 
00316     for (j=0 ; j<3 ; j++)
00317     {
00318         k = st_to_vec[axis][j];
00319         if (k < 0)
00320         {
00321             outXYZ[j] = -b[-k - 1];
00322         }
00323         else
00324         {
00325             outXYZ[j] = b[k - 1];
00326         }
00327     }
00328 
00329     // avoid bilerp seam
00330     s = (s+1)*0.5;
00331     t = (t+1)*0.5;
00332     if (s < sky_min)
00333     {
00334         s = sky_min;
00335     }
00336     else if (s > sky_max)
00337     {
00338         s = sky_max;
00339     }
00340 
00341     if (t < sky_min)
00342     {
00343         t = sky_min;
00344     }
00345     else if (t > sky_max)
00346     {
00347         t = sky_max;
00348     }
00349 
00350     t = 1.0 - t;
00351 
00352 
00353     if ( outSt )
00354     {
00355         outSt[0] = s;
00356         outSt[1] = t;
00357     }
00358 }
00359 
00360 static int  sky_texorder[6] = {0,2,1,3,4,5};
00361 static vec3_t   s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
00362 static float    s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
00363 
00364 static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] )
00365 {
00366     int s, t;
00367 
00368     GL_Bind( image );
00369 
00370     for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
00371     {
00372         qglBegin( GL_TRIANGLE_STRIP );
00373 
00374         for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
00375         {
00376             qglTexCoord2fv( s_skyTexCoords[t][s] );
00377             qglVertex3fv( s_skyPoints[t][s] );
00378 
00379             qglTexCoord2fv( s_skyTexCoords[t+1][s] );
00380             qglVertex3fv( s_skyPoints[t+1][s] );
00381         }
00382 
00383         qglEnd();
00384     }
00385 }
00386 
00387 static void DrawSkyBox( shader_t *shader )
00388 {
00389     int     i;
00390 
00391     sky_min = 0;
00392     sky_max = 1;
00393 
00394     Com_Memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) );
00395 
00396     for (i=0 ; i<6 ; i++)
00397     {
00398         int sky_mins_subd[2], sky_maxs_subd[2];
00399         int s, t;
00400 
00401         sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
00402         sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
00403         sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
00404         sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
00405 
00406         if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
00407              ( sky_mins[1][i] >= sky_maxs[1][i] ) )
00408         {
00409             continue;
00410         }
00411 
00412         sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS;
00413         sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS;
00414         sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS;
00415         sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS;
00416 
00417         if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS ) 
00418             sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
00419         else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS ) 
00420             sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
00421         if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS )
00422             sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS;
00423         else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS ) 
00424             sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
00425 
00426         if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS ) 
00427             sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
00428         else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS ) 
00429             sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
00430         if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS ) 
00431             sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS;
00432         else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) 
00433             sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
00434 
00435         //
00436         // iterate through the subdivisions
00437         //
00438         for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
00439         {
00440             for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
00441             {
00442                 MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, 
00443                             ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, 
00444                             i, 
00445                             s_skyTexCoords[t][s], 
00446                             s_skyPoints[t][s] );
00447             }
00448         }
00449 
00450         DrawSkySide( shader->sky.outerbox[sky_texorder[i]],
00451                      sky_mins_subd,
00452                      sky_maxs_subd );
00453     }
00454 
00455 }
00456 
00457 static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes )
00458 {
00459     int s, t;
00460     int vertexStart = tess.numVertexes;
00461     int tHeight, sWidth;
00462 
00463     tHeight = maxs[1] - mins[1] + 1;
00464     sWidth = maxs[0] - mins[0] + 1;
00465 
00466     for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
00467     {
00468         for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
00469         {
00470             VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] );
00471             tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
00472             tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
00473 
00474             tess.numVertexes++;
00475 
00476             if ( tess.numVertexes >= SHADER_MAX_VERTEXES )
00477             {
00478                 ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()\n" );
00479             }
00480         }
00481     }
00482 
00483     // only add indexes for one pass, otherwise it would draw multiple times for each pass
00484     if ( addIndexes ) {
00485         for ( t = 0; t < tHeight-1; t++ )
00486         {   
00487             for ( s = 0; s < sWidth-1; s++ )
00488             {
00489                 tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth );
00490                 tess.numIndexes++;
00491                 tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
00492                 tess.numIndexes++;
00493                 tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
00494                 tess.numIndexes++;
00495 
00496                 tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
00497                 tess.numIndexes++;
00498                 tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth );
00499                 tess.numIndexes++;
00500                 tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
00501                 tess.numIndexes++;
00502             }
00503         }
00504     }
00505 }
00506 
00507 static void FillCloudBox( const shader_t *shader, int stage )
00508 {
00509     int i;
00510 
00511     for ( i =0; i < 6; i++ )
00512     {
00513         int sky_mins_subd[2], sky_maxs_subd[2];
00514         int s, t;
00515         float MIN_T;
00516 
00517         if ( 1 ) // FIXME? shader->sky.fullClouds )
00518         {
00519             MIN_T = -HALF_SKY_SUBDIVISIONS;
00520 
00521             // still don't want to draw the bottom, even if fullClouds
00522             if ( i == 5 )
00523                 continue;
00524         }
00525         else
00526         {
00527             switch( i )
00528             {
00529             case 0:
00530             case 1:
00531             case 2:
00532             case 3:
00533                 MIN_T = -1;
00534                 break;
00535             case 5:
00536                 // don't draw clouds beneath you
00537                 continue;
00538             case 4:     // top
00539             default:
00540                 MIN_T = -HALF_SKY_SUBDIVISIONS;
00541                 break;
00542             }
00543         }
00544 
00545         sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
00546         sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
00547         sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
00548         sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
00549 
00550         if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
00551              ( sky_mins[1][i] >= sky_maxs[1][i] ) )
00552         {
00553             continue;
00554         }
00555 
00556         sky_mins_subd[0] = myftol( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS );
00557         sky_mins_subd[1] = myftol( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS );
00558         sky_maxs_subd[0] = myftol( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS );
00559         sky_maxs_subd[1] = myftol( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS );
00560 
00561         if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS ) 
00562             sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
00563         else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS ) 
00564             sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
00565         if ( sky_mins_subd[1] < MIN_T )
00566             sky_mins_subd[1] = MIN_T;
00567         else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS ) 
00568             sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
00569 
00570         if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS ) 
00571             sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
00572         else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS ) 
00573             sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
00574         if ( sky_maxs_subd[1] < MIN_T )
00575             sky_maxs_subd[1] = MIN_T;
00576         else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) 
00577             sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
00578 
00579         //
00580         // iterate through the subdivisions
00581         //
00582         for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
00583         {
00584             for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
00585             {
00586                 MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, 
00587                             ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, 
00588                             i, 
00589                             NULL,
00590                             s_skyPoints[t][s] );
00591 
00592                 s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0];
00593                 s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1];
00594             }
00595         }
00596 
00597         // only add indexes for first stage
00598         FillCloudySkySide( sky_mins_subd, sky_maxs_subd, ( stage == 0 ) );
00599     }
00600 }
00601 
00602 /*
00603 ** R_BuildCloudData
00604 */
00605 void R_BuildCloudData( shaderCommands_t *input )
00606 {
00607     int         i;
00608     shader_t    *shader;
00609 
00610     shader = input->shader;
00611 
00612     assert( shader->isSky );
00613 
00614     sky_min = 1.0 / 256.0f;     // FIXME: not correct?
00615     sky_max = 255.0 / 256.0f;
00616 
00617     // set up for drawing
00618     tess.numIndexes = 0;
00619     tess.numVertexes = 0;
00620 
00621     if ( input->shader->sky.cloudHeight )
00622     {
00623         for ( i = 0; i < MAX_SHADER_STAGES; i++ )
00624         {
00625             if ( !tess.xstages[i] ) {
00626                 break;
00627             }
00628             FillCloudBox( input->shader, i );
00629         }
00630     }
00631 }
00632 
00633 /*
00634 ** R_InitSkyTexCoords
00635 ** Called when a sky shader is parsed
00636 */
00637 #define SQR( a ) ((a)*(a))
00638 void R_InitSkyTexCoords( float heightCloud )
00639 {
00640     int i, s, t;
00641     float radiusWorld = 4096;
00642     float p;
00643     float sRad, tRad;
00644     vec3_t skyVec;
00645     vec3_t v;
00646 
00647     // init zfar so MakeSkyVec works even though
00648     // a world hasn't been bounded
00649     backEnd.viewParms.zFar = 1024;
00650 
00651     for ( i = 0; i < 6; i++ )
00652     {
00653         for ( t = 0; t <= SKY_SUBDIVISIONS; t++ )
00654         {
00655             for ( s = 0; s <= SKY_SUBDIVISIONS; s++ )
00656             {
00657                 // compute vector from view origin to sky side integral point
00658                 MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, 
00659                             ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, 
00660                             i, 
00661                             NULL,
00662                             skyVec );
00663 
00664                 // compute parametric value 'p' that intersects with cloud layer
00665                 p = ( 1.0f / ( 2 * DotProduct( skyVec, skyVec ) ) ) *
00666                     ( -2 * skyVec[2] * radiusWorld + 
00667                        2 * sqrt( SQR( skyVec[2] ) * SQR( radiusWorld ) + 
00668                                  2 * SQR( skyVec[0] ) * radiusWorld * heightCloud +
00669                                  SQR( skyVec[0] ) * SQR( heightCloud ) + 
00670                                  2 * SQR( skyVec[1] ) * radiusWorld * heightCloud +
00671                                  SQR( skyVec[1] ) * SQR( heightCloud ) + 
00672                                  2 * SQR( skyVec[2] ) * radiusWorld * heightCloud +
00673                                  SQR( skyVec[2] ) * SQR( heightCloud ) ) );
00674 
00675                 s_cloudTexP[i][t][s] = p;
00676 
00677                 // compute intersection point based on p
00678                 VectorScale( skyVec, p, v );
00679                 v[2] += radiusWorld;
00680 
00681                 // compute vector from world origin to intersection point 'v'
00682                 VectorNormalize( v );
00683 
00684                 sRad = Q_acos( v[0] );
00685                 tRad = Q_acos( v[1] );
00686 
00687                 s_cloudTexCoords[i][t][s][0] = sRad;
00688                 s_cloudTexCoords[i][t][s][1] = tRad;
00689             }
00690         }
00691     }
00692 }
00693 
00694 //======================================================================================
00695 
00696 /*
00697 ** RB_DrawSun
00698 */
00699 void RB_DrawSun( void ) {
00700     float       size;
00701     float       dist;
00702     vec3_t      origin, vec1, vec2;
00703     vec3_t      temp;
00704 
00705     if ( !backEnd.skyRenderedThisView ) {
00706         return;
00707     }
00708     if ( !r_drawSun->integer ) {
00709         return;
00710     }
00711     qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
00712     qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
00713 
00714     dist =  backEnd.viewParms.zFar / 1.75;      // div sqrt(3)
00715     size = dist * 0.4;
00716 
00717     VectorScale( tr.sunDirection, dist, origin );
00718     PerpendicularVector( vec1, tr.sunDirection );
00719     CrossProduct( tr.sunDirection, vec1, vec2 );
00720 
00721     VectorScale( vec1, size, vec1 );
00722     VectorScale( vec2, size, vec2 );
00723 
00724     // farthest depth range
00725     qglDepthRange( 1.0, 1.0 );
00726 
00727     // FIXME: use quad stamp
00728     RB_BeginSurface( tr.sunShader, tess.fogNum );
00729         VectorCopy( origin, temp );
00730         VectorSubtract( temp, vec1, temp );
00731         VectorSubtract( temp, vec2, temp );
00732         VectorCopy( temp, tess.xyz[tess.numVertexes] );
00733         tess.texCoords[tess.numVertexes][0][0] = 0;
00734         tess.texCoords[tess.numVertexes][0][1] = 0;
00735         tess.vertexColors[tess.numVertexes][0] = 255;
00736         tess.vertexColors[tess.numVertexes][1] = 255;
00737         tess.vertexColors[tess.numVertexes][2] = 255;
00738         tess.numVertexes++;
00739 
00740         VectorCopy( origin, temp );
00741         VectorAdd( temp, vec1, temp );
00742         VectorSubtract( temp, vec2, temp );
00743         VectorCopy( temp, tess.xyz[tess.numVertexes] );
00744         tess.texCoords[tess.numVertexes][0][0] = 0;
00745         tess.texCoords[tess.numVertexes][0][1] = 1;
00746         tess.vertexColors[tess.numVertexes][0] = 255;
00747         tess.vertexColors[tess.numVertexes][1] = 255;
00748         tess.vertexColors[tess.numVertexes][2] = 255;
00749         tess.numVertexes++;
00750 
00751         VectorCopy( origin, temp );
00752         VectorAdd( temp, vec1, temp );
00753         VectorAdd( temp, vec2, temp );
00754         VectorCopy( temp, tess.xyz[tess.numVertexes] );
00755         tess.texCoords[tess.numVertexes][0][0] = 1;
00756         tess.texCoords[tess.numVertexes][0][1] = 1;
00757         tess.vertexColors[tess.numVertexes][0] = 255;
00758         tess.vertexColors[tess.numVertexes][1] = 255;
00759         tess.vertexColors[tess.numVertexes][2] = 255;
00760         tess.numVertexes++;
00761 
00762         VectorCopy( origin, temp );
00763         VectorSubtract( temp, vec1, temp );
00764         VectorAdd( temp, vec2, temp );
00765         VectorCopy( temp, tess.xyz[tess.numVertexes] );
00766         tess.texCoords[tess.numVertexes][0][0] = 1;
00767         tess.texCoords[tess.numVertexes][0][1] = 0;
00768         tess.vertexColors[tess.numVertexes][0] = 255;
00769         tess.vertexColors[tess.numVertexes][1] = 255;
00770         tess.vertexColors[tess.numVertexes][2] = 255;
00771         tess.numVertexes++;
00772 
00773         tess.indexes[tess.numIndexes++] = 0;
00774         tess.indexes[tess.numIndexes++] = 1;
00775         tess.indexes[tess.numIndexes++] = 2;
00776         tess.indexes[tess.numIndexes++] = 0;
00777         tess.indexes[tess.numIndexes++] = 2;
00778         tess.indexes[tess.numIndexes++] = 3;
00779 
00780     RB_EndSurface();
00781 
00782     // back to normal depth range
00783     qglDepthRange( 0.0, 1.0 );
00784 }
00785 
00786 
00787 
00788 
00789 /*
00790 ================
00791 RB_StageIteratorSky
00792 
00793 All of the visible sky triangles are in tess
00794 
00795 Other things could be stuck in here, like birds in the sky, etc
00796 ================
00797 */
00798 void RB_StageIteratorSky( void ) {
00799     if ( r_fastsky->integer ) {
00800         return;
00801     }
00802 
00803     // go through all the polygons and project them onto
00804     // the sky box to see which blocks on each side need
00805     // to be drawn
00806     RB_ClipSkyPolygons( &tess );
00807 
00808     // r_showsky will let all the sky blocks be drawn in
00809     // front of everything to allow developers to see how
00810     // much sky is getting sucked in
00811     if ( r_showsky->integer ) {
00812         qglDepthRange( 0.0, 0.0 );
00813     } else {
00814         qglDepthRange( 1.0, 1.0 );
00815     }
00816 
00817     // draw the outer skybox
00818     if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) {
00819         qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
00820         
00821         qglPushMatrix ();
00822         GL_State( 0 );
00823         qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
00824 
00825         DrawSkyBox( tess.shader );
00826 
00827         qglPopMatrix();
00828     }
00829 
00830     // generate the vertexes for all the clouds, which will be drawn
00831     // by the generic shader routine
00832     R_BuildCloudData( &tess );
00833 
00834     RB_StageIteratorGeneric();
00835 
00836     // draw the inner skybox
00837 
00838 
00839     // back to normal depth range
00840     qglDepthRange( 0.0, 1.0 );
00841 
00842     // note that sky was drawn so we will draw a sun later
00843     backEnd.skyRenderedThisView = qtrue;
00844 }
00845 

Generated on Thu Aug 25 12:37:55 2005 for Quake III Arena by  doxygen 1.3.9.1