Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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