1 /*
2 * Compiz cube atlantis plugin
3 *
4 * atlantis.c
5 *
6 * This plugin renders a fish tank inside of the transparent cube,
7 * replete with fish, crabs, sand, bubbles, and coral.
8 *
9 * Copyright : (C) 2007-2008 by David Mikos
10 * Email : infiniteloopcounter@gmail.com
11 *
12 * Copyright : (C) 2007 by Dennis Kasprzyk
13 * E-mail : onestone@opencompositing.org
14 *
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 */
27
28 /*
29 * Original water.c code by Dennis Kasprzyk.
30 */
31
32 /*
33 * Water amplitude calculation, ripple effect, deformation
34 * code, and some other modifications by David Mikos.
35 */
36
37
38 #include "atlantis-internal.h"
39 #include "math.h"
40 #include "atlantis_options.h"
41
42 static void
genTriMesh(Vertex * vertices,int size,unsigned int * indices,int subdiv,float r,Vertex a)43 genTriMesh (Vertex *vertices,
44 int size,
45 unsigned int *indices,
46 int subdiv,
47 float r,
48 Vertex a)
49 {
50 int nRow;
51 Vertex *v;
52 unsigned int *idx;
53 int i, j, k;
54
55 float ang, d, dy, dx, y, x;
56
57 float angStep = 2 * PI / size;
58
59 int c = 1; /* counter for how many points already indexed */
60 int c2 = 0; /* similar to c but for indices add one for each layer */
61 int oc = 1;
62 int t;
63
64 if (subdiv < 0)
65 return;
66 if (!vertices || !indices)
67 return;
68
69 nRow = (subdiv) ? (2 << (subdiv - 1)) : 1;
70
71 v = vertices;
72 idx = indices;
73
74 v[0] = a;
75
76
77 /* initialize coordinates, spiralling around from centre */
78 for (i = 1; i <= nRow; i++)
79 {
80 ang = PI / size;
81 d = i * r/nRow;
82
83 for (j = 0; j < size; j++)
84 {
85 x = d * cosf (ang);
86 y = d * sinf (ang);
87
88 ang -= angStep;
89
90 dx = (d * cosf (ang) - x) / i;
91 dy = (d * sinf (ang) - y) / i;
92
93 c2 = i * j + c;
94 for (k = 0; k < i; k++, c2++)
95 {
96 v[c2].v[0] = y + k * dy + a.v[0];
97 v[c2].v[1] = a.v[1];
98 v[c2].v[2] = x + k*dx + a.v[2];
99 }
100 }
101
102 c += i * size;
103 }
104
105 c = 1;
106 c2 = 0;
107
108 int out = 1; /* outer */
109 int inn = 0; /* inner */
110
111 for (i = 1; i <= nRow; i++)
112 {
113 for (j = 0; j < size; j++)
114 {
115 t = (2 * i - 1) * j + c2;
116 for (k = 0; k < 2 * i - 1; k++)
117 {
118 idx[3 * (t + k) + 0] = out;
119 idx[3 * (t + k) + 1] = inn;
120
121 if (k % 2 == 0)
122 {
123 out++;
124 if (out >= c + i * size)
125 out -= i * size;
126
127 idx[3 * (t + k) + 2] = out;
128 }
129 else
130 {
131 inn++;
132 if (inn >= c)
133 inn -= (i - 1) * size;
134
135 idx[3 * (t + k) + 2] = inn;
136 }
137 }
138 }
139
140 oc = c;
141
142 c += i * size;
143 c2 += (2 * i - 1) * size;
144
145 inn = oc;
146 out = c;
147 }
148
149 }
150
151 static void
genTriWall(Vertex * lVer,Vertex * hVer,unsigned int * indices,unsigned int idxBaseL,unsigned int idxBaseH,int subdiv,float ang,Vertex a,Vertex b,Vertex c,Vertex d)152 genTriWall (Vertex *lVer,
153 Vertex *hVer,
154 unsigned int *indices,
155 unsigned int idxBaseL,
156 unsigned int idxBaseH,
157 int subdiv,
158 float ang,
159 Vertex a,
160 Vertex b,
161 Vertex c,
162 Vertex d)
163 {
164 int nRow;
165 int i, k;
166 float vab[3], vcd[3];
167
168 if (subdiv < 0)
169 return;
170 if (!lVer || !hVer || !indices)
171 return;
172
173 nRow = pow (2, subdiv);
174
175 for (i = 0; i < 3; i++)
176 {
177 vab[i] = b.v[i] - a.v[i];
178 vab[i] /= nRow;
179 vcd[i] = d.v[i] - c.v[i];
180 vcd[i] /= nRow;
181 }
182
183 for (i = 0; i <= nRow; i++)
184 {
185 for (k = 0; k < 3; k++)
186 {
187 lVer[i].v[k] = a.v[k] + (i * vab[k]);
188 hVer[i].v[k] = c.v[k] + (i * vcd[k]);
189 }
190
191 lVer[i].n[0] = sinf (ang);
192 lVer[i].n[1] = 0;
193 lVer[i].n[2] = cosf (ang);
194
195 hVer[i].n[0] = lVer[i].n[0];
196 hVer[i].n[1] = lVer[i].n[1];
197 hVer[i].n[2] = lVer[i].n[2];
198 }
199
200 for (i = 0; i < nRow; i++)
201 {
202 indices[(i * 6)] = idxBaseL + i;
203 indices[(i * 6) + 1] = idxBaseH + i;
204 indices[(i * 6) + 2] = idxBaseH + i + 1;
205 indices[(i * 6) + 3] = idxBaseL + i + 1;
206 indices[(i * 6) + 4] = idxBaseL + i;
207 indices[(i * 6) + 5] = idxBaseH + i + 1;
208 }
209 }
210
211 static void
updateRipple(Water * w,int size)212 updateRipple (Water *w,
213 int size)
214 {
215 int i;
216
217 if (!w->rippleFactor)
218 return;
219
220 for (i = 0; i < w->nSVer; i++)
221 w->rippleFactor[i] = NRAND (1001) - 500;
222 }
223
224 static Water *
genWater(int size,int sDiv,float distance,float bottom,Bool initRipple)225 genWater (int size,
226 int sDiv,
227 float distance,
228 float bottom,
229 Bool initRipple)
230 {
231 Water *w;
232 int i, j;
233
234 float ang, r, aStep;
235 int nVer, nRow, nIdx, nWVer, nWIdx;;
236 Vertex a = {{ 0.0, 0.0, 0.0 }};
237 Vertex b = {{ 0.0, 0.0, 0.0 }};
238 Vertex c = {{ 0.0, 0.0, 0.0 }};
239 Vertex d = {{ 0.0, bottom, 0.0 }};
240 Vertex e = {{ 0.0, bottom, 0.0 }};
241
242 Vertex *wv;
243 unsigned int *wi;
244
245 if (sDiv < 0)
246 return NULL;
247
248 if (size < 3)
249 return NULL;
250
251 w = malloc (sizeof (Water));
252 if (!w)
253 return NULL;
254
255 nRow = (sDiv) ? (2 << (sDiv - 1)) : 1;
256 nVer = size * ((nRow * (nRow + 1)) / 2) + 1;
257
258 nIdx = 3 * size * (nRow * nRow);
259
260 nWIdx = pow (2, sDiv + 1) * 3;
261 nWVer = pow (2, sDiv + 1) + 2;
262
263 w->nBIdx = nRow * size;
264
265 w->nVertices = nVer + (nWVer) * size;
266 w->nIndices = nIdx + (nWIdx) * size + w->nBIdx;
267
268 w->nSVer = nVer;
269 w->nSIdx = nIdx;
270 w->nWVer = nWVer * size;
271 w->nWIdx = nWIdx * size;
272
273 w->size = size;
274 w->distance = distance;
275 w->sDiv = sDiv;
276
277 w->wave1 = 0.0;
278 w->wave2 = 0.0;
279
280 w->vertices = calloc (1, sizeof (Vertex) * w->nVertices);
281 if (!w->vertices)
282 {
283 free (w);
284 return NULL;
285 }
286
287 w->indices = calloc (1, sizeof (int) * w->nIndices);
288 if (!w->indices)
289 {
290 free (w->vertices);
291 free (w);
292 return NULL;
293 }
294
295 w->vertices2 = NULL;
296 w->indices2 = NULL;
297
298 r = distance / cosf (M_PI / size);
299 ang = M_PI / size;
300 aStep = 2 * M_PI / size;
301
302 wv = w->vertices + nVer;
303 wi = w->indices + nIdx;
304
305 for (i = 0; i < size; i++)
306 {
307 d.v[0] = b.v[0] = sinf (ang - aStep) * r;
308 d.v[2] = b.v[2] = cosf (ang - aStep) * r;
309
310 e.v[0] = c.v[0] = sinf (ang) * r;
311 e.v[2] = c.v[2] = cosf (ang) * r;
312
313 genTriWall (wv + (i * nWVer / 2), wv + ((i + size) * nWVer / 2),
314 wi + (i * nWIdx), nVer + (i * nWVer / 2),
315 nVer + ((i + size) * nWVer / 2), sDiv,
316 ang - aStep / 2, b, c, d, e);
317
318 ang += aStep;
319 }
320 genTriMesh (w->vertices, size, w->indices, sDiv, r, a);
321
322
323 /* bottom face indices for cylinder deformation */
324 for (i = 0; i < size; i++)
325 {
326 wi = w->indices + w->nSIdx + w->nWIdx + i * nRow;
327
328 for (j = 0; j < nRow; j++)
329 wi[j] = w->nSVer + ((size - 1 - i + size) * nWVer / 2) +
330 nRow - 1 - j;
331 }
332
333
334 w->rippleTimer = 0;
335
336 if (initRipple)
337 {
338 w->rippleFactor = calloc (1, sizeof (int *) * w->nSVer);
339
340 if (!w->rippleFactor)
341 {
342 free (w->vertices);
343 free (w->indices);
344 free (w);
345 return NULL;
346 }
347 updateRipple(w, size);
348 }
349 else
350 w->rippleFactor = NULL;
351
352 return w;
353 }
354
355 void
freeWater(Water * w)356 freeWater (Water *w)
357 {
358 if (!w)
359 return;
360
361 if (w->vertices)
362 free (w->vertices);
363 if (w->indices)
364 free (w->indices);
365 if (w->vertices2)
366 free (w->vertices2);
367 if (w->indices2)
368 free (w->indices2);
369 if (w->rippleFactor)
370 free(w->rippleFactor);
371
372 w->vertices = NULL;
373 w->vertices2 = NULL;
374 w->indices = NULL;
375 w->indices2 = NULL;
376 w->rippleFactor = NULL;
377 }
378
379 static void
setAmplitude(Vertex * v,float bh,float wt,float swt,float wa,float swa,float wf,float swf,int ripple,int ripple2)380 setAmplitude (Vertex *v,
381 float bh,
382 float wt,
383 float swt,
384 float wa,
385 float swa,
386 float wf,
387 float swf,
388 int ripple,
389 int ripple2)
390 {
391 float dx, dz, d, c;
392
393 v->v[1] = bh + (wa * sinf (wt + wf * v->v[0] * v->v[2])) +
394 (swa * sinf (swt + swf * v->v[0] * v->v[2]));
395
396 v->v[1] = MIN (0.5, MAX (-0.5, v->v[1]));
397
398 c = wa * cosf (wt + wf * v->v[0] * v->v[2]) * wf;
399 c += swa * cosf (swt + swf * v->v[0] * v->v[2]) * swf;
400
401 dx = c * v->v[2];
402 dz = c * v->v[0];
403
404 /* actual normal
405 v->n[0] = -dx;
406 v->n[1] = 1;
407 v->n[2] = -dz;
408 */
409
410 v->n[0] = -0.2 * (v->v[1] - bh);
411 v->n[1] = 5;
412 v->n[2] = -0.2 * (v->v[1] - bh);
413
414 if (ripple)
415 {
416 float sum;
417 float rFactor = (ripple / 1000.0f);
418
419 v->n[0] -= (2 * dx + 3) * rFactor + 3 * dx;
420 rFactor = (ripple2 / 1000.0f);
421 v->n[2] -= (2 * dz + 3) * rFactor + 3 * dz;
422
423 if (ripple & 1)
424 rFactor = (ripple / 1000.0f);
425
426 /* for more equal normal vector lengths */
427 sum = (abs (ripple) + abs (ripple2)) / 2000.0f;
428
429 v->n[1] *= 0.8 + 0.2 * (1 - sum) * 2 * fabsf (rFactor);
430 }
431 else
432 {
433 v->n[0] -= (5 * dx);
434 v->n[2] -= (5 * dz);
435 }
436
437 d = sqrtf ((v->n[0] * v->n[0]) + (v->n[1] * v->n[1]) +
438 (v->n[2] * v->n[2]));
439
440 if (d == 0.0f)
441 return;
442
443 v->n[0] /= d;
444 v->n[1] /= d;
445 v->n[2] /= d;
446 }
447
448
449 static void
deformCylinder(CompScreen * s,Water * w,float progress)450 deformCylinder(CompScreen *s,
451 Water *w,
452 float progress)
453 {
454 ATLANTIS_SCREEN (s);
455 CUBE_SCREEN (s);
456
457 int nVer, nWVer, nRow, nRowS, subdiv;
458 Vertex *v;
459 int i, j, k, l;
460
461 float ang, r, aStep;
462
463 Vertex *wv;
464
465 int size = as->hsize;
466
467 float ratioRadiusToSideDist;
468
469 //Vertex a = {{ 0.0, 0.0, 0.0 }};
470 Vertex b = {{ 0.0, 0.0, 0.0 }};
471 Vertex c = {{ 0.0, 0.0, 0.0 }};
472
473 float vab[3];
474
475 int c1 = 1; /* counter for how many points already indexed */
476 int c2 = 1; /* similar to c but for indices add one for each layer */
477
478 float dist, x, y, dx, dy;
479
480
481 if (!w)
482 return;
483 if (w->sDiv < 0)
484 return;
485 if (!w->vertices)
486 return;
487 if (w->size != size)
488 return;
489
490 subdiv = w->sDiv;
491 nRow = (subdiv)?(2 << (subdiv - 1)) : 1;
492 nVer = size * ((nRow * (nRow + 1)) / 2) + 1;
493
494 nWVer = pow (2, subdiv + 1) + 2;
495
496 ratioRadiusToSideDist = as->radius * as->ratio / as->sideDistance;
497
498 r = cs->distance / cosf (M_PI / size);
499 ang = M_PI / size;
500 aStep = 2 * M_PI / size;
501
502 wv = w->vertices + w->nSVer;
503 v = w->vertices;
504
505 //v[0] = a;
506
507 /* new coordinates, spiralling around from centre */
508 for (i = 1; i <= nRow; i++)
509 {
510 ang = PI / size;
511 dist = i * r / nRow;
512
513 for (j = 0; j < size; j++)
514 {
515 x = cosf (ang);
516 y = sinf (ang);
517
518 ang -= aStep;
519 dx = (cosf (ang) - x) / i;
520 dy = (sinf (ang) - y) / i;
521
522 c2 = i * j + c1;
523 for (k = 0; k < i; k++, c2++)
524 {
525 v[c2].v[0] = y + k * dy;
526 v[c2].v[2] = x + k * dx;
527
528 v[c2].v[0] += progress * (sinf (ang + aStep -
529 (k * aStep) / i) - v[c2].v[0]);
530 v[c2].v[0] *= dist;
531
532 v[c2].v[2] += progress * (cosf (ang + aStep -
533 (k * aStep) / i) - v[c2].v[2]);
534 v[c2].v[2] *= dist;
535
536 /* translation not needed*/
537 /*
538 v[c2].v[0] += a[0];
539 v[c2].v[2] += a[2];
540 */
541 }
542 }
543
544 c1 += i * size;
545 }
546
547 ang = M_PI / size;
548
549 for (l = 0; l < size; l++)
550 {
551 v = w->vertices + (l * nVer);
552
553 b.v[0] = sinf (ang - aStep);
554 b.v[2] = cosf (ang - aStep);
555
556 c.v[0] = sinf (ang);
557 c.v[2] = cosf (ang);
558
559 for (i = 0; i < 3; i++)
560 {
561 vab[i] = b.v[i];// - a.v[i];
562 vab[i] /= nRow - 1.0;
563 }
564
565
566 Vertex *lVer = wv + (l * nWVer / 2);
567 Vertex *hVer = wv + ((l + size) * nWVer / 2);
568
569 /*side walls */
570 nRowS = pow (2, subdiv);
571
572 for (i = 0; i < 3; i++)
573 {
574 vab[i] = c.v[i] - b.v[i];
575 vab[i] /= nRowS;
576 }
577
578 for (i = 0; i <= nRowS; i++)
579 {
580 for (k = 0; k < 3; k += 2)
581 {
582 lVer[i].v[k] = b.v[k] + (i * vab[k]);
583 }
584
585 float th = atan2f(lVer[i].v[0], lVer[i].v[2]);
586
587
588 lVer[i].v[0] += progress * (sinf (ang - aStep + i * aStep /
589 nRowS) - lVer[i].v[0]);
590 lVer[i].v[2] += progress * (cosf (ang - aStep + i * aStep /
591 nRowS) - lVer[i].v[2]);
592 lVer[i].v[0] *= r;
593 lVer[i].v[2] *= r;
594
595 for (k = 0; k < 3; k += 2)
596 hVer[i].v[k] = lVer[i].v[k];
597
598
599 lVer[i].n[0] = (1 - progress) * sinf (ang) +
600 progress * sinf (th);
601 lVer[i].n[1] = 0;
602 lVer[i].n[2] = (1-progress)*cosf(ang) +
603 progress*cosf(th);
604
605 hVer[i].n[0] = lVer[i].n[0];
606 hVer[i].n[1] = lVer[i].n[1];
607 hVer[i].n[2] = lVer[i].n[2];
608 }
609
610 ang += aStep;
611 }
612 }
613
614 static void
deformSphere(CompScreen * s,Water * w,float progress,float waterBottom,Bool groundNormals)615 deformSphere(CompScreen *s,
616 Water *w,
617 float progress,
618 float waterBottom,
619 Bool groundNormals)
620 {
621 ATLANTIS_SCREEN (s);
622 CUBE_SCREEN (s);
623
624 int nWVer, nWIdx, nWVer2, nWIdx2, nRow, nRowS, subdiv;
625 Vertex *v;
626 int i, j, k, l;
627
628 float ang, r, aStep;
629
630 Vertex *wv;
631
632 int size = as->hsize;
633
634 float ratioRadiusToSideDist, sphereRadiusFactor, sphereRadiusFactor2;
635
636 //Vertex a = {{ 0.0, 0.0, 0.0 }};
637 Vertex b = {{ 0.0, 0.0, 0.0 }};
638 Vertex c = {{ 0.0, 0.0, 0.0 }};
639
640 float vab[3];
641
642 int c1 = 1; /* counter for how many points already indexed */
643 int c2 = 1; /* similar to c but for indices add one for each layer */
644
645 float dist, factor, x, y, dx, dy;
646
647 if (!w)
648 return;
649 if (w->sDiv < 0)
650 return;
651 if (!w->vertices)
652 return;
653 if (w->size != size)
654 return;
655
656 subdiv = w->sDiv;
657 nRow = (subdiv)?(2 << (subdiv - 1)) : 1;
658
659 nWIdx = pow (2, subdiv + 1) * 3;
660 nWVer = pow (2, subdiv + 1) + 2;
661
662 nWIdx2 = nWIdx * nRow * 2;
663 nWVer2 = nWVer * (nRow + 1) / 2;
664
665 ratioRadiusToSideDist = as->radius * as->ratio / as->sideDistance;
666
667 sphereRadiusFactor = as->radius / 100000;
668 sphereRadiusFactor = progress * (hypotf (sphereRadiusFactor, 0.5f) /
669 sphereRadiusFactor - 1);
670 sphereRadiusFactor2 = sphereRadiusFactor * cosf (w->bh*PI)+1;
671
672 r = cs->distance / cosf (M_PI / size);
673 ang = M_PI / size;
674 aStep = 2 * M_PI / size;
675
676 wv = w->vertices + w->nSVer;
677
678 if (nWVer2 * size != w->nWVer2 && w->vertices2)
679 {
680 free (w->vertices2);
681 w->vertices2 = NULL;
682 }
683 if (nWIdx2 * size != w->nWIdx2 && w->indices2)
684 {
685 free (w->indices2);
686 w->indices2 = NULL;
687 }
688
689 w->nWVer2 = nWVer2 * size;
690 w->nWIdx2 = nWIdx2 * size;
691
692 w->nBIdx2 = nRow * size;
693
694 if (!w->vertices2)
695 {
696 w->vertices2 = calloc (1, sizeof (Vertex) * w->nWVer2);
697 if (!w->vertices2)
698 return;
699 }
700
701 if (!w->indices2)
702 {
703 w->indices2 = calloc (1, sizeof (int) * (w->nWIdx2 + w->nBIdx2));
704 if (!w->indices2)
705 return;
706 }
707
708 v = w->vertices;
709
710 //v[0] = a;
711
712 /* new coordinates, spiralling around from centre */
713 for (i = 1; i <= nRow; i++)
714 {
715 ang = PI / size;
716 dist = i * r / nRow;
717 factor = dist * sphereRadiusFactor2;
718
719 for (j = 0; j < size; j++)
720 {
721 x = cosf (ang);
722 y = sinf (ang);
723
724 ang -= aStep;
725 dx = (cosf (ang) - x) / i;
726 dy = (sinf (ang) - y) / i;
727
728 c2 = i * j + c1;
729 for (k = 0; k < i; k++, c2++)
730 {
731 v[c2].v[0] = y + k * dy;
732 v[c2].v[2] = x + k * dx;
733
734 v[c2].v[0] += progress * (sinf (ang + aStep -
735 (k * aStep) / i) - v[c2].v[0]);
736 v[c2].v[2] += progress * (cosf (ang + aStep -
737 (k * aStep) / i) - v[c2].v[2]);
738 v[c2].v[0] *= factor;
739 v[c2].v[2] *= factor;
740
741 /* translation not needed*/
742 /*
743 v[c2].v[0] += a[0];
744 v[c2].v[2] += a[2];
745 */
746 }
747 }
748
749 c1 += i * size;
750 }
751
752 ang = M_PI / size;
753
754 for (l = 0; l < size; l++)
755 {
756 unsigned int * indices = w->indices2 + (l * nWIdx);
757 unsigned int idxBaseL = (l * nWVer / 2);
758
759 b.v[0] = sinf (ang - aStep);
760 b.v[2] = cosf (ang - aStep);
761
762 c.v[0] = sinf (ang);
763 c.v[2] = cosf (ang);
764
765 Vertex *lVer = w->vertices2 + (l * nWVer2 / (nRow + 1));
766
767 /*side walls */
768 nRowS = pow (2, subdiv);
769
770 for (i = 0; i < 3; i++)
771 {
772 vab[i] = c.v[i] - b.v[i];
773 vab[i] /= nRowS;
774 }
775
776 for (i = 0; i <= nRowS; i++)
777 {
778 float th;
779
780 for (k = 0; k < 3; k++)
781 lVer[i].v[k] = b.v[k] + (i * vab[k]);
782
783 lVer[i].v[0] += progress * (sinf (ang - aStep + i * aStep /
784 nRowS) - lVer[i].v[0]);
785 lVer[i].v[2] += progress * (cosf (ang - aStep + i * aStep /
786 nRowS) - lVer[i].v[2]);
787
788 th = atan2f (lVer[i].v[0], lVer[i].v[2]);
789
790 lVer[i].n[0] = (1 - progress) * sinf (ang - aStep / 2) +
791 progress * sinf (th);
792 lVer[i].n[1] = 0;
793 lVer[i].n[2] = (1 - progress) * cosf (ang - aStep / 2) +
794 progress * cosf (th);
795
796 for (j = nRow; j >= 0; j--)
797 {
798 Vertex *hVer = lVer + j * (size * nWVer2 / (nRow + 1));
799
800 float hFactor;
801 float p = ((float) j) / nRow;
802
803 for (k = 0; k < 3; k++)
804 {
805 hVer[i].v[k] = lVer[i].v[k];
806 hVer[i].n[k] = lVer[i].n[k];
807 }
808
809 hVer[i].n[0] = p * ((1 - progress) * sinf (ang - aStep / 2) +
810 progress * sinf (th));
811 hVer[i].n[1] = 1 - p;
812 hVer[i].n[2] = p * ((1 - progress) * cosf (ang - aStep / 2) +
813 progress * cosf(th));
814
815 hFactor = r * (sphereRadiusFactor * cosf ((w->bh - j *
816 (w->bh - waterBottom) / nRow) * PI)+1);
817
818 for (k = 0; k < 3; k += 2)
819 hVer[i].v[k] *= hFactor;
820 }
821 }
822
823 for (j = 0; j < nRow; j++)
824 {
825 unsigned int idxBaseH = idxBaseL + size * nWVer / 2;
826
827 for (i = 0; i < nRowS; i++)
828 {
829 indices[(i * 6)] = idxBaseL + i;
830 indices[(i * 6) + 1] = idxBaseH + i;
831 indices[(i * 6) + 2] = idxBaseH + i + 1;
832 indices[(i * 6) + 3] = idxBaseL + i + 1;
833 indices[(i * 6) + 4] = idxBaseL + i;
834 indices[(i * 6) + 5] = idxBaseH + i + 1;
835 }
836 idxBaseL = idxBaseH;
837 indices += 2 * nWIdx2 / nRow;
838 }
839
840 /* bottom face indices */
841 idxBaseL = (nRow - 1) * size * nWVer / 2;
842 indices = w->indices2 + w->nWIdx2 + (l * nRow);
843
844 for (j = 0; j < nRow; j++)
845 indices[j] = idxBaseL + ((size - 1 - l + size) * nWVer / 2) +
846 nRow - 1 - j;
847
848 ang += aStep;
849 }
850 }
851
852 void
updateHeight(Water * w,Water * w2,Bool rippleEffect,int currentDeformation)853 updateHeight (Water *w,
854 Water *w2,
855 Bool rippleEffect,
856 int currentDeformation)
857 {
858 int offset;
859
860 Bool useOtherWallVertices;
861 Vertex * vertices;
862
863 int i, j;
864
865 if (!w)
866 return;
867
868 offset = w->nSVer / 2 + 1;
869 rippleEffect = (rippleEffect && w->rippleFactor);
870
871 useOtherWallVertices = (currentDeformation == DeformationSphere &&
872 w->vertices2);
873 vertices = (useOtherWallVertices ? w->vertices2 - w->nSVer : w->vertices);
874
875 for (i = 0; i < w->nSVer; i++)
876 setAmplitude(&w->vertices[i], w->bh, w->wave1, w->wave2, w->wa,
877 w->swa, w->wf, w->swf,
878 (rippleEffect ? w->rippleFactor[i] : 0),
879 (rippleEffect ? w->rippleFactor[(i + offset) % w->nSVer] :
880 0));
881
882 for (i = w->nSVer; i < w->nSVer + (w->nWVer / 2); i++)
883 setAmplitude(&vertices[i], w->bh, w->wave1, w->wave2, w->wa,
884 w->swa, w->wf, w->swf, 0, 0);
885
886 if (useOtherWallVertices)
887 {
888 int nRow = (w->sDiv)?(2 << (w->sDiv - 1)) + 1 : 2;
889
890 Vertex * verticesL = vertices;
891
892 for (j = 1; j < nRow - 1; j++ )
893 {
894 vertices += w->nWVer / 2;
895
896 for (i=w->nSVer; i < w->nSVer + (w->nWVer / 2); i++)
897 vertices[i].v[1] = verticesL[i].v[1] - j *
898 (verticesL[i].v[1] + 0.5) / (nRow - 1);
899 }
900
901 vertices += w->nWVer / 2;
902
903 /* set bottom ground to base of deformed cube */
904 /* this is okay because ground and water have same grid size */
905 for (i = w->nSVer; i < w->nSVer + (w->nWVer / 2); i++)
906 vertices[i].v[1] = -0.5;
907 }
908 }
909
910 void
updateDeformation(CompScreen * s,int currentDeformation)911 updateDeformation (CompScreen *s,
912 int currentDeformation)
913 {
914 ATLANTIS_SCREEN (s);
915 CUBE_SCREEN (s);
916
917 static const float floatErr = 0.0001f;
918
919 Bool deform = FALSE;
920
921 float progress, dummy;
922 (*cs->getRotation) (s, &dummy, &dummy, &progress);
923
924 if (currentDeformation == DeformationNone)
925 {
926 if (as->oldProgress == 0.0f)
927 return;
928
929 as->oldProgress = 0.0f;
930 progress = 0.0f;
931 }
932 else
933 {
934 if (fabsf (progress) < floatErr)
935 progress = 0.0f;
936 else if (fabsf (1.0f - progress) < floatErr)
937 progress = 1.0f;
938
939 if ((as->oldProgress != 0.0f || progress != 0.0f) &&
940 (as->oldProgress != 1.0f || progress != 1.0f))
941 {
942 if (progress == 0.0f || progress == 1.0f)
943 {
944 if (as->oldProgress != progress)
945 {
946 deform = TRUE;
947 as->oldProgress = progress;
948 }
949 }
950 else if (fabsf (as->oldProgress - progress) >= floatErr)
951 {
952 deform = TRUE;
953 as->oldProgress = progress;
954 }
955 }
956 }
957
958 if (deform)
959 {
960 if (atlantisGetShowWater (s) || atlantisGetShowWaterWire (s))
961 {
962 switch (currentDeformation)
963 {
964 case DeformationNone :
965 case DeformationCylinder :
966 deformCylinder(s, as->water, progress);
967 break;
968
969 case DeformationSphere :
970 deformSphere(s, as->water, progress, -0.5, FALSE);
971 }
972 }
973
974 if (atlantisGetShowGround (s))
975 {
976 switch (currentDeformation)
977 {
978 case DeformationNone :
979 progress = 0.0f;
980 case DeformationCylinder :
981 deformCylinder (s, as->ground, progress);
982 break;
983
984 case DeformationSphere :
985 deformSphere (s, as->ground, progress, -0.5, TRUE);
986 }
987
988 updateHeight (as->ground, NULL, FALSE, currentDeformation);
989 }
990 }
991 }
992
993 void
updateWater(CompScreen * s,float time)994 updateWater (CompScreen *s,
995 float time)
996 {
997 ATLANTIS_SCREEN (s);
998 CUBE_SCREEN (s);
999
1000 int sDiv = (atlantisGetRenderWaves (s))?
1001 atlantisGetGridQuality (s) : 0;
1002 int size = as->hsize;
1003
1004 if (!as->water)
1005 as->water = genWater (size, sDiv, cs->distance, -0.5, atlantisGetWaveRipple (s));
1006
1007 if (!as->water)
1008 return;
1009
1010 if (as->water->size != size || as->water->sDiv != sDiv ||
1011 as->water->distance != cs->distance || (atlantisGetWaveRipple (s) && !as->water->rippleFactor))
1012 {
1013 freeWater (as->water);
1014 as->water = genWater (size, sDiv, cs->distance, -0.5, atlantisGetWaveRipple (s));
1015
1016 if (!as->water)
1017 return;
1018 }
1019
1020 if (atlantisGetWaveRipple (s))
1021 {
1022 as->water->rippleTimer -= (int) (time * 1000);
1023 if (as->water->rippleTimer <= 0)
1024 {
1025 as->water->rippleTimer += 170;
1026 updateRipple (as->water, size);
1027 }
1028 }
1029
1030 as->water->wave1 += time * as->speedFactor;
1031 as->water->wave2 += time * as->speedFactor;
1032
1033 as->water->wave1 = fmodf (as->water->wave1, 2 * M_PI);
1034 as->water->wave2 = fmodf (as->water->wave2, 2 * M_PI);
1035
1036 if (atlantisGetRenderWaves (s))
1037 {
1038 as->water->wa = atlantisGetWaveAmplitude (s);
1039 as->water->swa = atlantisGetSmallWaveAmplitude (s);
1040 as->water->wf = atlantisGetWaveFrequency (s);
1041 as->water->swf = atlantisGetSmallWaveFrequency (s);
1042 }
1043 else
1044 {
1045 as->water->wa = 0.0;
1046 as->water->swa = 0.0;
1047 as->water->wf = 0.0;
1048 as->water->swf = 0.0;
1049 }
1050
1051 as->water->bh = -0.5 + atlantisGetWaterHeight (s);
1052 }
1053
1054 void
updateGround(CompScreen * s,float time)1055 updateGround (CompScreen *s,
1056 float time)
1057 {
1058 ATLANTIS_SCREEN (s);
1059 CUBE_SCREEN (s);
1060
1061 int sDiv = atlantisGetGridQuality (s);
1062 int size = as->hsize;
1063
1064 Bool update = FALSE;
1065
1066 if (!as->ground)
1067 {
1068 as->ground = genWater (size, sDiv, cs->distance, -0.5, FALSE);
1069 update = TRUE;
1070 }
1071
1072 if (!as->ground)
1073 return;
1074
1075 if (as->ground->size != size || as->ground->sDiv != sDiv ||
1076 as->ground->distance != cs->distance)
1077 {
1078 freeWater (as->ground);
1079 as->ground = genWater (size, sDiv, cs->distance, -0.5, FALSE);
1080
1081 update = TRUE;
1082 if (!as->ground)
1083 return;
1084 }
1085
1086 if (!update)
1087 return;
1088
1089 as->ground->wave1 = (float)(rand () & 15) / 15.0;
1090 as->ground->wave2 = (float)(rand () & 15) / 15.0;
1091
1092 as->ground->bh = -0.45;
1093 as->ground->wa = 0.1;
1094 as->ground->swa = 0.02;
1095 as->ground->wf = 2.0;
1096 as->ground->swf = 10.0;
1097
1098 updateHeight (as->ground, NULL, FALSE, DeformationNone);
1099 }
1100
1101 void
drawWater(Water * w,Bool full,Bool wire,int currentDeformation)1102 drawWater (Water *w, Bool full, Bool wire, int currentDeformation)
1103 {
1104 float *v;
1105 if (!w)
1106 return;
1107
1108 glDisable (GL_DEPTH_TEST);
1109
1110 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1111
1112 if (full)
1113 {
1114 glEnable (GL_LIGHTING);
1115 glEnable (GL_LIGHT1);
1116 glDisable (GL_LIGHT0);
1117
1118 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1119 glEnableClientState (GL_NORMAL_ARRAY);
1120
1121 v = (float *) w->vertices;
1122
1123 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1124 glNormalPointer (GL_FLOAT, 6 * sizeof (float), v + 3);
1125
1126 glDrawElements (GL_TRIANGLES, w->nSIdx, GL_UNSIGNED_INT, w->indices);
1127
1128 glDisableClientState (GL_NORMAL_ARRAY);
1129 glDisable (GL_LIGHTING);
1130
1131 glEnable (GL_COLOR_MATERIAL);
1132 if (currentDeformation == DeformationSphere &&
1133 w->vertices2 && w->indices2)
1134 {
1135 v = (float *) w->vertices2;
1136
1137 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1138 glNormalPointer (GL_FLOAT, 6 * sizeof (float), v + 3);
1139
1140 glDrawElements (GL_TRIANGLES, w->nWIdx2,
1141 GL_UNSIGNED_INT, w->indices2);
1142 }
1143 else
1144 glDrawElements (GL_TRIANGLES, w->nWIdx,
1145 GL_UNSIGNED_INT, w->indices + w->nSIdx);
1146 }
1147
1148 glDisableClientState (GL_NORMAL_ARRAY);
1149
1150 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1151
1152 glColor4usv (defaultColor);
1153
1154 if (wire)
1155 {
1156 glDisable (GL_LIGHTING);
1157
1158 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1159
1160 v = (float *) w->vertices;
1161
1162 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1163
1164 glDisableClientState (GL_NORMAL_ARRAY);
1165
1166 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1167 glDrawElements (GL_LINE_STRIP, w->nSIdx, GL_UNSIGNED_INT, w->indices);
1168
1169 if (currentDeformation == DeformationSphere)
1170 {
1171 v = (float *) w->vertices2;
1172
1173 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1174 glDrawElements (GL_LINE_STRIP, w->nWIdx2,
1175 GL_UNSIGNED_INT, w->indices2);
1176 }
1177 else
1178 glDrawElements (GL_LINE_STRIP, w->nWIdx,
1179 GL_UNSIGNED_INT, w->indices + w->nSIdx);
1180 }
1181 }
1182
1183 void
drawGround(Water * w,Water * g,int currentDeformation)1184 drawGround (Water *w,
1185 Water *g,
1186 int currentDeformation)
1187 {
1188 float *v;
1189 float *n;
1190
1191 if (!g)
1192 return;
1193
1194 glEnable (GL_DEPTH_TEST);
1195
1196 glEnable (GL_LIGHTING);
1197 glEnable (GL_LIGHT1);
1198 glDisable (GL_LIGHT0);
1199
1200 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1201
1202 v = (float *) g->vertices;
1203 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1204
1205 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1206
1207 glEnableClientState (GL_NORMAL_ARRAY);
1208
1209 if (w)
1210 n = (float *) w->vertices;
1211 else
1212 n = (float *) g->vertices;
1213 glNormalPointer (GL_FLOAT, 6 * sizeof (float), n + 3);
1214
1215 glDrawElements (GL_TRIANGLES, g->nSIdx, GL_UNSIGNED_INT, g->indices);
1216
1217 if (currentDeformation == DeformationSphere && g->vertices2 && g->indices2)
1218 {
1219 v = (float *) g->vertices2;
1220 n = (float *) g->vertices2;
1221
1222 glNormalPointer (GL_FLOAT, 6 * sizeof (float), n + 3);
1223 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1224
1225 glDrawElements (GL_TRIANGLES, g->nWIdx2,
1226 GL_UNSIGNED_INT, g->indices2);
1227 }
1228 else
1229 glDrawElements (GL_TRIANGLES, g->nWIdx,
1230 GL_UNSIGNED_INT, g->indices + g->nSIdx);
1231
1232 glDisableClientState (GL_NORMAL_ARRAY);
1233 glDisable (GL_LIGHTING);
1234
1235 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1236 }
1237
fillBottom(Water * w,float distance,float bottom,int currentDeformation)1238 static void fillBottom (Water *w,
1239 float distance,
1240 float bottom,
1241 int currentDeformation)
1242 {
1243 int i;
1244 float *v;
1245 int size = w->size;
1246
1247 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1248
1249 if (currentDeformation == DeformationCylinder)
1250 {
1251 v = (float *) w->vertices;
1252
1253 glNormal3f (0, -1, 0);
1254
1255 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1256 glDisableClientState (GL_NORMAL_ARRAY);
1257
1258 glDrawElements (GL_TRIANGLE_FAN, w->nBIdx,
1259 GL_UNSIGNED_INT, w->indices + w->nSIdx + w->nWIdx);
1260 }
1261 else if (currentDeformation == DeformationSphere &&
1262 w->vertices2 && w->indices2)
1263 {
1264 v = (float *) w->vertices2;
1265
1266 glVertexPointer (3, GL_FLOAT, 6 * sizeof (float), v);
1267
1268 glDisableClientState (GL_NORMAL_ARRAY);
1269
1270 glNormal3f (0, -1, 0);
1271
1272 glDrawElements (GL_TRIANGLE_FAN, w->nBIdx2,
1273 GL_UNSIGNED_INT, w->indices2 + w->nWIdx2);
1274 }
1275 else
1276 {
1277 float r = distance / cosf (M_PI / size);
1278 float ang = M_PI / size;
1279 float aStep = 2 * M_PI / size;
1280
1281 glBegin (GL_TRIANGLE_FAN);
1282 glNormal3f (0, -1, 0);
1283 glVertex3f (0.0, bottom, 0.0);
1284
1285 for (i = 0; i <= size; i++)
1286 {
1287 glVertex3f (sinf (ang) * r, bottom, cosf (ang) * r);
1288 ang -= aStep;
1289 }
1290 glEnd ();
1291 }
1292
1293 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1294 }
1295
1296 void
drawBottomGround(Water * w,float distance,float bottom,int currentDeformation)1297 drawBottomGround (Water *w,
1298 float distance,
1299 float bottom,
1300 int currentDeformation)
1301 {
1302 glDisable (GL_DEPTH_TEST);
1303
1304 glEnable (GL_LIGHTING);
1305 glEnable (GL_LIGHT1);
1306 glDisable (GL_LIGHT0);
1307
1308 fillBottom (w, distance, bottom, currentDeformation);
1309
1310 glDisable (GL_LIGHTING);
1311 }
1312
1313 void
drawBottomWater(Water * w,float distance,float bottom,int currentDeformation)1314 drawBottomWater (Water *w,
1315 float distance,
1316 float bottom,
1317 int currentDeformation)
1318 {
1319 glDisable (GL_DEPTH_TEST);
1320
1321 glDisable (GL_LIGHTING);
1322
1323 glEnable (GL_COLOR_MATERIAL);
1324 fillBottom (w, distance, bottom, currentDeformation);
1325 }
1326
1327 void
setWaterMaterial(unsigned short * waterColor)1328 setWaterMaterial (unsigned short * waterColor)
1329 {
1330 static const float mat_shininess[] = { 140.0 };
1331 static const float mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
1332
1333 glDisable (GL_COLOR_MATERIAL);
1334 setMaterialAmbientDiffuse4us (waterColor, 2.0, 0.8);
1335
1336 glColor4usv (waterColor);
1337
1338 glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1339 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1340 }
1341
1342 void
setGroundMaterial(unsigned short * groundColor)1343 setGroundMaterial (unsigned short * groundColor)
1344 {
1345 static const float mat_shininess[] = { 40.0 };
1346 static const float mat_specular[] = { 0.0, 0.0, 0.0, 1.0 };
1347
1348 glDisable (GL_COLOR_MATERIAL);
1349 setMaterialAmbientDiffuse4us (groundColor, 1.5, 0.8);
1350
1351 glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1352 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1353 }
1354
1355 float
getHeight(Water * w,float x,float z)1356 getHeight (Water *w,
1357 float x,
1358 float z)
1359 {
1360 if (!w)
1361 return 0.0;
1362 return w->bh + (w->wa * sinf (w->wave1 + w->wf * x * z)) +
1363 (w->swa * sinf (w->wave2 + w->swf * x * z));
1364 }
1365
1366 /* use other scale for creatures inside cube */
1367 float
getGroundHeight(CompScreen * s,float x,float z)1368 getGroundHeight (CompScreen *s,
1369 float x,
1370 float z)
1371 {
1372 ATLANTIS_SCREEN (s);
1373
1374 Water *g = as->ground;
1375
1376 if (atlantisGetShowGround(s))
1377 return getHeight(g, x / (100000 * as->ratio),
1378 z / (100000 * as->ratio)) * 100000;
1379 return -0.5*100000;
1380 }
1381