DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarth/LineDrawable

332 lines
12 KiB
Plaintext
Raw Normal View History

2024-12-24 23:49:36 +00:00
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_LINEDRAWABLE_H
#define OSGEARTH_LINEDRAWABLE_H 1
#include <osgEarth/Common>
#include <osgEarth/Threading>
#include <osg/Array>
#include <osg/Geometry>
namespace osgEarth
{
/**
* Drawable that renders lines using the GPU. It will fall back on rendering
* OpenGL lines when shader-based rendering is unavailable.
*
* Note: If you use this class you must have the oe_Camera
* uniform set. MapNode sets it automatically so any LineDrawable under
* a MapNode is fine. Otherwise, use the osgEarth::InstallCameraUniform
* callback on your scene graph.
*/
class OSGEARTH_EXPORT LineDrawable : public osg::Drawable
{
public:
//! Create a new LineDrawable.
//! @param[in ] mode GL line mode: GL_LINE_STRIP or GL_LINE_LOOP
LineDrawable(GLenum mode =GL_LINE_STRIP);
//! Copy constructor
LineDrawable(const LineDrawable& rhs, const osg::CopyOp& copy);
//! Width in pixels of the line
void setLineWidth(float width_pixels);
float getLineWidth() const { return _width; }
//! Stippling pattern for the line (default is 0xFFFF)
void setStipplePattern(GLushort pattern);
GLushort getStipplePattern() const { return _pattern; }
//! Stippling factor for the line (default is 1)
void setStippleFactor(GLint factor);
GLint getStippleFactor() const { return _factor; }
//! Stippling quantization factor (default is 8.0)
void setStippleQuantize(GLfloat factor);
GLfloat getStippleQuantize() const { return _quantize; }
//! Line smoothing (antialiasing)
void setLineSmooth(bool value);
bool getLineSmooth() const { return _smooth; }
//! Sets the overall color of the line
void setColor(const osg::Vec4& color);
const osg::Vec4& getColor() const { return _color; }
//! Append a vertex to the line
void pushVertex(const osg::Vec3& vert);
//! Set the value of a vertex at index i
void setVertex(unsigned i, const osg::Vec3& vert);
//! Gets the vertex at index i
const osg::Vec3& getVertex(unsigned i) const;
//! Sets the color of a vertex at index i
void setColor(unsigned i, const osg::Vec4& color);
//! Sets whether to use a GPU shader to draw lines. Default=true.
//! Set this to false to invoke legacy OpenGL line drawing, which
//! may be a bit faster but will not support GL CORE profile or GLES.
//! NOTE: Calling this will remove any data you've added to the LineDrawable!
void setUseGPU(bool value);
bool getUseGPU() const { return _useGPU; }
//! Copy a vertex array into the drawable
void importVertexArray(const osg::Vec3Array* verts);
//! Copy a vertex attribute array into the drawable
template<typename T>
void importVertexAttribArray(unsigned location, const T* data);
//! Allocate space for vertices
void allocate(unsigned numVerts);
//! Clears all data
void clear();
//! Whether the size is zero.
bool empty() const { return size() == 0; }
//! Number of vertices in the drawable
unsigned getNumVerts() const;
//! Number of vertices in the drawable
unsigned size() const { return getNumVerts(); }
//! Appends a vertex to an attribute array. Use this instead of adding
//! to the array directly!
template<typename T>
void pushVertexAttrib(T* vaa, const typename T::ElementDataType& value);
//! Gets the value of the vertex attribute from an array at index i
template<typename T>
const typename T::ElementDataType& getVertexAttrib(const T* vaa, unsigned i) const;
//! Pre-allocate space for vertices
void reserve(unsigned size);
//! Index of the first vertex to draw (default = 0)
void setFirst(unsigned index);
unsigned getFirst() const;
//! Number of vertices to draw (default = 0, which means draw to the
//! end of the line
void setCount(unsigned count);
unsigned getCount() const;
//! Rebuild the primitive sets for this drawable. You MUST call this
//! after adding new data to the drawable!
void dirty();
void finish() { dirty(); }
//! Sets a vertex attribute array at the designated index.
//! The array must be EMPTY.
void setVertexAttribArray(unsigned i, osg::Array* a);
//! Sets a line width on a custom stateset that will apply to
//! all LineDrawables used with that state set.
static void setLineWidth(osg::StateSet* stateSet, float value, int overrideFlags=osg::StateAttribute::ON);
public:
//! Binding location for "previous" vertex attribute (default = 9)
static int PreviousVertexAttrLocation;
//! Binding location for "next" vertex attribute (default = 10)
static int NextVertexAttrLocation;
public: // osg::Node
//! Replace methods from META_Node so we can override accept
virtual osg::Object* cloneType() const override { return new LineDrawable(); }
virtual osg::Object* clone(const osg::CopyOp& copyop) const override { return new LineDrawable(*this,copyop); }
virtual bool isSameKindAs(const osg::Object* obj) const override { return dynamic_cast<const LineDrawable*>(obj)!=nullptr; }
virtual const char* className() const override { return "LineDrawable"; }
virtual const char* libraryName() const override { return "osgEarth"; }
//! Override Node::accept to include the singleton GPU statset
void accept(osg::NodeVisitor& nv) override;
public: // osg::Object
virtual void resizeGLObjectBuffers(unsigned maxSize) override;
virtual void releaseGLObjects(osg::State* state) const override;
public:
//! GL mode (for serializer only; do not use)
void setMode(GLenum mode);
GLenum getMode() const { return _mode; }
osg::StateSet* getGPUStateSet() const { return _gpuStateSet.get(); }
protected:
//! destructor
virtual ~LineDrawable();
private:
GLenum _mode;
bool _useGPU;
osg::Vec4 _color;
GLint _factor;
GLushort _pattern;
GLfloat _quantize;
float _width;
bool _smooth;
unsigned _first;
unsigned _count;
osg::Vec3Array* _current;
osg::Vec3Array* _previous;
osg::Vec3Array* _next;
osg::Vec4Array* _colors;
void initialize();
void setupShaders();
friend class LineGroup;
unsigned actualVertsPerVirtualVert(unsigned) const;
unsigned numVirtualVerts(const osg::Array*) const;
unsigned getRealIndex(unsigned) const;
void updateFirstCount();
//static osg::observer_ptr<osg::StateSet> s_gpuStateSet;
osg::ref_ptr<osg::StateSet> _gpuStateSet;
mutable std::mutex _mutex;
osg::ref_ptr<osg::Geometry> _geom;
public: // osg::Drawable pass thrus
virtual void drawImplementation(osg::RenderInfo& ri) const override;
void traverse(osg::NodeVisitor& nv) override;
virtual osg::BoundingSphere computeBound() const override {
return _geom->computeBound();
}
virtual osg::BoundingBox computeBoundingBox() const override {
return _geom->computeBoundingBox();
}
virtual bool supports(const AttributeFunctor& f) const override {
return _geom->supports(f);
}
virtual void accept(AttributeFunctor& f) override {
return _geom->accept(f);
}
virtual bool supports(const ConstAttributeFunctor& f) const override {
return _geom->supports(f);
}
virtual void accept(ConstAttributeFunctor& f) const override {
return _geom->accept(f);
}
virtual bool supports(const osg::PrimitiveFunctor& f) const override {
return _geom->supports(f);
}
virtual void accept(osg::PrimitiveFunctor& f) const override {
return _geom->accept(f);
}
virtual bool supports(const osg::PrimitiveIndexFunctor& f) const override {
return _geom->supports(f);
}
virtual void accept(osg::PrimitiveIndexFunctor& f) const {
return _geom->accept(f);
}
};
/**
* Group for importing LineDrawables from osg::Geometry or for
* optimizing multiple LineDrawables for performance.
*
* Note: LineGroup inherits from Geode (for now) to maintain support for
* the OSG 3.4 MergeGeometryVisitor (which only works on Geodes). Once we
* make OSG 3.6 the minimum supported version, we can change this to Group.
*/
class OSGEARTH_EXPORT LineGroup : public osg::Group
{
public:
META_Node(osgEarth, LineGroup);
//! Construct a new line group
LineGroup();
//! Copy constructor
LineGroup(const LineGroup& rhs, const osg::CopyOp& copy);
//! Imports any GL line drawables from a node graph, converts them
//! to LineDrawables, and adds them to this LineGroup. If will detect
//! and set any LineWidth or LineStipple attributes it finds, but will not
//! find any attributes that occur in the graph above the imported node.
//!
//! If you set removePrimitiveSets to true, it will remove all line-based
//! primitive sets from the node after import.
//!
//! This method is for quickly importing legacy scene graphs; if you are
//! writing new code, use the LineDrawable API directly instead!
void import(osg::Node* node, bool removePrimitiveSets =false);
//! Optimize the LineDrawables under this group for performance.
//! Only call this after you finish adding drawables to your group.
//! It will attempt to combine drawables and state sets, but it will also
//! render the graph henceforth immutable.
void optimize();
//! Get child i as a LineDrawable
LineDrawable* getLineDrawable(unsigned i);
protected:
//! destructor
virtual ~LineGroup();
};
// Template implementations ..........................................
template<typename T>
void LineDrawable::pushVertexAttrib(T* vaa, const typename T::ElementDataType& value)
{
unsigned nvv = numVirtualVerts(vaa);
unsigned num = actualVertsPerVirtualVert(nvv);
for (unsigned i = 0; i<num; ++i)
vaa->push_back(value);
}
template<typename T>
const typename T::ElementDataType& LineDrawable::getVertexAttrib(const T* vaa, unsigned i) const
{
return (*vaa)[getRealIndex(i)];
}
template<typename T>
void LineDrawable::importVertexAttribArray(unsigned location, const T* data)
{
T* vaa = osg::cloneType(data);
_geom->setVertexAttribArray(location, vaa);
for (unsigned i=0; i < data->getNumElements(); ++i)
pushVertexAttrib(vaa, (*data)[i]);
}
} // namespace osgEarth
#endif // OSGEARTH_LINEDRAWABLE_H