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

142 lines
5.5 KiB
Plaintext
Raw Permalink 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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* 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_GEOMETRY_CLOUD
#define OSGEARTH_GEOMETRY_CLOUD 1
#include <osgEarth/Common>
#include <osgEarth/GLUtils>
#include <osgEarth/TextureArena>
#include <osg/Geometry>
#include <osg/NodeVisitor>
#include <vector>
namespace osgEarth
{
/**
* Object that combines multiple models into a single GL_TRIANGLES geometry.
* This does two things:
*
* 1) Each time you call add(), the model is stripped down
* and transformed into a single primitive set. All state
* except for texture0 (and a normal map texture) will be lost.
* 2) The newly stripped geometry is appended to the One True
* Combined Geometry and its texture added to the combined
* atlas.
*
* You will end up with:
* - One GL_TRIANGLES geometry with one primitive set
* - One texture atlas
* - a DrawElementsIndirectCommand for each embedded model that you can
* use to call glDrawElementsIndirect or glMultiDrawElementsIndirect.
*/
class OSGEARTH_EXPORT GeometryCloud : public osg::NodeVisitor
{
public:
//! New geometry could that will store its textures in an arena.
//! @param arena Texture arena that will hold any textures
//! collected from node added to this cloud
GeometryCloud(TextureArena* arena);
//! Return from add()
struct AddResult
{
int _commandIndex;
//std::vector<Texture::Ptr> _textures;
};
//! Add a model to be incorporated into the cloud.
//! @param node Node whose geometry to add
//! @param texturesAdded Populated with any textures that were added
//! to the texture arena in the process of adding tis node
//! @param alignment If non-zero, pad the cloud's attribute arrays so
//! the index of the first vertex in this node is a multiple of the
//! alignment value. This is necessary for shaders that use gl_VertexID
//! as a modulus.
//! @param generateTextureHandles Whether to visit the node, add textures
//! to the arena, and generate texture handle vertex attribute. If false,
//! copy the pre-existing handles from the incoming geometry.
//! @param normalMapTextureImageUnit If the model contains normal map textures,
//! the TIU containing them. -1 = no normal maps.
//! @return Success: command number of the geometry; Failure: -1
AddResult add(
osg::Node* node,
unsigned alignment = 0,
int normalMapTextureImageUnit = -1);
//! The unified geometry
osg::Geometry* getGeometry() const { return _geom.get(); }
//! How many models were added
unsigned getNumDrawCommands() const { return _vertexOffsets.size(); }
//! Populates the i-th draw command from this cloud
//! @param[in] i Index of draw command to retrieve
//! @param[out] cmd Draw command output
//! @return True if [i] was in range, false if not
bool getDrawCommand(unsigned i, DrawElementsIndirectCommand& cmd) const;
//! Render the cloud
void draw(osg::RenderInfo& ri);
//! Whether this cloud contains any geometry
bool empty() const { return _vertexOffsets.empty(); }
//! Stateset supporting the geometry
osg::StateSet* getStateSet() { return _geom.valid() ? _geom->getStateSet() : nullptr; }
public: // osg::NodeVisitor
void apply(osg::Node& node) override;
void apply(osg::Transform& xform) override;
void apply(osg::Geometry& geom) override;
osg::ref_ptr<osg::Geometry> _geom;
private:
bool pushStateSet(osg::Node&);
void popStateSet();
osg::ref_ptr<TextureArena> _texarena;
osg::DrawElementsUShort* _primset;
osg::Vec3Array* _verts;
osg::Vec4Array* _colors;
osg::Vec3Array* _normals;
osg::Vec2Array* _texcoords;
osg::ShortArray* _albedoArenaIndices;
osg::ShortArray* _normalArenaIndices;
std::vector<unsigned> _vertexOffsets;
std::vector<unsigned> _elementOffsets;
std::vector<unsigned> _elementCounts;
//traversal data - must be cleared before each traversal
using ArenaIndexLUT = std::unordered_map<osg::Texture*, int>;
ArenaIndexLUT _arenaIndexLUT;
unsigned _numElements;
std::stack<int> _albedoArenaIndexStack;
std::stack<int> _normalArenaIndexStack;
std::stack<osg::Matrix> _matrixStack;
int _normalMapTextureImageUnit;
};
}
#endif // OSGEARTH_INSTANCE_CLOUD