2003-01-22 00:45:36 +08:00
|
|
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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.
|
|
|
|
*/
|
2001-09-20 05:19:47 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
|
|
|
|
|
|
|
#include <osg/Drawable>
|
|
|
|
#include <osg/State>
|
|
|
|
#include <osg/Notify>
|
2002-02-09 06:55:21 +08:00
|
|
|
#include <osg/Node>
|
2003-06-30 05:41:57 +08:00
|
|
|
#include <osg/GLExtensions>
|
2002-02-09 06:55:21 +08:00
|
|
|
|
|
|
|
#include <algorithm>
|
2002-11-19 18:56:59 +08:00
|
|
|
#include <map>
|
|
|
|
#include <set>
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
using namespace osg;
|
|
|
|
|
2002-11-19 18:56:59 +08:00
|
|
|
// static cache of deleted display lists which can only
|
|
|
|
// by completely deleted once the appropriate OpenGL context
|
|
|
|
// is set. Used osg::Drawable::deleteDisplayList(..) and flushDeletedDisplayLists(..) below.
|
2003-01-23 07:34:18 +08:00
|
|
|
typedef std::vector<GLuint> DisplayListVector;
|
|
|
|
typedef std::map<GLuint,DisplayListVector> DeletedDisplayListCache;
|
2002-11-19 18:56:59 +08:00
|
|
|
static DeletedDisplayListCache s_deletedDisplayListCache;
|
2003-06-30 05:41:57 +08:00
|
|
|
static DeletedDisplayListCache s_deletedVertexBufferObjectCache;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2003-02-14 19:41:52 +08:00
|
|
|
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj)
|
2003-01-23 07:34:18 +08:00
|
|
|
{
|
|
|
|
if (globj!=0)
|
|
|
|
{
|
|
|
|
// insert the globj into the cache for the appropriate context.
|
|
|
|
s_deletedDisplayListCache[contextID].push_back(globj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** flush all the cached display list which need to be deleted
|
|
|
|
* in the OpenGL context related to contextID.*/
|
2003-02-14 19:41:52 +08:00
|
|
|
void Drawable::flushDeletedDisplayLists(unsigned int contextID)
|
2003-01-23 07:34:18 +08:00
|
|
|
{
|
|
|
|
DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
|
|
|
|
if (citr!=s_deletedDisplayListCache.end())
|
|
|
|
{
|
|
|
|
DisplayListVector displayListSet;
|
2003-06-30 05:41:57 +08:00
|
|
|
displayListSet.reserve(1000);
|
2003-01-23 07:34:18 +08:00
|
|
|
|
|
|
|
// this swap will transfer the content of and empty citr->second
|
|
|
|
// in one quick pointer change.
|
|
|
|
displayListSet.swap(citr->second);
|
|
|
|
|
2003-01-23 16:37:15 +08:00
|
|
|
for(DisplayListVector::iterator gitr=displayListSet.begin();
|
2003-01-23 07:34:18 +08:00
|
|
|
gitr!=displayListSet.end();
|
|
|
|
++gitr)
|
|
|
|
{
|
|
|
|
glDeleteLists(*gitr,1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-30 05:41:57 +08:00
|
|
|
void Drawable::deleteVertexBufferObject(unsigned int contextID,GLuint globj)
|
|
|
|
{
|
|
|
|
if (globj!=0)
|
|
|
|
{
|
|
|
|
// insert the globj into the cache for the appropriate context.
|
|
|
|
s_deletedVertexBufferObjectCache[contextID].push_back(globj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** flush all the cached display list which need to be deleted
|
|
|
|
* in the OpenGL context related to contextID.*/
|
|
|
|
void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID)
|
|
|
|
{
|
|
|
|
DeletedDisplayListCache::iterator citr = s_deletedVertexBufferObjectCache.find(contextID);
|
|
|
|
if (citr!=s_deletedVertexBufferObjectCache.end())
|
|
|
|
{
|
|
|
|
const Extensions* extensions = getExtensions(contextID,true);
|
|
|
|
|
|
|
|
DisplayListVector displayListSet;
|
|
|
|
displayListSet.reserve(1000);
|
|
|
|
|
|
|
|
// this swap will transfer the content of and empty citr->second
|
|
|
|
// in one quick pointer change.
|
|
|
|
displayListSet.swap(citr->second);
|
|
|
|
|
|
|
|
for(DisplayListVector::iterator gitr=displayListSet.begin();
|
|
|
|
gitr!=displayListSet.end();
|
|
|
|
++gitr)
|
|
|
|
{
|
|
|
|
extensions->glDeleteBuffers(1,&(*gitr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-23 07:34:18 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
Drawable::Drawable()
|
|
|
|
{
|
|
|
|
_bbox_computed = false;
|
|
|
|
|
|
|
|
// Note, if your are defining a subclass from drawable which is
|
|
|
|
// dynamically updated then you should set both the following to
|
|
|
|
// to false in your constructor. This will prevent any display
|
|
|
|
// lists from being automatically created and safeguard the
|
|
|
|
// dynamic updating of data.
|
|
|
|
_supportsDisplayList = true;
|
|
|
|
_useDisplayList = true;
|
2003-06-30 05:41:57 +08:00
|
|
|
|
|
|
|
_supportsVertexBufferObjects = false;
|
|
|
|
_useVertexBufferObjects = true;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
2002-02-07 09:07:11 +08:00
|
|
|
Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop):
|
|
|
|
Object(drawable,copyop),
|
2002-02-09 06:55:21 +08:00
|
|
|
_parents(), // leave empty as parentList is managed by Geode
|
2002-09-02 20:31:35 +08:00
|
|
|
_stateset(copyop(drawable._stateset.get())),
|
2002-10-30 21:27:15 +08:00
|
|
|
_bbox(drawable._bbox),
|
|
|
|
_bbox_computed(drawable._bbox_computed),
|
|
|
|
_shape(copyop(drawable._shape.get())),
|
2002-02-07 09:07:11 +08:00
|
|
|
_supportsDisplayList(drawable._supportsDisplayList),
|
|
|
|
_useDisplayList(drawable._useDisplayList),
|
2003-06-30 05:41:57 +08:00
|
|
|
_supportsVertexBufferObjects(drawable._supportsVertexBufferObjects),
|
|
|
|
_useVertexBufferObjects(drawable._useVertexBufferObjects),
|
2002-03-14 06:44:22 +08:00
|
|
|
_drawCallback(drawable._drawCallback),
|
|
|
|
_cullCallback(drawable._cullCallback)
|
2002-11-19 18:56:59 +08:00
|
|
|
{
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
Drawable::~Drawable()
|
|
|
|
{
|
|
|
|
dirtyDisplayList();
|
|
|
|
}
|
|
|
|
|
2002-02-09 06:55:21 +08:00
|
|
|
void Drawable::addParent(osg::Node* node)
|
|
|
|
{
|
|
|
|
_parents.push_back(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::removeParent(osg::Node* node)
|
|
|
|
{
|
|
|
|
ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),node);
|
|
|
|
if (pitr!=_parents.end()) _parents.erase(pitr);
|
|
|
|
}
|
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
osg::StateSet* Drawable::getOrCreateStateSet()
|
|
|
|
{
|
2002-12-16 21:40:58 +08:00
|
|
|
if (!_stateset) _stateset = new StateSet;
|
2002-09-02 20:31:35 +08:00
|
|
|
return _stateset.get();
|
|
|
|
}
|
|
|
|
|
2002-02-09 06:55:21 +08:00
|
|
|
void Drawable::dirtyBound()
|
|
|
|
{
|
|
|
|
if (_bbox_computed)
|
|
|
|
{
|
|
|
|
_bbox_computed = false;
|
|
|
|
|
|
|
|
// dirty parent bounding sphere's to ensure that all are valid.
|
|
|
|
for(ParentList::iterator itr=_parents.begin();
|
|
|
|
itr!=_parents.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
(*itr)->dirtyBound();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2003-01-21 04:40:06 +08:00
|
|
|
void Drawable::compile(State& state) const
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
if (!_useDisplayList) return;
|
|
|
|
|
|
|
|
// get the contextID (user defined ID of 0 upwards) for the
|
|
|
|
// current OpenGL context.
|
2003-02-14 19:41:52 +08:00
|
|
|
unsigned int contextID = state.getContextID();
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
// get the globj for the current contextID.
|
2003-02-15 00:52:47 +08:00
|
|
|
GLuint& globj = _globjList[contextID];
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
// call the globj if already set otherwise comple and execute.
|
|
|
|
if( globj != 0 )
|
|
|
|
{
|
|
|
|
glDeleteLists( globj, 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
if (_stateset.valid())
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-09-02 20:31:35 +08:00
|
|
|
_stateset->compile(state);
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
globj = glGenLists( 1 );
|
|
|
|
glNewList( globj, GL_COMPILE );
|
2002-05-29 07:43:22 +08:00
|
|
|
|
|
|
|
if (_drawCallback.valid())
|
2002-11-06 23:43:11 +08:00
|
|
|
_drawCallback->drawImplementation(state,this);
|
2002-05-29 07:43:22 +08:00
|
|
|
else
|
2002-11-06 23:43:11 +08:00
|
|
|
drawImplementation(state);
|
2002-05-29 07:43:22 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
glEndList();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
void Drawable::setSupportsDisplayList(bool flag)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
// if value unchanged simply return.
|
|
|
|
if (_supportsDisplayList==flag) return;
|
|
|
|
|
|
|
|
// if previously set to true then need to check about display lists.
|
|
|
|
if (_supportsDisplayList)
|
|
|
|
{
|
|
|
|
if (_useDisplayList)
|
|
|
|
{
|
|
|
|
// used to support display lists and display lists switched
|
|
|
|
// on so now delete them and turn useDisplayList off.
|
|
|
|
dirtyDisplayList();
|
|
|
|
_useDisplayList = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// set with new value.
|
|
|
|
_supportsDisplayList=flag;
|
|
|
|
}
|
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
void Drawable::setUseDisplayList(bool flag)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
// if value unchanged simply return.
|
|
|
|
if (_useDisplayList==flag) return;
|
|
|
|
|
|
|
|
// if was previously set to true, remove display list.
|
|
|
|
if (_useDisplayList)
|
|
|
|
{
|
|
|
|
dirtyDisplayList();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_supportsDisplayList)
|
|
|
|
{
|
|
|
|
|
|
|
|
// set with new value.
|
|
|
|
_useDisplayList = flag;
|
|
|
|
|
|
|
|
}
|
|
|
|
else // does not support display lists.
|
|
|
|
{
|
|
|
|
if (flag)
|
|
|
|
{
|
2001-12-15 07:18:28 +08:00
|
|
|
notify(WARN)<<"Warning: attempt to setUseDisplayList(true) on a drawable with does not support display lists."<<std::endl;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// set with new value.
|
|
|
|
_useDisplayList = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-06 03:49:06 +08:00
|
|
|
void Drawable::setUseVertexBufferObjects(bool flag)
|
|
|
|
{
|
|
|
|
// if value unchanged simply return.
|
|
|
|
if (_useVertexBufferObjects==flag) return;
|
|
|
|
|
|
|
|
// if was previously set to true, remove display list.
|
|
|
|
if (_useVertexBufferObjects)
|
|
|
|
{
|
|
|
|
dirtyDisplayList();
|
|
|
|
}
|
|
|
|
|
|
|
|
_useVertexBufferObjects = flag;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
void Drawable::dirtyDisplayList()
|
|
|
|
{
|
2003-07-06 03:08:30 +08:00
|
|
|
unsigned int i;
|
|
|
|
for(i=0;i<_globjList.size();++i)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
if (_globjList[i] != 0)
|
|
|
|
{
|
|
|
|
Drawable::deleteDisplayList(i,_globjList[i]);
|
|
|
|
_globjList[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
2003-06-30 05:41:57 +08:00
|
|
|
|
2003-07-06 03:08:30 +08:00
|
|
|
for(i=0;i<_vboList.size();++i)
|
2003-06-30 05:41:57 +08:00
|
|
|
{
|
|
|
|
if (_vboList[i] != 0)
|
|
|
|
{
|
|
|
|
Drawable::deleteVertexBufferObject(i,_vboList[i]);
|
|
|
|
_vboList[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
2002-07-10 23:35:47 +08:00
|
|
|
|
2002-12-19 23:55:40 +08:00
|
|
|
void Drawable::setUpdateCallback(UpdateCallback* ac)
|
2002-07-10 23:35:47 +08:00
|
|
|
{
|
2002-12-19 23:55:40 +08:00
|
|
|
if (_updateCallback==ac) return;
|
2002-07-10 23:35:47 +08:00
|
|
|
|
|
|
|
int delta = 0;
|
2002-12-19 23:55:40 +08:00
|
|
|
if (_updateCallback.valid()) --delta;
|
2002-07-10 23:35:47 +08:00
|
|
|
if (ac) ++delta;
|
2002-07-11 04:30:57 +08:00
|
|
|
|
2002-12-19 23:55:40 +08:00
|
|
|
_updateCallback = ac;
|
2002-07-10 23:35:47 +08:00
|
|
|
|
|
|
|
if (delta!=0)
|
|
|
|
{
|
|
|
|
for(ParentList::iterator itr=_parents.begin();
|
|
|
|
itr!=_parents.end();
|
|
|
|
++itr)
|
|
|
|
{
|
2002-12-19 23:55:40 +08:00
|
|
|
(*itr)->setNumChildrenRequiringUpdateTraversal((*itr)->getNumChildrenRequiringUpdateTraversal()+delta);
|
2002-07-10 23:35:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-07-19 06:35:54 +08:00
|
|
|
|
|
|
|
struct ComputeBound : public Drawable::PrimitiveFunctor
|
|
|
|
{
|
|
|
|
ComputeBound():_vertices(0) {}
|
|
|
|
|
2003-06-30 05:41:57 +08:00
|
|
|
virtual void setVertexArray(unsigned int,const Vec2*)
|
2003-06-24 23:40:09 +08:00
|
|
|
{
|
|
|
|
notify(WARN)<<"ComputeBound does not support Vec2* vertex arrays"<<std::endl;
|
|
|
|
}
|
|
|
|
|
2002-11-06 18:24:33 +08:00
|
|
|
virtual void setVertexArray(unsigned int,const Vec3* vertices) { _vertices = vertices; }
|
2002-07-19 06:35:54 +08:00
|
|
|
|
2003-06-30 05:41:57 +08:00
|
|
|
virtual void setVertexArray(unsigned int,const Vec4*)
|
2003-06-24 23:40:09 +08:00
|
|
|
{
|
|
|
|
notify(WARN)<<"ComputeBound does not support Vec4* vertex arrays"<<std::endl;
|
|
|
|
}
|
|
|
|
|
2002-07-19 06:35:54 +08:00
|
|
|
virtual void drawArrays(GLenum,GLint first,GLsizei count)
|
|
|
|
{
|
|
|
|
if (_vertices)
|
|
|
|
{
|
2002-11-06 18:24:33 +08:00
|
|
|
const osg::Vec3* vert = _vertices+first;
|
2002-07-19 06:35:54 +08:00
|
|
|
for(;count>0;--count,++vert)
|
|
|
|
{
|
|
|
|
_bb.expandBy(*vert);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-06 18:24:33 +08:00
|
|
|
virtual void drawElements(GLenum,GLsizei count,const GLubyte* indices)
|
2002-07-19 06:35:54 +08:00
|
|
|
{
|
|
|
|
if (_vertices)
|
|
|
|
{
|
|
|
|
for(;count>0;--count,++indices)
|
|
|
|
{
|
|
|
|
_bb.expandBy(_vertices[*indices]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-06 18:24:33 +08:00
|
|
|
virtual void drawElements(GLenum,GLsizei count,const GLushort* indices)
|
2002-07-19 06:35:54 +08:00
|
|
|
{
|
|
|
|
if (_vertices)
|
|
|
|
{
|
|
|
|
for(;count>0;--count,++indices)
|
|
|
|
{
|
|
|
|
_bb.expandBy(_vertices[*indices]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-06 18:24:33 +08:00
|
|
|
virtual void drawElements(GLenum,GLsizei count,const GLuint* indices)
|
2002-07-19 06:35:54 +08:00
|
|
|
{
|
|
|
|
if (_vertices)
|
|
|
|
{
|
|
|
|
for(;count>0;--count,++indices)
|
|
|
|
{
|
|
|
|
_bb.expandBy(_vertices[*indices]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void begin(GLenum) {}
|
2003-06-24 23:40:09 +08:00
|
|
|
virtual void vertex(const Vec2& vert) { _bb.expandBy(osg::Vec3(vert[0],vert[1],0.0f)); }
|
2002-07-19 06:35:54 +08:00
|
|
|
virtual void vertex(const Vec3& vert) { _bb.expandBy(vert); }
|
2003-06-24 23:40:09 +08:00
|
|
|
virtual void vertex(const Vec4& vert) { if (vert[3]!=0.0f) _bb.expandBy(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]); }
|
|
|
|
virtual void vertex(float x,float y) { _bb.expandBy(x,y,1.0f); }
|
2002-07-19 06:35:54 +08:00
|
|
|
virtual void vertex(float x,float y,float z) { _bb.expandBy(x,y,z); }
|
2003-06-24 23:40:09 +08:00
|
|
|
virtual void vertex(float x,float y,float z,float w) { if (w!=0.0f) _bb.expandBy(x/w,y/w,z/w); }
|
2002-07-19 06:35:54 +08:00
|
|
|
virtual void end() {}
|
|
|
|
|
2002-11-06 18:24:33 +08:00
|
|
|
const Vec3* _vertices;
|
2002-07-19 06:35:54 +08:00
|
|
|
BoundingBox _bb;
|
|
|
|
};
|
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
bool Drawable::computeBound() const
|
2002-07-19 06:35:54 +08:00
|
|
|
{
|
|
|
|
ComputeBound cb;
|
|
|
|
|
|
|
|
Drawable* non_const_this = const_cast<Drawable*>(this);
|
|
|
|
non_const_this->accept(cb);
|
|
|
|
|
|
|
|
_bbox = cb._bb;
|
|
|
|
_bbox_computed = true;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2003-03-12 05:53:28 +08:00
|
|
|
void Drawable::setBound(const BoundingBox& bb) const
|
|
|
|
{
|
|
|
|
_bbox = bb;
|
|
|
|
_bbox_computed = true;
|
|
|
|
}
|
2003-06-30 05:41:57 +08:00
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Extension support
|
|
|
|
//
|
|
|
|
|
|
|
|
typedef buffered_value< ref_ptr<Drawable::Extensions> > BufferedExtensions;
|
|
|
|
static BufferedExtensions s_extensions;
|
|
|
|
|
|
|
|
Drawable::Extensions* Drawable::getExtensions(unsigned int contextID,bool createIfNotInitalized)
|
|
|
|
{
|
|
|
|
if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Drawable::Extensions;
|
|
|
|
return s_extensions[contextID].get();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::setExtensions(unsigned int contextID,Extensions* extensions)
|
|
|
|
{
|
|
|
|
s_extensions[contextID] = extensions;
|
|
|
|
}
|
|
|
|
|
|
|
|
Drawable::Extensions::Extensions()
|
|
|
|
{
|
|
|
|
setupGLExtenions();
|
|
|
|
}
|
|
|
|
|
|
|
|
Drawable::Extensions::Extensions(const Extensions& rhs):
|
|
|
|
Referenced()
|
|
|
|
{
|
|
|
|
_isVertexProgramSupported = rhs._isVertexProgramSupported;
|
|
|
|
_isSecondaryColorSupported = rhs._isSecondaryColorSupported;
|
|
|
|
_isFogCoordSupported = rhs._isFogCoordSupported;
|
|
|
|
_isMultiTexSupported = rhs._isMultiTexSupported;
|
|
|
|
_glFogCoordfv = rhs._glFogCoordfv;
|
|
|
|
_glSecondaryColor3ubv = rhs._glSecondaryColor3ubv;
|
|
|
|
_glSecondaryColor3fv = rhs._glSecondaryColor3fv;
|
|
|
|
_glMultiTexCoord1f = rhs._glMultiTexCoord1f;
|
|
|
|
_glMultiTexCoord2fv = rhs._glMultiTexCoord2fv;
|
|
|
|
_glMultiTexCoord3fv = rhs._glMultiTexCoord3fv;
|
|
|
|
_glMultiTexCoord4fv = rhs._glMultiTexCoord4fv;
|
|
|
|
_glVertexAttrib1s = rhs._glVertexAttrib1s;
|
|
|
|
_glVertexAttrib1f = rhs._glVertexAttrib1f;
|
|
|
|
_glVertexAttrib2fv = rhs._glVertexAttrib2fv;
|
|
|
|
_glVertexAttrib3fv = rhs._glVertexAttrib3fv;
|
|
|
|
_glVertexAttrib4fv = rhs._glVertexAttrib4fv;
|
|
|
|
_glVertexAttrib4ubv = rhs._glVertexAttrib4ubv;
|
|
|
|
_glVertexAttrib4Nubv = rhs._glVertexAttrib4Nubv;
|
|
|
|
_glGenBuffers = rhs._glGenBuffers;
|
|
|
|
_glBindBuffer = rhs._glBindBuffer;
|
|
|
|
_glBufferData = rhs._glBufferData;
|
|
|
|
_glBufferSubData = rhs._glBufferSubData;
|
|
|
|
_glDeleteBuffers = rhs._glDeleteBuffers;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Drawable::Extensions::lowestCommonDenominator(const Extensions& rhs)
|
|
|
|
{
|
|
|
|
if (!rhs._isVertexProgramSupported) _isVertexProgramSupported = false;
|
|
|
|
if (!rhs._isSecondaryColorSupported) _isSecondaryColorSupported = false;
|
|
|
|
if (!rhs._isFogCoordSupported) _isFogCoordSupported = false;
|
|
|
|
if (!rhs._isMultiTexSupported) _isMultiTexSupported = false;
|
|
|
|
|
|
|
|
if (!rhs._glFogCoordfv) _glFogCoordfv = 0;
|
|
|
|
if (!rhs._glSecondaryColor3ubv) _glSecondaryColor3ubv = 0;
|
|
|
|
if (!rhs._glSecondaryColor3fv) _glSecondaryColor3fv = 0;
|
|
|
|
if (!rhs._glMultiTexCoord1f) _glMultiTexCoord1f = 0;
|
|
|
|
if (!rhs._glMultiTexCoord2fv) _glMultiTexCoord2fv = 0;
|
|
|
|
if (!rhs._glMultiTexCoord3fv) _glMultiTexCoord3fv = 0;
|
|
|
|
if (!rhs._glMultiTexCoord4fv) _glMultiTexCoord4fv = 0;
|
|
|
|
|
|
|
|
if (!rhs._glVertexAttrib1s) _glVertexAttrib1s = 0;
|
|
|
|
if (!rhs._glVertexAttrib1f) _glVertexAttrib1f = 0;
|
|
|
|
if (!rhs._glVertexAttrib2fv) _glVertexAttrib2fv = 0;
|
|
|
|
if (!rhs._glVertexAttrib3fv) _glVertexAttrib3fv = 0;
|
|
|
|
if (!rhs._glVertexAttrib4fv) _glVertexAttrib4fv = 0;
|
|
|
|
if (!rhs._glVertexAttrib4ubv) _glVertexAttrib4ubv = 0;
|
|
|
|
if (!rhs._glVertexAttrib4Nubv) _glVertexAttrib4Nubv = 0;
|
|
|
|
|
|
|
|
if (!rhs._glGenBuffers) _glGenBuffers = 0;
|
|
|
|
if (!rhs._glBindBuffer) _glBindBuffer = 0;
|
|
|
|
if (!rhs._glBufferData) _glBufferData = 0;
|
|
|
|
if (!rhs._glBufferSubData) _glBufferSubData = 0;
|
|
|
|
if (!rhs._glDeleteBuffers) _glDeleteBuffers = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::setupGLExtenions()
|
|
|
|
{
|
|
|
|
_isVertexProgramSupported = isGLExtensionSupported("GL_ARB_vertex_program");
|
|
|
|
_isSecondaryColorSupported = isGLExtensionSupported("GL_EXT_secondary_color");
|
|
|
|
_isFogCoordSupported = isGLExtensionSupported("GL_EXT_fog_coord");
|
|
|
|
_isMultiTexSupported = isGLExtensionSupported("GL_ARB_multitexture");
|
|
|
|
|
|
|
|
_glFogCoordfv = ((FogCoordProc)osg::getGLExtensionFuncPtr("glFogCoordfv","glFogCoordfvEXT"));
|
|
|
|
_glSecondaryColor3ubv = ((SecondaryColor3ubvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3ubv","glSecondaryColor3ubvEXT"));
|
|
|
|
_glSecondaryColor3fv = ((SecondaryColor3fvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3fv","glSecondaryColor3fvEXT"));
|
|
|
|
_glMultiTexCoord1f = ((MultiTexCoord1fProc)osg::getGLExtensionFuncPtr("glMultiTexCoord1f","glMultiTexCoord1fARB"));
|
|
|
|
_glMultiTexCoord2fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord2fv","glMultiTexCoord2fvARB"));
|
|
|
|
_glMultiTexCoord3fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord3fv","glMultiTexCoord3fvARB"));
|
|
|
|
_glMultiTexCoord4fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord4fv","glMultiTexCoord4fvARB"));
|
|
|
|
|
|
|
|
_glVertexAttrib1s = ((VertexAttrib1sProc)osg::getGLExtensionFuncPtr("glVertexAttrib1s","glVertexAttrib1sARB"));
|
|
|
|
_glVertexAttrib1f = ((VertexAttrib1fProc)osg::getGLExtensionFuncPtr("glVertexAttrib1f","glVertexAttrib1fARB"));
|
|
|
|
_glVertexAttrib2fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib2fv","glVertexAttrib2fvARB"));
|
|
|
|
_glVertexAttrib3fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib3fv","glVertexAttrib3fvARB"));
|
|
|
|
_glVertexAttrib4fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4fv","glVertexAttrib4fvARB"));
|
|
|
|
_glVertexAttrib4ubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4ubv","glVertexAttrib4ubvARB"));
|
|
|
|
_glVertexAttrib4Nubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4Nubv","glVertexAttrib4NubvARB"));
|
|
|
|
|
|
|
|
_glGenBuffers = ((GenBuffersProc)osg::getGLExtensionFuncPtr("glGenBuffers","glGenBuffersARB"));
|
|
|
|
_glBindBuffer = ((BindBufferProc)osg::getGLExtensionFuncPtr("glBindBuffer","glBindBufferARB"));
|
|
|
|
_glBufferData = ((BufferDataProc)osg::getGLExtensionFuncPtr("glBufferData","glBufferDataARB"));
|
|
|
|
_glBufferSubData = ((BufferSubDataProc)osg::getGLExtensionFuncPtr("glBufferSubData","glBufferSubDataARB"));
|
|
|
|
_glDeleteBuffers = ((DeleteBuffersProc)osg::getGLExtensionFuncPtr("glDeleteBuffers","glDeleteBuffersARB"));
|
|
|
|
|
|
|
|
}
|
|
|
|
void Drawable::Extensions::glFogCoordfv(const GLfloat* coord) const
|
|
|
|
{
|
|
|
|
if (_glFogCoordfv)
|
|
|
|
{
|
|
|
|
_glFogCoordfv(coord);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glFogCoordfv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glSecondaryColor3ubv(const GLubyte* coord) const
|
|
|
|
{
|
|
|
|
if (_glSecondaryColor3ubv)
|
|
|
|
{
|
|
|
|
_glSecondaryColor3ubv(coord);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glSecondaryColor3ubv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glSecondaryColor3fv(const GLfloat* coord) const
|
|
|
|
{
|
|
|
|
if (_glSecondaryColor3fv)
|
|
|
|
{
|
|
|
|
_glSecondaryColor3fv(coord);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glSecondaryColor3fv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glMultiTexCoord1f(GLenum target,GLfloat coord) const
|
|
|
|
{
|
|
|
|
if (_glMultiTexCoord1f)
|
|
|
|
{
|
|
|
|
_glMultiTexCoord1f(target,coord);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glMultiTexCoord1f not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glMultiTexCoord2fv(GLenum target,const GLfloat* coord) const
|
|
|
|
{
|
|
|
|
if (_glMultiTexCoord2fv)
|
|
|
|
{
|
|
|
|
_glMultiTexCoord2fv(target,coord);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glMultiTexCoord2fv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glMultiTexCoord3fv(GLenum target,const GLfloat* coord) const
|
|
|
|
{
|
|
|
|
if (_glMultiTexCoord3fv)
|
|
|
|
{
|
|
|
|
_glMultiTexCoord3fv(target,coord);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: _glMultiTexCoord3fv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glMultiTexCoord4fv(GLenum target,const GLfloat* coord) const
|
|
|
|
{
|
|
|
|
if (_glMultiTexCoord4fv)
|
|
|
|
{
|
|
|
|
_glMultiTexCoord4fv(target,coord);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glMultiTexCoord4fv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glVertexAttrib1s(unsigned int index, GLshort s) const
|
|
|
|
{
|
|
|
|
if (_glVertexAttrib1s)
|
|
|
|
{
|
|
|
|
_glVertexAttrib1s(index,s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glVertexAttrib1s not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glVertexAttrib1f(unsigned int index, GLfloat f) const
|
|
|
|
{
|
|
|
|
if (_glVertexAttrib1f)
|
|
|
|
{
|
|
|
|
_glVertexAttrib1f(index,f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glVertexAttrib1f not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glVertexAttrib2fv(unsigned int index, const GLfloat * v) const
|
|
|
|
{
|
|
|
|
if (_glVertexAttrib2fv)
|
|
|
|
{
|
|
|
|
_glVertexAttrib2fv(index,v);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glVertexAttrib2fv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glVertexAttrib3fv(unsigned int index, const GLfloat * v) const
|
|
|
|
{
|
|
|
|
if (_glVertexAttrib3fv)
|
|
|
|
{
|
|
|
|
_glVertexAttrib3fv(index,v);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glVertexAttrib3fv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glVertexAttrib4fv(unsigned int index, const GLfloat * v) const
|
|
|
|
{
|
|
|
|
if (_glVertexAttrib4fv)
|
|
|
|
{
|
|
|
|
_glVertexAttrib4fv(index,v);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glVertexAttrib4fv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glVertexAttrib4ubv(unsigned int index, const GLubyte * v) const
|
|
|
|
{
|
|
|
|
if (_glVertexAttrib4ubv)
|
|
|
|
{
|
|
|
|
_glVertexAttrib4ubv(index,v);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glVertexAttrib4ubv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glVertexAttrib4Nubv(unsigned int index, const GLubyte * v) const
|
|
|
|
{
|
|
|
|
if (_glVertexAttrib4Nubv)
|
|
|
|
{
|
|
|
|
_glVertexAttrib4Nubv(index,v);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glVertexAttrib4Nubv not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glGenBuffers(GLsizei n, GLuint *buffers) const
|
|
|
|
{
|
|
|
|
if (_glGenBuffers)
|
|
|
|
{
|
|
|
|
_glGenBuffers(n, buffers);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glGenBuffers not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glBindBuffer(GLenum target, GLuint buffer) const
|
|
|
|
{
|
|
|
|
if (_glBindBuffer)
|
|
|
|
{
|
|
|
|
_glBindBuffer(target, buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glBindBuffer not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const
|
|
|
|
{
|
|
|
|
if (_glBufferData)
|
|
|
|
{
|
|
|
|
_glBufferData(target, size, data, usage);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const
|
|
|
|
{
|
|
|
|
if (_glBufferSubData)
|
|
|
|
{
|
|
|
|
_glBufferSubData(target, offset, size, data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawable::Extensions::glDeleteBuffers(GLsizei n, const GLuint *buffers) const
|
|
|
|
{
|
|
|
|
if (_glDeleteBuffers)
|
|
|
|
{
|
|
|
|
_glDeleteBuffers(n, buffers);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
|
|
|
|
}
|
|
|
|
}
|