323 lines
12 KiB
C++
323 lines
12 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
|
|
#ifndef OSG_VertexArrayState
|
|
#define OSG_VertexArrayState 1
|
|
|
|
#include <osg/Referenced>
|
|
#include <osg/GLExtensions>
|
|
#include <osg/Array>
|
|
#include <osg/AttributeDispatchers>
|
|
|
|
namespace osg {
|
|
|
|
class OSG_EXPORT VertexArrayState : public osg::Referenced
|
|
{
|
|
public:
|
|
|
|
VertexArrayState(osg::State* state);
|
|
|
|
struct ArrayDispatch : public osg::Referenced
|
|
{
|
|
ArrayDispatch():
|
|
array(0),
|
|
modifiedCount(0xffffffff),
|
|
active(false) {}
|
|
|
|
virtual bool isVertexAttribDispatch() const { return false; }
|
|
|
|
virtual const char* className() const = 0; // { return "ArrayDispatch"; }
|
|
|
|
virtual void enable_and_dispatch(osg::State& /*state*/, const osg::Array* /*new_array*/) {} // = 0;
|
|
|
|
virtual void enable_and_dispatch(osg::State& /*state*/, const osg::Array* /*new_array*/, const osg::GLBufferObject* /*vbo*/) {} // = 0;
|
|
|
|
virtual void enable_and_dispatch(osg::State& /*state*/, GLint /*size*/, GLenum /*type*/, GLsizei /*stride*/, const GLvoid * /*ptr*/, GLboolean /*normalized*/) {} // = 0;
|
|
|
|
virtual void dispatch(osg::State& /*state*/, const osg::Array* /*new_array*/) {} // = 0;
|
|
|
|
virtual void dispatch(osg::State& /*state*/, const osg::Array* /*new_array*/, const osg::GLBufferObject* /*vbo*/) {} // = 0;
|
|
|
|
virtual void dispatch(osg::State& /*state*/, GLint /*size*/, GLenum /*type*/, GLsizei /*stride*/, const GLvoid * /*ptr*/, GLboolean /*normalized*/) {} // = 0;
|
|
|
|
virtual void disable(osg::State& /*state*/) {} // = 0;
|
|
|
|
const osg::Array* array;
|
|
unsigned int modifiedCount;
|
|
bool active;
|
|
};
|
|
|
|
typedef std::vector< ref_ptr<ArrayDispatch> > ArrayDispatchList;
|
|
|
|
void setCurrentVertexBufferObject(osg::GLBufferObject* vbo) { _currentVBO = vbo; }
|
|
GLBufferObject* getCurrentVertexBufferObject() { return _currentVBO; }
|
|
|
|
inline void bindVertexBufferObject(osg::GLBufferObject* vbo)
|
|
{
|
|
if (vbo->isDirty())
|
|
{
|
|
vbo->compileBuffer();
|
|
_currentVBO = vbo;
|
|
}
|
|
else if (vbo != _currentVBO)
|
|
{
|
|
vbo->bindBuffer();
|
|
_currentVBO = vbo;
|
|
}
|
|
}
|
|
|
|
inline void unbindVertexBufferObject()
|
|
{
|
|
if (!_currentVBO) return;
|
|
_ext->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
|
|
_currentVBO = 0;
|
|
}
|
|
|
|
|
|
void setCurrentElementBufferObject(osg::GLBufferObject* ebo) { _currentEBO = ebo; }
|
|
GLBufferObject* getCurrentElementBufferObject() { return _currentEBO; }
|
|
|
|
inline void bindElementBufferObject(osg::GLBufferObject* ebo)
|
|
{
|
|
if (ebo->isDirty())
|
|
{
|
|
ebo->compileBuffer();
|
|
_currentEBO = ebo;
|
|
}
|
|
else if (ebo != _currentEBO)
|
|
{
|
|
ebo->bindBuffer();
|
|
_currentEBO = ebo;
|
|
}
|
|
}
|
|
|
|
inline void unbindElementBufferObject()
|
|
{
|
|
if (!_currentEBO) return;
|
|
_ext->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
|
|
_currentEBO = 0;
|
|
}
|
|
|
|
void resetBufferObjectPointers() { _currentVBO = 0; _currentEBO = 0; }
|
|
|
|
bool correctArrayDispatchAssigned(const ArrayDispatch* ad);
|
|
|
|
void assignAllDispatchers();
|
|
|
|
void assignVertexArrayDispatcher();
|
|
void assignNormalArrayDispatcher();
|
|
void assignColorArrayDispatcher();
|
|
void assignSecondaryColorArrayDispatcher();
|
|
void assignFogCoordArrayDispatcher();
|
|
void assignTexCoordArrayDispatcher(unsigned int numUnits);
|
|
void assignVertexAttribArrayDispatcher(unsigned int numUnits);
|
|
|
|
inline void setVertexBufferObjectSupported(bool flag) { _isVertexBufferObjectSupported = flag; }
|
|
inline bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupported; }
|
|
|
|
void setArray(ArrayDispatch* vad, osg::State& state, const osg::Array* new_array);
|
|
void setArray(ArrayDispatch* vad, osg::State& state, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized);
|
|
|
|
inline void disable(ArrayDispatch* vad, osg::State& state) { vad->disable(state); vad->array=0; vad->modifiedCount=0xffffffff; vad->active=false; }
|
|
|
|
void setInterleavedArrays( osg::State& state, GLenum format, GLsizei stride, const GLvoid* pointer);
|
|
|
|
inline void setVertexArray(osg::State& state, const osg::Array* array) { setArray(_vertexArray.get(), state, array); }
|
|
inline void setVertexArray(osg::State& state, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized=GL_FALSE) { setArray(_vertexArray.get(), state, size, type, stride, ptr, normalized); }
|
|
inline void disableVertexArray(osg::State& state) { disable(_vertexArray.get(), state); }
|
|
|
|
inline void setNormalArray(osg::State& state, const osg::Array* array) { setArray(_normalArray.get(), state, array); }
|
|
inline void setNormalArray(osg::State& state, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized=GL_FALSE ) { setArray(_normalArray.get(), state, 3, type, stride, ptr, normalized); }
|
|
inline void disableNormalArray(osg::State& state) { disable(_normalArray.get(), state); }
|
|
|
|
inline void setColorArray(osg::State& state, const osg::Array* array) { setArray(_colorArray.get(), state, array); }
|
|
inline void setColorArray(osg::State& state, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized=GL_TRUE ) { setArray(_colorArray.get(), state, size, type, stride, ptr, normalized); }
|
|
inline void disableColorArray(osg::State& state) { disable(_colorArray.get(), state); }
|
|
|
|
inline void setSecondaryColorArray(osg::State& state, const osg::Array* array) { setArray(_secondaryColorArray.get(), state, array); }
|
|
inline void disableSecondaryColorArray(osg::State& state) { disable(_secondaryColorArray.get(), state); }
|
|
|
|
inline void setFogCoordArray(osg::State& state, const osg::Array* array) { setArray(_fogCoordArray.get(), state, array); }
|
|
inline void disableFogCoordArray(osg::State& state) { disable(_fogCoordArray.get(), state); }
|
|
|
|
inline void setTexCoordArray(osg::State& state, unsigned int unit, const osg::Array* array) { setArray(_texCoordArrays[unit].get(), state, array); }
|
|
inline void setTexCoordArray(osg::State& state, unsigned int unit, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized=GL_FALSE ) { setArray(_texCoordArrays[unit].get(), state, size, type, stride, ptr, normalized); }
|
|
inline void disableTexCoordArray(osg::State& state, unsigned int unit) { disable(_texCoordArrays[unit].get(),state); }
|
|
inline void disableTexCoordArrayAboveAndIncluding(osg::State& state, unsigned int index);
|
|
|
|
inline void setVertexAttribArray(osg::State& state, unsigned int unit, const osg::Array* array) { setArray(_vertexAttribArrays[unit].get(), state, array); }
|
|
inline void disableVertexAttribArray(osg::State& state, unsigned int unit) { disable(_vertexAttribArrays[unit].get(), state); }
|
|
inline void disableVertexAttribArrayAboveAndIncluding(osg::State& state, unsigned int index);
|
|
|
|
/** Mark all the vertex attributes as being disabled but leave the disabling till a later call to applyDisablingOfVertexAttributes.*/
|
|
inline void lazyDisablingOfVertexAttributes();
|
|
|
|
/** Disable all the vertex attributes that have been marked as to be disabled.*/
|
|
inline void applyDisablingOfVertexAttributes(osg::State& state);
|
|
|
|
// Verex Array Object methods.
|
|
void generateVertexArrayObject();
|
|
|
|
void deleteVertexArrayObject();
|
|
|
|
GLuint getVertexArrayObject() const { return _vertexArrayObject; }
|
|
|
|
|
|
void setRequiresSetArrays(bool flag) { _requiresSetArrays = flag; }
|
|
bool getRequiresSetArrays() const { return _requiresSetArrays; }
|
|
|
|
void dirty();
|
|
|
|
void release();
|
|
|
|
public:
|
|
|
|
virtual ~VertexArrayState();
|
|
|
|
// osg::GLBufferObject* getGLBufferObject(osg::Array* array);
|
|
|
|
osg::State* _state;
|
|
osg::ref_ptr<ObserverSet> _stateObserverSet;
|
|
osg::ref_ptr<osg::GLExtensions> _ext;
|
|
|
|
bool _isVertexBufferObjectSupported;
|
|
|
|
GLuint _vertexArrayObject;
|
|
|
|
|
|
osg::ref_ptr<ArrayDispatch> _vertexArray;
|
|
osg::ref_ptr<ArrayDispatch> _normalArray;
|
|
osg::ref_ptr<ArrayDispatch> _colorArray;
|
|
osg::ref_ptr<ArrayDispatch> _secondaryColorArray;
|
|
osg::ref_ptr<ArrayDispatch> _fogCoordArray;
|
|
ArrayDispatchList _texCoordArrays;
|
|
ArrayDispatchList _vertexAttribArrays;
|
|
|
|
typedef std::vector<ArrayDispatch*> ActiveDispatchers;
|
|
ActiveDispatchers _activeDispatchers;
|
|
ActiveDispatchers _previous_activeDispatchers;
|
|
|
|
GLBufferObject* _currentVBO;
|
|
GLBufferObject* _currentEBO;
|
|
|
|
bool _requiresSetArrays;
|
|
};
|
|
|
|
|
|
|
|
class OSG_EXPORT VertexArrayStateList
|
|
{
|
|
public:
|
|
|
|
VertexArrayStateList();
|
|
|
|
VertexArrayStateList& operator = (const VertexArrayStateList& rhs);
|
|
|
|
inline void clear() { _array.clear(); }
|
|
|
|
inline bool empty() const { return _array.empty(); }
|
|
|
|
inline unsigned int size() const { return _array.size(); }
|
|
|
|
inline void resize(unsigned int newSize) { _array.resize(newSize); }
|
|
|
|
inline ref_ptr<VertexArrayState>& operator[] (unsigned int pos)
|
|
{
|
|
// automatically resize array.
|
|
if (_array.size()<=pos)
|
|
_array.resize(pos+1,0);
|
|
|
|
return _array[pos];
|
|
}
|
|
|
|
inline const ref_ptr<VertexArrayState>& operator[] (unsigned int pos) const
|
|
{
|
|
// automatically resize array.
|
|
if (_array.size()<=pos)
|
|
_array.resize(pos+1,0);
|
|
|
|
return _array[pos];
|
|
}
|
|
|
|
void assignAllDispatchers();
|
|
|
|
void assignVertexArrayDispatcher();
|
|
void assignNormalArrayDispatcher();
|
|
void assignColorArrayDispatcher();
|
|
void assignSecondaryColorArrayDispatcher();
|
|
void assignFogCoordArrayDispatcher();
|
|
void assignTexCoordArrayDispatcher(unsigned int numUnits);
|
|
void assignVertexAttribArrayDispatcher(unsigned int numUnits);
|
|
|
|
protected:
|
|
|
|
typedef std::vector< osg::ref_ptr<VertexArrayState> > Array;
|
|
mutable Array _array;
|
|
};
|
|
|
|
|
|
|
|
inline void VertexArrayState::lazyDisablingOfVertexAttributes()
|
|
{
|
|
_activeDispatchers.swap(_previous_activeDispatchers);
|
|
_activeDispatchers.clear();
|
|
|
|
for(ActiveDispatchers::iterator itr = _previous_activeDispatchers.begin();
|
|
itr != _previous_activeDispatchers.end();
|
|
++itr)
|
|
{
|
|
ArrayDispatch* ad = (*itr);
|
|
// ad->array = 0;
|
|
ad->active = false;
|
|
}
|
|
}
|
|
|
|
inline void VertexArrayState::applyDisablingOfVertexAttributes(osg::State& state)
|
|
{
|
|
for(ActiveDispatchers::iterator itr = _previous_activeDispatchers.begin();
|
|
itr != _previous_activeDispatchers.end();
|
|
++itr)
|
|
{
|
|
ArrayDispatch* ad = (*itr);
|
|
if (!ad->active)
|
|
{
|
|
ad->disable(state);
|
|
ad->array = 0;
|
|
ad->modifiedCount = 0xffffffff;
|
|
}
|
|
}
|
|
_previous_activeDispatchers.clear();
|
|
}
|
|
|
|
inline void VertexArrayState::disableTexCoordArrayAboveAndIncluding(osg::State& state, unsigned int index)
|
|
{
|
|
for(unsigned int i=index; i<_texCoordArrays.size(); ++i)
|
|
{
|
|
disable(_texCoordArrays[i].get(), state);
|
|
}
|
|
}
|
|
|
|
inline void VertexArrayState::disableVertexAttribArrayAboveAndIncluding(osg::State& state, unsigned int index)
|
|
{
|
|
for(unsigned int i=index; i<_vertexAttribArrays.size(); ++i)
|
|
{
|
|
disable(_vertexAttribArrays[i].get(), state);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|