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