2819d60069d2829be07cf40ccdb5a8c5238a0122
[freeglut] / freeglut-1.3 / freeglut_geometry.c
1 /*
2  * freeglut_geometry.c
3  *
4  * Freeglut geometry rendering methods.
5  *
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8  * Creation date: Fri Dec 3 1999
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #define  G_LOG_DOMAIN  "freeglut-geometry"
33
34 #include "../include/GL/freeglut.h"
35 #include "../include/GL/freeglut_internal.h"
36
37 /*
38  * TODO BEFORE THE STABLE RELEASE:
39  *
40  * Following functions have been contributed by Andreas Umbach. I modified
41  * them a bit to make them use GLib (for memory allocation).
42  *
43  *      glutWireCube()          -- could add normal vectors so that lighting works
44  *      glutSolidCube()         -- OK
45  *      glutWireSphere()        -- OK
46  *      glutSolidSphere()       -- OK
47  *
48  * Following functions have been implemented by me:
49  *
50  *      glutWireCone()          -- looks OK
51  *      glutSolidCone()         -- normals are missing, there are holes in the thing
52  *
53  * Those functions need to be implemented, as nothing has been done yet.
54  * For now all of them draw a wire or solid cube, just to mark their presence.
55  *
56  *      glutWireTorus()         --
57  *      glutSolidTorus()        --
58  *      glutWireDodecahedron()  --
59  *      glutSolidDodecahedron() --
60  *      glutWireOctahedron()    --
61  *      glutSolidOctahedron()   --
62  *      glutWireTetrahedron()   --
63  *      glutSolidTetrahedron()  --
64  *      glutWireIcosahedron()   --
65  *      glutSolidIcosahedron()  --
66  */
67
68
69 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
70
71 /*
72  * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
73  */
74 void FGAPIENTRY glutWireCube( GLdouble dSize )
75 {
76     float size = (float) dSize * 0.5f;
77
78 #   define V(a,b,c) glVertex3f( a size, b size, c size );
79
80     /*
81      * PWO: I dared to convert the code to use macros...
82      */
83     glBegin( GL_LINE_LOOP ); V(-,-,+); V(+,-,+); V(+,+,+); V(-,+,+); glEnd();
84     glBegin( GL_LINE_LOOP ); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd();
85     glBegin( GL_LINES );
86         V(-,-,+); V(-,-,-); V(-,+,+); V(-,+,-);
87         V(+,-,+); V(+,-,-); V(+,+,+); V(+,+,-);
88     glEnd();
89
90 #   undef V
91 }
92
93 /*
94  * Draws a solid cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
95  */
96 void FGAPIENTRY glutSolidCube( GLdouble dSize )
97 {
98     float size = (float) dSize * 0.5f;
99
100 #   define V(a,b,c) glVertex3f( a size, b size, c size );
101 #   define N(a,b,c) glNormal3f( a, b, c );
102
103     /*
104      * PWO: Again, I dared to convert the code to use macros...
105      */
106     glBegin( GL_QUADS );
107         N( 1, 0, 0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
108         N( 0, 1, 0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
109         N( 0, 0, 1); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
110         N(-1, 0, 0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
111         N( 0,-1, 0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
112         N( 0, 0,-1); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
113     glEnd();
114
115 #   undef V
116 #   undef N
117 }
118
119 /*
120  * Draws a wire sphere. Code contributed by Andreas Umbach <marvin@dataway.ch>
121  */
122 void FGAPIENTRY glutWireSphere( GLdouble dRadius, GLint slices, GLint stacks )
123 {
124     float  radius = (float) dRadius, phi, psi, dpsi, dphi;
125     float* vertex;
126     gint   i, j;
127
128     /*
129      * Allocate the vertices array
130      */
131     vertex = g_new0( float, 3 * slices * (stacks - 1) );
132
133     glPushMatrix();
134     glScalef( radius, radius, radius );
135
136     dpsi = M_PI / (stacks + 1);
137     dphi = 2 * M_PI / slices;
138     psi  = dpsi;
139
140     for( j=0; j<stacks-1; j++ )
141     {
142         phi = 0;
143
144         for( i=0; i<slices; i++ )
145         {
146             *(vertex + 3 * j * slices + 3 * i + 0) = sin( phi ) * sin( psi );
147             *(vertex + 3 * j * slices + 3 * i + 1) = cos( phi ) * sin( psi );
148             *(vertex + 3 * j * slices + 3 * i + 2) = cos( psi );
149             phi += dphi;
150             glVertex3fv( vertex + 3 * j * slices + 3 * i );
151         }
152
153         psi += dpsi;
154     }
155
156     for( i=0; i<slices; i++ )
157     {
158         glBegin( GL_LINE_STRIP );
159         glNormal3f( 0, 0, 1 );
160         glVertex3f( 0, 0, 1 );
161
162         for( j=0; j<stacks - 1; j++ )
163         {
164             glNormal3fv( vertex + 3 * j * slices + 3 * i );
165             glVertex3fv( vertex + 3 * j * slices + 3 * i );
166         }
167
168         glNormal3f(0, 0, -1);
169         glVertex3f(0, 0, -1);
170         glEnd();
171     }
172
173     for( j=0; j<stacks-1; j++ )
174     {
175         glBegin(GL_LINE_LOOP);
176
177         for( i=0; i<slices; i++ )
178         {
179             glNormal3fv( vertex + 3 * j * slices + 3 * i );
180             glVertex3fv( vertex + 3 * j * slices + 3 * i );
181         }
182
183         glEnd();
184     }
185
186     g_free( vertex );
187     glPopMatrix();
188 }
189
190 /*
191  * Draws a solid sphere. Code contributed by Andreas Umbach <marvin@dataway.ch>
192  */
193 void FGAPIENTRY glutSolidSphere( GLdouble dRadius, GLint slices, GLint stacks )
194 {
195     float  radius = (float) dRadius, phi, psi, dpsi, dphi;
196     float *next, *tmp, *row;
197     gint   i, j;
198
199     glPushMatrix();
200     //glScalef( radius, radius, radius );
201
202     row  = g_new0( float, slices * 3 );
203     next = g_new0( float, slices * 3 );
204
205     dpsi = M_PI / (stacks + 1);
206     dphi = 2 * M_PI / slices;
207     psi  = dpsi;
208     phi  = 0;
209
210     /* init first line + do polar cap */
211     glBegin( GL_TRIANGLE_FAN );
212     glNormal3f( 0, 0, 1 );
213     glVertex3f( 0, 0, radius );
214
215     for( i=0; i<slices; i++ )
216     {
217         row[ i * 3 + 0 ] = sin( phi ) * sin( psi );
218         row[ i * 3 + 1 ] = cos( phi ) * sin( psi );
219         row[ i * 3 + 2 ] = cos( psi );
220
221         glNormal3fv( row + 3 * i );
222         glVertex3f(
223             radius * *(row + 3 * i + 0),
224             radius * *(row + 3 * i + 1),
225                 radius * *(row + 3 * i + 2)
226             );
227         
228         phi += dphi;
229     }
230
231     glNormal3fv( row );
232     glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
233     glEnd();
234
235     for( j=0; j<stacks-1; j++ )
236     {
237         phi = 0;
238         psi += dpsi;
239
240         /* get coords */
241         glBegin( GL_QUAD_STRIP );
242
243         /* glBegin(GL_LINE_LOOP); */
244         for( i=0; i<slices; i++ )
245         {
246             next[ i * 3 + 0 ] = sin( phi ) * sin( psi );
247             next[ i * 3 + 1 ] = cos( phi ) * sin( psi );
248             next[ i * 3 + 2 ] = cos( psi );
249
250             glNormal3fv( row + i * 3 );
251             glVertex3f(
252                 radius * *(row + 3 * i + 0),
253                 radius * *(row + 3 * i + 1),
254                         radius * *(row + 3 * i + 2)
255                     );
256
257             glNormal3fv( next + i * 3 );
258             glVertex3f(
259                 radius * *(next + 3 * i + 0),
260                 radius * *(next + 3 * i + 1),
261                 radius * *(next + 3 * i + 2)
262             );
263
264             phi += dphi;
265         }
266
267         glNormal3fv( row );
268         glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
269         glNormal3fv( next );
270         glVertex3f( radius * *(next + 0), radius * *(next + 1), radius * *(next + 2) );
271         glEnd();
272
273         tmp = row;
274         row = next;
275         next = tmp;
276     }
277
278     /* south pole */
279     glBegin( GL_TRIANGLE_FAN );
280     glNormal3f( 0, 0, -1 );
281     glVertex3f( 0, 0, -radius );
282     glNormal3fv( row );
283     glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
284
285     for( i=slices-1; i>=0; i-- )
286     {
287         glNormal3fv(row + 3 * i);
288         glVertex3f(
289             radius * *(row + 3 * i + 0),
290             radius * *(row + 3 * i + 1),
291                 radius * *(row + 3 * i + 2)
292            );
293     }
294
295     glEnd();
296
297     g_free(row);
298     g_free(next);
299     glPopMatrix();
300 }
301
302 /*
303  * Draws a wire cone
304  */
305 void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
306 {
307     float  alt   = (float) height / (float) (stacks + 1);
308     float  angle = (float) M_PI / (float) slices * 2.0f;
309     float  slope = (float) tan( height / base );
310     float* vertices = NULL;
311     gint   i, j;
312
313     /*
314      * We need 'slices' points on a circle
315      */
316     vertices = g_new0( float, 2 * (slices + 1) );
317
318     for( i=0; i<slices+1; i++ )
319     {
320         vertices[ i*2 + 0 ] = cos( angle * i );
321         vertices[ i*2 + 1 ] = sin( angle * i );
322     }
323
324     /*
325      * First the cone's bottom...
326      */
327     for( i=0; i<slices; i++ )
328     {
329         float scl = height / slope;
330
331         glBegin( GL_LINE_LOOP );
332             glNormal3f( 0, 0, -1 );
333             glVertex3f( vertices[ (i+0)*2+0 ] * scl, vertices[ (i+0)*2+1 ] * scl, 0 );
334             glVertex3f( vertices[ (i+1)*2+0 ] * scl, vertices[ (i+1)*2+1 ] * scl, 0 );
335             glVertex3f( 0, 0, 0 );
336         glEnd();
337     }
338
339     /*
340      * Then all the stacks between the bottom and the top
341      *
342      * ekhm jak wektor normalny z trojkata?
343      */
344     for( i=0; i<stacks; i++ )
345     {
346         float alt_a = i * alt, alt_b = (i + 1) * alt;
347         float scl_a = (height - alt_a) / slope;
348         float scl_b = (height - alt_b) / slope;
349
350         for( j=0; j<slices; j++ )
351         {
352             glBegin( GL_LINE_LOOP );
353                 glVertex3f( vertices[(j+0)*2+0] * scl_a, vertices[(j+0)*2+1] * scl_a, alt_a );
354                 glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
355                 glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
356             glEnd();
357
358             glBegin( GL_LINE_LOOP );
359                 glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
360                 glVertex3f( vertices[(j+1)*2+0] * scl_b, vertices[(j+1)*2+1] * scl_b, alt_b );
361                 glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
362             glEnd();
363         }
364     }
365
366     /*
367      * Finally have the top part drawn...
368      */
369     for( i=0; i<slices; i++ )
370     {
371         float scl = alt / slope;
372
373         glBegin( GL_LINE_LOOP );
374             glVertex3f( vertices[ (i+0)*2+0 ] * scl, vertices[ (i+0)*2+1 ] * scl, height - alt );
375             glVertex3f( vertices[ (i+1)*2+0 ] * scl, vertices[ (i+1)*2+1 ] * scl, height - alt );
376             glVertex3f( 0, 0, height );
377         glEnd();
378     }
379 }
380
381 /*
382  * Draws a solid cone
383  */
384 void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
385 {
386     float  alt   = (float) height / (float) (stacks + 1);
387     float  angle = (float) M_PI / (float) slices * 2.0f;
388     float  slope = (float) tan( height / base );
389     float* vertices = NULL;
390     gint   i, j;
391
392     /*
393      * We need 'slices' points on a circle
394      */
395     vertices = g_new0( float, 2 * (slices + 1) );
396
397     for( i=0; i<slices+1; i++ )
398     {
399         vertices[ i*2 + 0 ] = cos( angle * i );
400         vertices[ i*2 + 1 ] = sin( angle * i );
401     }
402
403     /*
404      * First the cone's bottom...
405      */
406     for( i=0; i<slices; i++ )
407     {
408         float scl = height / slope;
409
410         glBegin( GL_TRIANGLES );
411             glNormal3f( 0, 0, -1 );
412             glVertex3f( vertices[ (i+0)*2+0 ] * scl, vertices[ (i+0)*2+1 ] * scl, 0 );
413             glVertex3f( vertices[ (i+1)*2+0 ] * scl, vertices[ (i+1)*2+1 ] * scl, 0 );
414             glVertex3f( 0, 0, 0 );
415         glEnd();
416     }
417
418     /*
419      * Then all the stacks between the bottom and the top
420      *
421      * ekhm jak wektor normalny z trojkata?
422      */
423     for( i=0; i<stacks; i++ )
424     {
425         float alt_a = i * alt, alt_b = (i + 1) * alt;
426         float scl_a = (height - alt_a) / slope;
427         float scl_b = (height - alt_b) / slope;
428
429         for( j=0; j<slices; j++ )
430         {
431             glBegin( GL_TRIANGLES );
432                 glVertex3f( vertices[(j+0)*2+0] * scl_a, vertices[(j+0)*2+1] * scl_a, alt_a );
433                 glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
434                 glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
435             glEnd();
436
437             glBegin( GL_TRIANGLES );
438                 glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
439                 glVertex3f( vertices[(j+1)*2+0] * scl_b, vertices[(j+1)*2+1] * scl_b, alt_b );
440                 glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
441             glEnd();
442         }
443     }
444
445     /*
446      * Finally have the top part drawn...
447      */
448     for( i=0; i<slices; i++ )
449     {
450         float scl = alt / slope;
451
452         glBegin( GL_TRIANGLES );
453             glVertex3f( vertices[ (i+0)*2+0 ] * scl, vertices[ (i+0)*2+1 ] * scl, height - alt );
454             glVertex3f( vertices[ (i+1)*2+0 ] * scl, vertices[ (i+1)*2+1 ] * scl, height - alt );
455             glVertex3f( 0, 0, height );
456         glEnd();
457     }
458 }
459
460 /*
461  *
462  */
463 void FGAPIENTRY glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
464 {
465     glutWireSphere( dOuterRadius, 5, 5 );
466 }
467
468 /*
469  *
470  */
471 void FGAPIENTRY glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
472 {
473     glutSolidSphere( dOuterRadius, 5, 5 );
474 }
475
476 /*
477  *
478  */
479 void FGAPIENTRY glutWireDodecahedron( void )
480 {
481     glutWireSphere( 1.0, 5, 5 );
482 }
483
484 /*
485  *
486  */
487 void FGAPIENTRY glutSolidDodecahedron( void )
488 {
489     glutSolidSphere( 1.0, 5, 5 );
490 }
491
492 /*
493  *
494  */
495 void FGAPIENTRY glutWireOctahedron( void )
496 {
497     glutWireSphere( 1.0, 5, 5 );
498 }
499
500 /*
501  *
502  */
503 void FGAPIENTRY glutSolidOctahedron( void )
504 {
505     glutSolidSphere( 1.0, 5, 5 );
506 }
507
508 /*
509  *
510  */
511 void FGAPIENTRY glutWireTetrahedron( void )
512 {
513     glutWireSphere( 1.0, 5, 5 );
514 }
515
516 /*
517  *
518  */
519 void FGAPIENTRY glutSolidTetrahedron( void )
520 {
521     glutSolidSphere( 1.0, 5, 5 );
522 }
523
524 /*
525  *
526  */
527 void FGAPIENTRY glutWireIcosahedron( void )
528 {
529     glutWireSphere( 1.0, 5, 5 );
530 }
531
532 /*
533  *
534  */
535 void FGAPIENTRY glutSolidIcosahedron( void )
536 {
537     glutSolidSphere( 1.0, 5, 5 );
538 }
539
540 /*** END OF FILE ***/