Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/glaux/shapes.c
3203 views
1
/* shapes.c */
2
3
4
#include <stdio.h>
5
#include <stdlib.h>
6
#include <math.h>
7
8
#include <GL/gl.h>
9
#include <GL/glu.h>
10
11
#include "glaux.h"
12
#include "3d.h"
13
14
15
16
#define SPHEREWIRE 0
17
#define CUBEWIRE 1
18
#define BOXWIRE 2
19
#define TORUSWIRE 3
20
#define CYLINDERWIRE 4
21
#define ICOSAWIRE 5
22
#define OCTAWIRE 6
23
#define TETRAWIRE 7
24
#define DODECAWIRE 8
25
#define CONEWIRE 9
26
#define SPHERESOLID 10
27
#define CUBESOLID 11
28
#define BOXSOLID 12
29
#define TORUSSOLID 13
30
#define CYLINDERSOLID 14
31
#define ICOSASOLID 15
32
#define OCTASOLID 16
33
#define TETRASOLID 17
34
#define DODECASOLID 18
35
#define CONESOLID 19
36
37
#define PI 3.1415926535897
38
39
/* structure for each geometric object */
40
typedef struct model {
41
GLuint list; /* display list to render object */
42
struct model *ptr; /* pointer to next object */
43
int numParam; /* # of parameters */
44
GLdouble *params; /* array with parameters */
45
} MODEL, *MODELPTR;
46
47
/* array of linked lists--used to keep track of display lists
48
* for each different type of geometric object.
49
*/
50
static MODELPTR lists[25] = {
51
NULL, NULL, NULL, NULL, NULL,
52
NULL, NULL, NULL, NULL, NULL,
53
NULL, NULL, NULL, NULL, NULL,
54
NULL, NULL, NULL, NULL, NULL,
55
NULL, NULL, NULL, NULL, NULL
56
};
57
58
GLuint findList (int lindex, GLdouble *paramArray, int size);
59
int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size);
60
GLuint makeModelPtr (int lindex, GLdouble *sizeArray, int count);
61
62
static void drawbox(GLdouble, GLdouble, GLdouble,
63
GLdouble, GLdouble, GLdouble, GLenum);
64
static void doughnut(GLdouble, GLdouble, GLint, GLint, GLenum);
65
static void icosahedron(GLdouble *, GLdouble, GLenum);
66
static void octahedron(GLdouble *, GLdouble, GLenum);
67
static void tetrahedron(GLdouble *, GLdouble, GLenum);
68
static void subdivide(int, GLdouble *, GLdouble *, GLdouble *,
69
GLdouble *, GLdouble, GLenum, int);
70
static void drawtriangle(int, int, int,
71
GLdouble *, GLdouble, GLenum, int);
72
static void recorditem(GLdouble *, GLdouble *, GLdouble *,
73
GLdouble *, GLdouble, GLenum, int);
74
static void initdodec(void);
75
static void dodecahedron(GLdouble *, GLdouble, GLenum);
76
static void pentagon(int, int, int, int, int, GLenum);
77
78
79
/* Render wire frame or solid sphere. If no display list with
80
* the current model size exists, create a new display list.
81
*/
82
void auxWireSphere (GLdouble radius)
83
{
84
GLUquadricObj *quadObj;
85
GLdouble *sizeArray;
86
GLuint displayList;
87
88
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
89
*sizeArray = radius;
90
displayList = findList (SPHEREWIRE, sizeArray, 1);
91
92
if (displayList == 0) {
93
glNewList(makeModelPtr (SPHEREWIRE, sizeArray, 1),
94
GL_COMPILE_AND_EXECUTE);
95
quadObj = gluNewQuadric ();
96
gluQuadricDrawStyle (quadObj, GLU_LINE);
97
gluSphere (quadObj, radius, 16, 16);
98
glEndList();
99
}
100
else {
101
glCallList(displayList);
102
free (sizeArray);
103
}
104
}
105
106
void auxSolidSphere (GLdouble radius)
107
{
108
GLUquadricObj *quadObj;
109
GLdouble *sizeArray;
110
GLuint displayList;
111
112
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
113
*sizeArray = radius;
114
displayList = findList (SPHERESOLID, sizeArray, 1);
115
116
if (displayList == 0) {
117
glNewList(makeModelPtr (SPHERESOLID, sizeArray, 1),
118
GL_COMPILE_AND_EXECUTE);
119
quadObj = gluNewQuadric ();
120
gluQuadricDrawStyle (quadObj, GLU_FILL);
121
gluQuadricNormals (quadObj, GLU_SMOOTH);
122
gluSphere (quadObj, radius, 16, 16);
123
glEndList();
124
}
125
else {
126
glCallList(displayList);
127
free (sizeArray);
128
}
129
}
130
131
/* Render wire frame or solid cube. If no display list with
132
* the current model size exists, create a new display list.
133
*/
134
void auxWireCube (GLdouble size)
135
{
136
GLdouble *sizeArray;
137
GLuint displayList;
138
139
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
140
*sizeArray = size;
141
displayList = findList (CUBEWIRE, sizeArray, 1);
142
143
if (displayList == 0) {
144
glNewList(makeModelPtr (CUBEWIRE, sizeArray, 1),
145
GL_COMPILE_AND_EXECUTE);
146
drawbox(-size/2., size/2., -size/2., size/2.,
147
-size/2., size/2., GL_LINE_LOOP);
148
glEndList();
149
}
150
else {
151
glCallList(displayList);
152
free (sizeArray);
153
}
154
}
155
156
void auxSolidCube (GLdouble size)
157
{
158
GLdouble *sizeArray;
159
GLuint displayList;
160
161
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
162
*sizeArray = size;
163
displayList = findList (CUBESOLID, sizeArray, 1);
164
165
if (displayList == 0) {
166
glNewList(makeModelPtr (CUBESOLID, sizeArray, 1),
167
GL_COMPILE_AND_EXECUTE);
168
drawbox(-size/2., size/2., -size/2., size/2.,
169
-size/2., size/2., GL_QUADS);
170
glEndList();
171
}
172
else {
173
glCallList(displayList);
174
free (sizeArray);
175
}
176
}
177
178
/* Render wire frame or solid cube. If no display list with
179
* the current model size exists, create a new display list.
180
*/
181
void auxWireBox (GLdouble width, GLdouble height, GLdouble depth)
182
{
183
GLdouble *sizeArray, *tmp;
184
GLuint displayList;
185
186
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
187
tmp = sizeArray;
188
*tmp++ = width;
189
*tmp++ = height;
190
*tmp++ = depth;
191
displayList = findList (BOXWIRE, sizeArray, 3);
192
193
if (displayList == 0) {
194
glNewList(makeModelPtr (BOXWIRE, sizeArray, 3),
195
GL_COMPILE_AND_EXECUTE);
196
drawbox(-width/2., width/2., -height/2., height/2.,
197
-depth/2., depth/2., GL_LINE_LOOP);
198
glEndList();
199
}
200
else {
201
glCallList(displayList);
202
free (sizeArray);
203
}
204
}
205
206
void auxSolidBox (GLdouble width, GLdouble height, GLdouble depth)
207
{
208
GLdouble *sizeArray, *tmp;
209
GLuint displayList;
210
211
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
212
tmp = sizeArray;
213
*tmp++ = width;
214
*tmp++ = height;
215
*tmp++ = depth;
216
displayList = findList (BOXSOLID, sizeArray, 3);
217
218
if (displayList == 0) {
219
glNewList(makeModelPtr (BOXSOLID, sizeArray, 3),
220
GL_COMPILE_AND_EXECUTE);
221
drawbox(-width/2., width/2., -height/2., height/2.,
222
-depth/2., depth/2., GL_QUADS);
223
glEndList();
224
}
225
else {
226
glCallList(displayList);
227
free (sizeArray);
228
}
229
}
230
231
/* Render wire frame or solid tori. If no display list with
232
* the current model size exists, create a new display list.
233
*/
234
void auxWireTorus (GLdouble innerRadius, GLdouble outerRadius)
235
{
236
GLdouble *sizeArray, *tmp;
237
GLuint displayList;
238
239
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
240
tmp = sizeArray;
241
*tmp++ = innerRadius;
242
*tmp++ = outerRadius;
243
displayList = findList (TORUSWIRE, sizeArray, 2);
244
245
if (displayList == 0) {
246
glNewList(makeModelPtr (TORUSWIRE, sizeArray, 2),
247
GL_COMPILE_AND_EXECUTE);
248
doughnut(innerRadius, outerRadius, 5, 10, GL_LINE_LOOP);
249
glEndList();
250
}
251
else {
252
glCallList(displayList);
253
free (sizeArray);
254
}
255
}
256
257
void auxSolidTorus (GLdouble innerRadius, GLdouble outerRadius)
258
{
259
GLdouble *sizeArray, *tmp;
260
GLuint displayList;
261
262
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
263
tmp = sizeArray;
264
*tmp++ = innerRadius;
265
*tmp++ = outerRadius;
266
displayList = findList (TORUSSOLID, sizeArray, 2);
267
268
if (displayList == 0) {
269
glNewList(makeModelPtr (TORUSSOLID, sizeArray, 2),
270
GL_COMPILE_AND_EXECUTE);
271
doughnut(innerRadius, outerRadius, 8, 15, GL_QUADS);
272
glEndList();
273
}
274
else {
275
glCallList(displayList);
276
free (sizeArray);
277
}
278
}
279
280
/* Render wire frame or solid cylinders. If no display list with
281
* the current model size exists, create a new display list.
282
*/
283
void auxWireCylinder (GLdouble radius, GLdouble height)
284
{
285
GLUquadricObj *quadObj;
286
GLdouble *sizeArray, *tmp;
287
GLuint displayList;
288
289
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
290
tmp = sizeArray;
291
*tmp++ = radius;
292
*tmp++ = height;
293
displayList = findList (CYLINDERWIRE, sizeArray, 2);
294
295
if (displayList == 0) {
296
glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
297
GL_COMPILE_AND_EXECUTE);
298
glPushMatrix ();
299
glRotatef (90.0, 1.0, 0.0, 0.0);
300
glTranslatef (0.0, 0.0, -1.0);
301
quadObj = gluNewQuadric ();
302
gluQuadricDrawStyle (quadObj, GLU_LINE);
303
gluCylinder (quadObj, radius, radius, height, 12, 2);
304
glPopMatrix ();
305
glEndList();
306
}
307
else {
308
glCallList(displayList);
309
free (sizeArray);
310
}
311
}
312
313
void auxSolidCylinder (GLdouble radius, GLdouble height)
314
{
315
GLUquadricObj *quadObj;
316
GLdouble *sizeArray, *tmp;
317
GLuint displayList;
318
319
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
320
tmp = sizeArray;
321
*tmp++ = radius;
322
*tmp++ = height;
323
displayList = findList (CYLINDERWIRE, sizeArray, 2);
324
325
if (displayList == 0) {
326
glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
327
GL_COMPILE_AND_EXECUTE);
328
glPushMatrix ();
329
glRotatef (90.0, 1.0, 0.0, 0.0);
330
glTranslatef (0.0, 0.0, -1.0);
331
quadObj = gluNewQuadric ();
332
gluQuadricDrawStyle (quadObj, GLU_FILL);
333
gluQuadricNormals (quadObj, GLU_SMOOTH);
334
gluCylinder (quadObj, radius, radius, height, 12, 2);
335
glPopMatrix ();
336
glEndList();
337
}
338
else {
339
glCallList(displayList);
340
free (sizeArray);
341
}
342
}
343
344
/* Render wire frame or solid icosahedra. If no display list with
345
* the current model size exists, create a new display list.
346
*/
347
void auxWireIcosahedron (GLdouble radius)
348
{
349
GLdouble *sizeArray;
350
GLuint displayList;
351
GLdouble center[3] = {0.0, 0.0, 0.0};
352
353
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
354
*sizeArray = radius;
355
displayList = findList (ICOSAWIRE, sizeArray, 1);
356
357
if (displayList == 0) {
358
glNewList(makeModelPtr (ICOSAWIRE, sizeArray, 1),
359
GL_COMPILE_AND_EXECUTE);
360
icosahedron (center, radius, GL_LINE_LOOP);
361
glEndList();
362
}
363
else {
364
glCallList(displayList);
365
free (sizeArray);
366
}
367
}
368
369
void auxSolidIcosahedron (GLdouble radius)
370
{
371
GLdouble *sizeArray;
372
GLuint displayList;
373
GLdouble center[3] = {0.0, 0.0, 0.0};
374
375
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
376
*sizeArray = radius;
377
displayList = findList (ICOSASOLID, sizeArray, 1);
378
379
if (displayList == 0) {
380
glNewList(makeModelPtr (ICOSASOLID, sizeArray, 1),
381
GL_COMPILE_AND_EXECUTE);
382
icosahedron (center, radius, GL_TRIANGLES);
383
glEndList();
384
}
385
else {
386
glCallList(displayList);
387
free (sizeArray);
388
}
389
}
390
391
/* Render wire frame or solid octahedra. If no display list with
392
* the current model size exists, create a new display list.
393
*/
394
void auxWireOctahedron (GLdouble radius)
395
{
396
GLdouble *sizeArray;
397
GLuint displayList;
398
GLdouble center[3] = {0.0, 0.0, 0.0};
399
400
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
401
*sizeArray = radius;
402
displayList = findList (OCTAWIRE, sizeArray, 1);
403
404
if (displayList == 0) {
405
glNewList(makeModelPtr (OCTAWIRE, sizeArray, 1),
406
GL_COMPILE_AND_EXECUTE);
407
octahedron (center, radius, GL_LINE_LOOP);
408
glEndList();
409
}
410
else {
411
glCallList(displayList);
412
free (sizeArray);
413
}
414
}
415
416
void auxSolidOctahedron (GLdouble radius)
417
{
418
GLdouble *sizeArray;
419
GLuint displayList;
420
GLdouble center[3] = {0.0, 0.0, 0.0};
421
422
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
423
*sizeArray = radius;
424
displayList = findList (OCTASOLID, sizeArray, 1);
425
426
if (displayList == 0) {
427
glNewList(makeModelPtr (OCTASOLID, sizeArray, 1),
428
GL_COMPILE_AND_EXECUTE);
429
octahedron (center, radius, GL_TRIANGLES);
430
glEndList();
431
}
432
else {
433
glCallList(displayList);
434
free (sizeArray);
435
}
436
}
437
438
/* Render wire frame or solid tetrahedra. If no display list with
439
* the current model size exists, create a new display list.
440
*/
441
void auxWireTetrahedron (GLdouble radius)
442
{
443
GLdouble *sizeArray;
444
GLuint displayList;
445
GLdouble center[3] = {0.0, 0.0, 0.0};
446
447
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
448
*sizeArray = radius;
449
displayList = findList (TETRAWIRE, sizeArray, 1);
450
451
if (displayList == 0) {
452
glNewList(makeModelPtr (TETRAWIRE, sizeArray, 1),
453
GL_COMPILE_AND_EXECUTE);
454
tetrahedron (center, radius, GL_LINE_LOOP);
455
glEndList();
456
}
457
else {
458
glCallList(displayList);
459
free (sizeArray);
460
}
461
}
462
463
void auxSolidTetrahedron (GLdouble radius)
464
{
465
GLdouble *sizeArray;
466
GLuint displayList;
467
GLdouble center[3] = {0.0, 0.0, 0.0};
468
469
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
470
*sizeArray = radius;
471
displayList = findList (TETRASOLID, sizeArray, 1);
472
473
if (displayList == 0) {
474
glNewList(makeModelPtr (TETRASOLID, sizeArray, 1),
475
GL_COMPILE_AND_EXECUTE);
476
tetrahedron (center, radius, GL_TRIANGLES);
477
glEndList();
478
}
479
else {
480
glCallList(displayList);
481
free (sizeArray);
482
}
483
}
484
485
/* Render wire frame or solid dodecahedra. If no display list with
486
* the current model size exists, create a new display list.
487
*/
488
void auxWireDodecahedron (GLdouble radius)
489
{
490
GLdouble *sizeArray;
491
GLuint displayList;
492
GLdouble center[3] = {0.0, 0.0, 0.0};
493
494
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
495
*sizeArray = radius;
496
displayList = findList (DODECAWIRE, sizeArray, 1);
497
498
if (displayList == 0) {
499
glNewList(makeModelPtr (DODECAWIRE, sizeArray, 1),
500
GL_COMPILE_AND_EXECUTE);
501
dodecahedron (center, radius/1.73, GL_LINE_LOOP);
502
glEndList();
503
}
504
else {
505
glCallList(displayList);
506
free (sizeArray);
507
}
508
}
509
510
void auxSolidDodecahedron (GLdouble radius)
511
{
512
GLdouble *sizeArray;
513
GLuint displayList;
514
GLdouble center[3] = {0.0, 0.0, 0.0};
515
516
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
517
*sizeArray = radius;
518
displayList = findList (DODECASOLID, sizeArray, 1);
519
520
if (displayList == 0) {
521
glNewList(makeModelPtr (DODECASOLID, sizeArray, 1),
522
GL_COMPILE_AND_EXECUTE);
523
dodecahedron (center, radius/1.73, GL_TRIANGLE_FAN);
524
glEndList();
525
}
526
else {
527
glCallList(displayList);
528
free (sizeArray);
529
}
530
}
531
532
/* Render wire frame or solid cones. If no display list with
533
* the current model size exists, create a new display list.
534
*/
535
void auxWireCone (GLdouble base, GLdouble height)
536
{
537
GLUquadricObj *quadObj;
538
GLdouble *sizeArray, *tmp;
539
GLuint displayList;
540
541
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
542
tmp = sizeArray;
543
*tmp++ = base;
544
*tmp++ = height;
545
displayList = findList (CONEWIRE, sizeArray, 2);
546
547
if (displayList == 0) {
548
glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
549
GL_COMPILE_AND_EXECUTE);
550
quadObj = gluNewQuadric ();
551
gluQuadricDrawStyle (quadObj, GLU_LINE);
552
gluCylinder (quadObj, base, 0.0, height, 15, 10);
553
glEndList();
554
}
555
else {
556
glCallList(displayList);
557
free (sizeArray);
558
}
559
}
560
561
void auxSolidCone (GLdouble base, GLdouble height)
562
{
563
GLUquadricObj *quadObj;
564
GLdouble *sizeArray, *tmp;
565
GLuint displayList;
566
567
sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
568
tmp = sizeArray;
569
*tmp++ = base;
570
*tmp++ = height;
571
displayList = findList (CONEWIRE, sizeArray, 2);
572
573
if (displayList == 0) {
574
glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
575
GL_COMPILE_AND_EXECUTE);
576
quadObj = gluNewQuadric ();
577
gluQuadricDrawStyle (quadObj, GLU_FILL);
578
gluQuadricNormals (quadObj, GLU_SMOOTH);
579
gluCylinder (quadObj, base, 0.0, height, 15, 10);
580
glEndList();
581
}
582
else {
583
glCallList(displayList);
584
free (sizeArray);
585
}
586
}
587
588
/* Routines to build 3 dimensional solids, including:
589
*
590
* drawbox, doughnut, icosahedron,
591
* octahedron, tetrahedron, dodecahedron.
592
*/
593
594
/* drawbox:
595
*
596
* draws a rectangular box with the given x, y, and z ranges.
597
* The box is axis-aligned.
598
*/
599
static void drawbox(GLdouble x0, GLdouble x1, GLdouble y0, GLdouble y1,
600
GLdouble z0, GLdouble z1, GLenum type)
601
{
602
static GLdouble n[6][3] = {
603
{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
604
{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
605
};
606
static GLint faces[6][4] = {
607
{ 0, 1, 2, 3 }, { 3, 2, 6, 7 }, { 7, 6, 5, 4 },
608
{ 4, 5, 1, 0 }, { 5, 6, 2, 1 }, { 7, 4, 0, 3 }
609
};
610
GLdouble v[8][3], tmp;
611
GLint i;
612
613
if (x0 > x1) {
614
tmp = x0; x0 = x1; x1 = tmp;
615
}
616
if (y0 > y1) {
617
tmp = y0; y0 = y1; y1 = tmp;
618
}
619
if (z0 > z1) {
620
tmp = z0; z0 = z1; z1 = tmp;
621
}
622
v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
623
v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
624
v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
625
v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
626
v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
627
v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
628
629
for (i = 0; i < 6; i++) {
630
glBegin(type);
631
glNormal3dv(&n[i][0]);
632
glVertex3dv(&v[faces[i][0]][0]);
633
glNormal3dv(&n[i][0]);
634
glVertex3dv(&v[faces[i][1]][0]);
635
glNormal3dv(&n[i][0]);
636
glVertex3dv(&v[faces[i][2]][0]);
637
glNormal3dv(&n[i][0]);
638
glVertex3dv(&v[faces[i][3]][0]);
639
glEnd();
640
}
641
}
642
643
/* doughnut:
644
*
645
* draws a doughnut, centered at (0, 0, 0) whose axis is aligned with
646
* the z-axis. The doughnut's major radius is R, and minor radius is r.
647
*/
648
649
static void doughnut(GLdouble r, GLdouble R, GLint nsides, GLint rings, GLenum type)
650
{
651
int i, j;
652
GLdouble theta, phi, theta1, phi1;
653
GLdouble p0[03], p1[3], p2[3], p3[3];
654
GLdouble n0[3], n1[3], n2[3], n3[3];
655
656
for (i = 0; i < rings; i++) {
657
theta = (GLdouble)i*2.0*PI/rings;
658
theta1 = (GLdouble)(i+1)*2.0*PI/rings;
659
for (j = 0; j < nsides; j++) {
660
phi = (GLdouble)j*2.0*PI/nsides;
661
phi1 = (GLdouble)(j+1)*2.0*PI/nsides;
662
663
p0[0] = cos(theta)*(R + r*cos(phi));
664
p0[1] = -sin(theta)*(R + r*cos(phi));
665
p0[2] = r*sin(phi);
666
667
p1[0] = cos(theta1)*(R + r*cos(phi));
668
p1[1] = -sin(theta1)*(R + r*cos(phi));
669
p1[2] = r*sin(phi);
670
671
p2[0] = cos(theta1)*(R + r*cos(phi1));
672
p2[1] = -sin(theta1)*(R + r*cos(phi1));
673
p2[2] = r*sin(phi1);
674
675
p3[0] = cos(theta)*(R + r*cos(phi1));
676
p3[1] = -sin(theta)*(R + r*cos(phi1));
677
p3[2] = r*sin(phi1);
678
679
n0[0] = cos(theta)*(cos(phi));
680
n0[1] = -sin(theta)*(cos(phi));
681
n0[2] = sin(phi);
682
683
n1[0] = cos(theta1)*(cos(phi));
684
n1[1] = -sin(theta1)*(cos(phi));
685
n1[2] = sin(phi);
686
687
n2[0] = cos(theta1)*(cos(phi1));
688
n2[1] = -sin(theta1)*(cos(phi1));
689
n2[2] = sin(phi1);
690
691
n3[0] = cos(theta)*(cos(phi1));
692
n3[1] = -sin(theta)*(cos(phi1));
693
n3[2] = sin(phi1);
694
695
m_xformpt(p0, p0, n0, n0);
696
m_xformpt(p1, p1, n1, n1);
697
m_xformpt(p2, p2, n2, n2);
698
m_xformpt(p3, p3, n3, n3);
699
700
glBegin(type);
701
glNormal3dv(n3);
702
glVertex3dv(p3);
703
glNormal3dv(n2);
704
glVertex3dv(p2);
705
glNormal3dv(n1);
706
glVertex3dv(p1);
707
glNormal3dv(n0);
708
glVertex3dv(p0);
709
glEnd();
710
}
711
}
712
}
713
714
/* octahedron data: The octahedron produced is centered
715
* at the origin and has radius 1.0
716
*/
717
static GLdouble odata[6][3] = {
718
{1.0, 0.0, 0.0},
719
{-1.0, 0.0, 0.0},
720
{0.0, 1.0, 0.0},
721
{0.0, -1.0, 0.0},
722
{0.0, 0.0, 1.0},
723
{0.0, 0.0, -1.0}
724
};
725
726
static int ondex[8][3] = {
727
{0, 4, 2}, {1, 2, 4}, {0, 3, 4}, {1, 4, 3},
728
{0, 2, 5}, {1, 5, 2}, {0, 5, 3}, {1, 3, 5}
729
};
730
731
/* tetrahedron data: */
732
733
#define T 1.73205080756887729
734
735
static GLdouble tdata[4][3] = {
736
{T, T, T}, {T, -T, -T}, {-T, T, -T}, {-T, -T, T}
737
};
738
739
static int tndex[4][3] = {
740
{0, 1, 3}, {2, 1, 0}, {3, 2, 0}, {1, 2, 3}
741
};
742
743
/* icosahedron data: These numbers are rigged to
744
* make an icosahedron of radius 1.0
745
*/
746
747
#define X .525731112119133606
748
#define Z .850650808352039932
749
750
static GLdouble idata[12][3] = {
751
{-X, 0.0, Z},
752
{X, 0.0, Z},
753
{-X, 0.0, -Z},
754
{X, 0.0, -Z},
755
{0.0, Z, X},
756
{0.0, Z, -X},
757
{0.0, -Z, X},
758
{0.0, -Z, -X},
759
{Z, X, 0.0},
760
{-Z, X, 0.0},
761
{Z, -X, 0.0},
762
{-Z, -X, 0.0},
763
};
764
765
static int iindex[20][3] = {
766
{0, 4, 1}, {0, 9, 4},
767
{9, 5, 4}, {4, 5, 8},
768
{4, 8, 1}, {8, 10, 1},
769
{8, 3, 10}, {5, 3, 8},
770
{5, 2, 3}, {2, 7, 3},
771
{7, 10, 3}, {7, 6, 10},
772
{7, 11, 6}, {11, 0, 6},
773
{0, 1, 6}, {6, 1, 10},
774
{9, 0, 11}, {9, 11, 2},
775
{9, 2, 5}, {7, 2, 11},
776
};
777
778
/* icosahedron:
779
*
780
* Draws an icosahedron with center at p0 having the
781
* given radius.
782
*/
783
784
static void icosahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
785
{
786
int i;
787
788
for (i = 0; i < 20; i++)
789
drawtriangle(i, 0, 1, p0, radius, shadeType, 0);
790
}
791
792
/* octahedron:
793
*
794
* Draws an octahedron with center at p0 having the
795
* given radius.
796
*/
797
static void octahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
798
{
799
int i;
800
801
for (i = 0; i < 8; i++)
802
drawtriangle(i, 1, 1, p0, radius, shadeType, 0);
803
}
804
805
/* tetrahedron:
806
*
807
* Draws an tetrahedron with center at p0 having the
808
* given radius.
809
*/
810
811
static void tetrahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
812
{
813
int i;
814
815
for (i = 0; i < 4; i++)
816
drawtriangle(i, 2, 1, p0, radius, shadeType, 0);
817
}
818
819
static void subdivide(int depth, GLdouble *v0, GLdouble *v1, GLdouble *v2,
820
GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
821
{
822
GLdouble w0[3], w1[3], w2[3];
823
GLdouble l;
824
int i, j, k, n;
825
826
for (i = 0; i < depth; i++)
827
for (j = 0; i + j < depth; j++) {
828
k = depth - i - j;
829
for (n = 0; n < 3; n++) {
830
w0[n] = (i*v0[n] + j*v1[n] + k*v2[n])/depth;
831
w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
832
w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
833
}
834
l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
835
w0[0] /= l; w0[1] /= l; w0[2] /= l;
836
l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
837
w1[0] /= l; w1[1] /= l; w1[2] /= l;
838
l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
839
w2[0] /= l; w2[1] /= l; w2[2] /= l;
840
recorditem(w1, w0, w2, p0, radius, shadeType, avnormal);
841
}
842
for (i = 0; i < depth-1; i++)
843
for (j = 0; i + j < depth-1; j++) {
844
k = depth - i - j;
845
for (n = 0; n < 3; n++) {
846
w0[n] = ((i+1)*v0[n] + (j+1)*v1[n] + (k-2)*v2[n])/depth;
847
w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
848
w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
849
}
850
l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
851
w0[0] /= l; w0[1] /= l; w0[2] /= l;
852
l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
853
w1[0] /= l; w1[1] /= l; w1[2] /= l;
854
l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
855
w2[0] /= l; w2[1] /= l; w2[2] /= l;
856
recorditem(w0, w1, w2, p0, radius, shadeType, avnormal);
857
}
858
}
859
860
static void drawtriangle(int i, int geomType, int depth,
861
GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
862
{
863
GLdouble *x0, *x1, *x2;
864
865
switch (geomType) {
866
case 0: /* icosahedron */
867
x0 = &idata[iindex[i][0]][0];
868
x1 = &idata[iindex[i][1]][0];
869
x2 = &idata[iindex[i][2]][0];
870
break;
871
case 1: /* octahedron */
872
x0 = &odata[ondex[i][0]][0];
873
x1 = &odata[ondex[i][1]][0];
874
x2 = &odata[ondex[i][2]][0];
875
break;
876
case 2: /* tetrahedron */
877
x0 = &tdata[tndex[i][0]][0];
878
x1 = &tdata[tndex[i][1]][0];
879
x2 = &tdata[tndex[i][2]][0];
880
break;
881
}
882
subdivide(depth, x0, x1, x2, p0, radius, shadeType, avnormal);
883
}
884
885
static void recorditem(GLdouble *n1, GLdouble *n2, GLdouble *n3,
886
GLdouble center[3], GLdouble radius, GLenum shadeType, int avnormal)
887
{
888
GLdouble p1[3], p2[3], p3[3], q0[3], q1[3], n11[3], n22[3], n33[3];
889
int i;
890
891
for (i = 0; i < 3; i++) {
892
p1[i] = n1[i]*radius + center[i];
893
p2[i] = n2[i]*radius + center[i];
894
p3[i] = n3[i]*radius + center[i];
895
}
896
if (avnormal == 0) {
897
diff3(p1, p2, q0);
898
diff3(p2, p3, q1);
899
crossprod(q0, q1, q1);
900
normalize(q1);
901
m_xformpt(p1, p1, q1, n11);
902
m_xformptonly(p2, p2);
903
m_xformptonly(p3, p3);
904
905
glBegin (shadeType);
906
glNormal3dv(n11);
907
glVertex3dv(p1);
908
glVertex3dv(p2);
909
glVertex3dv(p3);
910
glEnd();
911
return;
912
}
913
m_xformpt(p1, p1, n1, n11);
914
m_xformpt(p2, p2, n2, n22);
915
m_xformpt(p3, p3, n3, n33);
916
917
glBegin (shadeType);
918
glNormal3dv(n11);
919
glVertex3dv(p1);
920
glNormal3dv(n22);
921
glVertex3dv(p2);
922
glNormal3dv(n33);
923
glVertex3dv(p3);
924
glEnd();
925
}
926
927
static GLdouble dodec[20][3];
928
929
static void initdodec()
930
{
931
GLdouble alpha, beta;
932
933
alpha = sqrt(2.0/(3.0 + sqrt(5.0)));
934
beta = 1.0 + sqrt(6.0/(3.0 + sqrt(5.0)) - 2.0 + 2.0*sqrt(2.0/(3.0 +
935
sqrt(5.0))));
936
dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
937
dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
938
dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
939
dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
940
dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
941
dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
942
dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
943
dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
944
dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
945
dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
946
dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
947
dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
948
dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
949
dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
950
dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
951
dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
952
dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
953
dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
954
dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
955
dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
956
}
957
958
/* dodecahedron:
959
*
960
* Draws an dodecahedron with center at 0.0. The radius
961
* is sqrt(3).
962
*/
963
static void dodecahedron(GLdouble center[3], GLdouble sc, GLenum type)
964
{
965
static int inited = 0;
966
967
if ( inited == 0) {
968
inited = 1;
969
initdodec();
970
}
971
m_pushmatrix();
972
m_translate(center[0], center[1], center[2]);
973
m_scale(sc, sc, sc);
974
pentagon(0, 1, 9, 16, 5, type);
975
pentagon(1, 0, 3, 18, 7, type);
976
pentagon(1, 7, 11, 10, 9, type);
977
pentagon(11, 7, 18, 19, 6, type);
978
pentagon(8, 17, 16, 9, 10, type);
979
pentagon(2, 14, 15, 6, 19, type);
980
pentagon(2, 13, 12, 4, 14, type);
981
pentagon(2, 19, 18, 3, 13, type);
982
pentagon(3, 0, 5, 12, 13, type);
983
pentagon(6, 15, 8, 10, 11, type);
984
pentagon(4, 17, 8, 15, 14, type);
985
pentagon(4, 12, 5, 16, 17, type);
986
m_popmatrix();
987
}
988
989
static void pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
990
{
991
GLdouble n0[3], d1[3], d2[3], d3[3], d4[3], d5[3], nout[3];
992
993
diff3(&dodec[a][0], &dodec[b][0], d1);
994
diff3(&dodec[b][0], &dodec[c][0], d2);
995
crossprod(d1, d2, n0);
996
normalize(n0);
997
m_xformpt(&dodec[a][0], d1, n0, nout);
998
m_xformptonly(&dodec[b][0], d2);
999
m_xformptonly(&dodec[c][0], d3);
1000
m_xformptonly(&dodec[d][0], d4);
1001
m_xformptonly(&dodec[e][0], d5);
1002
1003
glBegin (shadeType);
1004
glNormal3dv(nout);
1005
glVertex3dv(d1);
1006
glVertex3dv(d2);
1007
glVertex3dv(d3);
1008
glVertex3dv(d4);
1009
glVertex3dv(d5);
1010
glEnd();
1011
}
1012
1013
/* linked lists--display lists for each different
1014
* type of geometric objects. The linked list is
1015
* searched, until an object of the requested
1016
* size is found. If no geometric object of that size
1017
* has been previously made, a new one is created.
1018
*/
1019
GLuint findList (int lindex, GLdouble *paramArray, int size)
1020
{
1021
MODELPTR endList;
1022
int found = 0;
1023
1024
endList = lists[lindex];
1025
while (endList != NULL) {
1026
if (compareParams (endList->params, paramArray, size))
1027
return (endList->list);
1028
endList = endList->ptr;
1029
}
1030
/* if not found, return 0 and calling routine should
1031
* make a new list
1032
*/
1033
return (0);
1034
}
1035
1036
int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size)
1037
{
1038
int i;
1039
int matches = 1;
1040
1041
for (i = 0; (i < size) && matches; i++) {
1042
if (*oneArray++ != *twoArray++)
1043
matches = 0;
1044
}
1045
return (matches);
1046
}
1047
1048
GLuint makeModelPtr (int lindex, GLdouble *sizeArray, int count)
1049
{
1050
MODELPTR newModel;
1051
1052
newModel = (MODELPTR) malloc (sizeof (MODEL));
1053
newModel->list = glGenLists (1);
1054
newModel->numParam = count;
1055
newModel->params = sizeArray;
1056
newModel->ptr = lists[lindex];
1057
lists[lindex] = newModel;
1058
1059
return (newModel->list);
1060
}
1061
1062