Quake II RTX doxygen  1.0 dev
sky.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "gl.h"
20 
21 static float skyrotate;
22 static vec3_t skyaxis;
23 static int sky_images[6];
24 
25 static const vec3_t skyclip[6] = {
26  { 1, 1, 0 },
27  { 1, -1, 0 },
28  { 0, -1, 1 },
29  { 0, 1, 1 },
30  { 1, 0, 1 },
31  { -1, 0, 1 }
32 };
33 
34 // 1 = s, 2 = t, 3 = 2048
35 static const int st_to_vec[6][3] = {
36  { 3, -1, 2 },
37  { -3, 1, 2 },
38 
39  { 1, 3, 2 },
40  { -1, -3, 2 },
41 
42  { -2, -1, 3 }, // 0 degrees yaw, look straight up
43  { 2, -1, -3 } // look straight down
44 };
45 
46 // s = [0]/[2], t = [1]/[2]
47 static const int vec_to_st[6][3] = {
48  { -2, 3, 1 },
49  { 2, 3, -1 },
50 
51  { 1, 3, 2 },
52  { -1, 3, -2 },
53 
54  { -2, -1, 3 },
55  { -2, 1, -3 }
56 };
57 
58 static vec3_t skymatrix[3];
59 static float skymins[2][6], skymaxs[2][6];
60 static int skyfaces;
61 static const float sky_min = 1.0f / 512.0f;
62 static const float sky_max = 511.0f / 512.0f;
63 
64 static void DrawSkyPolygon(int nump, vec3_t vecs)
65 {
66  int i, j;
67  vec3_t v, av;
68  float s, t, dv;
69  int axis;
70  float *vp;
71 
72  // decide which face it maps to
73  VectorClear(v);
74  for (i = 0, vp = vecs; i < nump; i++, vp += 3) {
75  VectorAdd(vp, v, v);
76  }
77  av[0] = fabs(v[0]);
78  av[1] = fabs(v[1]);
79  av[2] = fabs(v[2]);
80  if (av[0] > av[1] && av[0] > av[2]) {
81  if (v[0] < 0)
82  axis = 1;
83  else
84  axis = 0;
85  } else if (av[1] > av[2] && av[1] > av[0]) {
86  if (v[1] < 0)
87  axis = 3;
88  else
89  axis = 2;
90  } else {
91  if (v[2] < 0)
92  axis = 5;
93  else
94  axis = 4;
95  }
96 
97  // project new texture coords
98  for (i = 0; i < nump; i++, vecs += 3) {
99  j = vec_to_st[axis][2];
100  if (j > 0)
101  dv = vecs[j - 1];
102  else
103  dv = -vecs[-j - 1];
104  if (dv < 0.001)
105  continue; // don't divide by zero
106  j = vec_to_st[axis][0];
107  if (j < 0)
108  s = -vecs[-j - 1] / dv;
109  else
110  s = vecs[j - 1] / dv;
111  j = vec_to_st[axis][1];
112  if (j < 0)
113  t = -vecs[-j - 1] / dv;
114  else
115  t = vecs[j - 1] / dv;
116 
117  if (s < skymins[0][axis])
118  skymins[0][axis] = s;
119  if (t < skymins[1][axis])
120  skymins[1][axis] = t;
121  if (s > skymaxs[0][axis])
122  skymaxs[0][axis] = s;
123  if (t > skymaxs[1][axis])
124  skymaxs[1][axis] = t;
125  }
126 }
127 
128 #define ON_EPSILON 0.1 // point on plane side epsilon
129 #define MAX_CLIP_VERTS 64
130 
131 #define SIDE_FRONT 0
132 #define SIDE_BACK 1
133 #define SIDE_ON 2
134 
135 static void ClipSkyPolygon(int nump, vec3_t vecs, int stage)
136 {
137  const float *norm;
138  float *v;
139  qboolean front, back;
140  float d, e;
141  float dists[MAX_CLIP_VERTS];
142  int sides[MAX_CLIP_VERTS];
143  vec3_t newv[2][MAX_CLIP_VERTS];
144  int newc[2];
145  int i, j;
146 
147  if (nump > MAX_CLIP_VERTS - 2) {
148  Com_DPrintf("%s: too many verts\n", __func__);
149  return;
150  }
151 
152  if (stage == 6) {
153  // fully clipped, so draw it
154  DrawSkyPolygon(nump, vecs);
155  return;
156  }
157 
158  front = back = qfalse;
159  norm = skyclip[stage];
160  for (i = 0, v = vecs; i < nump; i++, v += 3) {
161  d = DotProduct(v, norm);
162  if (d > ON_EPSILON) {
163  front = qtrue;
164  sides[i] = SIDE_FRONT;
165  } else if (d < -ON_EPSILON) {
166  back = qtrue;
167  sides[i] = SIDE_BACK;
168  } else {
169  sides[i] = SIDE_ON;
170  }
171  dists[i] = d;
172  }
173 
174  if (!front || !back) {
175  // not clipped
176  ClipSkyPolygon(nump, vecs, stage + 1);
177  return;
178  }
179 
180  // clip it
181  sides[i] = sides[0];
182  dists[i] = dists[0];
183  VectorCopy(vecs, (vecs + (i * 3)));
184  newc[0] = newc[1] = 0;
185 
186  for (i = 0, v = vecs; i < nump; i++, v += 3) {
187  switch (sides[i]) {
188  case SIDE_FRONT:
189  VectorCopy(v, newv[0][newc[0]]);
190  newc[0]++;
191  break;
192  case SIDE_BACK:
193  VectorCopy(v, newv[1][newc[1]]);
194  newc[1]++;
195  break;
196  case SIDE_ON:
197  VectorCopy(v, newv[0][newc[0]]);
198  newc[0]++;
199  VectorCopy(v, newv[1][newc[1]]);
200  newc[1]++;
201  break;
202  }
203 
204  if (sides[i] == SIDE_ON || sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i])
205  continue;
206 
207  d = dists[i] / (dists[i] - dists[i + 1]);
208  for (j = 0; j < 3; j++) {
209  e = v[j] + d * (v[j + 3] - v[j]);
210  newv[0][newc[0]][j] = e;
211  newv[1][newc[1]][j] = e;
212  }
213  newc[0]++;
214  newc[1]++;
215  }
216 
217  // continue
218  ClipSkyPolygon(newc[0], newv[0][0], stage + 1);
219  ClipSkyPolygon(newc[1], newv[1][0], stage + 1);
220 }
221 
222 static inline void SkyInverseRotate(vec3_t out, const vec3_t in)
223 {
224  out[0] = skymatrix[0][0] * in[0] + skymatrix[1][0] * in[1] + skymatrix[2][0] * in[2];
225  out[1] = skymatrix[0][1] * in[0] + skymatrix[1][1] * in[1] + skymatrix[2][1] * in[2];
226  out[2] = skymatrix[0][2] * in[0] + skymatrix[1][2] * in[1] + skymatrix[2][2] * in[2];
227 }
228 
229 /*
230 =================
231 R_AddSkySurface
232 =================
233 */
234 void R_AddSkySurface(mface_t *fa)
235 {
236  int i;
237  vec3_t verts[MAX_CLIP_VERTS];
238  vec3_t temp;
239  msurfedge_t *surfedge;
240  mvertex_t *vert;
241 
242  if (fa->numsurfedges > MAX_CLIP_VERTS) {
243  Com_DPrintf("%s: too many verts\n", __func__);
244  return;
245  }
246 
247  // calculate vertex values for sky box
248  surfedge = fa->firstsurfedge;
249  if (skyrotate) {
250  if (!skyfaces)
252 
253  for (i = 0; i < fa->numsurfedges; i++, surfedge++) {
254  vert = surfedge->edge->v[surfedge->vert];
255  VectorSubtract(vert->point, glr.fd.vieworg, temp);
256  SkyInverseRotate(verts[i], temp);
257  }
258  } else {
259  for (i = 0; i < fa->numsurfedges; i++, surfedge++) {
260  vert = surfedge->edge->v[surfedge->vert];
261  VectorSubtract(vert->point, glr.fd.vieworg, verts[i]);
262  }
263  }
264 
265  ClipSkyPolygon(fa->numsurfedges, verts[0], 0);
266  skyfaces++;
267 }
268 
269 /*
270 ==============
271 R_ClearSkyBox
272 ==============
273 */
274 void R_ClearSkyBox(void)
275 {
276  int i;
277 
278  for (i = 0; i < 6; i++) {
279  skymins[0][i] = skymins[1][i] = 9999;
280  skymaxs[0][i] = skymaxs[1][i] = -9999;
281  }
282 
283  skyfaces = 0;
284 }
285 
286 static void MakeSkyVec(float s, float t, int axis, vec_t *out)
287 {
288  vec3_t b, v;
289  int j, k;
290 
291  b[0] = s * gl_static.world.size;
292  b[1] = t * gl_static.world.size;
293  b[2] = gl_static.world.size;
294 
295  for (j = 0; j < 3; j++) {
296  k = st_to_vec[axis][j];
297  if (k < 0)
298  v[j] = -b[-k - 1];
299  else
300  v[j] = b[k - 1];
301  }
302 
303  if (skyrotate) {
304  out[0] = DotProduct(skymatrix[0], v) + glr.fd.vieworg[0];
305  out[1] = DotProduct(skymatrix[1], v) + glr.fd.vieworg[1];
306  out[2] = DotProduct(skymatrix[2], v) + glr.fd.vieworg[2];
307  } else {
308  VectorAdd(v, glr.fd.vieworg, out);
309  }
310 
311  // avoid bilerp seam
312  s = (s + 1) * 0.5;
313  t = (t + 1) * 0.5;
314 
315  if (s < sky_min)
316  s = sky_min;
317  else if (s > sky_max)
318  s = sky_max;
319  if (t < sky_min)
320  t = sky_min;
321  else if (t > sky_max)
322  t = sky_max;
323 
324  out[3] = s;
325  out[4] = 1.0 - t;
326 }
327 
328 #define SKY_VISIBLE(side) \
329  (skymins[0][side] < skymaxs[0][side] && \
330  skymins[1][side] < skymaxs[1][side])
331 
332 /*
333 ==============
334 R_DrawSkyBox
335 ==============
336 */
337 void R_DrawSkyBox(void)
338 {
339  static const int skytexorder[6] = {0, 2, 1, 3, 4, 5};
340  vec5_t verts[4];
341  int i;
342 
343  // check for no sky at all
344  if (!skyfaces)
345  return; // nothing visible
346 
349  GL_VertexPointer(3, 5, &verts[0][0]);
350  GL_TexCoordPointer(2, 5, &verts[0][3]);
351 
352  for (i = 0; i < 6; i++) {
353  if (!SKY_VISIBLE(i)) {
354  continue;
355  }
356 
357  GL_BindTexture(0, sky_images[skytexorder[i]]);
358 
359  MakeSkyVec(skymaxs[0][i], skymins[1][i], i, verts[0]);
360  MakeSkyVec(skymins[0][i], skymins[1][i], i, verts[1]);
361  MakeSkyVec(skymaxs[0][i], skymaxs[1][i], i, verts[2]);
362  MakeSkyVec(skymins[0][i], skymaxs[1][i], i, verts[3]);
363  qglDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
364  }
365 }
366 
367 static void R_UnsetSky(void)
368 {
369  int i;
370 
371  skyrotate = 0;
372  for (i = 0; i < 6; i++) {
374  }
375 }
376 
377 /*
378 ============
379 R_SetSky
380 ============
381 */
382 void R_SetSky_GL(const char *name, float rotate, vec3_t axis)
383 {
384  int i;
385  char pathname[MAX_QPATH];
386  image_t *image;
387  size_t len;
388  // 3dstudio environment map names
389  static const char suf[6][3] = { "rt", "bk", "lf", "ft", "up", "dn" };
390 
391  if (!gl_drawsky->integer) {
392  R_UnsetSky();
393  return;
394  }
395 
396  skyrotate = rotate;
397  VectorNormalize2(axis, skyaxis);
398 
399  for (i = 0; i < 6; i++) {
400  len = Q_concat(pathname, sizeof(pathname),
401  "env/", name, suf[i], ".tga", NULL);
402  if (len >= sizeof(pathname)) {
403  R_UnsetSky();
404  return;
405  }
406  FS_NormalizePath(pathname, pathname);
407  image = IMG_Find(pathname, IT_SKY, IF_NONE);
408  if (image->texnum == TEXNUM_DEFAULT) {
409  R_UnsetSky();
410  return;
411  }
412  sky_images[i] = image->texnum;
413  }
414 }
415 
SKY_VISIBLE
#define SKY_VISIBLE(side)
Definition: sky.c:328
R_DrawSkyBox
void R_DrawSkyBox(void)
Definition: sky.c:337
image_t
struct image_s image_t
Definition: material.h:27
R_SetSky_GL
void R_SetSky_GL(const char *name, float rotate, vec3_t axis)
Definition: sky.c:382
sky_images
static int sky_images[6]
Definition: sky.c:23
skymins
static float skymins[2][6]
Definition: sky.c:59
glStatic_t::size
vec_t size
Definition: gl.h:66
MakeSkyVec
static void MakeSkyVec(float s, float t, int axis, vec_t *out)
Definition: sky.c:286
GL_BindTexture
void GL_BindTexture(GLuint tmu, GLuint texnum)
Definition: state.c:40
gl_drawsky
cvar_t * gl_drawsky
Definition: main.c:60
GLS_TEXTURE_REPLACE
@ GLS_TEXTURE_REPLACE
Definition: gl.h:289
R_UnsetSky
static void R_UnsetSky(void)
Definition: sky.c:367
GLA_VERTEX
@ GLA_VERTEX
Definition: gl.h:301
skymaxs
static float skymaxs[2][6]
Definition: sky.c:59
skyfaces
static int skyfaces
Definition: sky.c:60
TEXNUM_BLACK
#define TEXNUM_BLACK
Definition: gl.h:444
GL_ArrayBits
void GL_ArrayBits(glArrayBits_t bits)
Definition: state.c:185
TEXNUM_DEFAULT
#define TEXNUM_DEFAULT
Definition: gl.h:439
ON_EPSILON
#define ON_EPSILON
Definition: sky.c:128
glStatic_t::world
struct glStatic_t::@11 world
SkyInverseRotate
static void SkyInverseRotate(vec3_t out, const vec3_t in)
Definition: sky.c:222
vec_to_st
static const int vec_to_st[6][3]
Definition: sky.c:47
skyaxis
static vec3_t skyaxis
Definition: sky.c:22
GL_TexCoordPointer
static void GL_TexCoordPointer(GLint size, GLsizei stride, const GLfloat *pointer)
Definition: gl.h:339
SetupRotationMatrix
void SetupRotationMatrix(vec3_t matrix[3], const vec3_t dir, float degrees)
Definition: math.c:367
VectorNormalize2
vec_t VectorNormalize2(vec3_t v, vec3_t out)
Definition: shared.c:73
qglDrawArrays
#define qglDrawArrays
Definition: fixed.h:56
IMG_Find
image_t * IMG_Find(const char *name, imagetype_t type, imageflags_t flags)
Definition: images.c:1122
gl_static
glStatic_t gl_static
Definition: main.c:28
SIDE_ON
#define SIDE_ON
Definition: sky.c:133
GLA_TC
@ GLA_TC
Definition: gl.h:302
glr
glRefdef_t glr
Definition: main.c:27
GL_VertexPointer
static void GL_VertexPointer(GLint size, GLsizei stride, const GLfloat *pointer)
Definition: gl.h:334
skymatrix
static vec3_t skymatrix[3]
Definition: sky.c:58
SIDE_FRONT
#define SIDE_FRONT
Definition: sky.c:131
sky_min
static const float sky_min
Definition: sky.c:61
R_AddSkySurface
void R_AddSkySurface(mface_t *fa)
Definition: sky.c:234
skyrotate
static float skyrotate
Definition: sky.c:21
gl.h
MAX_CLIP_VERTS
#define MAX_CLIP_VERTS
Definition: sky.c:129
DrawSkyPolygon
static void DrawSkyPolygon(int nump, vec3_t vecs)
Definition: sky.c:64
skyclip
static const vec3_t skyclip[6]
Definition: sky.c:25
sky_max
static const float sky_max
Definition: sky.c:62
Q_concat
size_t Q_concat(char *dest, size_t size,...)
Definition: shared.c:758
GL_StateBits
void GL_StateBits(glStateBits_t bits)
Definition: state.c:60
R_ClearSkyBox
void R_ClearSkyBox(void)
Definition: sky.c:274
SIDE_BACK
#define SIDE_BACK
Definition: sky.c:132
FS_NormalizePath
size_t FS_NormalizePath(char *out, const char *in)
Definition: files.c:331
st_to_vec
static const int st_to_vec[6][3]
Definition: sky.c:35
glRefdef_t::fd
refdef_t fd
Definition: gl.h:81
ClipSkyPolygon
static void ClipSkyPolygon(int nump, vec3_t vecs, int stage)
Definition: sky.c:135