xref: /aosp_15_r20/frameworks/native/opengl/tests/angeles/demo.c (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /* San Angeles Observation OpenGL ES version example
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2004-2005 Jetro Lauha
3*38e8c45fSAndroid Build Coastguard Worker  * All rights reserved.
4*38e8c45fSAndroid Build Coastguard Worker  * Web: http://iki.fi/jetro/
5*38e8c45fSAndroid Build Coastguard Worker  *
6*38e8c45fSAndroid Build Coastguard Worker  * This source is free software; you can redistribute it and/or
7*38e8c45fSAndroid Build Coastguard Worker  * modify it under the terms of EITHER:
8*38e8c45fSAndroid Build Coastguard Worker  *   (1) The GNU Lesser General Public License as published by the Free
9*38e8c45fSAndroid Build Coastguard Worker  *       Software Foundation; either version 2.1 of the License, or (at
10*38e8c45fSAndroid Build Coastguard Worker  *       your option) any later version. The text of the GNU Lesser
11*38e8c45fSAndroid Build Coastguard Worker  *       General Public License is included with this source in the
12*38e8c45fSAndroid Build Coastguard Worker  *       file LICENSE-LGPL.txt.
13*38e8c45fSAndroid Build Coastguard Worker  *   (2) The BSD-style license that is included with this source in
14*38e8c45fSAndroid Build Coastguard Worker  *       the file LICENSE-BSD.txt.
15*38e8c45fSAndroid Build Coastguard Worker  *
16*38e8c45fSAndroid Build Coastguard Worker  * This source is distributed in the hope that it will be useful,
17*38e8c45fSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18*38e8c45fSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
19*38e8c45fSAndroid Build Coastguard Worker  * LICENSE-LGPL.txt and LICENSE-BSD.txt for more details.
20*38e8c45fSAndroid Build Coastguard Worker  *
21*38e8c45fSAndroid Build Coastguard Worker  * $Id: demo.c,v 1.10 2005/02/08 20:54:39 tonic Exp $
22*38e8c45fSAndroid Build Coastguard Worker  * $Revision: 1.10 $
23*38e8c45fSAndroid Build Coastguard Worker  */
24*38e8c45fSAndroid Build Coastguard Worker 
25*38e8c45fSAndroid Build Coastguard Worker #include <stdlib.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <math.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <float.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <assert.h>
29*38e8c45fSAndroid Build Coastguard Worker 
30*38e8c45fSAndroid Build Coastguard Worker #include <GLES/gl.h>
31*38e8c45fSAndroid Build Coastguard Worker 
32*38e8c45fSAndroid Build Coastguard Worker #include "app.h"
33*38e8c45fSAndroid Build Coastguard Worker #include "shapes.h"
34*38e8c45fSAndroid Build Coastguard Worker #include "cams.h"
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker 
37*38e8c45fSAndroid Build Coastguard Worker // Total run length is 20 * camera track base unit length (see cams.h).
38*38e8c45fSAndroid Build Coastguard Worker #define RUN_LENGTH  (20 * CAMTRACK_LEN)
39*38e8c45fSAndroid Build Coastguard Worker #undef PI
40*38e8c45fSAndroid Build Coastguard Worker #define PI 3.1415926535897932f
41*38e8c45fSAndroid Build Coastguard Worker #define RANDOM_UINT_MAX 65535
42*38e8c45fSAndroid Build Coastguard Worker 
43*38e8c45fSAndroid Build Coastguard Worker 
44*38e8c45fSAndroid Build Coastguard Worker static unsigned long sRandomSeed = 0;
45*38e8c45fSAndroid Build Coastguard Worker 
seedRandom(unsigned long seed)46*38e8c45fSAndroid Build Coastguard Worker static void seedRandom(unsigned long seed)
47*38e8c45fSAndroid Build Coastguard Worker {
48*38e8c45fSAndroid Build Coastguard Worker     sRandomSeed = seed;
49*38e8c45fSAndroid Build Coastguard Worker }
50*38e8c45fSAndroid Build Coastguard Worker 
randomUInt()51*38e8c45fSAndroid Build Coastguard Worker static unsigned long randomUInt()
52*38e8c45fSAndroid Build Coastguard Worker {
53*38e8c45fSAndroid Build Coastguard Worker     sRandomSeed = sRandomSeed * 0x343fd + 0x269ec3;
54*38e8c45fSAndroid Build Coastguard Worker     return sRandomSeed >> 16;
55*38e8c45fSAndroid Build Coastguard Worker }
56*38e8c45fSAndroid Build Coastguard Worker 
57*38e8c45fSAndroid Build Coastguard Worker 
58*38e8c45fSAndroid Build Coastguard Worker // Capped conversion from float to fixed.
floatToFixed(float value)59*38e8c45fSAndroid Build Coastguard Worker static long floatToFixed(float value)
60*38e8c45fSAndroid Build Coastguard Worker {
61*38e8c45fSAndroid Build Coastguard Worker     if (value < -32768) value = -32768;
62*38e8c45fSAndroid Build Coastguard Worker     if (value > 32767) value = 32767;
63*38e8c45fSAndroid Build Coastguard Worker     return (long)(value * 65536);
64*38e8c45fSAndroid Build Coastguard Worker }
65*38e8c45fSAndroid Build Coastguard Worker 
66*38e8c45fSAndroid Build Coastguard Worker #define FIXED(value) floatToFixed(value)
67*38e8c45fSAndroid Build Coastguard Worker 
68*38e8c45fSAndroid Build Coastguard Worker 
69*38e8c45fSAndroid Build Coastguard Worker // Definition of one GL object in this demo.
70*38e8c45fSAndroid Build Coastguard Worker typedef struct {
71*38e8c45fSAndroid Build Coastguard Worker     /* Vertex array and color array are enabled for all objects, so their
72*38e8c45fSAndroid Build Coastguard Worker      * pointers must always be valid and non-NULL. Normal array is not
73*38e8c45fSAndroid Build Coastguard Worker      * used by the ground plane, so when its pointer is NULL then normal
74*38e8c45fSAndroid Build Coastguard Worker      * array usage is disabled.
75*38e8c45fSAndroid Build Coastguard Worker      *
76*38e8c45fSAndroid Build Coastguard Worker      * Vertex array is supposed to use GL_FIXED datatype and stride 0
77*38e8c45fSAndroid Build Coastguard Worker      * (i.e. tightly packed array). Color array is supposed to have 4
78*38e8c45fSAndroid Build Coastguard Worker      * components per color with GL_UNSIGNED_BYTE datatype and stride 0.
79*38e8c45fSAndroid Build Coastguard Worker      * Normal array is supposed to use GL_FIXED datatype and stride 0.
80*38e8c45fSAndroid Build Coastguard Worker      */
81*38e8c45fSAndroid Build Coastguard Worker     GLfixed *vertexArray;
82*38e8c45fSAndroid Build Coastguard Worker     GLubyte *colorArray;
83*38e8c45fSAndroid Build Coastguard Worker     GLfixed *normalArray;
84*38e8c45fSAndroid Build Coastguard Worker     GLint vertexComponents;
85*38e8c45fSAndroid Build Coastguard Worker     GLsizei count;
86*38e8c45fSAndroid Build Coastguard Worker } GLOBJECT;
87*38e8c45fSAndroid Build Coastguard Worker 
88*38e8c45fSAndroid Build Coastguard Worker 
89*38e8c45fSAndroid Build Coastguard Worker static long sStartTick = 0;
90*38e8c45fSAndroid Build Coastguard Worker static long sTick = 0;
91*38e8c45fSAndroid Build Coastguard Worker 
92*38e8c45fSAndroid Build Coastguard Worker static int sCurrentCamTrack = 0;
93*38e8c45fSAndroid Build Coastguard Worker static long sCurrentCamTrackStartTick = 0;
94*38e8c45fSAndroid Build Coastguard Worker static long sNextCamTrackStartTick = 0x7fffffff;
95*38e8c45fSAndroid Build Coastguard Worker 
96*38e8c45fSAndroid Build Coastguard Worker static GLOBJECT *sSuperShapeObjects[SUPERSHAPE_COUNT] = { NULL };
97*38e8c45fSAndroid Build Coastguard Worker static GLOBJECT *sGroundPlane = NULL;
98*38e8c45fSAndroid Build Coastguard Worker 
99*38e8c45fSAndroid Build Coastguard Worker 
100*38e8c45fSAndroid Build Coastguard Worker typedef struct {
101*38e8c45fSAndroid Build Coastguard Worker     float x, y, z;
102*38e8c45fSAndroid Build Coastguard Worker } VECTOR3;
103*38e8c45fSAndroid Build Coastguard Worker 
104*38e8c45fSAndroid Build Coastguard Worker 
freeGLObject(GLOBJECT * object)105*38e8c45fSAndroid Build Coastguard Worker static void freeGLObject(GLOBJECT *object)
106*38e8c45fSAndroid Build Coastguard Worker {
107*38e8c45fSAndroid Build Coastguard Worker     if (object == NULL)
108*38e8c45fSAndroid Build Coastguard Worker         return;
109*38e8c45fSAndroid Build Coastguard Worker     free(object->normalArray);
110*38e8c45fSAndroid Build Coastguard Worker     free(object->colorArray);
111*38e8c45fSAndroid Build Coastguard Worker     free(object->vertexArray);
112*38e8c45fSAndroid Build Coastguard Worker     free(object);
113*38e8c45fSAndroid Build Coastguard Worker }
114*38e8c45fSAndroid Build Coastguard Worker 
115*38e8c45fSAndroid Build Coastguard Worker 
newGLObject(long vertices,int vertexComponents,int useNormalArray)116*38e8c45fSAndroid Build Coastguard Worker static GLOBJECT * newGLObject(long vertices, int vertexComponents,
117*38e8c45fSAndroid Build Coastguard Worker                               int useNormalArray)
118*38e8c45fSAndroid Build Coastguard Worker {
119*38e8c45fSAndroid Build Coastguard Worker     GLOBJECT *result;
120*38e8c45fSAndroid Build Coastguard Worker     result = (GLOBJECT *)malloc(sizeof(GLOBJECT));
121*38e8c45fSAndroid Build Coastguard Worker     if (result == NULL)
122*38e8c45fSAndroid Build Coastguard Worker         return NULL;
123*38e8c45fSAndroid Build Coastguard Worker     result->count = vertices;
124*38e8c45fSAndroid Build Coastguard Worker     result->vertexComponents = vertexComponents;
125*38e8c45fSAndroid Build Coastguard Worker     result->vertexArray = (GLfixed *)malloc(vertices * vertexComponents *
126*38e8c45fSAndroid Build Coastguard Worker                                             sizeof(GLfixed));
127*38e8c45fSAndroid Build Coastguard Worker     result->colorArray = (GLubyte *)malloc(vertices * 4 * sizeof(GLubyte));
128*38e8c45fSAndroid Build Coastguard Worker     if (useNormalArray)
129*38e8c45fSAndroid Build Coastguard Worker     {
130*38e8c45fSAndroid Build Coastguard Worker         result->normalArray = (GLfixed *)malloc(vertices * 3 *
131*38e8c45fSAndroid Build Coastguard Worker                                                 sizeof(GLfixed));
132*38e8c45fSAndroid Build Coastguard Worker     }
133*38e8c45fSAndroid Build Coastguard Worker     else
134*38e8c45fSAndroid Build Coastguard Worker         result->normalArray = NULL;
135*38e8c45fSAndroid Build Coastguard Worker     if (result->vertexArray == NULL ||
136*38e8c45fSAndroid Build Coastguard Worker         result->colorArray == NULL ||
137*38e8c45fSAndroid Build Coastguard Worker         (useNormalArray && result->normalArray == NULL))
138*38e8c45fSAndroid Build Coastguard Worker     {
139*38e8c45fSAndroid Build Coastguard Worker         freeGLObject(result);
140*38e8c45fSAndroid Build Coastguard Worker         return NULL;
141*38e8c45fSAndroid Build Coastguard Worker     }
142*38e8c45fSAndroid Build Coastguard Worker     return result;
143*38e8c45fSAndroid Build Coastguard Worker }
144*38e8c45fSAndroid Build Coastguard Worker 
145*38e8c45fSAndroid Build Coastguard Worker 
drawGLObject(GLOBJECT * object)146*38e8c45fSAndroid Build Coastguard Worker static void drawGLObject(GLOBJECT *object)
147*38e8c45fSAndroid Build Coastguard Worker {
148*38e8c45fSAndroid Build Coastguard Worker     assert(object != NULL);
149*38e8c45fSAndroid Build Coastguard Worker 
150*38e8c45fSAndroid Build Coastguard Worker     glVertexPointer(object->vertexComponents, GL_FIXED,
151*38e8c45fSAndroid Build Coastguard Worker                     0, object->vertexArray);
152*38e8c45fSAndroid Build Coastguard Worker     glColorPointer(4, GL_UNSIGNED_BYTE, 0, object->colorArray);
153*38e8c45fSAndroid Build Coastguard Worker 
154*38e8c45fSAndroid Build Coastguard Worker     // Already done in initialization:
155*38e8c45fSAndroid Build Coastguard Worker     //glEnableClientState(GL_VERTEX_ARRAY);
156*38e8c45fSAndroid Build Coastguard Worker     //glEnableClientState(GL_COLOR_ARRAY);
157*38e8c45fSAndroid Build Coastguard Worker 
158*38e8c45fSAndroid Build Coastguard Worker     if (object->normalArray)
159*38e8c45fSAndroid Build Coastguard Worker     {
160*38e8c45fSAndroid Build Coastguard Worker         glNormalPointer(GL_FIXED, 0, object->normalArray);
161*38e8c45fSAndroid Build Coastguard Worker         glEnableClientState(GL_NORMAL_ARRAY);
162*38e8c45fSAndroid Build Coastguard Worker     }
163*38e8c45fSAndroid Build Coastguard Worker     else
164*38e8c45fSAndroid Build Coastguard Worker         glDisableClientState(GL_NORMAL_ARRAY);
165*38e8c45fSAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, object->count);
166*38e8c45fSAndroid Build Coastguard Worker }
167*38e8c45fSAndroid Build Coastguard Worker 
168*38e8c45fSAndroid Build Coastguard Worker 
vector3Sub(VECTOR3 * dest,VECTOR3 * v1,VECTOR3 * v2)169*38e8c45fSAndroid Build Coastguard Worker static void vector3Sub(VECTOR3 *dest, VECTOR3 *v1, VECTOR3 *v2)
170*38e8c45fSAndroid Build Coastguard Worker {
171*38e8c45fSAndroid Build Coastguard Worker     dest->x = v1->x - v2->x;
172*38e8c45fSAndroid Build Coastguard Worker     dest->y = v1->y - v2->y;
173*38e8c45fSAndroid Build Coastguard Worker     dest->z = v1->z - v2->z;
174*38e8c45fSAndroid Build Coastguard Worker }
175*38e8c45fSAndroid Build Coastguard Worker 
176*38e8c45fSAndroid Build Coastguard Worker 
superShapeMap(VECTOR3 * point,float r1,float r2,float t,float p)177*38e8c45fSAndroid Build Coastguard Worker static void superShapeMap(VECTOR3 *point, float r1, float r2, float t, float p)
178*38e8c45fSAndroid Build Coastguard Worker {
179*38e8c45fSAndroid Build Coastguard Worker     // sphere-mapping of supershape parameters
180*38e8c45fSAndroid Build Coastguard Worker     point->x = (float)(cos(t) * cos(p) / r1 / r2);
181*38e8c45fSAndroid Build Coastguard Worker     point->y = (float)(sin(t) * cos(p) / r1 / r2);
182*38e8c45fSAndroid Build Coastguard Worker     point->z = (float)(sin(p) / r2);
183*38e8c45fSAndroid Build Coastguard Worker }
184*38e8c45fSAndroid Build Coastguard Worker 
185*38e8c45fSAndroid Build Coastguard Worker 
ssFunc(const float t,const float * p)186*38e8c45fSAndroid Build Coastguard Worker static float ssFunc(const float t, const float *p)
187*38e8c45fSAndroid Build Coastguard Worker {
188*38e8c45fSAndroid Build Coastguard Worker     return (float)(pow(pow(fabs(cos(p[0] * t / 4)) / p[1], p[4]) +
189*38e8c45fSAndroid Build Coastguard Worker                        pow(fabs(sin(p[0] * t / 4)) / p[2], p[5]), 1 / p[3]));
190*38e8c45fSAndroid Build Coastguard Worker }
191*38e8c45fSAndroid Build Coastguard Worker 
192*38e8c45fSAndroid Build Coastguard Worker 
193*38e8c45fSAndroid Build Coastguard Worker // Creates and returns a supershape object.
194*38e8c45fSAndroid Build Coastguard Worker // Based on Paul Bourke's POV-Ray implementation.
195*38e8c45fSAndroid Build Coastguard Worker // http://astronomy.swin.edu.au/~pbourke/povray/supershape/
createSuperShape(const float * params)196*38e8c45fSAndroid Build Coastguard Worker static GLOBJECT * createSuperShape(const float *params)
197*38e8c45fSAndroid Build Coastguard Worker {
198*38e8c45fSAndroid Build Coastguard Worker     const int resol1 = (int)params[SUPERSHAPE_PARAMS - 3];
199*38e8c45fSAndroid Build Coastguard Worker     const int resol2 = (int)params[SUPERSHAPE_PARAMS - 2];
200*38e8c45fSAndroid Build Coastguard Worker     // latitude 0 to pi/2 for no mirrored bottom
201*38e8c45fSAndroid Build Coastguard Worker     // (latitudeBegin==0 for -pi/2 to pi/2 originally)
202*38e8c45fSAndroid Build Coastguard Worker     const int latitudeBegin = resol2 / 4;
203*38e8c45fSAndroid Build Coastguard Worker     const int latitudeEnd = resol2 / 2;    // non-inclusive
204*38e8c45fSAndroid Build Coastguard Worker     const int longitudeCount = resol1;
205*38e8c45fSAndroid Build Coastguard Worker     const int latitudeCount = latitudeEnd - latitudeBegin;
206*38e8c45fSAndroid Build Coastguard Worker     const long triangleCount = longitudeCount * latitudeCount * 2;
207*38e8c45fSAndroid Build Coastguard Worker     const long vertices = triangleCount * 3;
208*38e8c45fSAndroid Build Coastguard Worker     GLOBJECT *result;
209*38e8c45fSAndroid Build Coastguard Worker     float baseColor[3];
210*38e8c45fSAndroid Build Coastguard Worker     int a, longitude, latitude;
211*38e8c45fSAndroid Build Coastguard Worker     long currentVertex, currentQuad;
212*38e8c45fSAndroid Build Coastguard Worker 
213*38e8c45fSAndroid Build Coastguard Worker     result = newGLObject(vertices, 3, 1);
214*38e8c45fSAndroid Build Coastguard Worker     if (result == NULL)
215*38e8c45fSAndroid Build Coastguard Worker         return NULL;
216*38e8c45fSAndroid Build Coastguard Worker 
217*38e8c45fSAndroid Build Coastguard Worker     for (a = 0; a < 3; ++a)
218*38e8c45fSAndroid Build Coastguard Worker         baseColor[a] = ((randomUInt() % 155) + 100) / 255.f;
219*38e8c45fSAndroid Build Coastguard Worker 
220*38e8c45fSAndroid Build Coastguard Worker     currentQuad = 0;
221*38e8c45fSAndroid Build Coastguard Worker     currentVertex = 0;
222*38e8c45fSAndroid Build Coastguard Worker 
223*38e8c45fSAndroid Build Coastguard Worker     // longitude -pi to pi
224*38e8c45fSAndroid Build Coastguard Worker     for (longitude = 0; longitude < longitudeCount; ++longitude)
225*38e8c45fSAndroid Build Coastguard Worker     {
226*38e8c45fSAndroid Build Coastguard Worker 
227*38e8c45fSAndroid Build Coastguard Worker         // latitude 0 to pi/2
228*38e8c45fSAndroid Build Coastguard Worker         for (latitude = latitudeBegin; latitude < latitudeEnd; ++latitude)
229*38e8c45fSAndroid Build Coastguard Worker         {
230*38e8c45fSAndroid Build Coastguard Worker             float t1 = -PI + longitude * 2 * PI / resol1;
231*38e8c45fSAndroid Build Coastguard Worker             float t2 = -PI + (longitude + 1) * 2 * PI / resol1;
232*38e8c45fSAndroid Build Coastguard Worker             float p1 = -PI / 2 + latitude * 2 * PI / resol2;
233*38e8c45fSAndroid Build Coastguard Worker             float p2 = -PI / 2 + (latitude + 1) * 2 * PI / resol2;
234*38e8c45fSAndroid Build Coastguard Worker             float r0, r1, r2, r3;
235*38e8c45fSAndroid Build Coastguard Worker 
236*38e8c45fSAndroid Build Coastguard Worker             r0 = ssFunc(t1, params);
237*38e8c45fSAndroid Build Coastguard Worker             r1 = ssFunc(p1, &params[6]);
238*38e8c45fSAndroid Build Coastguard Worker             r2 = ssFunc(t2, params);
239*38e8c45fSAndroid Build Coastguard Worker             r3 = ssFunc(p2, &params[6]);
240*38e8c45fSAndroid Build Coastguard Worker 
241*38e8c45fSAndroid Build Coastguard Worker             if (r0 != 0 && r1 != 0 && r2 != 0 && r3 != 0)
242*38e8c45fSAndroid Build Coastguard Worker             {
243*38e8c45fSAndroid Build Coastguard Worker                 VECTOR3 pa, pb, pc, pd;
244*38e8c45fSAndroid Build Coastguard Worker                 VECTOR3 v1, v2, n;
245*38e8c45fSAndroid Build Coastguard Worker                 float ca;
246*38e8c45fSAndroid Build Coastguard Worker                 int i;
247*38e8c45fSAndroid Build Coastguard Worker                 //float lenSq, invLenSq;
248*38e8c45fSAndroid Build Coastguard Worker 
249*38e8c45fSAndroid Build Coastguard Worker                 superShapeMap(&pa, r0, r1, t1, p1);
250*38e8c45fSAndroid Build Coastguard Worker                 superShapeMap(&pb, r2, r1, t2, p1);
251*38e8c45fSAndroid Build Coastguard Worker                 superShapeMap(&pc, r2, r3, t2, p2);
252*38e8c45fSAndroid Build Coastguard Worker                 superShapeMap(&pd, r0, r3, t1, p2);
253*38e8c45fSAndroid Build Coastguard Worker 
254*38e8c45fSAndroid Build Coastguard Worker                 // kludge to set lower edge of the object to fixed level
255*38e8c45fSAndroid Build Coastguard Worker                 if (latitude == latitudeBegin + 1)
256*38e8c45fSAndroid Build Coastguard Worker                     pa.z = pb.z = 0;
257*38e8c45fSAndroid Build Coastguard Worker 
258*38e8c45fSAndroid Build Coastguard Worker                 vector3Sub(&v1, &pb, &pa);
259*38e8c45fSAndroid Build Coastguard Worker                 vector3Sub(&v2, &pd, &pa);
260*38e8c45fSAndroid Build Coastguard Worker 
261*38e8c45fSAndroid Build Coastguard Worker                 // Calculate normal with cross product.
262*38e8c45fSAndroid Build Coastguard Worker                 /*   i    j    k      i    j
263*38e8c45fSAndroid Build Coastguard Worker                  * v1.x v1.y v1.z | v1.x v1.y
264*38e8c45fSAndroid Build Coastguard Worker                  * v2.x v2.y v2.z | v2.x v2.y
265*38e8c45fSAndroid Build Coastguard Worker                  */
266*38e8c45fSAndroid Build Coastguard Worker 
267*38e8c45fSAndroid Build Coastguard Worker                 n.x = v1.y * v2.z - v1.z * v2.y;
268*38e8c45fSAndroid Build Coastguard Worker                 n.y = v1.z * v2.x - v1.x * v2.z;
269*38e8c45fSAndroid Build Coastguard Worker                 n.z = v1.x * v2.y - v1.y * v2.x;
270*38e8c45fSAndroid Build Coastguard Worker 
271*38e8c45fSAndroid Build Coastguard Worker                 /* Pre-normalization of the normals is disabled here because
272*38e8c45fSAndroid Build Coastguard Worker                  * they will be normalized anyway later due to automatic
273*38e8c45fSAndroid Build Coastguard Worker                  * normalization (GL_NORMALIZE). It is enabled because the
274*38e8c45fSAndroid Build Coastguard Worker                  * objects are scaled with glScale.
275*38e8c45fSAndroid Build Coastguard Worker                  */
276*38e8c45fSAndroid Build Coastguard Worker                 /*
277*38e8c45fSAndroid Build Coastguard Worker                 lenSq = n.x * n.x + n.y * n.y + n.z * n.z;
278*38e8c45fSAndroid Build Coastguard Worker                 invLenSq = (float)(1 / sqrt(lenSq));
279*38e8c45fSAndroid Build Coastguard Worker                 n.x *= invLenSq;
280*38e8c45fSAndroid Build Coastguard Worker                 n.y *= invLenSq;
281*38e8c45fSAndroid Build Coastguard Worker                 n.z *= invLenSq;
282*38e8c45fSAndroid Build Coastguard Worker                 */
283*38e8c45fSAndroid Build Coastguard Worker 
284*38e8c45fSAndroid Build Coastguard Worker                 ca = pa.z + 0.5f;
285*38e8c45fSAndroid Build Coastguard Worker 
286*38e8c45fSAndroid Build Coastguard Worker                 for (i = currentVertex * 3;
287*38e8c45fSAndroid Build Coastguard Worker                      i < (currentVertex + 6) * 3;
288*38e8c45fSAndroid Build Coastguard Worker                      i += 3)
289*38e8c45fSAndroid Build Coastguard Worker                 {
290*38e8c45fSAndroid Build Coastguard Worker                     result->normalArray[i] = FIXED(n.x);
291*38e8c45fSAndroid Build Coastguard Worker                     result->normalArray[i + 1] = FIXED(n.y);
292*38e8c45fSAndroid Build Coastguard Worker                     result->normalArray[i + 2] = FIXED(n.z);
293*38e8c45fSAndroid Build Coastguard Worker                 }
294*38e8c45fSAndroid Build Coastguard Worker                 for (i = currentVertex * 4;
295*38e8c45fSAndroid Build Coastguard Worker                      i < (currentVertex + 6) * 4;
296*38e8c45fSAndroid Build Coastguard Worker                      i += 4)
297*38e8c45fSAndroid Build Coastguard Worker                 {
298*38e8c45fSAndroid Build Coastguard Worker                     int a, color[3];
299*38e8c45fSAndroid Build Coastguard Worker                     for (a = 0; a < 3; ++a)
300*38e8c45fSAndroid Build Coastguard Worker                     {
301*38e8c45fSAndroid Build Coastguard Worker                         color[a] = (int)(ca * baseColor[a] * 255);
302*38e8c45fSAndroid Build Coastguard Worker                         if (color[a] > 255) color[a] = 255;
303*38e8c45fSAndroid Build Coastguard Worker                     }
304*38e8c45fSAndroid Build Coastguard Worker                     result->colorArray[i] = (GLubyte)color[0];
305*38e8c45fSAndroid Build Coastguard Worker                     result->colorArray[i + 1] = (GLubyte)color[1];
306*38e8c45fSAndroid Build Coastguard Worker                     result->colorArray[i + 2] = (GLubyte)color[2];
307*38e8c45fSAndroid Build Coastguard Worker                     result->colorArray[i + 3] = 0;
308*38e8c45fSAndroid Build Coastguard Worker                 }
309*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3] = FIXED(pa.x);
310*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 1] = FIXED(pa.y);
311*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 2] = FIXED(pa.z);
312*38e8c45fSAndroid Build Coastguard Worker                 ++currentVertex;
313*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3] = FIXED(pb.x);
314*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 1] = FIXED(pb.y);
315*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 2] = FIXED(pb.z);
316*38e8c45fSAndroid Build Coastguard Worker                 ++currentVertex;
317*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3] = FIXED(pd.x);
318*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 1] = FIXED(pd.y);
319*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 2] = FIXED(pd.z);
320*38e8c45fSAndroid Build Coastguard Worker                 ++currentVertex;
321*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3] = FIXED(pb.x);
322*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 1] = FIXED(pb.y);
323*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 2] = FIXED(pb.z);
324*38e8c45fSAndroid Build Coastguard Worker                 ++currentVertex;
325*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3] = FIXED(pc.x);
326*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 1] = FIXED(pc.y);
327*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 2] = FIXED(pc.z);
328*38e8c45fSAndroid Build Coastguard Worker                 ++currentVertex;
329*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3] = FIXED(pd.x);
330*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 1] = FIXED(pd.y);
331*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 3 + 2] = FIXED(pd.z);
332*38e8c45fSAndroid Build Coastguard Worker                 ++currentVertex;
333*38e8c45fSAndroid Build Coastguard Worker             } // r0 && r1 && r2 && r3
334*38e8c45fSAndroid Build Coastguard Worker             ++currentQuad;
335*38e8c45fSAndroid Build Coastguard Worker         } // latitude
336*38e8c45fSAndroid Build Coastguard Worker     } // longitude
337*38e8c45fSAndroid Build Coastguard Worker 
338*38e8c45fSAndroid Build Coastguard Worker     // Set number of vertices in object to the actual amount created.
339*38e8c45fSAndroid Build Coastguard Worker     result->count = currentVertex;
340*38e8c45fSAndroid Build Coastguard Worker 
341*38e8c45fSAndroid Build Coastguard Worker     return result;
342*38e8c45fSAndroid Build Coastguard Worker }
343*38e8c45fSAndroid Build Coastguard Worker 
344*38e8c45fSAndroid Build Coastguard Worker 
createGroundPlane()345*38e8c45fSAndroid Build Coastguard Worker static GLOBJECT * createGroundPlane()
346*38e8c45fSAndroid Build Coastguard Worker {
347*38e8c45fSAndroid Build Coastguard Worker     const int scale = 4;
348*38e8c45fSAndroid Build Coastguard Worker     const int yBegin = -15, yEnd = 15;    // ends are non-inclusive
349*38e8c45fSAndroid Build Coastguard Worker     const int xBegin = -15, xEnd = 15;
350*38e8c45fSAndroid Build Coastguard Worker     const long triangleCount = (yEnd - yBegin) * (xEnd - xBegin) * 2;
351*38e8c45fSAndroid Build Coastguard Worker     const long vertices = triangleCount * 3;
352*38e8c45fSAndroid Build Coastguard Worker     GLOBJECT *result;
353*38e8c45fSAndroid Build Coastguard Worker     int x, y;
354*38e8c45fSAndroid Build Coastguard Worker     long currentVertex, currentQuad;
355*38e8c45fSAndroid Build Coastguard Worker 
356*38e8c45fSAndroid Build Coastguard Worker     result = newGLObject(vertices, 2, 0);
357*38e8c45fSAndroid Build Coastguard Worker     if (result == NULL)
358*38e8c45fSAndroid Build Coastguard Worker         return NULL;
359*38e8c45fSAndroid Build Coastguard Worker 
360*38e8c45fSAndroid Build Coastguard Worker     currentQuad = 0;
361*38e8c45fSAndroid Build Coastguard Worker     currentVertex = 0;
362*38e8c45fSAndroid Build Coastguard Worker 
363*38e8c45fSAndroid Build Coastguard Worker     for (y = yBegin; y < yEnd; ++y)
364*38e8c45fSAndroid Build Coastguard Worker     {
365*38e8c45fSAndroid Build Coastguard Worker         for (x = xBegin; x < xEnd; ++x)
366*38e8c45fSAndroid Build Coastguard Worker         {
367*38e8c45fSAndroid Build Coastguard Worker             GLubyte color;
368*38e8c45fSAndroid Build Coastguard Worker             int i, a;
369*38e8c45fSAndroid Build Coastguard Worker             color = (GLubyte)((randomUInt() & 0x5f) + 81);  // 101 1111
370*38e8c45fSAndroid Build Coastguard Worker             for (i = currentVertex * 4; i < (currentVertex + 6) * 4; i += 4)
371*38e8c45fSAndroid Build Coastguard Worker             {
372*38e8c45fSAndroid Build Coastguard Worker                 result->colorArray[i] = color;
373*38e8c45fSAndroid Build Coastguard Worker                 result->colorArray[i + 1] = color;
374*38e8c45fSAndroid Build Coastguard Worker                 result->colorArray[i + 2] = color;
375*38e8c45fSAndroid Build Coastguard Worker                 result->colorArray[i + 3] = 0;
376*38e8c45fSAndroid Build Coastguard Worker             }
377*38e8c45fSAndroid Build Coastguard Worker 
378*38e8c45fSAndroid Build Coastguard Worker             // Axis bits for quad triangles:
379*38e8c45fSAndroid Build Coastguard Worker             // x: 011100 (0x1c), y: 110001 (0x31)  (clockwise)
380*38e8c45fSAndroid Build Coastguard Worker             // x: 001110 (0x0e), y: 100011 (0x23)  (counter-clockwise)
381*38e8c45fSAndroid Build Coastguard Worker             for (a = 0; a < 6; ++a)
382*38e8c45fSAndroid Build Coastguard Worker             {
383*38e8c45fSAndroid Build Coastguard Worker                 const int xm = x + ((0x1c >> a) & 1);
384*38e8c45fSAndroid Build Coastguard Worker                 const int ym = y + ((0x31 >> a) & 1);
385*38e8c45fSAndroid Build Coastguard Worker                 const float m = (float)(cos(xm * 2) * sin(ym * 4) * 0.75f);
386*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 2] =
387*38e8c45fSAndroid Build Coastguard Worker                     FIXED(xm * scale + m);
388*38e8c45fSAndroid Build Coastguard Worker                 result->vertexArray[currentVertex * 2 + 1] =
389*38e8c45fSAndroid Build Coastguard Worker                     FIXED(ym * scale + m);
390*38e8c45fSAndroid Build Coastguard Worker                 ++currentVertex;
391*38e8c45fSAndroid Build Coastguard Worker             }
392*38e8c45fSAndroid Build Coastguard Worker             ++currentQuad;
393*38e8c45fSAndroid Build Coastguard Worker         }
394*38e8c45fSAndroid Build Coastguard Worker     }
395*38e8c45fSAndroid Build Coastguard Worker     return result;
396*38e8c45fSAndroid Build Coastguard Worker }
397*38e8c45fSAndroid Build Coastguard Worker 
398*38e8c45fSAndroid Build Coastguard Worker 
drawGroundPlane()399*38e8c45fSAndroid Build Coastguard Worker static void drawGroundPlane()
400*38e8c45fSAndroid Build Coastguard Worker {
401*38e8c45fSAndroid Build Coastguard Worker     glDisable(GL_CULL_FACE);
402*38e8c45fSAndroid Build Coastguard Worker     glDisable(GL_DEPTH_TEST);
403*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_BLEND);
404*38e8c45fSAndroid Build Coastguard Worker     glBlendFunc(GL_ZERO, GL_SRC_COLOR);
405*38e8c45fSAndroid Build Coastguard Worker     glDisable(GL_LIGHTING);
406*38e8c45fSAndroid Build Coastguard Worker 
407*38e8c45fSAndroid Build Coastguard Worker     drawGLObject(sGroundPlane);
408*38e8c45fSAndroid Build Coastguard Worker 
409*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_LIGHTING);
410*38e8c45fSAndroid Build Coastguard Worker     glDisable(GL_BLEND);
411*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_DEPTH_TEST);
412*38e8c45fSAndroid Build Coastguard Worker }
413*38e8c45fSAndroid Build Coastguard Worker 
414*38e8c45fSAndroid Build Coastguard Worker 
drawFadeQuad()415*38e8c45fSAndroid Build Coastguard Worker static void drawFadeQuad()
416*38e8c45fSAndroid Build Coastguard Worker {
417*38e8c45fSAndroid Build Coastguard Worker     static const GLfixed quadVertices[] = {
418*38e8c45fSAndroid Build Coastguard Worker         -0x10000, -0x10000,
419*38e8c45fSAndroid Build Coastguard Worker          0x10000, -0x10000,
420*38e8c45fSAndroid Build Coastguard Worker         -0x10000,  0x10000,
421*38e8c45fSAndroid Build Coastguard Worker          0x10000, -0x10000,
422*38e8c45fSAndroid Build Coastguard Worker          0x10000,  0x10000,
423*38e8c45fSAndroid Build Coastguard Worker         -0x10000,  0x10000
424*38e8c45fSAndroid Build Coastguard Worker     };
425*38e8c45fSAndroid Build Coastguard Worker 
426*38e8c45fSAndroid Build Coastguard Worker     const int beginFade = sTick - sCurrentCamTrackStartTick;
427*38e8c45fSAndroid Build Coastguard Worker     const int endFade = sNextCamTrackStartTick - sTick;
428*38e8c45fSAndroid Build Coastguard Worker     const int minFade = beginFade < endFade ? beginFade : endFade;
429*38e8c45fSAndroid Build Coastguard Worker 
430*38e8c45fSAndroid Build Coastguard Worker     if (minFade < 1024)
431*38e8c45fSAndroid Build Coastguard Worker     {
432*38e8c45fSAndroid Build Coastguard Worker         const GLfixed fadeColor = minFade << 6;
433*38e8c45fSAndroid Build Coastguard Worker         glColor4x(fadeColor, fadeColor, fadeColor, 0);
434*38e8c45fSAndroid Build Coastguard Worker 
435*38e8c45fSAndroid Build Coastguard Worker         glDisable(GL_DEPTH_TEST);
436*38e8c45fSAndroid Build Coastguard Worker         glEnable(GL_BLEND);
437*38e8c45fSAndroid Build Coastguard Worker         glBlendFunc(GL_ZERO, GL_SRC_COLOR);
438*38e8c45fSAndroid Build Coastguard Worker         glDisable(GL_LIGHTING);
439*38e8c45fSAndroid Build Coastguard Worker 
440*38e8c45fSAndroid Build Coastguard Worker         glMatrixMode(GL_MODELVIEW);
441*38e8c45fSAndroid Build Coastguard Worker         glLoadIdentity();
442*38e8c45fSAndroid Build Coastguard Worker 
443*38e8c45fSAndroid Build Coastguard Worker         glMatrixMode(GL_PROJECTION);
444*38e8c45fSAndroid Build Coastguard Worker         glLoadIdentity();
445*38e8c45fSAndroid Build Coastguard Worker 
446*38e8c45fSAndroid Build Coastguard Worker         glDisableClientState(GL_COLOR_ARRAY);
447*38e8c45fSAndroid Build Coastguard Worker         glDisableClientState(GL_NORMAL_ARRAY);
448*38e8c45fSAndroid Build Coastguard Worker         glVertexPointer(2, GL_FIXED, 0, quadVertices);
449*38e8c45fSAndroid Build Coastguard Worker         glDrawArrays(GL_TRIANGLES, 0, 6);
450*38e8c45fSAndroid Build Coastguard Worker 
451*38e8c45fSAndroid Build Coastguard Worker         glEnableClientState(GL_COLOR_ARRAY);
452*38e8c45fSAndroid Build Coastguard Worker 
453*38e8c45fSAndroid Build Coastguard Worker         glMatrixMode(GL_MODELVIEW);
454*38e8c45fSAndroid Build Coastguard Worker 
455*38e8c45fSAndroid Build Coastguard Worker         glEnable(GL_LIGHTING);
456*38e8c45fSAndroid Build Coastguard Worker         glDisable(GL_BLEND);
457*38e8c45fSAndroid Build Coastguard Worker         glEnable(GL_DEPTH_TEST);
458*38e8c45fSAndroid Build Coastguard Worker     }
459*38e8c45fSAndroid Build Coastguard Worker }
460*38e8c45fSAndroid Build Coastguard Worker 
461*38e8c45fSAndroid Build Coastguard Worker 
462*38e8c45fSAndroid Build Coastguard Worker // Called from the app framework.
appInit()463*38e8c45fSAndroid Build Coastguard Worker void appInit()
464*38e8c45fSAndroid Build Coastguard Worker {
465*38e8c45fSAndroid Build Coastguard Worker     unsigned int a;
466*38e8c45fSAndroid Build Coastguard Worker 
467*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_NORMALIZE);
468*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_DEPTH_TEST);
469*38e8c45fSAndroid Build Coastguard Worker     glDisable(GL_CULL_FACE);
470*38e8c45fSAndroid Build Coastguard Worker     glShadeModel(GL_FLAT);
471*38e8c45fSAndroid Build Coastguard Worker 
472*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_LIGHTING);
473*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_LIGHT0);
474*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_LIGHT1);
475*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_LIGHT2);
476*38e8c45fSAndroid Build Coastguard Worker 
477*38e8c45fSAndroid Build Coastguard Worker     glEnableClientState(GL_VERTEX_ARRAY);
478*38e8c45fSAndroid Build Coastguard Worker     glEnableClientState(GL_COLOR_ARRAY);
479*38e8c45fSAndroid Build Coastguard Worker 
480*38e8c45fSAndroid Build Coastguard Worker     seedRandom(15);
481*38e8c45fSAndroid Build Coastguard Worker 
482*38e8c45fSAndroid Build Coastguard Worker     for (a = 0; a < SUPERSHAPE_COUNT; ++a)
483*38e8c45fSAndroid Build Coastguard Worker     {
484*38e8c45fSAndroid Build Coastguard Worker         sSuperShapeObjects[a] = createSuperShape(sSuperShapeParams[a]);
485*38e8c45fSAndroid Build Coastguard Worker         assert(sSuperShapeObjects[a] != NULL);
486*38e8c45fSAndroid Build Coastguard Worker     }
487*38e8c45fSAndroid Build Coastguard Worker     sGroundPlane = createGroundPlane();
488*38e8c45fSAndroid Build Coastguard Worker     assert(sGroundPlane != NULL);
489*38e8c45fSAndroid Build Coastguard Worker }
490*38e8c45fSAndroid Build Coastguard Worker 
491*38e8c45fSAndroid Build Coastguard Worker 
492*38e8c45fSAndroid Build Coastguard Worker // Called from the app framework.
appDeinit()493*38e8c45fSAndroid Build Coastguard Worker void appDeinit()
494*38e8c45fSAndroid Build Coastguard Worker {
495*38e8c45fSAndroid Build Coastguard Worker     unsigned int a;
496*38e8c45fSAndroid Build Coastguard Worker     for (a = 0; a < SUPERSHAPE_COUNT; ++a)
497*38e8c45fSAndroid Build Coastguard Worker         freeGLObject(sSuperShapeObjects[a]);
498*38e8c45fSAndroid Build Coastguard Worker     freeGLObject(sGroundPlane);
499*38e8c45fSAndroid Build Coastguard Worker }
500*38e8c45fSAndroid Build Coastguard Worker 
501*38e8c45fSAndroid Build Coastguard Worker 
gluPerspective(GLfloat fovy,GLfloat aspect,GLfloat zNear,GLfloat zFar)502*38e8c45fSAndroid Build Coastguard Worker static void gluPerspective(GLfloat fovy, GLfloat aspect,
503*38e8c45fSAndroid Build Coastguard Worker                            GLfloat zNear, GLfloat zFar)
504*38e8c45fSAndroid Build Coastguard Worker {
505*38e8c45fSAndroid Build Coastguard Worker     GLfloat xmin, xmax, ymin, ymax;
506*38e8c45fSAndroid Build Coastguard Worker 
507*38e8c45fSAndroid Build Coastguard Worker     ymax = zNear * (GLfloat)tan(fovy * PI / 360);
508*38e8c45fSAndroid Build Coastguard Worker     ymin = -ymax;
509*38e8c45fSAndroid Build Coastguard Worker     xmin = ymin * aspect;
510*38e8c45fSAndroid Build Coastguard Worker     xmax = ymax * aspect;
511*38e8c45fSAndroid Build Coastguard Worker 
512*38e8c45fSAndroid Build Coastguard Worker     glFrustumx((GLfixed)(xmin * 65536), (GLfixed)(xmax * 65536),
513*38e8c45fSAndroid Build Coastguard Worker                (GLfixed)(ymin * 65536), (GLfixed)(ymax * 65536),
514*38e8c45fSAndroid Build Coastguard Worker                (GLfixed)(zNear * 65536), (GLfixed)(zFar * 65536));
515*38e8c45fSAndroid Build Coastguard Worker }
516*38e8c45fSAndroid Build Coastguard Worker 
517*38e8c45fSAndroid Build Coastguard Worker 
prepareFrame(int width,int height)518*38e8c45fSAndroid Build Coastguard Worker static void prepareFrame(int width, int height)
519*38e8c45fSAndroid Build Coastguard Worker {
520*38e8c45fSAndroid Build Coastguard Worker     glViewport(0, 0, width, height);
521*38e8c45fSAndroid Build Coastguard Worker 
522*38e8c45fSAndroid Build Coastguard Worker     glClearColorx((GLfixed)(0.1f * 65536),
523*38e8c45fSAndroid Build Coastguard Worker                   (GLfixed)(0.2f * 65536),
524*38e8c45fSAndroid Build Coastguard Worker                   (GLfixed)(0.3f * 65536), 0x10000);
525*38e8c45fSAndroid Build Coastguard Worker     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
526*38e8c45fSAndroid Build Coastguard Worker 
527*38e8c45fSAndroid Build Coastguard Worker     glMatrixMode(GL_PROJECTION);
528*38e8c45fSAndroid Build Coastguard Worker     glLoadIdentity();
529*38e8c45fSAndroid Build Coastguard Worker     gluPerspective(45, (float)width / height, 0.5f, 150);
530*38e8c45fSAndroid Build Coastguard Worker 
531*38e8c45fSAndroid Build Coastguard Worker     glMatrixMode(GL_MODELVIEW);
532*38e8c45fSAndroid Build Coastguard Worker 
533*38e8c45fSAndroid Build Coastguard Worker     glLoadIdentity();
534*38e8c45fSAndroid Build Coastguard Worker }
535*38e8c45fSAndroid Build Coastguard Worker 
536*38e8c45fSAndroid Build Coastguard Worker 
configureLightAndMaterial()537*38e8c45fSAndroid Build Coastguard Worker static void configureLightAndMaterial()
538*38e8c45fSAndroid Build Coastguard Worker {
539*38e8c45fSAndroid Build Coastguard Worker     static GLfixed light0Position[] = { -0x40000, 0x10000, 0x10000, 0 };
540*38e8c45fSAndroid Build Coastguard Worker     static GLfixed light0Diffuse[] = { 0x10000, 0x6666, 0, 0x10000 };
541*38e8c45fSAndroid Build Coastguard Worker     static GLfixed light1Position[] = { 0x10000, -0x20000, -0x10000, 0 };
542*38e8c45fSAndroid Build Coastguard Worker     static GLfixed light1Diffuse[] = { 0x11eb, 0x23d7, 0x5999, 0x10000 };
543*38e8c45fSAndroid Build Coastguard Worker     static GLfixed light2Position[] = { -0x10000, 0, -0x40000, 0 };
544*38e8c45fSAndroid Build Coastguard Worker     static GLfixed light2Diffuse[] = { 0x11eb, 0x2b85, 0x23d7, 0x10000 };
545*38e8c45fSAndroid Build Coastguard Worker     static GLfixed materialSpecular[] = { 0x10000, 0x10000, 0x10000, 0x10000 };
546*38e8c45fSAndroid Build Coastguard Worker 
547*38e8c45fSAndroid Build Coastguard Worker     glLightxv(GL_LIGHT0, GL_POSITION, light0Position);
548*38e8c45fSAndroid Build Coastguard Worker     glLightxv(GL_LIGHT0, GL_DIFFUSE, light0Diffuse);
549*38e8c45fSAndroid Build Coastguard Worker     glLightxv(GL_LIGHT1, GL_POSITION, light1Position);
550*38e8c45fSAndroid Build Coastguard Worker     glLightxv(GL_LIGHT1, GL_DIFFUSE, light1Diffuse);
551*38e8c45fSAndroid Build Coastguard Worker     glLightxv(GL_LIGHT2, GL_POSITION, light2Position);
552*38e8c45fSAndroid Build Coastguard Worker     glLightxv(GL_LIGHT2, GL_DIFFUSE, light2Diffuse);
553*38e8c45fSAndroid Build Coastguard Worker     glMaterialxv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecular);
554*38e8c45fSAndroid Build Coastguard Worker 
555*38e8c45fSAndroid Build Coastguard Worker     glMaterialx(GL_FRONT_AND_BACK, GL_SHININESS, 60 << 16);
556*38e8c45fSAndroid Build Coastguard Worker     glEnable(GL_COLOR_MATERIAL);
557*38e8c45fSAndroid Build Coastguard Worker }
558*38e8c45fSAndroid Build Coastguard Worker 
559*38e8c45fSAndroid Build Coastguard Worker 
drawModels(float zScale)560*38e8c45fSAndroid Build Coastguard Worker static void drawModels(float zScale)
561*38e8c45fSAndroid Build Coastguard Worker {
562*38e8c45fSAndroid Build Coastguard Worker     const int translationScale = 9;
563*38e8c45fSAndroid Build Coastguard Worker     int x, y;
564*38e8c45fSAndroid Build Coastguard Worker 
565*38e8c45fSAndroid Build Coastguard Worker     seedRandom(9);
566*38e8c45fSAndroid Build Coastguard Worker 
567*38e8c45fSAndroid Build Coastguard Worker     glScalex(1 << 16, 1 << 16, (GLfixed)(zScale * 65536));
568*38e8c45fSAndroid Build Coastguard Worker 
569*38e8c45fSAndroid Build Coastguard Worker     for (y = -5; y <= 5; ++y)
570*38e8c45fSAndroid Build Coastguard Worker     {
571*38e8c45fSAndroid Build Coastguard Worker         for (x = -5; x <= 5; ++x)
572*38e8c45fSAndroid Build Coastguard Worker         {
573*38e8c45fSAndroid Build Coastguard Worker             float buildingScale;
574*38e8c45fSAndroid Build Coastguard Worker             GLfixed fixedScale;
575*38e8c45fSAndroid Build Coastguard Worker 
576*38e8c45fSAndroid Build Coastguard Worker             int curShape = randomUInt() % SUPERSHAPE_COUNT;
577*38e8c45fSAndroid Build Coastguard Worker             buildingScale = sSuperShapeParams[curShape][SUPERSHAPE_PARAMS - 1];
578*38e8c45fSAndroid Build Coastguard Worker             fixedScale = (GLfixed)(buildingScale * 65536);
579*38e8c45fSAndroid Build Coastguard Worker 
580*38e8c45fSAndroid Build Coastguard Worker             glPushMatrix();
581*38e8c45fSAndroid Build Coastguard Worker             glTranslatex((x * translationScale) * 65536,
582*38e8c45fSAndroid Build Coastguard Worker                          (y * translationScale) * 65536,
583*38e8c45fSAndroid Build Coastguard Worker                          0);
584*38e8c45fSAndroid Build Coastguard Worker             glRotatex((GLfixed)((randomUInt() % 360) << 16), 0, 0, 1 << 16);
585*38e8c45fSAndroid Build Coastguard Worker             glScalex(fixedScale, fixedScale, fixedScale);
586*38e8c45fSAndroid Build Coastguard Worker 
587*38e8c45fSAndroid Build Coastguard Worker             drawGLObject(sSuperShapeObjects[curShape]);
588*38e8c45fSAndroid Build Coastguard Worker             glPopMatrix();
589*38e8c45fSAndroid Build Coastguard Worker         }
590*38e8c45fSAndroid Build Coastguard Worker     }
591*38e8c45fSAndroid Build Coastguard Worker 
592*38e8c45fSAndroid Build Coastguard Worker     for (x = -2; x <= 2; ++x)
593*38e8c45fSAndroid Build Coastguard Worker     {
594*38e8c45fSAndroid Build Coastguard Worker         const int shipScale100 = translationScale * 500;
595*38e8c45fSAndroid Build Coastguard Worker         const int offs100 = x * shipScale100 + (sTick % shipScale100);
596*38e8c45fSAndroid Build Coastguard Worker         float offs = offs100 * 0.01f;
597*38e8c45fSAndroid Build Coastguard Worker         GLfixed fixedOffs = (GLfixed)(offs * 65536);
598*38e8c45fSAndroid Build Coastguard Worker         glPushMatrix();
599*38e8c45fSAndroid Build Coastguard Worker         glTranslatex(fixedOffs, -4 * 65536, 2 << 16);
600*38e8c45fSAndroid Build Coastguard Worker         drawGLObject(sSuperShapeObjects[SUPERSHAPE_COUNT - 1]);
601*38e8c45fSAndroid Build Coastguard Worker         glPopMatrix();
602*38e8c45fSAndroid Build Coastguard Worker         glPushMatrix();
603*38e8c45fSAndroid Build Coastguard Worker         glTranslatex(-4 * 65536, fixedOffs, 4 << 16);
604*38e8c45fSAndroid Build Coastguard Worker         glRotatex(90 << 16, 0, 0, 1 << 16);
605*38e8c45fSAndroid Build Coastguard Worker         drawGLObject(sSuperShapeObjects[SUPERSHAPE_COUNT - 1]);
606*38e8c45fSAndroid Build Coastguard Worker         glPopMatrix();
607*38e8c45fSAndroid Build Coastguard Worker     }
608*38e8c45fSAndroid Build Coastguard Worker }
609*38e8c45fSAndroid Build Coastguard Worker 
610*38e8c45fSAndroid Build Coastguard Worker 
611*38e8c45fSAndroid Build Coastguard Worker /* Following gluLookAt implementation is adapted from the
612*38e8c45fSAndroid Build Coastguard Worker  * Mesa 3D Graphics library. http://www.mesa3d.org
613*38e8c45fSAndroid Build Coastguard Worker  */
gluLookAt(GLfloat eyex,GLfloat eyey,GLfloat eyez,GLfloat centerx,GLfloat centery,GLfloat centerz,GLfloat upx,GLfloat upy,GLfloat upz)614*38e8c45fSAndroid Build Coastguard Worker static void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
615*38e8c45fSAndroid Build Coastguard Worker 	              GLfloat centerx, GLfloat centery, GLfloat centerz,
616*38e8c45fSAndroid Build Coastguard Worker 	              GLfloat upx, GLfloat upy, GLfloat upz)
617*38e8c45fSAndroid Build Coastguard Worker {
618*38e8c45fSAndroid Build Coastguard Worker     GLfloat m[16];
619*38e8c45fSAndroid Build Coastguard Worker     GLfloat x[3], y[3], z[3];
620*38e8c45fSAndroid Build Coastguard Worker     GLfloat mag;
621*38e8c45fSAndroid Build Coastguard Worker 
622*38e8c45fSAndroid Build Coastguard Worker     /* Make rotation matrix */
623*38e8c45fSAndroid Build Coastguard Worker 
624*38e8c45fSAndroid Build Coastguard Worker     /* Z vector */
625*38e8c45fSAndroid Build Coastguard Worker     z[0] = eyex - centerx;
626*38e8c45fSAndroid Build Coastguard Worker     z[1] = eyey - centery;
627*38e8c45fSAndroid Build Coastguard Worker     z[2] = eyez - centerz;
628*38e8c45fSAndroid Build Coastguard Worker     mag = (float)sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
629*38e8c45fSAndroid Build Coastguard Worker     if (mag) {			/* mpichler, 19950515 */
630*38e8c45fSAndroid Build Coastguard Worker         z[0] /= mag;
631*38e8c45fSAndroid Build Coastguard Worker         z[1] /= mag;
632*38e8c45fSAndroid Build Coastguard Worker         z[2] /= mag;
633*38e8c45fSAndroid Build Coastguard Worker     }
634*38e8c45fSAndroid Build Coastguard Worker 
635*38e8c45fSAndroid Build Coastguard Worker     /* Y vector */
636*38e8c45fSAndroid Build Coastguard Worker     y[0] = upx;
637*38e8c45fSAndroid Build Coastguard Worker     y[1] = upy;
638*38e8c45fSAndroid Build Coastguard Worker     y[2] = upz;
639*38e8c45fSAndroid Build Coastguard Worker 
640*38e8c45fSAndroid Build Coastguard Worker     /* X vector = Y cross Z */
641*38e8c45fSAndroid Build Coastguard Worker     x[0] = y[1] * z[2] - y[2] * z[1];
642*38e8c45fSAndroid Build Coastguard Worker     x[1] = -y[0] * z[2] + y[2] * z[0];
643*38e8c45fSAndroid Build Coastguard Worker     x[2] = y[0] * z[1] - y[1] * z[0];
644*38e8c45fSAndroid Build Coastguard Worker 
645*38e8c45fSAndroid Build Coastguard Worker     /* Recompute Y = Z cross X */
646*38e8c45fSAndroid Build Coastguard Worker     y[0] = z[1] * x[2] - z[2] * x[1];
647*38e8c45fSAndroid Build Coastguard Worker     y[1] = -z[0] * x[2] + z[2] * x[0];
648*38e8c45fSAndroid Build Coastguard Worker     y[2] = z[0] * x[1] - z[1] * x[0];
649*38e8c45fSAndroid Build Coastguard Worker 
650*38e8c45fSAndroid Build Coastguard Worker     /* mpichler, 19950515 */
651*38e8c45fSAndroid Build Coastguard Worker     /* cross product gives area of parallelogram, which is < 1.0 for
652*38e8c45fSAndroid Build Coastguard Worker      * non-perpendicular unit-length vectors; so normalize x, y here
653*38e8c45fSAndroid Build Coastguard Worker      */
654*38e8c45fSAndroid Build Coastguard Worker 
655*38e8c45fSAndroid Build Coastguard Worker     mag = (float)sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
656*38e8c45fSAndroid Build Coastguard Worker     if (mag) {
657*38e8c45fSAndroid Build Coastguard Worker         x[0] /= mag;
658*38e8c45fSAndroid Build Coastguard Worker         x[1] /= mag;
659*38e8c45fSAndroid Build Coastguard Worker         x[2] /= mag;
660*38e8c45fSAndroid Build Coastguard Worker     }
661*38e8c45fSAndroid Build Coastguard Worker 
662*38e8c45fSAndroid Build Coastguard Worker     mag = (float)sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
663*38e8c45fSAndroid Build Coastguard Worker     if (mag) {
664*38e8c45fSAndroid Build Coastguard Worker         y[0] /= mag;
665*38e8c45fSAndroid Build Coastguard Worker         y[1] /= mag;
666*38e8c45fSAndroid Build Coastguard Worker         y[2] /= mag;
667*38e8c45fSAndroid Build Coastguard Worker     }
668*38e8c45fSAndroid Build Coastguard Worker 
669*38e8c45fSAndroid Build Coastguard Worker #define M(row,col)  m[(col)*4+(row)]
670*38e8c45fSAndroid Build Coastguard Worker     M(0, 0) = x[0];
671*38e8c45fSAndroid Build Coastguard Worker     M(0, 1) = x[1];
672*38e8c45fSAndroid Build Coastguard Worker     M(0, 2) = x[2];
673*38e8c45fSAndroid Build Coastguard Worker     M(0, 3) = 0.0;
674*38e8c45fSAndroid Build Coastguard Worker     M(1, 0) = y[0];
675*38e8c45fSAndroid Build Coastguard Worker     M(1, 1) = y[1];
676*38e8c45fSAndroid Build Coastguard Worker     M(1, 2) = y[2];
677*38e8c45fSAndroid Build Coastguard Worker     M(1, 3) = 0.0;
678*38e8c45fSAndroid Build Coastguard Worker     M(2, 0) = z[0];
679*38e8c45fSAndroid Build Coastguard Worker     M(2, 1) = z[1];
680*38e8c45fSAndroid Build Coastguard Worker     M(2, 2) = z[2];
681*38e8c45fSAndroid Build Coastguard Worker     M(2, 3) = 0.0;
682*38e8c45fSAndroid Build Coastguard Worker     M(3, 0) = 0.0;
683*38e8c45fSAndroid Build Coastguard Worker     M(3, 1) = 0.0;
684*38e8c45fSAndroid Build Coastguard Worker     M(3, 2) = 0.0;
685*38e8c45fSAndroid Build Coastguard Worker     M(3, 3) = 1.0;
686*38e8c45fSAndroid Build Coastguard Worker #undef M
687*38e8c45fSAndroid Build Coastguard Worker     {
688*38e8c45fSAndroid Build Coastguard Worker         int a;
689*38e8c45fSAndroid Build Coastguard Worker         GLfixed fixedM[16];
690*38e8c45fSAndroid Build Coastguard Worker         for (a = 0; a < 16; ++a)
691*38e8c45fSAndroid Build Coastguard Worker             fixedM[a] = (GLfixed)(m[a] * 65536);
692*38e8c45fSAndroid Build Coastguard Worker         glMultMatrixx(fixedM);
693*38e8c45fSAndroid Build Coastguard Worker     }
694*38e8c45fSAndroid Build Coastguard Worker 
695*38e8c45fSAndroid Build Coastguard Worker     /* Translate Eye to Origin */
696*38e8c45fSAndroid Build Coastguard Worker     glTranslatex((GLfixed)(-eyex * 65536),
697*38e8c45fSAndroid Build Coastguard Worker                  (GLfixed)(-eyey * 65536),
698*38e8c45fSAndroid Build Coastguard Worker                  (GLfixed)(-eyez * 65536));
699*38e8c45fSAndroid Build Coastguard Worker }
700*38e8c45fSAndroid Build Coastguard Worker 
701*38e8c45fSAndroid Build Coastguard Worker 
camTrack()702*38e8c45fSAndroid Build Coastguard Worker static void camTrack()
703*38e8c45fSAndroid Build Coastguard Worker {
704*38e8c45fSAndroid Build Coastguard Worker     float lerp[5];
705*38e8c45fSAndroid Build Coastguard Worker     float eX, eY, eZ, cX, cY, cZ;
706*38e8c45fSAndroid Build Coastguard Worker     float trackPos;
707*38e8c45fSAndroid Build Coastguard Worker     CAMTRACK *cam;
708*38e8c45fSAndroid Build Coastguard Worker     long currentCamTick;
709*38e8c45fSAndroid Build Coastguard Worker     int a;
710*38e8c45fSAndroid Build Coastguard Worker 
711*38e8c45fSAndroid Build Coastguard Worker     if (sNextCamTrackStartTick <= sTick)
712*38e8c45fSAndroid Build Coastguard Worker     {
713*38e8c45fSAndroid Build Coastguard Worker         ++sCurrentCamTrack;
714*38e8c45fSAndroid Build Coastguard Worker         sCurrentCamTrackStartTick = sNextCamTrackStartTick;
715*38e8c45fSAndroid Build Coastguard Worker     }
716*38e8c45fSAndroid Build Coastguard Worker     sNextCamTrackStartTick = sCurrentCamTrackStartTick +
717*38e8c45fSAndroid Build Coastguard Worker                              sCamTracks[sCurrentCamTrack].len * CAMTRACK_LEN;
718*38e8c45fSAndroid Build Coastguard Worker 
719*38e8c45fSAndroid Build Coastguard Worker     cam = &sCamTracks[sCurrentCamTrack];
720*38e8c45fSAndroid Build Coastguard Worker     currentCamTick = sTick - sCurrentCamTrackStartTick;
721*38e8c45fSAndroid Build Coastguard Worker     trackPos = (float)currentCamTick / (CAMTRACK_LEN * cam->len);
722*38e8c45fSAndroid Build Coastguard Worker 
723*38e8c45fSAndroid Build Coastguard Worker     for (a = 0; a < 5; ++a)
724*38e8c45fSAndroid Build Coastguard Worker         lerp[a] = (cam->src[a] + cam->dest[a] * trackPos) * 0.01f;
725*38e8c45fSAndroid Build Coastguard Worker 
726*38e8c45fSAndroid Build Coastguard Worker     if (cam->dist)
727*38e8c45fSAndroid Build Coastguard Worker     {
728*38e8c45fSAndroid Build Coastguard Worker         float dist = cam->dist * 0.1f;
729*38e8c45fSAndroid Build Coastguard Worker         cX = lerp[0];
730*38e8c45fSAndroid Build Coastguard Worker         cY = lerp[1];
731*38e8c45fSAndroid Build Coastguard Worker         cZ = lerp[2];
732*38e8c45fSAndroid Build Coastguard Worker         eX = cX - (float)cos(lerp[3]) * dist;
733*38e8c45fSAndroid Build Coastguard Worker         eY = cY - (float)sin(lerp[3]) * dist;
734*38e8c45fSAndroid Build Coastguard Worker         eZ = cZ - lerp[4];
735*38e8c45fSAndroid Build Coastguard Worker     }
736*38e8c45fSAndroid Build Coastguard Worker     else
737*38e8c45fSAndroid Build Coastguard Worker     {
738*38e8c45fSAndroid Build Coastguard Worker         eX = lerp[0];
739*38e8c45fSAndroid Build Coastguard Worker         eY = lerp[1];
740*38e8c45fSAndroid Build Coastguard Worker         eZ = lerp[2];
741*38e8c45fSAndroid Build Coastguard Worker         cX = eX + (float)cos(lerp[3]);
742*38e8c45fSAndroid Build Coastguard Worker         cY = eY + (float)sin(lerp[3]);
743*38e8c45fSAndroid Build Coastguard Worker         cZ = eZ + lerp[4];
744*38e8c45fSAndroid Build Coastguard Worker     }
745*38e8c45fSAndroid Build Coastguard Worker     gluLookAt(eX, eY, eZ, cX, cY, cZ, 0, 0, 1);
746*38e8c45fSAndroid Build Coastguard Worker }
747*38e8c45fSAndroid Build Coastguard Worker 
748*38e8c45fSAndroid Build Coastguard Worker 
749*38e8c45fSAndroid Build Coastguard Worker // Called from the app framework.
750*38e8c45fSAndroid Build Coastguard Worker /* The tick is current time in milliseconds, width and height
751*38e8c45fSAndroid Build Coastguard Worker  * are the image dimensions to be rendered.
752*38e8c45fSAndroid Build Coastguard Worker  */
appRender(long tick,int width,int height)753*38e8c45fSAndroid Build Coastguard Worker void appRender(long tick, int width, int height)
754*38e8c45fSAndroid Build Coastguard Worker {
755*38e8c45fSAndroid Build Coastguard Worker     if (sStartTick == 0)
756*38e8c45fSAndroid Build Coastguard Worker         sStartTick = tick;
757*38e8c45fSAndroid Build Coastguard Worker     if (!gAppAlive)
758*38e8c45fSAndroid Build Coastguard Worker         return;
759*38e8c45fSAndroid Build Coastguard Worker 
760*38e8c45fSAndroid Build Coastguard Worker     // Actual tick value is "blurred" a little bit.
761*38e8c45fSAndroid Build Coastguard Worker     sTick = (sTick + tick - sStartTick) >> 1;
762*38e8c45fSAndroid Build Coastguard Worker 
763*38e8c45fSAndroid Build Coastguard Worker     // Terminate application after running through the demonstration once.
764*38e8c45fSAndroid Build Coastguard Worker     if (sTick >= RUN_LENGTH)
765*38e8c45fSAndroid Build Coastguard Worker     {
766*38e8c45fSAndroid Build Coastguard Worker         gAppAlive = 0;
767*38e8c45fSAndroid Build Coastguard Worker         return;
768*38e8c45fSAndroid Build Coastguard Worker     }
769*38e8c45fSAndroid Build Coastguard Worker 
770*38e8c45fSAndroid Build Coastguard Worker     // Prepare OpenGL ES for rendering of the frame.
771*38e8c45fSAndroid Build Coastguard Worker     prepareFrame(width, height);
772*38e8c45fSAndroid Build Coastguard Worker 
773*38e8c45fSAndroid Build Coastguard Worker     // Update the camera position and set the lookat.
774*38e8c45fSAndroid Build Coastguard Worker     camTrack();
775*38e8c45fSAndroid Build Coastguard Worker 
776*38e8c45fSAndroid Build Coastguard Worker     // Configure environment.
777*38e8c45fSAndroid Build Coastguard Worker     configureLightAndMaterial();
778*38e8c45fSAndroid Build Coastguard Worker 
779*38e8c45fSAndroid Build Coastguard Worker     // Draw the reflection by drawing models with negated Z-axis.
780*38e8c45fSAndroid Build Coastguard Worker     glPushMatrix();
781*38e8c45fSAndroid Build Coastguard Worker     drawModels(-1);
782*38e8c45fSAndroid Build Coastguard Worker     glPopMatrix();
783*38e8c45fSAndroid Build Coastguard Worker 
784*38e8c45fSAndroid Build Coastguard Worker     // Blend the ground plane to the window.
785*38e8c45fSAndroid Build Coastguard Worker     drawGroundPlane();
786*38e8c45fSAndroid Build Coastguard Worker 
787*38e8c45fSAndroid Build Coastguard Worker     // Draw all the models normally.
788*38e8c45fSAndroid Build Coastguard Worker     drawModels(1);
789*38e8c45fSAndroid Build Coastguard Worker 
790*38e8c45fSAndroid Build Coastguard Worker     // Draw fade quad over whole window (when changing cameras).
791*38e8c45fSAndroid Build Coastguard Worker     drawFadeQuad();
792*38e8c45fSAndroid Build Coastguard Worker }
793