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.

715 lines
24 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: objects.cxx
  3. *
  4. * Creates command lists for pipe primitive objects
  5. *
  6. * Copyright (c) 1994 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include <windows.h>
  14. #include <GL/gl.h>
  15. #include "sscommon.h"
  16. #include "objects.h"
  17. #include "sspipes.h"
  18. #define ROOT_TWO 1.414213562373f
  19. /**************************************************************************\
  20. * OBJECT constructor
  21. *
  22. \**************************************************************************/
  23. OBJECT::OBJECT( )
  24. {
  25. listNum = glGenLists(1);
  26. }
  27. /**************************************************************************\
  28. * OBJECT destructor
  29. *
  30. \**************************************************************************/
  31. OBJECT::~OBJECT( )
  32. {
  33. glDeleteLists( listNum, 1 );
  34. }
  35. /**************************************************************************\
  36. * Draw
  37. *
  38. * - Draw the object by calling its display list
  39. *
  40. \**************************************************************************/
  41. void
  42. OBJECT::Draw( )
  43. {
  44. glCallList( listNum );
  45. }
  46. /**************************************************************************\
  47. * PIPE_OBJECT constructors
  48. *
  49. \**************************************************************************/
  50. PIPE_OBJECT::PIPE_OBJECT( OBJECT_BUILD_INFO *pBuildInfo, float len )
  51. {
  52. Build( pBuildInfo, len, 0.0f, 0.0f );
  53. }
  54. PIPE_OBJECT::PIPE_OBJECT( OBJECT_BUILD_INFO *pBuildInfo, float len, float s_start, float s_end )
  55. {
  56. Build( pBuildInfo, len, s_start, s_end );
  57. }
  58. /**************************************************************************\
  59. * ELBOW_OBJECT constructors
  60. *
  61. \**************************************************************************/
  62. ELBOW_OBJECT::ELBOW_OBJECT( OBJECT_BUILD_INFO *pBuildInfo, int notch )
  63. {
  64. Build( pBuildInfo, notch, 0.0f, 0.0f );
  65. }
  66. ELBOW_OBJECT::ELBOW_OBJECT( OBJECT_BUILD_INFO *pBuildInfo, int notch, float s_start, float s_end )
  67. {
  68. Build( pBuildInfo, notch, s_start, s_end );
  69. }
  70. /**************************************************************************\
  71. * BALLJOINT_OBJECT constructor
  72. *
  73. \**************************************************************************/
  74. BALLJOINT_OBJECT::BALLJOINT_OBJECT( OBJECT_BUILD_INFO *pBuildInfo, int notch, float s_start, float s_end )
  75. {
  76. Build( pBuildInfo, notch, s_start, s_end );
  77. }
  78. /**************************************************************************\
  79. * SPHERE_OBJECT constructors
  80. *
  81. \**************************************************************************/
  82. SPHERE_OBJECT::SPHERE_OBJECT( OBJECT_BUILD_INFO *pBuildInfo, float radius )
  83. {
  84. Build( pBuildInfo, radius, 0.0f, 0.0f );
  85. }
  86. SPHERE_OBJECT::SPHERE_OBJECT( OBJECT_BUILD_INFO *pBuildInfo, float radius, float s_start, float s_end )
  87. {
  88. Build( pBuildInfo, radius, s_start, s_end );
  89. }
  90. // rotate circle around x-axis, with edge attached to anchor
  91. static void TransformCircle(
  92. float angle,
  93. POINT3D *inPoint,
  94. POINT3D *outPoint,
  95. GLint num,
  96. POINT3D *anchor )
  97. {
  98. MATRIX matrix1, matrix2, matrix3;
  99. int i;
  100. // translate anchor point to origin
  101. ss_matrixIdent( &matrix1 );
  102. ss_matrixTranslate( &matrix1, -anchor->x, -anchor->y, -anchor->z );
  103. // rotate by angle, cw around x-axis
  104. ss_matrixIdent( &matrix2 );
  105. ss_matrixRotate( &matrix2, (double) -angle, 0.0, 0.0 );
  106. // concat these 2
  107. ss_matrixMult( &matrix3, &matrix2, &matrix1 );
  108. // translate back
  109. ss_matrixIdent( &matrix2 );
  110. ss_matrixTranslate( &matrix2, anchor->x, anchor->y, anchor->z );
  111. // concat these 2
  112. ss_matrixMult( &matrix1, &matrix2, &matrix3 );
  113. // transform all the points, + center
  114. for( i = 0; i < num; i ++, outPoint++, inPoint++ ) {
  115. ss_xformPoint( outPoint, inPoint, &matrix1 );
  116. }
  117. }
  118. static void CalcNormals( POINT3D *p, POINT3D *n, POINT3D *center,
  119. int num )
  120. {
  121. POINT3D vec;
  122. int i;
  123. for( i = 0; i < num; i ++, n++, p++ ) {
  124. n->x = p->x - center->x;
  125. n->y = p->y - center->y;
  126. n->z = p->z - center->z;
  127. ss_normalizeNorm( n );
  128. }
  129. }
  130. /*----------------------------------------------------------------------\
  131. | MakeQuadStrip() |
  132. | - builds quadstrip between 2 rows of points. pA points to one |
  133. | row of points, and pB to the next rotated row. Because |
  134. | the rotation has previously been defined CCW around the |
  135. | x-axis, using an A-B sequence will result in CCW quads |
  136. | |
  137. \----------------------------------------------------------------------*/
  138. static void MakeQuadStrip
  139. (
  140. POINT3D *pA,
  141. POINT3D *pB,
  142. POINT3D *nA,
  143. POINT3D *nB,
  144. BOOL bTexture,
  145. GLfloat *tex_s,
  146. GLfloat *tex_t,
  147. GLint slices
  148. )
  149. {
  150. GLint i;
  151. glBegin( GL_QUAD_STRIP );
  152. for( i = 0; i < slices; i ++ ) {
  153. glNormal3fv( (GLfloat *) nA++ );
  154. if( bTexture )
  155. glTexCoord2f( tex_s[0], *tex_t );
  156. glVertex3fv( (GLfloat *) pA++ );
  157. glNormal3fv( (GLfloat *) nB++ );
  158. if( bTexture )
  159. glTexCoord2f( tex_s[1], *tex_t++ );
  160. glVertex3fv( (GLfloat *) pB++ );
  161. }
  162. glEnd();
  163. }
  164. #define CACHE_SIZE 100
  165. /*----------------------------------------------------------------------\
  166. | BuildElbow() |
  167. | - builds elbows, by rotating a circle in the y=r plane |
  168. | centered at (0,r,-r), CW around the x-axis at anchor pt. |
  169. | (r = radius of the circle) |
  170. | - rotation is 90.0 degrees, ending at circle in z=0 plane, |
  171. | centered at origin. |
  172. | - in order to 'mate' texture coords with the cylinders |
  173. | generated with glu, we generate 4 elbows, each corresponding |
  174. | to the 4 possible CW 90 degree orientations of the start point|
  175. | for each circle. |
  176. | - We call this start point the 'notch'. If we characterize |
  177. | each notch by the axis it points down in the starting and |
  178. | ending circles of the elbow, then we get the following axis |
  179. | pairs for our 4 notches: |
  180. | - +z,+y |
  181. | - +x,+x |
  182. | - -z,-y |
  183. | - -x,-x |
  184. | Since the start of the elbow always points down +y, the 4 |
  185. | start notches give all possible 90.0 degree orientations |
  186. | around y-axis. |
  187. | - We can keep track of the current 'notch' vector to provide |
  188. | proper mating between primitives. |
  189. | - Each circle of points is described CW from the start point, |
  190. | assuming looking down the +y axis(+y direction). |
  191. | - texture 's' starts at 0.0, and goes to 2.0*r/divSize at |
  192. | end of the elbow. (Then a short pipe would start with this |
  193. | 's', and run it to 1.0). |
  194. | |
  195. \----------------------------------------------------------------------*/
  196. void
  197. ELBOW_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, int notch, float s_start, float s_end )
  198. {
  199. GLint stacks, slices;
  200. GLfloat angle, startAng, r;
  201. GLint numPoints;
  202. GLfloat s_delta;
  203. POINT3D pi[CACHE_SIZE]; // initial row of points + center
  204. POINT3D p0[CACHE_SIZE]; // 2 rows of points
  205. POINT3D p1[CACHE_SIZE];
  206. POINT3D n0[CACHE_SIZE]; // 2 rows of normals
  207. POINT3D n1[CACHE_SIZE];
  208. GLfloat tex_t[CACHE_SIZE];// 't' texture coords
  209. GLfloat tex_s[2]; // 's' texture coords
  210. POINT3D center; // center of circle
  211. POINT3D anchor; // where circle is anchored
  212. POINT3D *pA, *pB, *nA, *nB;
  213. int i, j;
  214. IPOINT2D *texRep = pBuildInfo->texRep;
  215. GLfloat radius = pBuildInfo->radius;
  216. BOOL bTexture = pBuildInfo->bTexture;
  217. slices = pBuildInfo->nSlices;
  218. stacks = slices / 2;
  219. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  220. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  221. s_delta = s_end - s_start;
  222. if( bTexture ) {
  223. // calculate 't' texture coords
  224. for( i = 0; i <= slices; i ++ ) {
  225. tex_t[i] = (GLfloat) i * texRep->y / slices;
  226. }
  227. }
  228. numPoints = slices + 1;
  229. // starting angle increment 90.0 degrees each time
  230. startAng = notch * PI / 2;
  231. // calc initial circle of points for circle centered at 0,r,-r
  232. // points start at (0,r,0), and rotate circle CCW
  233. for( i = 0; i <= slices; i ++ ) {
  234. angle = startAng + (2 * PI * i / slices);
  235. pi[i].x = radius * (float) sin(angle);
  236. pi[i].y = radius;
  237. // translate z by -r, cuz these cos calcs are for circle at origin
  238. pi[i].z = radius * (float) cos(angle) - radius;
  239. }
  240. // center point, tacked onto end of circle of points
  241. pi[i].x = 0.0f;
  242. pi[i].y = radius;
  243. pi[i].z = -radius;
  244. center = pi[i];
  245. // anchor point
  246. anchor.x = anchor.z = 0.0f;
  247. anchor.y = radius;
  248. // calculate initial normals
  249. CalcNormals( pi, n0, &center, numPoints );
  250. // initial 's' texture coordinate
  251. tex_s[0] = s_start;
  252. // setup pointers
  253. pA = pi;
  254. pB = p0;
  255. nA = n0;
  256. nB = n1;
  257. // now iterate throught the stacks
  258. glNewList(listNum, GL_COMPILE);
  259. for( i = 1; i <= stacks; i ++ ) {
  260. // ! this angle must be negative, for correct vertex orientation !
  261. angle = - 0.5f * PI * i / stacks;
  262. // transform to get next circle of points + center
  263. TransformCircle( angle, pi, pB, numPoints+1, &anchor );
  264. // calculate normals
  265. center = pB[numPoints];
  266. CalcNormals( pB, nB, &center, numPoints );
  267. // calculate next 's' texture coord
  268. tex_s[1] = (GLfloat) s_start + s_delta * i / stacks;
  269. // now we've got points and normals, ready to be quadstrip'd
  270. MakeQuadStrip( pA, pB, nA, nB, bTexture, tex_s, tex_t, numPoints );
  271. // reset pointers
  272. pA = pB;
  273. nA = nB;
  274. pB = (pB == p0) ? p1 : p0;
  275. nB = (nB == n0) ? n1 : n0;
  276. tex_s[0] = tex_s[1];
  277. }
  278. glEndList();
  279. }
  280. /*----------------------------------------------------------------------\
  281. | BuildBallJoint() |
  282. | - These are very similar to the elbows, in that the starting |
  283. | and ending positions are almost identical. The difference |
  284. | here is that the circles in the sweep describe a sphere as |
  285. | they are rotated. |
  286. | |
  287. \----------------------------------------------------------------------*/
  288. void
  289. BALLJOINT_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, int notch,
  290. float s_start, float s_end )
  291. {
  292. GLfloat ballRadius;
  293. GLfloat angle, delta_a, startAng, theta;
  294. GLint numPoints;
  295. GLfloat s_delta;
  296. POINT3D pi0[CACHE_SIZE]; // 2 circles of untransformed points
  297. POINT3D pi1[CACHE_SIZE];
  298. POINT3D p0[CACHE_SIZE]; // 2 rows of transformed points
  299. POINT3D p1[CACHE_SIZE];
  300. POINT3D n0[CACHE_SIZE]; // 2 rows of normals
  301. POINT3D n1[CACHE_SIZE];
  302. float r[CACHE_SIZE]; // radii of the circles
  303. GLfloat tex_t[CACHE_SIZE];// 't' texture coords
  304. GLfloat tex_s[2]; // 's' texture coords
  305. POINT3D center; // center of circle
  306. POINT3D anchor; // where circle is anchored
  307. POINT3D *pA, *pB, *nA, *nB;
  308. int i, j, k;
  309. GLint stacks, slices;
  310. IPOINT2D *texRep = pBuildInfo->texRep;
  311. GLfloat radius = pBuildInfo->radius;
  312. BOOL bTexture = pBuildInfo->bTexture;
  313. slices = pBuildInfo->nSlices;
  314. stacks = slices;
  315. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  316. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  317. // calculate the radii for each circle in the sweep, where
  318. // r[i] = y = sin(angle)/r
  319. angle = PI / 4; // first radius always at 45.0 degrees
  320. delta_a = (PI / 2.0f) / stacks;
  321. ballRadius = ROOT_TWO * radius;
  322. for( i = 0; i <= stacks; i ++, angle += delta_a ) {
  323. r[i] = (float) sin(angle) * ballRadius;
  324. }
  325. if( bTexture ) {
  326. // calculate 't' texture coords
  327. for( i = 0; i <= slices; i ++ ) {
  328. tex_t[i] = (GLfloat) i * texRep->y / slices;
  329. }
  330. }
  331. s_delta = s_end - s_start;
  332. numPoints = slices + 1;
  333. // unlike the elbow, the center for the ball joint is constant
  334. center.x = center.y = 0.0f;
  335. center.z = -radius;
  336. // starting angle along circle, increment 90.0 degrees each time
  337. startAng = notch * PI / 2;
  338. // calc initial circle of points for circle centered at 0,r,-r
  339. // points start at (0,r,0), and rotate circle CCW
  340. delta_a = 2 * PI / slices;
  341. for( i = 0, theta = startAng; i <= slices; i ++, theta += delta_a ) {
  342. pi0[i].x = r[0] * (float) sin(theta);
  343. pi0[i].y = radius;
  344. // translate z by -r, cuz these cos calcs are for circle at origin
  345. pi0[i].z = r[0] * (float) cos(theta) - r[0];
  346. }
  347. // anchor point
  348. anchor.x = anchor.z = 0.0f;
  349. anchor.y = radius;
  350. // calculate initial normals
  351. CalcNormals( pi0, n0, &center, numPoints );
  352. // initial 's' texture coordinate
  353. tex_s[0] = s_start;
  354. // setup pointers
  355. pA = pi0; // circles of transformed points
  356. pB = p0;
  357. nA = n0; // circles of transformed normals
  358. nB = n1;
  359. // now iterate throught the stacks
  360. glNewList(listNum, GL_COMPILE);
  361. for( i = 1; i <= stacks; i ++ ) {
  362. // ! this angle must be negative, for correct vertex orientation !
  363. angle = - 0.5f * PI * i / stacks;
  364. // calc the next circle of untransformed points into pi1[]
  365. for( k = 0, theta = startAng; k <= slices; k ++, theta+=delta_a ) {
  366. pi1[k].x = r[i] * (float) sin(theta);
  367. pi1[k].y = radius;
  368. // translate z by -r, cuz calcs are for circle at origin
  369. pi1[k].z = r[i] * (float) cos(theta) - r[i];
  370. }
  371. // rotate cirle of points to next position
  372. TransformCircle( angle, pi1, pB, numPoints, &anchor );
  373. // calculate normals
  374. CalcNormals( pB, nB, &center, numPoints );
  375. // calculate next 's' texture coord
  376. tex_s[1] = (GLfloat) s_start + s_delta * i / stacks;
  377. // now we've got points and normals, ready to be quadstrip'd
  378. MakeQuadStrip( pA, pB, nA, nB, bTexture, tex_s, tex_t, numPoints );
  379. // reset pointers
  380. pA = pB;
  381. nA = nB;
  382. pB = (pB == p0) ? p1 : p0;
  383. nB = (nB == n0) ? n1 : n0;
  384. tex_s[0] = tex_s[1];
  385. }
  386. glEndList();
  387. }
  388. // 'glu' routines
  389. #ifdef _EXTENSIONS_
  390. #define COS cosf
  391. #define SIN sinf
  392. #define SQRT sqrtf
  393. #else
  394. #define COS cos
  395. #define SIN sin
  396. #define SQRT sqrt
  397. #endif
  398. /**************************************************************************\
  399. * BuildCylinder
  400. *
  401. \**************************************************************************/
  402. void
  403. PIPE_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, float length, float s_start,
  404. float s_end )
  405. {
  406. GLint stacks, slices;
  407. GLint i,j,max;
  408. GLfloat sinCache[CACHE_SIZE];
  409. GLfloat cosCache[CACHE_SIZE];
  410. GLfloat sinCache2[CACHE_SIZE];
  411. GLfloat cosCache2[CACHE_SIZE];
  412. GLfloat angle;
  413. GLfloat x, y, zLow, zHigh;
  414. GLfloat sintemp, costemp;
  415. GLfloat zNormal;
  416. GLfloat s_delta;
  417. IPOINT2D *texRep = pBuildInfo->texRep;
  418. GLfloat radius = pBuildInfo->radius;
  419. BOOL bTexture = pBuildInfo->bTexture;
  420. slices = pBuildInfo->nSlices;
  421. stacks = (int) SS_ROUND_UP( (length/pBuildInfo->divSize) * (float)slices) ;
  422. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  423. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  424. zNormal = 0.0f;
  425. s_delta = s_end - s_start;
  426. for (i = 0; i < slices; i++) {
  427. angle = 2 * PI * i / slices;
  428. sinCache2[i] = (float) SIN(angle);
  429. cosCache2[i] = (float) COS(angle);
  430. sinCache[i] = (float) SIN(angle);
  431. cosCache[i] = (float) COS(angle);
  432. }
  433. sinCache[slices] = sinCache[0];
  434. cosCache[slices] = cosCache[0];
  435. sinCache2[slices] = sinCache2[0];
  436. cosCache2[slices] = cosCache2[0];
  437. glNewList(listNum, GL_COMPILE);
  438. for (j = 0; j < stacks; j++) {
  439. zLow = j * length / stacks;
  440. zHigh = (j + 1) * length / stacks;
  441. glBegin(GL_QUAD_STRIP);
  442. for (i = 0; i <= slices; i++) {
  443. glNormal3f(sinCache2[i], cosCache2[i], zNormal);
  444. if (bTexture) {
  445. glTexCoord2f( (float) s_start + s_delta * j / stacks,
  446. (float) i * texRep->y / slices );
  447. }
  448. glVertex3f(radius * sinCache[i],
  449. radius * cosCache[i], zLow);
  450. if (bTexture) {
  451. glTexCoord2f( (float) s_start + s_delta*(j+1) / stacks,
  452. (float) i * texRep->y / slices );
  453. }
  454. glVertex3f(radius * sinCache[i],
  455. radius * cosCache[i], zHigh);
  456. }
  457. glEnd();
  458. }
  459. glEndList();
  460. }
  461. /*----------------------------------------------------------------------\
  462. | pipeSphere() |
  463. | |
  464. \----------------------------------------------------------------------*/
  465. void
  466. SPHERE_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, GLfloat radius,
  467. GLfloat s_start, GLfloat s_end)
  468. {
  469. GLint i,j,max;
  470. GLfloat sinCache1a[CACHE_SIZE];
  471. GLfloat cosCache1a[CACHE_SIZE];
  472. GLfloat sinCache2a[CACHE_SIZE];
  473. GLfloat cosCache2a[CACHE_SIZE];
  474. GLfloat sinCache1b[CACHE_SIZE];
  475. GLfloat cosCache1b[CACHE_SIZE];
  476. GLfloat sinCache2b[CACHE_SIZE];
  477. GLfloat cosCache2b[CACHE_SIZE];
  478. GLfloat angle;
  479. GLfloat x, y, zLow, zHigh;
  480. GLfloat sintemp1, sintemp2, sintemp3, sintemp4;
  481. GLfloat costemp1, costemp2, costemp3, costemp4;
  482. GLfloat zNormal;
  483. GLfloat s_delta;
  484. GLint start, finish;
  485. GLint stacks, slices;
  486. BOOL bTexture = pBuildInfo->bTexture;
  487. IPOINT2D *texRep = pBuildInfo->texRep;
  488. slices = pBuildInfo->nSlices;
  489. stacks = slices;
  490. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  491. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  492. // invert sense of s - it seems the glu sphere is not built similarly
  493. // to the glu cylinder
  494. // (this probably means stacks don't grow along +z - check it out)
  495. s_delta = s_start;
  496. s_start = s_end;
  497. s_end = s_delta;
  498. s_delta = s_end - s_start;
  499. /* Cache is the vertex locations cache */
  500. /* Cache2 is the various normals at the vertices themselves */
  501. for (i = 0; i < slices; i++) {
  502. angle = 2 * PI * i / slices;
  503. sinCache1a[i] = (float) SIN(angle);
  504. cosCache1a[i] = (float) COS(angle);
  505. sinCache2a[i] = sinCache1a[i];
  506. cosCache2a[i] = cosCache1a[i];
  507. }
  508. for (j = 0; j <= stacks; j++) {
  509. angle = PI * j / stacks;
  510. sinCache2b[j] = (float) SIN(angle);
  511. cosCache2b[j] = (float) COS(angle);
  512. sinCache1b[j] = radius * (float) SIN(angle);
  513. cosCache1b[j] = radius * (float) COS(angle);
  514. }
  515. /* Make sure it comes to a point */
  516. sinCache1b[0] = 0.0f;
  517. sinCache1b[stacks] = 0.0f;
  518. sinCache1a[slices] = sinCache1a[0];
  519. cosCache1a[slices] = cosCache1a[0];
  520. sinCache2a[slices] = sinCache2a[0];
  521. cosCache2a[slices] = cosCache2a[0];
  522. glNewList(listNum, GL_COMPILE);
  523. /* Do ends of sphere as TRIANGLE_FAN's (if not bTexture)
  524. ** We don't do it when bTexture because we need to respecify the
  525. ** texture coordinates of the apex for every adjacent vertex (because
  526. ** it isn't a constant for that point)
  527. */
  528. if (!bTexture) {
  529. start = 1;
  530. finish = stacks - 1;
  531. /* Low end first (j == 0 iteration) */
  532. sintemp2 = sinCache1b[1];
  533. zHigh = cosCache1b[1];
  534. sintemp3 = sinCache2b[1];
  535. costemp3 = cosCache2b[1];
  536. glNormal3f(sinCache2a[0] * sinCache2b[0],
  537. cosCache2a[0] * sinCache2b[0],
  538. cosCache2b[0]);
  539. glBegin(GL_TRIANGLE_FAN);
  540. glVertex3f(0.0f, 0.0f, radius);
  541. for (i = slices; i >= 0; i--) {
  542. glNormal3f(sinCache2a[i] * sintemp3,
  543. cosCache2a[i] * sintemp3,
  544. costemp3);
  545. glVertex3f(sintemp2 * sinCache1a[i],
  546. sintemp2 * cosCache1a[i], zHigh);
  547. }
  548. glEnd();
  549. /* High end next (j == stacks-1 iteration) */
  550. sintemp2 = sinCache1b[stacks-1];
  551. zHigh = cosCache1b[stacks-1];
  552. sintemp3 = sinCache2b[stacks-1];
  553. costemp3 = cosCache2b[stacks-1];
  554. glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
  555. cosCache2a[stacks] * sinCache2b[stacks],
  556. cosCache2b[stacks]);
  557. glBegin(GL_TRIANGLE_FAN);
  558. glVertex3f(0.0f, 0.0f, -radius);
  559. for (i = 0; i <= slices; i++) {
  560. glNormal3f(sinCache2a[i] * sintemp3,
  561. cosCache2a[i] * sintemp3,
  562. costemp3);
  563. glVertex3f(sintemp2 * sinCache1a[i],
  564. sintemp2 * cosCache1a[i], zHigh);
  565. }
  566. glEnd();
  567. } else {
  568. start = 0;
  569. finish = stacks;
  570. }
  571. for (j = start; j < finish; j++) {
  572. zLow = cosCache1b[j];
  573. zHigh = cosCache1b[j+1];
  574. sintemp1 = sinCache1b[j];
  575. sintemp2 = sinCache1b[j+1];
  576. sintemp3 = sinCache2b[j+1];
  577. costemp3 = cosCache2b[j+1];
  578. sintemp4 = sinCache2b[j];
  579. costemp4 = cosCache2b[j];
  580. glBegin(GL_QUAD_STRIP);
  581. for (i = 0; i <= slices; i++) {
  582. glNormal3f(sinCache2a[i] * sintemp3,
  583. cosCache2a[i] * sintemp3,
  584. costemp3);
  585. if (bTexture) {
  586. glTexCoord2f( (float) s_start + s_delta*(j+1) / stacks,
  587. (float) i * texRep->y / slices );
  588. }
  589. glVertex3f(sintemp2 * sinCache1a[i],
  590. sintemp2 * cosCache1a[i], zHigh);
  591. glNormal3f(sinCache2a[i] * sintemp4,
  592. cosCache2a[i] * sintemp4,
  593. costemp4);
  594. if (bTexture) {
  595. glTexCoord2f( (float) s_start + s_delta * j / stacks,
  596. (float) i * texRep->y / slices );
  597. }
  598. glVertex3f(sintemp1 * sinCache1a[i],
  599. sintemp1 * cosCache1a[i], zLow);
  600. }
  601. glEnd();
  602. }
  603. glEndList();
  604. }