r_geoscape.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 1997-2001 Id Software, Inc.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "r_local.h"
00026 #include "r_error.h"
00027 #include "r_sphere.h"
00028 #include "r_geoscape.h"
00029 
00030 #include "r_mesh.h"
00031 #include "r_draw.h"
00032 
00033 #define MARKER_SIZE 60.0
00034 
00035 extern const float STANDARD_3D_ZOOM;
00036 
00051 void R_DrawFlatGeoscape (int x, int y, int w, int h, float p, float cx, float cy, float iz, const char *map, qboolean overlayNation, qboolean overlayXVI, qboolean overlayRadar, image_t *r_dayandnightTexture, image_t *r_xviTexture, image_t *r_radarTexture)
00052 {
00053     image_t *gl;
00054     float geoscape_texcoords[4 * 2];
00055     short geoscape_verts[4 * 2];
00056 
00057     /* normalize */
00058     const float nx = x * viddef.rx;
00059     const float ny = y * viddef.ry;
00060     const float nw = w * viddef.rx;
00061     const float nh = h * viddef.ry;
00062 
00063     /* load day image */
00064     gl = R_FindImage(va("pics/geoscape/%s_day", map), it_wrappic);
00065     if (gl == r_noTexture)
00066         Com_Error(ERR_FATAL, "Could not load geoscape day image");
00067 
00068     /* alter the array pointers */
00069     glVertexPointer(2, GL_SHORT, 0, geoscape_verts);
00070     R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);
00071 
00072     geoscape_texcoords[0] = cx - iz;
00073     geoscape_texcoords[1] = cy - iz;
00074     geoscape_texcoords[2] = cx + iz;
00075     geoscape_texcoords[3] = cy - iz;
00076     geoscape_texcoords[4] = cx + iz;
00077     geoscape_texcoords[5] = cy + iz;
00078     geoscape_texcoords[6] = cx - iz;
00079     geoscape_texcoords[7] = cy + iz;
00080 
00081     geoscape_verts[0] = nx;
00082     geoscape_verts[1] = ny;
00083     geoscape_verts[2] = nx + nw;
00084     geoscape_verts[3] = ny;
00085     geoscape_verts[4] = nx + nw;
00086     geoscape_verts[5] = ny + nh;
00087     geoscape_verts[6] = nx;
00088     geoscape_verts[7] = ny + nh;
00089 
00090     /* draw day image */
00091     R_BindTexture(gl->texnum);
00092     glDrawArrays(GL_QUADS, 0, 4);
00093 
00094     /* draw night map */
00095     gl = R_FindImage(va("pics/geoscape/%s_night", map), it_wrappic);
00096     /* maybe the campaign map doesn't have a night image */
00097     if (gl != r_noTexture) {
00098         float geoscape_nighttexcoords[4 * 2];
00099 
00100         R_BindTexture(gl->texnum);
00101         R_EnableTexture(&texunit_lightmap, qtrue);
00102         R_SelectTexture(&texunit_lightmap);
00103 
00104         geoscape_nighttexcoords[0] = geoscape_texcoords[0] + p;
00105         geoscape_nighttexcoords[1] = geoscape_texcoords[1];
00106         geoscape_nighttexcoords[2] = geoscape_texcoords[2] + p;
00107         geoscape_nighttexcoords[3] = geoscape_texcoords[3];
00108         geoscape_nighttexcoords[4] = geoscape_texcoords[4] + p;
00109         geoscape_nighttexcoords[5] = geoscape_texcoords[5];
00110         geoscape_nighttexcoords[6] = geoscape_texcoords[6] + p;
00111         geoscape_nighttexcoords[7] = geoscape_texcoords[7];
00112 
00113         R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_nighttexcoords);
00114 
00115         R_BindTexture(r_dayandnightTexture->texnum);
00116 
00117         R_SelectTexture(&texunit_diffuse);
00118         glDrawArrays(GL_QUADS, 0, 4);
00119 
00120         R_SelectTexture(&texunit_lightmap);
00121         R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);
00122 
00123         R_EnableTexture(&texunit_lightmap, qfalse);
00124     }
00125 
00126     /* draw nation overlay */
00127     if (overlayNation) {
00128         gl = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
00129         if (gl == r_noTexture)
00130             Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");
00131 
00132         /* draw day image */
00133         R_BindTexture(gl->texnum);
00134         glDrawArrays(GL_QUADS, 0, 4);
00135     }
00136 
00137     /* draw XVI image */
00138     if (overlayXVI) {
00139         gl = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
00140         if (gl == r_noTexture)
00141             Com_Error(ERR_FATAL, "Could not load xvi overlay image");
00142 
00143         R_BindTexture(gl->texnum);
00144 
00145         R_EnableTexture(&texunit_lightmap, qtrue);
00146         R_BindLightmapTexture(r_xviTexture->texnum);
00147 
00148         glDrawArrays(GL_QUADS, 0, 4);
00149 
00150         R_EnableTexture(&texunit_lightmap, qfalse);
00151     }
00152 
00153     /* draw radar image */
00154     if (overlayRadar) {
00155         R_BindTexture(r_radarTexture->texnum);
00156         glDrawArrays(GL_QUADS, 0, 4);
00157     }
00158 
00159     /* and restore them */
00160     R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
00161     R_BindDefaultArray(GL_VERTEX_ARRAY);
00162 }
00163 
00169 void R_Draw2DMapMarkers (const vec2_t screenPos, float direction, const char *model, int skin)
00170 {
00171     modelInfo_t mi;
00172     vec2_t size;
00173     vec3_t scale, center, position, angles;
00174     float zoom = 0.4f;
00175 
00176     memset(&mi, 0, sizeof(mi));
00177     VectorCopy(vec3_origin, position);
00178     VectorCopy(vec3_origin, angles);
00179 
00180     mi.model = R_RegisterModelShort(model);
00181     if (!mi.model) {
00182         Com_Printf("Could not find model '%s'\n", model);
00183         return;
00184     }
00185 
00186     mi.name = model;
00187     mi.origin = position;
00188     mi.angles = angles;
00189     mi.skin = skin;
00190 
00191     size[0] = size[1] = MARKER_SIZE * zoom;
00192     R_ModelAutoScale(size, &mi, scale, center);
00193     /* reset the center, as we want to place the models onto the surface of the earth */
00194     mi.center = NULL;
00195 
00196     /* go to a new matrix */
00197     glPushMatrix();
00198 
00199     /* Apply all transformation to model. Note that the transformations are applied starting
00200      * from the last one and ending with the first one */
00201 
00202     /* move model to its location */
00203     glTranslatef(screenPos[0]* viddef.rx, screenPos[1]* viddef.ry, 0);
00204     /* scale model to proper resolution */
00205     glScalef(viddef.rx, viddef.ry, 1.0f);
00206     /* rotate model to proper direction. */
00207     glRotatef(180.0f, 0, 1, 0);
00208     glRotatef(90.f - direction, 0, 0, 1);
00209 
00210     R_DrawModelDirect(&mi, NULL, NULL);
00211 
00212     /* restore previous matrix */
00213     glPopMatrix();
00214 }
00215 
00227 void R_Draw3DMapMarkers (int x, int y, int w, int h, const vec3_t rotate, const vec2_t pos, float direction, float earthRadius, const char *model, int skin)
00228 {
00229     /* normalize */
00230     const float nx = x * viddef.rx;
00231     const float ny = y * viddef.ry;
00232     const float nw = w * viddef.rx;
00233     const float nh = h * viddef.ry;
00234 
00235     /* Earth center is in the middle of node.
00236      * Due to Orthographic view, this is also camera position */
00237     const vec3_t earthPos = {nx + nw / 2.0, ny + nh / 2.0, 0.0};
00238 
00239     modelInfo_t mi;
00240     vec2_t size;
00241     vec3_t scale, center, position, angles;
00242     float zoom = 0.4f;
00243 
00244     memset(&mi, 0, sizeof(mi));
00245     VectorCopy(vec3_origin, position);
00246     VectorCopy(vec3_origin, angles);
00247 
00248     mi.model = R_RegisterModelShort(model);
00249     if (!mi.model) {
00250         Com_Printf("Could not find model '%s'\n", model);
00251         return;
00252     }
00253 
00254     mi.name = model;
00255     mi.origin = position;
00256     mi.angles = angles;
00257     mi.skin = skin;
00258 
00259     size[0] = size[1] = MARKER_SIZE * zoom;
00260     R_ModelAutoScale(size, &mi, scale, center);
00261     /* reset the center, as we want to place the models onto the surface of the earth */
00262     mi.center = NULL;
00263 
00264     /* go to a new matrix */
00265     glPushMatrix();
00266 
00267     /* Apply all transformation to model. Note that the transformations are applied starting
00268      * from the last one and ending with the first one */
00269 
00270     /* center model on earth. Translate also along z to avoid seeing
00271      * bottom part of the model through earth (only half of earth is drawn) */
00272     glTranslatef(earthPos[0], earthPos[1], 10.0f);
00273     /* scale model to proper resolution */
00274     glScalef(viddef.rx, viddef.ry, 1.0f);
00275     /* place model on earth: make it tangent to earth surface, heading toward it if direction is used. */
00276     glRotatef(-rotate[1], 1, 0, 0);
00277     glRotatef(rotate[2], 0, 1, 0);
00278     glRotatef(rotate[0] - pos[0], 0, 0, 1);
00279     glRotatef(90.0f - pos[1], 1, 0, 0);
00280     glTranslatef(0, 0, earthRadius);
00281     glRotatef(-90.0f + direction, 0, 0, 1);
00282 
00283     R_DrawModelDirect(&mi, NULL, NULL);
00284 
00285     /* restore previous matrix */
00286     glPopMatrix();
00287 }
00288 
00294 const float SKYBOX_DEPTH = -9999.0f;
00295 
00303 #define SKYBOX_HALFSIZE 800.0f
00304 
00305 static const float starFieldVerts[] = {
00306     /* face 1 */
00307     -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00308     +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00309     +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00310     -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00311 
00312     /* face 2 */
00313     -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00314     +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00315     +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00316     -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00317 
00318     /* face 3 */
00319     +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00320     +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00321     +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00322     +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00323 
00324     /* face 4 */
00325     -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00326     -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00327     -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00328     -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00329 
00330     /* face 5 */
00331     -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00332     +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00333     +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00334     -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00335 
00336     /* face 6 */
00337     -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00338     +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, +SKYBOX_HALFSIZE,
00339     +SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE,
00340     -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE
00341 };
00342 
00343 static const float starFieldTexCoords[] = {
00344     0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
00345     0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
00346     0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
00347     0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
00348     0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
00349     0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
00350 };
00351 
00361 static void R_DrawStarfield (int texnum, const vec3_t pos, const vec3_t rotate, float p)
00362 {
00363     vec3_t angle;       
00365     /* go to a new matrix */
00366     glPushMatrix();
00367 
00368     /* we must center the skybox on the camera border of view, and not on the earth, in order
00369      * to see only the inside of the cube */
00370     glTranslatef(pos[0], pos[1], -SKYBOX_DEPTH);
00371 
00372     /* rotates starfield: only time and rotation of earth around itself causes starfield to rotate. */
00373     VectorSet(angle, rotate[0] - p * todeg, rotate[1], rotate[2]);
00374     glRotatef(angle[YAW], 1, 0, 0);
00375     glRotatef(angle[ROLL], 0, 1, 0);
00376     glRotatef(angle[PITCH], 0, 0, 1);
00377 
00378     R_BindTexture(texnum);
00379 
00380     /* alter the array pointers */
00381     glVertexPointer(3, GL_FLOAT, 0, starFieldVerts);
00382     glTexCoordPointer(2, GL_FLOAT, 0, starFieldTexCoords);
00383 
00384     /* draw the cube */
00385     glDrawArrays(GL_QUADS, 0, 24);
00386 
00387     /* restore previous matrix */
00388     glPopMatrix();
00389 }
00390 
00399 static inline void RotateCelestialBody (const vec4_t v, vec4_t * r, const vec3_t rotate, const vec3_t earthPos, const float celestialDist)
00400 {
00401     vec4_t v1;
00402     vec4_t v2;
00403     vec3_t rotationAxis;
00404 
00405     VectorSet(v2, v[1], v[0], v[2]);
00406     VectorSet(rotationAxis, 0, 0, 1);
00407     RotatePointAroundVector(v1, rotationAxis, v2, -rotate[PITCH]);
00408     VectorSet(rotationAxis, 0, 1, 0);
00409     RotatePointAroundVector(v2, rotationAxis, v1, -rotate[YAW]);
00410 
00411     Vector4Set((*r), earthPos[0] + celestialDist * v2[1], earthPos[1] + celestialDist * v2[0], -celestialDist * v2[2], 0);
00412 }
00413 
00414 
00427 void R_Draw3DGlobe (int x, int y, int w, int h, int day, int second, const vec3_t rotate, float zoom, const char *map, qboolean disableSolarRender, float ambient, qboolean overlayNation, qboolean overlayXVI, qboolean overlayRadar, image_t *r_xviTexture, image_t *r_radarTexture)
00428 {
00429     /* globe scaling */
00430     const float fullscale = zoom / STANDARD_3D_ZOOM;
00431 
00432     /* lighting colors */
00433     static const vec4_t diffuseLightColor = { 1.75f, 1.75f, 1.75f, 1.0f };
00434     static const vec4_t specularLightColor = { 2.0f, 1.9f, 1.7f, 1.0f };
00435     static const vec4_t darknessLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
00436     static const vec4_t brightDiffuseLightColor = { 5.0f, 5.0f, 5.0f, 1.0f };
00437     const vec4_t ambientLightColor = { ambient + 0.2f, ambient + 0.2f, ambient + 0.2f, ambient + 0.2f };
00438     /* billboard textures */
00439     image_t *starfield;
00440     image_t *halo;
00441     image_t *sun;
00442     image_t *sunOverlay;
00443 
00444     /* set distance of the sun and moon to make them static on starfield when
00445      * time is stoped.  this distance should be used for any celestial body
00446      * considered at infinite location (sun, moon) */
00447     static const float celestialDist = 1.37f * SKYBOX_HALFSIZE;
00448     static const float moonSize = 0.025f;
00449     vec4_t sunPos;
00450     vec4_t antiSunPos;
00451     vec4_t moonLoc;
00452     vec4_t sunLoc;
00453 
00454     /* normalize */
00455     const float nx = x * viddef.rx;
00456     const float ny = y * viddef.ry;
00457     const float nw = w * viddef.rx;
00458     const float nh = h * viddef.ry;
00459 
00460     /* Earth center is in the middle of node.
00461      * Due to Orthographic view, this is also camera position */
00462     const vec3_t earthPos = { nx + nw / 2.0, ny + nh / 2.0, 0.0 };
00463 
00464     /* estimate the progress through the current season so we can do
00465      * smooth transitions between textures.  Currently there are 12
00466      * "seasons", because we have one image per Earth-month. */
00467     const float season = (float) (day % DAYS_PER_YEAR) / ((float) (DAYS_PER_YEAR) / (float) (SEASONS_PER_YEAR));
00468     const int currSeason = (int) floorf(season) % SEASONS_PER_YEAR;
00469     const int nextSeason = (int) ceilf(season) % SEASONS_PER_YEAR;
00470     const float seasonProgress = season - (float) currSeason;
00471 
00472     /* Compute sun position in absolute frame */
00473     const float q = (day % DAYS_PER_YEAR * SECONDS_PER_DAY + second) * (2 * M_PI / (SECONDS_PER_DAY * DAYS_PER_YEAR));  /* sun rotation (year) */
00474     const float a = cos(q) * SIN_ALPHA; /* due to earth obliquity */
00475     const float sqrta = sqrt(0.5f * (1 - a * a));
00476 
00477     /* earth rotation (day) */
00478     const float p = (second - SECONDS_PER_DAY / 4) * (2.0 * M_PI / SECONDS_PER_DAY);
00479     /* lunar orbit */
00480     const float m = p + (((double)((10 * day % 249) / 10.0) + ((double)second / (double)SECONDS_PER_DAY)) / 24.9) * (2.0 * M_PI);
00481 
00482     glPushMatrix();
00483     glMatrixMode(GL_TEXTURE);
00484     glLoadIdentity();
00485     glMatrixMode(GL_MODELVIEW);
00486     glDisable(GL_LIGHTING);
00487     /* draw the starfield, rotating with the planet */
00488     starfield = R_FindImage(va("pics/geoscape/%s_stars", map), it_wrappic);
00489     if (starfield != r_noTexture)
00490         R_DrawStarfield(starfield->texnum, earthPos, rotate, p);
00491 
00492     glPopMatrix();
00493 
00494     /* set up position vectors for celestial bodies */
00495     Vector4Set(sunPos, cos(p) * sqrta, -sin(p) * sqrta, a, 0);
00496     Vector4Set(antiSunPos, -cos(p) * sqrta, sin(p) * sqrta, -a, 0);
00497 
00498     /* Rotate the sun in the relative frame of player view, to get sun location */
00499     RotateCelestialBody(sunPos, &sunLoc, rotate, earthPos, 1.0);
00500     /* load sun texture image */
00501     sun = R_FindImage(va("pics/geoscape/%s_sun", map), it_wrappic);
00502     sunOverlay = R_FindImage(va("pics/geoscape/%s_sun_overlay", map), it_pic);
00503     if (sun != r_noTexture && sunOverlay != r_noTexture && sunLoc[2] > 0 && !disableSolarRender) {
00504         const int sunx = earthPos[0] + viddef.rx * (-128.0 + celestialDist * (sunLoc[0] - earthPos[0]));
00505         const int suny = earthPos[1] + viddef.ry * (-128.0 + celestialDist * (sunLoc[1] - earthPos[1]));
00506 
00507         R_DrawTexture(sunOverlay->texnum, sunx, suny, 256.0 * viddef.rx, 256.0 * viddef.ry);
00508         R_DrawBuffers(2);
00509         R_DrawTexture(sun->texnum, sunx, suny, 256.0 * viddef.rx, 256.0 * viddef.ry);
00510         R_DrawBuffers(1);
00511     }
00512 
00513     /* calculate position of the moon (it rotates around earth with a period of
00514      * about 24.9 h, and we must take day into account to avoid moon to "jump"
00515      * every time the day is changing) */
00516     VectorSet(moonLoc, cos(m) * sqrta, -sin(m) * sqrta, a);
00517     RotateCelestialBody(moonLoc, &moonLoc, rotate, earthPos, celestialDist);
00518 
00519     /* free last month's texture image */
00520     if (r_globeEarth.season != currSeason) {
00521         r_globeEarth.season = currSeason;
00522         R_FreeImage(r_globeEarth.texture);
00523     }
00524 
00525     /* load diffuse texture map (with embedded night-glow map as alpha channel) */
00526     r_globeEarth.texture = R_FindImage(va("pics/geoscape/%s/%s_season_%02d", r_config.lodDir, map, currSeason), it_wrappic);
00527     if (r_globeEarth.texture == r_noTexture)
00528         Com_Error(ERR_FATAL, "Could not find pics/geoscape/%s/%s_season_%02d\n", r_config.lodDir, map, currSeason);
00529 
00530     /* set up for advanced GLSL rendering if we have the capability */
00531     if (r_programs->integer) {
00532         r_globeEarth.glslProgram = r_state.geoscape_program;
00533         /* load earth image for the next month so we can blend them */
00534         r_globeEarth.blendTexture = R_FindImage(va("pics/geoscape/%s/%s_season_%02d", r_config.lodDir, map, nextSeason), it_wrappic);
00535         if (r_globeEarth.blendTexture == r_noTexture)
00536             Com_Error(ERR_FATAL, "Could not find pics/geoscape/%s/%s_season_%02d\n", r_config.lodDir, map, nextSeason);
00537 
00538         /* load normal map (with embedded gloss map as alpha channel) */
00539         r_globeEarth.normalMap = R_FindImage(va("pics/geoscape/%s/%s_bump", r_config.lodDir, map), it_wrappic);
00540         if (r_globeEarth.normalMap == r_noTexture)
00541             r_globeEarth.normalMap = NULL;
00542 
00543         /* weight the blending based on how much of the month has elapsed */
00544         r_globeEarth.blendScale = seasonProgress;
00545         /* set up lights for nighttime city glow */
00546         VectorCopy(antiSunPos, r_globeEarth.nightLightPos);
00547         glLightfv(GL_LIGHT1, GL_AMBIENT, darknessLightColor);
00548         glLightfv(GL_LIGHT1, GL_DIFFUSE, brightDiffuseLightColor);
00549         glLightfv(GL_LIGHT1, GL_SPECULAR, darknessLightColor);
00550 
00551         r_globeEarth.glowScale = 0.7;
00552     }
00553 
00554     /* load moon texture image */
00555     r_globeMoon.texture = R_FindImage(va("pics/geoscape/%s_moon", map), it_wrappic);
00556 
00557     /* globe texture scaling */
00558     glMatrixMode(GL_TEXTURE);
00559     glLoadIdentity();
00560     glScalef(2, 1, 1);
00561     glMatrixMode(GL_MODELVIEW);
00562 
00563     /* enable the lighting */
00564     glEnable(GL_LIGHTING);
00565     glEnable(GL_LIGHT0);
00566     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLightColor);
00567     glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLightColor);
00568     glLightfv(GL_LIGHT0, GL_SPECULAR, specularLightColor);
00569 
00570     /* draw the moon */
00571     if (r_globeMoon.texture != r_noTexture && moonLoc[2] > 0 && !disableSolarRender)
00572         R_SphereRender(&r_globeMoon, moonLoc, rotate, moonSize, sunPos);
00573 
00574     /* activate depth to hide 3D models behind earth */
00575     glEnable(GL_DEPTH_TEST);
00576 
00577     /* draw the earth */
00578     R_DrawBuffers(2);
00579     if (r_programs->integer == 0) /* ignore alpha channel, since the city-light map is stored there */
00580         glBlendFunc(GL_ONE, GL_ZERO);
00581 
00582     R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
00583 
00584     if (r_programs->integer == 0) /* restore default blend function */
00585         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00586 
00587     r_globeEarthAtmosphere.texture = R_FindImage(va("pics/geoscape/%s_atmosphere", map), it_wrappic);
00588 
00589     /* Draw earth atmosphere */
00590     if (r_programs->integer && r_postprocess->integer) {
00591         r_globeEarthAtmosphere.normalMap = r_globeEarth.normalMap;
00592         r_globeEarthAtmosphere.glowScale = 1.0;
00593         r_globeEarthAtmosphere.blendScale = -1.0;
00594         r_globeEarthAtmosphere.glslProgram = r_state.atmosphere_program;
00595         R_SphereRender(&r_globeEarthAtmosphere, earthPos, rotate, fullscale, sunPos);
00596     } else {
00597         halo = R_FindImage("pics/geoscape/map_earth_halo", it_pic);
00598         if (halo != r_noTexture) {
00600             const float earthSizeX = fullscale * 20500.0 * viddef.rx;
00601             const float earthSizeY = fullscale * 20500.0 * viddef.ry;
00602             glMatrixMode(GL_TEXTURE);
00603             glPushMatrix();
00604             glLoadIdentity();
00605             glDisable(GL_LIGHTING);
00606 
00607             R_DrawTexture(halo->texnum, earthPos[0] - earthSizeX * 0.5, earthPos[1] - earthSizeY * 0.5, earthSizeX, earthSizeY);
00608             glEnable(GL_LIGHTING);
00609             glPopMatrix();
00610             glMatrixMode(GL_MODELVIEW);
00611         }
00612     }
00613 
00614     R_DrawBuffers(1);
00615     glDisable(GL_DEPTH_TEST);
00616 
00617     /* draw nation overlay */
00618     if (overlayNation) {
00619         r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
00620         if (r_globeEarth.overlay == r_noTexture)
00621             Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");
00622 
00623         R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
00624 
00625         /* draw glowing borders */
00626         r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_nations_overlay_glow", map), it_wrappic);
00627         if (r_globeEarth.overlay == r_noTexture)
00628             Com_Error(ERR_FATAL, "Could not load geoscape nation overlay glow image");
00629 
00630         R_DrawBuffers(2);
00631         glDisable(GL_LIGHTING);
00632         R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
00633         glEnable(GL_LIGHTING);
00634         R_DrawBuffers(1);
00635 
00636         r_globeEarth.overlay = NULL;
00637     }
00638     /* draw XVI overlay */
00639     if (overlayXVI) {
00640         r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
00641         r_globeEarth.overlayAlphaMask = r_xviTexture;
00642         assert(r_globeEarth.overlayAlphaMask);
00643         R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
00644         r_globeEarth.overlayAlphaMask = NULL;
00645         r_globeEarth.overlay = NULL;
00646     }
00647     /* draw radar overlay */
00648     if (overlayRadar) {
00649         r_globeEarth.overlay = r_radarTexture;
00650         assert(r_globeEarth.overlay);
00651         R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
00652         r_globeEarth.overlay = NULL;
00653     }
00654 
00655     /* disable 3d geoscape lighting */
00656     glDisable(GL_LIGHTING);
00657 
00658     /* restore the previous matrix */
00659     glMatrixMode(GL_TEXTURE);
00660     glLoadIdentity();
00661     glMatrixMode(GL_MODELVIEW);
00662 }
00663 
00667 static inline void R_DrawQuad (void)
00668 {
00669     glBegin(GL_QUADS);
00670     glTexCoord2i(0, 1);
00671     glVertex2i(0, 0);
00672     glTexCoord2i(1, 1);
00673     glVertex2i(fbo_render->width, 0);
00674     glTexCoord2i(1, 0);
00675     glVertex2i(fbo_render->width, fbo_render->height);
00676     glTexCoord2i(0, 0);
00677     glVertex2i(0, fbo_render->height);
00678     glEnd();
00679 }
00680 
00685 static void R_Blur (r_framebuffer_t * source, r_framebuffer_t * dest, int tex, int dir)
00686 {
00687     R_EnableBlur(r_state.convolve_program, qtrue, source, dest, dir);
00688 
00689     /* draw new texture onto a flat surface */
00690     R_BindTextureForTexUnit(source->textures[tex], &texunit_0);
00691     R_UseViewport(source);
00692     R_DrawQuad();
00693 
00694     R_EnableBlur(r_state.convolve_program, qfalse, NULL, NULL, 0);
00695 }
00696 
00700 static void R_BlurStack (int levels, r_framebuffer_t ** sources, r_framebuffer_t ** dests)
00701 {
00702     int i;
00703 
00704     for (i = 0; i < levels; i++) {
00705         const int l = levels - i - 1;
00706 
00707         R_UseProgram(i == 0 ? default_program : r_state.combine2_program);
00708         R_UseFramebuffer(dests[l]);
00709         R_BindTextureForTexUnit(sources[l]->textures[0], &texunit_0);
00710         if (i != 0)
00711             R_BindTextureForTexUnit(dests[l + 1]->textures[0], &texunit_1);
00712 
00713         R_UseViewport(sources[l]);
00714         R_DrawQuad();
00715 
00716         R_Blur(dests[l], sources[l], 0, 1);
00717         R_Blur(sources[l], dests[l], 0, 0);
00718     }
00719 }
00720 
00724 void R_DrawBloom (void)
00725 {
00726     int i;
00727     qboolean renderBufferState;
00728 
00729     if (!r_config.frameBufferObject || !r_postprocess->integer || !r_programs->integer)
00730         return;
00731 
00732     /* save state, then set up for blit-style rendering to quads */
00733     renderBufferState = R_RenderbufferEnabled();
00734     glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
00735     glMatrixMode(GL_TEXTURE);
00736     glPushMatrix();
00737     glLoadIdentity();
00738     glMatrixMode(GL_MODELVIEW);
00739     glPushMatrix();
00740     glLoadIdentity();
00741     glMatrixMode(GL_PROJECTION);
00742     glPushMatrix();
00743     glLoadIdentity();
00744     glOrtho(0, viddef.width, viddef.height, 0, 9999.0f, SKYBOX_DEPTH);
00745 
00746     glDisable(GL_LIGHTING);
00747     glDisable(GL_DEPTH_TEST);
00748 
00749     /* downsample into image pyramid */
00750     R_BindTexture(fbo_render->textures[1]);
00751     qglGenerateMipmapEXT(GL_TEXTURE_2D);
00752 
00753     R_Blur(fbo_render, fbo_bloom0, 1, 0);
00754     R_Blur(fbo_bloom0, fbo_bloom1, 0, 1);
00755 
00756     R_UseFramebuffer(r_state.buffers0[0]);
00757     R_BindTexture(fbo_bloom1->textures[0]);
00758     qglGenerateMipmapEXT(GL_TEXTURE_2D);
00759     R_UseViewport(r_state.buffers0[0]);
00760     R_DrawQuad();
00761 
00762     for (i = 1; i < DOWNSAMPLE_PASSES; i++) {
00763         R_Blur(r_state.buffers0[i - 1], r_state.buffers1[i - 1], 0, 0);
00764         R_Blur(r_state.buffers1[i - 1], r_state.buffers2[i - 1], 0, 1);
00765         R_UseFramebuffer(r_state.buffers0[i]);
00766         R_BindTexture(r_state.buffers2[i - 1]->textures[0]);
00767         R_UseViewport(r_state.buffers0[i]);
00768         R_DrawQuad();
00769     }
00770 
00771     /* blur and combine downsampled images */
00772     R_BlurStack(DOWNSAMPLE_PASSES, r_state.buffers0, r_state.buffers1);
00773 
00774     /* re-combine the blurred version with the original "glow" image */
00775     R_UseProgram(r_state.combine2_program);
00776     R_UseFramebuffer(fbo_bloom0);
00777     R_BindTextureForTexUnit(fbo_render->textures[1], &texunit_0);
00778     R_BindTextureForTexUnit(r_state.buffers1[0]->textures[0], &texunit_1);
00779 
00780     R_UseViewport(fbo_screen);
00781     R_DrawQuad();
00782 
00783     /* draw final result to the screenbuffer */
00784     R_UseFramebuffer(fbo_screen);
00785     R_UseProgram(r_state.combine2_program);
00786     R_BindTextureForTexUnit(fbo_render->textures[0], &texunit_0);
00787     R_BindTextureForTexUnit(fbo_bloom0->textures[0], &texunit_1);
00788 
00789     R_DrawQuad();
00790 
00791     /* cleanup before returning */
00792     R_UseProgram(default_program);
00793 
00794     R_CheckError();
00795 
00796     glMatrixMode(GL_PROJECTION);
00797     glPopMatrix();
00798     glMatrixMode(GL_MODELVIEW);
00799     glPopMatrix();
00800     glMatrixMode(GL_TEXTURE);
00801     glPopMatrix();
00802     glPopAttrib();
00803     R_CheckError();
00804 
00805     /* reset renderbuffer state to what it was before */
00806     R_EnableRenderbuffer(renderBufferState);
00807 }

Generated by  doxygen 1.6.2