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.

877 lines
23 KiB

  1. /**********************************Module**********************************\
  2. *
  3. * geom.c
  4. *
  5. * 3D FlowerBox screen saver
  6. * Geometry routines
  7. *
  8. * History:
  9. * Wed Jul 19 14:50:27 1995 -by- Drew Bliss [drewb]
  10. * Created
  11. *
  12. * Copyright (c) 1995 Microsoft Corporation
  13. *
  14. \**************************************************************************/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. // Sphere radius
  18. #define RADIUS 1
  19. // Values to map a 2D point onto a 3D plane
  20. // Base point and axes to map X and Y coordinates onto
  21. typedef struct _PLANE_MAP
  22. {
  23. PT3 base, x_axis, y_axis;
  24. } PLANE_MAP;
  25. // Data area used by the current geometry
  26. // Base points and generated points
  27. PT3 pts[MAXPTS], npts[MAXPTS];
  28. // Scaling factor for spherical projection
  29. FLT vlen[MAXPTS];
  30. // Normals
  31. PT3 normals[MAXPTS];
  32. // Vertex data indices
  33. int index[MAXPTS*2];
  34. // Triangle strip sizes
  35. int strip_size[MAXSIDES*MAXSUBDIV];
  36. void InitCube(GEOMETRY *geom);
  37. void InitTetra(GEOMETRY *geom);
  38. void InitPyramids(GEOMETRY *geom);
  39. void InitCylinder(GEOMETRY *geom);
  40. void InitSpring(GEOMETRY *geom);
  41. GEOMETRY cube_geom = {InitCube};
  42. GEOMETRY tetra_geom = {InitTetra};
  43. GEOMETRY pyramids_geom = {InitPyramids};
  44. GEOMETRY cylinder_geom = {InitCylinder};
  45. GEOMETRY spring_geom = {InitSpring};
  46. GEOMETRY *geom_table[] =
  47. {
  48. &cube_geom,
  49. &tetra_geom,
  50. &pyramids_geom,
  51. &cylinder_geom,
  52. &spring_geom
  53. };
  54. extern BOOL bOgl11;
  55. extern BOOL bCheckerOn;
  56. /******************************Public*Routine******************************\
  57. *
  58. * InitVlen
  59. *
  60. * Precomputes scaling factor for spherical projection
  61. *
  62. * History:
  63. * Mon Jul 24 14:59:03 1995 -by- Drew Bliss [drewb]
  64. * Created
  65. *
  66. \**************************************************************************/
  67. void InitVlen(GEOMETRY *geom, int npts, PT3 *pts)
  68. {
  69. FLT d;
  70. FLT *vl;
  71. vl = vlen;
  72. while (npts-- > 0)
  73. {
  74. d = V3Len(pts);
  75. // Don't allow really close points because this leads to
  76. // numeric instability and really large objects
  77. assert(d > 0.01f);
  78. // Geometries are created with size one, filling the area
  79. // from -.5 to .5. This leads to distances generally less
  80. // than one, which leaves off half of the interesting morphing
  81. // effects due to the projection
  82. // Scaling up the scaling factor allows the values to
  83. // be both above and below one
  84. d *= geom->init_sf;
  85. assert(d > 0.0001f);
  86. *vl++ = (RADIUS-d)/d;
  87. #if 0
  88. dprintf(("Distance is %f, vl %f\n", d, *(vl-1)));
  89. #endif
  90. pts++;
  91. }
  92. }
  93. /******************************Public*Routine******************************\
  94. *
  95. * MapToSide
  96. *
  97. * Takes x,y coordinates in the range 0-1 and maps them onto the given
  98. * side plane for the current geometry
  99. *
  100. * History:
  101. * Mon Jul 24 15:10:34 1995 -by- Drew Bliss [drewb]
  102. * Created
  103. *
  104. \**************************************************************************/
  105. void MapToSide(PLANE_MAP *map, FLT x, FLT y, PT3 *pt)
  106. {
  107. pt->x = x*map->x_axis.x+y*map->y_axis.x+map->base.x;
  108. pt->y = x*map->x_axis.y+y*map->y_axis.y+map->base.y;
  109. pt->z = x*map->x_axis.z+y*map->y_axis.z+map->base.z;
  110. #if 0
  111. dprintf(("Point is %f,%f,%f\n", pt->x, pt->y, pt->z));
  112. #endif
  113. }
  114. void DrawWithVArrays (GEOMETRY *geom)
  115. {
  116. int side, ss, idc, k;
  117. unsigned int *idx;
  118. for (side = 0; side < geom->nsides; side++) {
  119. geom->sides[side].dBuf = (GLuint *) LocalAlloc (LMEM_FIXED,
  120. sizeof (GLuint) *
  121. 3 * MAXPTS * 2);
  122. k = 0;
  123. idx = geom->sides[side].strip_index;
  124. for (ss = 0; ss < geom->sides[side].nstrips; ss++) {
  125. if (geom->sides[side].strip_size[ss] < 3) continue;
  126. for (idc = 2; idc < geom->sides[side].strip_size[ss]; idc++) {
  127. if (!(idc % 2)) { //even
  128. geom->sides[side].dBuf[k++] = *(idx+idc-2);
  129. geom->sides[side].dBuf[k++] = *(idx+idc-1);
  130. } else {
  131. geom->sides[side].dBuf[k++] = *(idx+idc-1);
  132. geom->sides[side].dBuf[k++] = *(idx+idc-2);
  133. }
  134. geom->sides[side].dBuf[k++] = *(idx+idc);
  135. }
  136. idx += geom->sides[side].strip_size[ss];
  137. }
  138. geom->sides[side].num_eles = k;
  139. }
  140. glNormalPointer (GL_FLOAT, sizeof (PT3),
  141. (GLfloat *)&(geom->normals[0].x));
  142. glVertexPointer (3, GL_FLOAT, sizeof (PT3),
  143. (GLfloat *)&(geom->npts[0].x));
  144. glEnableClientState (GL_VERTEX_ARRAY);
  145. glEnableClientState (GL_NORMAL_ARRAY);
  146. glDisableClientState (GL_COLOR_ARRAY);
  147. glDisableClientState (GL_INDEX_ARRAY);
  148. glDisableClientState (GL_EDGE_FLAG_ARRAY);
  149. glDisableClientState (GL_TEXTURE_COORD_ARRAY);
  150. }
  151. /******************************Public*Routine******************************\
  152. *
  153. * InitCube
  154. *
  155. * Initialize the cube's geometry
  156. *
  157. * History:
  158. * Wed Jul 19 14:52:50 1995 -by- Drew Bliss [drewb]
  159. * Created
  160. *
  161. \**************************************************************************/
  162. #define CUBE_SIDES 6
  163. PLANE_MAP cube_planes[CUBE_SIDES] =
  164. {
  165. -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
  166. 0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
  167. 0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
  168. -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
  169. 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
  170. -0.5f, 0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f
  171. };
  172. #define CUBE_IDX(side, x, y) ((side)*side_pts+(x)*(config.subdiv+1)+(y))
  173. void InitCube(GEOMETRY *geom)
  174. {
  175. int side, x, y, k, num_in_side;
  176. PT3 *pt;
  177. unsigned int *sz, *idx, idc, ss, i0, i1, i2, i3;
  178. int side_pts;
  179. side_pts = (config.subdiv+1)*(config.subdiv+1);
  180. geom->nsides = CUBE_SIDES;
  181. geom->pts = &pts[0];
  182. geom->npts = &npts[0];
  183. geom->normals = &normals[0];
  184. geom->min_sf = -1.1f;
  185. geom->max_sf = 5.1f;
  186. geom->sf_inc = 0.05f;
  187. geom->init_sf = 2.0f;
  188. // Generate triangle strip data
  189. sz = &strip_size[0];
  190. idx = &index[0];
  191. for (side = 0; side < geom->nsides; side++)
  192. {
  193. geom->sides[side].nstrips = config.subdiv;
  194. geom->sides[side].strip_size = sz;
  195. geom->sides[side].strip_index = idx;
  196. for (x = 0; x < config.subdiv; x++)
  197. {
  198. *sz++ = (config.subdiv+1)*2;
  199. for (y = 0; y < config.subdiv+1; y++)
  200. {
  201. *idx++ = CUBE_IDX(side, x, y);
  202. *idx++ = CUBE_IDX(side, x+1, y);
  203. }
  204. }
  205. }
  206. assert(sz-strip_size <= DIMA(strip_size));
  207. assert(idx-index <= DIMA(index));
  208. // Generate base vertices
  209. pt = geom->pts;
  210. for (side = 0; side < geom->nsides; side++)
  211. {
  212. #if 0
  213. dprintf(("Side %d\n", side));
  214. #endif
  215. for (x = 0; x < config.subdiv+1; x++)
  216. {
  217. for (y = 0; y < config.subdiv+1; y++)
  218. {
  219. MapToSide(&cube_planes[side],
  220. (FLT)x/config.subdiv, (FLT)y/config.subdiv,
  221. pt);
  222. pt++;
  223. }
  224. }
  225. }
  226. assert(pt-pts <= DIMA(pts));
  227. geom->total_pts = geom->nsides*side_pts;
  228. }
  229. /******************************Public*Routine******************************\
  230. *
  231. * InitTetra
  232. *
  233. * Initialize the tetrahedron's geometry
  234. *
  235. * History:
  236. * Tue Jul 25 11:43:18 1995 -by- Drew Bliss [drewb]
  237. * Created
  238. *
  239. \**************************************************************************/
  240. #define TETRA_SIDES 4
  241. #define SQRT3 1.73205f
  242. #define SQRT3_2 (SQRT3/2.0f)
  243. #define SQRT3_3 (SQRT3/3.0f)
  244. #define SQRT3_6 (SQRT3/6.0f)
  245. #define SQRT3_12 (SQRT3/12.0f)
  246. #define TETRA_BASE (-SQRT3/8.0f)
  247. PLANE_MAP tetra_planes[TETRA_SIDES] =
  248. {
  249. -0.5f, TETRA_BASE, SQRT3_6,
  250. 1.0f, 0.0f, 0.0f, 0.0f, SQRT3_2, -SQRT3_6,
  251. 0.0f, TETRA_BASE, -SQRT3_3,
  252. -0.5f, 0.0f, SQRT3_2, 0.25f, SQRT3_2, SQRT3_12,
  253. 0.5f, TETRA_BASE, SQRT3_6,
  254. -0.5f, 0.0f, -SQRT3_2, -0.25f, SQRT3_2, SQRT3_12,
  255. 0.5f, TETRA_BASE, SQRT3_6,
  256. -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -SQRT3_2
  257. };
  258. void InitTetra(GEOMETRY *geom)
  259. {
  260. int side, x, y, k, ss, num_in_side;
  261. PT3 *pt;
  262. int *sz, *idx, idc, i0, i1, i2, i3;
  263. int side_pts;
  264. int base_pt;
  265. int row_pts;
  266. FLT fx, fy;
  267. side_pts = (config.subdiv+2)*(config.subdiv+1)/2;
  268. geom->nsides = TETRA_SIDES;
  269. geom->pts = &pts[0];
  270. geom->npts = &npts[0];
  271. geom->normals = &normals[0];
  272. geom->min_sf = -1.1f;
  273. geom->max_sf = 5.2f;
  274. geom->sf_inc = 0.05f;
  275. geom->init_sf = 3.75f;
  276. // Generate triangle strip data
  277. sz = &strip_size[0];
  278. idx = &index[0];
  279. base_pt = 0;
  280. for (side = 0; side < geom->nsides; side++)
  281. {
  282. geom->sides[side].nstrips = config.subdiv;
  283. geom->sides[side].strip_size = sz;
  284. geom->sides[side].strip_index = idx;
  285. for (x = 0; x < config.subdiv; x++)
  286. {
  287. row_pts = config.subdiv-x+1;
  288. *sz++ = row_pts*2-1;
  289. *idx++ = base_pt;
  290. for (y = 0; y < row_pts-1; y++)
  291. {
  292. *idx++ = base_pt+row_pts+y;
  293. *idx++ = base_pt+1+y;
  294. }
  295. base_pt += row_pts;
  296. }
  297. base_pt++;
  298. }
  299. assert(sz-strip_size <= DIMA(strip_size));
  300. assert(idx-index <= DIMA(index));
  301. // Generate base vertices
  302. pt = geom->pts;
  303. for (side = 0; side < geom->nsides; side++)
  304. {
  305. #if 0
  306. dprintf(("Side %d\n", side));
  307. #endif
  308. for (x = 0; x < config.subdiv+1; x++)
  309. {
  310. fx = (FLT)x/config.subdiv;
  311. for (y = 0; y < config.subdiv-x+1; y++)
  312. {
  313. MapToSide(&tetra_planes[side],
  314. fx+(FLT)y/(config.subdiv*2),
  315. (FLT)y/config.subdiv,
  316. pt);
  317. pt++;
  318. }
  319. }
  320. }
  321. assert(pt-pts <= DIMA(pts));
  322. geom->total_pts = geom->nsides*side_pts;
  323. }
  324. /******************************Public*Routine******************************\
  325. *
  326. * InitPyramids
  327. *
  328. * Initializes double pyramid geometry
  329. *
  330. * History:
  331. * Wed Jul 26 18:37:11 1995 -by- Drew Bliss [drewb]
  332. * Created
  333. *
  334. \**************************************************************************/
  335. #define PYRAMIDS_SIDES 8
  336. PLANE_MAP pyramids_planes[PYRAMIDS_SIDES] =
  337. {
  338. -0.5f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.5f, -0.5f,
  339. 0.5f, 0.0f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f,
  340. 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, -1.0f, -0.5f, 0.5f, 0.0f,
  341. 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, -0.5f, -0.5f, 0.0f,
  342. 0.5f, 0.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.5f,
  343. -0.5f, 0.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f,
  344. -0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.5f, 0.5f, 0.0f,
  345. -0.5f, 0.0f, 0.5f, 0.0f, 0.0f, -1.0f, 0.5f, -0.5f, 0.0f
  346. };
  347. void InitPyramids(GEOMETRY *geom)
  348. {
  349. int side, x, y, k, num_in_side;
  350. PT3 *pt;
  351. int *sz, *idx, idc, i0, i1, i2, i3, ss;
  352. int side_pts;
  353. int base_pt;
  354. int row_pts;
  355. FLT fx, fy;
  356. side_pts = (config.subdiv+2)*(config.subdiv+1)/2;
  357. geom->nsides = PYRAMIDS_SIDES;
  358. geom->pts = &pts[0];
  359. geom->npts = &npts[0];
  360. geom->normals = &normals[0];
  361. geom->min_sf = -1.1f;
  362. geom->max_sf = 5.2f;
  363. geom->sf_inc = 0.05f;
  364. geom->init_sf = 3.0f;
  365. // Generate triangle strip data
  366. sz = &strip_size[0];
  367. idx = &index[0];
  368. base_pt = 0;
  369. for (side = 0; side < geom->nsides; side++) {
  370. geom->sides[side].nstrips = config.subdiv;
  371. geom->sides[side].strip_size = sz;
  372. geom->sides[side].strip_index = idx;
  373. for (x = 0; x < config.subdiv; x++) {
  374. row_pts = config.subdiv-x+1;
  375. *sz++ = row_pts*2-1;
  376. *idx++ = base_pt;
  377. for (y = 0; y < row_pts-1; y++) {
  378. *idx++ = base_pt+row_pts+y;
  379. *idx++ = base_pt+1+y;
  380. }
  381. base_pt += row_pts;
  382. }
  383. base_pt++;
  384. }
  385. assert(sz-strip_size <= DIMA(strip_size));
  386. assert(idx-index <= DIMA(index));
  387. // Generate base vertices
  388. pt = geom->pts;
  389. for (side = 0; side < geom->nsides; side++)
  390. {
  391. #if 0
  392. dprintf(("Side %d\n", side));
  393. #endif
  394. for (x = 0; x < config.subdiv+1; x++)
  395. {
  396. fx = (FLT)x/config.subdiv;
  397. for (y = 0; y < config.subdiv-x+1; y++)
  398. {
  399. MapToSide(&pyramids_planes[side],
  400. fx+(FLT)y/(config.subdiv*2),
  401. (FLT)y/config.subdiv,
  402. pt);
  403. pt++;
  404. }
  405. }
  406. }
  407. assert(pt-pts <= DIMA(pts));
  408. geom->total_pts = geom->nsides*side_pts;
  409. }
  410. /******************************Public*Routine******************************\
  411. *
  412. * InitCylinder
  413. *
  414. * Initializes the cylinder geometry
  415. *
  416. * History:
  417. * Fri Jul 28 16:12:39 1995 -by- Drew Bliss [drewb]
  418. * Created
  419. *
  420. \**************************************************************************/
  421. void InitCylinder(GEOMETRY *geom)
  422. {
  423. int side, x, y, k, num_in_side;
  424. PT3 *pt;
  425. int *sz, *idx, ss, idc, i0, i1, i2, i3;
  426. int base_pt;
  427. int row_pts;
  428. FLT fx, fy, fz;
  429. double ang;
  430. geom->nsides = 1;
  431. geom->pts = &pts[0];
  432. geom->npts = &npts[0];
  433. geom->normals = &normals[0];
  434. geom->min_sf = -2.5f;
  435. geom->max_sf = 8.5f;
  436. geom->sf_inc = 0.05f;
  437. geom->init_sf = 2.1f;
  438. // Generate triangle strip data
  439. // If version 1.1 then allocate the index buffer for glDrawElements
  440. sz = &strip_size[0];
  441. idx = &index[0];
  442. side = 0;
  443. geom->sides[side].nstrips = config.subdiv;
  444. geom->sides[side].strip_size = sz;
  445. geom->sides[side].strip_index = idx;
  446. row_pts = config.subdiv+1;
  447. base_pt = 0;
  448. for (x = 0; x < config.subdiv; x++) {
  449. *sz++ = row_pts*2;
  450. for (y = 0; y < row_pts; y++) {
  451. // Wrap around at the edge so the cylinder normals
  452. // are properly averaged
  453. if (x == config.subdiv-1) {
  454. *idx++ = y;
  455. }
  456. else {
  457. *idx++ = base_pt+row_pts+y;
  458. }
  459. *idx++ = base_pt+y;
  460. }
  461. base_pt += row_pts;
  462. }
  463. assert(sz-strip_size <= DIMA(strip_size));
  464. assert(idx-index <= DIMA(index));
  465. // Generate base vertices
  466. pt = geom->pts;
  467. ang = 0;
  468. for (x = 0; x < config.subdiv; x++)
  469. {
  470. fx = (FLT)cos(ang)*0.5f;
  471. fz = (FLT)sin(ang)*0.5f;
  472. for (y = 0; y < config.subdiv+1; y++)
  473. {
  474. pt->x = fx;
  475. pt->y = (FLT)y/config.subdiv-0.5f;
  476. pt->z = fz;
  477. pt++;
  478. }
  479. ang += (2*PI)/config.subdiv;
  480. }
  481. assert(pt-pts <= DIMA(pts));
  482. geom->total_pts = geom->nsides*(config.subdiv+1)*config.subdiv;
  483. }
  484. /******************************Public*Routine******************************\
  485. *
  486. * InitSpring
  487. *
  488. * Initializes the spring geometry
  489. *
  490. * History:
  491. * Fri Jul 28 16:12:39 1995 -by- Drew Bliss [drewb]
  492. * Created
  493. *
  494. \**************************************************************************/
  495. #define SPRING_RADIUS 0.1f
  496. #define SPRING_CENTER (0.5f-SPRING_RADIUS)
  497. void InitSpring(GEOMETRY *geom)
  498. {
  499. int side, x, y, k, num_in_side;
  500. PT3 *pt;
  501. int *sz, *idx, idc, ss, i0, i1, i2, i3;
  502. double ang_center, ang_surf;
  503. FLT cs, sn;
  504. FLT rad;
  505. PLANE_MAP plane;
  506. int spin_pts;
  507. int row_pts;
  508. geom->nsides = 1;
  509. geom->pts = &pts[0];
  510. geom->npts = &npts[0];
  511. geom->normals = &normals[0];
  512. geom->min_sf = -2.2f;
  513. geom->max_sf = 0.2f;
  514. geom->sf_inc = 0.05f;
  515. geom->init_sf = 1.0f;
  516. // Generate triangle strip data
  517. // If version 1.1 then allocate the index buffer for glDrawElements
  518. sz = &strip_size[0];
  519. idx = &index[0];
  520. side = 0;
  521. geom->sides[side].nstrips = config.subdiv;
  522. geom->sides[side].strip_size = sz;
  523. geom->sides[side].strip_index = idx;
  524. row_pts = config.subdiv;
  525. spin_pts = 4*config.subdiv+1;
  526. for (x = 0; x < config.subdiv; x++) {
  527. *sz++ = spin_pts*2;
  528. for (y = 0; y < spin_pts; y++) {
  529. *idx++ = x+row_pts*y;
  530. // Wrap around at the edge so the cylindrical surface
  531. // of the tube is seamless. Without this the normal
  532. // averaging would be incorrect and a seam would be visible
  533. if (x == config.subdiv-1) {
  534. *idx++ = row_pts*y;
  535. }
  536. else {
  537. *idx++ = x+row_pts*y+1;
  538. }
  539. }
  540. }
  541. assert(sz-strip_size <= DIMA(strip_size));
  542. assert(idx-index <= DIMA(index));
  543. // Generate base vertices
  544. pt = geom->pts;
  545. ang_center = 0;
  546. plane.y_axis.x = 0.0f;
  547. plane.y_axis.y = SPRING_RADIUS;
  548. plane.y_axis.z = 0.0f;
  549. plane.x_axis.y = 0.0f;
  550. for (x = 0; x < spin_pts; x++)
  551. {
  552. cs = (FLT)cos(ang_center);
  553. sn = (FLT)sin(ang_center);
  554. rad = 0.5f-(FLT)x/(spin_pts-1)*(SPRING_CENTER/2);
  555. plane.base.x = cs*rad;
  556. plane.base.y = -0.5f+(FLT)x/(spin_pts-1);
  557. plane.base.z = sn*rad;
  558. plane.x_axis.x = cs*SPRING_RADIUS;
  559. plane.x_axis.z = sn*SPRING_RADIUS;
  560. ang_surf = 0;
  561. for (y = 0; y < config.subdiv; y++)
  562. {
  563. MapToSide(&plane,
  564. (FLT)cos(ang_surf), (FLT)sin(ang_surf),
  565. pt);
  566. pt++;
  567. ang_surf += (2*PI)/config.subdiv;
  568. }
  569. ang_center += (4*PI)/(spin_pts-1);
  570. }
  571. assert(pt-pts <= DIMA(pts));
  572. geom->total_pts = geom->nsides*spin_pts*config.subdiv;
  573. }
  574. /******************************Public*Routine******************************\
  575. *
  576. * DrawGeom
  577. *
  578. * Draw the current geometry
  579. *
  580. * History:
  581. * Wed Jul 19 14:53:02 1995 -by- Drew Bliss [drewb]
  582. * Created
  583. *
  584. \**************************************************************************/
  585. void DrawGeom(GEOMETRY *geom)
  586. {
  587. int side, strip, k;
  588. int *idx, idc, idxv;
  589. if (config.smooth_colors)
  590. {
  591. glShadeModel(GL_SMOOTH);
  592. }
  593. else
  594. {
  595. glShadeModel(GL_FLAT);
  596. }
  597. if (config.color_pick == ID_COL_SINGLE)
  598. {
  599. glMaterialfv(config.two_sided, GL_DIFFUSE, solid_cols);
  600. }
  601. #if 1
  602. if (!(bOgl11 && !bCheckerOn)) {
  603. for (side = 0; side < geom->nsides; side++) {
  604. if (config.color_pick == ID_COL_PER_SIDE) {
  605. glMaterialfv(config.two_sided, GL_DIFFUSE, side_cols[side]);
  606. }
  607. idx = geom->sides[side].strip_index;
  608. for (strip = 0; strip < geom->sides[side].nstrips; strip++) {
  609. glBegin(GL_TRIANGLE_STRIP);
  610. for (idc = 0; idc < geom->sides[side].strip_size[strip];
  611. idc++) {
  612. idxv = *idx++;
  613. assert(idxv >=0 && idxv < geom->total_pts);
  614. if (config.color_pick == ID_COL_CHECKER) {
  615. if (config.triangle_colors) {
  616. glMaterialfv(config.two_sided, GL_DIFFUSE,
  617. checker_cols[side][(idc+1)/2+strip &
  618. 1]);
  619. }
  620. else {
  621. glMaterialfv(config.two_sided, GL_DIFFUSE,
  622. checker_cols[side][idc/2+strip & 1]);
  623. }
  624. }
  625. glNormal3fv((GLfloat *)&geom->normals[idxv]);
  626. glVertex3fv((GLfloat *)&geom->npts[idxv]);
  627. }
  628. glEnd();
  629. }
  630. }
  631. } else {
  632. k = 0;
  633. for (side = 0; side < geom->nsides; side++) {
  634. if (config.color_pick == ID_COL_PER_SIDE)
  635. glMaterialfv(config.two_sided, GL_DIFFUSE, side_cols[side]);
  636. glDrawElements (GL_TRIANGLES, geom->sides[side].num_eles,
  637. GL_UNSIGNED_INT, &(geom->sides[side].dBuf[0]));
  638. k += geom->sides[side].num_eles;
  639. }
  640. }
  641. #else
  642. glBegin(GL_POINTS);
  643. for (side = 0; side < geom->total_pts; side++)
  644. {
  645. glVertex3fv((GLfloat *)&geom->npts[side]);
  646. }
  647. glEnd();
  648. #endif
  649. }
  650. /******************************Public*Routine******************************\
  651. *
  652. * ComputeAveragedNormals
  653. *
  654. * Compute face-averaged normals for each vertex
  655. *
  656. * History:
  657. * Wed Jul 19 14:53:13 1995 -by- Drew Bliss [drewb]
  658. * Created
  659. *
  660. \**************************************************************************/
  661. void ComputeAveragedNormals(GEOMETRY *geom)
  662. {
  663. int side, strip;
  664. int *sz;
  665. int *idx, idx1, idx2, idx3;
  666. int tc, idc;
  667. PT3 v1, v2, n1;
  668. memset(geom->normals, 0, sizeof(PT3)*geom->total_pts);
  669. for (side = 0; side < geom->nsides; side++)
  670. {
  671. idx = geom->sides[side].strip_index;
  672. sz = geom->sides[side].strip_size;
  673. for (strip = 0; strip < geom->sides[side].nstrips; strip++)
  674. {
  675. idx1 = *idx++;
  676. idx2 = *idx++;
  677. assert(idx1 >= 0 && idx1 < geom->total_pts &&
  678. idx2 >= 0 && idx2 < geom->total_pts);
  679. tc = (*sz++)-2;
  680. for (idc = 0; idc < tc; idc++)
  681. {
  682. idx3 = *idx++;
  683. assert(idx3 >= 0 && idx3 < geom->total_pts);
  684. V3Sub(&geom->npts[idx3], &geom->npts[idx1], &v1);
  685. V3Sub(&geom->npts[idx2], &geom->npts[idx1], &v2);
  686. V3Cross(&v1, &v2, &n1);
  687. // Triangle strip ordering causes half of the triangles
  688. // to be oriented oppositely from the others
  689. // Those triangles need to have their normals flipped
  690. // so the whole triangle strip has consistent normals
  691. if ((idc & 1) == 0)
  692. {
  693. n1.x = -n1.x;
  694. n1.y = -n1.y;
  695. n1.z = -n1.z;
  696. }
  697. #if 0
  698. dprintf(("Normal is %f,%f,%f\n", n1.x, n1.y, n1.z));
  699. #endif
  700. V3Add(&geom->normals[idx1], &n1, &geom->normals[idx1]);
  701. V3Add(&geom->normals[idx2], &n1, &geom->normals[idx2]);
  702. V3Add(&geom->normals[idx3], &n1, &geom->normals[idx3]);
  703. idx1 = idx2;
  704. idx2 = idx3;
  705. }
  706. }
  707. }
  708. }
  709. /******************************Public*Routine******************************\
  710. *
  711. * UpdatePts
  712. *
  713. * Project the point array through a sphere according to the given scale factor
  714. *
  715. * History:
  716. * Wed Jul 19 14:53:53 1995 -by- Drew Bliss [drewb]
  717. * Created
  718. *
  719. \**************************************************************************/
  720. void UpdatePts(GEOMETRY *geom, FLT sf)
  721. {
  722. int pt;
  723. FLT f, *vl;
  724. PT3 *v;
  725. PT3 *p;
  726. vl = vlen;
  727. p = &geom->pts[0];
  728. v = &geom->npts[0];
  729. for (pt = 0; pt < geom->total_pts; pt++)
  730. {
  731. f = (*vl++)*sf+1;
  732. v->x = p->x*f;
  733. v->y = p->y*f;
  734. v->z = p->z*f;
  735. #if 0
  736. dprintf(("%f: %f,%f,%f to %f,%f,%f by %f\n", sf,
  737. p->x, p->y, p->z, v->x, v->y, v->z, f));
  738. #endif
  739. p++;
  740. v++;
  741. }
  742. ComputeAveragedNormals(geom);
  743. }