Skip to content
This repository was archived by the owner on Sep 10, 2025. It is now read-only.

Commit 632c470

Browse files
author
Kyq
committed
From issue tumcms#98
1 parent 6204260 commit 632c470

5 files changed

Lines changed: 176 additions & 117 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ Documentation/doxymentation/*
2121

2222
.vscode
2323

24+
UserInterface/ViewPanel/ViewportDOTcpp
25+
UserInterface/ViewPanel/Effects/IfcGeometryEffectDOTh
26+
UserInterface/ViewPanel/Effects/IfcGeometryEffectDOTcpp
27+
Core/src/IfcGeometryConverter/ConverterBuwDOTh

Core/src/IfcGeometryConverter/ConverterBuw.h

Lines changed: 99 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,17 @@
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)
613632
EMBED_CORE_IFCGEOMETRYCONVERTER_INTO_OIP_NAMESPACE(IfcGeometryModel)
614633

615-
#endif
634+
#endif

0 commit comments

Comments
 (0)