1 /*
2      PLIB - A Suite of Portable Game Libraries
3      Copyright (C) 1998,2002  Steve Baker
4 
5      This library is free software; you can redistribute it and/or
6      modify it under the terms of the GNU Library General Public
7      License as published by the Free Software Foundation; either
8      version 2 of the License, or (at your option) any later version.
9 
10      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Library General Public License for more details.
14 
15      You should have received a copy of the GNU Library General Public
16      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 
19      For further information visit http://plib.sourceforge.net
20 
21      $Id: ssgaShapes.cxx 2015 2005-02-02 15:48:09Z sjbaker $
22 */
23 
24 
25 #include "ssgAux.h"
26 #include <string.h>
27 
28 #define SIN(x) ((float)(sin(x)))
29 #define COS(x) ((float)(cos(x)))
30 #define ATAN2(x, y) ((float)(atan2(x, y)))
31 
32 
copy_from(ssgaShape * src,int clone_flags)33 void ssgaShape::copy_from ( ssgaShape *src, int clone_flags )
34 {
35   ssgBranch::copy_from ( src, clone_flags ) ;
36   if ( src -> isCorrupt () ) makeCorrupt () ;
37   sgCopyVec4 ( colour, src->colour ) ;
38   sgCopyVec3 ( center, src->center ) ;
39   sgCopyVec3 ( size  , src->size   ) ;
40   ntriangles    = src -> ntriangles ;
41   kidState      = src -> getKidState      () ;
42   kidPreDrawCB  = src -> getKidPreDrawCB  () ;
43   kidPostDrawCB = src -> getKidPostDrawCB () ;
44 }
45 
46 
copy_from(ssgaCube * src,int clone_flags)47 void ssgaCube    ::copy_from ( ssgaCube     *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;}
copy_from(ssgaSphere * src,int clone_flags)48 void ssgaSphere  ::copy_from ( ssgaSphere   *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;}
copy_from(ssgaCylinder * src,int clone_flags)49 void ssgaCylinder::copy_from ( ssgaCylinder *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;}
copy_from(ssgaPatch * src,int clone_flags)50 void ssgaPatch   ::copy_from ( ssgaPatch    *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;}
copy_from(ssgaTeapot * src,int clone_flags)51 void ssgaTeapot  ::copy_from ( ssgaTeapot   *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;}
52 
53 
54 
clone(int clone_flags)55 ssgBase *ssgaShape   ::clone ( int clone_flags )
56 {
57 /*
58   ssgaShape *b = new ssgaShape ;
59   b -> copy_from ( this, clone_flags ) ;
60   return b ;
61 */
62   return NULL ;
63 }
64 
65 
clone(int clone_flags)66 ssgBase *ssgaCube    ::clone ( int clone_flags )
67 {
68   ssgaCube *b = new ssgaCube ;
69   b -> copy_from ( this, clone_flags ) ;
70   return b ;
71 }
72 
73 
clone(int clone_flags)74 ssgBase *ssgaSphere  ::clone ( int clone_flags )
75 {
76   ssgaSphere *b = new ssgaSphere ;
77   b -> copy_from ( this, clone_flags ) ;
78   return b ;
79 }
80 
81 
clone(int clone_flags)82 ssgBase *ssgaTeapot::clone ( int clone_flags )
83 {
84   ssgaTeapot *b = new ssgaTeapot ;
85   b -> copy_from ( this, clone_flags ) ;
86   return b ;
87 }
88 
89 
clone(int clone_flags)90 ssgBase *ssgaPatch::clone ( int clone_flags )
91 {
92   ssgaPatch *b = new ssgaPatch ;
93   b -> copy_from ( this, clone_flags ) ;
94   return b ;
95 }
96 
97 
clone(int clone_flags)98 ssgBase *ssgaCylinder::clone ( int clone_flags )
99 {
100   ssgaCylinder *b = new ssgaCylinder ;
101   b -> copy_from ( this, clone_flags ) ;
102   return b ;
103 }
104 
105 
ssgaShape(void)106 ssgaShape::ssgaShape (void)
107 {
108   ntriangles = 50 ;
109   init () ;
110 }
111 
ssgaShape(int np)112 ssgaShape::ssgaShape ( int np )
113 {
114   ntriangles = np ;
115   init () ;
116 }
117 
init()118 void ssgaShape::init ()
119 {
120   type = ssgaTypeShape () ;
121   corrupted = FALSE ;
122   sgZeroVec3 ( center ) ;
123   sgSetVec4 ( colour, 1.0f, 1.0f, 1.0f, 1.0f ) ;
124   sgSetVec3 ( size, 1.0f, 1.0f, 1.0f ) ;
125   kidState      = NULL ;
126   kidPreDrawCB  = NULL ;
127   kidPostDrawCB = NULL ;
128 }
129 
ssgaCube(void)130 ssgaCube ::ssgaCube ( void ):ssgaShape ()  {type=ssgaTypeCube ();regenerate();}
ssgaCube(int nt)131 ssgaCube ::ssgaCube (int nt):ssgaShape (nt){type=ssgaTypeCube ();regenerate();}
ssgaPatch(void)132 ssgaPatch::ssgaPatch( void ):ssgaShape ()  {type=ssgaTypePatch();regenerate();}
ssgaPatch(int nt)133 ssgaPatch::ssgaPatch(int nt):ssgaShape (nt){type=ssgaTypePatch();regenerate();}
ssgaTeapot(void)134 ssgaTeapot::ssgaTeapot( void ):ssgaShape ()  {type=ssgaTypeTeapot();regenerate();}
ssgaTeapot(int nt)135 ssgaTeapot::ssgaTeapot(int nt):ssgaShape (nt){type=ssgaTypeTeapot();regenerate();}
136 
ssgaSphere(void)137 ssgaSphere  ::ssgaSphere   ( void ) : ssgaShape ()
138 {
139  type = ssgaTypeSphere () ;
140  latlong_style = TRUE ;
141  regenerate () ;
142 }
143 
144 
ssgaSphere(int nt)145 ssgaSphere  ::ssgaSphere   (int nt) : ssgaShape ( nt )
146 {
147  type = ssgaTypeSphere () ;
148  latlong_style = TRUE ;
149  regenerate () ;
150 }
151 
152 
ssgaCylinder(void)153 ssgaCylinder::ssgaCylinder ( void ) : ssgaShape ()
154 {
155  type = ssgaTypeCylinder () ;
156  capped = TRUE ;
157  regenerate () ;
158 }
159 
160 
ssgaCylinder(int nt)161 ssgaCylinder::ssgaCylinder (int nt) : ssgaShape ( nt )
162 {
163  type = ssgaTypeCylinder () ;
164  capped = TRUE ;
165  regenerate () ;
166 }
167 
168 
~ssgaShape(void)169 ssgaShape   ::~ssgaShape    (void) {}
~ssgaCube(void)170 ssgaCube    ::~ssgaCube     (void) {}
~ssgaPatch(void)171 ssgaPatch   ::~ssgaPatch    (void) {}
~ssgaTeapot(void)172 ssgaTeapot  ::~ssgaTeapot   (void) {}
~ssgaSphere(void)173 ssgaSphere  ::~ssgaSphere   (void) {}
~ssgaCylinder(void)174 ssgaCylinder::~ssgaCylinder (void) {}
175 
getTypeName(void)176 const char *ssgaShape   ::getTypeName(void) { return "ssgaShape"    ; }
getTypeName(void)177 const char *ssgaCube    ::getTypeName(void) { return "ssgaCube"     ; }
getTypeName(void)178 const char *ssgaSphere  ::getTypeName(void) { return "ssgaSphere"   ; }
getTypeName(void)179 const char *ssgaCylinder::getTypeName(void) { return "ssgaCylinder" ; }
getTypeName(void)180 const char *ssgaPatch   ::getTypeName(void) { return "ssgaPatch"    ; }
getTypeName(void)181 const char *ssgaTeapot  ::getTypeName(void) { return "ssgaTeapot"   ; }
182 
183 
regenerate()184 void ssgaCube    ::regenerate ()
185 {
186   if ( kidState != NULL ) kidState -> ref () ;
187   removeAllKids () ;
188   if ( kidState != NULL ) kidState -> deRef () ;
189 
190   if ( ntriangles == 0 )
191     return ;
192 
193   ssgVtxTable     *vt0 = new ssgVtxTable () ;
194   ssgVtxTable     *vt1 = new ssgVtxTable () ;
195 
196   ssgVertexArray   *v0 = new ssgVertexArray   ( 8 ) ;
197   ssgVertexArray   *v1 = new ssgVertexArray   ( 8 ) ;
198   ssgNormalArray   *n0 = new ssgNormalArray   ( 8 ) ;
199   ssgNormalArray   *n1 = new ssgNormalArray   ( 8 ) ;
200   ssgColourArray   *c0 = new ssgColourArray   ( 8 ) ;
201   ssgColourArray   *c1 = new ssgColourArray   ( 8 ) ;
202   ssgTexCoordArray *t0 = new ssgTexCoordArray ( 8 ) ;
203   ssgTexCoordArray *t1 = new ssgTexCoordArray ( 8 ) ;
204 
205   vt0 -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ;
206   vt1 -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ;
207 
208   addKid ( vt0 ) ; addKid ( vt1 ) ;
209 
210   vt0 -> setState    ( getKidState () ) ;
211   vt1 -> setState    ( getKidState () ) ;
212   vt0 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB  () ) ;
213   vt1 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB  () ) ;
214   vt0 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ;
215   vt1 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ;
216 
217   sgVec3 v ; sgVec3 n ; sgVec2 t ;
218 
219   sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]-size[1]/2.0f, center[2]+size[2]/2.0f ) ; v0->add ( v ) ;
220   sgSetVec3 ( n,          1            ,          0            ,          0             ) ; n0->add ( n ) ;
221   c0->add ( colour ) ;
222   sgSetVec2 ( t,          0                       ,                1                    ) ; t0->add ( t ) ;
223 
224   sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]-size[1]/2.0f, center[2]-size[2]/2.0f ) ; v0->add ( v ) ;
225   sgSetVec3 ( n,          1            ,          0            ,          0             ) ; n0->add ( n ) ;
226   c0->add ( colour ) ;
227   sgSetVec2 ( t,          0                       ,                0                    ) ; t0->add ( t ) ;
228 
229   sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]+size[1]/2.0f, center[2]+size[2]/2.0f ) ; v0->add ( v ) ;
230   sgSetVec3 ( n,          1            ,          0            ,          0             ) ; n0->add ( n ) ;
231   c0->add ( colour ) ;
232   sgSetVec2 ( t,          1                       ,                1                    ) ; t0->add ( t ) ;
233 
234   sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]+size[1]/2.0f, center[2]-size[2]/2.0f ) ; v0->add ( v ) ;
235   sgSetVec3 ( n,          1            ,          0            ,          0             ) ; n0->add ( n ) ;
236   c0->add ( colour ) ;
237   sgSetVec2 ( t,          1                       ,                0                    ) ; t0->add ( t ) ;
238 
239   sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]+size[1]/2.0f, center[2]+size[2]/2.0f ) ; v0->add ( v ) ;
240   sgSetVec3 ( n,          0            ,          1            ,          0             ) ; n0->add ( n ) ;
241   c0->add ( colour ) ;
242   sgSetVec2 ( t,          2                       ,                1                    ) ; t0->add ( t ) ;
243 
244   sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]+size[1]/2.0f, center[2]-size[2]/2.0f ) ; v0->add ( v ) ;
245   sgSetVec3 ( n,          0            ,          1            ,          0             ) ; n0->add ( n ) ;
246   c0->add ( colour ) ;
247   sgSetVec2 ( t,          2                       ,                0                    ) ; t0->add ( t ) ;
248 
249   sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]-size[1]/2.0f, center[2]+size[2]/2.0f ) ; v0->add ( v ) ;
250   sgSetVec3 ( n,         -1            ,          0            ,          0             ) ; n0->add ( n ) ;
251   c0->add ( colour ) ;
252   sgSetVec2 ( t,          3                       ,                1                    ) ; t0->add ( t ) ;
253 
254   sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]-size[1]/2.0f, center[2]-size[2]/2.0f ) ; v0->add ( v ) ;
255   sgSetVec3 ( n,         -1            ,          0            ,          0             ) ; n0->add ( n ) ;
256   c0->add ( colour ) ;
257   sgSetVec2 ( t,          3                       ,                0                    ) ; t0->add ( t ) ;
258 
259   vt0 -> setVertices  ( v0 ) ;
260   vt0 -> setNormals   ( n0 ) ;
261   vt0 -> setColours   ( c0 ) ;
262   vt0 -> setTexCoords ( t0 ) ;
263 
264   vt0 -> recalcBSphere () ;
265 
266   sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]+size[1]/2.0f, center[2]-size[2]/2.0f ) ; v1->add ( v ) ;
267   sgSetVec3 ( n,          0            ,          0            ,         -1             ) ; n1->add ( n ) ;
268   c1->add ( colour ) ;
269   sgSetVec2 ( t,          0                       ,                0                    ) ; t1->add ( t ) ;
270 
271   sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]+size[1]/2.0f, center[2]-size[2]/2.0f ) ; v1->add ( v ) ;
272   sgSetVec3 ( n,          0            ,          0            ,         -1             ) ; n1->add ( n ) ;
273   c1->add ( colour ) ;
274   sgSetVec2 ( t,          1                       ,                0                    ) ; t1->add ( t ) ;
275 
276   sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]-size[1]/2.0f, center[2]-size[2]/2.0f ) ; v1->add ( v ) ;
277   sgSetVec3 ( n,          0            ,          0            ,         -1             ) ; n1->add ( n ) ;
278   c1->add ( colour ) ;
279   sgSetVec2 ( t,          0                       ,                1                    ) ; t1->add ( t ) ;
280 
281   sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]-size[1]/2.0f, center[2]-size[2]/2.0f ) ; v1->add ( v ) ;
282   sgSetVec3 ( n,          0            ,          0            ,         -1             ) ; n1->add ( n ) ;
283   c1->add ( colour ) ;
284   sgSetVec2 ( t,          1                       ,                1                    ) ; t1->add ( t ) ;
285 
286   sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]-size[1]/2.0f, center[2]+size[2]/2.0f ) ; v1->add ( v ) ;
287   sgSetVec3 ( n,          0            ,         -1            ,          0             ) ; n1->add ( n ) ;
288   c1->add ( colour ) ;
289   sgSetVec2 ( t,          0                       ,                2                    ) ; t1->add ( t ) ;
290 
291   sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]-size[1]/2.0f, center[2]+size[2]/2.0f ) ; v1->add ( v ) ;
292   sgSetVec3 ( n,          0            ,         -1            ,          0             ) ; n1->add ( n ) ;
293   c1->add ( colour ) ;
294   sgSetVec2 ( t,          1                       ,                2                    ) ; t1->add ( t ) ;
295 
296   sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]+size[1]/2.0f, center[2]+size[2]/2.0f ) ; v1->add ( v ) ;
297   sgSetVec3 ( n,          0            ,          0            ,          1             ) ; n1->add ( n ) ;
298   c1->add ( colour ) ;
299   sgSetVec2 ( t,          0                       ,                3                    ) ; t1->add ( t ) ;
300 
301   sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]+size[1]/2.0f, center[2]+size[2]/2.0f ) ; v1->add ( v ) ;
302   sgSetVec3 ( n,          0            ,          0            ,          1             ) ; n1->add ( n ) ;
303   c1->add ( colour ) ;
304   sgSetVec2 ( t,          1                       ,                3                    ) ; t1->add ( t ) ;
305 
306   vt1 -> setVertices  ( v1 ) ;
307   vt1 -> setNormals   ( n1 ) ;
308   vt1 -> setColours   ( c1 ) ;
309   vt1 -> setTexCoords ( t1 ) ;
310 
311   vt1 -> recalcBSphere () ;
312 
313   recalcBSphere () ;
314 }
315 
316 
317 /*
318   This code is 'inspired' by the function 'sphere' written by
319   David Blythe for GLUT 3.5 and uses his values for the coordinates
320   of the initial Icosahedron.
321 */
322 
323 #define CZ 0.89442719099991f   /* 2/sqrt(5) */
324 #define SZ 0.44721359549995f   /* 1/sqrt(5) */
325 #define C1 0.951056516f        /* cos(18) */
326 #define S1 0.309016994f        /* sin(18) */
327 #define C2 0.587785252f        /* cos(54) */
328 #define S2 0.809016994f        /* sin(54) */
329 #define X1 (C1*CZ)
330 #define Y1 (S1*CZ)
331 #define X2 (C2*CZ)
332 #define Y2 (S2*CZ)
333 
334 #define P0 {   0,   0,   1 }
335 #define P1 { -X2, -Y2,  SZ }
336 #define P2 {  X2, -Y2,  SZ }
337 #define P3 {  X1,  Y1,  SZ }
338 #define P4 {   0,  CZ,  SZ }
339 #define P5 { -X1,  Y1,  SZ }
340 #define P6 { -X1, -Y1, -SZ }
341 #define P7 {   0, -CZ, -SZ }
342 #define P8 {  X1, -Y1, -SZ }
343 #define P9 {  X2,  Y2, -SZ }
344 #define PA { -X2,  Y2, -SZ }
345 #define PB {   0,   0,  -1 }
346 
347 struct Triangle
348 {
349   sgVec3 v0, v1, v2 ;
350 } ;
351 
352 
353 static Triangle icosahedron [ 20 ] =
354 {
355   { P0, P1, P2 }, { P0, P5, P1 }, { P0, P4, P5 }, { P0, P3, P4 }, { P0, P2, P3 },
356   { P1, P6, P7 }, { P6, P1, P5 }, { P5, PA, P6 }, { PA, P5, P4 }, { P4, P9, PA },
357   { P9, P4, P3 }, { P3, P8, P9 }, { P8, P3, P2 }, { P2, P7, P8 }, { P7, P2, P1 },
358   { P9, P8, PB }, { PA, P9, PB }, { P6, PA, PB }, { P7, P6, PB }, { P8, P7, PB }
359 } ;
360 
361 
362 
regenerateTessellatedIcosahedron()363 void ssgaSphere::regenerateTessellatedIcosahedron ()
364 {
365   int tris_per_strip = 1 ;
366   int nstrips = 1 ;
367   int nt = 20 ;
368 
369   while ( nt < ntriangles )
370   {
371     nstrips++ ;
372     tris_per_strip += 2 ;
373     nt += tris_per_strip * 20 ;
374   }
375 
376   /* 20 sides of an Icosahedron */
377 
378   for ( int s = 0 ; s < 20 ; s++ )
379   {
380     Triangle *tri = & icosahedron [ s ] ;
381 
382     for ( int i = 0 ; i < nstrips ; i++ )
383     {
384       /*
385         Create a tri-strip for each row
386         The number of triangles in each strip is two greater
387         than the last one.
388       */
389 
390       sgVec3 v0, v1, v2, v3, va, vb ;
391 
392       /*
393                           t->v[0]
394                              /\
395                             /  \
396                            /____\v1
397                           /\    /\
398                          /  \  /  \
399                         /____\/vb__\v0
400                        /\    /\    /\
401                       /  \  /  \  /  \
402                      /____\/____\/va__\
403                     /\    /\    /\    /\
404                    /  \  /  \  /  \  /  \
405           t->v[2] /____\/____\/____\/____\ t->v[1]
406                        v3     v2
407       */
408 
409       /*
410         This should be a spherical interpolation - but that's slow and
411         nobody can tell the difference anyway
412       */
413 
414       ssgVtxTable      *vt = new ssgVtxTable ;
415       ssgVertexArray   *vv = new ssgVertexArray   ( i + 3 ) ;
416       ssgNormalArray   *nn = new ssgNormalArray   ( i + 3 ) ;
417       ssgColourArray   *cc = new ssgColourArray   ( i + 3 ) ;
418       ssgTexCoordArray *tt = new ssgTexCoordArray ( i + 3 ) ;
419 
420       addKid ( vt ) ;
421 
422       vt -> setState    ( getKidState () ) ;
423       vt -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB  () ) ;
424       vt -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ;
425 
426       sgVec3 v ; sgVec3 n ; sgVec2 t ;
427 
428       vt -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ;
429 
430       sgLerpVec3 ( v0, tri->v1, tri->v0, (float)(i+1) / (float) nstrips ) ;
431       sgLerpVec3 ( v1, tri->v1, tri->v0, (float)  i   / (float) nstrips ) ;
432       sgLerpVec3 ( v2, tri->v1, tri->v2, (float)(i+1) / (float) nstrips ) ;
433       sgLerpVec3 ( v3, tri->v1, tri->v2, (float)  i   / (float) nstrips ) ;
434 
435       sgNormalizeVec3 ( v0 ) ;
436       sgNormalizeVec3 ( v1 ) ;
437       sgNormalizeVec3 ( v2 ) ;
438       sgNormalizeVec3 ( v3 ) ;
439 
440       sgSetVec3 ( v, center[0]+size[0]*v0[0]/2.0f,
441                      center[1]+size[1]*v0[1]/2.0f,
442                      center[2]+size[2]*v0[2]/2.0f ) ;
443       sgSetVec3 ( n, size[0]*v0[0],
444                      size[1]*v0[1],
445                      size[2]*v0[2] ) ;
446       sgNormalizeVec3 ( n ) ;
447       sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+v0[2]/2.0f ) ;
448       vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
449 
450       sgSetVec3 ( v, center[0]+size[0]*v1[0]/2.0f,
451                      center[1]+size[1]*v1[1]/2.0f,
452                      center[2]+size[2]*v1[2]/2.0f ) ;
453       sgSetVec3 ( n, size[0]*v1[0],
454                      size[1]*v1[1],
455                      size[2]*v1[2] ) ;
456       sgNormalizeVec3 ( n ) ;
457       sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+v1[2]/2.0f ) ;
458       vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
459 
460       for ( int j = 0 ; j < i ; j++ )
461       {
462         sgLerpVec3 ( va, v0, v2, (float)(j+1) / (float) (i+1) ) ;
463         sgLerpVec3 ( vb, v1, v3, (float)(j+1) / (float)   i   ) ;
464         sgNormalizeVec3 ( va ) ;
465         sgNormalizeVec3 ( vb ) ;
466 
467 	sgSetVec3 ( v, center[0]+size[0]*va[0]/2.0f,
468 		       center[1]+size[1]*va[1]/2.0f,
469 		       center[2]+size[2]*va[2]/2.0f ) ;
470 	sgSetVec3 ( n, size[0]*va[0],
471 		       size[1]*va[1],
472 		       size[2]*va[2] ) ;
473 	sgNormalizeVec3 ( n ) ;
474         sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+va[2]/2.0f ) ;
475 	vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
476 
477 	sgSetVec3 ( v, center[0]+size[0]*vb[0]/2.0f,
478 		       center[1]+size[1]*vb[1]/2.0f,
479 		       center[2]+size[2]*vb[2]/2.0f ) ;
480 	sgSetVec3 ( n, size[0]*vb[0],
481 		       size[1]*vb[1],
482 		       size[2]*vb[2] ) ;
483 	sgNormalizeVec3 ( n ) ;
484         sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+vb[2]/2.0f ) ;
485 	vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
486       }
487 
488       sgSetVec3 ( v, center[0]+size[0]*v2[0]/2.0f,
489                      center[1]+size[1]*v2[1]/2.0f,
490                      center[2]+size[2]*v2[2]/2.0f ) ;
491       sgSetVec3 ( n, size[0]*v2[0],
492                      size[1]*v2[1],
493                      size[2]*v2[2] ) ;
494       sgNormalizeVec3 ( n ) ;
495       sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+v2[2]/2.0f ) ;
496       vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
497 
498       vt -> setVertices  ( vv ) ;
499       vt -> setNormals   ( nn ) ;
500       vt -> setColours   ( cc ) ;
501       vt -> setTexCoords ( tt ) ;
502 
503       vt -> recalcBSphere () ;
504     }
505   }
506 
507   recalcBSphere () ;
508 }
509 
510 
regenerateLatLong()511 void ssgaSphere::regenerateLatLong ()
512 {
513   int stacks = (int) sqrt ( (double) ntriangles / 2.0f ) ;
514 
515   if ( stacks < 2 ) stacks = 2 ;
516 
517   int slices = ntriangles / stacks ;
518 
519   if ( slices < 3 ) slices = 3 ;
520 
521   for ( int i = 0 ; i < stacks ; i++ )
522   {
523     ssgVtxTable      *vt = new ssgVtxTable ;
524     ssgVertexArray   *vv = new ssgVertexArray   ( (slices+1)*2 ) ;
525     ssgNormalArray   *nn = new ssgNormalArray   ( (slices+1)*2 ) ;
526     ssgColourArray   *cc = new ssgColourArray   ( (slices+1)*2 ) ;
527     ssgTexCoordArray *tt = new ssgTexCoordArray ( (slices+1)*2 ) ;
528 
529     addKid ( vt ) ;
530 
531     vt -> setState    ( getKidState () ) ;
532     vt -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB  () ) ;
533     vt -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ;
534 
535     sgVec3 v ; sgVec3 n ; sgVec2 t ;
536 
537     if ( i == stacks-1 )   /* North Pole */
538     {
539       vt -> setPrimitiveType ( GL_TRIANGLE_FAN ) ;
540 
541       sgSetVec3 ( v, center[0], center[1], center[2]+size[2]/2.0f ) ;
542       sgSetVec3 ( n, 0, 0, 1 ) ;
543       sgSetVec2 ( t, 0.5f, 1 ) ;
544       vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
545 
546       for ( int j = slices ; j >= 0 ; j-- )
547       {
548         float a = (j==0 || j==slices) ? 0.0f : (float) j * SG_PI * 2.0f / (float) slices ;
549         float b = (float) i * SG_PI / (float) stacks ;
550 
551 	sgSetVec3 ( v, center[0] + size[0]*SIN(a)*SIN(b)/2.0f,
552                        center[1] + size[1]*COS(a)*SIN(b)/2.0f,
553                        center[2] - size[2]*       COS(b)/2.0f ) ;
554 	sgSetVec3 ( n, SIN(a)*SIN(b)*size[0],
555                        COS(a)*SIN(b)*size[1],
556                        -COS(b)*size[2] ) ;
557         sgNormalizeVec3 ( n ) ;
558 	sgSetVec2 ( t, (float)j/(float)slices, (float) i /(float)stacks ) ;
559 	vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
560       }
561     }
562     else
563     if ( i == 0 )   /* South Pole */
564     {
565       vt -> setPrimitiveType ( GL_TRIANGLE_FAN ) ;
566 
567       sgSetVec3 ( v, center[0], center[1], center[2]-size[2]/2.0f ) ;
568       sgSetVec3 ( n, 0, 0, -1 ) ;
569       sgSetVec2 ( t, 0.5, 0 ) ;
570       vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
571 
572       for ( int j = 0 ; j < slices+1 ; j++ )
573       {
574         float a = (j==0 || j==slices) ? 0.0f : (float) j * SG_PI * 2.0f / (float) slices ;
575         float b = (float)(i+1) * SG_PI / (float) stacks ;
576 
577 	sgSetVec3 ( v, center[0] + size[0]*SIN(a)*SIN(b)/2.0f,
578                        center[1] + size[1]*COS(a)*SIN(b)/2.0f,
579                        center[2] - size[2]*       COS(b)/2.0f ) ;
580 	sgSetVec3 ( n, SIN(a)*SIN(b)*size[0],
581                        COS(a)*SIN(b)*size[1],
582                        -COS(b)*size[2] ) ;
583         sgNormalizeVec3 ( n ) ;
584 	sgSetVec2 ( t, (float)j/(float)slices,
585                        (float)(i+1)/(float)stacks ) ;
586 	vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
587       }
588     }
589     else
590     {
591       vt -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ;
592 
593       for ( int j = 0 ; j < slices+1 ; j++ )
594       {
595         float a = (j==0 || j==slices) ? 0.0f : (float) j * SG_PI * 2.0f / (float) slices ;
596         float b0 = (float) i * SG_PI / (float) stacks ;
597         float b1 = (float)(i+1) * SG_PI / (float) stacks ;
598 
599 	sgSetVec3 ( v, center[0] + size[0]*SIN(a)*SIN(b0)/2.0f,
600                        center[1] + size[1]*COS(a)*SIN(b0)/2.0f,
601                        center[2] - size[2]*       COS(b0)/2.0f ) ;
602 	sgSetVec3 ( n, SIN(a)*SIN(b0)*size[0],
603                        COS(a)*SIN(b0)*size[1],
604                        -COS(b0)*size[2] ) ;
605         sgNormalizeVec3 ( n ) ;
606 	sgSetVec2 ( t, (float)j/(float)slices,
607                        (float)i/(float)stacks ) ;
608 	vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
609 
610 	sgSetVec3 ( v, center[0] + size[0]*SIN(a)*SIN(b1)/2.0f,
611                        center[1] + size[1]*COS(a)*SIN(b1)/2.0f,
612                        center[2] - size[2]*       COS(b1)/2.0f ) ;
613 	sgSetVec3 ( n, SIN(a)*SIN(b1)*size[0],
614                        COS(a)*SIN(b1)*size[1],
615                        -COS(b1)*size[2] ) ;
616         sgNormalizeVec3 ( n ) ;
617 	sgSetVec2 ( t, (float)j/(float)slices,
618                        (float)(i+1)/(float)stacks ) ;
619 	vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
620 
621       }
622     }
623 
624     vt -> setVertices  ( vv ) ;
625     vt -> setNormals   ( nn ) ;
626     vt -> setColours   ( cc ) ;
627     vt -> setTexCoords ( tt ) ;
628 
629     vt -> recalcBSphere () ;
630   }
631 
632   recalcBSphere () ;
633 }
634 
635 
regenerate()636 void ssgaSphere::regenerate ()
637 {
638   if ( kidState != NULL ) kidState -> ref () ;
639   removeAllKids () ;
640   if ( kidState != NULL ) kidState -> deRef () ;
641 
642   if ( ntriangles == 0 )
643     return ;
644 
645   if ( latlong_style )
646     regenerateLatLong () ;
647   else
648     regenerateTessellatedIcosahedron () ;
649 }
650 
651 
652 
regenerate()653 void ssgaCylinder::regenerate ()
654 {
655   if ( kidState != NULL ) kidState -> ref () ;
656   removeAllKids () ;
657   if ( kidState != NULL ) kidState -> deRef () ;
658 
659   if ( ntriangles == 0 )
660     return ;
661 
662   int slices = 1 + ntriangles / 4 ;
663 
664   if ( slices < 3 ) slices = 3 ;
665 
666   ssgVtxTable      *vt = new ssgVtxTable ;
667   ssgVertexArray   *vv = new ssgVertexArray   ( (slices+1)*2 ) ;
668   ssgNormalArray   *nn = new ssgNormalArray   ( (slices+1)*2 ) ;
669   ssgColourArray   *cc = new ssgColourArray   ( (slices+1)*2 ) ;
670   ssgTexCoordArray *tt = new ssgTexCoordArray ( (slices+1)*2 ) ;
671 
672   addKid ( vt ) ;
673 
674   vt -> setState    ( getKidState () ) ;
675   vt -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB  () ) ;
676   vt -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ;
677 
678   sgVec3 v ; sgVec3 n ; sgVec2 t ;
679 
680   vt -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ;
681 
682   for ( int j = 0 ; j < slices+1 ; j++ )
683   {
684     float a = (j==0 || j==slices) ? 0.0f : (float) j * SG_PI * 2.0f / (float) slices ;
685 
686     sgSetVec3 ( v, center[0] + size[0]*SIN(a)/2.0f,
687 		   center[1] + size[1]*COS(a)/2.0f,
688 		   center[2] - size[2] / 2.0f ) ;
689     sgSetVec3 ( n, -SIN(a) * size[0], -COS(a) * size[1], 0 ) ;
690     sgNormalizeVec3 ( n ) ;
691     sgSetVec2 ( t, (float)j/(float)slices, 0 ) ;
692     vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
693 
694     sgSetVec3 ( v, center[0] + size[0]*SIN(a)/2.0f,
695 		   center[1] + size[1]*COS(a)/2.0f,
696 		   center[2] + size[2] / 2.0f ) ;
697     sgSetVec3 ( n, -SIN(a) * size[0], -COS(a) * size[1], 0 ) ;
698     sgNormalizeVec3 ( n ) ;
699     sgSetVec2 ( t, (float)j/(float)slices, 1 ) ;
700     vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ;
701 
702   }
703 
704   vt -> setVertices  ( vv ) ;
705   vt -> setNormals   ( nn ) ;
706   vt -> setColours   ( cc ) ;
707   vt -> setTexCoords ( tt ) ;
708   vt -> recalcBSphere () ;
709 
710   if ( capped )
711   {
712     ssgVtxTable      *vt0 = new ssgVtxTable ;
713     ssgVtxTable      *vt1 = new ssgVtxTable ;
714 
715     ssgVertexArray   *vv0 = new ssgVertexArray   ( slices ) ;
716     ssgNormalArray   *nn0 = new ssgNormalArray   ( slices ) ;
717     ssgColourArray   *cc0 = new ssgColourArray   ( slices ) ;
718     ssgTexCoordArray *tt0 = new ssgTexCoordArray ( slices ) ;
719 
720     ssgVertexArray   *vv1 = new ssgVertexArray   ( slices ) ;
721     ssgNormalArray   *nn1 = new ssgNormalArray   ( slices ) ;
722     ssgColourArray   *cc1 = new ssgColourArray   ( slices ) ;
723     ssgTexCoordArray *tt1 = new ssgTexCoordArray ( slices ) ;
724 
725     addKid ( vt0 ) ;
726     addKid ( vt1 ) ;
727 
728     vt0 -> setState    ( getKidState () ) ;
729     vt0 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB  () ) ;
730     vt0 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ;
731 
732     vt1 -> setState    ( getKidState () ) ;
733     vt1 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB  () ) ;
734     vt1 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ;
735 
736     sgVec3 v ; sgVec3 n ; sgVec2 t ;
737 
738     vt0 -> setPrimitiveType ( GL_TRIANGLE_FAN ) ;
739     vt1 -> setPrimitiveType ( GL_TRIANGLE_FAN ) ;
740 
741     for ( int j = 0 ; j < slices ; j++ )
742     {
743       float a0 = (float)(1+slices-j) * SG_PI * 2.0f / (float) slices ;
744       float a1 = (float)      j      * SG_PI * 2.0f / (float) slices ;
745 
746       /* Top */
747 
748       sgSetVec3 ( v, center[0] + size[0]*SIN(a0)/2.0f,
749 		     center[1] + size[1]*COS(a0)/2.0f,
750 		     center[2] + size[2] / 2.0f ) ;
751       sgSetVec3 ( n, 0, 0, 1 ) ;
752       sgSetVec2 ( t, 0.5f + SIN(a0)/2.0f, 0.5f + COS(a0)/2.0f ) ;
753       vv0->add(v) ; nn0->add(n) ; cc0->add(colour) ; tt0->add(t) ;
754 
755       /* Bottom */
756 
757       sgSetVec3 ( v, center[0] + size[0]*SIN(a1)/2.0f,
758 		     center[1] + size[1]*COS(a1)/2.0f,
759 		     center[2] - size[2] / 2.0f ) ;
760       sgSetVec3 ( n, 0, 0, -1 ) ;
761       sgSetVec2 ( t, 0.5f + SIN(a1)/2.0f, 0.5f + COS(a1)/2.0f ) ;
762       vv1->add(v) ; nn1->add(n) ; cc1->add(colour) ; tt1->add(t) ;
763     }
764 
765     vt0 -> setVertices  ( vv0 ) ; vt1 -> setVertices  ( vv1 ) ;
766     vt0 -> setNormals   ( nn0 ) ; vt1 -> setNormals   ( nn1 ) ;
767     vt0 -> setColours   ( cc0 ) ; vt1 -> setColours   ( cc1 ) ;
768     vt0 -> setTexCoords ( tt0 ) ; vt1 -> setTexCoords ( tt1 ) ;
769     vt0 -> recalcBSphere  ()    ; vt1 -> recalcBSphere  () ;
770   }
771 
772   recalcBSphere () ;
773 }
774 
775 
776 // XXX really need these (and ssgLocal.h is not accessible):
777 extern int _ssgLoadObject ( FILE *, ssgBase **, int ) ;
778 extern int _ssgSaveObject ( FILE *, ssgBase * ) ;
779 
780 
781 #define load_field(fp, name) (fread(&(name), 1, sizeof(name), fp) == sizeof(name))
782 #define save_field(fp, name) (fwrite(&(name), 1, sizeof(name), fp) == sizeof(name))
783 
784 
load(FILE * fp)785 int ssgaShape::load ( FILE *fp )
786 {
787    return ( load_field ( fp, corrupted ) &&
788 	    load_field ( fp, colour ) &&
789 	    load_field ( fp, center ) &&
790 	    load_field ( fp, size ) &&
791 	    load_field ( fp, ntriangles ) &&
792 	    _ssgLoadObject ( fp, (ssgBase **) &kidState, ssgTypeState () ) &&
793 	    ssgBranch::load ( fp ) ) ;
794 }
795 
save(FILE * fp)796 int ssgaShape::save ( FILE *fp )
797 {
798    return ( save_field ( fp, corrupted ) &&
799 	    save_field ( fp, colour ) &&
800 	    save_field ( fp, center ) &&
801 	    save_field ( fp, size ) &&
802 	    save_field ( fp, ntriangles ) &&
803 	    _ssgSaveObject ( fp, kidState ) &&
804 	    ssgBranch::save ( fp ) ) ;
805 }
806 
807 
load(FILE * fp)808 int ssgaSphere::load ( FILE *fp )
809 {
810    return ( load_field ( fp, latlong_style ) &&
811 	    ssgaShape::load ( fp ) ) ;
812 }
813 
save(FILE * fp)814 int ssgaSphere::save ( FILE *fp )
815 {
816    return ( save_field ( fp, latlong_style ) &&
817 	    ssgaShape::save ( fp ) ) ;
818 }
819 
820 
load(FILE * fp)821 int ssgaTeapot::load ( FILE *fp )
822 {
823    return ssgaShape::load ( fp ) ;
824 }
825 
save(FILE * fp)826 int ssgaTeapot::save ( FILE *fp )
827 {
828    return ssgaShape::save ( fp ) ;
829 }
830 
831 
832 
load(FILE * fp)833 int ssgaPatch::load ( FILE *fp )
834 {
835    return ( load_field ( fp, levels ) &&
836       fread(control_points, 1, 16*9*sizeof(float), fp) == 16*9*sizeof(float) &&
837             ssgaShape::load ( fp ) ) ;
838 }
839 
save(FILE * fp)840 int ssgaPatch::save ( FILE *fp )
841 {
842    return ( save_field ( fp, levels ) &&
843       fwrite(control_points, 1, 16*9*sizeof(float), fp) == 16*9*sizeof(float) &&
844             ssgaShape::save ( fp ) ) ;
845 }
846 
847 
load(FILE * fp)848 int ssgaCylinder::load ( FILE *fp )
849 {
850    return ( load_field ( fp, capped ) &&
851 	    ssgaShape::load ( fp ) ) ;
852 }
853 
save(FILE * fp)854 int ssgaCylinder::save ( FILE *fp )
855 {
856    return ( save_field ( fp, capped ) &&
857 	    ssgaShape::save ( fp ) ) ;
858 }
859 
860 
861