From 212c5aeb50f3813ba7f36100024aa4baab01e4a4 Mon Sep 17 00:00:00 2001 From: ifcquery Date: Mon, 29 May 2023 22:59:57 +0200 Subject: [PATCH] update example LoadFileWithGeometryExample --- IfcPlusPlus/src/ifcpp/geometry/ConverterOSG.h | 91 ++++++----- .../src/ifcpp/geometry/SceneGraphUtils.h | 44 ++++++ .../LoadFileWithGeometryExample/src/main.cpp | 141 ++++++++++-------- .../src/gui/TabReadWrite.cpp | 2 - 4 files changed, 169 insertions(+), 109 deletions(-) diff --git a/IfcPlusPlus/src/ifcpp/geometry/ConverterOSG.h b/IfcPlusPlus/src/ifcpp/geometry/ConverterOSG.h index 22186a550..02686529d 100644 --- a/IfcPlusPlus/src/ifcpp/geometry/ConverterOSG.h +++ b/IfcPlusPlus/src/ifcpp/geometry/ConverterOSG.h @@ -236,7 +236,7 @@ class ConverterOSG : public StatusCallback //#define DEBUG_DRAW_NORMALS - static void drawMeshSet(const shared_ptr >& meshset, osg::Geode* geode, double crease_angle, double min_triangle_area, bool add_color_array = false) + void drawMeshSet(const shared_ptr >& meshset, osg::Geode* geode, double crease_angle, double min_triangle_area, bool add_color_array, bool disableBackFaceCulling) { if (!meshset) { @@ -467,6 +467,12 @@ class ConverterOSG : public StatusCallback geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertices_tri->size())); geode->addDrawable(geometry); + // disable back face culling for open meshes + if (disableBackFaceCulling) + { + geometry->getOrCreateStateSet()->setAttributeAndModes(m_cull_back_off.get(), osg::StateAttribute::OFF); + } + #ifdef DEBUG_DRAW_NORMALS osg::ref_ptr vertices_normals = new osg::Vec3Array(); for (size_t i = 0; i < vertices_tri->size(); ++i) @@ -667,7 +673,7 @@ class ConverterOSG : public StatusCallback } } - void applyAppearancesToGroup(const std::vector >& vec_product_appearances, osg::Group* grp) + void applyAppearancesToGroup(const std::vector >& vec_product_appearances, osg::Group* grp, float transparencyOverride) { for (size_t ii = 0; ii < vec_product_appearances.size(); ++ii) { @@ -680,7 +686,7 @@ class ConverterOSG : public StatusCallback if (appearance->m_apply_to_geometry_type == AppearanceData::GEOM_TYPE_SURFACE || appearance->m_apply_to_geometry_type == AppearanceData::GEOM_TYPE_ANY) { osg::ref_ptr item_stateset; - convertToOSGStateSet(appearance, item_stateset); + convertToOSGStateSet(appearance, item_stateset, transparencyOverride); if (item_stateset) { osg::StateSet* existing_item_stateset = grp->getStateSet(); @@ -712,7 +718,7 @@ class ConverterOSG : public StatusCallback mat_in.m[3][0], mat_in.m[3][1], mat_in.m[3][2], mat_in.m[3][3]); } - void convertMeshSets(std::vector > >& vecMeshSets, osg::Geode* geode, size_t ii_item) + void convertMeshSets(std::vector > >& vecMeshSets, osg::Geode* geode, size_t ii_item, bool disableBackfaceCulling) { double min_triangle_area = m_geom_settings->getMinTriangleArea(); double eps = m_geom_settings->getEpsilonCoplanarDistance(); @@ -721,15 +727,12 @@ class ConverterOSG : public StatusCallback { shared_ptr >& item_meshset = vecMeshSets[ii]; - //static void retriangulateMeshSetSimple(shared_ptr >&meshset, bool ignoreResultOpenEdges, GeomProcessingParams & params, size_t retryCount); - double epsCoplanarFacesAngle = eps; double minFaceArea = eps; bool dumpMeshes = false; GeomProcessingParams params(eps, epsCoplanarFacesAngle, minFaceArea, dumpMeshes); MeshOps::retriangulateMeshSetSimple(item_meshset, true, params, 0); - //osg::ref_ptr geode = item_group;//new osg::Geode(); - drawMeshSet(item_meshset, geode, crease_angle, min_triangle_area); + drawMeshSet(item_meshset, geode, crease_angle, min_triangle_area, false, disableBackfaceCulling); if (m_render_crease_edges) { @@ -748,7 +751,6 @@ class ConverterOSG : public StatusCallback void convertGeometricItem(const shared_ptr& item_data, shared_ptr& ifc_product, size_t ii_representation, size_t ii_item, osg::Group* parentNode, float transparencyOverride) { - bool includeChildren = false; if (item_data->hasGeometricRepresentation(includeChildren)) { @@ -760,29 +762,27 @@ class ConverterOSG : public StatusCallback product_guid = ifc_product->m_GlobalId->m_value; } + std::string ifc_entity_type = EntityFactory::getStringForClassID(ifc_product->classID()); std::stringstream strs_product_switch_name; - strs_product_switch_name << product_guid << ":" << EntityFactory::getStringForClassID(ifc_product->classID()) << " group"; + strs_product_switch_name << product_guid << ":" << ifc_entity_type << " group"; std::string product_switch_name = strs_product_switch_name.str(); #ifdef _DEBUG int tag = ifc_product->m_tag; - if (product_guid.compare("3WMG3ehJnBiu4F_L5ltNmO") == 0) + if (product_guid.compare("3WMG3ehJnBiu4F_L5ltNmO") == 0 || ifc_product->classID() == IFC4X3::IFCWINDOW) { int wait = 0; } #endif - // create shape for open shells if (item_data->m_meshsets_open.size() > 0) { - osg::ref_ptr geode_open_meshes = new osg::Geode(); - convertMeshSets(item_data->m_meshsets_open, geode_open_meshes, ii_item); // disable back face culling for open meshes - geode_open_meshes->getOrCreateStateSet()->setAttributeAndModes(m_cull_back_off.get(), osg::StateAttribute::OFF); - item_geode->addChild(geode_open_meshes); + convertMeshSets(item_data->m_meshsets_open, item_geode, ii_item, true); } - convertMeshSets(item_data->m_meshsets, item_geode, ii_item); + // create shape for closed meshes + convertMeshSets(item_data->m_meshsets, item_geode, ii_item, false); // create shape for points const std::vector >& vertex_points = item_data->getVertexPoints(); @@ -862,18 +862,12 @@ class ConverterOSG : public StatusCallback txt->setText(text_str.c_str()); txt->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - osg::ref_ptr geode = new osg::Geode(); - geode->addDrawable(txt); - //representation_switch->addChild(geode); + osg::ref_ptr geodeText = new osg::Geode(); + geodeText->addDrawable(txt); + item_geode->addChild(geodeText); } } - // apply statesets if there are any - if (item_data->m_vec_item_appearances.size() > 0) - { - applyAppearancesToGroup(item_data->m_vec_item_appearances, item_geode); - } - // If anything has been created, add it to the product group if (item_geode->getNumChildren() > 0) { @@ -884,9 +878,22 @@ class ConverterOSG : public StatusCallback } #endif + // apply statesets if there are any + if (item_data->m_vec_item_appearances.size() > 0) + { + applyAppearancesToGroup(item_data->m_vec_item_appearances, item_geode, transparencyOverride); + } + if (transparencyOverride > 0) { - SceneGraphUtils::setMaterialAlpha(item_geode, transparencyOverride, false); + bool hasTriangles = SceneGraphUtils::hasTrianglesWithMaterial(item_geode); + bool createMaterialIfNotExisting = false; + + if (!hasTriangles) + { + createMaterialIfNotExisting = true; + } + SceneGraphUtils::setMaterialAlpha(item_geode, transparencyOverride, createMaterialIfNotExisting ); } parentNode->addChild(item_geode); @@ -898,8 +905,6 @@ class ConverterOSG : public StatusCallback const shared_ptr& child = item_data->m_child_items[i_item]; convertGeometricItem(child, ifc_product, ii_representation, i_item, parentNode, transparencyOverride); } - - } //\brief method convertProductShapeToOSG: creates geometry objects from an IfcProduct object @@ -923,8 +928,7 @@ class ConverterOSG : public StatusCallback product_guid = product_shape->m_entity_guid; auto it_find = m_map_entity_guid_to_switch.find(product_guid); - - if (it_find != m_map_entity_guid_to_switch.end()) + if (it_find == m_map_entity_guid_to_switch.end()) { m_map_entity_guid_to_switch[product_guid] = product_switch; } @@ -937,10 +941,9 @@ class ConverterOSG : public StatusCallback if (!product_shape->m_ifc_object_definition.expired()) { shared_ptr ifc_object_def(product_shape->m_ifc_object_definition); - shared_ptr ifc_product = dynamic_pointer_cast(ifc_object_def); - entityType = EntityFactory::getStringForClassID(ifc_object_def->classID()); - + + shared_ptr ifc_product = dynamic_pointer_cast(ifc_object_def); if (ifc_product) { // enable transparency for certain objects @@ -976,7 +979,7 @@ class ConverterOSG : public StatusCallback } #ifdef _DEBUG - if (product_guid.compare("3WMG3ehJnBiu4F_L5ltNmO") == 0) + if (product_guid.compare("0mmrfTIC96mu8Q5Pb3rKvn") == 0) { int wait = 0; } @@ -1005,7 +1008,7 @@ class ConverterOSG : public StatusCallback // TODO: if no color or material is given, set color 231/219/169 for walls, 140/140/140 for slabs if (product_shape->m_vec_product_appearances.size() > 0) { - applyAppearancesToGroup(product_shape->m_vec_product_appearances, product_transform); + applyAppearancesToGroup(product_shape->m_vec_product_appearances, product_transform, transparencyOverride); } ++m_numConvertedProducts; @@ -1162,15 +1165,15 @@ class ConverterOSG : public StatusCallback progressValueCallback(0.9, "scenegraph"); } - void convertToOSGStateSet(const shared_ptr& appearence, osg::ref_ptr& target_stateset) + void convertToOSGStateSet(const shared_ptr& appearence, osg::ref_ptr& target_stateset, float transparencyOverride) { if (!appearence) { return; } - const float shininess = appearence->m_shininess; - const float transparency = appearence->m_transparency; - const bool set_transparent = appearence->m_set_transparent; + float shininess = appearence->m_shininess; + float transparency = appearence->m_transparency; + bool set_transparent = appearence->m_set_transparent; const float color_ambient_r = appearence->m_color_ambient.r(); const float color_ambient_g = appearence->m_color_ambient.g(); @@ -1187,6 +1190,12 @@ class ConverterOSG : public StatusCallback const float color_specular_b = appearence->m_color_specular.b(); const float color_specular_a = appearence->m_color_specular.a(); + if (transparencyOverride > 0) + { + set_transparent = true; + transparency = transparencyOverride; + } + osg::Vec4f ambientColor(color_ambient_r, color_ambient_g, color_ambient_b, transparency); osg::Vec4f diffuseColor(color_diffuse_r, color_diffuse_g, color_diffuse_b, transparency); osg::Vec4f specularColor(color_specular_r, color_specular_g, color_specular_b, transparency); @@ -1202,7 +1211,7 @@ class ConverterOSG : public StatusCallback target_stateset = new osg::StateSet(); target_stateset->setAttribute(mat, osg::StateAttribute::ON); - if (appearence->m_set_transparent) + if (set_transparent) { mat->setTransparency(osg::Material::FRONT, transparency); target_stateset->setMode(GL_BLEND, osg::StateAttribute::ON); diff --git a/IfcPlusPlus/src/ifcpp/geometry/SceneGraphUtils.h b/IfcPlusPlus/src/ifcpp/geometry/SceneGraphUtils.h index 2e681768d..23f2988ad 100644 --- a/IfcPlusPlus/src/ifcpp/geometry/SceneGraphUtils.h +++ b/IfcPlusPlus/src/ifcpp/geometry/SceneGraphUtils.h @@ -517,6 +517,48 @@ namespace SceneGraphUtils } } } + + inline bool hasTrianglesWithMaterial(osg::Node* node) + { + osg::ref_ptr mat; + osg::StateSet* stateset = node->getStateSet(); + if (stateset) + { + mat = dynamic_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); + } + + osg::Geometry* geom = dynamic_cast(node); + if (geom) + { + for (unsigned int ii = 0; ii < geom->getNumPrimitiveSets(); ++ii) + { + osg::PrimitiveSet* prim = geom->getPrimitiveSet(ii); + + if (prim->getMode() == osg::PrimitiveSet::TRIANGLES || prim->getMode() == osg::PrimitiveSet::QUADS) + { + if (mat) + { + return true; + } + } + } + } + + osg::Group* group = dynamic_cast(node); + if (group) + { + for (unsigned int ii = 0; ii < group->getNumChildren(); ++ii) + { + osg::Node* child_node = group->getChild(ii); + if (hasTrianglesWithMaterial(child_node)) + { + return true; + } + } + } + return false; + } + inline void setMaterialAlpha( osg::Node* node, float alpha, bool create_material_if_not_existing ) { osg::StateSet* stateset = node->getOrCreateStateSet(); @@ -541,6 +583,7 @@ namespace SceneGraphUtils stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } } + osg::Group* group = dynamic_cast( node ); if( group ) { @@ -551,6 +594,7 @@ namespace SceneGraphUtils } } } + inline void removeChildren( osg::Group* group ) { if( group ) diff --git a/examples/LoadFileWithGeometryExample/src/main.cpp b/examples/LoadFileWithGeometryExample/src/main.cpp index e9dc2f06b..e2b4686ca 100644 --- a/examples/LoadFileWithGeometryExample/src/main.cpp +++ b/examples/LoadFileWithGeometryExample/src/main.cpp @@ -161,6 +161,67 @@ shared_ptr resolveTreeItems(shared_ptr obj, std:: return item; } +void resolveShapeData(shared_ptr& shapeData) +{ + carve::math::Matrix localTransform = shapeData->getTransform(); + + // traverse geometry + for (auto geometricItem : shapeData->m_geometric_items) + { + // closed meshes + for (auto meshset : geometricItem->m_meshsets) + { + std::vector >& vertexData = meshset->vertex_storage; + for (auto mesh : meshset->meshes) + { + for (auto face : mesh->faces) + { + carve::mesh::Edge<3>* edge = face->edge; + for (size_t ii = 0; ii < face->n_edges; ++ii) + { + carve::mesh::Vertex<3>* vertex = edge->vert; + carve::geom::vector<3> pointLocal = vertex->v; + carve::geom::vector<3> pointGlobal = localTransform * pointLocal; + double x = pointGlobal.x; + double y = pointGlobal.y; + double z = pointGlobal.z; + std::cout << "point in mesh: (" << x << "/" << y << "/" << z << ")" << std::endl; + } + } + } + } + + // open meshes + for (auto meshset : geometricItem->m_meshsets_open) + { + std::vector >& vertexData = meshset->vertex_storage; + for (auto mesh : meshset->meshes) + { + for (auto face : mesh->faces) + { + carve::mesh::Edge<3>* edge = face->edge; + for (size_t ii = 0; ii < face->n_edges; ++ii) + { + carve::mesh::Vertex<3>* vertex = edge->vert; + carve::geom::vector<3> pointLocal = vertex->v; + carve::geom::vector<3> pointGlobal = localTransform * pointLocal; + double x = pointGlobal.x; + double y = pointGlobal.y; + double z = pointGlobal.z; + std::cout << "point in mesh: (" << x << "/" << y << "/" << z << ")" << std::endl; + } + } + } + } + } + + for (auto child_object : shapeData->m_vec_children) + { + resolveShapeData(child_object); + } +} + + int main() { // 1: create an IFC model and a reader for IFC files in STEP format: @@ -195,86 +256,34 @@ int main() // 3: get a flat map of all loaded IFC entities with geometry: const std::map >& map_entities = geometry_converter->getShapeInputData(); + shared_ptr shapeDataIfcProject; for (auto it : map_entities) { shared_ptr shapeData = it.second; - shared_ptr ifcObject; - if( !shapeData->m_ifc_object_definition.expired() ) + if (shapeData->m_ifc_object_definition.expired()) { - ifcObject = shared_ptr(shapeData->m_ifc_object_definition); - } - - // check for certain type of the entity: - shared_ptr ifc_root = dynamic_pointer_cast(ifcObject); - if (ifc_root) - { - // access attributes: - if (ifc_root->m_GlobalId) - { - std::cout << "Entity with GUID: " << ifc_root->m_GlobalId->m_value << std::endl; - } + continue; } - carve::math::Matrix localTransform = shapeData->getTransform(); + shared_ptr ifcObject = shared_ptr(shapeData->m_ifc_object_definition); - // traverse geometry - for( auto representation : shapeData->m_vec_representations ) + // check for certain type of the entity: + shared_ptr ifc_project = dynamic_pointer_cast(ifcObject); + if (ifc_project) { - // representation can be a bounding box, text, 2D geometry, or 3D geometry - for( auto representationItem : representation->m_vec_item_data ) - { - // closed meshes - for( auto meshset : representationItem->m_meshsets ) - { - std::vector >& vertexData = meshset->vertex_storage; - for( auto mesh : meshset->meshes ) - { - for( auto face : mesh->faces ) - { - carve::mesh::Edge<3>* edge = face->edge; - for( size_t ii = 0; ii < face->n_edges; ++ii ) - { - carve::mesh::Vertex<3>* vertex = edge->vert; - carve::geom::vector<3> pointLocal = vertex->v; - carve::geom::vector<3> pointGlobal = localTransform*pointLocal; - double x = pointGlobal.x; - double y = pointGlobal.y; - double z = pointGlobal.z; - std::cout << "point in mesh: (" << x << "/" << y << "/" << z << ")" << std::endl; - } - } - } - } - - // open meshes - for( auto meshset : representationItem->m_meshsets_open ) - { - std::vector >& vertexData = meshset->vertex_storage; - for( auto mesh : meshset->meshes ) - { - for( auto face : mesh->faces ) - { - carve::mesh::Edge<3>* edge = face->edge; - for( size_t ii = 0; ii < face->n_edges; ++ii ) - { - carve::mesh::Vertex<3>* vertex = edge->vert; - carve::geom::vector<3> pointLocal = vertex->v; - carve::geom::vector<3> pointGlobal = localTransform * pointLocal; - double x = pointGlobal.x; - double y = pointGlobal.y; - double z = pointGlobal.z; - std::cout << "point in mesh: (" << x << "/" << y << "/" << z << ")" << std::endl; - } - } - } - } - } + shapeDataIfcProject = shapeData; + break; } + } + if (shapeDataIfcProject) + { + resolveShapeData(shapeDataIfcProject); } + // 4: traverse tree structure of model, starting at root object (IfcProject) shared_ptr ifc_project = ifc_model->getIfcProject(); std::unordered_set set_visited; diff --git a/examples/SimpleViewerExampleQt/src/gui/TabReadWrite.cpp b/examples/SimpleViewerExampleQt/src/gui/TabReadWrite.cpp index c239bae35..722bee62c 100644 --- a/examples/SimpleViewerExampleQt/src/gui/TabReadWrite.cpp +++ b/examples/SimpleViewerExampleQt/src/gui/TabReadWrite.cpp @@ -304,8 +304,6 @@ void TabReadWrite::loadIfcFile( QString& path_in ) converter_osg->setMessageTarget(geometry_converter.get()); converter_osg->convertToOSG(geometry_converter->getShapeInputData(), model_switch); - - if (model_switch) { bool optimize = true;