UFO: Alien Invasion
Loading...
Searching...
No Matches
r_geoscape.cpp
Go to the documentation of this file.
1
4
5/*
6Copyright (C) 1997-2001 Id Software, Inc.
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23*/
24
25#include "r_local.h"
26#include "r_error.h"
27#include "r_sphere.h"
28#include "r_geoscape.h"
29
30#include "r_mesh.h"
31#include "r_draw.h"
32
33#include "../DateTime.h"
34
35#define MARKER_SIZE 60.0
36
50void R_DrawFlatGeoscape (const vec2_t nodePos, const vec2_t nodeSize, float p, float cx, float cy, float iz, const char* map, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t* r_dayandnightTexture, image_t* r_xviTexture, image_t* r_radarTexture)
51{
52 image_t* gl;
53 float geoscape_texcoords[4 * 2];
54 short geoscape_verts[4 * 2];
55
56 /* normalize */
57 const float nx = nodePos[0] * viddef.rx;
58 const float ny = nodePos[1] * viddef.ry;
59 const float nw = nodeSize[0] * viddef.rx;
60 const float nh = nodeSize[1] * viddef.ry;
61
62 /* load day image */
63 gl = R_FindImage(va("pics/geoscape/%s_day", map), it_wrappic);
64 if (gl == r_noTexture)
65 Com_Error(ERR_FATAL, "Could not load geoscape day image");
66
67 /* alter the array pointers */
68 glVertexPointer(2, GL_SHORT, 0, geoscape_verts);
69 R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);
70
71 geoscape_texcoords[0] = cx - iz;
72 geoscape_texcoords[1] = cy - iz;
73 geoscape_texcoords[2] = cx + iz;
74 geoscape_texcoords[3] = cy - iz;
75 geoscape_texcoords[4] = cx + iz;
76 geoscape_texcoords[5] = cy + iz;
77 geoscape_texcoords[6] = cx - iz;
78 geoscape_texcoords[7] = cy + iz;
79
80 geoscape_verts[0] = nx;
81 geoscape_verts[1] = ny;
82 geoscape_verts[2] = nx + nw;
83 geoscape_verts[3] = ny;
84 geoscape_verts[4] = nx + nw;
85 geoscape_verts[5] = ny + nh;
86 geoscape_verts[6] = nx;
87 geoscape_verts[7] = ny + nh;
88
89 /* draw day image */
91 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
92
93 refdef.batchCount++;
94
95 /* draw night map */
96 gl = R_FindImage(va("pics/geoscape/%s_night", map), it_wrappic);
97 /* maybe the campaign map doesn't have a night image */
98 if (gl != r_noTexture) {
99 float geoscape_nighttexcoords[4 * 2];
100
104
105 geoscape_nighttexcoords[0] = geoscape_texcoords[0] + p;
106 geoscape_nighttexcoords[1] = geoscape_texcoords[1];
107 geoscape_nighttexcoords[2] = geoscape_texcoords[2] + p;
108 geoscape_nighttexcoords[3] = geoscape_texcoords[3];
109 geoscape_nighttexcoords[4] = geoscape_texcoords[4] + p;
110 geoscape_nighttexcoords[5] = geoscape_texcoords[5];
111 geoscape_nighttexcoords[6] = geoscape_texcoords[6] + p;
112 geoscape_nighttexcoords[7] = geoscape_texcoords[7];
113
114 R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_nighttexcoords);
115
117
119 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
120
121 refdef.batchCount++;
122
124 R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);
125
127 }
128
129 /* draw nation overlay */
130 if (overlayNation) {
131 gl = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
132 if (gl == r_noTexture)
133 Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");
134
135 /* draw day image */
137 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
138
139 refdef.batchCount++;
140 }
141
142 /* draw XVI image */
143 if (overlayXVI) {
144 gl = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
145 if (gl == r_noTexture)
146 Com_Error(ERR_FATAL, "Could not load xvi overlay image");
147
149
152
153 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
154
155 refdef.batchCount++;
156
158 }
159
160 /* draw radar image */
161 if (overlayRadar) {
163 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
164
165 refdef.batchCount++;
166 }
167
168 /* and restore them */
169 R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
170 R_BindDefaultArray(GL_VERTEX_ARRAY);
171}
172
180void R_Draw2DMapMarkers (const vec2_t screenPos, float direction, const char* model, int skin)
181{
182 modelInfo_t mi;
183 vec2_t size;
184 vec3_t scale, center, position, angles;
185 float zoom = 0.4f;
186
187 OBJZERO(mi);
188 VectorCopy(vec3_origin, position);
189 VectorCopy(vec3_origin, angles);
190
191 mi.model = R_FindModel(model);
192 if (!mi.model) {
193 Com_Printf("Could not find model '%s'\n", model);
194 return;
195 }
196
197 mi.name = model;
198 mi.origin = position;
199 mi.angles = angles;
200 mi.skin = skin;
201
202 size[0] = size[1] = MARKER_SIZE * zoom;
203 R_ModelAutoScale(size, &mi, scale, center);
204 /* reset the center, as we want to place the models onto the surface of the earth */
205 mi.center = nullptr;
206
207 /* go to a new matrix */
208 glPushMatrix();
209
210 /* Apply all transformation to model. Note that the transformations are applied starting
211 * from the last one and ending with the first one */
212
213 /* move model to its location */
214 glTranslatef(screenPos[0]* viddef.rx, screenPos[1]* viddef.ry, 0);
215 /* scale model to proper resolution */
216 glScalef(viddef.rx, viddef.ry, 1.0f);
217 /* rotate model to proper direction. */
218 glRotatef(-90.f + direction, 0, 0, 1);
219
220 R_DrawModelDirect(&mi, nullptr, nullptr);
221
222 /* restore previous matrix */
223 glPopMatrix();
224}
225
237void R_Draw3DMapMarkers (const vec2_t nodePos, const vec2_t nodeSize, const vec3_t rotate, const vec2_t pos, float direction, float earthRadius, const char* model, int skin)
238{
239 /* normalize */
240 const float nx = nodePos[0] * viddef.rx;
241 const float ny = nodePos[1] * viddef.ry;
242 const float nw = nodeSize[0] * viddef.rx;
243 const float nh = nodeSize[1] * viddef.ry;
244
245 /* Earth center is in the middle of node.
246 * Due to Orthographic view, this is also camera position */
247 const vec3_t earthPos = {nx + nw / 2.0f, ny + nh / 2.0f, 0.0f};
248
249 modelInfo_t mi;
250 vec2_t size;
251 vec3_t scale, center, position, angles;
252 float zoom = 0.4f;
253
254 OBJZERO(mi);
255 VectorCopy(vec3_origin, position);
256 VectorCopy(vec3_origin, angles);
257
258 mi.model = R_FindModel(model);
259 if (!mi.model) {
260 Com_Printf("Could not find model '%s'\n", model);
261 return;
262 }
263
264 mi.name = model;
265 mi.origin = position;
266 mi.angles = angles;
267 mi.skin = skin;
268
269 size[0] = size[1] = MARKER_SIZE * zoom;
270 R_ModelAutoScale(size, &mi, scale, center);
271 /* reset the center, as we want to place the models onto the surface of the earth */
272 mi.center = nullptr;
273
274 /* go to a new matrix */
275 glPushMatrix();
276
277 /* Apply all transformation to model. Note that the transformations are applied starting
278 * from the last one and ending with the first one */
279
280 /* center model on earth. Translate also along z to avoid seeing
281 * bottom part of the model through earth (only half of earth is drawn) */
282 glTranslatef(earthPos[0], earthPos[1], 10.0f);
283 /* scale model to proper resolution */
284 glScalef(viddef.rx, viddef.ry, 1.0f);
285 /* place model on earth: make it tangent to earth surface, heading toward it if direction is used. */
286 glRotatef(-rotate[1], 1, 0, 0);
287 glRotatef(rotate[2], 0, 1, 0);
288 glRotatef(rotate[0] - pos[0], 0, 0, 1);
289 glRotatef(90.0f - pos[1], 1, 0, 0);
290 glTranslatef(0, 0, earthRadius);
291 glRotatef(90.0f + direction, 0, 0, 1);
292
293 R_DrawModelDirect(&mi, nullptr, nullptr);
294
295 /* restore previous matrix */
296 glPopMatrix();
297}
298
306#define SKYBOX_HALFSIZE 800.0f
307
308static const float starFieldVerts[] = {
309 /* face 1 */
314
315 /* face 2 */
320
321 /* face 3 */
326
327 /* face 4 */
332
333 /* face 5 */
338
339 /* face 6 */
344};
345
346static const float starFieldTexCoords[] = {
347 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
348 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
349 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
350 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
351 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
352 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
353};
354
367static void R_DrawStarfield (int texnum, const vec3_t pos, const vec3_t rotate, float timeOfDay)
368{
369 vec3_t angle;
370
371 /* go to a new matrix */
372 glPushMatrix();
373
374 /* we must center the skybox on the camera border of view, and not on the earth, in order
375 * to see only the inside of the cube */
376 glTranslatef(pos[0], pos[1], -SKYBOX_DEPTH);
377
378 /* rotates starfield: only time and rotation of earth around itself causes starfield to rotate. */
379 VectorSet(angle, rotate[0] - timeOfDay * todeg, rotate[1], rotate[2]);
380 glRotatef(angle[YAW], 1, 0, 0);
381 glRotatef(angle[ROLL], 0, 1, 0);
382 glRotatef(angle[PITCH], 0, 0, 1);
383
384 R_BindTexture(texnum);
385
386 /* alter the array pointers */
387 glVertexPointer(3, GL_FLOAT, 0, starFieldVerts);
388 glTexCoordPointer(2, GL_FLOAT, 0, starFieldTexCoords);
389
390 /* draw the cube */
391#ifdef GL_VERSION_ES_CM_1_0
392 for( int ii = 0; ii < 6; ii++ )
393 glDrawArrays(GL_TRIANGLE_FAN, ii * 4, 4);
394#else
395 glDrawArrays(GL_QUADS, 0, 24);
396#endif
397
398 refdef.batchCount++;
399
400 /* restore previous matrix */
401 glPopMatrix();
402}
403
407static inline void R_RotateCelestialBody (const vec4_t v, vec4_t r, const vec3_t rotate, const vec3_t earthPos, const float celestialDist)
408{
409 vec4_t v1;
410 vec3_t v2;
411 vec3_t rotationAxis;
412
413 VectorSet(v2, v[1], v[0], v[2]);
414 VectorSet(rotationAxis, 0, 0, 1);
415 RotatePointAroundVector(v1, rotationAxis, v2, -rotate[PITCH]);
416 VectorSet(rotationAxis, 0, 1, 0);
417 RotatePointAroundVector(v2, rotationAxis, v1, -rotate[YAW]);
418
419 Vector4Set(r, earthPos[0] + celestialDist * v2[1], earthPos[1] + celestialDist * v2[0], -celestialDist * v2[2], 0);
420}
421
430void R_Draw3DGlobe (const vec2_t pos, const vec2_t size, int day, int second, const vec3_t rotate, float zoom, const char* map,
431 bool disableSolarRender, float ambient, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t* r_xviTexture,
432 image_t* r_radarTexture, bool renderNationGlow)
433{
434 /* globe scaling */
435 const float fullscale = zoom / STANDARD_3D_ZOOM;
436
437 /* lighting colors */
438 static const vec4_t diffuseLightColor = { 1.75f, 1.75f, 1.75f, 1.0f };
439 static const vec4_t specularLightColor = { 2.0f, 1.9f, 1.7f, 1.0f };
440 static const vec4_t darknessLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
441 static const vec4_t brightDiffuseLightColor = { 5.0f, 5.0f, 5.0f, 1.0f };
442 const vec4_t ambientLightColor = { ambient + 0.2f, ambient + 0.2f, ambient + 0.2f, ambient + 0.2f };
443 /* billboard textures */
444 image_t* starfield;
445 image_t* sun;
446 image_t* sunOverlay;
447
448 /* set distance of the sun and moon to make them static on starfield when
449 * time is stoped. this distance should be used for any celestial body
450 * considered at infinite location (sun, moon) */
451 static const float celestialDist = 1.37f * SKYBOX_HALFSIZE;
452 static const float moonSize = 0.025f;
453 vec4_t sunPos;
454 vec4_t antiSunPos;
455 vec4_t moonLoc;
456 vec4_t sunLoc;
457
458 /* normalize */
459 const float nx = pos[0] * viddef.rx;
460 const float ny = pos[1] * viddef.ry;
461 const float nw = size[0] * viddef.rx;
462 const float nh = size[1] * viddef.ry;
463
464 /* Earth center is in the middle of node.
465 * Due to Orthographic view, this is also camera position */
466 const vec3_t earthPos = { nx + nw / 2.0f, ny + nh / 2.0f, 0.0f };
467
468 /* estimate the progress through the current season so we can do
469 * smooth transitions between textures. Currently there are 12
470 * "seasons", because we have one image per Earth-month. */
471 const float season = (float) (day % DateTime::DAYS_PER_YEAR) / ((float) (DateTime::DAYS_PER_YEAR) / (float) (DateTime::SEASONS_PER_YEAR));
472 const int currSeason = (int) floorf(season) % DateTime::SEASONS_PER_YEAR;
473 const int nextSeason = (int) ceilf(season) % DateTime::SEASONS_PER_YEAR;
474 const float seasonProgress = season - (float) currSeason;
475
476 /* Compute sun position in absolute frame */
477 const float q = (day % DateTime::DAYS_PER_YEAR * DateTime::SECONDS_PER_DAY + second) * (2.0f * M_PI / (DateTime::SECONDS_PER_DAY * DateTime::DAYS_PER_YEAR)); /* sun rotation (year) */
478 const float a = cos(q) * SIN_ALPHA; /* due to earth obliquity */
479 const float sqrta = sqrt(0.5f * (1 - a * a));
480
481 /* earth rotation (day) */
482 const float p = (second - DateTime::SECONDS_PER_DAY / 4) * (2.0f * M_PI / DateTime::SECONDS_PER_DAY);
483 /* lunar orbit */
484 const float m = p + (((double)((10 * day % 249) / 10.0f) + ((double)second / (double)DateTime::SECONDS_PER_DAY)) / 24.9f) * (2.0f * M_PI);
485
486 glPushMatrix();
487 glMatrixMode(GL_TEXTURE);
488 glLoadIdentity();
489 glMatrixMode(GL_MODELVIEW);
490 glDisable(GL_LIGHTING);
491 /* draw the starfield, rotating with the planet */
492 starfield = R_FindImage(va("pics/geoscape/%s_stars", map), it_wrappic);
493 if (starfield != r_noTexture)
494 R_DrawStarfield(starfield->texnum, earthPos, rotate, p);
495
496 glPopMatrix();
497
498 /* set up position vectors for celestial bodies */
499 Vector4Set(sunPos, cos(p) * sqrta, -sin(p) * sqrta, a, 0);
500 Vector4Set(antiSunPos, -cos(p) * sqrta, sin(p) * sqrta, -a, 0);
501
502 /* Rotate the sun in the relative frame of player view, to get sun location */
503 R_RotateCelestialBody(sunPos, sunLoc, rotate, earthPos, 1.0f);
504 /* load sun texture image */
505 sun = R_FindImage(va("pics/geoscape/%s_sun", map), it_wrappic);
506 sunOverlay = R_FindImage(va("pics/geoscape/%s_sun_overlay", map), it_pic);
507 if (sun != r_noTexture && sunOverlay != r_noTexture && sunLoc[2] > 0 && !disableSolarRender) {
508 const int sunx = earthPos[0] + viddef.rx * (-128.0f + celestialDist * (sunLoc[0] - earthPos[0]));
509 const int suny = earthPos[1] + viddef.ry * (-128.0f + celestialDist * (sunLoc[1] - earthPos[1]));
510
511 R_DrawTexture(sunOverlay->texnum, sunx, suny, 256.0f * viddef.rx, 256.0f * viddef.ry);
512 R_DrawBuffers(2);
513 R_DrawTexture(sun->texnum, sunx, suny, 256.0 * viddef.rx, 256.0 * viddef.ry);
514 R_DrawBuffers(1);
515 }
516
517 /* calculate position of the moon (it rotates around earth with a period of
518 * about 24.9 h, and we must take day into account to avoid moon to "jump"
519 * every time the day is changing) */
520 VectorSet(moonLoc, cos(m) * sqrta, -sin(m) * sqrta, a);
521 R_RotateCelestialBody(moonLoc, moonLoc, rotate, earthPos, celestialDist);
522
523 /* free last month's texture image */
524 if (r_globeEarth.season != currSeason) {
525 r_globeEarth.season = currSeason;
526 R_FreeImage(r_globeEarth.texture);
527 }
528
529 /* load diffuse texture map (with embedded night-glow map as alpha channel) */
530 r_globeEarth.texture = R_FindImage(va("pics/geoscape/%s/%s_season_%02d", r_config.lodDir, map, currSeason), it_wrappic);
531 if (r_globeEarth.texture == r_noTexture)
532 Com_Error(ERR_FATAL, "Could not find pics/geoscape/%s/%s_season_%02d\n", r_config.lodDir, map, currSeason);
533
534 /* set up for advanced GLSL rendering if we have the capability */
535 if (r_programs->integer) {
536 r_globeEarth.glslProgram = r_state.geoscape_program;
537 /* load earth image for the next month so we can blend them */
538 r_globeEarth.blendTexture = R_FindImage(va("pics/geoscape/%s/%s_season_%02d", r_config.lodDir, map, nextSeason), it_wrappic);
539 if (r_globeEarth.blendTexture == r_noTexture)
540 Com_Error(ERR_FATAL, "Could not find pics/geoscape/%s/%s_season_%02d\n", r_config.lodDir, map, nextSeason);
541
542 /* load normal map (with embedded gloss map as alpha channel) */
543 r_globeEarth.normalMap = R_FindImage(va("pics/geoscape/%s/%s_bump", r_config.lodDir, map), it_wrappic);
544 if (r_globeEarth.normalMap == r_noTexture)
545 r_globeEarth.normalMap = nullptr;
546
547 /* weight the blending based on how much of the month has elapsed */
548 r_globeEarth.blendScale = seasonProgress;
549 /* set up lights for nighttime city glow */
550 VectorCopy(antiSunPos, r_globeEarth.nightLightPos);
551 glLightfv(GL_LIGHT1, GL_AMBIENT, darknessLightColor);
552 glLightfv(GL_LIGHT1, GL_DIFFUSE, brightDiffuseLightColor);
553 glLightfv(GL_LIGHT1, GL_SPECULAR, darknessLightColor);
554
555 r_globeEarth.glowScale = 0.7f;
556 }
557
558 /* load moon texture image */
559 r_globeMoon.texture = R_FindImage(va("pics/geoscape/%s_moon", map), it_wrappic);
560
561 /* globe texture scaling */
562 glMatrixMode(GL_TEXTURE);
563 glLoadIdentity();
564 glScalef(2.0f, 1.0f, 1.0f);
565 glMatrixMode(GL_MODELVIEW);
566
567 /* enable the lighting */
568 glEnable(GL_LIGHTING);
569 glEnable(GL_LIGHT0);
570 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLightColor);
571 glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLightColor);
572 glLightfv(GL_LIGHT0, GL_SPECULAR, specularLightColor);
573
574 /* draw the moon */
575 if (r_globeMoon.texture != r_noTexture && moonLoc[2] > 0 && !disableSolarRender)
576 R_SphereRender(&r_globeMoon, moonLoc, rotate, moonSize, sunPos);
577
578 /* activate depth to hide 3D models behind earth */
579 glEnable(GL_DEPTH_TEST);
580
581 /* draw the earth */
582 R_DrawBuffers(2);
583#if 0 /* old rendering code which doesn't render city lights in FFP */
584 if (r_programs->integer == 0) /* ignore alpha channel, since the city-light map is stored there */
585 glBlendFunc(GL_ONE, GL_ZERO);
586
587 R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
588
589 if (r_programs->integer == 0) /* restore default blend function */
590 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
591#else /* new which does render city lights in FFP */
592 if (r_programs->integer == 0) {
593 /* set up rendering of city lights map, which is stored in alpha channel; OpenGL 1.3 required */
594 R_SelectTexture(&texunit_diffuse); /* select texture to edit texture environment for */
595 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); /* enable color combiner */
596 /* setup texture combiner to blend between daylight diffuse map stored in the RGB channels of the diffuse texture
597 * and the monochomatic emission map (which simulates city lights) stored in the alpha channel;
598 * incoming color value is the blend factor.
599 */
600 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); /* set day color as blending target*/
601 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
602 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); /* set night color as blending source */
603 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
604 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS); /* set incoming color as blending factor */
605 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
606 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); /* set blending mode to interpolation from src1 to src0 */
607 /* copy alpha from incoming color, bypassing the value read from texture, which is not a "real" alpha anyway */
608 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
609 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
610 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
611 }
612
613 R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
614
615 if (r_programs->integer == 0) { /* disable combiner */
617 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
618 }
619#endif
620
621 r_globeEarthAtmosphere.texture = R_FindImage(va("pics/geoscape/%s_atmosphere", map), it_wrappic);
622
623 /* Draw earth atmosphere */
625 if (r_programs->integer && r_postprocess->integer) {
626 r_globeEarthAtmosphere.normalMap = r_globeEarth.normalMap;
627 r_globeEarthAtmosphere.glowScale = 1.0;
628 r_globeEarthAtmosphere.blendScale = -1.0;
629 r_globeEarthAtmosphere.glslProgram = r_state.atmosphere_program;
630 R_SphereRender(&r_globeEarthAtmosphere, earthPos, rotate, fullscale, sunPos);
631 } else {
632 image_t* halo = R_FindImage("pics/geoscape/map_earth_halo", it_pic);
633 if (halo != r_noTexture) {
635 const float earthSizeX = fullscale * 20500.0f * viddef.rx;
636 const float earthSizeY = fullscale * 20500.0f * viddef.ry;
637 glMatrixMode(GL_TEXTURE);
638 glPushMatrix();
639 glLoadIdentity();
640 glDisable(GL_LIGHTING);
641
642 R_DrawTexture(halo->texnum, earthPos[0] - earthSizeX * 0.5f, earthPos[1] - earthSizeY * 0.5f, earthSizeX, earthSizeY);
643 glEnable(GL_LIGHTING);
644 glPopMatrix();
645 glMatrixMode(GL_MODELVIEW);
646 }
647 }
648
649 R_DrawBuffers(1);
650 glDisable(GL_DEPTH_TEST);
651
652 /* draw nation overlay */
653 if (overlayNation) {
654 r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
655 if (r_globeEarth.overlay == r_noTexture)
656 Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");
657
658 R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
659
660 if (renderNationGlow) {
661 /* draw glowing borders */
662 r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_nations_overlay_glow", map), it_wrappic);
663 if (r_globeEarth.overlay == r_noTexture)
664 Com_Error(ERR_FATAL, "Could not load geoscape nation overlay glow image");
665
666 R_DrawBuffers(2);
667 glDisable(GL_LIGHTING);
668 R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
669 glEnable(GL_LIGHTING);
670 R_DrawBuffers(1);
671 }
672
673 r_globeEarth.overlay = nullptr;
674 }
675 /* draw XVI overlay */
676 if (overlayXVI) {
677 r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
678 r_globeEarth.overlayAlphaMask = r_xviTexture;
679 assert(r_globeEarth.overlayAlphaMask);
680 R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
681 r_globeEarth.overlayAlphaMask = nullptr;
682 r_globeEarth.overlay = nullptr;
683 }
684 /* draw radar overlay */
685 if (overlayRadar) {
687 assert(r_globeEarth.overlay);
688 R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
689 r_globeEarth.overlay = nullptr;
690 }
691
692 /* disable 3d geoscape lighting */
693 glDisable(GL_LIGHTING);
694
695 /* restore the previous matrix */
696 glMatrixMode(GL_TEXTURE);
697 glLoadIdentity();
698 glMatrixMode(GL_MODELVIEW);
699}
700
704static inline void R_DrawQuad (void)
705{
707 const vec2_t texcoord[] = { { 0.0f, 1.0f }, { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 0.0f, 0.0f } };
708 const vec2_t verts[] = { { 0.0f, 0.0f }, Vector2FromInt(fbo_render->width, 0.0f), Vector2FromInt(fbo_render->width, fbo_render->height), Vector2FromInt(0.0f, fbo_render->height) };
709
710 glVertexPointer(2, GL_FLOAT, 0, verts);
711 R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoord);
712
713 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
714
715 refdef.batchCount++;
716
717 R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
718 R_BindDefaultArray(GL_VERTEX_ARRAY);
719}
720
725static void R_Blur (r_framebuffer_t* source, r_framebuffer_t* dest, int tex, int dir)
726{
727 R_EnableBlur(r_state.convolve_program, true, source, dest, dir);
728
729 /* draw new texture onto a flat surface */
731 R_UseViewport(source);
732 R_DrawQuad();
733
734 R_EnableBlur(r_state.convolve_program, false, nullptr, nullptr, 0);
735}
736
740static void R_BlurStack (int levels, r_framebuffer_t** sources, r_framebuffer_t** dests)
741{
742 for (int i = 0; i < levels; i++) {
743 const int l = levels - i - 1;
744
745 R_UseProgram(i == 0 ? default_program : r_state.combine2_program);
746 R_UseFramebuffer(dests[l]);
747 R_BindTextureForTexUnit(sources[l]->textures[0], &texunit_0);
748 if (i != 0)
749 R_BindTextureForTexUnit(dests[l + 1]->textures[0], &texunit_1);
750
752 R_DrawQuad();
753
754 R_Blur(dests[l], sources[l], 0, 1);
755 R_Blur(sources[l], dests[l], 0, 0);
756 }
757}
758
762void R_DrawBloom (void)
763{
764 int i;
765 bool renderBufferState;
766
767 if (!r_config.frameBufferObject || !r_postprocess->integer || !r_programs->integer)
768 return;
769
770 /* save state, then set up for blit-style rendering to quads */
771 renderBufferState = R_RenderbufferEnabled();
772 glMatrixMode(GL_MODELVIEW);
773 glPushMatrix();
774 glLoadIdentity();
775 glMatrixMode(GL_TEXTURE);
776 glPushMatrix();
777 glLoadIdentity();
778 glMatrixMode(GL_PROJECTION);
779 glPushMatrix();
780 glLoadIdentity();
781#ifndef GL_VERSION_ES_CM_1_0
782 glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT);
783#endif
784 glOrtho(0, viddef.context.width, viddef.context.height, 0, 9999.0f, SKYBOX_DEPTH);
785
786 glDisable(GL_LIGHTING);
787 glDisable(GL_DEPTH_TEST);
788
789 /* downsample into image pyramid */
791 R_BindTexture(fbo_render->textures[1]);
792 qglGenerateMipmapEXT(GL_TEXTURE_2D);
793
796
797 R_UseFramebuffer(r_state.buffers0[0]);
798 R_BindTexture(fbo_bloom1->textures[0]);
799 qglGenerateMipmapEXT(GL_TEXTURE_2D);
800 R_UseViewport(r_state.buffers0[0]);
801 R_DrawQuad();
802
803 for (i = 1; i < DOWNSAMPLE_PASSES; i++) {
804 R_Blur(r_state.buffers0[i - 1], r_state.buffers1[i - 1], 0, 0);
805 R_Blur(r_state.buffers1[i - 1], r_state.buffers2[i - 1], 0, 1);
806 R_UseFramebuffer(r_state.buffers0[i]);
807 R_BindTexture(r_state.buffers2[i - 1]->textures[0]);
808 R_UseViewport(r_state.buffers0[i]);
809 R_DrawQuad();
810 }
811
812 /* blur and combine downsampled images */
813 R_BlurStack(DOWNSAMPLE_PASSES, r_state.buffers0, r_state.buffers1);
814
815 /* re-combine the blurred version with the original "glow" image */
816 R_UseProgram(r_state.combine2_program);
819 R_BindTextureForTexUnit(r_state.buffers1[0]->textures[0], &texunit_1);
820
822 R_DrawQuad();
823
824 /* draw final result to the screenbuffer */
826 R_UseProgram(r_state.combine2_program);
829
830 R_DrawQuad();
831
832 /* cleanup before returning */
834
835 R_CheckError();
836
837#ifndef GL_VERSION_ES_CM_1_0
838 glPopAttrib();
839#endif
840 glMatrixMode(GL_PROJECTION);
841 glPopMatrix();
842 glMatrixMode(GL_TEXTURE);
843 glPopMatrix();
844 glMatrixMode(GL_MODELVIEW);
845 glPopMatrix();
846 R_CheckError();
847
848 /* reset renderbuffer state to what it was before */
849 R_EnableRenderbuffer(renderBufferState);
850}
DateTime class definition.
rendererData_t refdef
Definition r_main.cpp:45
viddef_t viddef
Definition cl_video.cpp:34
static const short SEASONS_PER_YEAR
Definition DateTime.h:40
static const int SECONDS_PER_DAY
Definition DateTime.h:43
static const int DAYS_PER_YEAR
Definition DateTime.h:37
void Com_Error(int code, const char *fmt,...)
Definition common.cpp:459
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define ERR_FATAL
Definition common.h:210
voidpf void uLong size
Definition ioapi.h:42
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
const vec3_t vec3_origin
Definition mathlib.cpp:35
void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees)
Rotate a point around a given vector.
Definition mathlib.cpp:849
#define YAW
Definition mathlib.h:55
#define PITCH
Definition mathlib.h:54
#define SIN_ALPHA
Definition mathlib.h:65
#define todeg
Definition mathlib.h:51
#define M_PI
Definition mathlib.h:34
#define ROLL
Definition mathlib.h:56
static struct mdfour * m
Definition md4.cpp:35
void R_DrawTexture(int texnum, int x, int y, int w, int h)
Bind and draw a texture.
Definition r_draw.cpp:328
Error checking function.
#define R_CheckError()
Definition r_error.h:30
void R_UseFramebuffer(const r_framebuffer_t *buf)
bind specified framebuffer object so we render to it
bool R_EnableRenderbuffer(bool enable)
Enable the render to the framebuffer.
void R_UseViewport(const r_framebuffer_t *buf)
Set the viewport to the dimensions of the given framebuffer.
void R_DrawBuffers(unsigned int drawBufferNum)
Activate draw buffer(s).
void R_ResolveMSAA(const r_framebuffer_t *buf)
Forces multisample antialiasing resolve on given framebuffer, if needed.
bool R_RenderbufferEnabled(void)
static void R_DrawQuad(void)
Draw the current texture on a quad the size of the renderbuffer.
void R_DrawFlatGeoscape(const vec2_t nodePos, const vec2_t nodeSize, float p, float cx, float cy, float iz, const char *map, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t *r_dayandnightTexture, image_t *r_xviTexture, image_t *r_radarTexture)
Draw the day and night images of a flat geoscape multitexture feature is used to blend the images.
void R_Draw3DMapMarkers(const vec2_t nodePos, const vec2_t nodeSize, const vec3_t rotate, const vec2_t pos, float direction, float earthRadius, const char *model, int skin)
Draw 3D Marker on the 3D geoscape.
static void R_RotateCelestialBody(const vec4_t v, vec4_t r, const vec3_t rotate, const vec3_t earthPos, const float celestialDist)
rotate a planet (sun or moon) with respect to the earth
void R_Draw2DMapMarkers(const vec2_t screenPos, float direction, const char *model, int skin)
Draw 3D Marker on the 2D geoscape.
void R_DrawBloom(void)
handle post-processing bloom
void R_Draw3DGlobe(const vec2_t pos, const vec2_t size, int day, int second, const vec3_t rotate, float zoom, const char *map, bool disableSolarRender, float ambient, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t *r_xviTexture, image_t *r_radarTexture, bool renderNationGlow)
responsible for drawing the 3d globe on geoscape param[in] rotate the rotate angle of the globe param...
static void R_BlurStack(int levels, r_framebuffer_t **sources, r_framebuffer_t **dests)
blur from the source image pyramid into the dest image pyramid
#define MARKER_SIZE
static void R_DrawStarfield(int texnum, const vec3_t pos, const vec3_t rotate, float timeOfDay)
Bind and draw starfield.
#define SKYBOX_HALFSIZE
Half size of Skybox.
static const float starFieldVerts[]
static void R_Blur(r_framebuffer_t *source, r_framebuffer_t *dest, int tex, int dir)
does 1D filter convolution to blur a framebuffer texture. dir=0 for horizontal, dir=1 for vertical
static const float starFieldTexCoords[]
#define STANDARD_3D_ZOOM
Typical zoom to use on the 3D geoscape to use same zoom values for both 2D and 3D geoscape.
Definition r_geoscape.h:32
QGL_EXTERN GLuint GLchar ** sources
Definition r_gl.h:99
QGL_EXTERN GLenum GLuint * dest
Definition r_gl.h:101
QGL_EXTERN int GLboolean GLfloat * v
Definition r_gl.h:120
QGL_EXTERN GLint i
Definition r_gl.h:113
#define GL_SOURCE2_RGB
#define GL_SOURCE1_RGB
#define GL_SOURCE0_RGB
#define GL_SOURCE0_ALPHA
void R_FreeImage(image_t *image)
Free the image and its assigned maps (roughness, normal, specular, glow - if there are any).
Definition r_image.cpp:735
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
Definition r_image.cpp:603
image_t * r_noTexture
Definition r_main.cpp:51
@ it_pic
Definition r_image.h:45
@ it_wrappic
Definition r_image.h:46
local graphics definitions
cvar_t * r_postprocess
Definition r_main.cpp:100
cvar_t * r_programs
Definition r_main.cpp:97
rconfig_t r_config
Definition r_main.cpp:47
rstate_t r_state
Definition r_main.cpp:48
void R_DrawModelDirect(modelInfo_t *mi, modelInfo_t *pmi, const char *tagname)
Draws a model in 2d mode (for rendering model data from the ui).
Definition r_mesh.cpp:306
void R_ModelAutoScale(const vec2_t boxSize, modelInfo_t *mi, vec3_t scale, vec3_t center)
Compute scale and center for a model info data structure.
Definition r_mesh.cpp:278
model_t * R_FindModel(const char *name)
Tries to load a model.
Definition r_model.cpp:203
void R_UseProgram(r_program_t *prog)
Definition r_program.cpp:43
sphere_t r_globeEarth
Definition r_sphere.cpp:33
sphere_t r_globeEarthAtmosphere
Definition r_sphere.cpp:35
void R_SphereRender(const sphere_t *sphere, const vec3_t pos, const vec3_t rotate, const float scale, const vec4_t lightPos)
Draw the sphere.
Definition r_sphere.cpp:247
sphere_t r_globeMoon
Definition r_sphere.cpp:34
Functions to generate and render spheres.
void R_EnableTexture(gltexunit_t *texunit, bool enable)
Definition r_state.cpp:303
void R_BindDefaultArray(GLenum target)
Binds the appropriate shared vertex array to the specified target.
Definition r_state.cpp:182
void R_EnableBlur(r_program_t *program, bool enable, r_framebuffer_t *source, r_framebuffer_t *dest, int dir)
Definition r_state.cpp:523
bool R_SelectTexture(gltexunit_t *texunit)
Returns false if the texunit is not supported.
Definition r_state.cpp:40
void R_BindLightmapTexture(GLuint texnum)
Definition r_state.cpp:90
void R_BindTextureForTexUnit(GLuint texnum, gltexunit_t *texunit)
Definition r_state.cpp:77
void R_BindArray(GLenum target, GLenum type, const void *array)
Definition r_state.cpp:148
#define default_program
Definition r_state.h:92
#define DOWNSAMPLE_PASSES
Definition r_state.h:84
#define texunit_diffuse
Definition r_state.h:68
#define SKYBOX_DEPTH
Center position of skybox along z-axis. This is used to make sure we see only the inside of Skybox.
Definition r_state.h:41
#define texunit_lightmap
Definition r_state.h:69
#define fbo_render
Definition r_state.h:88
#define fbo_bloom0
Definition r_state.h:89
#define fbo_bloom1
Definition r_state.h:90
#define texunit_1
Definition r_state.h:62
#define R_BindTexture(tn)
Definition r_state.h:184
#define fbo_screen
Definition r_state.h:87
#define texunit_0
Definition r_state.h:61
#define OBJZERO(obj)
Definition shared.h:178
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
GLuint texnum
Definition r_image.h:66
float * origin
Definition cl_renderer.h:61
float * center
Definition cl_renderer.h:64
float * angles
Definition cl_renderer.h:62
const char * name
Definition cl_renderer.h:59
model_t * model
Definition cl_renderer.h:58
unsigned int * textures
vec_t vec3_t[3]
Definition ufotypes.h:39
vec_t vec4_t[4]
Definition ufotypes.h:40
vec_t vec2_t[2]
Definition ufotypes.h:38
static const vec3_t scale
image_t * r_dayandnightTexture
image_t * r_xviTexture
image_t * r_radarTexture
#define Vector2FromInt(x, y)
Definition vector.h:40
#define Vector4Set(v, r, g, b, a)
Definition vector.h:62
#define VectorCopy(src, dest)
Definition vector.h:51
#define VectorSet(v, x, y, z)
Definition vector.h:59