11/*
22 Copyright (c) 2018 Technical University of Munich
33 Chair of Computational Modeling and Simulation.
4-
54 TUM Open Infra Platform is free software; you can redistribute it and/or modify
65 it under the terms of the GNU General Public License Version 3
76 as published by the Free Software Foundation.
8-
97 TUM Open Infra Platform is distributed in the hope that it will be useful,
108 but WITHOUT ANY WARRANTY; without even the implied warranty of
119 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1210 GNU General Public License for more details.
13-
1411 You should have received a copy of the GNU General Public License
1512 along with this program. If not, see <http://www.gnu.org/licenses/>.
1613*/
1714
18-
19- /* Kike. April, 2020. Modified code to pass colour information for rendering.
20- In the original version, colours are assigned per triangle and type of object, eg. all the triangles in all the wall objects are rendered in gray.
21- Therefore, a random colour is produced before rendering each mesh inside meshSet to colour all the faces (i.e. triangles) of an object. Applied to walls
22-
23- */
24-
25-
26-
2715// visual studio
2816#pragma once
2917// unix
@@ -52,22 +40,89 @@ namespace OpenInfraPlatform
5240 namespace Core
5341 {
5442 namespace IfcGeometryConverter {
43+ /* !
44+ \brief Internal implementation of a bounding box.
45+ This is a wrapper around the carve's aabb (axis-aligned bounding box).
46+ */
47+ struct BoundingBox : public carve ::geom::aabb<3 > {
48+ using base = carve::geom::aabb<3 >;
49+ public:
50+ // ! constructor
51+ BoundingBox () { reset (); }
52+ /* !
53+ * \brief updates the bounding box extent
54+ *
55+ * \param[in] x the x-coordinate of the point
56+ * \param[in] y the y-coordinate of the point
57+ * \param[in] z the z-coordinate of the point
58+ */
59+ void update (const float x, const float y, const float z)
60+ {
61+ if (isEmpty ())
62+ {
63+ base::fit ( carve::geom::VECTOR (x, y, z));
64+ isFirst = false ;
65+ }
66+ else
67+ update ( base ( carve::geom::VECTOR ( x, y, z ), base::mid () ) );
68+ }
69+ /* !
70+ * \brief updates the bounding box extent
71+ *
72+ * \param[in] other the other bounding box to update self with
73+ */
74+ void update (const base& other)
75+ {
76+ if (other.isEmpty ())
77+ return ;
78+
79+ if (isEmpty ())
80+ {
81+ base::operator =( other );
82+ isFirst = false ;
83+ }
84+ else
85+ base::unionAABB ( other );
86+ }
87+ // ! resets the bounding box to zero
88+ void reset () { base::empty (); isFirst = true ; }
89+ // ! is the bounding box empty?
90+ bool isEmpty () { return isFirst && base::isEmpty (); }
91+ // ! returns the min-max extents
92+ std::string toString () const {
93+ return " min: (" + std::to_string (min ().x ()) + " , " + std::to_string (min ().y ()) + " , " + std::to_string (min ().z ())
94+ + " ) max: (" + std::to_string (max ().x ()) + " , " + std::to_string (max ().y ()) + " , " + std::to_string (max ().z ()) + " )" ;
95+ }
96+ // ! returns the center point of the bounding box
97+ buw::Vector3d center () const { return buw::Vector3d ( base::mid ().x , base::mid ().y , base::mid ().z ); }
98+ // ! returns the smallest point of the bounding box
99+ buw::Vector3d min () const { return buw::Vector3d ( base::min ().x , base::min ().y , base::min ().z ); }
100+ // ! returns the maximal point of the bounding box
101+ buw::Vector3d max () const { return buw::Vector3d ( base::max ().x , base::max ().y , base::max ().z ); }
102+ // ! carve::geom::aabb doesn't have a "not set" value, but rather everything is 0,0,0 per default. This variable helps overcome this.
103+ bool isFirst = true ;
104+ };
105+
55106 struct IndexedMeshDescription {
56107 std::vector<uint32_t > indices;
57108 std::vector<VertexLayout> vertices;
58109 bool isEmpty () { return (indices.size () == 0 && vertices.size () == 0 ); };
110+ void reset () { indices.clear (); vertices.clear (); }
59111 };
60112
61113 struct PolylineDescription {
62114 std::vector<uint32_t > indices;
63115 std::vector<buw::Vector3f> vertices;
64116 bool isEmpty () { return (indices.size () == 0 && vertices.size () == 0 ); };
117+ void reset () { indices.clear (); vertices.clear (); }
65118 };
66119
67120 struct IfcGeometryModel {
121+ BoundingBox bb_;
68122 IndexedMeshDescription meshDescription_;
69123 PolylineDescription polylineDescription_;
70124 bool isEmpty () { return (meshDescription_.isEmpty () && polylineDescription_.isEmpty ()); };
125+ void reset () { bb_.reset (); meshDescription_.reset (); polylineDescription_.reset (); }
71126 };
72127
73128
@@ -97,9 +152,8 @@ namespace OpenInfraPlatform
97152 static bool insertFaceIntoBuffers (const std::shared_ptr<typename IfcEntityTypesT::IfcProduct>& product,
98153 const carve::mesh::Face<3 >* face,
99154 std::vector<VertexLayout>& vertices,
100- std::vector<uint32_t >& indices, buw::Vector3f colour) // Kike. Added colour to pass colour info
155+ std::vector<uint32_t >& indices)
101156 {
102-
103157 const int32_t numVertices = face->nVertices ();
104158
105159 if (numVertices > 4 ) {
@@ -109,7 +163,7 @@ namespace OpenInfraPlatform
109163 }
110164
111165 // determine color
112- buw::Vector3f color = determineColorFromBaseTypes (product, colour); // Kike. Added colour
166+ buw::Vector3f color = determineColorFromBaseTypes (product);
113167 // if (color.w() <= FullyTransparentAlphaThreshold) {
114168 // return false; //skip fully transparent vertices
115169 // }
@@ -192,10 +246,8 @@ namespace OpenInfraPlatform
192246 static bool insertMeshIntoBuffers (const std::shared_ptr<typename IfcEntityTypesT::IfcProduct>& product,
193247 const carve::mesh::Mesh<3 >* mesh,
194248 std::vector<VertexLayout>& vertices,
195- std::vector<uint32_t >& indices, buw::Vector3f colour) // Kike. Added colour
249+ std::vector<uint32_t >& indices)
196250 {
197-
198-
199251 // walk through all faces of the mesh
200252 bool ret = false ;
201253 for (const auto & face : mesh->faces ) {
@@ -205,36 +257,11 @@ namespace OpenInfraPlatform
205257 continue ;
206258 }
207259
208-
209- ret |= insertFaceIntoBuffers (product, face, vertices, indices, colour); // Kike. Added colour
260+ ret |= insertFaceIntoBuffers (product, face, vertices, indices);
210261 }
211262 return ret;
212263 }
213264
214- // Kike. Create a buw::Vector3f with random values between 0 and 1
215- static buw::Vector3f getRandomVector3f () {
216- buw::Vector3f vec;
217-
218- // First create an instance of an engine.
219- std::random_device rnd_device;
220- // Specify the engine and distribution.
221- std::mt19937 mersenne_engine{ rnd_device () }; // Generates random integers
222- std::uniform_real_distribution<float > dist{ 0 , 1 };
223-
224- auto gen = [&dist, &mersenne_engine]() {
225- return dist (mersenne_engine);
226- };
227-
228- std::vector<float > v (3 );
229- std::generate (begin (v), end (v), gen);
230-
231- for (int i = 0 ; i < 3 ; i++)
232- vec[i] = v[i];
233-
234- return vec;
235-
236- }
237-
238265 static bool insertMeshSetIntoBuffers (const std::shared_ptr<typename IfcEntityTypesT::IfcProduct>& product,
239266 const carve::mesh::MeshSet<3 >* meshSet,
240267 std::vector<VertexLayout>& vertices,
@@ -246,13 +273,8 @@ namespace OpenInfraPlatform
246273 }
247274
248275 // walk through all meshes of the mesh set
249-
250276 for (const auto & mesh : meshSet->meshes ) {
251-
252- // Kike. Same colour for all the faces in the mesh
253- buw::Vector3f colour = getRandomVector3f ();
254-
255- ret |= insertMeshIntoBuffers (product, mesh, vertices, indices, colour); // Kike. Added colour
277+ ret |= insertMeshIntoBuffers (product, mesh, vertices, indices);
256278 }
257279 return ret;
258280 }
@@ -366,7 +388,6 @@ namespace OpenInfraPlatform
366388 buw::Vector3f vertex (position[0 ], position[1 ], position[2 ]);
367389
368390 /* const std::string vKey = createVertexKeyLine(vertex);
369-
370391 if (ConverterBuwUtil::vertexMapLines_.find(vKey) == ConverterBuwUtil::vertexMapLines_.end())
371392 {
372393 vertices.push_back(vertex);
@@ -405,20 +426,13 @@ namespace OpenInfraPlatform
405426 // ! NOTE (mk): Could be optimized if we omit cache building and just add triangles (with redundant vertices)
406427
407428 // clear all descriptions
408- auto & meshDescription = ifcGeometryModel->meshDescription_ ;
409- meshDescription.vertices .clear ();
410- meshDescription.indices .clear ();
411-
412- auto & polylineDescription = ifcGeometryModel->polylineDescription_ ;
413- polylineDescription.vertices .clear ();
414- polylineDescription.indices .clear ();
429+ ifcGeometryModel->reset ();
415430
416431 // obtain maximum number of threads supported by machine
417432 const unsigned int maxNumThreads = std::thread::hardware_concurrency ();
418433
419- // gather tasks for all threads
434+ // split up tasks for all threads
420435 std::vector<std::vector<std::shared_ptr<ShapeInputDataT<IfcEntityTypesT>>>> tasks (maxNumThreads);
421-
422436 uint32_t counter = 0 ;
423437 for (auto it = shapeDatas.begin (); it != shapeDatas.end (); ++it) {
424438 std::shared_ptr<ShapeInputDataT<IfcEntityTypesT>> shapeData = it->second ;
@@ -430,7 +444,7 @@ namespace OpenInfraPlatform
430444 std::vector<std::thread> threads (maxNumThreads);
431445 // every thread gets its local triangle/polyline pool
432446 for (unsigned int k = 0 ; k < maxNumThreads; ++k) {
433- threads[k] = std::thread (&ConverterBuwT<IfcEntityTypesT>::createTrianglesJob, tasks[k], k, &meshDescription, &polylineDescription );
447+ threads[k] = std::thread (&ConverterBuwT<IfcEntityTypesT>::createTrianglesJob, tasks[k], k, ifcGeometryModel );
434448 }
435449
436450 // wait for all threads to be finished
@@ -444,18 +458,18 @@ namespace OpenInfraPlatform
444458
445459 // convert mesh and polyline descriptions to triangles/lines for BlueFramework
446460 static void createTrianglesJob (const std::vector<std::shared_ptr<ShapeInputDataT<IfcEntityTypesT>>>& tasks,
447- int threadID, IndexedMeshDescription* meshDesc, PolylineDescription* polyDesc)
461+ int threadID, buw::ReferenceCounted<IfcGeometryModel>& ifcGeometryModel /* IndexedMeshDescription* meshDesc, PolylineDescription* polyDesc*/ )
448462 {
449463 // #ifdef _DEBUG
450464 // std::cout << "Info\t| IfcGeometryConverter.ConverterBuw: Starting thread " << threadID << " to create triangles and polylines" << std::endl;
451465 // #endif
466+ BoundingBox bb;
452467 IndexedMeshDescription threadMeshDesc;
453468 PolylineDescription threadLineDesc;
454- threadMeshDesc.vertices .clear ();
455- threadMeshDesc.indices .clear ();
456- threadLineDesc.vertices .clear ();
457- threadLineDesc.indices .clear ();
458469
470+ bb.reset ();
471+ threadMeshDesc.reset ();
472+ threadLineDesc.reset ();
459473
460474 for (const auto & shapeData : tasks) {
461475 const std::shared_ptr<typename IfcEntityTypesT::IfcProduct>& product = shapeData->ifc_product ;
@@ -479,22 +493,32 @@ namespace OpenInfraPlatform
479493 }
480494 }
481495
496+ // update the bounding box
497+ for (const auto & vertex : threadMeshDesc.vertices )
498+ bb.update (vertex.position [0 ], vertex.position [1 ], vertex.position [2 ]);
499+ for (const auto & vertex : threadLineDesc.vertices )
500+ bb.update (vertex[0 ], vertex[1 ], vertex[2 ]);
501+
502+ // lock the multithread access to the lists
482503 ConverterBuwUtil::s_geometryMutex.lock ();
483504
484- const uint64_t globalIndexOffsetMesh = meshDesc-> vertices .size ();
485- const uint64_t globalIndexOffsetLines = polyDesc-> vertices .size ();
505+ const uint64_t globalIndexOffsetMesh = ifcGeometryModel-> meshDescription_ . vertices .size ();
506+ const uint64_t globalIndexOffsetLines = ifcGeometryModel-> polylineDescription_ . vertices .size ();
486507
487508 std::for_each (threadMeshDesc.indices .begin (), threadMeshDesc.indices .end (),
488509 [&](uint32_t & index) { index += globalIndexOffsetMesh; });
489510 std::for_each (threadLineDesc.indices .begin (), threadLineDesc.indices .end (),
490511 [&](uint32_t & index) { index += globalIndexOffsetLines; });
491512
492- meshDesc->vertices .insert (meshDesc->vertices .end (), threadMeshDesc.vertices .begin (), threadMeshDesc.vertices .end ());
493- meshDesc->indices .insert (meshDesc->indices .end (), threadMeshDesc.indices .begin (), threadMeshDesc.indices .end ());
494- polyDesc->vertices .insert (polyDesc->vertices .end (), threadLineDesc.vertices .begin (), threadLineDesc.vertices .end ());
495- polyDesc->indices .insert (polyDesc->indices .end (), threadLineDesc.indices .begin (), threadLineDesc.indices .end ());
513+ ifcGeometryModel->meshDescription_ .vertices .insert (ifcGeometryModel->meshDescription_ .vertices .end (), threadMeshDesc.vertices .begin (), threadMeshDesc.vertices .end ());
514+ ifcGeometryModel->meshDescription_ .indices .insert (ifcGeometryModel->meshDescription_ .indices .end (), threadMeshDesc.indices .begin (), threadMeshDesc.indices .end ());
515+ ifcGeometryModel->polylineDescription_ .vertices .insert (ifcGeometryModel->polylineDescription_ .vertices .end (), threadLineDesc.vertices .begin (), threadLineDesc.vertices .end ());
516+ ifcGeometryModel->polylineDescription_ .indices .insert (ifcGeometryModel->polylineDescription_ .indices .end (), threadLineDesc.indices .begin (), threadLineDesc.indices .end ());
517+ ifcGeometryModel->bb_ .update (bb);
496518
519+ // free the access to the lists
497520 ConverterBuwUtil::s_geometryMutex.unlock ();
521+
498522 // #ifdef _DEBUG
499523 // std::cout << "Info\t| IfcGeometryConverter.ConverterBuw: Finished thread " << threadID << std::endl;
500524 // #endif
@@ -503,17 +527,11 @@ namespace OpenInfraPlatform
503527 protected:
504528
505529 static buw::Vector3f determineColorFromBaseTypes (
506- const std::shared_ptr<typename IfcEntityTypesT::IfcProduct>& product, buw::Vector3f colour) // Kike. Added colour to pass data per object and not triangle
530+ const std::shared_ptr<typename IfcEntityTypesT::IfcProduct>& product)
507531 {
508532 if (std::dynamic_pointer_cast<typename IfcEntityTypesT::IfcWindow>(product)) {
509533 return buw::Vector3f (0 .1f , 0 .6f , 1 .0f );// , 0.4f);
510534 }
511- // Kike. Adding colour for walls
512- else if (std::dynamic_pointer_cast<typename IfcEntityTypesT::IfcWall>(product)
513- || std::dynamic_pointer_cast<typename IfcEntityTypesT::IfcWallStandardCase>(product)) {
514- return colour;
515- }
516- //
517535
518536 // Balken
519537 else if (std::dynamic_pointer_cast<typename IfcEntityTypesT::IfcBeam>(product)
@@ -610,6 +628,7 @@ namespace OpenInfraPlatform
610628 }
611629}
612630
631+ EMBED_CORE_IFCGEOMETRYCONVERTER_INTO_OIP_NAMESPACE (BoundingBox)
613632EMBED_CORE_IFCGEOMETRYCONVERTER_INTO_OIP_NAMESPACE(IfcGeometryModel)
614633
615- #endif
634+ #endif
0 commit comments