#include #include #include #include #include using namespace osg; State::State() { _contextID = 0; _identity = new osg::RefMatrix(); // default RefMatrix constructs to identity. _projection = _identity; _modelView = _identity; _currentActiveTextureUnit=0; _currentClientActiveTextureUnit=0; _isSecondColorSupportResolved = false; _isSecondColorSupported = false; _isFogCoordSupportResolved = false; _isFogCoordSupported = false; } State::~State() { } void State::reset() { /* for(ModeMap::iterator mitr=_modeMap.begin(); mitr!=_modeMap.end(); ++mitr) { ModeStack& ms = mitr->second; ms.valueVec.clear(); ms.last_applied_value = !ms.global_default_value; ms.changed = true; } */ _modeMap.clear(); _modeMap[GL_DEPTH_TEST].global_default_value = true; _modeMap[GL_DEPTH_TEST].changed = true; // go through all active StateAttribute's, setting to change to force update, // the idea is to leave only the global defaults left. for(AttributeMap::iterator aitr=_attributeMap.begin(); aitr!=_attributeMap.end(); ++aitr) { AttributeStack& as = aitr->second; as.attributeVec.clear(); as.last_applied_attribute = NULL; as.changed = true; } // we can do a straight clear, we arn't intrested in GL_DEPTH_TEST defaults in texture modes. for(TextureModeMapList::iterator tmmItr=_textureModeMapList.begin(); tmmItr!=_textureModeMapList.end(); ++tmmItr) { tmmItr->clear(); } // empty all the texture attributes as per normal attributes, leaving only the global defaults left. for(TextureAttributeMapList::iterator tamItr=_textureAttributeMapList.begin(); tamItr!=_textureAttributeMapList.end(); ++tamItr) { AttributeMap& attributeMap = *tamItr; // go through all active StateAttribute's, setting to change to force update. for(AttributeMap::iterator aitr=attributeMap.begin(); aitr!=attributeMap.end(); ++aitr) { AttributeStack& as = aitr->second; as.attributeVec.clear(); as.last_applied_attribute = NULL; as.changed = true; } } _drawStateStack.clear(); _modelView = _identity; _projection = _identity; dirtyAllVertexArrays(); setActiveTextureUnit(0); } void State::pushStateSet(const StateSet* dstate) { _drawStateStack.push_back(dstate); if (dstate) { pushModeList(_modeMap,dstate->getModeList()); // iterator through texture modes. unsigned int unit; const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList(); for(unit=0;unitgetAttributeList()); // iterator through texture attributes. const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList(); for(unit=0;unitgetModeList()); // iterator through texture modes. unsigned int unit; const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList(); for(unit=0;unitgetAttributeList()); // iterator through texture attributes. const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList(); for(unit=0;unitfirst const ModeStack& ms = mitr->second; if (!ms.valueVec.empty()) { stateset.setMode(mitr->first,ms.valueVec.back()); } } for(AttributeMap::const_iterator aitr=_attributeMap.begin(); aitr!=_attributeMap.end(); ++aitr) { const AttributeStack& as = aitr->second; if (!as.attributeVec.empty()) { stateset.setAttribute(const_cast(as.attributeVec.back().first)); } } } // visual studio 6.0 doesn't appear to define std::max?!? So do our own here.. template T mymax(const T& a,const T& b) { return (((a) > (b)) ? (a) : (b)); } void State::apply(const StateSet* dstate) { // equivilant to: //pushStateSet(dstate); //apply(); //popStateSet(); if (dstate) { applyModeList(_modeMap,dstate->getModeList()); applyAttributeList(_attributeMap,dstate->getAttributeList()); const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList(); const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList(); unsigned int unit; unsigned int unitMax = mymax(static_cast(ds_textureModeList.size()),static_cast(ds_textureAttributeList.size())); unitMax = mymax(static_cast(unitMax),static_cast(_textureModeMapList.size())); unitMax = mymax(static_cast(unitMax),static_cast(_textureAttributeMapList.size())); for(unit=0;unit=_textureModeMapList.size()) return false; return getLastAppliedMode(_textureModeMapList[unit],mode); } const StateAttribute* State::getLastAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type) const { if (unit>=_textureAttributeMapList.size()) return false; return getLastAppliedAttribute(_textureAttributeMapList[unit],type); } void State::haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value) { ModeStack& ms = modeMap[mode]; ms.last_applied_value = value & StateAttribute::ON; // will need to disable this mode on next apply so set it to changed. ms.changed = true; } /** mode has been set externally, update state to reflect this setting.*/ void State::haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode) { ModeStack& ms = modeMap[mode]; // don't know what last applied value is can't apply it. // assume that it has changed by toggle the value of last_applied_value. ms.last_applied_value = !ms.last_applied_value; // will need to disable this mode on next apply so set it to changed. ms.changed = true; } /** attribute has been applied externally, update state to reflect this setting.*/ void State::haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute) { if (attribute) { AttributeStack& as = attributeMap[attribute->getType()]; as.last_applied_attribute = attribute; // will need to update this attribute on next apply so set it to changed. as.changed = true; } } void State::haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type) { AttributeMap::iterator itr = attributeMap.find(type); if (itr!=attributeMap.end()) { AttributeStack& as = itr->second; as.last_applied_attribute = 0L; // will need to update this attribute on next apply so set it to changed. as.changed = true; } } bool State::getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const { ModeMap::const_iterator itr = modeMap.find(mode); if (itr!=modeMap.end()) { const ModeStack& ms = itr->second; return ms.last_applied_value; } else { return false; } } const StateAttribute* State::getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type) const { AttributeMap::const_iterator itr = attributeMap.find(type); if (itr!=attributeMap.end()) { const AttributeStack& as = itr->second; return as.last_applied_attribute; } else { return NULL; } } Polytope State::getViewFrustum() const { Polytope cv; cv.setToUnitFrustum(); cv.transformProvidingInverse((*_modelView)*(*_projection)); return cv; } void State::disableAllVertexArrays() { disableVertexPointer(); disableTexCoordPointersAboveAndIncluding(0); disableColorPointer(); disableFogCoordPointer(); disableIndexPointer(); disableNormalPointer(); disableSecondaryColorPointer(); } void State::dirtyAllVertexArrays() { dirtyVertexPointer(); dirtyTexCoordPointersAboveAndIncluding(0); dirtyColorPointer(); dirtyFogCoordPointer(); dirtyIndexPointer(); dirtyNormalPointer(); dirtySecondaryColorPointer(); } void State::setInterleavedArrays( GLenum format, GLsizei stride, void* pointer) { glInterleavedArrays( format, stride, pointer); // the crude way, assume that all arrays have been effected so dirty them and // disable them... dirtyAllVertexArrays(); disableAllVertexArrays(); } typedef void (APIENTRY * ActiveTextureProc) (GLenum texture); bool State::setClientActiveTextureUnit( unsigned int unit ) { if (unit!=_currentClientActiveTextureUnit) { static ActiveTextureProc s_glClientActiveTexture = (ActiveTextureProc) osg::getGLExtensionFuncPtr("glClientActiveTexture","glClientActiveTextureARB"); if (s_glClientActiveTexture) { s_glClientActiveTexture(GL_TEXTURE0+unit); _currentClientActiveTextureUnit = unit; } else { return unit==0; } } 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.*/ bool State::setActiveTextureUnit( unsigned int unit ) { if (unit!=_currentActiveTextureUnit) { static ActiveTextureProc s_glActiveTexture = (ActiveTextureProc) osg::getGLExtensionFuncPtr("glActiveTexture","glActiveTextureARB"); if (s_glActiveTexture) { s_glActiveTexture(GL_TEXTURE0+unit); _currentActiveTextureUnit = unit; } else { return unit==0; } } return true; } typedef void (APIENTRY * FogCoordPointerProc) (GLenum type, GLsizei stride, const GLvoid *pointer); void State::setFogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr) { static FogCoordPointerProc s_glFogCoordPointer = (FogCoordPointerProc) osg::getGLExtensionFuncPtr("glFogCoordPointer","glFogCoordPointerEXT"); if (s_glFogCoordPointer) { if (!_fogArray._enabled || _fogArray._dirty) { _fogArray._enabled = true; glEnableClientState(GL_FOG_COORDINATE_ARRAY); } if (_fogArray._pointer!=ptr || _fogArray._dirty) { _fogArray._pointer=ptr; s_glFogCoordPointer( type, stride, ptr ); } _fogArray._dirty = false; } } typedef void (APIENTRY * SecondaryColorPointerProc) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); void State::setSecondaryColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr ) { static SecondaryColorPointerProc s_glSecondaryColorPointer = (SecondaryColorPointerProc) osg::getGLExtensionFuncPtr("glSecondaryColorPointer","glSecondaryColorPointerEXT"); if (s_glSecondaryColorPointer) { if (!_secondaryColorArray._enabled || _secondaryColorArray._dirty) { _secondaryColorArray._enabled = true; glEnableClientState(GL_SECONDARY_COLOR_ARRAY); } if (_secondaryColorArray._pointer!=ptr || _secondaryColorArray._dirty) { _secondaryColorArray._pointer=ptr; s_glSecondaryColorPointer( size, type, stride, ptr ); } _secondaryColorArray._dirty = false; } } bool State::computeSecondaryColorSupported() const { _isSecondColorSupportResolved = true; _isSecondColorSupported = osg::isGLExtensionSupported("GL_EXT_secondary_color");; return _isSecondColorSupported; } bool State::computeFogCoordSupported() const { _isFogCoordSupportResolved = true; _isFogCoordSupported = osg::isGLExtensionSupported("GL_EXT_fog_coord"); return _isFogCoordSupported; }