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: ssg.cxx 2125 2007-09-29 17:20:40Z fayjf $
22 */
23 
24 
25 #define _UL_GENERATE_CODE_
26 #include "ssgLocal.h"
27 
28 #if defined(UL_MACINTOSH)
29 #  include <agl.h>
30 #elif defined(UL_MAC_OSX)
31 #  include <OpenGL/CGLCurrent.h>
32 #elif defined(UL_WIN32)
33    /* Nothing */
34 #else
35 #  include <GL/glx.h>
36 #endif
37 
glIsValidContext(void)38 static bool glIsValidContext ( void )
39 {
40 #if defined(CONSOLE)
41   return true ;
42 #elif defined(UL_WIN32)
43   return ( wglGetCurrentContext () != NULL ) ;
44 #elif defined(UL_MACINTOSH)
45   return ( aglGetCurrentContext () != NULL ) ;
46 #elif defined(UL_MAC_OSX)
47   return ( CGLGetCurrentContext () != NULL ) ;
48 #else
49   return ( glXGetCurrentContext () != NULL ) ;
50 #endif
51 }
52 
53 sgMat4 _ssgOpenGLAxisSwapMatrix =
54 {
55   {  1.0f,  0.0f,  0.0f,  0.0f },
56   {  0.0f,  0.0f, -1.0f,  0.0f },
57   {  0.0f,  1.0f,  0.0f,  0.0f },
58   {  0.0f,  0.0f,  0.0f,  1.0f }
59 } ;
60 
61 sgVec3 _ssgVertex000   = { 0.0f, 0.0f, 0.0f } ;
62 sgVec4 _ssgColourWhite = { 1.0f, 1.0f, 1.0f, 1.0f } ;
63 sgVec3 _ssgNormalUp    = { 0.0f, 0.0f, 1.0f } ;
64 sgVec2 _ssgTexCoord00  = { 0.0f, 0.0f } ;
65 short  _ssgIndex0      = 0;
66 bool   _ssgBackFaceCollisions = false ;
67 
ssgSetBackFaceCollisions(bool b)68 void ssgSetBackFaceCollisions ( bool b ) { _ssgBackFaceCollisions = b ; }
69 
70 static ssgLight _ssgLights [ 8 ] ;
71 static int      _ssgFrameCounter = 0 ;
72 
ssgGetFrameCounter()73 int  ssgGetFrameCounter () { return _ssgFrameCounter ; }
ssgSetFrameCounter(int fc)74 void ssgSetFrameCounter ( int fc ) { _ssgFrameCounter = fc ; }
75 
ssgGetVersion()76 const char *ssgGetVersion ()
77 {
78 #ifdef VERSION
79   return VERSION ;
80 #else
81   return "Unknown" ;
82 #endif
83 }
84 
ssgDeRefDelete(ssgBase * s)85 void ssgDeRefDelete ( ssgBase *s )
86 {
87   if ( s == NULL ) return ;
88 
89   s -> deRef () ;
90 
91   if ( s -> getRef () <= 0 )
92     delete s ;
93 }
94 
ssgDelete(ssgBranch * br)95 void ssgDelete ( ssgBranch *br )
96 {
97   if ( br == NULL )
98     return ;
99 
100   br -> removeAllKids () ;
101   delete br ;
102 }
103 
ssgGetLight(int i)104 ssgLight *ssgGetLight ( int i )
105 {
106   return &_ssgLights [ i ] ;
107 }
108 
ssgInit()109 void ssgInit ()
110 {
111   if ( ! glIsValidContext () )
112   {
113     ulSetError ( UL_FATAL, "ssgInit called without a valid OpenGL context.");
114   }
115 
116   ssgTexturePath ( "." ) ;
117   ssgModelPath   ( "." ) ;
118 
119   _ssgLights [ 0 ] . setID ( 0 ) ;
120   _ssgLights [ 0 ] . on    () ;
121 
122   for ( int i = 1 ; i < 8 ; i++ )
123   {
124     _ssgLights [ i ] . setID ( i ) ;
125     _ssgLights [ i ] . off   () ;
126   }
127 
128   new ssgContext ;  /* Sets the current context with defaults */
129 
130   ssgAddModelFormat ( ".ssg",   ssgLoadSSG  , ssgSaveSSG ) ;
131 
132   ssgAddModelFormat ( ".3ds",   ssgLoad3ds  , ssgSave3ds ) ;
133   ssgAddModelFormat ( ".ac" ,   ssgLoadAC3D , ssgSaveAC  ) ;
134   ssgAddModelFormat ( ".ase",   ssgLoadASE  , ssgSaveASE ) ;
135   ssgAddModelFormat ( ".dof",   ssgLoadDOF  , NULL       ) ;
136   ssgAddModelFormat ( ".dxf",   ssgLoadDXF  , ssgSaveDXF ) ;
137   ssgAddModelFormat ( ".obj",   ssgLoadOBJ  , ssgSaveOBJ ) ;
138   ssgAddModelFormat ( ".tri",   ssgLoadTRI  , ssgSaveTRI ) ;
139   ssgAddModelFormat ( ".md2",   ssgLoadMD2  , NULL       ) ;
140   ssgAddModelFormat ( ".x"  ,   ssgLoadX    , ssgSaveX   ) ;
141   ssgAddModelFormat ( ".flt",   ssgLoadFLT  , ssgSaveFLT ) ;
142   ssgAddModelFormat ( ".strip", ssgLoadStrip, NULL       ) ;
143   ssgAddModelFormat ( ".m"  ,   ssgLoadM    , ssgSaveM   ) ;
144   ssgAddModelFormat ( ".off"  , ssgLoadOFF  , ssgSaveOFF ) ;
145   ssgAddModelFormat ( ".atg"  , ssgLoadATG  , ssgSaveATG ) ;
146   ssgAddModelFormat ( ".qhi"  , NULL        , ssgSaveQHI ) ;
147   ssgAddModelFormat ( ".wrl",   ssgLoadVRML1, ssgSaveVRML1 ) ;
148   ssgAddModelFormat ( ".iv",    ssgLoadIV   , ssgSaveIV  ) ;
149   ssgAddModelFormat ( ".asc",   ssgLoadASC  , ssgSaveASC ) ;
150 //ssgAddModelFormat ( ".pov",   NULL        , ssgSavePOV ) ;
151 
152 
153 #ifdef SSG_LOAD_MDL_SUPPORTED
154   ssgAddModelFormat ( ".mdl",   ssgLoadMDL  , NULL       ) ;
155 #endif
156 
157 #ifdef SSG_LOAD_TGA_SUPPORTED
158   ssgAddTextureFormat ( ".tga" ,   ssgLoadTGA ) ;
159 #endif
160 
161 #ifdef SSG_LOAD_BMP_SUPPORTED
162   ssgAddTextureFormat ( ".bmp" ,   ssgLoadBMP ) ;
163 #endif
164 
165 #ifdef SSG_LOAD_PNG_SUPPORTED
166   ssgAddTextureFormat ( ".png" ,   ssgLoadPNG ) ;
167 #endif
168 
169 #ifdef SSG_LOAD_PCX_SUPPORTED
170   ssgAddTextureFormat ( ".pcx" ,   ssgLoadPCX ) ;
171 #endif
172 
173 #ifdef SSG_LOAD_SGI_SUPPORTED
174   ssgAddTextureFormat ( ".rgb" ,   ssgLoadSGI ) ;
175   ssgAddTextureFormat ( ".rgba" ,  ssgLoadSGI ) ;
176   ssgAddTextureFormat ( ".int" ,   ssgLoadSGI ) ;
177   ssgAddTextureFormat ( ".inta" ,  ssgLoadSGI ) ;
178   ssgAddTextureFormat ( ".bw" ,    ssgLoadSGI ) ;
179 #endif
180 
181 #if defined(SSG_LOAD_MDL_SUPPORTED) || defined(SSG_LOAD_MDL_BGL_TEXTURE_SUPPORTED)
182   ssgAddTextureFormat ( ".0af" ,   ssgLoadMDLTexture ) ;
183   ssgAddTextureFormat ( ".1af" ,   ssgLoadMDLTexture ) ;
184   ssgAddTextureFormat ( ".2af" ,   ssgLoadMDLTexture ) ;
185   ssgAddTextureFormat ( ".3af" ,   ssgLoadMDLTexture ) ;
186   ssgAddTextureFormat ( ".4af" ,   ssgLoadMDLTexture ) ;
187   ssgAddTextureFormat ( ".5af" ,   ssgLoadMDLTexture ) ;
188   ssgAddTextureFormat ( ".6af" ,   ssgLoadMDLTexture ) ;
189   ssgAddTextureFormat ( ".7af" ,   ssgLoadMDLTexture ) ;
190   ssgAddTextureFormat ( ".8af" ,   ssgLoadMDLTexture ) ;
191   ssgAddTextureFormat ( ".9af" ,   ssgLoadMDLTexture ) ;
192   ssgAddTextureFormat ( ".aaf" ,   ssgLoadMDLTexture ) ;
193   ssgAddTextureFormat ( ".baf" ,   ssgLoadMDLTexture ) ;
194   ssgAddTextureFormat ( ".caf" ,   ssgLoadMDLTexture ) ;
195   ssgAddTextureFormat ( ".daf" ,   ssgLoadMDLTexture ) ;
196   ssgAddTextureFormat ( ".eaf" ,   ssgLoadMDLTexture ) ;
197   ssgAddTextureFormat ( ".faf" ,   ssgLoadMDLTexture ) ;
198   ssgAddTextureFormat ( ".gaf" ,   ssgLoadMDLTexture ) ;
199   ssgAddTextureFormat ( ".haf" ,   ssgLoadMDLTexture ) ;
200   ssgAddTextureFormat ( ".iaf" ,   ssgLoadMDLTexture ) ;
201   ssgAddTextureFormat ( ".jaf" ,   ssgLoadMDLTexture ) ;
202   ssgAddTextureFormat ( ".kaf" ,   ssgLoadMDLTexture ) ;
203   ssgAddTextureFormat ( ".pat" ,   ssgLoadMDLTexture ) ;
204   ssgAddTextureFormat ( ".r8"  ,   ssgLoadMDLTexture ) ;
205   ssgAddTextureFormat ( ".naz" ,   ssgLoadMDLTexture ) ;
206   ssgAddTextureFormat ( ".ktx" ,   ssgLoadMDLTexture ) ;
207   ssgAddTextureFormat ( ".oav" ,   ssgLoadMDLTexture ) ;
208   ssgAddTextureFormat ( ".sky" ,   ssgLoadMDLTexture ) ;
209   ssgAddTextureFormat ( ".ngt" ,   ssgLoadMDLTexture ) ;
210 #endif
211 
212 #ifdef SSG_LOAD_XPL_SUPPORTED
213   ssgAddModelFormat ( ".xpl",   ssgLoadXPlaneOBJ  , NULL ) ;
214 #endif
215 }
216 
217 
218 
ssgCullAndPick(ssgBranch * r,sgVec2 botleft,sgVec2 topright)219 void ssgCullAndPick ( ssgBranch *r, sgVec2 botleft, sgVec2 topright )
220 {
221   if ( _ssgCurrentContext == NULL )
222   {
223     ulSetError ( UL_FATAL, "ssg: No Current Context: Did you forgot to call ssgInit()?" ) ;
224   }
225 
226   ssgForceBasicState () ;
227 
228   GLint vp [ 4 ] ;
229   sgVec4 viewport ;
230   sgMat4 mat ;
231 
232   float w = (topright[0] - botleft[0]) ;
233   float h = (topright[1] - botleft[1]) ;
234 
235   float x = (botleft[0] + topright[0]) / 2.0f ;
236   float y = (botleft[1] + topright[1]) / 2.0f ;
237 
238   glGetIntegerv ( GL_VIEWPORT, vp ) ;
239 
240   sgSetVec4 ( viewport, (float)vp[0], (float)vp[1],
241                         (float)vp[2], (float)vp[3] ) ;
242   sgMakePickMatrix ( mat, x, y, w, h, viewport ) ;
243 
244   glMatrixMode ( GL_PROJECTION ) ;
245   glLoadIdentity () ;
246   glMultMatrixf ( (float *) mat ) ;
247 
248   _ssgCurrentContext->pushProjectionMatrix () ;
249 
250   glMatrixMode ( GL_MODELVIEW ) ;
251   glLoadIdentity () ;
252 
253   int i ;
254 
255   for ( i = 0 ; i < 8 ; i++ )
256     if ( _ssgLights [ i ] . isHeadlight () )
257       _ssgLights [ i ] . setup () ;
258 
259   _ssgCurrentContext->loadModelviewMatrix () ;
260 
261   for ( i = 0 ; i < 8 ; i++ )
262     if ( ! _ssgLights [ i ] . isHeadlight () )
263       _ssgLights [ i ] . setup () ;
264 
265   _ssgCurrentContext->cull(r) ;
266   _ssgDrawDList () ;
267 
268   glMatrixMode ( GL_MODELVIEW ) ;
269   glLoadIdentity () ;
270 }
271 
272 
ssgCullAndDraw(ssgBranch * r)273 void ssgCullAndDraw ( ssgBranch *r )
274 {
275   if ( _ssgCurrentContext == NULL )
276   {
277     ulSetError ( UL_FATAL, "ssg: No Current Context: Did you forgot to call ssgInit()?" ) ;
278   }
279 
280   _ssgStartOfFrameInit () ;
281 
282   ssgForceBasicState () ;
283 
284   glMatrixMode ( GL_PROJECTION ) ;
285   _ssgCurrentContext->loadProjectionMatrix () ;
286 
287   glMatrixMode ( GL_MODELVIEW ) ;
288   glLoadIdentity () ;
289 
290   int i ;
291 
292   for ( i = 0 ; i < 8 ; i++ )
293     if ( _ssgLights [ i ] . isHeadlight () )
294       _ssgLights [ i ] . setup () ;
295 
296   _ssgCurrentContext->loadModelviewMatrix () ;
297   _ssgCurrentContext->applyClipPlanes () ;
298 
299   for ( i = 0 ; i < 8 ; i++ )
300     if ( ! _ssgLights [ i ] . isHeadlight () )
301       _ssgLights [ i ] . setup () ;
302 
303   _ssgCurrentContext->cull(r) ;
304   _ssgDrawDList () ;
305 
306   _ssgCurrentContext->removeClipPlanes () ;
307 
308   glMatrixMode ( GL_MODELVIEW ) ;
309   glLoadIdentity () ;
310 
311   _ssgEndOfFrameCleanup () ;
312   _ssgFrameCounter++ ;
313 }
314 
315 
getTypeName(void)316 const char *ssgAxisTransform::getTypeName (void) { return "ssgAxisTransform" ; }
getTypeName(void)317 const char *ssgBase         ::getTypeName (void) { return "ssgBase"          ; }
getTypeName(void)318 const char *ssgTexture      ::getTypeName (void) { return "ssgTexture"       ; }
getTypeName(void)319 const char *ssgState        ::getTypeName (void) { return "ssgState"         ; }
getTypeName(void)320 const char *ssgSimpleState  ::getTypeName (void) { return "ssgSimpleState"   ; }
getTypeName(void)321 const char *ssgStateSelector::getTypeName (void) { return "ssgStateSelector" ; }
getTypeName(void)322 const char *ssgEntity       ::getTypeName (void) { return "ssgEntity"        ; }
getTypeName(void)323 const char *ssgLeaf         ::getTypeName (void) { return "ssgLeaf"          ; }
getTypeName(void)324 const char *ssgVTable       ::getTypeName (void) { return "ssgVTable"        ; }
getTypeName(void)325 const char *ssgVtxTable     ::getTypeName (void) { return "ssgVtxTable"      ; }
getTypeName(void)326 const char *ssgVtxArray     ::getTypeName (void) { return "ssgVtxArray"      ; }
getTypeName(void)327 const char *ssgBranch       ::getTypeName (void) { return "ssgBranch"        ; }
getTypeName(void)328 const char *ssgSelector     ::getTypeName (void) { return "ssgSelector"      ; }
getTypeName(void)329 const char *ssgRangeSelector::getTypeName (void) { return "ssgRangeSelector" ; }
getTypeName(void)330 const char *ssgTimedSelector::getTypeName (void) { return "ssgTimedSelector" ; }
getTypeName(void)331 const char *ssgBaseTransform::getTypeName (void) { return "ssgBaseTransform" ; }
getTypeName(void)332 const char *ssgTransform    ::getTypeName (void) { return "ssgTransform"     ; }
getTypeName(void)333 const char *ssgTexTrans     ::getTypeName (void) { return "ssgTexTrans"      ; }
getTypeName(void)334 const char *ssgCutout       ::getTypeName (void) { return "ssgCutout"        ; }
getTypeName(void)335 const char *ssgRoot         ::getTypeName (void) { return "ssgRoot"          ; }
336 
getTypeName(void)337 const char *ssgSimpleList   ::getTypeName (void) { return "ssgSimpleList"    ; }
getTypeName(void)338 const char *ssgColourArray  ::getTypeName (void) { return "ssgColourArray"   ; }
getTypeName(void)339 const char *ssgIndexArray   ::getTypeName (void) { return "ssgIndexArray"    ; }
getTypeName(void)340 const char *ssgTransformArray::getTypeName (void) { return "ssgTransformArray" ; }
getTypeName(void)341 const char *ssgTexCoordArray::getTypeName (void) { return "ssgTexCoordArray" ; }
getTypeName(void)342 const char *ssgVertexArray  ::getTypeName (void) { return "ssgVertexArray"   ; }
getTypeName(void)343 const char *ssgNormalArray  ::getTypeName (void) { return "ssgNormalArray"   ; }
getTypeName(void)344 const char *ssgInterleavedArray::getTypeName (void) { return "ssgInterleavedArray"; }
345 
346 
347 
createBase()348 static ssgBase *createBase ()              { return new ssgBase             ; }
349 
350 //static ssgBase *createEntity ()            { return new ssgEntity           ; }
351 //static ssgBase *createLeaf ()              { return new ssgLeaf             ; }
createVTable()352 static ssgBase *createVTable ()            { return new ssgVTable           ; }
createVtxTable()353 static ssgBase *createVtxTable ()          { return new ssgVtxTable         ; }
createVtxArray()354 static ssgBase *createVtxArray ()          { return new ssgVtxArray         ; }
createTween()355 static ssgBase *createTween ()             { return new ssgTween            ; }
createBranch()356 static ssgBase *createBranch ()            { return new ssgBranch           ; }
357 //static ssgBase *createBaseTransform ()     { return new ssgBaseTransform    ; }
createTransform()358 static ssgBase *createTransform ()         { return new ssgTransform        ; }
createTexTrans()359 static ssgBase *createTexTrans ()          { return new ssgTexTrans         ; }
createAnimTransform()360 static ssgBase *createAnimTransform()      { return new ssgAnimTransform    ; }
createAxisTransform()361 static ssgBase *createAxisTransform()      { return new ssgAxisTransform    ; }
createSelector()362 static ssgBase *createSelector ()          { return new ssgSelector         ; }
createRangeSelector()363 static ssgBase *createRangeSelector ()     { return new ssgRangeSelector    ; }
createTimedSelector()364 static ssgBase *createTimedSelector ()     { return new ssgTimedSelector    ; }
createTweenController()365 static ssgBase *createTweenController ()   { return new ssgTweenController  ; }
createRoot()366 static ssgBase *createRoot ()              { return new ssgRoot             ; }
createCutout()367 static ssgBase *createCutout ()            { return new ssgCutout           ; }
createInvisible()368 static ssgBase *createInvisible ()         { return new ssgInvisible        ; }
369 
370 //static ssgBase *createState ()             { return new ssgState            ; }
createSimpleState()371 static ssgBase *createSimpleState ()       { return new ssgSimpleState      ; }
createStateSelector()372 static ssgBase *createStateSelector ()     { return new ssgStateSelector    ; }
373 
createSimpleList()374 static ssgBase *createSimpleList ()        { return new ssgSimpleList       ; }
createVertexArray()375 static ssgBase *createVertexArray ()       { return new ssgVertexArray      ; }
createNormalArray()376 static ssgBase *createNormalArray ()       { return new ssgNormalArray      ; }
createTexCoordArray()377 static ssgBase *createTexCoordArray ()     { return new ssgTexCoordArray    ; }
createColourArray()378 static ssgBase *createColourArray ()       { return new ssgColourArray      ; }
createIndexArray()379 static ssgBase *createIndexArray ()        { return new ssgIndexArray       ; }
createTransformArray()380 static ssgBase *createTransformArray ()    { return new ssgTransformArray   ; }
createInterleavedArray()381 static ssgBase *createInterleavedArray ()  { return new ssgInterleavedArray ; }
382 
createTexture()383 static ssgBase *createTexture ()           { return new ssgTexture          ; }
384 
385 
386 static struct {
387 
388   int type ;
389   ssgBase * ( *func ) () ;
390 
391 } table[256] = {
392 
393   { ssgTypeBase ()              , createBase              },
394 
395 //{ ssgTypeEntity ()            , createEntity            },
396 //{ ssgTypeLeaf ()              , createLeaf              },
397   { ssgTypeVTable ()            , createVTable            },
398   { ssgTypeVtxTable ()          , createVtxTable          },
399   { ssgTypeVtxArray ()          , createVtxArray          },
400   { ssgTypeTween ()             , createTween             },
401   { ssgTypeBranch ()            , createBranch            },
402 //{ ssgTypeBaseTransform ()     , createBaseTransform     },
403   { ssgTypeTransform ()         , createTransform         },
404   { ssgTypeAnimTransform ()     , createAnimTransform     },
405   { ssgTypeTexTrans ()          , createTexTrans          },
406   { ssgTypeAxisTransform ()     , createAxisTransform     },
407   { ssgTypeSelector ()          , createSelector          },
408   { ssgTypeRangeSelector ()     , createRangeSelector     },
409   { ssgTypeTimedSelector ()     , createTimedSelector     },
410   { ssgTypeTweenController ()   , createTweenController   },
411   { ssgTypeRoot ()              , createRoot              },
412   { ssgTypeCutout ()            , createCutout            },
413   { ssgTypeInvisible ()         , createInvisible         },
414 
415 //{ ssgTypeState ()             , createState             },
416   { ssgTypeSimpleState ()       , createSimpleState       },
417   { ssgTypeStateSelector ()     , createStateSelector     },
418 
419   { ssgTypeSimpleList ()        , createSimpleList        },
420   { ssgTypeVertexArray ()       , createVertexArray       },
421   { ssgTypeNormalArray ()       , createNormalArray       },
422   { ssgTypeTexCoordArray ()     , createTexCoordArray     },
423   { ssgTypeColourArray ()       , createColourArray       },
424   { ssgTypeIndexArray ()        , createIndexArray        },
425   { ssgTypeTransformArray ()    , createTransformArray    },
426   { ssgTypeInterleavedArray ()  , createInterleavedArray  },
427 
428   { ssgTypeTexture ()           , createTexture           },
429 
430   { 0, NULL }
431 
432 };
433 
ssgRegisterType(int type,ssgBase * (* func)())434 void ssgRegisterType ( int type, ssgBase * ( *func ) () )
435 {
436   if ( type == 0 || func == NULL )
437   {
438     ulSetError ( UL_WARNING, "ssgRegisterType: Bad arguments (type %#x, func %p).",
439      type, func ) ;
440     return ;
441   }
442 
443   int i ;
444   for ( i = 0 ; table[i].type != 0 && table[i].type != type ; i++ )
445     ;
446 
447   if ( table[i].type == type && table[i].func != func )
448     ulSetError ( UL_WARNING, "ssgRegisterType: Type %#x redefined differently.", type ) ;
449 
450   table[i].type = type ;
451   table[i].func = func ;
452 }
453 
ssgCreateOfType(int type)454 ssgBase *ssgCreateOfType ( int type )
455 {
456   // XXX linear search
457   int i ;
458 
459   for ( i = 0 ; table[i].type != 0 && table[i].type != type ; i++ )
460     ;
461 
462   if ( table[i].type == 0 )
463   {
464     ulSetError ( UL_WARNING, "ssgCreateOfType: Unrecognized type %#x.", type ) ;
465     return NULL ;
466   }
467 
468   ssgBase *obj = (*table[i].func) () ;
469 
470   if ( obj == NULL )
471     ulSetError ( UL_WARNING, "ssgCreateOfType: Got null object for type %#x.", type ) ;
472   else if ( obj -> getType () != type )
473     ulSetError ( UL_WARNING,
474      "ssgCreateOfType: Created object has wrong type %#x (%s), expected %#x.",
475      obj -> getType (), obj -> getTypeName (), type ) ;
476 
477   return obj ;
478 }
479 
ssgSearchExtensionString(char * extString,char * extName)480 static bool ssgSearchExtensionString(char *extString, char *extName)
481 {
482   // Returns GL_TRUE if the *extName string appears in the *extString string,
483   // surrounded by white spaces, or GL_FALSE otherwise.
484 
485   char *p, *end;
486   int n, extNameLen;
487 
488   if ( ( extString == NULL ) || ( extName == NULL ) )
489     return false;
490 
491   extNameLen = strlen ( extName );
492 
493   p = extString;
494   end = p + strlen ( p );
495 
496   while ( p < end )
497   {
498     n = strcspn ( p, " " );
499     if ( ( extNameLen == n ) && ( strncmp ( extName, p, n ) == 0 ) )
500       return GL_TRUE;
501 
502     p += (n + 1);
503   }
504 
505   return GL_FALSE;
506 }
507 
ssgIsExtensionSupported(char * extName)508 bool ssgIsExtensionSupported(char *extName)
509 {
510   // Returns GL_TRUE if the OpenGL Extension whose name is *extName
511   // is supported by the system, or GL_FALSE otherwise.
512 
513   // The *extName string must follow the OpenGL extensions naming scheme
514   // (ie: "GL_type_extension", like GL_EXT_convolution)
515 
516   return ssgSearchExtensionString ( (char *)glGetString(GL_EXTENSIONS), extName );
517 }
518 
519