146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo/* San Angeles Observation OpenGL ES version example
246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * Copyright 2004-2005 Jetro Lauha
346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * All rights reserved.
446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * Web: http://iki.fi/jetro/
546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *
646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * This source is free software; you can redistribute it and/or
746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * modify it under the terms of EITHER:
846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *   (1) The GNU Lesser General Public License as published by the Free
946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *       Software Foundation; either version 2.1 of the License, or (at
1046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *       your option) any later version. The text of the GNU Lesser
1146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *       General Public License is included with this source in the
1246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *       file LICENSE-LGPL.txt.
1346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *   (2) The BSD-style license that is included with this source in
1446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *       the file LICENSE-BSD.txt.
1546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *
1646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * This source is distributed in the hope that it will be useful,
1746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * but WITHOUT ANY WARRANTY; without even the implied warranty of
1846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
1946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * LICENSE-LGPL.txt and LICENSE-BSD.txt for more details.
2046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo *
2146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * $Id: demo.c,v 1.10 2005/02/08 20:54:39 tonic Exp $
2246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * $Revision: 1.10 $
2346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo */
2446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
25c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo// The GLES2 implementation is adapted from the javascript implementation
26c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo// upon WebGL by kwaters@.
274545a8e20f4025c2d34bee31f38e45119ef40b22Zhenyao Mo
28c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo// The OpenGL implementation uses VBO extensions instead.
29c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
30c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#include <stdio.h>
3146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#include <stdlib.h>
3246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#include <math.h>
3346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#include <float.h>
3446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#include <assert.h>
3546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
36c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
37c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#undef IMPORTGL_API
38c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#undef IMPORTGL_FNPTRINIT
3946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#include "importgl.h"
40c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#include "matrixop.h"
41c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#include "shader.h"
42c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // SAN_ANGELES_OBSERVATION_GLES
43c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#undef IMPORTVBO_API
44c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#undef IMPORTVBO_FNPTRINIT
45a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo#include "importvbo.h"
46c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
4746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
4846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#include "app.h"
4946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#include "shapes.h"
5046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#include "cams.h"
5146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
5246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
5346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo// Total run length is 20 * camera track base unit length (see cams.h).
5446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#define RUN_LENGTH  (20 * CAMTRACK_LEN)
5546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#undef PI
5646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#define PI 3.1415926535897932f
5746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#define RANDOM_UINT_MAX 65535
5846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
5946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
6046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic unsigned long sRandomSeed = 0;
6146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
6246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void seedRandom(unsigned long seed)
6346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
6446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    sRandomSeed = seed;
6546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
6646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
6746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic unsigned long randomUInt()
6846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
6946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    sRandomSeed = sRandomSeed * 0x343fd + 0x269ec3;
7046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    return sRandomSeed >> 16;
7146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
7246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
7346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
7446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo// Definition of one GL object in this demo.
7546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Motypedef struct {
7646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* Vertex array and color array are enabled for all objects, so their
7746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     * pointers must always be valid and non-NULL. Normal array is not
7846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     * used by the ground plane, so when its pointer is NULL then normal
7946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     * array usage is disabled.
8046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     *
8146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     * Vertex array is supposed to use GL_FIXED datatype and stride 0
8246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     * (i.e. tightly packed array). Color array is supposed to have 4
8346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     * components per color with GL_UNSIGNED_BYTE datatype and stride 0.
8446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     * Normal array is supposed to use GL_FIXED datatype and stride 0.
8546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     */
86c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLfloat *vertexArray;
87c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLint vertexArraySize;
88fd97ee8636d2e52212eb5d4d8ba6450ec643263fIlja H. Friedel    GLintptr vertexArrayOffset;
8946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLubyte *colorArray;
90c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLint colorArraySize;
91fd97ee8636d2e52212eb5d4d8ba6450ec643263fIlja H. Friedel    GLintptr colorArrayOffset;
92c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLfloat *normalArray;
93c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLint normalArraySize;
94fd97ee8636d2e52212eb5d4d8ba6450ec643263fIlja H. Friedel    GLintptr normalArrayOffset;
9546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLint vertexComponents;
9646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLsizei count;
97c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
98c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLuint shaderProgram;
99c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
10046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo} GLOBJECT;
10146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
10246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
10346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic long sStartTick = 0;
10446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic long sTick = 0;
10546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
10646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic int sCurrentCamTrack = 0;
10746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic long sCurrentCamTrackStartTick = 0;
10846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic long sNextCamTrackStartTick = 0x7fffffff;
10946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
11046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic GLOBJECT *sSuperShapeObjects[SUPERSHAPE_COUNT] = { NULL };
11146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic GLOBJECT *sGroundPlane = NULL;
1123eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mostatic GLOBJECT *sFadeQuad = NULL;
11346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
1143eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mostatic GLuint sVBO = 0;
11546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
11646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Motypedef struct {
11746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    float x, y, z;
11846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo} VECTOR3;
11946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
12046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
12146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void freeGLObject(GLOBJECT *object)
12246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
12346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (object == NULL)
12446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        return;
125c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
12646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    free(object->normalArray);
12746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    free(object->colorArray);
12846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    free(object->vertexArray);
129c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
13046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    free(object);
13146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
13246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
13346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
13446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic GLOBJECT * newGLObject(long vertices, int vertexComponents,
1353eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                              int useColorArray, int useNormalArray)
13646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
13746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLOBJECT *result;
138c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result = malloc(sizeof(GLOBJECT));
13946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (result == NULL)
14046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        return NULL;
14146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    result->count = vertices;
14246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    result->vertexComponents = vertexComponents;
143c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result->vertexArraySize = vertices * vertexComponents * sizeof(GLfloat);
144c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result->vertexArray = malloc(result->vertexArraySize);
145c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result->vertexArrayOffset = 0;
1463eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    if (useColorArray)
1473eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    {
1483eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        result->colorArraySize = vertices * 4 * sizeof(GLubyte);
1493eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        result->colorArray = malloc(result->colorArraySize);
1503eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    }
1513eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    else
1523eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    {
1533eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        result->colorArraySize = 0;
1543eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        result->colorArray = NULL;
1553eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    }
156c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result->colorArrayOffset = result->vertexArrayOffset +
157c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                               result->vertexArraySize;
15846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (useNormalArray)
15946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
160c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        result->normalArraySize = vertices * 3 * sizeof(GLfloat);
161c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        result->normalArray = malloc(result->normalArraySize);
16246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
16346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    else
164c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    {
165c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        result->normalArraySize = 0;
16646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        result->normalArray = NULL;
167c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    }
168c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result->normalArrayOffset = result->colorArrayOffset +
169c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                                result->colorArraySize;
17046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (result->vertexArray == NULL ||
1713eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        (useColorArray && result->colorArray == NULL) ||
17246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        (useNormalArray && result->normalArray == NULL))
17346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
17446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        freeGLObject(result);
17546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        return NULL;
17646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
177c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
178c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result->shaderProgram = 0;
179c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
18046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    return result;
18146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
18246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
18346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
1843eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mostatic void appendObjectVBO(GLOBJECT *object, GLint *offset)
185a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo{
186a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    assert(object != NULL);
187a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo
1883eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    object->vertexArrayOffset += *offset;
1893eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    object->colorArrayOffset += *offset;
1903eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    object->normalArrayOffset += *offset;
1913eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    *offset += object->vertexArraySize + object->colorArraySize +
1923eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo               object->normalArraySize;
19308f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel
194c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glBufferSubData(GL_ARRAY_BUFFER, object->vertexArrayOffset,
195c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                    object->vertexArraySize, object->vertexArray);
1963eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    if (object->colorArray)
1973eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        glBufferSubData(GL_ARRAY_BUFFER, object->colorArrayOffset,
1983eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                        object->colorArraySize, object->colorArray);
199a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    if (object->normalArray)
200c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glBufferSubData(GL_ARRAY_BUFFER, object->normalArrayOffset,
201c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                        object->normalArraySize, object->normalArray);
202a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo
203a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    free(object->normalArray);
204c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    object->normalArray = NULL;
205a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    free(object->colorArray);
206c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    object->colorArray = NULL;
207a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    free(object->vertexArray);
208c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    object->vertexArray = NULL;
209a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo}
210a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo
211a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo
2123eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mostatic GLuint createVBO(GLOBJECT **superShapes, int superShapeCount,
2133eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                        GLOBJECT *groundPlane, GLOBJECT *fadeQuad)
2143eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo{
2153eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    GLuint vbo;
2163eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    GLint totalSize = 0;
2173eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    int a;
2183eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    for (a = 0; a < superShapeCount; ++a)
2193eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    {
2203eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        assert(superShapes[a] != NULL);
2213eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        totalSize += superShapes[a]->vertexArraySize +
2223eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                     superShapes[a]->colorArraySize +
2233eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                     superShapes[a]->normalArraySize;
2243eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    }
2253eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    totalSize += groundPlane->vertexArraySize +
2263eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                 groundPlane->colorArraySize +
2273eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                 groundPlane->normalArraySize;
2283eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    totalSize += fadeQuad->vertexArraySize +
2293eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                 fadeQuad->colorArraySize +
2303eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                 fadeQuad->normalArraySize;
23108f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel    glGenBuffers(1, &vbo);
23208f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel    glBindBuffer(GL_ARRAY_BUFFER, vbo);
2333eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    glBufferData(GL_ARRAY_BUFFER, totalSize, 0, GL_STATIC_DRAW);
2343eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    GLint offset = 0;
2353eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    for (a = 0; a < superShapeCount; ++a)
2363eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        appendObjectVBO(superShapes[a], &offset);
2373eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    appendObjectVBO(groundPlane, &offset);
2383eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    appendObjectVBO(fadeQuad, &offset);
2393eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    assert(offset == totalSize);
2403eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    return vbo;
2413eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo}
2423eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo
2433eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo
24446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void drawGLObject(GLOBJECT *object)
24546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
246c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
247c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    int loc_pos = -1;
248c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    int loc_colorIn = -1;
249c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    int loc_normal = -1;
250c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
25146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
252c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    assert(object != NULL);
253a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo
254c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
255c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    bindShaderProgram(object->shaderProgram);
256c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    if (object->shaderProgram == sShaderLit.program)
257a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    {
258c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        loc_pos = sShaderLit.pos;
259c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        loc_colorIn = sShaderLit.colorIn;
260c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        loc_normal = sShaderLit.normal;
261c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    }
262c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    else if (object->shaderProgram == sShaderFlat.program)
263c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    {
264c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        loc_pos = sShaderFlat.pos;
265c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        loc_colorIn = sShaderFlat.colorIn;
266a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    }
267a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    else
268c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    {
269c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        assert(0);
270c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    }
271c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glVertexAttribPointer(loc_pos, object->vertexComponents, GL_FLOAT,
27208f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel                          GL_FALSE, 0, (GLvoid *)object->vertexArrayOffset);
273c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glEnableVertexAttribArray(loc_pos);
274c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glVertexAttribPointer(loc_colorIn, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0,
27508f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel                          (GLvoid *)object->colorArrayOffset);
276c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glEnableVertexAttribArray(loc_colorIn);
277c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    if (object->normalArraySize > 0)
278c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    {
279c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glVertexAttribPointer(loc_normal, 3, GL_FLOAT, GL_FALSE, 0,
28008f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel                              (GLvoid *)object->normalArrayOffset);
281c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glEnableVertexAttribArray(loc_normal);
282c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    }
283a625f7322b08a512761b64ae1485d782dccee8a4Zhenyao Mo    glDrawArrays(GL_TRIANGLES, 0, object->count);
28446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
285c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    if (object->normalArraySize > 0)
286c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glDisableVertexAttribArray(loc_normal);
287c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glDisableVertexAttribArray(loc_colorIn);
288c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glDisableVertexAttribArray(loc_pos);
289c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
290c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glVertexPointer(object->vertexComponents, GL_FLOAT, 0,
29108f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel                    (GLvoid *)object->vertexArrayOffset);
29208f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel    glColorPointer(4, GL_UNSIGNED_BYTE, 0, (GLvoid *)object->colorArrayOffset);
293c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    if (object->normalArraySize > 0)
29446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
29508f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel        glNormalPointer(GL_FLOAT, 0, (GLvoid *)object->normalArrayOffset);
29646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glEnableClientState(GL_NORMAL_ARRAY);
29746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
29846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    else
29946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glDisableClientState(GL_NORMAL_ARRAY);
30046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glDrawArrays(GL_TRIANGLES, 0, object->count);
301c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
30246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
30346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
30446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
30546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void vector3Sub(VECTOR3 *dest, VECTOR3 *v1, VECTOR3 *v2)
30646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
30746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    dest->x = v1->x - v2->x;
30846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    dest->y = v1->y - v2->y;
30946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    dest->z = v1->z - v2->z;
31046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
31146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
31246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
31346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void superShapeMap(VECTOR3 *point, float r1, float r2, float t, float p)
31446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
31546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // sphere-mapping of supershape parameters
31646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    point->x = (float)(cos(t) * cos(p) / r1 / r2);
31746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    point->y = (float)(sin(t) * cos(p) / r1 / r2);
31846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    point->z = (float)(sin(p) / r2);
31946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
32046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
32146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
32246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic float ssFunc(const float t, const float *p)
32346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
32446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    return (float)(pow(pow(fabs(cos(p[0] * t / 4)) / p[1], p[4]) +
32546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                       pow(fabs(sin(p[0] * t / 4)) / p[2], p[5]), 1 / p[3]));
32646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
32746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
32846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
32946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo// Creates and returns a supershape object.
33046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo// Based on Paul Bourke's POV-Ray implementation.
33146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo// http://astronomy.swin.edu.au/~pbourke/povray/supershape/
33246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic GLOBJECT * createSuperShape(const float *params)
33346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
33446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int resol1 = (int)params[SUPERSHAPE_PARAMS - 3];
33546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int resol2 = (int)params[SUPERSHAPE_PARAMS - 2];
33646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // latitude 0 to pi/2 for no mirrored bottom
33746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // (latitudeBegin==0 for -pi/2 to pi/2 originally)
33846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int latitudeBegin = resol2 / 4;
33946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int latitudeEnd = resol2 / 2;    // non-inclusive
34046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int longitudeCount = resol1;
34146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int latitudeCount = latitudeEnd - latitudeBegin;
34246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const long triangleCount = longitudeCount * latitudeCount * 2;
34346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const long vertices = triangleCount * 3;
34446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLOBJECT *result;
34546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    float baseColor[3];
34646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    int a, longitude, latitude;
34746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    long currentVertex, currentQuad;
34846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
3493eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    result = newGLObject(vertices, 3, 1, 1);
35046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (result == NULL)
35146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        return NULL;
35246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
35346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    for (a = 0; a < 3; ++a)
35446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        baseColor[a] = ((randomUInt() % 155) + 100) / 255.f;
35546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
35646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    currentQuad = 0;
35746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    currentVertex = 0;
35846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
35946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // longitude -pi to pi
36046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    for (longitude = 0; longitude < longitudeCount; ++longitude)
36146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
36246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
36346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        // latitude 0 to pi/2
36446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        for (latitude = latitudeBegin; latitude < latitudeEnd; ++latitude)
36546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        {
36646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            float t1 = -PI + longitude * 2 * PI / resol1;
36746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            float t2 = -PI + (longitude + 1) * 2 * PI / resol1;
36846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            float p1 = -PI / 2 + latitude * 2 * PI / resol2;
36946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            float p2 = -PI / 2 + (latitude + 1) * 2 * PI / resol2;
37046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            float r0, r1, r2, r3;
37146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
37246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            r0 = ssFunc(t1, params);
37346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            r1 = ssFunc(p1, &params[6]);
37446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            r2 = ssFunc(t2, params);
37546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            r3 = ssFunc(p2, &params[6]);
37646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
37746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            if (r0 != 0 && r1 != 0 && r2 != 0 && r3 != 0)
37846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            {
37946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                VECTOR3 pa, pb, pc, pd;
38046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                VECTOR3 v1, v2, n;
38146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                float ca;
38246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                int i;
38346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                //float lenSq, invLenSq;
38446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
38546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                superShapeMap(&pa, r0, r1, t1, p1);
38646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                superShapeMap(&pb, r2, r1, t2, p1);
38746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                superShapeMap(&pc, r2, r3, t2, p2);
38846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                superShapeMap(&pd, r0, r3, t1, p2);
38946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
39046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                // kludge to set lower edge of the object to fixed level
39146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                if (latitude == latitudeBegin + 1)
39246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    pa.z = pb.z = 0;
39346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
39446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                vector3Sub(&v1, &pb, &pa);
39546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                vector3Sub(&v2, &pd, &pa);
39646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
39746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                // Calculate normal with cross product.
39846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                /*   i    j    k      i    j
39946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                 * v1.x v1.y v1.z | v1.x v1.y
40046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                 * v2.x v2.y v2.z | v2.x v2.y
40146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                 */
40246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
40346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                n.x = v1.y * v2.z - v1.z * v2.y;
40446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                n.y = v1.z * v2.x - v1.x * v2.z;
40546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                n.z = v1.x * v2.y - v1.y * v2.x;
40646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
40746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                /* Pre-normalization of the normals is disabled here because
40846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                 * they will be normalized anyway later due to automatic
40946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                 * normalization (GL_NORMALIZE). It is enabled because the
41046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                 * objects are scaled with glScale.
41146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                 */
41246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                /*
41346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                lenSq = n.x * n.x + n.y * n.y + n.z * n.z;
41446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                invLenSq = (float)(1 / sqrt(lenSq));
41546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                n.x *= invLenSq;
41646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                n.y *= invLenSq;
41746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                n.z *= invLenSq;
41846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                */
41946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
42046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                ca = pa.z + 0.5f;
42146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
42246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                for (i = currentVertex * 3;
42346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                     i < (currentVertex + 6) * 3;
42446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                     i += 3)
42546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                {
426c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                    result->normalArray[i] = n.x;
427c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                    result->normalArray[i + 1] = n.y;
428c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                    result->normalArray[i + 2] = n.z;
42946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                }
43046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                for (i = currentVertex * 4;
43146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                     i < (currentVertex + 6) * 4;
43246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                     i += 4)
43346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                {
43446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    int a, color[3];
43546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    for (a = 0; a < 3; ++a)
43646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    {
43746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                        color[a] = (int)(ca * baseColor[a] * 255);
43846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                        if (color[a] > 255) color[a] = 255;
43946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    }
44046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    result->colorArray[i] = (GLubyte)color[0];
44146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    result->colorArray[i + 1] = (GLubyte)color[1];
44246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    result->colorArray[i + 2] = (GLubyte)color[2];
44346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                    result->colorArray[i + 3] = 0;
44446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                }
445c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3] = pa.x;
446c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 1] = pa.y;
447c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 2] = pa.z;
44846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                ++currentVertex;
449c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3] = pb.x;
450c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 1] = pb.y;
451c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 2] = pb.z;
45246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                ++currentVertex;
453c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3] = pd.x;
454c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 1] = pd.y;
455c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 2] = pd.z;
45646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                ++currentVertex;
457c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3] = pb.x;
458c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 1] = pb.y;
459c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 2] = pb.z;
46046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                ++currentVertex;
461c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3] = pc.x;
462c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 1] = pc.y;
463c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 2] = pc.z;
46446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                ++currentVertex;
465c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3] = pd.x;
466c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 1] = pd.y;
467c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 3 + 2] = pd.z;
46846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                ++currentVertex;
46946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            } // r0 && r1 && r2 && r3
47046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            ++currentQuad;
47146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        } // latitude
47246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    } // longitude
47346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
47446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Set number of vertices in object to the actual amount created.
47546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    result->count = currentVertex;
476c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
477c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result->shaderProgram = sShaderLit.program;
478c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
47946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    return result;
48046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
48146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
48246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
48346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic GLOBJECT * createGroundPlane()
48446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
48546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int scale = 4;
48646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int yBegin = -15, yEnd = 15;    // ends are non-inclusive
48746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int xBegin = -15, xEnd = 15;
48846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const long triangleCount = (yEnd - yBegin) * (xEnd - xBegin) * 2;
48946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const long vertices = triangleCount * 3;
49046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLOBJECT *result;
49146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    int x, y;
49246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    long currentVertex, currentQuad;
49346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
4943eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    result = newGLObject(vertices, 2, 1, 0);
49546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (result == NULL)
49646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        return NULL;
49746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
49846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    currentQuad = 0;
49946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    currentVertex = 0;
50046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
50146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    for (y = yBegin; y < yEnd; ++y)
50246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
50346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        for (x = xBegin; x < xEnd; ++x)
50446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        {
50546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            GLubyte color;
50646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            int i, a;
50746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            color = (GLubyte)((randomUInt() & 0x5f) + 81);  // 101 1111
50846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            for (i = currentVertex * 4; i < (currentVertex + 6) * 4; i += 4)
50946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            {
51046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                result->colorArray[i] = color;
51146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                result->colorArray[i + 1] = color;
51246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                result->colorArray[i + 2] = color;
51346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                result->colorArray[i + 3] = 0;
51446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            }
51546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
51646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            // Axis bits for quad triangles:
51746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            // x: 011100 (0x1c), y: 110001 (0x31)  (clockwise)
51846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            // x: 001110 (0x0e), y: 100011 (0x23)  (counter-clockwise)
51946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            for (a = 0; a < 6; ++a)
52046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            {
52146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                const int xm = x + ((0x1c >> a) & 1);
52246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                const int ym = y + ((0x31 >> a) & 1);
52346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                const float m = (float)(cos(xm * 2) * sin(ym * 4) * 0.75f);
524c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 2] = xm * scale + m;
525c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                result->vertexArray[currentVertex * 2 + 1] = ym * scale + m;
52646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                ++currentVertex;
52746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            }
52846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            ++currentQuad;
52946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        }
53046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
531c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
532c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    result->shaderProgram = sShaderFlat.program;
533c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
53446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    return result;
53546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
53646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
53746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
53846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void drawGroundPlane()
53946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
54046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glDisable(GL_CULL_FACE);
54146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glDisable(GL_DEPTH_TEST);
54246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnable(GL_BLEND);
54346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glBlendFunc(GL_ZERO, GL_SRC_COLOR);
544c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifndef SAN_ANGELES_OBSERVATION_GLES
54546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glDisable(GL_LIGHTING);
546c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // !SAN_ANGELES_OBSERVATION_GLES
54746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
54846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    drawGLObject(sGroundPlane);
54946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
550c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifndef SAN_ANGELES_OBSERVATION_GLES
55146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnable(GL_LIGHTING);
552c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // !SAN_ANGELES_OBSERVATION_GLES
55346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glDisable(GL_BLEND);
55446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnable(GL_DEPTH_TEST);
55546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
55646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
55746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
5583eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mostatic GLOBJECT * createFadeQuad()
55946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
560c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    static const GLfloat quadVertices[] = {
5613eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        -1, -1,
5623eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo         1, -1,
5633eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        -1,  1,
5643eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo         1, -1,
5653eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo         1,  1,
5663eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        -1,  1
56746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    };
56846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
5693eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    GLOBJECT *result;
5703eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    int i;
5713eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo
5723eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    result = newGLObject(6, 2, 0, 0);
5733eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    if (result == NULL)
5743eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        return NULL;
5753eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo
5763eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    for (i = 0; i < 12; ++i)
5773eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        result->vertexArray[i] = quadVertices[i];
5783eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo
5793eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
5803eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    result->shaderProgram = sShaderFade.program;
5813eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
5823eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    return result;
5833eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo}
5843eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo
5853eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo
5863eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mostatic void drawFadeQuad()
5873eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo{
58846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int beginFade = sTick - sCurrentCamTrackStartTick;
58946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int endFade = sNextCamTrackStartTick - sTick;
59046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int minFade = beginFade < endFade ? beginFade : endFade;
59146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
59246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (minFade < 1024)
59346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
594c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        const GLfloat fadeColor = minFade / 1024.f;
59546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glDisable(GL_DEPTH_TEST);
59646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glEnable(GL_BLEND);
59746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glBlendFunc(GL_ZERO, GL_SRC_COLOR);
598c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
599c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        bindShaderProgram(sShaderFade.program);
600c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glUniform1f(sShaderFade.minFade, fadeColor);
6013eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo        glVertexAttribPointer(sShaderFade.pos, 2, GL_FLOAT, GL_FALSE, 0,
60208f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel                              (GLvoid *)sFadeQuad->vertexArrayOffset);
603c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glEnableVertexAttribArray(sShaderFade.pos);
604c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glDrawArrays(GL_TRIANGLES, 0, 6);
605c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glDisableVertexAttribArray(sShaderFade.pos);
606c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
607c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glColor4f(fadeColor, fadeColor, fadeColor, 0);
608c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
60946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glDisable(GL_LIGHTING);
61046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
61146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glMatrixMode(GL_MODELVIEW);
61246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glLoadIdentity();
61346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
61446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glMatrixMode(GL_PROJECTION);
61546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glLoadIdentity();
61646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
61746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glDisableClientState(GL_COLOR_ARRAY);
61846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glDisableClientState(GL_NORMAL_ARRAY);
61908f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel        glVertexPointer(2, GL_FLOAT, 0, (GLvoid *)sFadeQuad->vertexArrayOffset);
6204545a8e20f4025c2d34bee31f38e45119ef40b22Zhenyao Mo
62146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glDrawArrays(GL_TRIANGLES, 0, 6);
62246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
62346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glEnableClientState(GL_COLOR_ARRAY);
62446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
62546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glMatrixMode(GL_MODELVIEW);
62646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
62746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glEnable(GL_LIGHTING);
628c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
62946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glDisable(GL_BLEND);
63046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glEnable(GL_DEPTH_TEST);
63146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
63246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
63346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
63446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
63546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo// Called from the app framework.
636c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Moint appInit()
63746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
63846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    int a;
639c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    static GLfloat light0Diffuse[] = { 1.f, 0.4f, 0, 1.f };
640c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    static GLfloat light1Diffuse[] = { 0.07f, 0.14f, 0.35f, 1.f };
641c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    static GLfloat light2Diffuse[] = { 0.07f, 0.17f, 0.14f, 1.f };
642c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    static GLfloat materialSpecular[] = { 1.f, 1.f, 1.f, 1.f };
643c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
644c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    static GLfloat lightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.f };
645c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
64646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
64746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glDisable(GL_CULL_FACE);
648c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glEnable(GL_DEPTH_TEST);
649c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
650c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    if (initShaderPrograms() == 0)
651c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    {
65208f9dd023db83e838b93b46e432e3e8bfe6680d1Ilja H. Friedel        fprintf(stderr, "Error: initShaderPrograms failed\n");
653c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        return 0;
654c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    }
655c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
65646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glShadeModel(GL_FLAT);
657c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glEnable(GL_NORMALIZE);
65846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
65946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnable(GL_LIGHTING);
66046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnable(GL_LIGHT0);
66146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnable(GL_LIGHT1);
66246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnable(GL_LIGHT2);
66346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
66446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnableClientState(GL_VERTEX_ARRAY);
66546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnableClientState(GL_COLOR_ARRAY);
666c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
66746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    seedRandom(15);
66846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
66946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    for (a = 0; a < SUPERSHAPE_COUNT; ++a)
67046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
67146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        sSuperShapeObjects[a] = createSuperShape(sSuperShapeParams[a]);
67246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        assert(sSuperShapeObjects[a] != NULL);
67346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
67446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    sGroundPlane = createGroundPlane();
67546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    assert(sGroundPlane != NULL);
6763eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    sFadeQuad = createFadeQuad();
6773eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    assert(sFadeQuad != NULL);
6783eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    sVBO = createVBO(sSuperShapeObjects, SUPERSHAPE_COUNT,
6793eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo                     sGroundPlane, sFadeQuad);
680c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
681c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    // setup non-changing lighting parameters
682c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
683c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    bindShaderProgram(sShaderLit.program);
684c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform4fv(sShaderLit.ambient, 1, lightAmbient);
685c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform4fv(sShaderLit.light_0_diffuse, 1, light0Diffuse);
686c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform4fv(sShaderLit.light_1_diffuse, 1, light1Diffuse);
687c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform4fv(sShaderLit.light_2_diffuse, 1, light2Diffuse);
688c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform4fv(sShaderLit.light_0_specular, 1, materialSpecular);
689c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform1f(sShaderLit.shininess, 60.f);
690c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
691c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diffuse);
692c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1Diffuse);
693c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glLightfv(GL_LIGHT2, GL_DIFFUSE, light2Diffuse);
694c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecular);
695c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60);
696c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
697c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    return 1;
69846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
69946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
70046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
70146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo// Called from the app framework.
70246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Movoid appDeinit()
70346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
70446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    int a;
70546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    for (a = 0; a < SUPERSHAPE_COUNT; ++a)
70646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        freeGLObject(sSuperShapeObjects[a]);
70746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    freeGLObject(sGroundPlane);
7083eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    freeGLObject(sFadeQuad);
7093eba93a219c446c336a33e4e3288779eade2ef16Zhenyao Mo    glDeleteBuffers(1, &sVBO);
710c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
711c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    deInitShaderPrograms();
712c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
71346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
71446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
715c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifndef SAN_ANGELES_OBSERVATION_GLES
71646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void gluPerspective(GLfloat fovy, GLfloat aspect,
71746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                           GLfloat zNear, GLfloat zFar)
71846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
71946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLfloat xmin, xmax, ymin, ymax;
72046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
72146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    ymax = zNear * (GLfloat)tan(fovy * PI / 360);
72246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    ymin = -ymax;
72346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    xmin = ymin * aspect;
72446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    xmax = ymax * aspect;
72546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
726c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
72746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
728c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // !SAN_ANGELES_OBSERVATION_GLES
72946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
73046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void prepareFrame(int width, int height)
73146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
73246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glViewport(0, 0, width, height);
73346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
734c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glClearColor(0.1f, 0.2f, 0.3f, 1.f);
73546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
73646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
737c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
738c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_LoadIdentity(sProjection);
739c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Perspective(sProjection,
740c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                          45.f, (float)width / height, 0.5f, 150);
741c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
742c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_LoadIdentity(sModelView);
743c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
74446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glMatrixMode(GL_PROJECTION);
74546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glLoadIdentity();
74646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    gluPerspective(45, (float)width / height, 0.5f, 150);
74746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
74846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glMatrixMode(GL_MODELVIEW);
74946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glLoadIdentity();
750c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
75146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
75246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
75346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
75446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void configureLightAndMaterial()
75546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
756c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLfloat light0Position[] = { -4.f, 1.f, 1.f, 0 };
757c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLfloat light1Position[] = { 1.f, -2.f, -1.f, 0 };
758c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    GLfloat light2Position[] = { -1.f, 0, -4.f, 0 };
759c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
760c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
761c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Transform(sModelView,
762c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                        light0Position, light0Position + 1, light0Position + 2);
763c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Transform(sModelView,
764c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                        light1Position, light1Position + 1, light1Position + 2);
765c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Transform(sModelView,
766c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                        light2Position, light2Position + 1, light2Position + 2);
767c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
768c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    bindShaderProgram(sShaderLit.program);
769c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform3fv(sShaderLit.light_0_direction, 1, light0Position);
770c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform3fv(sShaderLit.light_1_direction, 1, light1Position);
771c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glUniform3fv(sShaderLit.light_2_direction, 1, light2Position);
772c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
773c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glLightfv(GL_LIGHT0, GL_POSITION, light0Position);
774c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glLightfv(GL_LIGHT1, GL_POSITION, light1Position);
775c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glLightfv(GL_LIGHT2, GL_POSITION, light2Position);
776c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
77746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glEnable(GL_COLOR_MATERIAL);
778c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
77946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
78046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
78146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
78246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void drawModels(float zScale)
78346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
78446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    const int translationScale = 9;
78546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    int x, y;
78646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
78746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    seedRandom(9);
78846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
789c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
790c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Scale(sModelView, 1.f, 1.f, zScale);
791c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
792c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glScalef(1.f, 1.f, zScale);
793c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
79446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
79546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    for (y = -5; y <= 5; ++y)
79646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
79746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        for (x = -5; x <= 5; ++x)
79846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        {
79946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            float buildingScale;
800c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
801c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            Matrix4x4 tmp;
802c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
80346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
80446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            int curShape = randomUInt() % SUPERSHAPE_COUNT;
80546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            buildingScale = sSuperShapeParams[curShape][SUPERSHAPE_PARAMS - 1];
806c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
807c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            Matrix4x4_Copy(tmp, sModelView);
808c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            Matrix4x4_Translate(sModelView, x * translationScale,
809c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                                y * translationScale, 0);
810c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            Matrix4x4_Rotate(sModelView, randomUInt() % 360, 0, 0, 1.f);
811c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            Matrix4x4_Scale(sModelView,
812c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo                            buildingScale, buildingScale, buildingScale);
81346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
814c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            drawGLObject(sSuperShapeObjects[curShape]);
815c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            Matrix4x4_Copy(sModelView, tmp);
816c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
81746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            glPushMatrix();
818c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            glTranslatef(x * translationScale, y * translationScale, 0);
819c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            glRotatef(randomUInt() % 360, 0, 0, 1.f);
820c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo            glScalef(buildingScale, buildingScale, buildingScale);
82146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
82246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            drawGLObject(sSuperShapeObjects[curShape]);
82346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo            glPopMatrix();
824c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
82546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        }
82646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
82746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
82846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    for (x = -2; x <= 2; ++x)
82946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
83046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        const int shipScale100 = translationScale * 500;
83146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        const int offs100 = x * shipScale100 + (sTick % shipScale100);
83246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        float offs = offs100 * 0.01f;
833c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
834c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        Matrix4x4 tmp;
835c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        Matrix4x4_Copy(tmp, sModelView);
836c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        Matrix4x4_Translate(sModelView, offs, -4.f, 2.f);
837c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        drawGLObject(sSuperShapeObjects[SUPERSHAPE_COUNT - 1]);
838c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        Matrix4x4_Copy(sModelView, tmp);
839c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        Matrix4x4_Translate(sModelView, -4.f, offs, 4.f);
840c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        Matrix4x4_Rotate(sModelView, 90.f, 0, 0, 1.f);
841c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        drawGLObject(sSuperShapeObjects[SUPERSHAPE_COUNT - 1]);
842c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        Matrix4x4_Copy(sModelView, tmp);
843c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
84446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glPushMatrix();
845c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glTranslatef(offs, -4.f, 2.f);
84646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        drawGLObject(sSuperShapeObjects[SUPERSHAPE_COUNT - 1]);
84746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glPopMatrix();
84846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glPushMatrix();
849c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glTranslatef(-4.f, offs, 4.f);
850c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo        glRotatef(90.f, 0, 0, 1.f);
85146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        drawGLObject(sSuperShapeObjects[SUPERSHAPE_COUNT - 1]);
85246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        glPopMatrix();
853c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
85446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
85546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
85646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
85746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo/* Following gluLookAt implementation is adapted from the
85846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * Mesa 3D Graphics library. http://www.mesa3d.org
85946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo */
86046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
86146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo	              GLfloat centerx, GLfloat centery, GLfloat centerz,
86246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo	              GLfloat upx, GLfloat upy, GLfloat upz)
86346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
864c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
865c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4 m;
866c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
86746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLfloat m[16];
868c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
86946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLfloat x[3], y[3], z[3];
87046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    GLfloat mag;
87146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
87246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* Make rotation matrix */
87346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
87446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* Z vector */
87546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    z[0] = eyex - centerx;
87646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    z[1] = eyey - centery;
87746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    z[2] = eyez - centerz;
87846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    mag = (float)sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
87946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (mag) {			/* mpichler, 19950515 */
88046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        z[0] /= mag;
88146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        z[1] /= mag;
88246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        z[2] /= mag;
88346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
88446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
88546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* Y vector */
88646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    y[0] = upx;
88746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    y[1] = upy;
88846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    y[2] = upz;
88946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
89046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* X vector = Y cross Z */
89146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    x[0] = y[1] * z[2] - y[2] * z[1];
89246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    x[1] = -y[0] * z[2] + y[2] * z[0];
89346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    x[2] = y[0] * z[1] - y[1] * z[0];
89446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
89546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* Recompute Y = Z cross X */
89646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    y[0] = z[1] * x[2] - z[2] * x[1];
89746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    y[1] = -z[0] * x[2] + z[2] * x[0];
89846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    y[2] = z[0] * x[1] - z[1] * x[0];
89946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
90046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* mpichler, 19950515 */
90146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* cross product gives area of parallelogram, which is < 1.0 for
90246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     * non-perpendicular unit-length vectors; so normalize x, y here
90346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo     */
90446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
90546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    mag = (float)sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
90646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (mag) {
90746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        x[0] /= mag;
90846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        x[1] /= mag;
90946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        x[2] /= mag;
91046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
91146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
91246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    mag = (float)sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
91346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (mag) {
91446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        y[0] /= mag;
91546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        y[1] /= mag;
91646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        y[2] /= mag;
91746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
91846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
919c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
920c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#define M(row, col) m[col*4 + row]
92146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(0, 0) = x[0];
92246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(0, 1) = x[1];
92346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(0, 2) = x[2];
92446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(0, 3) = 0.0;
92546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(1, 0) = y[0];
92646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(1, 1) = y[1];
92746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(1, 2) = y[2];
92846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(1, 3) = 0.0;
92946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(2, 0) = z[0];
93046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(2, 1) = z[1];
93146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(2, 2) = z[2];
93246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(2, 3) = 0.0;
93346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(3, 0) = 0.0;
93446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(3, 1) = 0.0;
93546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(3, 2) = 0.0;
93646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    M(3, 3) = 1.0;
93746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo#undef M
938c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
939c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Multiply(sModelView, m, sModelView);
940c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
941c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Translate(sModelView, -eyex, -eyey, -eyez);
942c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
943c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#define M(row, col)  m[col*4 + row]
944c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(0, 0) = x[0];
945c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(0, 1) = x[1];
946c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(0, 2) = x[2];
947c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(0, 3) = 0.0;
948c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(1, 0) = y[0];
949c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(1, 1) = y[1];
950c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(1, 2) = y[2];
951c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(1, 3) = 0.0;
952c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(2, 0) = z[0];
953c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(2, 1) = z[1];
954c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(2, 2) = z[2];
955c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(2, 3) = 0.0;
956c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(3, 0) = 0.0;
957c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(3, 1) = 0.0;
958c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(3, 2) = 0.0;
959c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    M(3, 3) = 1.0;
960c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#undef M
961c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
962c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glMultMatrixf(m);
96346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
96446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    /* Translate Eye to Origin */
965c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    glTranslatef(-eyex, -eyey, -eyez);
966c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
96746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
96846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
96946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mostatic void camTrack()
97046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
97146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    float lerp[5];
97246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    float eX, eY, eZ, cX, cY, cZ;
97346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    float trackPos;
97446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    CAMTRACK *cam;
97546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    long currentCamTick;
97646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    int a;
97746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
97846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (sNextCamTrackStartTick <= sTick)
97946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
98046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        ++sCurrentCamTrack;
98146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        sCurrentCamTrackStartTick = sNextCamTrackStartTick;
98246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
98346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    sNextCamTrackStartTick = sCurrentCamTrackStartTick +
98446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo                             sCamTracks[sCurrentCamTrack].len * CAMTRACK_LEN;
98546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
98646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    cam = &sCamTracks[sCurrentCamTrack];
98746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    currentCamTick = sTick - sCurrentCamTrackStartTick;
98846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    trackPos = (float)currentCamTick / (CAMTRACK_LEN * cam->len);
98946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
99046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    for (a = 0; a < 5; ++a)
99146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        lerp[a] = (cam->src[a] + cam->dest[a] * trackPos) * 0.01f;
99246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
99346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (cam->dist)
99446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
99546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        float dist = cam->dist * 0.1f;
99646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        cX = lerp[0];
99746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        cY = lerp[1];
99846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        cZ = lerp[2];
99946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        eX = cX - (float)cos(lerp[3]) * dist;
100046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        eY = cY - (float)sin(lerp[3]) * dist;
100146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        eZ = cZ - lerp[4];
100246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
100346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    else
100446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
100546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        eX = lerp[0];
100646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        eY = lerp[1];
100746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        eZ = lerp[2];
100846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        cX = eX + (float)cos(lerp[3]);
100946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        cY = eY + (float)sin(lerp[3]);
101046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        cZ = eZ + lerp[4];
101146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
101246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    gluLookAt(eX, eY, eZ, cX, cY, cZ, 0, 0, 1);
101346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
101446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
101546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
101646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo// Called from the app framework.
101746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo/* The tick is current time in milliseconds, width and height
101846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo * are the image dimensions to be rendered.
101946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo */
102046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Movoid appRender(long tick, int width, int height)
102146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo{
1022c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
1023c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4 tmp;
1024c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES
1025c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo
102646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (sStartTick == 0)
102746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        sStartTick = tick;
102846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (!gAppAlive)
102946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        return;
103046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
103146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Actual tick value is "blurred" a little bit.
103246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    sTick = (sTick + tick - sStartTick) >> 1;
103346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
103446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Terminate application after running through the demonstration once.
103546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    if (sTick >= RUN_LENGTH)
103646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    {
103746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        gAppAlive = 0;
103846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo        return;
103946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    }
104046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
104146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Prepare OpenGL ES for rendering of the frame.
104246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    prepareFrame(width, height);
104346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
104446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Update the camera position and set the lookat.
104546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    camTrack();
104646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
104746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Configure environment.
104846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    configureLightAndMaterial();
104946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
105046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Draw the reflection by drawing models with negated Z-axis.
1051c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#ifdef SAN_ANGELES_OBSERVATION_GLES
1052c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Copy(tmp, sModelView);
1053c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    drawModels(-1);
1054c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo    Matrix4x4_Copy(sModelView, tmp);
1055c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#else  // !SAN_ANGELES_OBSERVATION_GLES
105646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glPushMatrix();
105746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    drawModels(-1);
105846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    glPopMatrix();
1059c8ab85b5ab0cf6bc500d8b31cfcb199a7107c8e8Zhenyao Mo#endif  // SAN_ANGELES_OBSERVATION_GLES | !SAN_ANGELES_OBSERVATION_GLES
106046645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
106146645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Blend the ground plane to the window.
106246645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    drawGroundPlane();
106346645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
106446645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Draw all the models normally.
106546645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    drawModels(1);
106646645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo
106746645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    // Draw fade quad over whole window (when changing cameras).
106846645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo    drawFadeQuad();
106946645d3bc30237d5be6552a255c9100fd6d1c5c3Zhenyao Mo}
10704545a8e20f4025c2d34bee31f38e45119ef40b22Zhenyao Mo
1071