551 lines
20 KiB
Plaintext
551 lines
20 KiB
Plaintext
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
|
|
//Distributed under the terms of the GNU Library General Public License (LGPL)
|
|
//as published by the Free Software Foundation.
|
|
|
|
#ifndef OSG_STATE
|
|
#define OSG_STATE 1
|
|
|
|
#include <osg/Export>
|
|
#include <osg/StateSet>
|
|
#include <osg/Matrix>
|
|
|
|
#include <osg/FrameStamp>
|
|
#include <osg/DisplaySettings>
|
|
#include <osg/Polytope>
|
|
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
namespace osg {
|
|
|
|
/** macro for use with osg::StateAttrbiute::apply methods for detected and
|
|
* reporting OpenGL error messages.*/
|
|
#define OSG_GL_DEBUG(message) \
|
|
if (state.getFineGrainedErrorDetection()) \
|
|
{ \
|
|
GLenum errorNo = glGetError(); \
|
|
if (errorNo!=GL_NO_ERROR) \
|
|
{ \
|
|
osg::notify(WARN)<<"Warning: detected OpenGL error '"<<gluErrorString(errorNo)<<" "<<message<<endl; \
|
|
}\
|
|
}
|
|
|
|
/** State class for managing a state stack.
|
|
* Lazy state updating is used to minimize state changes.
|
|
*/
|
|
class SG_EXPORT State : public Referenced
|
|
{
|
|
public :
|
|
|
|
State();
|
|
|
|
virtual ~State();
|
|
|
|
/** push stateset onto state stack.*/
|
|
void pushStateSet(const StateSet* dstate);
|
|
|
|
/** pop drawstate off state stack.*/
|
|
void popStateSet();
|
|
|
|
/** copy the modes and attributes which captures the current state.*/
|
|
void captureCurrentState(StateSet& stateset) const;
|
|
|
|
/** reset the state object to an empty stack.*/
|
|
void reset();
|
|
|
|
inline void applyProjectionMatrix(const osg::Matrix* matrix)
|
|
{
|
|
if (_projection!=matrix)
|
|
{
|
|
glMatrixMode( GL_PROJECTION );
|
|
if (matrix)
|
|
{
|
|
_projection=matrix;
|
|
glLoadMatrixf(matrix->ptr());
|
|
}
|
|
else
|
|
{
|
|
_projection=_identity;
|
|
glLoadIdentity();
|
|
}
|
|
glMatrixMode( GL_MODELVIEW );
|
|
}
|
|
}
|
|
|
|
const osg::Matrix& getProjectionMatrix() const
|
|
{
|
|
return *_projection;
|
|
}
|
|
|
|
inline void applyModelViewMatrix(const osg::Matrix* matrix)
|
|
{
|
|
if (_modelView!=matrix)
|
|
{
|
|
if (matrix)
|
|
{
|
|
_modelView=matrix;
|
|
glLoadMatrixf(matrix->ptr());
|
|
}
|
|
else
|
|
{
|
|
_modelView=_identity;
|
|
glLoadIdentity();
|
|
}
|
|
}
|
|
}
|
|
|
|
const osg::Matrix& getModelViewMatrix() const
|
|
{
|
|
return *_modelView;
|
|
}
|
|
|
|
|
|
Polytope getViewFrustum() const;
|
|
|
|
|
|
/** Apply stateset.*/
|
|
void apply(const StateSet* dstate);
|
|
|
|
/** Apply the state.*/
|
|
void apply();
|
|
|
|
|
|
/** Apply an OpenGL mode if required. */
|
|
inline const bool applyMode(const StateAttribute::GLMode mode,const bool enabled)
|
|
{
|
|
ModeStack& ms = _modeMap[mode];
|
|
ms.changed = true;
|
|
return applyMode(mode,enabled,ms);
|
|
}
|
|
|
|
inline const bool applyTextureMode(unsigned int unit, const StateAttribute::GLMode mode,const bool enabled)
|
|
{
|
|
if (unit>=_textureModeMapList.size()) _textureModeMapList.resize(unit);
|
|
ModeMap& modeMap = _textureModeMapList[unit];
|
|
|
|
ModeStack& ms = modeMap[mode];
|
|
ms.changed = true;
|
|
return applyMode(mode,enabled,ms);
|
|
}
|
|
|
|
/** Apply an attribute if required. */
|
|
inline const bool applyAttribute(const StateAttribute* attribute)
|
|
{
|
|
AttributeStack& as = _attributeMap[attribute->getType()];
|
|
as.changed = true;
|
|
return applyAttribute(attribute,as);
|
|
}
|
|
|
|
inline const bool applyTextureAttribute(unsigned int unit, const StateAttribute* attribute)
|
|
{
|
|
if (unit>=_textureAttributeMapList.size()) _textureAttributeMapList.resize(unit);
|
|
AttributeMap& attributeMap = _textureAttributeMapList[unit];
|
|
|
|
AttributeStack& as = attributeMap[attribute->getType()];
|
|
as.changed = true;
|
|
return applyAttribute(attribute,as);
|
|
}
|
|
|
|
/** Mode has been set externally, update state to reflect this setting.*/
|
|
void haveAppliedMode(const StateAttribute::GLMode mode,const StateAttribute::GLModeValue value);
|
|
|
|
/** Mode has been set externally, therefore dirty the associated mode in osg::State
|
|
* so it is applied on next call to osg::State::apply(..)*/
|
|
void haveAppliedMode(const StateAttribute::GLMode mode);
|
|
|
|
/** Attribute has been applied externally, update state to reflect this setting.*/
|
|
void haveAppliedAttribute(const StateAttribute* attribute);
|
|
|
|
/** Attribute has been applied externally,
|
|
* and therefore this attribute type has been dirtied
|
|
* and will need to be re-appplied on next osg::State.apply(..).
|
|
* note, if you have an osg::StateAttribute which you have applied externally
|
|
* then use the have_applied(attribute) method as this will the osg::State to
|
|
* track the current state more accuratly and enable lazy state updating such
|
|
* that only changed state will be applied.*/
|
|
void haveAppliedAttribute(const StateAttribute::Type type);
|
|
|
|
/** Get whether the current specified mode is enabled (true) or disabled (false).*/
|
|
const bool getLastAppliedMode(const StateAttribute::GLMode mode) const;
|
|
|
|
/** Get the current specified attribute, return NULL is one has not yet been applied.*/
|
|
const StateAttribute* getLastAppliedAttribute(const StateAttribute::Type type) const;
|
|
|
|
|
|
|
|
/** texture Mode has been set externally, update state to reflect this setting.*/
|
|
void haveAppliedTextureMode(unsigned int unit, const StateAttribute::GLMode mode,const StateAttribute::GLModeValue value);
|
|
|
|
/** texture Mode has been set externally, therefore dirty the associated mode in osg::State
|
|
* so it is applied on next call to osg::State::apply(..)*/
|
|
void haveAppliedTextureMode(unsigned int unit, const StateAttribute::GLMode mode);
|
|
|
|
/** texture Attribute has been applied externally, update state to reflect this setting.*/
|
|
void haveAppliedTextureAttribute(unsigned int unit, const StateAttribute* attribute);
|
|
|
|
/** texture Attribute has been applied externally,
|
|
* and therefore this attribute type has been dirtied
|
|
* and will need to be re-appplied on next osg::State.apply(..).
|
|
* note, if you have an osg::StateAttribute which you have applied externally
|
|
* then use the have_applied(attribute) method as this will the osg::State to
|
|
* track the current state more accuratly and enable lazy state updating such
|
|
* that only changed state will be applied.*/
|
|
void haveAppliedTextureAttribute(unsigned int unit, const StateAttribute::Type type);
|
|
|
|
/** Get whether the current specified texture mode is enabled (true) or disabled (false).*/
|
|
const bool getLastAppliedTextureMode(unsigned int unit, const StateAttribute::GLMode mode) const;
|
|
|
|
/** Get the current specified texture attribute, return NULL is one has not yet been applied.*/
|
|
const StateAttribute* getLastAppliedTextureAttribute(unsigned int unit, const StateAttribute::Type type) const;
|
|
|
|
|
|
|
|
/** wrapper around glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(..);
|
|
* note, only updates values that change.*/
|
|
inline void setVertexPointer( GLint size, GLenum type,
|
|
GLsizei stride, const GLvoid *ptr )
|
|
{
|
|
if (!_vertexArray._enabled)
|
|
{
|
|
_vertexArray._enabled = true;
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
}
|
|
if (_vertexArray._pointer!=ptr)
|
|
{
|
|
_vertexArray._pointer=ptr;
|
|
glVertexPointer( size, type, stride, ptr );
|
|
}
|
|
}
|
|
|
|
/** wrapper glDisableClientState(GL_VERTEX_ARRAY).
|
|
* note, only updates values that change.*/
|
|
inline void disableVertexPointer()
|
|
{
|
|
if (_vertexArray._enabled)
|
|
{
|
|
_vertexArray._enabled = false;
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
}
|
|
}
|
|
|
|
/** wrapper around glEnableClientState(GL_NORMAL_ARRAY);glNormalPointer(..);
|
|
* note, only updates values that change.*/
|
|
inline void setNormalPointer( GLenum type, GLsizei stride,
|
|
const GLvoid *ptr )
|
|
{
|
|
if (!_normalArray._enabled)
|
|
{
|
|
_normalArray._enabled = true;
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
}
|
|
if (_normalArray._pointer!=ptr)
|
|
{
|
|
_normalArray._pointer=ptr;
|
|
glNormalPointer( type, stride, ptr );
|
|
}
|
|
}
|
|
|
|
/** wrapper around glDisableClientState(GL_NORMAL_ARRAY);
|
|
* note, only updates values that change.*/
|
|
inline void disableNormalPointer()
|
|
{
|
|
if (_normalArray._enabled)
|
|
{
|
|
_normalArray._enabled = false;
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
}
|
|
}
|
|
|
|
/** wrapper around glEnableClientState(GL_COLOR_ARRAY);glColorPointer(..);
|
|
* note, only updates values that change.*/
|
|
inline void setColorPointer( GLint size, GLenum type,
|
|
GLsizei stride, const GLvoid *ptr )
|
|
{
|
|
if (!_colorArray._enabled)
|
|
{
|
|
_colorArray._enabled = true;
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
}
|
|
if (_colorArray._pointer!=ptr)
|
|
{
|
|
_colorArray._pointer=ptr;
|
|
glColorPointer( size, type, stride, ptr );
|
|
}
|
|
}
|
|
|
|
/** wrapper around glDisableClientState(GL_COLOR_ARRAY);
|
|
* note, only updates values that change.*/
|
|
inline void disableColorPointer()
|
|
{
|
|
if (_colorArray._enabled)
|
|
{
|
|
_colorArray._enabled = false;
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
}
|
|
}
|
|
|
|
/** wrapper around glEnableClientState(GL_INDEX_ARRAY);glIndexPointer(..);
|
|
* note, only updates values that change.*/
|
|
inline void setIndexPointer( GLenum type, GLsizei stride,
|
|
const GLvoid *ptr )
|
|
{
|
|
if (!_indexArray._enabled)
|
|
{
|
|
_indexArray._enabled = true;
|
|
glEnableClientState(GL_INDEX_ARRAY);
|
|
}
|
|
if (_indexArray._pointer!=ptr)
|
|
{
|
|
_indexArray._pointer=ptr;
|
|
glIndexPointer( type, stride, ptr );
|
|
}
|
|
}
|
|
|
|
/** wrapper around glDisableClientState(GL_INDEX_ARRAY);
|
|
* note, only updates values that change.*/
|
|
inline void disableIndexPointer()
|
|
{
|
|
//if (_indexArray._enabled)
|
|
{
|
|
_indexArray._enabled = false;
|
|
glDisableClientState(GL_INDEX_ARRAY);
|
|
}
|
|
}
|
|
|
|
/** wrapper around glEnableClientState(GL_TEXTURE_COORD_ARRAY);glTexCoordPointer(..);
|
|
* note, only updates values that change.*/
|
|
inline void setTexCoordPointer( unsigned int unit,
|
|
GLint size, GLenum type,
|
|
GLsizei stride, const GLvoid *ptr )
|
|
{
|
|
if (setClientActiveTextureUnit(unit))
|
|
{
|
|
if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
|
|
EnabledArrayPair& eap = _texCoordArrayList[unit];
|
|
|
|
//if (!eap._enabled)
|
|
{
|
|
eap._enabled = true;
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
if (eap._pointer!=ptr)
|
|
{
|
|
glTexCoordPointer( size, type, stride, ptr );
|
|
eap._pointer = ptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** wrapper around glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
* note, only updates values that change.*/
|
|
inline void disableTexCoordPointer( unsigned int unit )
|
|
{
|
|
if (setClientActiveTextureUnit(unit))
|
|
{
|
|
if ( unit > _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
|
|
EnabledArrayPair& eap = _texCoordArrayList[unit];
|
|
|
|
if (eap._enabled)
|
|
{
|
|
eap._enabled = false;
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/** set the current tex coord array texture unit, return true if selected, false if selection failed such as when multitexturing is not supported.
|
|
* note, only updates values that change.*/
|
|
inline bool setClientActiveTextureUnit( unsigned int unit )
|
|
{
|
|
return unit==0;
|
|
// will need to check for extensions etc.
|
|
// if (unit!=_currentClientActiveTextureUnit)
|
|
// {
|
|
// glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
|
|
// _currentClientActiveTextureUnit = unit;
|
|
// }
|
|
// return true;
|
|
}
|
|
|
|
|
|
/** set the current texture unit, return true if selected, false if selection failed such as when multitexturing is not supported.
|
|
* note, only updates values that change.*/
|
|
inline bool setActiveTextureUnit( unsigned int unit )
|
|
{
|
|
return unit==0;
|
|
//
|
|
// if (unit!=_currentActiveTextureUnit)
|
|
// {
|
|
// glActiveTextureARB(GL_TEXTURE0_ARB+unit);
|
|
// _currentActiveTextureUnit = unit;
|
|
// }
|
|
// return true;
|
|
}
|
|
|
|
|
|
|
|
/** Set the current OpenGL context uniqueID.
|
|
Note, it is the application developers responsibility to
|
|
set up unique ID for each OpenGL context. This value is
|
|
then used by osg::StateAttribure's and osg::Drawable's to
|
|
help manage OpenGL display list and texture binds appropriate
|
|
for each context.*/
|
|
inline void setContextID(unsigned int contextID) { _contextID=contextID; }
|
|
|
|
/** Get the current OpenGL context unique ID.*/
|
|
inline const unsigned int getContextID() const { return _contextID; }
|
|
|
|
|
|
/** Set the frame stamp for the current frame.*/
|
|
inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
|
|
|
|
/** Set the frame stamp for the current frame.*/
|
|
inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
|
|
|
|
|
|
/** Set the DisplaySettings. Note, nothing is applied, the visual settings are just used
|
|
* used in the State object to pass the current visual settings to Drawables
|
|
* during rendering. */
|
|
inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
|
|
|
|
/** Get the DisplaySettings */
|
|
inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
|
|
|
|
typedef std::pair<const StateAttribute*,StateAttribute::OverrideValue> AttributePair;
|
|
typedef std::vector<AttributePair> AttributeVec;
|
|
typedef std::vector<StateAttribute::GLModeValue> ValueVec;
|
|
|
|
private:
|
|
|
|
|
|
unsigned int _contextID;
|
|
ref_ptr<FrameStamp> _frameStamp;
|
|
|
|
ref_ptr<const Matrix> _identity;
|
|
ref_ptr<const Matrix> _projection;
|
|
ref_ptr<const Matrix> _modelView;
|
|
|
|
ref_ptr<DisplaySettings> _displaySettings;
|
|
|
|
|
|
struct ModeStack
|
|
{
|
|
ModeStack()
|
|
{
|
|
changed = false;
|
|
last_applied_value = false;
|
|
global_default_value = false;
|
|
}
|
|
|
|
bool changed;
|
|
bool last_applied_value;
|
|
bool global_default_value;
|
|
ValueVec valueVec;
|
|
};
|
|
|
|
|
|
|
|
struct AttributeStack
|
|
{
|
|
AttributeStack()
|
|
{
|
|
changed = false;
|
|
last_applied_attribute = 0L;
|
|
global_default_attribute = 0L;
|
|
}
|
|
|
|
/** apply an attribute if required, passing in attribute and appropriate attribute stack */
|
|
bool changed;
|
|
const StateAttribute* last_applied_attribute;
|
|
ref_ptr<StateAttribute> global_default_attribute;
|
|
AttributeVec attributeVec;
|
|
};
|
|
|
|
/** apply an OpenGL mode if required, passing in mode, enable flag and appropriate mode stack */
|
|
inline const bool applyMode(const StateAttribute::GLMode mode,const bool enabled,ModeStack& ms)
|
|
{
|
|
if (ms.last_applied_value != enabled)
|
|
{
|
|
ms.last_applied_value = enabled;
|
|
|
|
if (enabled) glEnable(mode);
|
|
else glDisable(mode);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/** apply an attribute if required, passing in attribute and appropriate attribute stack */
|
|
inline const bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
|
|
{
|
|
if (as.last_applied_attribute != attribute)
|
|
{
|
|
if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
|
|
|
|
as.last_applied_attribute = attribute;
|
|
attribute->apply(*this);
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
inline const bool applyGlobalDefaultAttribute(AttributeStack& as)
|
|
{
|
|
if (as.last_applied_attribute != as.global_default_attribute.get())
|
|
{
|
|
as.last_applied_attribute = as.global_default_attribute.get();
|
|
if (as.global_default_attribute.valid()) as.global_default_attribute->apply(*this);
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
typedef std::map<StateAttribute::GLMode,ModeStack> ModeMap;
|
|
typedef std::vector<ModeMap> TextureModeMapList;
|
|
|
|
typedef std::map<StateAttribute::Type,AttributeStack> AttributeMap;
|
|
typedef std::vector<AttributeMap> TextureAttributeMapList;
|
|
|
|
typedef std::vector<ref_ptr<const StateSet> > StateSetStack;
|
|
typedef std::vector<ref_ptr<const Matrix> > MatrixStack;
|
|
|
|
ModeMap _modeMap;
|
|
AttributeMap _attributeMap;
|
|
|
|
TextureModeMapList _textureModeMapList;
|
|
TextureAttributeMapList _textureAttributeMapList;
|
|
|
|
StateSetStack _drawStateStack;
|
|
|
|
struct EnabledArrayPair
|
|
{
|
|
EnabledArrayPair():_enabled(false),_pointer(0) {}
|
|
EnabledArrayPair(const EnabledArrayPair& eap):_enabled(eap._enabled),_pointer(eap._pointer) {}
|
|
EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _enabled=eap._enabled; _pointer=eap._pointer; return *this; }
|
|
|
|
bool _enabled;
|
|
const GLvoid* _pointer;
|
|
};
|
|
|
|
typedef std::vector<EnabledArrayPair> EnabledTexCoordArrayList;
|
|
|
|
EnabledArrayPair _vertexArray;
|
|
EnabledArrayPair _colorArray;
|
|
EnabledArrayPair _indexArray;
|
|
EnabledArrayPair _normalArray;
|
|
EnabledTexCoordArrayList _texCoordArrayList;
|
|
|
|
unsigned int _currentActiveTextureUnit;
|
|
unsigned int _currentClientActiveTextureUnit;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|