]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_warp.c
commented out COM_LoadCacheFile
[divverent/darkplaces.git] / gl_warp.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (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.  
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // gl_warp.c -- sky and water polygons
21
22 #include "quakedef.h"
23
24 int             skytexturenum;
25
26 rtexture_t *solidskytexture;
27 rtexture_t *alphaskytexture;
28 float   speedscale;             // for top sky and bottom sky
29
30 msurface_t      *warpface;
31
32 void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
33 {
34         int             i, j;
35         float   *v;
36
37         mins[0] = mins[1] = mins[2] = 9999;
38         maxs[0] = maxs[1] = maxs[2] = -9999;
39         v = verts;
40         for (i=0 ; i<numverts ; i++)
41                 for (j=0 ; j<3 ; j++, v++)
42                 {
43                         if (*v < mins[j])
44                                 mins[j] = *v;
45                         if (*v > maxs[j])
46                                 maxs[j] = *v;
47                 }
48 }
49
50 void SubdividePolygon (int numverts, float *verts)
51 {
52         int             i, j, k;
53         vec3_t  mins, maxs;
54         float   m;
55         float   *v;
56         vec3_t  front[64], back[64];
57         int             f, b;
58         float   dist[64];
59         float   frac;
60         glpoly_t        *poly;
61         float   s, t;
62
63         if (numverts > 60)
64                 Sys_Error ("numverts = %i", numverts);
65
66         BoundPoly (numverts, verts, mins, maxs);
67
68         for (i=0 ; i<3 ; i++)
69         {
70                 m = (mins[i] + maxs[i]) * 0.5;
71                 m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5);
72                 if (maxs[i] - m < 8)
73                         continue;
74                 if (m - mins[i] < 8)
75                         continue;
76
77                 // cut it
78                 v = verts + i;
79                 for (j=0 ; j<numverts ; j++, v+= 3)
80                         dist[j] = *v - m;
81
82                 // wrap cases
83                 dist[j] = dist[0];
84                 v-=i;
85                 VectorCopy (verts, v);
86
87                 f = b = 0;
88                 v = verts;
89                 for (j=0 ; j<numverts ; j++, v+= 3)
90                 {
91                         if (dist[j] >= 0)
92                         {
93                                 VectorCopy (v, front[f]);
94                                 f++;
95                         }
96                         if (dist[j] <= 0)
97                         {
98                                 VectorCopy (v, back[b]);
99                                 b++;
100                         }
101                         if (dist[j] == 0 || dist[j+1] == 0)
102                                 continue;
103                         if ( (dist[j] > 0) != (dist[j+1] > 0) )
104                         {
105                                 // clip point
106                                 frac = dist[j] / (dist[j] - dist[j+1]);
107                                 for (k=0 ; k<3 ; k++)
108                                         front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
109                                 f++;
110                                 b++;
111                         }
112                 }
113
114                 SubdividePolygon (f, front[0]);
115                 SubdividePolygon (b, back[0]);
116                 return;
117         }
118
119         poly = Hunk_AllocName (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float), "surfaces");
120         poly->next = warpface->polys;
121         warpface->polys = poly;
122         poly->numverts = numverts;
123         for (i=0 ; i<numverts ; i++, verts+= 3)
124         {
125                 VectorCopy (verts, poly->verts[i]);
126                 s = DotProduct (verts, warpface->texinfo->vecs[0]);
127                 t = DotProduct (verts, warpface->texinfo->vecs[1]);
128                 poly->verts[i][3] = s;
129                 poly->verts[i][4] = t;
130         }
131 }
132
133 /*
134 ================
135 GL_SubdivideSurface
136
137 Breaks a polygon up along axial 64 unit
138 boundaries so that turbulent and sky warps
139 can be done reasonably.
140 ================
141 */
142 void GL_SubdivideSurface (msurface_t *fa)
143 {
144         vec3_t          verts[64];
145         int                     numverts;
146         int                     i;
147         int                     lindex;
148         float           *vec;
149
150         warpface = fa;
151
152         //
153         // convert edges back to a normal polygon
154         //
155         numverts = 0;
156         for (i=0 ; i<fa->numedges ; i++)
157         {
158                 lindex = loadmodel->surfedges[fa->firstedge + i];
159
160                 if (lindex > 0)
161                         vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
162                 else
163                         vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
164                 VectorCopy (vec, verts[numverts]);
165                 numverts++;
166         }
167
168         SubdividePolygon (numverts, verts[0]);
169 }
170
171 //=========================================================
172
173
174
175 rtexture_t *skyboxside[6];
176
177 char skyname[256];
178
179 // LordHavoc: moved LoadTGA and LoadPCX to gl_draw.c
180
181 /*
182 ==================
183 R_LoadSkyBox
184 ==================
185 */
186 char    *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
187 void R_LoadSkyBox (void)
188 {
189         int             i;
190         char    name[1024];
191         byte*   image_rgba;
192
193         if (strlen(skyname) >= 1000)
194         {
195                 Con_Printf ("sky name too long (%i, max is 1000)\n", strlen(skyname));
196                 return;
197         }
198         for (i=0 ; i<6 ; i++)
199         {
200                 sprintf (name, "env/%s%s", skyname, suf[i]);
201                 if (!(image_rgba = loadimagepixels(name, false, 0, 0)))
202                 {
203                         sprintf (name, "gfx/env/%s%s", skyname, suf[i]);
204                         if (!(image_rgba = loadimagepixels(name, false, 0, 0)))
205                         {
206                                 Con_Printf ("Couldn't load %s\n", name);
207                                 continue;
208                         }
209                 }
210                 skyboxside[i] = R_LoadTexture(va("skyboxside%d", i), image_width, image_height, image_rgba, TEXF_RGBA | TEXF_PRECACHE);
211                 qfree(image_rgba);
212         }
213 }
214
215 void R_SetSkyBox (char *sky)
216 {
217         strcpy(skyname, sky);
218         R_LoadSkyBox ();
219 }
220
221 // LordHavoc: added LoadSky console command
222 void LoadSky_f (void)
223 {
224         switch (Cmd_Argc())
225         {
226         case 1:
227                 if (skyname[0])
228                         Con_Printf("current sky: %s\n", skyname);
229                 else
230                         Con_Printf("no skybox has been set\n", skyname);
231                 break;
232         case 2:
233                 R_SetSkyBox(Cmd_Argv(1));
234                 Con_Printf("skybox set to %s\n", skyname);
235                 break;
236         default:
237                 Con_Printf("usage: loadsky skyname\n");
238                 break;
239         }
240 }
241
242 #define R_SkyBoxPolyVec(s,t,x,y,z) \
243         glTexCoord2f((s) * (254.0f/256.0f) + (1.0f/256.0f), (t) * (254.0f/256.0f) + (1.0f/256.0f));\
244         glVertex3f((x) * 1024.0 + r_origin[0], (y) * 1024.0 + r_origin[1], (z) * 1024.0 + r_origin[2]);
245
246 void R_SkyBox(void)
247 {
248         glDisable (GL_BLEND);
249         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
250         if (lighthalf)
251                 glColor3f(0.5,0.5,0.5);
252         else
253                 glColor3f(1,1,1);
254         glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[3])); // front
255         glBegin(GL_QUADS);
256         R_SkyBoxPolyVec(1, 0,  1, -1,  1);
257         R_SkyBoxPolyVec(1, 1,  1, -1, -1);
258         R_SkyBoxPolyVec(0, 1,  1,  1, -1);
259         R_SkyBoxPolyVec(0, 0,  1,  1,  1);
260         glEnd();
261         glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[1])); // back
262         glBegin(GL_QUADS);
263         R_SkyBoxPolyVec(1, 0, -1,  1,  1);
264         R_SkyBoxPolyVec(1, 1, -1,  1, -1);
265         R_SkyBoxPolyVec(0, 1, -1, -1, -1);
266         R_SkyBoxPolyVec(0, 0, -1, -1,  1);
267         glEnd();
268         glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[0])); // right
269         glBegin(GL_QUADS);
270         R_SkyBoxPolyVec(1, 0,  1,  1,  1);
271         R_SkyBoxPolyVec(1, 1,  1,  1, -1);
272         R_SkyBoxPolyVec(0, 1, -1,  1, -1);
273         R_SkyBoxPolyVec(0, 0, -1,  1,  1);
274         glEnd();
275         glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[2])); // left
276         glBegin(GL_QUADS);
277         R_SkyBoxPolyVec(1, 0, -1, -1,  1);
278         R_SkyBoxPolyVec(1, 1, -1, -1, -1);
279         R_SkyBoxPolyVec(0, 1,  1, -1, -1);
280         R_SkyBoxPolyVec(0, 0,  1, -1,  1);
281         glEnd();
282         glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[4])); // up
283         glBegin(GL_QUADS);
284         R_SkyBoxPolyVec(1, 0,  1, -1,  1);
285         R_SkyBoxPolyVec(1, 1,  1,  1,  1);
286         R_SkyBoxPolyVec(0, 1, -1,  1,  1);
287         R_SkyBoxPolyVec(0, 0, -1, -1,  1);
288         glEnd();
289         glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[5])); // down
290         glBegin(GL_QUADS);
291         R_SkyBoxPolyVec(1, 0,  1,  1, -1);
292         R_SkyBoxPolyVec(1, 1,  1, -1, -1);
293         R_SkyBoxPolyVec(0, 1, -1, -1, -1);
294         R_SkyBoxPolyVec(0, 0, -1,  1, -1);
295         glEnd();
296 }
297
298 /*
299 float skydomeouter[33*33*3];
300 float skydomeinner[33*33*3];
301 unsigned short skydomeindices[32*66];
302 qboolean skydomeinitialized = 0;
303 void skydomecalc(float *dome, float dx, float dy, float dz)
304 {
305         float a, b, x, ax, ay;
306         int i;
307         unsigned short *index;
308         for (a = 0;a <= 1;a += (1.0 / 32.0))
309         {
310                 ax = cos(a * M_PI * 2);
311                 ay = -sin(a * M_PI * 2);
312                 for (b = 0;b <= 1;b += (1.0 / 32.0))
313                 {
314                         x = cos(b * M_PI * 2);
315                         *dome++ = ax*x * dx;
316                         *dome++ = ay*x * dy;
317                         *dome++ = -sin(b * M_PI * 2) * dz;
318                 }
319         }
320         index = skydomeindices;
321         for (i = 0;i < (32*33);i++)
322         {
323                 *index++ = i;
324                 *index++ = i + 33;
325         }
326 }
327
328 void skydome(float *source, float s, float texscale)
329 {
330         vec_t vert[33*33][3], tex[33*33][2], *v, *t;
331         int i, j;
332         unsigned short *index;
333         v = &vert[0][0];t = &tex[0][0];
334         for (i = 0;i < (33*33);i++)
335         {
336                 *t++ = source[0] * texscale + s;
337                 *t++ = source[1] * texscale + s;
338                 *v++ = *source++ + r_origin[0];
339                 *v++ = *source++ + r_origin[1];
340                 *v++ = *source++ + r_origin[2];
341         }
342         glTexCoordPointer(2, GL_FLOAT, 0, tex);
343         glVertexPointer(3, GL_FLOAT, 0, vert);
344         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
345         glEnableClientState(GL_VERTEX_ARRAY);
346 //      glInterleavedArrays(GL_T2F_V3F, 0, vert);
347         for (i = 0;i < (32*66);i+=66)
348                 glDrawElements(GL_TRIANGLE_STRIP, 66, GL_UNSIGNED_SHORT, &skydomeindices[i]);
349         glDisableClientState(GL_VERTEX_ARRAY);
350         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
351 }
352
353 void R_SkyDome(void)
354 {
355         glDisable (GL_BLEND);
356         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
357         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
358         if (lighthalf)
359                 glColor3f(0.5,0.5,0.5);
360         else
361                 glColor3f(1,1,1);
362         glBindTexture(GL_TEXTURE_2D, solidskytexture); // upper clouds
363         if (!skydomeinitialized)
364         {
365                 skydomeinitialized = true;
366                 skydomecalc(skydomeouter, 1024, 1024, 256);
367                 skydomecalc(skydomeinner, 512, 512, 128);
368         }
369         speedscale = cl.time*8.0/256.0;
370         speedscale -= (int)speedscale;
371         skydome(skydomeouter, speedscale, 1.0 / 256.0);
372         glEnable (GL_BLEND);
373         glBindTexture(GL_TEXTURE_2D, alphaskytexture); // lower clouds
374         speedscale = cl.time*8.0/128.0;
375         speedscale -= (int)speedscale;
376         skydome(skydomeinner, speedscale, 1.0 / 128.0);
377         glDisable (GL_BLEND);
378 }
379 */
380
381 void R_Sky(void)
382 {
383         if (!r_render.value)
384                 return;
385         if (!skyname[0])
386                 return;
387         glDisable(GL_DEPTH_TEST);
388         glDepthMask(0);
389 //      if (skyname[0])
390                 R_SkyBox();
391 //      else // classic quake sky
392 //              R_SkyDome();
393         glDepthMask(1);
394         glEnable (GL_DEPTH_TEST);
395         glColor3f (1,1,1);
396 }
397
398 //===============================================================
399
400 /*
401 =============
402 R_InitSky
403
404 A sky texture is 256*128, with the right side being a masked overlay
405 ==============
406 */
407 void R_InitSky (byte *src, int bytesperpixel)
408 {
409         int                     i, j, p;
410         unsigned        trans[128*128];
411         unsigned        transpix;
412         int                     r, g, b;
413         unsigned        *rgba;
414
415         if (bytesperpixel == 4)
416         {
417                 for (i = 0;i < 128;i++)
418                         for (j = 0;j < 128;j++)
419                                 trans[(i*128) + j] = src[i*256+j+128];
420         }
421         else
422         {
423                 // make an average value for the back to avoid
424                 // a fringe on the top level
425                 r = g = b = 0;
426                 for (i=0 ; i<128 ; i++)
427                         for (j=0 ; j<128 ; j++)
428                         {
429                                 p = src[i*256 + j + 128];
430                                 rgba = &d_8to24table[p];
431                                 trans[(i*128) + j] = *rgba;
432                                 r += ((byte *)rgba)[0];
433                                 g += ((byte *)rgba)[1];
434                                 b += ((byte *)rgba)[2];
435                         }
436
437                 ((byte *)&transpix)[0] = r/(128*128);
438                 ((byte *)&transpix)[1] = g/(128*128);
439                 ((byte *)&transpix)[2] = b/(128*128);
440                 ((byte *)&transpix)[3] = 0;
441         }
442
443         solidskytexture = R_LoadTexture ("sky_solidtexture", 128, 128, (byte *) trans, TEXF_RGBA | TEXF_PRECACHE);
444
445         if (bytesperpixel == 4)
446         {
447                 for (i = 0;i < 128;i++)
448                         for (j = 0;j < 128;j++)
449                                 trans[(i*128) + j] = src[i*256+j];
450         }
451         else
452         {
453                 for (i=0 ; i<128 ; i++)
454                         for (j=0 ; j<128 ; j++)
455                         {
456                                 p = src[i*256 + j];
457                                 if (p == 0)
458                                         trans[(i*128) + j] = transpix;
459                                 else
460                                         trans[(i*128) + j] = d_8to24table[p];
461                         }
462         }
463
464         alphaskytexture = R_LoadTexture ("sky_alphatexture", 128, 128, (byte *) trans, TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
465 }
466