OpenSceneGraph/include/osg/Geometry
Robert Osfield aa52005b87 Added empty() method to Geometry to facilitate tests for removing empty
geometry from the scene graph.

Added removal of empty geometry leaves from within the RemoveEmptyNodeVisitor
2004-03-29 10:24:16 +00:00

397 lines
18 KiB
C++

/* -*-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.
*/
#ifndef OSG_GEOMETRY
#define OSG_GEOMETRY 1
#include <osg/Drawable>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Array>
#include <osg/PrimitiveSet>
namespace osg {
class SG_EXPORT Geometry : public Drawable
{
public:
Geometry();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
Geometry(const Geometry& geometry,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
virtual Object* cloneType() const { return new Geometry(); }
virtual Object* clone(const CopyOp& copyop) const { return new Geometry(*this,copyop); }
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Geometry*>(obj)!=NULL; }
virtual const char* libraryName() const { return "osg"; }
virtual const char* className() const { return "Geometry"; }
virtual Geometry* asGeometry() { return this; }
virtual const Geometry* asGeometry() const { return this; }
bool empty() const;
enum AttributeBinding
{
BIND_OFF=0,
BIND_OVERALL,
BIND_PER_PRIMITIVE_SET,
BIND_PER_PRIMITIVE,
BIND_PER_VERTEX
};
struct ArrayData
{
ArrayData():
binding(BIND_OFF),
normalize(GL_FALSE),
offset(0) {}
ArrayData(const ArrayData& data,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
ArrayData(Array* a, AttributeBinding b, GLboolean n = GL_FALSE):
array(a),
indices(0),
binding(b),
normalize(n),
offset(0) {}
ArrayData(Array* a, IndexArray* i, AttributeBinding b, GLboolean n = GL_FALSE):
array(a),
indices(i),
binding(b),
normalize(n),
offset(0) {}
ArrayData& operator = (const ArrayData& rhs)
{
array = rhs.array;
indices = rhs.indices;
binding = rhs.binding;
normalize = rhs.normalize;
offset = rhs.offset;
return *this;
}
inline bool empty() const { return !array.valid(); }
ref_ptr<Array> array;
ref_ptr<IndexArray> indices;
AttributeBinding binding;
GLboolean normalize;
mutable unsigned int offset;
};
struct Vec3ArrayData
{
Vec3ArrayData():
binding(BIND_OFF),
normalize(GL_FALSE),
offset(0) {}
Vec3ArrayData(const Vec3ArrayData& data,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
Vec3ArrayData(Vec3Array* a, AttributeBinding b, GLboolean n = GL_FALSE):
array(a),
indices(0),
binding(b),
normalize(n),
offset(0) {}
Vec3ArrayData(Vec3Array* a, IndexArray* i, AttributeBinding b, GLboolean n = GL_FALSE):
array(a),
indices(i),
binding(b),
normalize(n),
offset(0) {}
Vec3ArrayData& operator = (const Vec3ArrayData& rhs)
{
array = rhs.array;
indices = rhs.indices;
binding = rhs.binding;
normalize = rhs.normalize;
offset = rhs.offset;
return *this;
}
inline bool empty() const { return !array.valid(); }
ref_ptr<Vec3Array> array;
ref_ptr<IndexArray> indices;
AttributeBinding binding;
GLboolean normalize;
mutable unsigned int offset;
};
/** static ArrayData which is returned get getTexCoordData(i) const and getVertexAttribData(i) const
* when i is out of range.*/
static const ArrayData s_InvalidArrayData;
typedef std::vector< ArrayData > ArrayList;
void setVertexArray(Array* array) { _vertexData.array = array; dirtyDisplayList(); dirtyBound(); }
Array* getVertexArray() { return _vertexData.array.get(); }
const Array* getVertexArray() const { return _vertexData.array.get(); }
void setVertexIndices(IndexArray* array) { _vertexData.indices = array; computeFastPathsUsed(); dirtyDisplayList(); dirtyBound(); }
IndexArray* getVertexIndices() { return _vertexData.indices.get(); }
const IndexArray* getVertexIndices() const { return _vertexData.indices.get(); }
void setVertexData(const ArrayData& arrayData) { _vertexData = arrayData; }
ArrayData& getVertexData() { return _vertexData; }
const ArrayData& getVertexData() const { return _vertexData; }
void setNormalBinding(AttributeBinding ab) { _normalData.binding = ab; dirtyDisplayList(); computeFastPathsUsed(); }
AttributeBinding getNormalBinding() const { return _normalData.binding; }
void setNormalArray(Vec3Array* array) { _normalData.array = array; if (!_normalData.array.valid()) _normalData.binding=BIND_OFF; computeFastPathsUsed(); dirtyDisplayList(); }
Vec3Array* getNormalArray() { return _normalData.array.get(); }
const Vec3Array* getNormalArray() const { return _normalData.array.get(); }
void setNormalIndices(IndexArray* array) { _normalData.indices = array; computeFastPathsUsed(); dirtyDisplayList(); }
IndexArray* getNormalIndices() { return _normalData.indices.get(); }
const IndexArray* getNormalIndices() const { return _normalData.indices.get(); }
void setNormalData(const Vec3ArrayData& arrayData) { _normalData = arrayData; }
Vec3ArrayData& getNormalData() { return _normalData; }
const Vec3ArrayData& getNormalData() const { return _normalData; }
void setColorBinding(AttributeBinding ab) { _colorData.binding = ab; computeFastPathsUsed();}
AttributeBinding getColorBinding() const { return _colorData.binding; }
void setColorArray(Array* array) { _colorData.array = array; if (!_colorData.array.valid()) _colorData.binding=BIND_OFF; computeFastPathsUsed(); dirtyDisplayList(); }
Array* getColorArray() { return _colorData.array.get(); }
const Array* getColorArray() const { return _colorData.array.get(); }
void setColorIndices(IndexArray* array) { _colorData.indices = array; computeFastPathsUsed(); dirtyDisplayList(); }
IndexArray* getColorIndices() { return _colorData.indices.get(); }
const IndexArray* getColorIndices() const { return _colorData.indices.get(); }
void setColorData(const ArrayData& arrayData) { _colorData = arrayData; }
ArrayData& getColorData() { return _colorData; }
const ArrayData& getColorData() const { return _colorData; }
void setSecondaryColorBinding(AttributeBinding ab) { _secondaryColorData.binding = ab; computeFastPathsUsed();}
AttributeBinding getSecondaryColorBinding() const { return _secondaryColorData.binding; }
void setSecondaryColorArray(Array* array) { _secondaryColorData.array = array; if (!_secondaryColorData.array.valid()) _secondaryColorData.binding=BIND_OFF; computeFastPathsUsed(); dirtyDisplayList(); }
Array* getSecondaryColorArray() { return _secondaryColorData.array.get(); }
const Array* getSecondaryColorArray() const { return _secondaryColorData.array.get(); }
void setSecondaryColorIndices(IndexArray* array) { _secondaryColorData.indices = array; computeFastPathsUsed(); dirtyDisplayList(); }
IndexArray* getSecondaryColorIndices() { return _secondaryColorData.indices.get(); }
const IndexArray* getSecondaryColorIndices() const { return _secondaryColorData.indices.get(); }
void setSecondaryColorData(const ArrayData& arrayData) { _secondaryColorData = arrayData; }
ArrayData& getSecondaryColorData() { return _secondaryColorData; }
const ArrayData& getSecondaryColorData() const { return _secondaryColorData; }
void setFogCoordBinding(AttributeBinding ab) { _fogCoordData.binding = ab; computeFastPathsUsed();}
AttributeBinding getFogCoordBinding() const { return _fogCoordData.binding; }
void setFogCoordArray(Array* array) { _fogCoordData.array = array; if (!_fogCoordData.array.valid()) _fogCoordData.binding=BIND_OFF; dirtyDisplayList(); }
Array* getFogCoordArray() { return _fogCoordData.array.get(); }
const Array* getFogCoordArray() const { return _fogCoordData.array.get(); }
void setFogCoordIndices(IndexArray* array) { _fogCoordData.indices = array; dirtyDisplayList(); }
IndexArray* getFogCoordIndices() { return _fogCoordData.indices.get(); }
const IndexArray* getFogCoordIndices() const { return _fogCoordData.indices.get(); }
void setFogCoordData(const ArrayData& arrayData) { _fogCoordData = arrayData; }
ArrayData& getFogCoordData() { return _fogCoordData; }
const ArrayData& getFogCoordData() const { return _fogCoordData; }
void setTexCoordArray(unsigned int unit,Array*);
Array* getTexCoordArray(unsigned int unit);
const Array* getTexCoordArray(unsigned int unit) const;
void setTexCoordIndices(unsigned int unit,IndexArray*);
IndexArray* getTexCoordIndices(unsigned int unit);
const IndexArray* getTexCoordIndices(unsigned int unit) const;
void setTexCoordData(unsigned int index,const ArrayData& arrayData);
ArrayData& getTexCoordData(unsigned int index);
const ArrayData& getTexCoordData(unsigned int index) const;
unsigned int getNumTexCoordArrays() const { return _texCoordList.size(); }
ArrayList& getTexCoordArrayList() { return _texCoordList; }
const ArrayList& getTexCoordArrayList() const { return _texCoordList; }
void setVertexAttribArray(unsigned int index,Array* array);
Array *getVertexAttribArray(unsigned int index);
const Array *getVertexAttribArray(unsigned int index) const;
void setVertexAttribIndices(unsigned int index,IndexArray* array);
IndexArray* getVertexAttribIndices(unsigned int index);
const IndexArray* getVertexAttribIndices(unsigned int index) const;
void setVertexAttribBinding(unsigned int index,AttributeBinding ab);
AttributeBinding getVertexAttribBinding(unsigned int index) const;
void setVertexAttribNormalize(unsigned int index,GLboolean norm);
GLboolean getVertexAttribNormalize(unsigned int index) const;
void setVertexAttribData(unsigned int index,const ArrayData& arrayData);
ArrayData& getVertexAttribData(unsigned int index);
const ArrayData& getVertexAttribData(unsigned int index) const;
unsigned int getNumVertexAttribArrays() const { return _vertexAttribList.size(); }
ArrayList& getVertexAttribArrayList() { return _vertexAttribList; }
const ArrayList& getVertexAttribArrayList() const { return _vertexAttribList; }
typedef std::vector< ref_ptr<PrimitiveSet> > PrimitiveSetList;
void setPrimitiveSetList(const PrimitiveSetList& primitives) { _primitives = primitives; dirtyDisplayList(); dirtyBound(); }
PrimitiveSetList& getPrimitiveSetList() { return _primitives; }
const PrimitiveSetList& getPrimitiveSetList() const { return _primitives; }
unsigned int getNumPrimitiveSets() const { return _primitives.size(); }
PrimitiveSet* getPrimitiveSet(unsigned int pos) { return _primitives[pos].get(); }
const PrimitiveSet* getPrimitiveSet(unsigned int pos) const { return _primitives[pos].get(); }
/** Add a primitive set to the geometry.*/
bool addPrimitiveSet(PrimitiveSet* primitiveset);
/** Set a primitive set to the specified position in geometry's primitive set list.*/
bool setPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset);
/** Insert a primitive set to the specified position in geometry's primitive set list.*/
bool insertPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset);
/** Remove primitive set(s) from the specified position in geometry's primitive set list.*/
bool removePrimitiveSet(unsigned int i,unsigned int numElementsToRemove=1);
/** Get the index number of a primitive set, return a value between
* 0 and getNumPrimitiveSet()-1 if found, if not found then return getNumPrimitiveSet().
* When checking for a valid find value use if ((value=geoemtry->getPrimitiveSetIndex(primitive))!=geometry.getNumPrimitiveSet()) as*/
unsigned int getPrimitiveSetIndex(const PrimitiveSet* primitiveset) const;
/** Set whether fast paths should be used when supported.*/
void setFastPathHint(bool on) { _fastPathHint = on; }
/** Get whether fast paths should be used when supported.*/
bool getFastPathHint() const { return _fastPathHint; }
/** return true if OpenGL fast paths will be used with drawing this Geometry.
* Fast paths use vertex arrays, and glDrawArrays/glDrawElements. Slow paths
* use glBegin()/glVertex.../glEnd(). Use of per primitive bindings or per vertex indexed
* arrays will drop the rendering path off the fast path.*/
inline bool areFastPathsUsed() const { return _fastPath && _fastPathHint; }
bool computeFastPathsUsed();
bool verifyBindings() const;
void computeCorrectBindingsAndArraySizes();
bool suitableForOptimization() const;
void copyToAndOptimize(Geometry& target);
void computeInternalOptimizedGeometry();
void removeInternalOptimizedGeometry() { _internalOptimizedGeometry = 0; }
void setInternalOptimizedGeometry(osg::Geometry* geometry) { _internalOptimizedGeometry = geometry; }
osg::Geometry* getInternalOptimizedGeometry() { return _internalOptimizedGeometry.get(); }
const osg::Geometry* getInternalOptimizedGeometry() const { return _internalOptimizedGeometry.get(); }
/** draw Geometry directly ignoring an OpenGL display list which could be attached.
* This is the internal draw method which does the drawing itself,
* and is the method to override when deriving from Geometry for user-drawn objects.
*/
virtual void drawImplementation(State& state) const;
/** return true, osg::Geometry does support accept(AttributeFunctor&).*/
virtual bool supports(AttributeFunctor&) const { return true; }
/** accept an AttributeFunctor and call its methods to tell it about the interal attributes that this Drawable has.*/
virtual void accept(AttributeFunctor& af);
/** return true, osg::Geometry does support accept(ConstAttributeFunctor&).*/
virtual bool supports(ConstAttributeFunctor&) const { return true; }
/** accept an ConstAttributeFunctor and call its methods to tell it about the interal attributes that this Drawable has.*/
virtual void accept(ConstAttributeFunctor& af) const;
/** return true, osg::Geometry does support accept(PrimitiveFunctor&) .*/
virtual bool supports(PrimitiveFunctor&) const { return true; }
/** accept a PrimitiveFunctor and call its methods to tell it about the interal primitives that this Drawable has.*/
virtual void accept(PrimitiveFunctor& pf) const;
/** return true, osg::Geometry does support accept(PrimitiveIndexFunctor&) .*/
virtual bool supports(PrimitiveIndexFunctor&) const { return true; }
/** accept a PrimitiveFunctor and call its methods to tell it about the interal primitives that this Drawable has.*/
virtual void accept(PrimitiveIndexFunctor& pf) const;
protected:
Geometry& operator = (const Geometry&) { return *this;}
virtual ~Geometry();
bool verifyBindings(const ArrayData& arrayData) const;
bool verifyBindings(const Vec3ArrayData& arrayData) const;
void computeCorrectBindingsAndArraySizes(ArrayData& arrayData,const char* arrayName);
void computeCorrectBindingsAndArraySizes(Vec3ArrayData& arrayData,const char* arrayName);
PrimitiveSetList _primitives;
ArrayData _vertexData;
Vec3ArrayData _normalData;
ArrayData _colorData;
ArrayData _secondaryColorData;
ArrayData _fogCoordData;
ArrayList _texCoordList;
ArrayList _vertexAttribList;
mutable bool _fastPath;
bool _fastPathHint;
ref_ptr<Geometry> _internalOptimizedGeometry;
};
/** Convenience function to be used for creating quad geometry with texture coords.
* Tex coords go from bottom left (0,0) to top right (1,1).*/
extern SG_EXPORT Geometry* createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float s=1.0f, float t=1.0f);
}
#endif