Leaked source code of windows server 2003
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.

1158 lines
30 KiB

  1. /*
  2. ** Copyright 1992, Silicon Graphics, Inc.
  3. ** All Rights Reserved.
  4. **
  5. ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6. ** the contents of this file may not be disclosed to third parties, copied or
  7. ** duplicated in any form, in whole or in part, without the prior written
  8. ** permission of Silicon Graphics, Inc.
  9. **
  10. ** RESTRICTED RIGHTS LEGEND:
  11. ** Use, duplication or disclosure by the Government is subject to restrictions
  12. ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13. ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14. ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15. ** rights reserved under the Copyright Laws of the United States.
  16. **
  17. ** $Revision: 1.5 $
  18. ** $Date: 1996/04/02 00:42:17 $
  19. */
  20. #ifdef NT
  21. #include <glos.h>
  22. #endif
  23. #include "gluint.h"
  24. #include <stdio.h>
  25. #ifndef NT
  26. #include <stdlib.h>
  27. #else
  28. #include "winmem.h"
  29. #endif
  30. #include <math.h>
  31. #include <GL/gl.h>
  32. #include <GL/glu.h>
  33. /* Make it not a power of two to avoid cache thrashing on the chip */
  34. #define CACHE_SIZE 240
  35. #define PI 3.14159265358979323846
  36. struct GLUquadric {
  37. GLint normals;
  38. GLboolean textureCoords;
  39. GLint orientation;
  40. GLint drawStyle;
  41. #ifdef NT
  42. GLUquadricErrorProc errorCallback;
  43. #else
  44. void (*errorCallback)( GLint );
  45. #endif
  46. };
  47. GLUquadric * APIENTRY gluNewQuadric(void)
  48. {
  49. GLUquadric *newstate;
  50. newstate = (GLUquadric *) malloc(sizeof(GLUquadric));
  51. if (newstate == NULL) {
  52. /* Can't report an error at this point... */
  53. return NULL;
  54. }
  55. newstate->normals = GLU_SMOOTH;
  56. newstate->textureCoords = GL_FALSE;
  57. newstate->orientation = GLU_OUTSIDE;
  58. newstate->drawStyle = GLU_FILL;
  59. #ifdef NT
  60. newstate->errorCallback = (GLUquadricErrorProc)NULL;
  61. #endif
  62. return newstate;
  63. }
  64. void APIENTRY gluDeleteQuadric(GLUquadric *state)
  65. {
  66. free(state);
  67. }
  68. static void gluQuadricError(GLUquadric *qobj, GLenum which)
  69. {
  70. if (qobj->errorCallback) {
  71. qobj->errorCallback(which);
  72. }
  73. }
  74. void APIENTRY gluQuadricCallback(GLUquadric *qobj, GLenum which, void (CALLBACK *fn)())
  75. {
  76. switch (which) {
  77. case GLU_ERROR:
  78. #ifdef NT
  79. qobj->errorCallback = (GLUquadricErrorProc) fn;
  80. #else
  81. qobj->errorCallback = (void (*)(GLint)) fn;
  82. #endif
  83. break;
  84. default:
  85. gluQuadricError(qobj, GLU_INVALID_ENUM);
  86. return;
  87. }
  88. }
  89. void APIENTRY gluQuadricNormals(GLUquadric *qobj, GLenum normals)
  90. {
  91. switch (normals) {
  92. case GLU_SMOOTH:
  93. case GLU_FLAT:
  94. case GLU_NONE:
  95. break;
  96. default:
  97. gluQuadricError(qobj, GLU_INVALID_ENUM);
  98. return;
  99. }
  100. qobj->normals = normals;
  101. }
  102. void APIENTRY gluQuadricTexture(GLUquadric *qobj, GLboolean textureCoords)
  103. {
  104. qobj->textureCoords = textureCoords;
  105. }
  106. void APIENTRY gluQuadricOrientation(GLUquadric *qobj, GLenum orientation)
  107. {
  108. switch(orientation) {
  109. case GLU_OUTSIDE:
  110. case GLU_INSIDE:
  111. break;
  112. default:
  113. gluQuadricError(qobj, GLU_INVALID_ENUM);
  114. return;
  115. }
  116. qobj->orientation = orientation;
  117. }
  118. void APIENTRY gluQuadricDrawStyle(GLUquadric *qobj, GLenum drawStyle)
  119. {
  120. switch(drawStyle) {
  121. case GLU_POINT:
  122. case GLU_LINE:
  123. case GLU_FILL:
  124. case GLU_SILHOUETTE:
  125. break;
  126. default:
  127. gluQuadricError(qobj, GLU_INVALID_ENUM);
  128. return;
  129. }
  130. qobj->drawStyle = drawStyle;
  131. }
  132. void APIENTRY gluCylinder(GLUquadric *qobj, GLdouble baseRadius, GLdouble topRadius,
  133. GLdouble height, GLint slices, GLint stacks)
  134. {
  135. GLint i,j,max;
  136. GLfloat sinCache[CACHE_SIZE];
  137. GLfloat cosCache[CACHE_SIZE];
  138. GLfloat sinCache2[CACHE_SIZE];
  139. GLfloat cosCache2[CACHE_SIZE];
  140. GLfloat sinCache3[CACHE_SIZE];
  141. GLfloat cosCache3[CACHE_SIZE];
  142. GLfloat angle;
  143. GLfloat x, y, zLow, zHigh;
  144. GLfloat sintemp, costemp;
  145. GLfloat length;
  146. GLfloat deltaRadius;
  147. GLfloat zNormal;
  148. GLfloat xyNormalRatio;
  149. GLfloat radiusLow, radiusHigh;
  150. int needCache2, needCache3;
  151. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  152. if (slices < 2 || stacks < 1 || baseRadius < 0.0 || topRadius < 0.0 ||
  153. height < 0.0) {
  154. gluQuadricError(qobj, GLU_INVALID_VALUE);
  155. return;
  156. }
  157. /* Compute length (needed for normal calculations) */
  158. deltaRadius = baseRadius - topRadius;
  159. length = SQRT(deltaRadius*deltaRadius + height*height);
  160. #ifdef NT
  161. if (length == (GLfloat)0.0) {
  162. #else
  163. if (length == 0.0) {
  164. #endif
  165. gluQuadricError(qobj, GLU_INVALID_VALUE);
  166. return;
  167. }
  168. /* Cache is the vertex locations cache */
  169. /* Cache2 is the various normals at the vertices themselves */
  170. /* Cache3 is the various normals for the faces */
  171. needCache2 = needCache3 = 0;
  172. if (qobj->normals == GLU_SMOOTH) {
  173. needCache2 = 1;
  174. }
  175. if (qobj->normals == GLU_FLAT) {
  176. if (qobj->drawStyle != GLU_POINT) {
  177. needCache3 = 1;
  178. }
  179. if (qobj->drawStyle == GLU_LINE) {
  180. needCache2 = 1;
  181. }
  182. }
  183. zNormal = deltaRadius / length;
  184. xyNormalRatio = height / length;
  185. for (i = 0; i < slices; i++) {
  186. angle = 2 * PI * i / slices;
  187. if (needCache2) {
  188. if (qobj->orientation == GLU_OUTSIDE) {
  189. sinCache2[i] = xyNormalRatio * SIN(angle);
  190. cosCache2[i] = xyNormalRatio * COS(angle);
  191. } else {
  192. sinCache2[i] = -xyNormalRatio * SIN(angle);
  193. cosCache2[i] = -xyNormalRatio * COS(angle);
  194. }
  195. }
  196. sinCache[i] = SIN(angle);
  197. cosCache[i] = COS(angle);
  198. }
  199. if (needCache3) {
  200. for (i = 0; i < slices; i++) {
  201. angle = 2 * PI * (i-0.5) / slices;
  202. if (qobj->orientation == GLU_OUTSIDE) {
  203. sinCache3[i] = xyNormalRatio * SIN(angle);
  204. cosCache3[i] = xyNormalRatio * COS(angle);
  205. } else {
  206. sinCache3[i] = -xyNormalRatio * SIN(angle);
  207. cosCache3[i] = -xyNormalRatio * COS(angle);
  208. }
  209. }
  210. }
  211. sinCache[slices] = sinCache[0];
  212. cosCache[slices] = cosCache[0];
  213. if (needCache2) {
  214. sinCache2[slices] = sinCache2[0];
  215. cosCache2[slices] = cosCache2[0];
  216. }
  217. if (needCache3) {
  218. sinCache3[slices] = sinCache3[0];
  219. cosCache3[slices] = cosCache3[0];
  220. }
  221. switch (qobj->drawStyle) {
  222. case GLU_FILL:
  223. /* Note:
  224. ** An argument could be made for using a TRIANGLE_FAN for the end
  225. ** of the cylinder of either radii is 0.0 (a cone). However, a
  226. ** TRIANGLE_FAN would not work in smooth shading mode (the common
  227. ** case) because the normal for the apex is different for every
  228. ** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
  229. ** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
  230. ** just let the GL trivially reject one of the two triangles of the
  231. ** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
  232. ** alone.
  233. */
  234. for (j = 0; j < stacks; j++) {
  235. zLow = j * height / stacks;
  236. zHigh = (j + 1) * height / stacks;
  237. radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
  238. radiusHigh = baseRadius - deltaRadius * ((float) (j + 1) / stacks);
  239. glBegin(GL_QUAD_STRIP);
  240. for (i = 0; i <= slices; i++) {
  241. switch(qobj->normals) {
  242. case GLU_FLAT:
  243. glNormal3f(sinCache3[i], cosCache3[i], zNormal);
  244. break;
  245. case GLU_SMOOTH:
  246. glNormal3f(sinCache2[i], cosCache2[i], zNormal);
  247. break;
  248. case GLU_NONE:
  249. default:
  250. break;
  251. }
  252. if (qobj->orientation == GLU_OUTSIDE) {
  253. if (qobj->textureCoords) {
  254. glTexCoord2f(1 - (float) i / slices,
  255. (float) j / stacks);
  256. }
  257. glVertex3f(radiusLow * sinCache[i],
  258. radiusLow * cosCache[i], zLow);
  259. if (qobj->textureCoords) {
  260. glTexCoord2f(1 - (float) i / slices,
  261. (float) (j+1) / stacks);
  262. }
  263. glVertex3f(radiusHigh * sinCache[i],
  264. radiusHigh * cosCache[i], zHigh);
  265. } else {
  266. if (qobj->textureCoords) {
  267. glTexCoord2f(1 - (float) i / slices,
  268. (float) (j+1) / stacks);
  269. }
  270. glVertex3f(radiusHigh * sinCache[i],
  271. radiusHigh * cosCache[i], zHigh);
  272. if (qobj->textureCoords) {
  273. glTexCoord2f(1 - (float) i / slices,
  274. (float) j / stacks);
  275. }
  276. glVertex3f(radiusLow * sinCache[i],
  277. radiusLow * cosCache[i], zLow);
  278. }
  279. }
  280. glEnd();
  281. }
  282. break;
  283. case GLU_POINT:
  284. glBegin(GL_POINTS);
  285. for (i = 0; i < slices; i++) {
  286. switch(qobj->normals) {
  287. case GLU_FLAT:
  288. case GLU_SMOOTH:
  289. glNormal3f(sinCache2[i], cosCache2[i], zNormal);
  290. break;
  291. case GLU_NONE:
  292. default:
  293. break;
  294. }
  295. sintemp = sinCache[i];
  296. costemp = cosCache[i];
  297. for (j = 0; j <= stacks; j++) {
  298. zLow = j * height / stacks;
  299. radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
  300. if (qobj->textureCoords) {
  301. glTexCoord2f(1 - (float) i / slices,
  302. (float) j / stacks);
  303. }
  304. glVertex3f(radiusLow * sintemp,
  305. radiusLow * costemp, zLow);
  306. }
  307. }
  308. glEnd();
  309. break;
  310. case GLU_LINE:
  311. for (j = 1; j < stacks; j++) {
  312. zLow = j * height / stacks;
  313. radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
  314. glBegin(GL_LINE_STRIP);
  315. for (i = 0; i <= slices; i++) {
  316. switch(qobj->normals) {
  317. case GLU_FLAT:
  318. glNormal3f(sinCache3[i], cosCache3[i], zNormal);
  319. break;
  320. case GLU_SMOOTH:
  321. glNormal3f(sinCache2[i], cosCache2[i], zNormal);
  322. break;
  323. case GLU_NONE:
  324. default:
  325. break;
  326. }
  327. if (qobj->textureCoords) {
  328. glTexCoord2f(1 - (float) i / slices,
  329. (float) j / stacks);
  330. }
  331. glVertex3f(radiusLow * sinCache[i],
  332. radiusLow * cosCache[i], zLow);
  333. }
  334. glEnd();
  335. }
  336. /* Intentionally fall through here... */
  337. case GLU_SILHOUETTE:
  338. for (j = 0; j <= stacks; j += stacks) {
  339. zLow = j * height / stacks;
  340. radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
  341. glBegin(GL_LINE_STRIP);
  342. for (i = 0; i <= slices; i++) {
  343. switch(qobj->normals) {
  344. case GLU_FLAT:
  345. glNormal3f(sinCache3[i], cosCache3[i], zNormal);
  346. break;
  347. case GLU_SMOOTH:
  348. glNormal3f(sinCache2[i], cosCache2[i], zNormal);
  349. break;
  350. case GLU_NONE:
  351. default:
  352. break;
  353. }
  354. if (qobj->textureCoords) {
  355. glTexCoord2f(1 - (float) i / slices,
  356. (float) j / stacks);
  357. }
  358. glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i],
  359. zLow);
  360. }
  361. glEnd();
  362. }
  363. for (i = 0; i < slices; i++) {
  364. switch(qobj->normals) {
  365. case GLU_FLAT:
  366. case GLU_SMOOTH:
  367. glNormal3f(sinCache2[i], cosCache2[i], 0.0);
  368. break;
  369. case GLU_NONE:
  370. default:
  371. break;
  372. }
  373. sintemp = sinCache[i];
  374. costemp = cosCache[i];
  375. glBegin(GL_LINE_STRIP);
  376. for (j = 0; j <= stacks; j++) {
  377. zLow = j * height / stacks;
  378. radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
  379. if (qobj->textureCoords) {
  380. glTexCoord2f(1 - (float) i / slices,
  381. (float) j / stacks);
  382. }
  383. glVertex3f(radiusLow * sintemp,
  384. radiusLow * costemp, zLow);
  385. }
  386. glEnd();
  387. }
  388. break;
  389. default:
  390. break;
  391. }
  392. }
  393. void APIENTRY gluDisk(GLUquadric *qobj, GLdouble innerRadius, GLdouble outerRadius,
  394. GLint slices, GLint loops)
  395. {
  396. gluPartialDisk(qobj, innerRadius, outerRadius, slices, loops, 0.0, 360.0);
  397. }
  398. void APIENTRY gluPartialDisk(GLUquadric *qobj, GLdouble innerRadius,
  399. GLdouble outerRadius, GLint slices, GLint loops,
  400. GLdouble startAngle, GLdouble sweepAngle)
  401. {
  402. GLint i,j,max;
  403. GLfloat sinCache[CACHE_SIZE];
  404. GLfloat cosCache[CACHE_SIZE];
  405. GLfloat angle;
  406. GLfloat x, y;
  407. GLfloat sintemp, costemp;
  408. GLfloat deltaRadius;
  409. GLfloat radiusLow, radiusHigh;
  410. GLfloat texLow, texHigh;
  411. GLfloat angleOffset;
  412. GLint slices2;
  413. GLint finish;
  414. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  415. if (slices < 2 || loops < 1 || outerRadius <= 0.0 || innerRadius < 0.0 ||
  416. innerRadius > outerRadius) {
  417. gluQuadricError(qobj, GLU_INVALID_VALUE);
  418. return;
  419. }
  420. if (sweepAngle < -360.0) sweepAngle = 360.0;
  421. if (sweepAngle > 360.0) sweepAngle = 360.0;
  422. if (sweepAngle < 0) {
  423. startAngle += sweepAngle;
  424. sweepAngle = -sweepAngle;
  425. }
  426. if (sweepAngle == 360.0) {
  427. slices2 = slices;
  428. } else {
  429. slices2 = slices + 1;
  430. }
  431. /* Compute length (needed for normal calculations) */
  432. deltaRadius = outerRadius - innerRadius;
  433. /* Cache is the vertex locations cache */
  434. angleOffset = startAngle / 180.0 * PI;
  435. for (i = 0; i <= slices; i++) {
  436. angle = angleOffset + ((PI * sweepAngle) / 180.0) * i / slices;
  437. sinCache[i] = SIN(angle);
  438. cosCache[i] = COS(angle);
  439. }
  440. if (sweepAngle == 360.0) {
  441. sinCache[slices] = sinCache[0];
  442. cosCache[slices] = cosCache[0];
  443. }
  444. switch(qobj->normals) {
  445. case GLU_FLAT:
  446. case GLU_SMOOTH:
  447. if (qobj->orientation == GLU_OUTSIDE) {
  448. glNormal3f(0.0, 0.0, 1.0);
  449. } else {
  450. glNormal3f(0.0, 0.0, -1.0);
  451. }
  452. break;
  453. default:
  454. case GLU_NONE:
  455. break;
  456. }
  457. switch (qobj->drawStyle) {
  458. case GLU_FILL:
  459. if (innerRadius == 0.0) {
  460. finish = loops - 1;
  461. /* Triangle strip for inner polygons */
  462. glBegin(GL_TRIANGLE_FAN);
  463. if (qobj->textureCoords) {
  464. glTexCoord2f(0.5, 0.5);
  465. }
  466. glVertex3f(0.0, 0.0, 0.0);
  467. radiusLow = outerRadius -
  468. deltaRadius * ((float) (loops-1) / loops);
  469. if (qobj->textureCoords) {
  470. texLow = radiusLow / outerRadius / 2;
  471. }
  472. if (qobj->orientation == GLU_OUTSIDE) {
  473. for (i = slices; i >= 0; i--) {
  474. if (qobj->textureCoords) {
  475. glTexCoord2f(texLow * sinCache[i] + 0.5,
  476. texLow * cosCache[i] + 0.5);
  477. }
  478. glVertex3f(radiusLow * sinCache[i],
  479. radiusLow * cosCache[i], 0.0);
  480. }
  481. } else {
  482. for (i = 0; i <= slices; i++) {
  483. if (qobj->textureCoords) {
  484. glTexCoord2f(texLow * sinCache[i] + 0.5,
  485. texLow * cosCache[i] + 0.5);
  486. }
  487. glVertex3f(radiusLow * sinCache[i],
  488. radiusLow * cosCache[i], 0.0);
  489. }
  490. }
  491. glEnd();
  492. } else {
  493. finish = loops;
  494. }
  495. for (j = 0; j < finish; j++) {
  496. radiusLow = outerRadius - deltaRadius * ((float) j / loops);
  497. radiusHigh = outerRadius - deltaRadius * ((float) (j + 1) / loops);
  498. if (qobj->textureCoords) {
  499. texLow = radiusLow / outerRadius / 2;
  500. texHigh = radiusHigh / outerRadius / 2;
  501. }
  502. glBegin(GL_QUAD_STRIP);
  503. for (i = 0; i <= slices; i++) {
  504. if (qobj->orientation == GLU_OUTSIDE) {
  505. if (qobj->textureCoords) {
  506. glTexCoord2f(texLow * sinCache[i] + 0.5,
  507. texLow * cosCache[i] + 0.5);
  508. }
  509. glVertex3f(radiusLow * sinCache[i],
  510. radiusLow * cosCache[i], 0.0);
  511. if (qobj->textureCoords) {
  512. glTexCoord2f(texHigh * sinCache[i] + 0.5,
  513. texHigh * cosCache[i] + 0.5);
  514. }
  515. glVertex3f(radiusHigh * sinCache[i],
  516. radiusHigh * cosCache[i], 0.0);
  517. } else {
  518. if (qobj->textureCoords) {
  519. glTexCoord2f(texHigh * sinCache[i] + 0.5,
  520. texHigh * cosCache[i] + 0.5);
  521. }
  522. glVertex3f(radiusHigh * sinCache[i],
  523. radiusHigh * cosCache[i], 0.0);
  524. if (qobj->textureCoords) {
  525. glTexCoord2f(texLow * sinCache[i] + 0.5,
  526. texLow * cosCache[i] + 0.5);
  527. }
  528. glVertex3f(radiusLow * sinCache[i],
  529. radiusLow * cosCache[i], 0.0);
  530. }
  531. }
  532. glEnd();
  533. }
  534. break;
  535. case GLU_POINT:
  536. glBegin(GL_POINTS);
  537. for (i = 0; i < slices2; i++) {
  538. sintemp = sinCache[i];
  539. costemp = cosCache[i];
  540. for (j = 0; j <= loops; j++) {
  541. radiusLow = outerRadius - deltaRadius * ((float) j / loops);
  542. if (qobj->textureCoords) {
  543. texLow = radiusLow / outerRadius / 2;
  544. glTexCoord2f(texLow * sinCache[i] + 0.5,
  545. texLow * cosCache[i] + 0.5);
  546. }
  547. glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
  548. }
  549. }
  550. glEnd();
  551. break;
  552. case GLU_LINE:
  553. if (innerRadius == outerRadius) {
  554. glBegin(GL_LINE_STRIP);
  555. for (i = 0; i <= slices; i++) {
  556. if (qobj->textureCoords) {
  557. glTexCoord2f(sinCache[i] / 2 + 0.5,
  558. cosCache[i] / 2 + 0.5);
  559. }
  560. glVertex3f(innerRadius * sinCache[i],
  561. innerRadius * cosCache[i], 0.0);
  562. }
  563. glEnd();
  564. break;
  565. }
  566. for (j = 0; j <= loops; j++) {
  567. radiusLow = outerRadius - deltaRadius * ((float) j / loops);
  568. if (qobj->textureCoords) {
  569. texLow = radiusLow / outerRadius / 2;
  570. }
  571. glBegin(GL_LINE_STRIP);
  572. for (i = 0; i <= slices; i++) {
  573. if (qobj->textureCoords) {
  574. glTexCoord2f(texLow * sinCache[i] + 0.5,
  575. texLow * cosCache[i] + 0.5);
  576. }
  577. glVertex3f(radiusLow * sinCache[i],
  578. radiusLow * cosCache[i], 0.0);
  579. }
  580. glEnd();
  581. }
  582. for (i=0; i < slices2; i++) {
  583. sintemp = sinCache[i];
  584. costemp = cosCache[i];
  585. glBegin(GL_LINE_STRIP);
  586. for (j = 0; j <= loops; j++) {
  587. radiusLow = outerRadius - deltaRadius * ((float) j / loops);
  588. if (qobj->textureCoords) {
  589. texLow = radiusLow / outerRadius / 2;
  590. }
  591. if (qobj->textureCoords) {
  592. glTexCoord2f(texLow * sinCache[i] + 0.5,
  593. texLow * cosCache[i] + 0.5);
  594. }
  595. glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
  596. }
  597. glEnd();
  598. }
  599. break;
  600. case GLU_SILHOUETTE:
  601. if (sweepAngle < 360.0) {
  602. for (i = 0; i <= slices; i+= slices) {
  603. sintemp = sinCache[i];
  604. costemp = cosCache[i];
  605. glBegin(GL_LINE_STRIP);
  606. for (j = 0; j <= loops; j++) {
  607. radiusLow = outerRadius - deltaRadius * ((float) j / loops);
  608. if (qobj->textureCoords) {
  609. texLow = radiusLow / outerRadius / 2;
  610. glTexCoord2f(texLow * sinCache[i] + 0.5,
  611. texLow * cosCache[i] + 0.5);
  612. }
  613. glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
  614. }
  615. glEnd();
  616. }
  617. }
  618. for (j = 0; j <= loops; j += loops) {
  619. radiusLow = outerRadius - deltaRadius * ((float) j / loops);
  620. if (qobj->textureCoords) {
  621. texLow = radiusLow / outerRadius / 2;
  622. }
  623. glBegin(GL_LINE_STRIP);
  624. for (i = 0; i <= slices; i++) {
  625. if (qobj->textureCoords) {
  626. glTexCoord2f(texLow * sinCache[i] + 0.5,
  627. texLow * cosCache[i] + 0.5);
  628. }
  629. glVertex3f(radiusLow * sinCache[i],
  630. radiusLow * cosCache[i], 0.0);
  631. }
  632. glEnd();
  633. if (innerRadius == outerRadius) break;
  634. }
  635. break;
  636. default:
  637. break;
  638. }
  639. }
  640. void APIENTRY gluSphere(GLUquadric *qobj, GLdouble radius, GLint slices, GLint stacks)
  641. {
  642. GLint i,j,max;
  643. GLfloat sinCache1a[CACHE_SIZE];
  644. GLfloat cosCache1a[CACHE_SIZE];
  645. GLfloat sinCache2a[CACHE_SIZE];
  646. GLfloat cosCache2a[CACHE_SIZE];
  647. GLfloat sinCache3a[CACHE_SIZE];
  648. GLfloat cosCache3a[CACHE_SIZE];
  649. GLfloat sinCache1b[CACHE_SIZE];
  650. GLfloat cosCache1b[CACHE_SIZE];
  651. GLfloat sinCache2b[CACHE_SIZE];
  652. GLfloat cosCache2b[CACHE_SIZE];
  653. GLfloat sinCache3b[CACHE_SIZE];
  654. GLfloat cosCache3b[CACHE_SIZE];
  655. GLfloat angle;
  656. GLfloat x, y, zLow, zHigh;
  657. GLfloat sintemp1, sintemp2, sintemp3, sintemp4;
  658. GLfloat costemp1, costemp2, costemp3, costemp4;
  659. GLfloat zNormal;
  660. GLfloat xyNormalRatio;
  661. GLboolean needCache2, needCache3;
  662. GLint start, finish;
  663. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  664. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  665. if (slices < 2 || stacks < 1 || radius < 0.0) {
  666. gluQuadricError(qobj, GLU_INVALID_VALUE);
  667. return;
  668. }
  669. /* Cache is the vertex locations cache */
  670. /* Cache2 is the various normals at the vertices themselves */
  671. /* Cache3 is the various normals for the faces */
  672. needCache2 = needCache3 = GL_FALSE;
  673. if (qobj->normals == GLU_SMOOTH) {
  674. needCache2 = GL_TRUE;
  675. }
  676. if (qobj->normals == GLU_FLAT) {
  677. if (qobj->drawStyle != GLU_POINT) {
  678. needCache3 = GL_TRUE;
  679. }
  680. if (qobj->drawStyle == GLU_LINE) {
  681. needCache2 = GL_TRUE;
  682. }
  683. }
  684. for (i = 0; i < slices; i++) {
  685. angle = 2 * PI * i / slices;
  686. sinCache1a[i] = SIN(angle);
  687. cosCache1a[i] = COS(angle);
  688. if (needCache2) {
  689. sinCache2a[i] = sinCache1a[i];
  690. cosCache2a[i] = cosCache1a[i];
  691. }
  692. }
  693. for (j = 0; j <= stacks; j++) {
  694. angle = PI * j / stacks;
  695. if (needCache2) {
  696. if (qobj->orientation == GLU_OUTSIDE) {
  697. sinCache2b[j] = SIN(angle);
  698. cosCache2b[j] = COS(angle);
  699. } else {
  700. sinCache2b[j] = -SIN(angle);
  701. cosCache2b[j] = -COS(angle);
  702. }
  703. }
  704. sinCache1b[j] = radius * SIN(angle);
  705. cosCache1b[j] = radius * COS(angle);
  706. }
  707. /* Make sure it comes to a point */
  708. sinCache1b[0] = 0;
  709. sinCache1b[stacks] = 0;
  710. if (needCache3) {
  711. for (i = 0; i < slices; i++) {
  712. angle = 2 * PI * (i-0.5) / slices;
  713. sinCache3a[i] = SIN(angle);
  714. cosCache3a[i] = COS(angle);
  715. }
  716. for (j = 0; j <= stacks; j++) {
  717. angle = PI * (j - 0.5) / stacks;
  718. if (qobj->orientation == GLU_OUTSIDE) {
  719. sinCache3b[j] = SIN(angle);
  720. cosCache3b[j] = COS(angle);
  721. } else {
  722. sinCache3b[j] = -SIN(angle);
  723. cosCache3b[j] = -COS(angle);
  724. }
  725. }
  726. }
  727. sinCache1a[slices] = sinCache1a[0];
  728. cosCache1a[slices] = cosCache1a[0];
  729. if (needCache2) {
  730. sinCache2a[slices] = sinCache2a[0];
  731. cosCache2a[slices] = cosCache2a[0];
  732. }
  733. if (needCache3) {
  734. sinCache3a[slices] = sinCache3a[0];
  735. cosCache3a[slices] = cosCache3a[0];
  736. }
  737. switch (qobj->drawStyle) {
  738. case GLU_FILL:
  739. /* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
  740. ** We don't do it when texturing because we need to respecify the
  741. ** texture coordinates of the apex for every adjacent vertex (because
  742. ** it isn't a constant for that point)
  743. */
  744. if (!(qobj->textureCoords)) {
  745. start = 1;
  746. finish = stacks - 1;
  747. /* Low end first (j == 0 iteration) */
  748. sintemp2 = sinCache1b[1];
  749. zHigh = cosCache1b[1];
  750. switch(qobj->normals) {
  751. case GLU_FLAT:
  752. sintemp3 = sinCache3b[1];
  753. costemp3 = cosCache3b[1];
  754. break;
  755. case GLU_SMOOTH:
  756. sintemp3 = sinCache2b[1];
  757. costemp3 = cosCache2b[1];
  758. glNormal3f(sinCache2a[0] * sinCache2b[0],
  759. cosCache2a[0] * sinCache2b[0],
  760. cosCache2b[0]);
  761. break;
  762. default:
  763. break;
  764. }
  765. glBegin(GL_TRIANGLE_FAN);
  766. glVertex3f(0.0, 0.0, radius);
  767. if (qobj->orientation == GLU_OUTSIDE) {
  768. for (i = slices; i >= 0; i--) {
  769. switch(qobj->normals) {
  770. case GLU_SMOOTH:
  771. glNormal3f(sinCache2a[i] * sintemp3,
  772. cosCache2a[i] * sintemp3,
  773. costemp3);
  774. break;
  775. case GLU_FLAT:
  776. if (i != slices) {
  777. glNormal3f(sinCache3a[i+1] * sintemp3,
  778. cosCache3a[i+1] * sintemp3,
  779. costemp3);
  780. }
  781. break;
  782. case GLU_NONE:
  783. default:
  784. break;
  785. }
  786. glVertex3f(sintemp2 * sinCache1a[i],
  787. sintemp2 * cosCache1a[i], zHigh);
  788. }
  789. } else {
  790. for (i = 0; i <= slices; i++) {
  791. switch(qobj->normals) {
  792. case GLU_SMOOTH:
  793. glNormal3f(sinCache2a[i] * sintemp3,
  794. cosCache2a[i] * sintemp3,
  795. costemp3);
  796. break;
  797. case GLU_FLAT:
  798. glNormal3f(sinCache3a[i] * sintemp3,
  799. cosCache3a[i] * sintemp3,
  800. costemp3);
  801. break;
  802. case GLU_NONE:
  803. default:
  804. break;
  805. }
  806. glVertex3f(sintemp2 * sinCache1a[i],
  807. sintemp2 * cosCache1a[i], zHigh);
  808. }
  809. }
  810. glEnd();
  811. /* High end next (j == stacks-1 iteration) */
  812. sintemp2 = sinCache1b[stacks-1];
  813. zHigh = cosCache1b[stacks-1];
  814. switch(qobj->normals) {
  815. case GLU_FLAT:
  816. sintemp3 = sinCache3b[stacks];
  817. costemp3 = cosCache3b[stacks];
  818. break;
  819. case GLU_SMOOTH:
  820. sintemp3 = sinCache2b[stacks-1];
  821. costemp3 = cosCache2b[stacks-1];
  822. glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
  823. cosCache2a[stacks] * sinCache2b[stacks],
  824. cosCache2b[stacks]);
  825. break;
  826. default:
  827. break;
  828. }
  829. glBegin(GL_TRIANGLE_FAN);
  830. glVertex3f(0.0, 0.0, -radius);
  831. if (qobj->orientation == GLU_OUTSIDE) {
  832. for (i = 0; i <= slices; i++) {
  833. switch(qobj->normals) {
  834. case GLU_SMOOTH:
  835. glNormal3f(sinCache2a[i] * sintemp3,
  836. cosCache2a[i] * sintemp3,
  837. costemp3);
  838. break;
  839. case GLU_FLAT:
  840. glNormal3f(sinCache3a[i] * sintemp3,
  841. cosCache3a[i] * sintemp3,
  842. costemp3);
  843. break;
  844. case GLU_NONE:
  845. default:
  846. break;
  847. }
  848. glVertex3f(sintemp2 * sinCache1a[i],
  849. sintemp2 * cosCache1a[i], zHigh);
  850. }
  851. } else {
  852. for (i = slices; i >= 0; i--) {
  853. switch(qobj->normals) {
  854. case GLU_SMOOTH:
  855. glNormal3f(sinCache2a[i] * sintemp3,
  856. cosCache2a[i] * sintemp3,
  857. costemp3);
  858. break;
  859. case GLU_FLAT:
  860. if (i != slices) {
  861. glNormal3f(sinCache3a[i+1] * sintemp3,
  862. cosCache3a[i+1] * sintemp3,
  863. costemp3);
  864. }
  865. break;
  866. case GLU_NONE:
  867. default:
  868. break;
  869. }
  870. glVertex3f(sintemp2 * sinCache1a[i],
  871. sintemp2 * cosCache1a[i], zHigh);
  872. }
  873. }
  874. glEnd();
  875. } else {
  876. start = 0;
  877. finish = stacks;
  878. }
  879. for (j = start; j < finish; j++) {
  880. zLow = cosCache1b[j];
  881. zHigh = cosCache1b[j+1];
  882. sintemp1 = sinCache1b[j];
  883. sintemp2 = sinCache1b[j+1];
  884. switch(qobj->normals) {
  885. case GLU_FLAT:
  886. sintemp4 = sinCache3b[j+1];
  887. costemp4 = cosCache3b[j+1];
  888. break;
  889. case GLU_SMOOTH:
  890. if (qobj->orientation == GLU_OUTSIDE) {
  891. sintemp3 = sinCache2b[j+1];
  892. costemp3 = cosCache2b[j+1];
  893. sintemp4 = sinCache2b[j];
  894. costemp4 = cosCache2b[j];
  895. } else {
  896. sintemp3 = sinCache2b[j];
  897. costemp3 = cosCache2b[j];
  898. sintemp4 = sinCache2b[j+1];
  899. costemp4 = cosCache2b[j+1];
  900. }
  901. break;
  902. default:
  903. break;
  904. }
  905. glBegin(GL_QUAD_STRIP);
  906. for (i = 0; i <= slices; i++) {
  907. switch(qobj->normals) {
  908. case GLU_SMOOTH:
  909. glNormal3f(sinCache2a[i] * sintemp3,
  910. cosCache2a[i] * sintemp3,
  911. costemp3);
  912. break;
  913. case GLU_FLAT:
  914. case GLU_NONE:
  915. default:
  916. break;
  917. }
  918. if (qobj->orientation == GLU_OUTSIDE) {
  919. if (qobj->textureCoords) {
  920. glTexCoord2f(1 - (float) i / slices,
  921. 1 - (float) (j+1) / stacks);
  922. }
  923. glVertex3f(sintemp2 * sinCache1a[i],
  924. sintemp2 * cosCache1a[i], zHigh);
  925. } else {
  926. if (qobj->textureCoords) {
  927. glTexCoord2f(1 - (float) i / slices,
  928. 1 - (float) j / stacks);
  929. }
  930. glVertex3f(sintemp1 * sinCache1a[i],
  931. sintemp1 * cosCache1a[i], zLow);
  932. }
  933. switch(qobj->normals) {
  934. case GLU_SMOOTH:
  935. glNormal3f(sinCache2a[i] * sintemp4,
  936. cosCache2a[i] * sintemp4,
  937. costemp4);
  938. break;
  939. case GLU_FLAT:
  940. glNormal3f(sinCache3a[i] * sintemp4,
  941. cosCache3a[i] * sintemp4,
  942. costemp4);
  943. break;
  944. case GLU_NONE:
  945. default:
  946. break;
  947. }
  948. if (qobj->orientation == GLU_OUTSIDE) {
  949. if (qobj->textureCoords) {
  950. glTexCoord2f(1 - (float) i / slices,
  951. 1 - (float) j / stacks);
  952. }
  953. glVertex3f(sintemp1 * sinCache1a[i],
  954. sintemp1 * cosCache1a[i], zLow);
  955. } else {
  956. if (qobj->textureCoords) {
  957. glTexCoord2f(1 - (float) i / slices,
  958. 1 - (float) (j+1) / stacks);
  959. }
  960. glVertex3f(sintemp2 * sinCache1a[i],
  961. sintemp2 * cosCache1a[i], zHigh);
  962. }
  963. }
  964. glEnd();
  965. }
  966. break;
  967. case GLU_POINT:
  968. glBegin(GL_POINTS);
  969. for (j = 0; j <= stacks; j++) {
  970. sintemp1 = sinCache1b[j];
  971. costemp1 = cosCache1b[j];
  972. switch(qobj->normals) {
  973. case GLU_FLAT:
  974. case GLU_SMOOTH:
  975. sintemp2 = sinCache2b[j];
  976. costemp2 = cosCache2b[j];
  977. break;
  978. default:
  979. break;
  980. }
  981. for (i = 0; i < slices; i++) {
  982. switch(qobj->normals) {
  983. case GLU_FLAT:
  984. case GLU_SMOOTH:
  985. glNormal3f(sinCache2a[i] * sintemp2,
  986. cosCache2a[i] * sintemp2,
  987. costemp2);
  988. break;
  989. case GLU_NONE:
  990. default:
  991. break;
  992. }
  993. zLow = j * radius / stacks;
  994. if (qobj->textureCoords) {
  995. glTexCoord2f(1 - (float) i / slices,
  996. 1 - (float) j / stacks);
  997. }
  998. glVertex3f(sintemp1 * sinCache1a[i],
  999. sintemp1 * cosCache1a[i], costemp1);
  1000. }
  1001. }
  1002. glEnd();
  1003. break;
  1004. case GLU_LINE:
  1005. case GLU_SILHOUETTE:
  1006. for (j = 1; j < stacks; j++) {
  1007. sintemp1 = sinCache1b[j];
  1008. costemp1 = cosCache1b[j];
  1009. switch(qobj->normals) {
  1010. case GLU_FLAT:
  1011. case GLU_SMOOTH:
  1012. sintemp2 = sinCache2b[j];
  1013. costemp2 = cosCache2b[j];
  1014. break;
  1015. default:
  1016. break;
  1017. }
  1018. glBegin(GL_LINE_STRIP);
  1019. for (i = 0; i <= slices; i++) {
  1020. switch(qobj->normals) {
  1021. case GLU_FLAT:
  1022. glNormal3f(sinCache3a[i] * sintemp2,
  1023. cosCache3a[i] * sintemp2,
  1024. costemp2);
  1025. break;
  1026. case GLU_SMOOTH:
  1027. glNormal3f(sinCache2a[i] * sintemp2,
  1028. cosCache2a[i] * sintemp2,
  1029. costemp2);
  1030. break;
  1031. case GLU_NONE:
  1032. default:
  1033. break;
  1034. }
  1035. if (qobj->textureCoords) {
  1036. glTexCoord2f(1 - (float) i / slices,
  1037. 1 - (float) j / stacks);
  1038. }
  1039. glVertex3f(sintemp1 * sinCache1a[i],
  1040. sintemp1 * cosCache1a[i], costemp1);
  1041. }
  1042. glEnd();
  1043. }
  1044. for (i = 0; i < slices; i++) {
  1045. sintemp1 = sinCache1a[i];
  1046. costemp1 = cosCache1a[i];
  1047. switch(qobj->normals) {
  1048. case GLU_FLAT:
  1049. case GLU_SMOOTH:
  1050. sintemp2 = sinCache2a[i];
  1051. costemp2 = cosCache2a[i];
  1052. break;
  1053. default:
  1054. break;
  1055. }
  1056. glBegin(GL_LINE_STRIP);
  1057. for (j = 0; j <= stacks; j++) {
  1058. switch(qobj->normals) {
  1059. case GLU_FLAT:
  1060. glNormal3f(sintemp2 * sinCache3b[j],
  1061. costemp2 * sinCache3b[j],
  1062. cosCache3b[j]);
  1063. break;
  1064. case GLU_SMOOTH:
  1065. glNormal3f(sintemp2 * sinCache2b[j],
  1066. costemp2 * sinCache2b[j],
  1067. cosCache2b[j]);
  1068. break;
  1069. case GLU_NONE:
  1070. default:
  1071. break;
  1072. }
  1073. if (qobj->textureCoords) {
  1074. glTexCoord2f(1 - (float) i / slices,
  1075. 1 - (float) j / stacks);
  1076. }
  1077. glVertex3f(sintemp1 * sinCache1b[j],
  1078. costemp1 * sinCache1b[j], cosCache1b[j]);
  1079. }
  1080. glEnd();
  1081. }
  1082. break;
  1083. default:
  1084. break;
  1085. }
  1086. }