gl_warp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // gl_warp.c -- sky and water polygons
  16. #include "gl_local.h"
  17. extern model_t *loadmodel;
  18. char skyname[MAX_QPATH];
  19. float skyrotate;
  20. vec3_t skyaxis;
  21. image_t *sky_images[6];
  22. msurface_t *warpface;
  23. #define SUBDIVIDE_SIZE 64
  24. //#define SUBDIVIDE_SIZE 1024
  25. void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
  26. {
  27. int i, j;
  28. float *v;
  29. mins[0] = mins[1] = mins[2] = 9999;
  30. maxs[0] = maxs[1] = maxs[2] = -9999;
  31. v = verts;
  32. for (i=0 ; i<numverts ; i++)
  33. for (j=0 ; j<3 ; j++, v++)
  34. {
  35. if (*v < mins[j])
  36. mins[j] = *v;
  37. if (*v > maxs[j])
  38. maxs[j] = *v;
  39. }
  40. }
  41. void SubdividePolygon (int numverts, float *verts)
  42. {
  43. int i, j, k;
  44. vec3_t mins, maxs;
  45. float m;
  46. float *v;
  47. vec3_t front[64], back[64];
  48. int f, b;
  49. float dist[64];
  50. float frac;
  51. glpoly_t *poly;
  52. float s, t;
  53. vec3_t total;
  54. float total_s, total_t;
  55. if (numverts > 60)
  56. ri.Sys_Error (ERR_DROP, "numverts = %i", numverts);
  57. BoundPoly (numverts, verts, mins, maxs);
  58. for (i=0 ; i<3 ; i++)
  59. {
  60. m = (mins[i] + maxs[i]) * 0.5;
  61. m = SUBDIVIDE_SIZE * floor (m/SUBDIVIDE_SIZE + 0.5);
  62. if (maxs[i] - m < 8)
  63. continue;
  64. if (m - mins[i] < 8)
  65. continue;
  66. // cut it
  67. v = verts + i;
  68. for (j=0 ; j<numverts ; j++, v+= 3)
  69. dist[j] = *v - m;
  70. // wrap cases
  71. dist[j] = dist[0];
  72. v-=i;
  73. VectorCopy (verts, v);
  74. f = b = 0;
  75. v = verts;
  76. for (j=0 ; j<numverts ; j++, v+= 3)
  77. {
  78. if (dist[j] >= 0)
  79. {
  80. VectorCopy (v, front[f]);
  81. f++;
  82. }
  83. if (dist[j] <= 0)
  84. {
  85. VectorCopy (v, back[b]);
  86. b++;
  87. }
  88. if (dist[j] == 0 || dist[j+1] == 0)
  89. continue;
  90. if ( (dist[j] > 0) != (dist[j+1] > 0) )
  91. {
  92. // clip point
  93. frac = dist[j] / (dist[j] - dist[j+1]);
  94. for (k=0 ; k<3 ; k++)
  95. front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
  96. f++;
  97. b++;
  98. }
  99. }
  100. SubdividePolygon (f, front[0]);
  101. SubdividePolygon (b, back[0]);
  102. return;
  103. }
  104. // add a point in the center to help keep warp valid
  105. poly = Hunk_Alloc (sizeof(glpoly_t) + ((numverts-4)+2) * VERTEXSIZE*sizeof(float));
  106. poly->next = warpface->polys;
  107. warpface->polys = poly;
  108. poly->numverts = numverts+2;
  109. VectorClear (total);
  110. total_s = 0;
  111. total_t = 0;
  112. for (i=0 ; i<numverts ; i++, verts+= 3)
  113. {
  114. VectorCopy (verts, poly->verts[i+1]);
  115. s = DotProduct (verts, warpface->texinfo->vecs[0]);
  116. t = DotProduct (verts, warpface->texinfo->vecs[1]);
  117. total_s += s;
  118. total_t += t;
  119. VectorAdd (total, verts, total);
  120. poly->verts[i+1][3] = s;
  121. poly->verts[i+1][4] = t;
  122. }
  123. VectorScale (total, (1.0/numverts), poly->verts[0]);
  124. poly->verts[0][3] = total_s/numverts;
  125. poly->verts[0][4] = total_t/numverts;
  126. // copy first vertex to last
  127. memcpy (poly->verts[i+1], poly->verts[1], sizeof(poly->verts[0]));
  128. }
  129. /*
  130. ================
  131. GL_SubdivideSurface
  132. Breaks a polygon up along axial 64 unit
  133. boundaries so that turbulent and sky warps
  134. can be done reasonably.
  135. ================
  136. */
  137. void GL_SubdivideSurface (msurface_t *fa)
  138. {
  139. vec3_t verts[64];
  140. int numverts;
  141. int i;
  142. int lindex;
  143. float *vec;
  144. warpface = fa;
  145. //
  146. // convert edges back to a normal polygon
  147. //
  148. numverts = 0;
  149. for (i=0 ; i<fa->numedges ; i++)
  150. {
  151. lindex = loadmodel->surfedges[fa->firstedge + i];
  152. if (lindex > 0)
  153. vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
  154. else
  155. vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
  156. VectorCopy (vec, verts[numverts]);
  157. numverts++;
  158. }
  159. SubdividePolygon (numverts, verts[0]);
  160. }
  161. //=========================================================
  162. // speed up sin calculations - Ed
  163. float r_turbsin[] =
  164. {
  165. #include "warpsin.h"
  166. };
  167. #define TURBSCALE (256.0 / (2 * M_PI))
  168. /*
  169. =============
  170. EmitWaterPolys
  171. Does a water warp on the pre-fragmented glpoly_t chain
  172. =============
  173. */
  174. void EmitWaterPolys (msurface_t *fa)
  175. {
  176. glpoly_t *p, *bp;
  177. float *v;
  178. int i;
  179. float s, t, os, ot;
  180. float scroll;
  181. float rdt = r_newrefdef.time;
  182. if (fa->texinfo->flags & SURF_FLOWING)
  183. scroll = -64 * ( (r_newrefdef.time*0.5) - (int)(r_newrefdef.time*0.5) );
  184. else
  185. scroll = 0;
  186. for (bp=fa->polys ; bp ; bp=bp->next)
  187. {
  188. p = bp;
  189. qglBegin (GL_TRIANGLE_FAN);
  190. for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
  191. {
  192. os = v[3];
  193. ot = v[4];
  194. #if !id386
  195. s = os + r_turbsin[(int)((ot*0.125+r_newrefdef.time) * TURBSCALE) & 255];
  196. #else
  197. s = os + r_turbsin[Q_ftol( ((ot*0.125+rdt) * TURBSCALE) ) & 255];
  198. #endif
  199. s += scroll;
  200. s *= (1.0/64);
  201. #if !id386
  202. t = ot + r_turbsin[(int)((os*0.125+rdt) * TURBSCALE) & 255];
  203. #else
  204. t = ot + r_turbsin[Q_ftol( ((os*0.125+rdt) * TURBSCALE) ) & 255];
  205. #endif
  206. t *= (1.0/64);
  207. qglTexCoord2f (s, t);
  208. qglVertex3fv (v);
  209. }
  210. qglEnd ();
  211. }
  212. }
  213. //===================================================================
  214. vec3_t skyclip[6] = {
  215. {1,1,0},
  216. {1,-1,0},
  217. {0,-1,1},
  218. {0,1,1},
  219. {1,0,1},
  220. {-1,0,1}
  221. };
  222. int c_sky;
  223. // 1 = s, 2 = t, 3 = 2048
  224. int st_to_vec[6][3] =
  225. {
  226. {3,-1,2},
  227. {-3,1,2},
  228. {1,3,2},
  229. {-1,-3,2},
  230. {-2,-1,3}, // 0 degrees yaw, look straight up
  231. {2,-1,-3} // look straight down
  232. // {-1,2,3},
  233. // {1,2,-3}
  234. };
  235. // s = [0]/[2], t = [1]/[2]
  236. int vec_to_st[6][3] =
  237. {
  238. {-2,3,1},
  239. {2,3,-1},
  240. {1,3,2},
  241. {-1,3,-2},
  242. {-2,-1,3},
  243. {-2,1,-3}
  244. // {-1,2,3},
  245. // {1,2,-3}
  246. };
  247. float skymins[2][6], skymaxs[2][6];
  248. float sky_min, sky_max;
  249. void DrawSkyPolygon (int nump, vec3_t vecs)
  250. {
  251. int i,j;
  252. vec3_t v, av;
  253. float s, t, dv;
  254. int axis;
  255. float *vp;
  256. c_sky++;
  257. #if 0
  258. glBegin (GL_POLYGON);
  259. for (i=0 ; i<nump ; i++, vecs+=3)
  260. {
  261. VectorAdd(vecs, r_origin, v);
  262. qglVertex3fv (v);
  263. }
  264. glEnd();
  265. return;
  266. #endif
  267. // decide which face it maps to
  268. VectorCopy (vec3_origin, v);
  269. for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
  270. {
  271. VectorAdd (vp, v, v);
  272. }
  273. av[0] = fabs(v[0]);
  274. av[1] = fabs(v[1]);
  275. av[2] = fabs(v[2]);
  276. if (av[0] > av[1] && av[0] > av[2])
  277. {
  278. if (v[0] < 0)
  279. axis = 1;
  280. else
  281. axis = 0;
  282. }
  283. else if (av[1] > av[2] && av[1] > av[0])
  284. {
  285. if (v[1] < 0)
  286. axis = 3;
  287. else
  288. axis = 2;
  289. }
  290. else
  291. {
  292. if (v[2] < 0)
  293. axis = 5;
  294. else
  295. axis = 4;
  296. }
  297. // project new texture coords
  298. for (i=0 ; i<nump ; i++, vecs+=3)
  299. {
  300. j = vec_to_st[axis][2];
  301. if (j > 0)
  302. dv = vecs[j - 1];
  303. else
  304. dv = -vecs[-j - 1];
  305. if (dv < 0.001)
  306. continue; // don't divide by zero
  307. j = vec_to_st[axis][0];
  308. if (j < 0)
  309. s = -vecs[-j -1] / dv;
  310. else
  311. s = vecs[j-1] / dv;
  312. j = vec_to_st[axis][1];
  313. if (j < 0)
  314. t = -vecs[-j -1] / dv;
  315. else
  316. t = vecs[j-1] / dv;
  317. if (s < skymins[0][axis])
  318. skymins[0][axis] = s;
  319. if (t < skymins[1][axis])
  320. skymins[1][axis] = t;
  321. if (s > skymaxs[0][axis])
  322. skymaxs[0][axis] = s;
  323. if (t > skymaxs[1][axis])
  324. skymaxs[1][axis] = t;
  325. }
  326. }
  327. #define ON_EPSILON 0.1 // point on plane side epsilon
  328. #define MAX_CLIP_VERTS 64
  329. void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
  330. {
  331. float *norm;
  332. float *v;
  333. qboolean front, back;
  334. float d, e;
  335. float dists[MAX_CLIP_VERTS];
  336. int sides[MAX_CLIP_VERTS];
  337. vec3_t newv[2][MAX_CLIP_VERTS];
  338. int newc[2];
  339. int i, j;
  340. if (nump > MAX_CLIP_VERTS-2)
  341. ri.Sys_Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
  342. if (stage == 6)
  343. { // fully clipped, so draw it
  344. DrawSkyPolygon (nump, vecs);
  345. return;
  346. }
  347. front = back = false;
  348. norm = skyclip[stage];
  349. for (i=0, v = vecs ; i<nump ; i++, v+=3)
  350. {
  351. d = DotProduct (v, norm);
  352. if (d > ON_EPSILON)
  353. {
  354. front = true;
  355. sides[i] = SIDE_FRONT;
  356. }
  357. else if (d < -ON_EPSILON)
  358. {
  359. back = true;
  360. sides[i] = SIDE_BACK;
  361. }
  362. else
  363. sides[i] = SIDE_ON;
  364. dists[i] = d;
  365. }
  366. if (!front || !back)
  367. { // not clipped
  368. ClipSkyPolygon (nump, vecs, stage+1);
  369. return;
  370. }
  371. // clip it
  372. sides[i] = sides[0];
  373. dists[i] = dists[0];
  374. VectorCopy (vecs, (vecs+(i*3)) );
  375. newc[0] = newc[1] = 0;
  376. for (i=0, v = vecs ; i<nump ; i++, v+=3)
  377. {
  378. switch (sides[i])
  379. {
  380. case SIDE_FRONT:
  381. VectorCopy (v, newv[0][newc[0]]);
  382. newc[0]++;
  383. break;
  384. case SIDE_BACK:
  385. VectorCopy (v, newv[1][newc[1]]);
  386. newc[1]++;
  387. break;
  388. case SIDE_ON:
  389. VectorCopy (v, newv[0][newc[0]]);
  390. newc[0]++;
  391. VectorCopy (v, newv[1][newc[1]]);
  392. newc[1]++;
  393. break;
  394. }
  395. if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  396. continue;
  397. d = dists[i] / (dists[i] - dists[i+1]);
  398. for (j=0 ; j<3 ; j++)
  399. {
  400. e = v[j] + d*(v[j+3] - v[j]);
  401. newv[0][newc[0]][j] = e;
  402. newv[1][newc[1]][j] = e;
  403. }
  404. newc[0]++;
  405. newc[1]++;
  406. }
  407. // continue
  408. ClipSkyPolygon (newc[0], newv[0][0], stage+1);
  409. ClipSkyPolygon (newc[1], newv[1][0], stage+1);
  410. }
  411. /*
  412. =================
  413. R_AddSkySurface
  414. =================
  415. */
  416. void R_AddSkySurface (msurface_t *fa)
  417. {
  418. int i;
  419. vec3_t verts[MAX_CLIP_VERTS];
  420. glpoly_t *p;
  421. // calculate vertex values for sky box
  422. for (p=fa->polys ; p ; p=p->next)
  423. {
  424. for (i=0 ; i<p->numverts ; i++)
  425. {
  426. VectorSubtract (p->verts[i], r_origin, verts[i]);
  427. }
  428. ClipSkyPolygon (p->numverts, verts[0], 0);
  429. }
  430. }
  431. /*
  432. ==============
  433. R_ClearSkyBox
  434. ==============
  435. */
  436. void R_ClearSkyBox (void)
  437. {
  438. int i;
  439. for (i=0 ; i<6 ; i++)
  440. {
  441. skymins[0][i] = skymins[1][i] = 9999;
  442. skymaxs[0][i] = skymaxs[1][i] = -9999;
  443. }
  444. }
  445. void MakeSkyVec (float s, float t, int axis)
  446. {
  447. vec3_t v, b;
  448. int j, k;
  449. b[0] = s*2300;
  450. b[1] = t*2300;
  451. b[2] = 2300;
  452. for (j=0 ; j<3 ; j++)
  453. {
  454. k = st_to_vec[axis][j];
  455. if (k < 0)
  456. v[j] = -b[-k - 1];
  457. else
  458. v[j] = b[k - 1];
  459. }
  460. // avoid bilerp seam
  461. s = (s+1)*0.5;
  462. t = (t+1)*0.5;
  463. if (s < sky_min)
  464. s = sky_min;
  465. else if (s > sky_max)
  466. s = sky_max;
  467. if (t < sky_min)
  468. t = sky_min;
  469. else if (t > sky_max)
  470. t = sky_max;
  471. t = 1.0 - t;
  472. qglTexCoord2f (s, t);
  473. qglVertex3fv (v);
  474. }
  475. /*
  476. ==============
  477. R_DrawSkyBox
  478. ==============
  479. */
  480. int skytexorder[6] = {0,2,1,3,4,5};
  481. void R_DrawSkyBox (void)
  482. {
  483. int i;
  484. #if 0
  485. qglEnable (GL_BLEND);
  486. GL_TexEnv( GL_MODULATE );
  487. qglColor4f (1,1,1,0.5);
  488. qglDisable (GL_DEPTH_TEST);
  489. #endif
  490. if (skyrotate)
  491. { // check for no sky at all
  492. for (i=0 ; i<6 ; i++)
  493. if (skymins[0][i] < skymaxs[0][i]
  494. && skymins[1][i] < skymaxs[1][i])
  495. break;
  496. if (i == 6)
  497. return; // nothing visible
  498. }
  499. qglPushMatrix ();
  500. qglTranslatef (r_origin[0], r_origin[1], r_origin[2]);
  501. qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]);
  502. for (i=0 ; i<6 ; i++)
  503. {
  504. if (skyrotate)
  505. { // hack, forces full sky to draw when rotating
  506. skymins[0][i] = -1;
  507. skymins[1][i] = -1;
  508. skymaxs[0][i] = 1;
  509. skymaxs[1][i] = 1;
  510. }
  511. if (skymins[0][i] >= skymaxs[0][i]
  512. || skymins[1][i] >= skymaxs[1][i])
  513. continue;
  514. GL_Bind (sky_images[skytexorder[i]]->texnum);
  515. qglBegin (GL_QUADS);
  516. MakeSkyVec (skymins[0][i], skymins[1][i], i);
  517. MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
  518. MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
  519. MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
  520. qglEnd ();
  521. }
  522. qglPopMatrix ();
  523. #if 0
  524. glDisable (GL_BLEND);
  525. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  526. glColor4f (1,1,1,0.5);
  527. glEnable (GL_DEPTH_TEST);
  528. #endif
  529. }
  530. /*
  531. ============
  532. R_SetSky
  533. ============
  534. */
  535. // 3dstudio environment map names
  536. char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
  537. void R_SetSky (char *name, float rotate, vec3_t axis)
  538. {
  539. int i;
  540. char pathname[MAX_QPATH];
  541. strncpy (skyname, name, sizeof(skyname)-1);
  542. skyrotate = rotate;
  543. VectorCopy (axis, skyaxis);
  544. for (i=0 ; i<6 ; i++)
  545. {
  546. // chop down rotating skies for less memory
  547. if (gl_skymip->value || skyrotate)
  548. gl_picmip->value++;
  549. if ( qglColorTableEXT && gl_ext_palettedtexture->value )
  550. Com_sprintf (pathname, sizeof(pathname), "env/%s%s.pcx", skyname, suf[i]);
  551. else
  552. Com_sprintf (pathname, sizeof(pathname), "env/%s%s.tga", skyname, suf[i]);
  553. sky_images[i] = GL_FindImage (pathname, it_sky);
  554. if (!sky_images[i])
  555. sky_images[i] = r_notexture;
  556. if (gl_skymip->value || skyrotate)
  557. { // take less memory
  558. gl_picmip->value--;
  559. sky_min = 1.0/256;
  560. sky_max = 255.0/256;
  561. }
  562. else
  563. {
  564. sky_min = 1.0/512;
  565. sky_max = 511.0/512;
  566. }
  567. }
  568. }