From 0088c280f9410c217508ba199287fc23c1378c41 Mon Sep 17 00:00:00 2001 From: Myriam Guedey Date: Mon, 30 Jan 2017 15:07:40 +0100 Subject: [PATCH 1/6] add Windows dllexport --- sources/include/citygml/featureobject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/include/citygml/featureobject.h b/sources/include/citygml/featureobject.h index 35d812da..f20745fc 100644 --- a/sources/include/citygml/featureobject.h +++ b/sources/include/citygml/featureobject.h @@ -9,7 +9,7 @@ namespace citygml { class Envelope; - class FeatureObject : public Object { + class LIBCITYGML_EXPORT FeatureObject : public Object { public: FeatureObject(const std::string& gmlID); From 61a0071319ca68b880ab99c615180240c6e4808c Mon Sep 17 00:00:00 2001 From: Myriam Guedey Date: Mon, 30 Jan 2017 16:25:26 +0100 Subject: [PATCH 2/6] ignore probably empty nodes --- sources/src/citygml/cityobject.cpp | 8 ++++++-- sources/src/parser/citygmlelementparser.cpp | 7 +++++-- sources/src/parser/cityobjectelementparser.cpp | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sources/src/citygml/cityobject.cpp b/sources/src/citygml/cityobject.cpp index a3b14735..4954894c 100644 --- a/sources/src/citygml/cityobject.cpp +++ b/sources/src/citygml/cityobject.cpp @@ -65,7 +65,7 @@ namespace citygml { void CityObject::addImplictGeometry(ImplicitGeometry* implictGeom) { - m_implicitGeometries.push_back(std::unique_ptr(implictGeom)); + m_implicitGeometries.push_back(std::unique_ptr(implictGeom)); } unsigned int CityObject::getChildCityObjectsCount() const @@ -85,7 +85,11 @@ namespace citygml { void CityObject::addChildCityObject(CityObject* cityObj) { - m_children.push_back(std::unique_ptr(cityObj)); + // don't add empty nodes as children + if(cityObj!=NULL) + { + m_children.push_back(std::unique_ptr(cityObj)); + } } const Address* CityObject::address() const diff --git a/sources/src/parser/citygmlelementparser.cpp b/sources/src/parser/citygmlelementparser.cpp index 5a30c868..eeb11c08 100644 --- a/sources/src/parser/citygmlelementparser.cpp +++ b/sources/src/parser/citygmlelementparser.cpp @@ -37,8 +37,11 @@ namespace citygml { // This might happen if an container element that usally contains a child element links to an exting object using XLink an thus // uses a combined start/end element: e.g.: // For such elements a child parser must only be created if there is no xlink attribute. - CITYGML_LOG_ERROR(m_logger, "CityGMLElementParser::endElement called on unbound " << elementParserName() << " object for element <" << node << "> at " << getDocumentLocation()); - throw std::runtime_error("CityGMLElementParser::endElement called on unbound CityGMLElementParser object."); + //CITYGML_LOG_ERROR(m_logger, "CityGMLElementParser::endElement called on unbound " << elementParserName() << " object for element <" << node << "> at " << getDocumentLocation()); + //throw std::runtime_error("CityGMLElementParser::endElement called on unbound CityGMLElementParser object."); + + m_documentParser.removeCurrentElementParser(this); // ignore (probably) empty node + return parseElementEndTag(node, characters); } if (m_boundElement == node) { diff --git a/sources/src/parser/cityobjectelementparser.cpp b/sources/src/parser/cityobjectelementparser.cpp index dd43786a..cb7ee436 100644 --- a/sources/src/parser/cityobjectelementparser.cpp +++ b/sources/src/parser/cityobjectelementparser.cpp @@ -39,6 +39,7 @@ namespace citygml { , m_lastAttributeType(AttributeType::String) { m_callback = callback; + m_model = nullptr; } std::string CityObjectElementParser::elementParserName() const From 8be1bf6205ac46c1e5b4a9be87c12200c9a8189a Mon Sep 17 00:00:00 2001 From: hpcwoess Date: Tue, 25 Feb 2020 00:20:22 +0100 Subject: [PATCH 3/6] support forward slash on windows added performance mode --- osgplugin/ReaderWriterCityGML.cpp | 176 ++++++++++++++++++++++++++- sources/src/parser/parserxercesc.cpp | 2 +- 2 files changed, 176 insertions(+), 2 deletions(-) diff --git a/osgplugin/ReaderWriterCityGML.cpp b/osgplugin/ReaderWriterCityGML.cpp index bce2dd1b..961ed488 100644 --- a/osgplugin/ReaderWriterCityGML.cpp +++ b/osgplugin/ReaderWriterCityGML.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -122,6 +123,15 @@ class CityGMLSettings std::string _theme; }; +class wallRoofObj +{ + +public: + osg::Vec3Array* verticesWall = nullptr; + osg::Vec3Array* verticesRoof = nullptr; + std::vector indicesWall; + std::vector indicesRoof; +}; class ReaderWriterCityGML : public osgDB::ReaderWriter { public: @@ -156,8 +166,13 @@ class ReaderWriterCityGML : public osgDB::ReaderWriter ReadResult readCity(std::shared_ptr, CityGMLSettings& ) const; bool createCityObject(const citygml::CityObject&, CityGMLSettings&, osg::Group*, const osg::Vec3d& offset = osg::Vec3d(0.0, 0.0, 0.0), unsigned int minimumLODToConsider = 0) const; + bool createSingleCityObject(const citygml::CityObject&, CityGMLSettings&, wallRoofObj &wr, const osg::Vec3d& offset = osg::Vec3d(0.0, 0.0, 0.0), unsigned int minimumLODToConsider = 0) const; + + void createSingleOsgGeometryFromCityGMLGeometry(const citygml::CityObject& object,const citygml::Geometry& geometry, CityGMLSettings& settings, wallRoofObj &wr, const osg::Vec3d& offset) const; + }; + // Register with Registry to instantiate the above reader/writer. REGISTER_OSGPLUGIN( citygml, ReaderWriterCityGML ) @@ -189,6 +204,15 @@ osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readNode( const std::string std::streambuf* cerrsb = std::cerr.rdbuf( osg::notify(osg::NOTICE).rdbuf() ); osg::notify(osg::NOTICE) << "Parsing CityGML file " << fileName << "..." << std::endl; +#ifdef WIN32 + if (fileName[0] == '/') + { + //xerces on windows wants \ as a start to figure out that it is an absolute path + fileName[0] = '\\'; + if(fileName[1]=='/') + fileName[1] = '\\'; + } +#endif std::shared_ptr city = citygml::load( fileName, settings._params, m_logger ); @@ -199,6 +223,7 @@ osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readNode( const std::string // Let osg calculate the normals osgUtil::SmoothingVisitor sv; + sv.setCreaseAngle(osg::PI_2); rr.getNode()->accept(sv); } @@ -259,8 +284,73 @@ osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readCity(std::shared_ptrgetEnvelope().getLowerBound(); offset = osg::Vec3d(lb.x, lb.y, lb.z); } + if (!settings._useMaxLODOnly) + { + for (unsigned int i = 0; i < roots.size(); ++i) createCityObject(*roots[i], settings, root, offset); + } + else + { + osg::Geode* geode = new osg::Geode(); + osg::Geometry* wallGeom = new osg::Geometry; + osg::Geometry* roofGeom = new osg::Geometry; + + wallRoofObj wr; + // Vertices + wr.verticesWall = new osg::Vec3Array; + wr.verticesRoof = new osg::Vec3Array; + wr.indicesWall.reserve(5000); + wr.indicesRoof.reserve(5000); + wr.verticesWall->reserve(5000); + wr.verticesRoof->reserve(5000); + + wallGeom->setVertexArray(wr.verticesWall); + roofGeom->setVertexArray(wr.verticesRoof); + for (unsigned int i = 0; i < roots.size(); ++i) createSingleCityObject(*roots[i], settings, wr, offset); + + // Indices + osg::DrawElementsUInt* indicesW = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, wr.indicesWall.begin(), wr.indicesWall.end()); + wallGeom->addPrimitiveSet(indicesW); + osg::DrawElementsUInt* indicesR = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, wr.indicesRoof.begin(), wr.indicesRoof.end()); + roofGeom->addPrimitiveSet(indicesR); - for ( unsigned int i = 0; i < roots.size(); ++i ) createCityObject( *roots[i], settings, root, offset ); + // Appearance + + osg::ref_ptr stateset = roofGeom->getOrCreateStateSet(); + + + osg::Material* material = new osg::Material; + material->setColorMode(osg::Material::OFF); + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f)); + material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); + material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); + material->setShininess(osg::Material::FRONT_AND_BACK, 128.f * 0.5f); + material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.1f, 0.1f, 0.1f,1.0f)); + stateset->setAttributeAndModes(material, osg::StateAttribute::ON); + stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); osg::CullFace* cullFace = new osg::CullFace(); + cullFace->setMode(osg::CullFace::BACK); + stateset->setAttributeAndModes(cullFace, osg::StateAttribute::ON); + + + stateset = wallGeom->getOrCreateStateSet(); + + + material = new osg::Material; + material->setColorMode(osg::Material::OFF); + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.9f, 0.9f, 0.9f, 1.0f)); + material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); + material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f)); + material->setShininess(osg::Material::FRONT_AND_BACK, 128.f * 0.5f); + material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.5f, 0.5f, 0.5f, 1.0f)); + stateset->setAttributeAndModes(material, osg::StateAttribute::ON); + stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); + stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); cullFace = new osg::CullFace(); + cullFace->setMode(osg::CullFace::BACK); + stateset->setAttributeAndModes(cullFace, osg::StateAttribute::ON); + + geode->addDrawable(wallGeom); + geode->addDrawable(roofGeom); + root->addChild(geode); + } osg::notify(osg::NOTICE) << "Done." << std::endl; @@ -411,6 +501,58 @@ void createOsgGeometryFromCityGMLGeometry(const citygml::Geometry& geometry, Cit } } +void ReaderWriterCityGML::createSingleOsgGeometryFromCityGMLGeometry(const citygml::CityObject& object, const citygml::Geometry& geometry, CityGMLSettings& settings, wallRoofObj &wr, const osg::Vec3d& offset) const +{ + for (unsigned int j = 0; j < geometry.getPolygonsCount(); j++) + { + const citygml::Polygon& p = *geometry.getPolygon(j); + + if (p.getIndices().size() == 0) continue; + + const std::vector& vert = p.getVertices(); + + if (object.getType() == citygml::CityObject::CityObjectsType::COT_RoofSurface) + { + GLuint startIndex = wr.verticesRoof->size(); + for (const auto& i : p.getIndices()) + { + wr.indicesRoof.push_back(i+startIndex); + } + + for (unsigned int k = 0; k < vert.size(); k++) + { + TVec3d v = vert[k]; + osg::Vec3d pt = osg::Vec3d(v.x, v.y, v.z) - offset; + wr.verticesRoof->push_back(pt); + } + } + if (object.getType() == citygml::CityObject::CityObjectsType::COT_WallSurface) + { + GLuint startIndex = wr.verticesWall->size(); + for (const auto& i : p.getIndices()) + { + wr.indicesWall.push_back(i + startIndex); + } + + for (unsigned int k = 0; k < vert.size(); k++) + { + TVec3d v = vert[k]; + osg::Vec3d pt = osg::Vec3d(v.x, v.y, v.z) - offset; + wr.verticesWall->push_back(pt); + } + } + + + // Indices + osg::DrawElementsUInt* indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, p.getIndices().begin(), p.getIndices().end()); + } + + // Parse child geoemtries + for (unsigned int i = 0; i < geometry.getGeometriesCount(); i++) { + createSingleOsgGeometryFromCityGMLGeometry(object, geometry.getGeometry(i), settings, wr, offset); + } +} + bool ReaderWriterCityGML::createCityObject(const citygml::CityObject& object, CityGMLSettings& settings, osg::Group* parent, const osg::Vec3d& offset , unsigned int minimumLODToConsider) const { // Skip objects without geometry @@ -485,6 +627,38 @@ bool ReaderWriterCityGML::createCityObject(const citygml::CityObject& object, Ci return true; } +bool ReaderWriterCityGML::createSingleCityObject(const citygml::CityObject& object, CityGMLSettings& settings, wallRoofObj& wr, const osg::Vec3d& offset, unsigned int minimumLODToConsider) const +{ + osg::ref_ptr roof_color = new osg::Vec4Array; + roof_color->push_back(osg::Vec4(0.9f, 0.1f, 0.1f, 1.0f)); + + unsigned int highestLOD = ReaderWriterCityGML::getHighestLodForObject(object); + + for (unsigned int i = 0; i < object.getGeometriesCount(); i++) + { + const citygml::Geometry& geometry = object.getGeometry(i); + + const unsigned int currentLOD = geometry.getLOD(); + + if (settings._useMaxLODOnly && (currentLOD < highestLOD || currentLOD < minimumLODToConsider)) { + continue; + } + + createSingleOsgGeometryFromCityGMLGeometry(object,geometry, settings, wr, offset); + } + + + // Manage transparency for windows + if (object.getType() == citygml::CityObject::CityObjectsType::COT_Window) + { + } + + for (unsigned int i = 0; i < object.getChildCityObjectsCount(); ++i) + createSingleCityObject(object.getChildCityObject(i), settings, wr, offset, highestLOD); + + return true; +} + unsigned int ReaderWriterCityGML::getHighestLodForObject( const citygml::CityObject& object){ unsigned int highestLOD = 0; // first find out highest LOD for this object diff --git a/sources/src/parser/parserxercesc.cpp b/sources/src/parser/parserxercesc.cpp index 2d3dd6f8..584272bc 100644 --- a/sources/src/parser/parserxercesc.cpp +++ b/sources/src/parser/parserxercesc.cpp @@ -301,7 +301,7 @@ namespace citygml } #endif - delete parser; + delete parser; return handler.getModel(); } From 63af36310e685b5cc19eab1ffc78072b926064f4 Mon Sep 17 00:00:00 2001 From: hpcwoess Date: Wed, 4 Mar 2020 17:37:15 +0100 Subject: [PATCH 4/6] support textures --- osgplugin/ReaderWriterCityGML.cpp | 479 ++++++++++++++++++++++-------- 1 file changed, 351 insertions(+), 128 deletions(-) diff --git a/osgplugin/ReaderWriterCityGML.cpp b/osgplugin/ReaderWriterCityGML.cpp index 961ed488..445db4db 100644 --- a/osgplugin/ReaderWriterCityGML.cpp +++ b/osgplugin/ReaderWriterCityGML.cpp @@ -90,6 +90,7 @@ class CityGMLSettings CityGMLSettings( void ) : _printNames(false) , _useMaxLODOnly(false) + , _singleObject(false) , _storeGeomIDs(false) , _theme("") {} @@ -108,7 +109,8 @@ class CityGMLSettings else if ( currentOption == "maxlod" ) iss >> _params.maxLOD; else if ( currentOption == "optimize" ) _params.optimize = true; else if ( currentOption == "pruneemptyobjects" ) _params.pruneEmptyObjects = true; - else if ( currentOption == "usemaxlodonly" ) _useMaxLODOnly = true; + else if (currentOption == "usemaxlodonly") _useMaxLODOnly = true; + else if (currentOption == "singleobject") _singleObject = true; else if ( currentOption == "usetheme" ) iss >> _theme; else if ( currentOption == "storegeomids" ) _storeGeomIDs = true; } @@ -118,20 +120,36 @@ class CityGMLSettings citygml::ParserParams _params; bool _printNames; bool _useMaxLODOnly; + bool _singleObject; bool _storeGeomIDs; std::map< std::string, osg::Texture2D* > _textureMap; std::string _theme; }; -class wallRoofObj +class materialArrays { public: - osg::Vec3Array* verticesWall = nullptr; - osg::Vec3Array* verticesRoof = nullptr; - std::vector indicesWall; - std::vector indicesRoof; + materialArrays::materialArrays(int sizehint = 3) + { + texCoords = new osg::Vec2Array; + vertices = new osg::Vec3Array; + texCoords = new osg::Vec2Array; + indices.reserve(sizehint); + vertices->reserve(sizehint); + texCoords->reserve(sizehint); + texture = nullptr; + } + materialArrays::~materialArrays() + { + } + osg::Texture2D* texture; + std::string textureName; + osg::ref_ptr vertices; + osg::ref_ptr texCoords; + std::vector indices; }; + class ReaderWriterCityGML : public osgDB::ReaderWriter { public: @@ -160,18 +178,19 @@ class ReaderWriterCityGML : public osgDB::ReaderWriter virtual ReadResult readNode( std::istream&, const osgDB::ReaderWriter::Options* ) const override; private: - std::shared_ptr m_logger; static unsigned int getHighestLodForObject(const citygml::CityObject& object); ReadResult readCity(std::shared_ptr, CityGMLSettings& ) const; bool createCityObject(const citygml::CityObject&, CityGMLSettings&, osg::Group*, const osg::Vec3d& offset = osg::Vec3d(0.0, 0.0, 0.0), unsigned int minimumLODToConsider = 0) const; - bool createSingleCityObject(const citygml::CityObject&, CityGMLSettings&, wallRoofObj &wr, const osg::Vec3d& offset = osg::Vec3d(0.0, 0.0, 0.0), unsigned int minimumLODToConsider = 0) const; + bool createSingleCityObject(const citygml::CityObject&, CityGMLSettings&, const osg::Vec3d& offset = osg::Vec3d(0.0, 0.0, 0.0), unsigned int minimumLODToConsider = 0) const; - void createSingleOsgGeometryFromCityGMLGeometry(const citygml::CityObject& object,const citygml::Geometry& geometry, CityGMLSettings& settings, wallRoofObj &wr, const osg::Vec3d& offset) const; + void createSingleOsgGeometryFromCityGMLGeometry(const citygml::CityObject& object,const citygml::Geometry& geometry, CityGMLSettings& settings, const osg::Vec3d& offset) const; }; +std::map ma; + // Register with Registry to instantiate the above reader/writer. REGISTER_OSGPLUGIN( citygml, ReaderWriterCityGML ) @@ -284,73 +303,78 @@ osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readCity(std::shared_ptrgetEnvelope().getLowerBound(); offset = osg::Vec3d(lb.x, lb.y, lb.z); } - if (!settings._useMaxLODOnly) - { - for (unsigned int i = 0; i < roots.size(); ++i) createCityObject(*roots[i], settings, root, offset); - } - else + if(settings._singleObject) { osg::Geode* geode = new osg::Geode(); - osg::Geometry* wallGeom = new osg::Geometry; - osg::Geometry* roofGeom = new osg::Geometry; - wallRoofObj wr; // Vertices - wr.verticesWall = new osg::Vec3Array; - wr.verticesRoof = new osg::Vec3Array; - wr.indicesWall.reserve(5000); - wr.indicesRoof.reserve(5000); - wr.verticesWall->reserve(5000); - wr.verticesRoof->reserve(5000); + materialArrays *arrW = new materialArrays(); + ma["wall"] = arrW; + materialArrays* arrR = new materialArrays(); + ma["roof"] = arrR; + + for (unsigned int i = 0; i < roots.size(); ++i) createSingleCityObject(*roots[i], settings, offset); + for (const auto& it : ma) + { + materialArrays* arrays = it.second; + if(arrays->vertices->size()>0) + { + osg::Geometry* geom = new osg::Geometry; + geom->setVertexArray(arrays->vertices); + osg::DrawElementsUInt* indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, arrays->indices.begin(), arrays->indices.end()); + geom->addPrimitiveSet(indices); + + + // Appearance + + osg::ref_ptr stateset = geom->getOrCreateStateSet(); + + + osg::Material* material = new osg::Material; + material->setColorMode(osg::Material::OFF); + if (it.first == "wall") + { + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.9f, 0.9f, 0.9f, 1.0f)); + } + else if (it.first == "roof") + { + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f)); + } + else // textured + { + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); + if (arrays->texture) + { + if (arrays->texCoords->size() > 0) + { + geom->setTexCoordArray(0, arrays->texCoords); + + stateset->setTextureAttributeAndModes(0, arrays->texture, osg::StateAttribute::ON); + } + } + } + material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); + material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); + material->setShininess(osg::Material::FRONT_AND_BACK, 128.f * 0.5f); + material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.1f, 0.1f, 0.1f, 1.0f)); + stateset->setAttributeAndModes(material, osg::StateAttribute::ON); + stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); osg::CullFace* cullFace = new osg::CullFace(); + cullFace->setMode(osg::CullFace::BACK); + stateset->setAttributeAndModes(cullFace, osg::StateAttribute::ON); + geode->addDrawable(geom); + } + delete arrays; + } + ma.clear(); + - wallGeom->setVertexArray(wr.verticesWall); - roofGeom->setVertexArray(wr.verticesRoof); - for (unsigned int i = 0; i < roots.size(); ++i) createSingleCityObject(*roots[i], settings, wr, offset); - // Indices - osg::DrawElementsUInt* indicesW = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, wr.indicesWall.begin(), wr.indicesWall.end()); - wallGeom->addPrimitiveSet(indicesW); - osg::DrawElementsUInt* indicesR = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, wr.indicesRoof.begin(), wr.indicesRoof.end()); - roofGeom->addPrimitiveSet(indicesR); - - // Appearance - - osg::ref_ptr stateset = roofGeom->getOrCreateStateSet(); - - - osg::Material* material = new osg::Material; - material->setColorMode(osg::Material::OFF); - material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f)); - material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); - material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); - material->setShininess(osg::Material::FRONT_AND_BACK, 128.f * 0.5f); - material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.1f, 0.1f, 0.1f,1.0f)); - stateset->setAttributeAndModes(material, osg::StateAttribute::ON); - stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); osg::CullFace* cullFace = new osg::CullFace(); - cullFace->setMode(osg::CullFace::BACK); - stateset->setAttributeAndModes(cullFace, osg::StateAttribute::ON); - - - stateset = wallGeom->getOrCreateStateSet(); - - - material = new osg::Material; - material->setColorMode(osg::Material::OFF); - material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.9f, 0.9f, 0.9f, 1.0f)); - material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); - material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f)); - material->setShininess(osg::Material::FRONT_AND_BACK, 128.f * 0.5f); - material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.5f, 0.5f, 0.5f, 1.0f)); - stateset->setAttributeAndModes(material, osg::StateAttribute::ON); - stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); - stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); cullFace = new osg::CullFace(); - cullFace->setMode(osg::CullFace::BACK); - stateset->setAttributeAndModes(cullFace, osg::StateAttribute::ON); - - geode->addDrawable(wallGeom); - geode->addDrawable(roofGeom); root->addChild(geode); } + else + { + for (unsigned int i = 0; i < roots.size(); ++i) createCityObject(*roots[i], settings, root, offset); + } osg::notify(osg::NOTICE) << "Done." << std::endl; @@ -360,6 +384,57 @@ osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readCity(std::shared_ptr stateset, osg::Geometry* geom,CityGMLSettings& settings, std::shared_ptr citygmlTex) { + + if (!citygmlTex) + { + return; + } + osg::Texture2D* texture = nullptr; + + if (settings._textureMap.find(citygmlTex->getUrl()) == settings._textureMap.end()) { + std::string fullPath = osgDB::findDataFile(citygmlTex->getUrl()); + + if (fullPath.empty()) { + osg::notify(osg::NOTICE) << " Texture file " << citygmlTex->getUrl() << " not found..." << std::endl; + return; + } + + // Load a new texture + osg::notify(osg::NOTICE) << " Loading texture " << fullPath << "..." << std::endl; + + osg::Image* image = osgDB::readImageFile(citygmlTex->getUrl()); + + if (!image) { + osg::notify(osg::NOTICE) << " Warning: Failed to read Texture " << fullPath << std::endl; + return; + } + + texture = new osg::Texture2D; + texture->setImage(image); + texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); + texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); + texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + texture->setWrap(osg::Texture::WRAP_R, osg::Texture::REPEAT); + + settings._textureMap[citygmlTex->getUrl()] = texture; + } + else { + texture = settings._textureMap[citygmlTex->getUrl()]; + } + + if (!texture) + { + return; + } + + + stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); + osg::CullFace* cullFace = new osg::CullFace(); + cullFace->setMode(osg::CullFace::BACK); + stateset->setAttributeAndModes(cullFace, osg::StateAttribute::ON); +} void setTexture(osg::ref_ptr stateset, osg::Geometry* geom, const citygml::Polygon& polygon, CityGMLSettings& settings) { const auto citygmlTex = polygon.getTextureFor(settings._theme); @@ -421,6 +496,9 @@ void setTexture(osg::ref_ptr stateset, osg::Geometry* geom, const geom->setTexCoordArray( 0, tex ); stateset->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON ); + osg::CullFace* cullFace = new osg::CullFace(); + cullFace->setMode(osg::CullFace::BACK); + stateset->setAttributeAndModes(cullFace, osg::StateAttribute::ON); } void setMaterial(osg::ref_ptr stateset, const citygml::Polygon& polygon, CityGMLSettings& settings) { @@ -446,53 +524,137 @@ void setMaterial(osg::ref_ptr stateset, const citygml::Polygon& p material->setTransparency( osg::Material::FRONT_AND_BACK, citygmlMaterial->getTransparency() ); stateset->setAttributeAndModes( material, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON ); stateset->setMode( GL_LIGHTING, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON ); + + osg::CullFace *cullFace = new osg::CullFace(); + cullFace->setMode(osg::CullFace::BACK); + stateset->setAttributeAndModes(cullFace, osg::StateAttribute::ON); } void createOsgGeometryFromCityGMLGeometry(const citygml::Geometry& geometry, CityGMLSettings& settings, osg::Geode* geometryContainer, const osg::Vec3d& offset ) { - for ( unsigned int j = 0; j < geometry.getPolygonsCount(); j++ ) - { - const citygml::Polygon& p = *geometry.getPolygon(j); - - if ( p.getIndices().size() == 0 ) continue; - - // Geometry management + std::string texName = "axaxaxax"; + if (geometry.getPolygonsCount() > 0) + { osg::Geometry* geom = new osg::Geometry; - geom->setName( p.getId() ); geom->setUserValue("cot_type", geometry.getTypeAsString()); - - // Vertices osg::Vec3Array* vertices = new osg::Vec3Array; - const std::vector& vert = p.getVertices(); - vertices->reserve( vert.size() ); - for ( unsigned int k = 0; k < vert.size(); k++ ) + osg::ref_ptr tex = new osg::Vec2Array; + tex->reserve(3); + vertices->reserve(3); + std::vector indicesVec; + indicesVec.reserve(2); + + for (unsigned int j = 0; j < geometry.getPolygonsCount(); j++) { - TVec3d v = vert[k]; - osg::Vec3d pt = osg::Vec3d( v.x, v.y, v.z ) - offset; - vertices->push_back( pt ); - } + const citygml::Polygon& p = *geometry.getPolygon(j); + const auto citygmlTex = p.getTextureFor(settings._theme); - geom->setVertexArray( vertices ); + if (p.getIndices().size() == 0) continue; - // Indices - osg::DrawElementsUInt* indices = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, p.getIndices().begin(), p.getIndices().end()); - geom->addPrimitiveSet( indices ); + // Geometry management + + if (texName != "axaxaxax" && (citygmlTex != nullptr && (citygmlTex->getUrl() != texName)) || (citygmlTex == nullptr && (texName != ""))) + { + + geom->setVertexArray(vertices); + if (tex->size() > 0) + geom->setTexCoordArray(0, tex); + + // Indices + osg::DrawElementsUInt* indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, indicesVec.begin(), indicesVec.end()); + geom->addPrimitiveSet(indices); + indicesVec.clear(); - // Appearance + // Appearance - osg::ref_ptr stateset = geom->getOrCreateStateSet(); + osg::ref_ptr stateset = geom->getOrCreateStateSet(); - setMaterial(stateset, p, settings); - setTexture(stateset, geom, p, settings); + setMaterial(stateset, p, settings); + setTextureOnly(stateset, geom, settings,citygmlTex); #if OSG_VERSION_GREATER_OR_EQUAL(3,3,2) - if (settings._storeGeomIDs) { - geom->addDescription(p.getId()); + if (settings._storeGeomIDs) { + geom->addDescription(p.getId()); + } +#endif + + + geometryContainer->addDrawable(geom); + // create new Geometry + geom = new osg::Geometry; + geom->setUserValue("cot_type", geometry.getTypeAsString()); + vertices = new osg::Vec3Array; + tex = new osg::Vec2Array; + vertices->reserve(3); + tex->reserve(3); + } + + if (citygmlTex == nullptr) + texName = ""; + else + texName = citygmlTex->getUrl(); + geom->setName(p.getId()); + + + GLuint startIndex = vertices->size(); + for (const auto& i : p.getIndices()) + { + indicesVec.push_back(i+ startIndex); + } + + // Vertices + const std::vector& vert = p.getVertices(); + for (unsigned int k = 0; k < vert.size(); k++) + { + TVec3d v = vert[k]; + osg::Vec3d pt = osg::Vec3d(v.x, v.y, v.z) - offset; + vertices->push_back(pt); + } + //texcoords + + + + const std::vector& texCoords = p.getTexCoordsForTheme(settings._theme, true); + + if (!texCoords.empty()) { + for (unsigned int k = 0; k < texCoords.size(); k++) + tex->push_back(osg::Vec2(texCoords[k].x, texCoords[k].y)); + } + + + + + + } + if (vertices->size()) + { + const citygml::Polygon& p = *geometry.getPolygon(geometry.getPolygonsCount() - 1); + geom->setVertexArray(vertices); + if (tex->size() > 0) + geom->setTexCoordArray(0, tex); + + // Indices + osg::DrawElementsUInt* indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, indicesVec.begin(), indicesVec.end()); + geom->addPrimitiveSet(indices); + + // Appearance + + osg::ref_ptr stateset = geom->getOrCreateStateSet(); + + setMaterial(stateset, p, settings); + const auto citygmlTex = p.getTextureFor(settings._theme); + setTextureOnly(stateset, geom, settings,citygmlTex); + +#if OSG_VERSION_GREATER_OR_EQUAL(3,3,2) + if (settings._storeGeomIDs) { + geom->addDescription(p.getId()); + } #endif - geometryContainer->addDrawable( geom ); + geometryContainer->addDrawable(geom); + } } // Parse child geoemtries @@ -501,55 +663,113 @@ void createOsgGeometryFromCityGMLGeometry(const citygml::Geometry& geometry, Cit } } -void ReaderWriterCityGML::createSingleOsgGeometryFromCityGMLGeometry(const citygml::CityObject& object, const citygml::Geometry& geometry, CityGMLSettings& settings, wallRoofObj &wr, const osg::Vec3d& offset) const +void ReaderWriterCityGML::createSingleOsgGeometryFromCityGMLGeometry(const citygml::CityObject& object, const citygml::Geometry& geometry, CityGMLSettings& settings, const osg::Vec3d& offset) const { for (unsigned int j = 0; j < geometry.getPolygonsCount(); j++) { const citygml::Polygon& p = *geometry.getPolygon(j); + const auto citygmlTex = p.getTextureFor(settings._theme); if (p.getIndices().size() == 0) continue; const std::vector& vert = p.getVertices(); + materialArrays* arrays = nullptr; if (object.getType() == citygml::CityObject::CityObjectsType::COT_RoofSurface) { - GLuint startIndex = wr.verticesRoof->size(); - for (const auto& i : p.getIndices()) - { - wr.indicesRoof.push_back(i+startIndex); - } - - for (unsigned int k = 0; k < vert.size(); k++) + } + if (citygmlTex) { - TVec3d v = vert[k]; - osg::Vec3d pt = osg::Vec3d(v.x, v.y, v.z) - offset; - wr.verticesRoof->push_back(pt); + auto it = ma.find(citygmlTex->getUrl()); + if (it != ma.end()) + arrays = it->second; + else + { + arrays = new materialArrays(); + arrays->textureName = citygmlTex->getUrl(); + ma[arrays->textureName] = arrays; + + if (settings._textureMap.find(citygmlTex->getUrl()) == settings._textureMap.end()) { + std::string fullPath = osgDB::findDataFile(citygmlTex->getUrl()); + + if (fullPath.empty()) { + osg::notify(osg::NOTICE) << " Texture file " << citygmlTex->getUrl() << " not found..." << std::endl; + return; + } + + // Load a new texture + osg::notify(osg::NOTICE) << " Loading texture " << fullPath << "..." << std::endl; + + osg::Image* image = osgDB::readImageFile(citygmlTex->getUrl()); + + if (!image) { + osg::notify(osg::NOTICE) << " Warning: Failed to read Texture " << fullPath << std::endl; + return; + } + + arrays->texture = new osg::Texture2D; + arrays->texture->setImage(image); + arrays->texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); + arrays->texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); + arrays->texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + arrays->texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + arrays->texture->setWrap(osg::Texture::WRAP_R, osg::Texture::REPEAT); + + settings._textureMap[citygmlTex->getUrl()] = arrays->texture; + } + else { + arrays->texture = settings._textureMap[citygmlTex->getUrl()]; + } + } } - } - if (object.getType() == citygml::CityObject::CityObjectsType::COT_WallSurface) - { - GLuint startIndex = wr.verticesWall->size(); - for (const auto& i : p.getIndices()) + else { - wr.indicesWall.push_back(i + startIndex); + if (object.getType() == citygml::CityObject::CityObjectsType::COT_RoofSurface) + { + auto it = ma.find("roof"); + if (it != ma.end()) + arrays = it->second; + } + else if (object.getType() == citygml::CityObject::CityObjectsType::COT_WallSurface) + { + auto it = ma.find("wall"); + if (it != ma.end()) + arrays = it->second; + } } - - for (unsigned int k = 0; k < vert.size(); k++) + if(arrays) { - TVec3d v = vert[k]; - osg::Vec3d pt = osg::Vec3d(v.x, v.y, v.z) - offset; - wr.verticesWall->push_back(pt); + GLuint startIndex = arrays->vertices->size(); + for (const auto& i : p.getIndices()) + { + arrays->indices.push_back(i + startIndex); + } + + for (unsigned int k = 0; k < vert.size(); k++) + { + TVec3d v = vert[k]; + osg::Vec3d pt = osg::Vec3d(v.x, v.y, v.z) - offset; + arrays->vertices->push_back(pt); + } + if (citygmlTex) + { + const std::vector& texCoords = p.getTexCoordsForTheme(settings._theme, true); + + if (!texCoords.empty()) { + for (unsigned int k = 0; k < texCoords.size(); k++) + arrays->texCoords->push_back(osg::Vec2(texCoords[k].x, texCoords[k].y)); + } + } } - } // Indices - osg::DrawElementsUInt* indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, p.getIndices().begin(), p.getIndices().end()); + //osg::DrawElementsUInt* indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, p.getIndices().begin(), p.getIndices().end()); } // Parse child geoemtries for (unsigned int i = 0; i < geometry.getGeometriesCount(); i++) { - createSingleOsgGeometryFromCityGMLGeometry(object, geometry.getGeometry(i), settings, wr, offset); + createSingleOsgGeometryFromCityGMLGeometry(object, geometry.getGeometry(i), settings, offset); } } @@ -572,6 +792,7 @@ bool ReaderWriterCityGML::createCityObject(const citygml::CityObject& object, Ci unsigned int highestLOD = ReaderWriterCityGML::getHighestLodForObject(object); + bool gotGeometry = false; for ( unsigned int i = 0; i < object.getGeometriesCount(); i++ ) { const citygml::Geometry& geometry = object.getGeometry( i ); @@ -581,7 +802,7 @@ bool ReaderWriterCityGML::createCityObject(const citygml::CityObject& object, Ci if (settings._useMaxLODOnly && (currentLOD < highestLOD || currentLOD < minimumLODToConsider )){ continue; } - + gotGeometry = true; createOsgGeometryFromCityGMLGeometry(geometry, settings, geode, offset); } @@ -620,14 +841,16 @@ bool ReaderWriterCityGML::createCityObject(const citygml::CityObject& object, Ci geodeSS->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } - - for ( unsigned int i = 0; i < object.getChildCityObjectsCount(); ++i ) - createCityObject( object.getChildCityObject(i), settings, grp, offset, highestLOD); + if(!gotGeometry) + { + for (unsigned int i = 0; i < object.getChildCityObjectsCount(); ++i) + createCityObject(object.getChildCityObject(i), settings, grp, offset, highestLOD); + } return true; } -bool ReaderWriterCityGML::createSingleCityObject(const citygml::CityObject& object, CityGMLSettings& settings, wallRoofObj& wr, const osg::Vec3d& offset, unsigned int minimumLODToConsider) const +bool ReaderWriterCityGML::createSingleCityObject(const citygml::CityObject& object, CityGMLSettings& settings, const osg::Vec3d& offset, unsigned int minimumLODToConsider) const { osg::ref_ptr roof_color = new osg::Vec4Array; roof_color->push_back(osg::Vec4(0.9f, 0.1f, 0.1f, 1.0f)); @@ -644,7 +867,7 @@ bool ReaderWriterCityGML::createSingleCityObject(const citygml::CityObject& obje continue; } - createSingleOsgGeometryFromCityGMLGeometry(object,geometry, settings, wr, offset); + createSingleOsgGeometryFromCityGMLGeometry(object,geometry, settings, offset); } @@ -654,7 +877,7 @@ bool ReaderWriterCityGML::createSingleCityObject(const citygml::CityObject& obje } for (unsigned int i = 0; i < object.getChildCityObjectsCount(); ++i) - createSingleCityObject(object.getChildCityObject(i), settings, wr, offset, highestLOD); + createSingleCityObject(object.getChildCityObject(i), settings, offset, highestLOD); return true; } From 91ee10f58d009c76aac605adc4bb0c242f0d4e1a Mon Sep 17 00:00:00 2001 From: Uwe Woessner Date: Wed, 4 Mar 2020 18:44:17 +0100 Subject: [PATCH 5/6] linux copile fix --- osgplugin/ReaderWriterCityGML.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osgplugin/ReaderWriterCityGML.cpp b/osgplugin/ReaderWriterCityGML.cpp index 445db4db..ff74dcb9 100644 --- a/osgplugin/ReaderWriterCityGML.cpp +++ b/osgplugin/ReaderWriterCityGML.cpp @@ -130,7 +130,7 @@ class materialArrays { public: - materialArrays::materialArrays(int sizehint = 3) + materialArrays(int sizehint = 3) { texCoords = new osg::Vec2Array; vertices = new osg::Vec3Array; @@ -140,7 +140,7 @@ class materialArrays texCoords->reserve(sizehint); texture = nullptr; } - materialArrays::~materialArrays() + ~materialArrays() { } osg::Texture2D* texture; From 7de7603e581dcc5c5bada2e078aa9b51cc1bd6c2 Mon Sep 17 00:00:00 2001 From: Uwe Woessner Date: Sun, 7 Jul 2024 11:43:44 +0200 Subject: [PATCH 6/6] readObject --- osgplugin/ReaderWriterCityGML.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osgplugin/ReaderWriterCityGML.cpp b/osgplugin/ReaderWriterCityGML.cpp index ff74dcb9..c3fc6f65 100644 --- a/osgplugin/ReaderWriterCityGML.cpp +++ b/osgplugin/ReaderWriterCityGML.cpp @@ -176,6 +176,21 @@ class ReaderWriterCityGML : public osgDB::ReaderWriter virtual ReadResult readNode( const std::string&, const osgDB::ReaderWriter::Options* ) const override; virtual ReadResult readNode( std::istream&, const osgDB::ReaderWriter::Options* ) const override; + virtual ReadResult readObject(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const + { + ReadResult result = readNode(fileName, options); + osg::Node* node = result.getNode(); + if (node) return node; + else return result; + } + + virtual ReadResult readObject(std::istream& fin, const Options* options) const + { + ReadResult result = readNode(fin, options); + osg::Node* node = result.getNode(); + if (node) return node; + else return result; + } private: std::shared_ptr m_logger;