class ssgState
- OpenGL state representation.There can (in principal) be a number of different ways to represent OpenGL state - but all must be derived from an ssgState:
class ssgState : public ssgBase { int getExternalPropertyIndex () ; void setExternalPropertyIndex ( int i ) ; ssgStateCallback getStateCallback ( int cb_type ) ; void setStateCallback ( int cb_type, ssgStateCallback cb ) ; virtual void force () ; virtual void apply () ; } ;
Each state has three optional callback function hooks. The application program can have a function called before the state is applied, after it is applied (but before the geometry is drawn) and another after the geometry is rendered - immediately before the next state is applied.
You can set those three callbacks with setStateCallback - passing either SSG_CALLBACK_PREAPPLY, SSG_CALLBACK_PREDRAW or SSG_CALLBACK_POSTDRAW as the first parameter and the address of your function as the second.
ssgState::setExternalPropertyIndex(i)
or queried using ssgState::getExternalPropertyIndex()
.
External properties are of use to certain sorts of applications programs,
for example, a game might want to encode the set of OpenGL state information
that represents Lava as something that is hot and Ice as something that
is cold by encoding the temperature of the material in the External
property field. Most applications will probably use this field as an
index into a table of material properties inside the application itself.
In such cases, it is important to bear in mind that SSG changes the OpenGL state as little as possible - in order to save time. Hence, when a leaf node has just been drawn with one set of state information, and another leaf node is about to be drawn using another, SSG carefully compares the two states to see how they differ and arranges to make only the fewest possible OpenGL state change calls. If the application goes in "behind SSG's back" and changes state then SSG will be confused.
There are two ways to achive this. One is to use SSG state classes to
change the state by calling ssgState::apply()
. That call
will ensure that OpenGL's state matches the desired state using the
minimum of calls. However, if your application absolutely MUST make
it's own state calls then you should call ssgState::force()
to force all aspects of a specified state to be set in OpenGL so that
SSG can be certain about how things are set up.
class ssgSimpleState
- Simple State class.class ssgSimpleState : ssgState { void disable ( GLenum mode ) ; void enable ( GLenum mode ) ; void set ( GLenum mode, int val ) { val ? enable(mode) : disable(mode) ; } void setTexture ( char *fname, int wrapu = TRUE, int wrapv = TRUE ) void setTexture ( ssgTexture *tex ) void setTexture ( GLuint tex ) void setColourMaterial ( GLenum which ) void setMaterial ( GLenum which, float r, float g, float b, float a = 1.0f ) void setMaterial ( GLenum which, sgVec4 rgba ) void setShininess ( float sh ) void setShadeModel ( GLenum model ) void setAlphaClamp ( float clamp ) } ;These calls mostly correspond to similarly named OpenGL functions.
ssgSimpleState:: disable ( mode )
,
ssgSimpleState:: enable ( mode )
and
ssgSimpleState:: set ( mode, val )
provide
the same services as glEnable and glDisable ('set' is a convenience function
that is a 'disable' if 'val' is FALSE, 'enable' otherwise). The 'mode'
parameter uses tokens that are similarly named to those in OpenGL:
SSG_GL_TEXTURE_EN SSG_GL_CULL_FACE_EN SSG_GL_COLOR_MATERIAL_EN SSG_GL_BLEND_EN SSG_GL_ALPHA_TEST_EN SSG_GL_LIGHTING_EN
ssgSimpleState::setTexture ( fname, wrapu, wrapv )
,
ssgSimpleState::setTexture ( ssgtexture )
, and
ssgSimpleState::setTexture ( texture_handle )
.
In the form that takes a filename, U-axis wrap and V-axis wrap flags, the
texture is loaded from a texture file on disk (see ssgTexture
below for details on how this is done). The map will be MIPmapped and set with
a texture environment that is GL_LINEAR_MIPMAP_LINEAR and GL_MODULATE.
If you need something fancier, then declare an 'ssgTexture' class and pass that to the setTexture function. You can also load your own texture and pass the OpenGL glBindTexture handle to setTexture.
If you need the texture file name, first check that isEnabled ( GL_TEXTURE_2D ) returns true, then you may call getTextureFilename(). But you should still check the return value for NULL and for "".
ssgSimpleState::setColourMaterial(which)
ssgSimpleState::setMaterial(which,r,g,b,a)
ssgSimpleState::setMaterial(which,rgba)
ssgSimpleState::setShininess(sh)
ssgSimpleState::setShadeModel(model)
ssgSimpleState::setAlphaClamp(clamp)
class ssgTexture
- Storing texture maps.
The ssgTexture constructor function
ssgTexture::ssgTexture( char *fname,
int wrapu = TRUE, int wrapv = TRUE )
does all the work,
presuming that you require GL_LINEAR_MIPMAP_LINEAR filtering and a
GL_MODULATE texture environment.
You can obtain the OpenGL glBindTexture handle for the texture
using ssgTexture::getHandle()
.
When ssgTexture loads a map from disk, it uses the filename extension to determine which image format the file is in.
Currently, only SGI format and uncompressed 8 or 24 bit BMP images are supported - but more formats are planned for the future. Filenames ending with '.rgb', '.rgba', '.int', '.inta', '.bw' are assumed to be SGI formatted files, '.bmp' are in Microsoft's BMP format and '.png' are in Portable Network Graphics format.
If for any reason ssgTexture cannot load the requested file, it creates a 2x2 texel red and white chequerboard map to enable the program to continue running. This is often very useful for debugging and to enable program development to continue when texture maps are not yet painted.
class ssgStateSelector
- Switchable State class.class ssgStateSelector : ssgSimpleState { ssgStateSelector ( int nstates ) ; void selectStep ( unsigned int s ) ; int getSelectStep (void) ; ssgSimpleState *getCurrentStep (void) ; void setStep ( int i, ssgSimpleState *step ) ; ssgSimpleState *getStep ( int i ) ; } ;This class is used to switch between some number of
ssgSimpleStates
.
You could (for example) draw the ground for your game as either
grass or snow - depending on the season. Construct objects of this
class with the number of alternative representations you will require
as it's parameter, then create a number of ssgSimpleState
s - passing
them to ssgStateSelector::setStep()
. You can then select which
step you wish to render using ssgStateSelector::selectStep()
.
ssgStateSelector::getSelectStep()
returns the number of the currently
selected step. ssgStateSelector::getCurrentStep()
returns a pointer to
the currently selected ssgSimpleState
. ssgStateSelector::getStep()
returns a pointer to the i'th ssgSimpleState
.
Since ssgStateSelector
is derived from ssgSimpleState
,
all the other ssgSimpleState
calls work - and the effect is to
operate on the currently selected ssgSimpleState
.
Example:
ssgStateSelector *s = new ssgStateSelector ( 2 ) ; ssgSimpleState *grass = new ssgSimpleState () ; ssgSimpleState *snow = new ssgSimpleState () ; ...set up grass and snow states appropriately... s -> setStep ( 0, grass ) ; s -> setStep ( 1, snow ) ; leafnode1 -> setState ( s ) ; leafnode2 -> setState ( s ) ; leafnode3 -> setState ( s ) ; ...choose grass or snow... if ( ! winter ) s -> selectStep ( 0 ) ; else s -> selectStep ( 1 ) ; ...render the scene...Notice that one selectStep call changes the material on all leaf nodes that use that ssgStateSelector.
<= previous = | Return to SSG Index | = next => |
Steve J. Baker. <sjbaker1@airmail.net> |