Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1067 lines
25 KiB

  1. extern "C" {
  2. #include <windows.h>
  3. #include <GL/glaux.h>
  4. #include <GL/glu.h>
  5. #include <GL/gl.h>
  6. }
  7. #ifdef GLX_MOTIF
  8. #include <GL/glx.h>
  9. #endif
  10. #include <math.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <malloc.h>
  14. #include "Unitdisk.hxx"
  15. #include "scene.hxx"
  16. const GLfloat I[16] = {
  17. 1, 0, 0, 0,
  18. 0, 1, 0, 0,
  19. 0, 0, 1, 0,
  20. 0, 0, 0, 1
  21. };
  22. Color white;
  23. Color black;
  24. const double M_2PI = 2.0 * M_PI;
  25. const float scene_fudge = .000001;
  26. // Lights are native to the xz plane and are rotated into position -
  27. // shadows and refraction will not have to be changed if lights are
  28. // just rotating about the z axis
  29. light lights[] = {
  30. {{1, 0, 0, 1}, {0, 0, 0, 0}, {1, 0, 0, 0},
  31. {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
  32. "Red", 1},
  33. {{0, 1, 0, 1}, {0, 0, 0, 0}, {0, 1, 0, 0},
  34. {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
  35. "Green", 1},
  36. {{0, 0, 1, 1}, {0, 0, 0, 0}, {0, 0, 1, 0},
  37. {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
  38. "Blue", 1}
  39. };
  40. GLfloat light_init_position[nlights][4] = {
  41. {1.5, 0, 2.5, 1},
  42. {1, 0, 3, 1},
  43. {2, 0, 3, 1}
  44. };
  45. GLfloat light_init_rotation[nlights] = {135, 0, 90};
  46. GLfloat light_rotation[nlights];
  47. Color world_ambient(.25, .25, .25);
  48. GLfloat index = indices[def_refraction_index].index;
  49. GLfloat square_ambient[4] = {.25, .25, .25, 1};
  50. GLfloat square_diffuse[4] = {1, 1, 1, 1};
  51. GLfloat square_specular[4] = {0, 0, 0, 1};
  52. const GLfloat fov = 45.0;
  53. GLfloat aspect = 1.0;
  54. GLfloat eyep[3] = {-6, 0, 6};
  55. GLfloat lookp[3] = {0, 0, 1};
  56. #ifdef GLX_MOTIF
  57. static GLXContext glx_context;
  58. #endif
  59. const int max_args = 20;
  60. static int list_square;
  61. static int lists_shadows;
  62. static int lists_refraction;
  63. static int lists_lights = 5;
  64. static int list_sphere = 4;
  65. static int list_spheredisk = 9;
  66. static int list_lights_on = 6;
  67. static int list_lights_off = 7;
  68. static int list_light_draw = 8;
  69. int draw_square = 1;
  70. int draw_shadows = 1;
  71. int draw_refraction = 1;
  72. int draw_sphere = 1;
  73. int draw_lights = 1;
  74. int draw_texture = 0;
  75. int possible_divisions[] = {10, 20, 30, 40};
  76. // Sphere is stored as floats - more efficient
  77. GLfloat *spherepts = NULL;
  78. int nspherepts = 0;
  79. int spherediv = 0;
  80. Point sphere_position = {0, 0, 1, 1};
  81. GLfloat sphere_size = .5;
  82. const GLfloat sphere_ambient[4] = {0, 0, 0, 0};
  83. const GLfloat sphere_specular[4] = {0, 0, 0, 0};
  84. Unitdisk sphere_disk;
  85. static void sphere_build();
  86. static void sphere_list_init();
  87. static void sphere_draw();
  88. static void square_list_init();
  89. static void lights_init_onoff();
  90. static void lights_init_position();
  91. static void lights_init_position(int i);
  92. static void lights_list_init();
  93. static void lights_list_init(int n);
  94. static void light_draw_list_init();
  95. Unitdisk disks[nlights];
  96. int diskdiv = possible_divisions[def_divisions_index];
  97. static void disk_build();
  98. static void disk_build(int disk);
  99. Unitdisk shadows[nlights];
  100. static void shadow_list_init();
  101. static void shadow_list_init(int n);
  102. static void shadow_draw(int n);
  103. Unitdisk refraction[nlights];
  104. static void refraction_list_init();
  105. static void refraction_list_init(int n);
  106. static void shadow_refraction_full_build();
  107. static void shadow_refraction_full_build(int n);
  108. void scene_init();
  109. #ifdef MYDEBUG
  110. void lists_init();
  111. void lights_init();
  112. int lights_move(int light, float dr, float dphi, float dtheta,
  113. int update);
  114. void lights_move_update(int light, int dr, int dphi, int dtheta);
  115. #else
  116. static void lists_init();
  117. static void lights_init();
  118. static int lights_move(int light, float dr, float dphi, float dtheta,
  119. int update);
  120. static void lights_move_update(int light, int dr, int dphi, int dtheta);
  121. #endif
  122. void scene_draw();
  123. void texture_init();
  124. AUX_RGBImageRec *teximage = NULL;
  125. inline float sign(float a)
  126. {
  127. // This is badly written so let's not call it too often, 'k?
  128. return (a > 0) ? (float)1 : (a < 0) ? (float) -1 : (float) 0;
  129. }
  130. inline double degrees(double a)
  131. {
  132. return (a * 180.0 / M_PI);
  133. }
  134. inline double radians(double a)
  135. {
  136. return (a * M_PI / 180.0);
  137. }
  138. inline double degrees_clamp(double a)
  139. {
  140. while (a < 0.0) a += 360.0;
  141. while (a > 360.0) a -= 360.0;
  142. return a;
  143. }
  144. inline double radians_clamp(double a)
  145. {
  146. while (a < 0.0) a += M_2PI;
  147. while (a > M_2PI) a -= M_2PI;
  148. return a;
  149. }
  150. void scene_init()
  151. {
  152. int i;
  153. white.c[0] = white.c[1] = white.c[2] = white.c[3] = 1;
  154. black.c[0] = black.c[1] = black.c[2] = 0;
  155. black.c[3] = 1;
  156. lists_init();
  157. for (i = 0; i < nlights; i++) {
  158. lights[i].pos = light_init_position[i];
  159. light_rotation[i] = light_init_rotation[i];
  160. lights_init_position(i);
  161. }
  162. divisions_change(possible_divisions[def_divisions_index]);
  163. lights_init_onoff();
  164. lights_init();
  165. lights_init_position();
  166. texture_init();
  167. glClearStencil(0);
  168. // This is for profiling
  169. // exit(0);
  170. }
  171. static void scene_project()
  172. {
  173. glMatrixMode(GL_PROJECTION);
  174. gluPerspective(fov, aspect, 0.01, 20.0);
  175. gluLookAt(eyep[0], eyep[1], eyep[2], lookp[0], lookp[1], lookp[2],
  176. 1, 0, 0);
  177. }
  178. static void scene_rasterize()
  179. {
  180. int i;
  181. glLoadName(name_square);
  182. if (draw_square) {
  183. if (draw_texture) glEnable(GL_TEXTURE_2D);
  184. glCallList(list_square);
  185. glDisable(GL_TEXTURE_2D);
  186. }
  187. if (draw_shadows)
  188. for (i = 0; i < nlights; i++)
  189. if (lights[i].on) {
  190. glPushMatrix();
  191. glRotatef(-light_rotation[i], 0, 0, 1);
  192. glCallList(lists_shadows + i);
  193. glPopMatrix();
  194. }
  195. if (draw_refraction)
  196. for (i = 0; i < nlights; i++)
  197. if (lights[i].on) {
  198. glPushMatrix();
  199. glRotatef(-light_rotation[i], 0, 0, 1);
  200. glCallList(lists_refraction + i);
  201. glPopMatrix();
  202. }
  203. glLoadName(name_sphere);
  204. /* Drawing the sphere here makes the sphere visible through itself when we
  205. * do the refraction redraw hack -- for now, just don't draw it */
  206. // if (draw_sphere) glCallList(list_sphere);
  207. for (i = 0; i < nlights; i++)
  208. if (draw_lights) glCallList(lists_lights + i);
  209. }
  210. /* This draws an image of the scene seen through the sphere */
  211. static void scene_draw_refracted()
  212. {
  213. int i;
  214. if (!draw_sphere) return;
  215. /* Draw an image of the sphere into the stencil plane -
  216. * must do this every time in case the lights have moved in front
  217. * of it */
  218. glEnable(GL_STENCIL_TEST);
  219. glClearStencil(0);
  220. glClear(GL_STENCIL_BUFFER_BIT);
  221. glStencilFunc(GL_ALWAYS, 0x1, 0x1);
  222. glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
  223. glColorMask(0, 0, 0, 0);
  224. glMatrixMode(GL_PROJECTION);
  225. glLoadIdentity();
  226. scene_project();
  227. glEnable(GL_DEPTH_TEST);
  228. glEnable(GL_CULL_FACE);
  229. glCallList(list_sphere);
  230. glDisable(GL_CULL_FACE);
  231. glDisable(GL_DEPTH_TEST);
  232. glColorMask(1, 1, 1, 1);
  233. /* Set up a transform with a wider field of view - this is inaccurate
  234. * but I don't have time to do it right */
  235. glMatrixMode(GL_PROJECTION);
  236. glLoadIdentity();
  237. gluPerspective(fov * index, aspect, 0.01, 20.0);
  238. gluLookAt(eyep[0], eyep[1], eyep[2], lookp[0], lookp[1], lookp[2],
  239. 1, 0, 0);
  240. glMatrixMode(GL_MODELVIEW);
  241. glLoadIdentity();
  242. /* Set up the stencil stuff which will be used to draw the image */
  243. glStencilFunc(GL_NOTEQUAL, 0x0, 0xffffffff);
  244. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  245. /* Draw the image, gambling that we'll never see anything but the
  246. * floor through the table */
  247. glLoadName(name_sphere);
  248. if (draw_texture) glEnable(GL_TEXTURE_2D);
  249. if (draw_square) glCallList(list_square);
  250. if (draw_shadows)
  251. for (i = 0; i < nlights; i++)
  252. if (lights[i].on) {
  253. glPushMatrix();
  254. glRotatef(-light_rotation[i], 0, 0, 1);
  255. glCallList(lists_shadows + i);
  256. glPopMatrix();
  257. }
  258. if (draw_refraction)
  259. for (i = 0; i < nlights; i++)
  260. if (lights[i].on) {
  261. glPushMatrix();
  262. glRotatef(-light_rotation[i], 0, 0, 1);
  263. glCallList(lists_refraction + i);
  264. glPopMatrix();
  265. }
  266. glDisable(GL_TEXTURE_2D);
  267. /* Draw the sphere to make it look like it
  268. * has some substance */
  269. glMatrixMode(GL_PROJECTION);
  270. glLoadIdentity();
  271. scene_project();
  272. glCallList(list_spheredisk);
  273. glDisable(GL_STENCIL_TEST);
  274. }
  275. void scene_draw()
  276. {
  277. glMatrixMode(GL_PROJECTION);
  278. glLoadIdentity();
  279. glMatrixMode(GL_MODELVIEW);
  280. glLoadIdentity();
  281. scene_project();
  282. /* Should draw an image of the square into the stencil buffer
  283. * to make sure that refractions which are not on the square do not get
  284. * drawn, but it can wait. */
  285. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  286. scene_rasterize();
  287. scene_draw_refracted();
  288. }
  289. const int pick_maxz = 0xffffffff;
  290. int scene_pick(GLdouble x, GLdouble y)
  291. {
  292. GLuint buffer[128];
  293. GLint vp[4], nhits, nnames;
  294. GLuint minz, hit = name_background;
  295. GLint i, j;
  296. glMatrixMode(GL_MODELVIEW);
  297. glLoadIdentity();
  298. glMatrixMode(GL_PROJECTION);
  299. glLoadIdentity();
  300. glGetIntegerv(GL_VIEWPORT, vp);
  301. glSelectBuffer(128, buffer);
  302. glRenderMode(GL_SELECT);
  303. // Where is this supposed to go, anyway?
  304. gluPickMatrix(x, vp[3] - y, 1, 1, vp);
  305. scene_project();
  306. glMatrixMode(GL_MODELVIEW);
  307. glInitNames();
  308. glPushName(name_background);
  309. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  310. scene_rasterize();
  311. glFlush();
  312. nhits = glRenderMode(GL_RENDER);
  313. minz = pick_maxz;
  314. for (i = j = 0; j < nhits; j++) {
  315. nnames = buffer[i];
  316. i++;
  317. if (buffer[i] < minz) {
  318. minz = buffer[i];
  319. hit = buffer[i + 1 + nnames];
  320. }
  321. i++;
  322. i += nnames + 1;
  323. }
  324. if (minz == pick_maxz) return name_background;
  325. else return hit;
  326. }
  327. void scene_reset_lights()
  328. {
  329. int i;
  330. for (i = 0; i < nlights; i++) {
  331. lights[i].pos = light_init_position[i];
  332. light_rotation[i] = light_init_rotation[i];
  333. }
  334. lights_init_position();
  335. lights_list_init();
  336. }
  337. static void square_list_init()
  338. {
  339. GLfloat x, y, inc;
  340. int i, j;
  341. glNewList(list_square, GL_COMPILE);
  342. glLoadName(name_square);
  343. glNormal3f(0, 0, 1);
  344. glEnable(GL_LIGHTING);
  345. glCallList(list_lights_on);
  346. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, square_ambient);
  347. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, square_diffuse);
  348. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, square_specular);
  349. inc = (GLfloat) (10.0 / diskdiv);
  350. glEnable(GL_CULL_FACE);
  351. for (i = 0, y = -5.0; i < diskdiv; i++, y += inc) {
  352. glBegin(GL_TRIANGLE_STRIP);
  353. for (j = 0, x = -5.0; j <= diskdiv; j++, x += inc) {
  354. glTexCoord2f(x, y + inc);
  355. glVertex2f(x, y + inc);
  356. glTexCoord2f(x, y);
  357. glVertex2f(x, y);
  358. }
  359. glEnd();
  360. }
  361. glDisable(GL_CULL_FACE);
  362. glCallList(list_lights_off);
  363. glDisable(GL_LIGHTING);
  364. glEndList();
  365. }
  366. static void spheredisk_list_init()
  367. {
  368. glNewList(list_spheredisk, GL_COMPILE);
  369. glEnable(GL_BLEND);
  370. glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
  371. glEnable(GL_LIGHTING);
  372. glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
  373. glEnable(GL_COLOR_MATERIAL);
  374. glMaterialfv(GL_AMBIENT, GL_FRONT_AND_BACK, sphere_ambient);
  375. glMaterialfv(GL_SPECULAR, GL_FRONT_AND_BACK, sphere_specular);
  376. glCallList(list_lights_on);
  377. sphere_disk.draw();
  378. glCallList(list_lights_off);
  379. glDisable(GL_COLOR_MATERIAL);
  380. glDisable(GL_LIGHTING);
  381. glDisable(GL_BLEND);
  382. glEndList();
  383. }
  384. void lights_onoff(int light, int val)
  385. {
  386. lights[light].on = val;
  387. lights_init_onoff();
  388. lights_list_init(light);
  389. square_list_init();
  390. }
  391. void refraction_change(GLfloat refraction)
  392. {
  393. if (refraction == index) return;
  394. index = refraction;
  395. shadow_refraction_full_build();
  396. refraction_list_init();
  397. }
  398. void divisions_change(int divisions)
  399. {
  400. Point eye, look;
  401. if (divisions != spherediv) {
  402. spherediv = divisions;
  403. light_draw_list_init();
  404. lights_list_init();
  405. sphere_disk.set_divisions(spherediv, spherediv);
  406. sphere_disk.fill_points();
  407. sphere_disk.set_colors(white);
  408. sphere_disk.scale_alpha_by_z();
  409. eye = eyep;
  410. look = lookp;
  411. sphere_disk.face_direction((eye - look).unit());
  412. sphere_disk.copy_normals_from_points();
  413. sphere_disk.scale_translate(sphere_size, sphere_position);
  414. sphere_build();
  415. sphere_list_init();
  416. diskdiv = divisions;
  417. disk_build();
  418. shadow_refraction_full_build();
  419. square_list_init();
  420. spheredisk_list_init();
  421. shadow_list_init();
  422. refraction_list_init();
  423. }
  424. }
  425. int scene_move(int name, float dr, float dphi, float dtheta, int update)
  426. {
  427. switch(name) {
  428. case name_background:
  429. return 0;
  430. case name_square:
  431. return 0;
  432. case name_sphere:
  433. return 0;
  434. default:
  435. if (name < name_lights || name > name_lights + nlights) return 0;
  436. return lights_move(name - name_lights, dr, dphi, dtheta, update);
  437. }
  438. }
  439. void scene_move_update(int name, int dr, int dphi, int dtheta)
  440. {
  441. switch(name) {
  442. case name_background:
  443. break;
  444. case name_square:
  445. break;
  446. case name_sphere:
  447. break;
  448. default:
  449. if (name < name_lights || name > name_lights + nlights) break;
  450. lights_move_update(name - name_lights, dr, dphi, dtheta);
  451. break;
  452. }
  453. }
  454. #ifdef MYDEBUG
  455. void lights_init_onoff()
  456. #else
  457. static void lights_init_onoff()
  458. #endif
  459. {
  460. int i;
  461. glNewList(list_lights_on, GL_COMPILE);
  462. for (i = 0; i < nlights; i++)
  463. if (lights[i].on) glEnable(GL_LIGHT0 + i);
  464. else glDisable(GL_LIGHT0 + i);
  465. glEndList();
  466. glNewList(list_lights_off, GL_COMPILE);
  467. for (i = 0; i < nlights; i++) glDisable(GL_LIGHT0 + i);
  468. glEndList();
  469. }
  470. #ifdef MYDEBUG
  471. void lights_init_position()
  472. #else
  473. static void lights_init_position()
  474. #endif
  475. {
  476. int i;
  477. for (i = 0; i < nlights; i++) lights_init_position(i);
  478. }
  479. static void lights_init_position(int i)
  480. {
  481. Point l, d;
  482. glMatrixMode(GL_MODELVIEW);
  483. glLoadIdentity();
  484. glMatrixMode(GL_PROJECTION);
  485. glLoadIdentity();
  486. l = lights[i].pos;
  487. l.pt[0] = (GLfloat)(lights[i].pos.pt[0] * cos((double)radians(light_rotation[i])));
  488. l.pt[1] = (GLfloat)(lights[i].pos.pt[0] * -sin((double)radians(light_rotation[i])));
  489. d = (sphere_position - l).unit();
  490. glLightfv(GL_LIGHT0 + i, GL_POSITION, l.pt);
  491. glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, d.pt);
  492. }
  493. static void lights_list_init()
  494. {
  495. int i;
  496. for (i = 0; i < nlights; i++) lights_list_init(i);
  497. }
  498. static void lights_list_init(int n)
  499. {
  500. Color c;
  501. glNewList(lists_lights + n, GL_COMPILE);
  502. if (lights[n].on) {
  503. glLoadName(name_lights + n);
  504. glEnable(GL_DEPTH_TEST);
  505. glEnable(GL_LIGHTING);
  506. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
  507. glCallList(list_lights_on);
  508. c = lights[n].diffuse;
  509. glMaterialfv(GL_BACK, GL_AMBIENT, c.c);
  510. glMaterialfv(GL_BACK, GL_DIFFUSE, black.c);
  511. glMaterialfv(GL_BACK, GL_SPECULAR, black.c);
  512. glMaterialfv(GL_FRONT, GL_AMBIENT, (c * .75).c);
  513. glMaterialfv(GL_FRONT, GL_DIFFUSE, white.c);
  514. glMaterialfv(GL_FRONT, GL_SPECULAR, white.c);
  515. glMatrixMode(GL_MODELVIEW);
  516. glPushMatrix();
  517. glRotatef(-light_rotation[n], 0, 0, 1);
  518. glTranslatef(lights[n].pos.pt[0], lights[n].pos.pt[1],
  519. lights[n].pos.pt[2]);
  520. glRotatef((GLfloat)-degrees(atan2((double)(lights[n].pos.pt[2] - sphere_position.pt[2]),
  521. (double)(lights[n].pos.pt[0]))), 0, 1, 0);
  522. glCallList(list_light_draw);
  523. glPopMatrix();
  524. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
  525. glDisable(GL_LIGHTING);
  526. glCallList(list_lights_off);
  527. glDisable(GL_DEPTH_TEST);
  528. } else {
  529. /* 5.0.1 for Elans seems to object strongly to replacing
  530. * empty display lists, so will put a placeholder command
  531. * in here */
  532. glColor3f(0, 0, 0);
  533. }
  534. glEndList();
  535. }
  536. static void light_draw_list_init()
  537. {
  538. float c, s;
  539. int t;
  540. glNewList(list_light_draw, GL_COMPILE);
  541. glEnable(GL_NORMALIZE);
  542. glMatrixMode(GL_MODELVIEW);
  543. glPushMatrix();
  544. glScalef(.25, .15, .15);
  545. glBegin(GL_QUAD_STRIP);
  546. for (t = 0; t <= spherediv; t++) {
  547. c = (float) cos((double)(M_2PI * (float)t / (float)spherediv));
  548. s = (float) sin((double)(M_2PI * (float)t / (float)spherediv));
  549. glNormal3f((GLfloat).25, (GLfloat)(.968*s), (GLfloat)(.968*c));
  550. glVertex3f((GLfloat)0, (GLfloat)s, (GLfloat)c);
  551. glVertex3f((GLfloat)1, (GLfloat)(.75*s), (GLfloat)(.75*c));
  552. }
  553. glEnd();
  554. glNormal3f(1, 0, 0);
  555. glBegin(GL_TRIANGLE_STRIP);
  556. for (t = 0; t <= spherediv; t++) {
  557. c = (float)cos((double)(M_2PI * (float)t / (float)spherediv));
  558. s = (float)sin((double)(M_2PI * (float)t / (float)spherediv));
  559. glVertex3f((GLfloat)1, (GLfloat)(.75*s), (GLfloat)(.75*c));
  560. glVertex3f(1, 0, 0);
  561. }
  562. glEnd();
  563. glPopMatrix();
  564. glDisable(GL_NORMALIZE);
  565. glEndList();
  566. }
  567. #ifdef MYDEBUG
  568. void lights_init()
  569. #else
  570. static void lights_init()
  571. #endif
  572. {
  573. int i;
  574. for (i = 0; i < nlights; i++) {
  575. glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lights[i].diffuse);
  576. glLightfv(GL_LIGHT0 + i, GL_SPECULAR, black.c);
  577. glLightfv(GL_LIGHT0 + i, GL_AMBIENT, black.c);
  578. glLightf(GL_LIGHT0 + i, GL_SPOT_EXPONENT, 4);
  579. glLightf(GL_LIGHT0 + i, GL_SPOT_CUTOFF, 90);
  580. }
  581. glLightfv(GL_LIGHT0 + nlights, GL_DIFFUSE, black.c);
  582. glLightfv(GL_LIGHT0 + nlights, GL_SPECULAR, black.c);
  583. glLightfv(GL_LIGHT0 + nlights, GL_AMBIENT, world_ambient.c);
  584. glEnable(GL_LIGHT0 + nlights);
  585. /* GL_LIGHT0 + nlights + 1 willl eventually be used to draw the
  586. * refractions - stay tuned. */
  587. glLightfv(GL_LIGHT0 + nlights + 1, GL_DIFFUSE, black.c);
  588. glLightfv(GL_LIGHT0 + nlights + 1, GL_SPECULAR, black.c);
  589. glLightfv(GL_LIGHT0 + nlights + 1, GL_AMBIENT, white.c);
  590. }
  591. #ifdef MYDEBUG
  592. int lights_move(int light, float dr, float dphi, float dtheta,
  593. #else
  594. static int lights_move(int light, float dr, float dphi, float dtheta,
  595. #endif
  596. int update)
  597. {
  598. float cphi, sphi, x, y;
  599. Point l, dl;
  600. if (!(dr || dphi || dtheta)) return 0;
  601. l = lights[light].pos - sphere_position;
  602. if (dr) {
  603. dl = l + l*dr;
  604. if (dl.mag() > sphere_size) l = dl;
  605. }
  606. if (dphi) {
  607. cphi = (float)cos((double)dphi);
  608. sphi = (float)sin((double)dphi);
  609. y = -l.pt[0]*sphi + l.pt[2]*cphi;
  610. /* This hack keeps with light from getting below the sphere -
  611. * the projection sections would completely get messed up if this ever
  612. * happened - sphere_size is multiplied by two as a fudge factor*/
  613. if (y < 2.0*sphere_size) {
  614. dphi = (float)atan2((double)(l.pt[2] - 2.0*sphere_size), (double)l.pt[0]);
  615. cphi = (float)cos((double)dphi);
  616. sphi = (float)sin((double)dphi);
  617. }
  618. x = l.pt[0];
  619. l.pt[0] = x*cphi + l.pt[2]*sphi;
  620. l.pt[2] = -x*sphi + l.pt[2]*cphi;
  621. }
  622. if (dtheta) {
  623. light_rotation[light] += (GLfloat)degrees((double)dtheta);
  624. light_rotation[light] = (GLfloat)degrees_clamp((double)light_rotation[light]);
  625. }
  626. lights[light].pos = l + sphere_position;
  627. lights[light].pos.pt[3] = 1;
  628. lights_init_position(light);
  629. lights_list_init(light);
  630. if (update) lights_move_update(light, dr ? 1 : 0, dphi ? 1 : 0,
  631. dtheta ? 1 : 0);
  632. return 1;
  633. }
  634. #ifdef MYDEBUG
  635. void lights_move_update(int light, int dr, int dphi,
  636. #else
  637. static void lights_move_update(int light, int dr, int dphi,
  638. #endif
  639. int dtheta)
  640. {
  641. if (dr) {
  642. disk_build(light);
  643. shadow_refraction_full_build(light);
  644. shadow_list_init(light);
  645. refraction_list_init(light);
  646. } else if (dphi) {
  647. shadow_refraction_full_build(light);
  648. shadow_list_init(light);
  649. refraction_list_init(light);
  650. } else if (dtheta) {
  651. }
  652. }
  653. #ifdef MYDEBUG
  654. int get_lists(int size)
  655. #else
  656. static int get_lists(int size)
  657. #endif
  658. {
  659. int i;
  660. i = glGenLists(size);
  661. if (size && !i) {
  662. fprintf(stderr, "Unable to allocate display lists.\n");
  663. exit(1);
  664. }
  665. return i;
  666. }
  667. #ifdef MYDEBUG
  668. void lists_init()
  669. #else
  670. static void lists_init()
  671. #endif
  672. {
  673. list_square = get_lists(1);
  674. lists_shadows = get_lists(nlights);
  675. lists_refraction = get_lists(nlights);
  676. lists_lights = get_lists(nlights);
  677. list_sphere = get_lists(1);
  678. list_spheredisk = get_lists(1);
  679. list_lights_on = get_lists(1);
  680. list_lights_off = get_lists(1);
  681. list_light_draw = get_lists(1);
  682. // sphere_build();
  683. }
  684. static inline int sphere_npoints()
  685. {
  686. return (spherediv+1)*spherediv*3;
  687. }
  688. void sphere_build()
  689. {
  690. int nspherepts;
  691. int r, t, index;
  692. float c, s;
  693. delete spherepts;
  694. nspherepts = sphere_npoints();
  695. if (nspherepts == 0) return;
  696. spherepts = new GLfloat[nspherepts];
  697. index = 0;
  698. for (r = 0; r <= spherediv; r++) {
  699. spherepts[index++] = (GLfloat)sin((double)(M_PI * (float)r / (float)spherediv));
  700. spherepts[index++] = 0;
  701. spherepts[index++] = (GLfloat)-cos((double)(M_PI * (float)r / (float)spherediv));
  702. }
  703. for (t = 1; t < spherediv; t++) {
  704. c = (float)cos((double)(2.0 * M_PI * (float)t / (float)spherediv));
  705. s = (float)sin((double)(2.0 * M_PI * (float)t / (float)spherediv));
  706. for (r = 0; r <= spherediv; r++) {
  707. spherepts[index++] = c*spherepts[r*3];
  708. spherepts[index++] = s*spherepts[r*3];
  709. spherepts[index++] = spherepts[r*3 + 2];
  710. }
  711. }
  712. }
  713. void sphere_list_init()
  714. {
  715. glNewList(list_sphere, GL_COMPILE);
  716. sphere_disk.draw_by_perimeter();
  717. glEndList();
  718. }
  719. void sphere_draw()
  720. {
  721. int r, t, p1, p2;
  722. for (t = 1; t < spherediv; t++) {
  723. glBegin(GL_QUAD_STRIP);
  724. p1 = (t - 1) * (spherediv + 1);
  725. p2 = t * (spherediv + 1);
  726. for (r = 0; r <= spherediv; r++, p1++, p2++) {
  727. glNormal3fv(&spherepts[p1*3]);
  728. glVertex3fv(&spherepts[p1*3]);
  729. glNormal3fv(&spherepts[p2*3]);
  730. glVertex3fv(&spherepts[p2*3]);
  731. }
  732. glEnd();
  733. }
  734. glBegin(GL_QUAD_STRIP);
  735. p1 = (spherediv + 1) * (spherediv - 1);
  736. p2 = 0;
  737. for (r = 0; r <= spherediv; r++, p1++, p2++) {
  738. glNormal3fv(&spherepts[p1*3]);
  739. glVertex3fv(&spherepts[p1*3]);
  740. glNormal3fv(&spherepts[p2*3]);
  741. glVertex3fv(&spherepts[p2*3]);
  742. }
  743. glEnd();
  744. }
  745. static void disk_build()
  746. {
  747. int i;
  748. for (i = 0; i < nlights; i++) disk_build(i);
  749. }
  750. static void disk_build(int disk)
  751. {
  752. Point light;
  753. light = lights[disk].pos;
  754. disks[disk].free_points_normals();
  755. disks[disk].free_colors();
  756. disks[disk].set_divisions(diskdiv, diskdiv);
  757. disks[disk].set_angle((float)(2.0 *
  758. acos((double)(sphere_size / light.dist(sphere_position)))));
  759. disks[disk].fill_points();
  760. }
  761. static void shadow_list_init()
  762. {
  763. int i;
  764. for (i = 0; i < nlights; i++) shadow_list_init(i);
  765. }
  766. static void shadow_list_init(int n)
  767. {
  768. Color c(square_ambient[0], square_ambient[1], square_ambient[2]);
  769. c *= world_ambient;
  770. glNewList(lists_shadows + n, GL_COMPILE);
  771. glColorMask(lights[n].shadow_mask[0], lights[n].shadow_mask[1],
  772. lights[n].shadow_mask[2], lights[n].shadow_mask[3]);
  773. glDisable(GL_DEPTH_TEST);
  774. glColor3fv(c.c);
  775. shadows[n].draw_by_perimeter(0, 0, 1);
  776. glColorMask(1, 1, 1, 1);
  777. glEndList();
  778. }
  779. static void refraction_list_init()
  780. {
  781. int i;
  782. for (i = 0; i < nlights; i++) refraction_list_init(i);
  783. }
  784. static void refraction_list_init(int n) {
  785. /* This could be loads simpler if it weren't for the texture mapping -
  786. * that's where all this weirdness with GL_LIGHT0 + nlights + 1 comes
  787. * in */
  788. glNewList(lists_refraction + n, GL_COMPILE);
  789. glEnable(GL_LIGHTING);
  790. glCallList(list_lights_off);
  791. /* This is white ambient light */
  792. glEnable(GL_LIGHT0 + nlights + 1);
  793. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, black.c);
  794. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black.c);
  795. glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
  796. glEnable(GL_COLOR_MATERIAL);
  797. glBlendFunc(GL_ONE, GL_ONE);
  798. glEnable(GL_BLEND);
  799. glDisable(GL_DEPTH_TEST);
  800. refraction[n].draw();
  801. glDisable(GL_BLEND);
  802. glDisable(GL_COLOR_MATERIAL);
  803. glDisable(GL_LIGHT0 + nlights + 1);
  804. glDisable(GL_LIGHTING);
  805. glEndList();
  806. }
  807. static void shadow_refraction_full_build()
  808. {
  809. int i;
  810. for (i = 0; i < nlights; i++) shadow_refraction_full_build(i);
  811. }
  812. /* This entire function is written a bit oddly... */
  813. static void shadow_refraction_full_build(int n)
  814. {
  815. Color c;
  816. float dist_light;
  817. Point dlight, zaxis;
  818. /* Make sure that we're starting over from scratch */
  819. shadows[n].free_points_normals();
  820. shadows[n].free_colors();
  821. refraction[n].free_points_normals();
  822. refraction[n].free_colors();
  823. dlight = lights[n].pos - sphere_position;
  824. dist_light = dlight.mag();
  825. dlight.unitize();
  826. zaxis.pt[0] = 0;
  827. zaxis.pt[1] = 0;
  828. zaxis.pt[2] = 1;
  829. shadows[n].set_divisions(disks[n].get_rdivisions(),
  830. disks[n].get_tdivisions());
  831. refraction[n].set_divisions(disks[n].get_rdivisions(),
  832. disks[n].get_tdivisions());
  833. shadows[n].alloc_points();
  834. shadows[n].face_direction(dlight, disks[n]);
  835. shadows[n].scale_translate(sphere_size, sphere_position);
  836. c = square_diffuse;
  837. c *= lights[n].diffuse;
  838. refraction[n].copy_points(disks[n]);
  839. refraction[n].set_colors(c);
  840. refraction[n].scale_colors_by_z();
  841. refraction[n].scale(sphere_size);
  842. refraction[n].refract_normals(zaxis * dist_light, index);
  843. refraction[n].face_direction(dlight);
  844. refraction[n].project_borrow_points(shadows[n]);
  845. refraction[n].free_normals();
  846. shadows[n].project(lights[n].pos);
  847. if (index != 1.0) refraction[n].scale_colors_by_darea(shadows[n]);
  848. }
  849. int scene_load_texture(char *texfile)
  850. {
  851. #ifdef TEXTURE
  852. teximage = auxRGBImageLoad(texfile);
  853. #else
  854. teximage = NULL;
  855. #endif
  856. if (teximage == NULL) return 0;
  857. else return 1;
  858. }
  859. void texture_init()
  860. {
  861. if (teximage == NULL) return;
  862. gluBuild2DMipmaps(GL_TEXTURE_2D, 3, teximage->sizeX, teximage->sizeY,
  863. GL_RGB, GL_UNSIGNED_BYTE, teximage->data);
  864. glMatrixMode(GL_TEXTURE);
  865. glLoadIdentity();
  866. glRotatef(90, 0, 0, 1);
  867. /* This scales the texture so that it fits on the square */
  868. glTranslatef(.5, .5, 0);
  869. glScalef(2, 2, 1);
  870. glMatrixMode(GL_MODELVIEW);
  871. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  872. GL_NEAREST_MIPMAP_NEAREST);
  873. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
  874. GL_LINEAR);
  875. }