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 * Detailed fish/fish2 and coral 3D models made by Biswajyoti Mahanta.
30 *
31 * Butterflyfish and Chromis 3D models/auto-generated code by "unpush"
32 */
33
34 /*
35 * Based on atlantis xscreensaver http://www.jwz.org/xscreensaver/
36 */
37
38 /* atlantis --- Shows moving 3D sea animals */
39
40 /* Copyright (c) E. Lassauge, 1998. */
41
42 /*
43 * Permission to use, copy, modify, and distribute this software and its
44 * documentation for any purpose and without fee is hereby granted,
45 * provided that the above copyright notice appear in all copies and that
46 * both that copyright notice and this permission notice appear in
47 * supporting documentation.
48 *
49 * This file is provided AS IS with no warranties of any kind. The author
50 * shall have no liability with respect to the infringement of copyrights,
51 * trade secrets or any patents by this file or any part thereof. In no
52 * event will the author be liable for any lost revenue or profits or
53 * other special, indirect and consequential damages.
54 *
55 * The original code for this mode was written by Mark J. Kilgard
56 * as a demo for openGL programming.
57 *
58 * Porting it to xlock was possible by comparing the original Mesa's morph3d
59 * demo with it's ported version to xlock, so thanks for Marcelo F. Vianna
60 * (look at morph3d.c) for his indirect help.
61 *
62 * Thanks goes also to Brian Paul for making it possible and inexpensive
63 * to use OpenGL at home.
64 *
65 * My e-mail address is lassauge@users.sourceforge.net
66 *
67 * Eric Lassauge (May-13-1998)
68 *
69 */
70
71 /**
72 * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
73 * ALL RIGHTS RESERVED
74 * Permission to use, copy, modify, and distribute this software for
75 * any purpose and without fee is hereby granted, provided that the above
76 * copyright notice appear in all copies and that both the copyright notice
77 * and this permission notice appear in supporting documentation, and that
78 * the name of Silicon Graphics, Inc. not be used in advertising
79 * or publicity pertaining to distribution of the software without specific,
80 * written prior permission.
81 *
82 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
83 * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
84 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
85 * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
86 * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
87 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
88 * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
89 * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
90 * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
91 * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
92 * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
93 * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
94 *
95 * US Government Users Restricted Rights
96 * Use, duplication, or disclosure by the Government is subject to
97 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
98 * (c)(1)(ii) of the Rights in Technical Data and Computer Software
99 * clause at DFARS 252.227-7013 and/or in similar or successor
100 * clauses in the FAR or the DOD or NASA FAR Supplement.
101 * Unpublished-- rights reserved under the copyright laws of the
102 * United States. Contractor/manufacturer is Silicon Graphics,
103 * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
104 *
105 * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
106 */
107
108
109 /*
110 * Coordinate system:
111 * clockwise from top
112 * with x=radius, y=0 the "top" (towards 1st desktop from above view)
113 * and the z coordinate as height.
114 */
115
116 #include <stdlib.h>
117 #include <string.h>
118 #include <stdio.h>
119 #include <signal.h>
120 #include <unistd.h>
121 #include <math.h>
122
123 #include "atlantis-internal.h"
124 #include "atlantis_options.h"
125
126
127 static void initWorldVariables (CompScreen *);
128 static void loadModels (CompScreen *);
129 static void freeModels (CompScreen *s);
130 static void setLightPosition (CompScreen *, GLenum light);
131 static void atlantisInitLightPosition (CompScreen *);
132
133 int atlantisDisplayPrivateIndex;
134
135 int cubeDisplayPrivateIndex;
136
137
138 static void
initAtlantis(CompScreen * s)139 initAtlantis (CompScreen *s)
140 {
141 ATLANTIS_SCREEN (s);
142
143 int i = 0, i2 = 0;
144 int j, k;
145 int num;
146
147 CompListValue * cType = atlantisGetCreatureType (s);
148 CompListValue * cNumber = atlantisGetCreatureNumber (s);
149 CompListValue * cSize = atlantisGetCreatureSize (s);
150 CompListValue * cColor = atlantisGetCreatureColor (s);
151
152 num = MIN (cType->nValue, cNumber->nValue);
153 num = MIN (num, cSize->nValue);
154 num = MIN (num, cColor->nValue);
155
156 as->water = NULL;
157 as->ground = NULL;
158
159 as->numFish = 0;
160 as->numCrabs = 0;
161
162 for (k = 0; k < num; k++)
163 {
164 if (cSize->value[k].i == 0)
165 continue;
166
167 if (cType->value[k].i != CRAB)
168 as->numFish += cNumber->value[k].i;
169 else
170 as->numCrabs += cNumber->value[k].i;
171 }
172
173 as->fish = calloc (as->numFish, sizeof(fishRec));
174 as->crab = calloc (as->numCrabs, sizeof(crabRec));
175
176 if (atlantisGetShowWater (s))
177 as->waterHeight = atlantisGetWaterHeight (s) * 100000 - 50000;
178 else
179 as->waterHeight = 50000;
180
181 as->oldProgress = 0;
182
183 for (k = 0; k < num; k++)
184 {
185 for (j = 0; j < cNumber->value[k].i; j++)
186 {
187 int size = cSize->value[k].i;
188 int type = cType->value[k].i;
189
190 if (size==0)
191 break;
192
193 if (type != CRAB)
194 {
195 fishRec * fish = &(as->fish[i]);
196
197 fish->type = type;
198
199 if (type == WHALE)
200 size /= 2;
201 if (type == DOLPHIN)
202 size *= 2;
203 if (type == SHARK)
204 size *= 3;
205
206 fish->size = randf (sqrtf (size) ) + size;
207 fish->speed = randf (150) + 50;
208
209 if (j == 0)
210 setSimilarColor4us (fish->color, cColor->value[k].c,
211 0.2, 0.1);
212 else
213 setSimilarColor (fish->color, as->fish[i-j].color,
214 0.2, 0.1);
215
216 fish->x = randf (size);
217 fish->y = randf (size);
218 fish->z = (as->waterHeight - 50000) / 2 +
219 randf (size * 0.02) - size * 0.01;
220 fish->psi = randf (360) - 180.0;
221 fish->theta = randf (100) - 50;
222 fish->v = 1.0;
223
224 fish->group = k;
225
226 fish->boidsCounter = i % NUM_GROUPS;
227 fish->boidsPsi = fish->psi;
228 fish->boidsTheta = fish->theta;
229
230 fish->smoothTurnCounter = NRAND (3);
231 fish->smoothTurnAmount = NRAND (3) - 1;
232
233 fish->prevRandPsi = 0;
234 fish->prevRandTh = 0;
235
236 i++;
237 }
238 else
239 {
240 crabRec * crab = &(as->crab[i2]);
241
242 crab->size = randf (sqrtf (size)) + size;
243 crab->speed = randf (100) + 50;
244
245 if (j == 0)
246 setSimilarColor4us (crab->color, cColor->value[k].c,
247 0.2, 0.1);
248 else
249 setSimilarColor (crab->color, as->crab[i2 - j].color,
250 0.2, 0.1);
251
252 crab->x = randf (2 * size) - size;
253 crab->y = randf (2 * size) - size;
254
255 if (atlantisGetStartCrabsBottom (s))
256 {
257 crab->z = 50000;
258 crab->isFalling = FALSE;
259 }
260 else
261 {
262 crab->z = (as->waterHeight - 50000)/2;
263 crab->isFalling = TRUE;
264 }
265
266 crab->psi = randf (360);
267 crab->theta= 0;
268
269 crab->scuttlePsi = 0;
270 crab->scuttleAmount = NRAND (3) - 1;
271
272 i2++;
273 }
274 }
275 }
276
277 as->numCorals = 0;
278 as->numAerators = 0;
279
280 cType = atlantisGetPlantType (s);
281 cNumber = atlantisGetPlantNumber (s);
282 cSize = atlantisGetPlantSize (s);
283 cColor = atlantisGetPlantColor (s);
284
285 num = MIN (cType->nValue, cNumber->nValue);
286 num = MIN (num, cSize->nValue);
287 num = MIN (num, cColor->nValue);
288
289 for (k = 0; k < num; k++)
290 {
291 switch (cType->value[k].i) {
292 case 0:
293 case 1:
294 as->numCorals += cNumber->value[k].i;
295 break;
296
297 case 2:
298 as->numAerators += cNumber->value[k].i;
299 break;
300 }
301 }
302
303 as->coral = calloc (as->numCorals, sizeof(coralRec));
304 as->aerator = calloc (as->numAerators, sizeof(aeratorRec));
305
306 for (k = 0; k < as->numAerators; k++)
307 {
308 as->aerator[k].numBubbles = 20;
309 as->aerator[k].bubbles = calloc (as->aerator[k].numBubbles,
310 sizeof (Bubble));
311 }
312
313 initWorldVariables(s);
314
315 updateWater (s, 0); /* make sure normals are initialized */
316 updateGround (s, 0);
317
318 loadModels(s);
319 }
320
321 static void
loadModels(CompScreen * s)322 loadModels (CompScreen *s)
323 {
324 ATLANTIS_SCREEN (s);
325
326 as->crabDisplayList = glGenLists (1);
327 glNewList (as->crabDisplayList, GL_COMPILE);
328 DrawCrab (0);
329 glEndList ();
330
331 as->coralDisplayList = glGenLists (1);
332 glNewList (as->coralDisplayList, GL_COMPILE);
333 atlantisGetLowPoly (s) ? DrawCoralLow (0) : DrawCoral (0);
334 glEndList ();
335
336 as->coral2DisplayList = glGenLists (1);
337 glNewList (as->coral2DisplayList, GL_COMPILE);
338 atlantisGetLowPoly (s) ? DrawCoral2Low (0) : DrawCoral2 (0);
339 glEndList ();
340
341 as->bubbleDisplayList = glGenLists (1);
342 glNewList (as->bubbleDisplayList, GL_COMPILE);
343 atlantisGetLowPoly (s) ? DrawBubble (0, 6) : DrawBubble (0, 9);
344 glEndList ();
345 }
346
347 static void
freeModels(CompScreen * s)348 freeModels (CompScreen *s)
349 {
350 ATLANTIS_SCREEN (s);
351
352 glDeleteLists (as->crabDisplayList, 1);
353 glDeleteLists (as->coralDisplayList, 1);
354 glDeleteLists (as->coral2DisplayList, 1);
355 glDeleteLists (as->bubbleDisplayList, 1);
356 }
357
calculateScreenRatio(CompScreen * s)358 static float calculateScreenRatio (CompScreen *s)
359 {
360 CUBE_SCREEN (s);
361
362 float temp, ratio;
363 int i;
364
365 if (!atlantisGetRescaleWidth (s))
366 return 1.0f;
367
368 ratio = (float) s->width / (float) s->height;
369
370 if (s->nOutputDev <= 1)
371 return ratio;
372
373 temp = 0;
374
375 if (cs->moMode == CUBE_MOMODE_AUTO && cs->nOutput < s->nOutputDev)
376 {
377 return ratio;
378 }
379 else if (cs->moMode == CUBE_MOMODE_ONE)
380 {
381 /* this doesn't seem right, but it works */
382 for (i = 0; i < s->nOutputDev; i++)
383 temp += (float) s->width / (float) s->outputDev->height;;
384
385 if (temp != 0)
386 ratio = temp / s->nOutputDev;
387 }
388 else
389 {
390 for (i = 0; i < s->nOutputDev; i++)
391 temp += (float) s->outputDev->width / (float) s->outputDev->height;
392
393 if (temp != 0)
394 ratio = temp / s->nOutputDev;
395 }
396
397 return ratio;
398 }
399
400 static void
initWorldVariables(CompScreen * s)401 initWorldVariables (CompScreen *s)
402 {
403 ATLANTIS_SCREEN (s);
404 CUBE_SCREEN (s);
405
406 int i = 0, i2 = 0;
407 int j, k;
408 int bi, num;
409
410 coralRec * coral;
411 aeratorRec * aerator;
412
413 CompListValue * cType = atlantisGetPlantType (s);
414 CompListValue * cNumber = atlantisGetPlantNumber (s);
415 CompListValue * cSize = atlantisGetPlantSize (s);
416 CompListValue * cColor = atlantisGetPlantColor (s);
417
418 as->speedFactor = atlantisGetSpeedFactor (s);
419
420 as->hsize = s->hsize * cs->nOutput;
421
422 as->arcAngle = 360.0f / as->hsize;
423 as->radius = (100000 - 1) * cs->distance /
424 cosf (0.5 * (as->arcAngle * toRadians));
425 as->topDistance = (100000 - 1) * cs->distance;
426
427 as->ratio = calculateScreenRatio (s);
428
429 as->sideDistance = as->topDistance * as->ratio;
430 /* the 100000 comes from scaling by 0.00001 ( = (1/0.00001) ) */
431
432 num = MIN (cType->nValue, cNumber->nValue);
433 num = MIN (num, cSize->nValue);
434 num = MIN (num, cColor->nValue);
435
436 for (k = 0; k < num; k++)
437 {
438 for (j = 0; j < cNumber->value[k].i; j++)
439 {
440 int size = cSize->value[k].i;
441
442 switch (cType->value[k].i) {
443 case 0:
444 case 1:
445 coral = &(as->coral[i]);
446
447 coral->size = (randf (sqrtf(size)) + size);
448 coral->type = cType->value[k].i;
449
450 if (j == 0)
451 setSimilarColor4us (coral->color, cColor->value[k].c,
452 0.2, 0.2);
453 else
454 setSimilarColor (coral->color, as->coral[i - j].color,
455 0.2, 0.2);
456
457 coral->psi = randf (360);
458
459 setRandomLocation (s, &(coral->x), &(coral->y), 3 * size);
460 coral->z = -50000;
461 i++;
462 break;
463
464 case 2:
465 aerator = &(as->aerator[i2]);
466
467 aerator->size = randf (sqrtf (size)) + size;
468 aerator->type = cType->value[k].i;
469
470 if (j == 0)
471 setSimilarColor4us (aerator->color, cColor->value[k].c,
472 0, 0);
473 else
474 setSimilarColor (aerator->color, as->aerator[i2-j].color,
475 0.0, 0.0);
476
477 setRandomLocation (s, &(aerator->x), &(aerator->y), size);
478 aerator->z = -50000;
479
480 for (bi = 0; bi < aerator->numBubbles; bi++)
481 {
482 aerator->bubbles[bi].size = size;
483 aerator->bubbles[bi].x = aerator->x;
484 aerator->bubbles[bi].y = aerator->y;
485 aerator->bubbles[bi].z = aerator->z;
486 aerator->bubbles[bi].speed = 100 + randf (150);
487 aerator->bubbles[bi].offset = randf (2 * PI);
488 aerator->bubbles[bi].counter = 0;
489 }
490
491 i2++;
492 break;
493 }
494 }
495 }
496
497 }
498
499 static void
freeAtlantis(CompScreen * s)500 freeAtlantis (CompScreen *s)
501 {
502 ATLANTIS_SCREEN (s);
503
504 int i;
505
506 if (as->fish)
507 free (as->fish);
508 if (as->crab)
509 free (as->crab);
510 if (as->coral)
511 free (as->coral);
512
513 if (as->aerator)
514 {
515 for (i = 0; i < as->numAerators; i++)
516 {
517 if (as->aerator[i].bubbles)
518 free (as->aerator[i].bubbles);
519 }
520
521 free (as->aerator);
522 }
523
524 freeWater (as->water);
525 freeWater (as->ground);
526
527 as->fish = NULL;
528 as->crab = NULL;
529 as->coral= NULL;
530 as->aerator = NULL;
531
532 freeModels(s);
533 }
534
535 static void
updateAtlantis(CompScreen * s)536 updateAtlantis (CompScreen *s)
537 {
538 freeAtlantis (s);
539 initAtlantis (s);
540 }
541 static void
atlantisScreenOptionChange(CompScreen * s,CompOption * opt,AtlantisScreenOptions num)542 atlantisScreenOptionChange (CompScreen *s,
543 CompOption *opt,
544 AtlantisScreenOptions num)
545 {
546 updateAtlantis (s);
547 }
548 static void
atlantisSpeedFactorOptionChange(CompScreen * s,CompOption * opt,AtlantisScreenOptions num)549 atlantisSpeedFactorOptionChange (CompScreen *s,
550 CompOption *opt,
551 AtlantisScreenOptions num)
552 {
553 ATLANTIS_SCREEN (s);
554 as->speedFactor = atlantisGetSpeedFactor (s);
555 }
556
557 static void
atlantisLightingOptionChange(CompScreen * s,CompOption * opt,AtlantisScreenOptions num)558 atlantisLightingOptionChange (CompScreen *s,
559 CompOption *opt,
560 AtlantisScreenOptions num)
561 {
562 atlantisInitLightPosition (s);
563 }
564
565 static void
atlantisLowPolyOptionChange(CompScreen * s,CompOption * opt,AtlantisScreenOptions num)566 atlantisLowPolyOptionChange (CompScreen *s,
567 CompOption *opt,
568 AtlantisScreenOptions num)
569 {
570 freeModels (s);
571 loadModels (s);
572 }
573
574 static void
atlantisClearTargetOutput(CompScreen * s,float xRotate,float vRotate)575 atlantisClearTargetOutput (CompScreen *s,
576 float xRotate,
577 float vRotate)
578 {
579 ATLANTIS_SCREEN (s);
580 CUBE_SCREEN (s);
581
582 UNWRAP (as, cs, clearTargetOutput);
583 (*cs->clearTargetOutput)(s, xRotate, vRotate);
584 WRAP (as, cs, clearTargetOutput, atlantisClearTargetOutput);
585
586 glClear (GL_DEPTH_BUFFER_BIT);
587 }
588
589 static void
setLightPosition(CompScreen * s,GLenum light)590 setLightPosition (CompScreen *s,
591 GLenum light)
592 {
593 float position[] = { 0.0, 0.0, 1.0, 0.0 };
594 float angle = atlantisGetLightInclination(s) * toRadians;
595
596 if (atlantisGetRotateLighting (s))
597 angle = 0;
598
599 position[1] = sinf (angle);
600 position[2] = cosf (angle);
601
602 glLightfv (light, GL_POSITION, position);
603 }
604
605 static void
atlantisInitLightPosition(CompScreen * s)606 atlantisInitLightPosition(CompScreen *s)
607 {
608 glPushMatrix ();
609 glLoadIdentity ();
610 setLightPosition (s, GL_LIGHT1);
611 glPopMatrix();
612 }
613
614 static void
atlantisPaintInside(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * output,int size)615 atlantisPaintInside(CompScreen *s,
616 const ScreenPaintAttrib *sAttrib,
617 const CompTransform *transform,
618 CompOutput *output,
619 int size)
620 {
621 ATLANTIS_SCREEN (s);
622 CUBE_SCREEN (s);
623
624 int i, j;
625
626 float scale, ratio;
627
628 static const float mat_shininess[] = { 60.0 };
629 static const float mat_specular[] = { 0.6, 0.6, 0.6, 1.0 };
630 static const float mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
631 static const float mat_ambient[] = { 0.8, 0.8, 0.9, 1.0 };
632
633 static const float lmodel_localviewer[] = { 0.0 };
634 static const float lmodel_twoside[] = { 0.0 };
635 static float lmodel_ambient[] = { 0.4, 0.4, 0.4, 0.4 };
636
637 ScreenPaintAttrib sA = *sAttrib;
638 CompTransform mT = *transform;
639
640 int new_hsize = s->hsize * cs->nOutput;
641
642 int drawDeformation = (as->oldProgress == 0.0f ? getCurrentDeformation(s) :
643 getDeformationMode (s));
644
645 if (atlantisGetShowWater(s))
646 as->waterHeight = atlantisGetWaterHeight(s) * 100000 - 50000;
647 else
648 as->waterHeight = 50000;
649
650 ratio = calculateScreenRatio (s);
651
652 if (new_hsize < as->hsize || fabsf (ratio - as->ratio) > 0.0001)
653 updateAtlantis (s);
654 else if (new_hsize > as->hsize)
655 { /* let fish swim in their expanded enclosure without fully resetting */
656 initWorldVariables (s);
657 }
658
659 if (atlantisGetShowWater (s) || atlantisGetShowWaterWire (s) ||
660 atlantisGetShowGround (s))
661 {
662 updateDeformation (s, drawDeformation);
663 updateHeight (as->water, atlantisGetShowGround (s) ? as->ground : NULL,
664 atlantisGetWaveRipple(s), drawDeformation);
665 }
666
667 sA.yRotate += cs->invert * (360.0f / size) * (cs->xRotations -
668 (s->x * cs->nOutput));
669
670 (*s->applyScreenTransform)(s, &sA, output, &mT);
671
672 glPushMatrix();
673
674 glLoadMatrixf (mT.m);
675
676 if (!atlantisGetRotateLighting (s))
677 setLightPosition(s, GL_LIGHT1);
678
679 glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
680
681 glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
682
683 Bool enabledCull = FALSE;
684
685 glPushAttrib (GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT | GL_LIGHTING_BIT);
686
687 glEnable (GL_BLEND);
688 glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
689
690 for (i=0; i<4; i++)
691 lmodel_ambient[i] = atlantisGetLightAmbient(s);
692
693 glLightModelfv (GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_localviewer);
694 glLightModelfv (GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
695 glLightModelfv (GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
696
697 if (glIsEnabled (GL_CULL_FACE))
698 {
699 enabledCull = TRUE;
700 }
701
702 if (atlantisGetShowWater (s))
703 {
704 int cull;
705
706 glGetIntegerv (GL_CULL_FACE_MODE, &cull);
707 glEnable (GL_CULL_FACE);
708
709 glCullFace (~cull & (GL_FRONT | GL_BACK));
710 setWaterMaterial (atlantisGetWaterColor (s));
711 drawWater (as->water, TRUE, FALSE, drawDeformation);
712 glCullFace (cull);
713 }
714
715 if (atlantisGetShowGround (s))
716 {
717 setGroundMaterial (atlantisGetGroundColor (s));
718
719 if (atlantisGetRenderWaves (s) && atlantisGetShowWater (s) &&
720 !atlantisGetWaveRipple (s))
721 drawGround (as->water, as->ground, drawDeformation);
722 else
723 drawGround (NULL, as->ground, drawDeformation);
724 }
725
726 glPushMatrix();
727
728 glColor4usv (defaultColor);
729
730 glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
731 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
732 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
733 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
734
735 glEnable (GL_NORMALIZE);
736 glEnable (GL_DEPTH_TEST);
737 glEnable (GL_COLOR_MATERIAL);
738 glEnable (GL_LIGHTING);
739 glEnable (GL_LIGHT1);
740 glDisable (GL_LIGHT0);
741
742 glShadeModel(GL_SMOOTH);
743
744 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
745
746 glScalef (0.00001f / as->ratio, 0.00001f, 0.00001f / as->ratio);
747
748 for (i = 0; i < as->numCrabs; i++)
749 {
750 glPushMatrix ();
751
752 CrabTransform (& (as->crab[i]));
753
754 scale = as->crab[i].size;
755 scale /= 6000.0f;
756 glScalef (scale, scale, scale);
757 glColor4fv (as->crab[i].color);
758
759 initDrawCrab ();
760 glCallList (as->crabDisplayList);
761 finDrawCrab ();
762
763 glPopMatrix ();
764 }
765
766 for (i = 0; i < as->numCorals; i++)
767 {
768 glPushMatrix ();
769
770 glTranslatef (as->coral[i].y, as->coral[i].z, as->coral[i].x);
771 glRotatef (-as->coral[i].psi, 0.0, 1.0, 0.0);
772
773 scale = as->coral[i].size;
774 scale /= 6000.0f;
775 glScalef (scale, scale, scale);
776 glColor4fv (as->coral[i].color);
777
778 switch (as->coral[i].type) {
779 case 0:
780 initDrawCoral ();
781 glCallList (as->coralDisplayList);
782 finDrawCoral ();
783 break;
784 case 1:
785 initDrawCoral2 ();
786 glCallList (as->coral2DisplayList);
787 finDrawCoral2 ();
788 break;
789 }
790
791 glPopMatrix ();
792 }
793
794 for (i = 0; i < as->numFish; i++)
795 {
796 glPushMatrix ();
797 FishTransform (& (as->fish[i]));
798 scale = as->fish[i].size;
799 scale /= 6000.0f;
800 glScalef (scale, scale, scale);
801 glColor4fv (as->fish[i].color);
802
803 switch (as->fish[i].type)
804 {
805 case SHARK:
806 DrawShark (& (as->fish[i]), 0);
807 break;
808
809 case WHALE:
810 DrawWhale (& (as->fish[i]), 0);
811 break;
812
813 case DOLPHIN:
814 DrawDolphin (& (as->fish[i]), 0);
815 break;
816
817 case BUTTERFLYFISH:
818 initDrawBFish (as->fish[i].color);
819 AnimateBFish (as->fish[i].htail);
820 DrawAnimatedBFish ();
821 finDrawBFish ();
822 break;
823
824 case CHROMIS:
825 initDrawChromis (as->fish[i].color);
826 AnimateChromis (as->fish[i].htail);
827 DrawAnimatedChromis ();
828 finDrawChromis ();
829 break;
830
831 case CHROMIS2:
832 initDrawChromis2 (as->fish[i].color);
833 AnimateChromis (as->fish[i].htail);
834 DrawAnimatedChromis ();
835 finDrawChromis ();
836 break;
837
838 case CHROMIS3:
839 initDrawChromis3 (as->fish[i].color);
840 AnimateChromis (as->fish[i].htail);
841 DrawAnimatedChromis ();
842 finDrawChromis ();
843 break;
844
845 case FISH:
846 initDrawFish (as->fish[i].color);
847 AnimateFish (as->fish[i].htail);
848 DrawAnimatedFish ();
849 finDrawFish ();
850 break;
851
852 case FISH2:
853 initDrawFish2 (as->fish[i].color);
854 AnimateFish2 (as->fish[i].htail);
855 DrawAnimatedFish2 ();
856 finDrawFish2 ();
857 break;
858
859 default:
860 break;
861 }
862
863 glPopMatrix();
864 }
865
866 glEnable(GL_CULL_FACE);
867
868 for (i = 0; i < as->numAerators; i++)
869 {
870 for (j = 0; j < as->aerator[i].numBubbles; j++)
871 {
872 glPushMatrix ();
873
874 BubbleTransform (&(as->aerator[i].bubbles[j]));
875 scale = as->aerator[i].bubbles[j].size;
876
877 glScalef (scale, scale, scale);
878 glColor4fv (as->aerator[i].color);
879
880 glCallList (as->bubbleDisplayList);
881
882 glPopMatrix ();
883 }
884 }
885
886 glPopMatrix ();
887
888 if (atlantisGetShowWater (s) || atlantisGetShowWaterWire (s))
889 {
890 glEnable (GL_CULL_FACE);
891 setWaterMaterial (atlantisGetWaterColor (s));
892 drawWater (as->water, atlantisGetShowWater (s),
893 atlantisGetShowWaterWire (s), drawDeformation);
894 }
895
896
897 if (atlantisGetShowGround (s))
898 {
899 setGroundMaterial (atlantisGetGroundColor (s));
900 drawBottomGround (as->ground, cs->distance, -0.5, drawDeformation);
901 }
902 else if (atlantisGetShowWater (s))
903 {
904 setWaterMaterial (atlantisGetWaterColor (s));
905 drawBottomWater (as->water, cs->distance, -0.5, drawDeformation);
906 }
907
908
909 glDisable (GL_LIGHT1);
910 glDisable (GL_NORMALIZE);
911
912 if (!s->lighting)
913 glDisable (GL_LIGHTING);
914
915 glDisable (GL_DEPTH_TEST);
916
917 if (enabledCull)
918 glDisable (GL_CULL_FACE);
919
920 glPopMatrix ();
921
922 glPopAttrib ();
923
924 as->damage = TRUE;
925
926 UNWRAP (as, cs, paintInside);
927 (*cs->paintInside)(s, sAttrib, transform, output, size);
928 WRAP (as, cs, paintInside, atlantisPaintInside);
929 }
930
931 static void
atlantisPreparePaintScreen(CompScreen * s,int ms)932 atlantisPreparePaintScreen (CompScreen *s,
933 int ms)
934 {
935 ATLANTIS_SCREEN (s);
936
937 int i, j;
938
939 Bool currentDeformation = getCurrentDeformation (s);
940 int oldhsize = as->hsize;
941
942 updateWater (s, (float) ms / 1000.0f);
943 updateGround (s, (float) ms / 1000.0f);
944
945 /* temporary change for animals inside */
946 if (currentDeformation == DeformationCylinder && as->oldProgress > 0.9)
947 {
948 as->hsize *= 32 / as->hsize;
949 as->arcAngle = 360.0f / as->hsize;
950 as->sideDistance = as->radius * as->ratio;
951 }
952 else if (currentDeformation == DeformationSphere)
953 {
954 /* treat enclosure as a cylinder */
955 as->hsize *= 32 / as->hsize;
956 as->arcAngle = 360.0f / as->hsize;
957 as->sideDistance = as->radius * as->ratio;
958
959 }
960
961 for (i = 0; i < as->numFish; i++)
962 {
963 FishPilot (s, i);
964
965 /* animate fish tails */
966 if (as->fish[i].type <= FISH2)
967 {
968 as->fish[i].htail = fmodf (as->fish[i].htail + 0.00025 *
969 as->fish[i].speed * as->speedFactor, 1);
970 }
971 }
972
973 for (i = 0; i < as->numCrabs; i++)
974 {
975 CrabPilot (s, i);
976 }
977
978 for (i = 0; i < as->numCorals; i++)
979 {
980 as->coral[i].z = getGroundHeight (s, as->coral[i].x, as->coral[i].y);
981 }
982
983 for (i = 0; i < as->numAerators; i++)
984 {
985 aeratorRec * aerator = &(as->aerator[i]);
986 float bottom = getGroundHeight (s, aerator->x, aerator->y);
987
988 if (aerator->z < bottom)
989 {
990 for (j = 0; j < aerator->numBubbles; j++)
991 {
992 if (aerator->bubbles[j].counter == 0)
993 aerator->bubbles[j].z = bottom;
994 }
995 }
996 aerator->z = bottom;
997 for (j = 0; j < aerator->numBubbles; j++)
998 {
999 BubblePilot(s, i, j);
1000 }
1001 }
1002
1003 as->hsize = oldhsize;
1004 as->arcAngle = 360.0f / as->hsize;
1005 as->sideDistance = as->topDistance * as->ratio;
1006
1007 UNWRAP (as, s, preparePaintScreen);
1008 (*s->preparePaintScreen)(s, ms);
1009 WRAP (as, s, preparePaintScreen, atlantisPreparePaintScreen);
1010 }
1011
1012 static void
atlantisDonePaintScreen(CompScreen * s)1013 atlantisDonePaintScreen (CompScreen * s)
1014 {
1015 ATLANTIS_SCREEN (s);
1016
1017 if (as->damage)
1018 {
1019 damageScreen (s);
1020 as->damage = FALSE;
1021 }
1022
1023 UNWRAP (as, s, donePaintScreen);
1024 (*s->donePaintScreen)(s);
1025 WRAP (as, s, donePaintScreen, atlantisDonePaintScreen);
1026 }
1027
1028 static Bool
atlantisInitDisplay(CompPlugin * p,CompDisplay * d)1029 atlantisInitDisplay (CompPlugin *p,
1030 CompDisplay *d)
1031 {
1032 AtlantisDisplay *ad;
1033
1034 if (!checkPluginABI ("core", CORE_ABIVERSION) ||!checkPluginABI ("cube",
1035 CUBE_ABIVERSION))
1036 return FALSE;
1037
1038 if (!getPluginDisplayIndex (d, "cube", &cubeDisplayPrivateIndex))
1039 return FALSE;
1040
1041 ad = malloc (sizeof(AtlantisDisplay));
1042
1043 if (!ad)
1044 return FALSE;
1045
1046 ad->screenPrivateIndex = allocateScreenPrivateIndex (d);
1047
1048 if (ad->screenPrivateIndex < 0)
1049 {
1050 free (ad);
1051 return FALSE;
1052 }
1053
1054 d->base.privates[atlantisDisplayPrivateIndex].ptr = ad;
1055
1056 return TRUE;
1057 }
1058
1059 static void
atlantisFiniDisplay(CompPlugin * p,CompDisplay * d)1060 atlantisFiniDisplay (CompPlugin *p,
1061 CompDisplay *d)
1062 {
1063 ATLANTIS_DISPLAY (d);
1064
1065 freeScreenPrivateIndex (d, ad->screenPrivateIndex);
1066 free (ad);
1067 }
1068
1069 static Bool
atlantisInitScreen(CompPlugin * p,CompScreen * s)1070 atlantisInitScreen (CompPlugin *p,
1071 CompScreen *s)
1072 {
1073 static const float ambient[] = { 0.0, 0.0, 0.0, 0.0 };
1074 static const float diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
1075 static const float specular[] = { 0.6, 0.6, 0.6, 1.0 };
1076
1077 AtlantisScreen *as;
1078
1079 ATLANTIS_DISPLAY (s->display);
1080 CUBE_SCREEN (s);
1081
1082 as = malloc (sizeof (AtlantisScreen));
1083
1084 if (!as)
1085 return FALSE;
1086
1087 s->base.privates[ad->screenPrivateIndex].ptr = as;
1088
1089 as->damage = FALSE;
1090
1091 glLightfv (GL_LIGHT1, GL_AMBIENT, ambient);
1092 glLightfv (GL_LIGHT1, GL_DIFFUSE, diffuse);
1093 glLightfv (GL_LIGHT1, GL_SPECULAR, specular);
1094 atlantisInitLightPosition (s);
1095
1096 initAtlantis (s);
1097
1098 atlantisSetSpeedFactorNotify (s, atlantisSpeedFactorOptionChange);
1099
1100 atlantisSetLowPolyNotify (s, atlantisLowPolyOptionChange);
1101
1102 atlantisSetCreatureNumberNotify (s, atlantisScreenOptionChange);
1103 atlantisSetCreatureSizeNotify (s, atlantisScreenOptionChange);
1104 atlantisSetCreatureColorNotify (s, atlantisScreenOptionChange);
1105 atlantisSetCreatureTypeNotify (s, atlantisScreenOptionChange);
1106
1107 atlantisSetPlantNumberNotify (s, atlantisScreenOptionChange);
1108 atlantisSetPlantSizeNotify (s, atlantisScreenOptionChange);
1109 atlantisSetPlantColorNotify (s, atlantisScreenOptionChange);
1110 atlantisSetPlantTypeNotify (s, atlantisScreenOptionChange);
1111
1112 atlantisSetRescaleWidthNotify (s, atlantisScreenOptionChange);
1113
1114 atlantisSetRotateLightingNotify (s, atlantisLightingOptionChange);
1115 atlantisSetLightInclinationNotify (s, atlantisLightingOptionChange);
1116
1117
1118 WRAP (as, s, donePaintScreen, atlantisDonePaintScreen);
1119 WRAP (as, s, preparePaintScreen, atlantisPreparePaintScreen);
1120 WRAP (as, cs, clearTargetOutput, atlantisClearTargetOutput);
1121 WRAP (as, cs, paintInside, atlantisPaintInside);
1122
1123 return TRUE;
1124 }
1125
1126 static void
atlantisFiniScreen(CompPlugin * p,CompScreen * s)1127 atlantisFiniScreen (CompPlugin *p,
1128 CompScreen *s)
1129 {
1130 ATLANTIS_SCREEN (s);
1131 CUBE_SCREEN (s);
1132
1133 freeAtlantis (s);
1134
1135 UNWRAP (as, s, donePaintScreen);
1136 UNWRAP (as, s, preparePaintScreen);
1137 UNWRAP (as, cs, clearTargetOutput);
1138 UNWRAP (as, cs, paintInside);
1139
1140 free (as);
1141 }
1142
1143 static Bool
atlantisInit(CompPlugin * p)1144 atlantisInit (CompPlugin * p)
1145 {
1146 atlantisDisplayPrivateIndex = allocateDisplayPrivateIndex ();
1147
1148 if (atlantisDisplayPrivateIndex < 0)
1149 return FALSE;
1150
1151 return TRUE;
1152 }
1153
1154 static void
atlantisFini(CompPlugin * p)1155 atlantisFini (CompPlugin * p)
1156 {
1157 if (atlantisDisplayPrivateIndex >= 0)
1158 freeDisplayPrivateIndex (atlantisDisplayPrivateIndex);
1159 }
1160
1161 static CompBool
atlantisInitObject(CompPlugin * p,CompObject * o)1162 atlantisInitObject (CompPlugin *p,
1163 CompObject *o)
1164 {
1165 static InitPluginObjectProc dispTab[] = {
1166 (InitPluginObjectProc) 0, /* InitCore */
1167 (InitPluginObjectProc) atlantisInitDisplay,
1168 (InitPluginObjectProc) atlantisInitScreen
1169 };
1170
1171 RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
1172 }
1173
1174 static void
atlantisFiniObject(CompPlugin * p,CompObject * o)1175 atlantisFiniObject (CompPlugin *p,
1176 CompObject *o)
1177 {
1178 static FiniPluginObjectProc dispTab[] = {
1179 (FiniPluginObjectProc) 0, /* FiniCore */
1180 (FiniPluginObjectProc) atlantisFiniDisplay,
1181 (FiniPluginObjectProc) atlantisFiniScreen
1182 };
1183
1184 DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
1185 }
1186
1187 CompPluginVTable atlantisVTable = {
1188
1189 "atlantis",
1190 0,
1191 atlantisInit,
1192 atlantisFini,
1193 atlantisInitObject,
1194 atlantisFiniObject,
1195 0,
1196 0
1197 };
1198
1199 CompPluginVTable *
getCompPluginInfo(void)1200 getCompPluginInfo (void)
1201 {
1202 return &atlantisVTable;
1203 }
1204