demo.c 23 KB

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