ChunkBuilder.cpp
Go to the documentation of this file.
1 
37 
38 namespace lvr2
39 {
40 
42  std::shared_ptr<HalfEdgeMesh<BaseVector<float>>> originalMesh,
43  std::shared_ptr<std::unordered_map<unsigned int, std::vector<std::weak_ptr<ChunkBuilder>>>>
44  vertexUse)
45  : m_originalMesh(originalMesh), m_vertexUse(vertexUse)
46 {
47 }
48 
50 
51 void ChunkBuilder::addFace(const FaceHandle& faceHandle)
52 {
53  // add the original index of the face to the chunk with its chunkID
54  m_faces.push_back(faceHandle);
55 
56  std::array<VertexHandle, 3> vertices = m_originalMesh->getVerticesOfFace(faceHandle);
57 
58  // next add the vertices of the face to the chunk
59  for (unsigned int i = 0; i < 3; i++)
60  {
61  std::weak_ptr<ChunkBuilder> thisBuilderPtr(shared_from_this());
62  // if the vertex is not in the vector, we add the vertex (we just mark the vertex by adding
63  // the chunkID)
64  if (m_vertexUse->find(vertices[i].idx()) == m_vertexUse->end())
65  {
66  m_vertexUse->insert({vertices[i].idx(), std::vector<std::weak_ptr<ChunkBuilder>>()});
67  }
68  if (std::find_if(m_vertexUse->at(vertices[i].idx()).begin(),
69  m_vertexUse->at(vertices[i].idx()).end(),
70  [&thisBuilderPtr](const std::weak_ptr<ChunkBuilder>& otherBuilderPtr) {
71  return thisBuilderPtr.lock() == otherBuilderPtr.lock();
72  })
73  == m_vertexUse->at(vertices[i].idx()).end())
74  {
75  m_vertexUse->at(vertices[i].idx()).push_back(shared_from_this());
76 
77  m_numVertices++;
78 
79  if (m_vertexUse->at(vertices[i].idx()).size() == 2)
80  {
81  for (unsigned int j = 0; j < 2; j++)
82  {
83  m_vertexUse->at(vertices[i].idx())[j].lock()->addDuplicateVertex(vertices[i]);
84  }
85  }
86  else if (m_vertexUse->at(vertices[i].idx()).size() > 2)
87  {
88  m_vertexUse->at(vertices[i].idx()).back().lock()->addDuplicateVertex(vertices[i]);
89  }
90  }
91  }
92 }
93 
95 {
96  if (std::find(m_duplicateVertices.begin(), m_duplicateVertices.end(), index)
97  == m_duplicateVertices.end())
98  {
99  m_duplicateVertices.push_back(index);
100  }
101 }
102 
103 unsigned int ChunkBuilder::numFaces() const
104 {
105  return m_faces.size();
106 }
107 
108 unsigned int ChunkBuilder::numVertices() const
109 {
110  return m_numVertices;
111 }
112 
114  MeshBufferPtr attributedMesh,
115  std::shared_ptr<std::unordered_map<unsigned int, unsigned int>> splitVertices,
116  std::shared_ptr<std::unordered_map<unsigned int, unsigned int>> splitFaces) const
117 {
118  std::unordered_map<unsigned int, unsigned int> vertexIndices;
119 
120  lvr2::floatArr vertices(new float[numVertices() * 3]);
121  lvr2::indexArray faceIndices(new unsigned int[numFaces() * 3]);
122 
123  // build new model by adding vertices, faces and attribute channels
125 
126  // TODO: add more types if needed; it is more efficient to sort the channel in the channel manager
127  std::vector<std::string> vertexChannelUChar;
128  std::vector<std::string> vertexChannelUInt;
129  std::vector<std::string> vertexChannelFloat;
130  std::vector<std::string> faceChannelUChar;
131  std::vector<std::string> faceChannelUInt;
132  std::vector<std::string> faceChannelFloat;
133 
134 
135  for (auto elem : *attributedMesh)
136  {
137  if(elem.first != "vertices" && elem.first != "face_indices")
138  {
139  if(elem.second.is_type<unsigned char>())
140  {
141  if(elem.second.numElements() == attributedMesh->numVertices())
142  {
143  mesh->addEmptyUCharChannel(elem.first, numVertices(), elem.second.width());
144  vertexChannelUChar.push_back(elem.first);
145  }
146  else if(elem.second.numElements() == attributedMesh->numFaces())
147  {
148  mesh->addEmptyUCharChannel(elem.first, numFaces(), elem.second.width());
149  faceChannelUChar.push_back(elem.first);
150  }
151  else
152  {
153  // a channel that is not a vertex or a face channel will be added unchanged to each chunk
154  mesh->addUCharChannel(std::make_shared<
155  lvr2::Channel<unsigned char>>(attributedMesh->getUCharChannel(elem.first).get()), elem.first);
156  }
157  }
158  else if(elem.second.is_type<unsigned int>())
159  {
160  if(elem.second.numElements() == attributedMesh->numVertices())
161  {
162  mesh->addEmptyIndexChannel(elem.first, numVertices(), elem.second.width());
163  vertexChannelUInt.push_back(elem.first);
164  }
165  else if(elem.second.numElements() == attributedMesh->numFaces())
166  {
167  mesh->addEmptyIndexChannel(elem.first, numFaces(), elem.second.width());
168  faceChannelUInt.push_back(elem.first);
169  }
170  else
171  {
172  // a channel that is not a vertex or a face channel will be added unchanged to each chunk
173  mesh->addIndexChannel(std::make_shared<
174  lvr2::Channel<unsigned int>>(attributedMesh->getIndexChannel(elem.first).get()), elem.first);
175  }
176  }
177  else if(elem.second.is_type<float>())
178  {
179  if(elem.second.numElements() == attributedMesh->numVertices())
180  {
181  mesh->addEmptyFloatChannel(elem.first, numVertices(), elem.second.width());
182  vertexChannelFloat.push_back(elem.first);
183  }
184  else if(elem.second.numElements() == attributedMesh->numFaces())
185  {
186  mesh->addEmptyFloatChannel(elem.first, numFaces(), elem.second.width());
187  faceChannelFloat.push_back(elem.first);
188  }
189  else
190  {
191  // a channel that is not a vertex or a face channel will be added unchanged to each chunk
192  mesh->addFloatChannel(std::make_shared<
193  lvr2::Channel<float>>(attributedMesh->getFloatChannel(elem.first).get()), elem.first);
194  }
195  }
196  else
197  {
198 
199  }
200 
201  }
202 
203  }
204 
205 
206  // fill vertex buffer with duplicate vertices
207  for (VertexHandle vertex : m_duplicateVertices)
208  {
209  if (vertexIndices.find(vertex.idx()) == vertexIndices.end())
210  {
211  unsigned int vertexIndex = vertexIndices.size();
212  vertexIndices[static_cast<unsigned int>(vertex.idx())] = vertexIndex;
213 
214  // apply vertex position
215  for (uint8_t j = 0; j < 3; j++)
216  {
217  vertices[vertexIndex * 3 + j] = m_originalMesh->getVertexPosition(vertex)[j];
218  }
219 
220  // apply vertex attributes
221  unsigned int attributedVertexIndex = vertex.idx();
222  if (splitVertices->find(attributedVertexIndex) != splitVertices->end())
223  {
224  attributedVertexIndex = splitVertices->at(attributedVertexIndex);
225  }
226 
227 
228  // vertex channels
229  for(const std::string& name : vertexChannelUChar)
230  {
231  Channel<unsigned char> tmp = mesh->getUCharChannel(name).get();
232  for(size_t component = 0; component < tmp.width(); component++)
233  {
234 
235  tmp.dataPtr()[vertexIndex * tmp.width() + component]
236  = attributedMesh->getUCharHandle(attributedVertexIndex, name)[component];
237 
238 // // alternative way using Handles instead of dataPtr():
239 // mesh->getUCharHandle(vertexIndex, name)[component]
240 // = attributedMesh->getFloatHandle(attributedVertexIndex, name)[component];
241  }
242  }
243  for(const std::string& name : vertexChannelUInt)
244  {
245  Channel<unsigned int> tmp = mesh->getIndexChannel(name).get();
246  for(size_t component = 0; component < tmp.width(); component++)
247  {
248  tmp.dataPtr()[vertexIndex * tmp.width() + component]
249  = attributedMesh->getIndexHandle(attributedVertexIndex, name)[component];
250  }
251  }
252  for(const std::string& name : vertexChannelFloat)
253  {
254  Channel<float> tmp = mesh->getFloatChannel(name).get();
255 
256  for(size_t component = 0; component < tmp.width(); component++)
257  {
258  tmp.dataPtr()[vertexIndex * tmp.width() + component]
259  = attributedMesh->getFloatHandle(attributedVertexIndex, name)[component];
260  }
261  }
262  }
263  }
264 
265  // fill new vertex and face buffer
266  for (unsigned int face = 0; face < m_faces.size(); face++)
267  {
268  for (uint8_t faceVertex = 0; faceVertex < 3; faceVertex++)
269  {
270  if (vertexIndices.find(
271  m_originalMesh->getVerticesOfFace(m_faces[face])[faceVertex].idx())
272  == vertexIndices.end())
273  {
274  unsigned int vertexIndex = vertexIndices.size();
275  vertexIndices[static_cast<unsigned int>(
276  m_originalMesh->getVerticesOfFace(m_faces[face])[faceVertex].idx())]
277  = vertexIndex;
278 
279  // apply vertex position
280  for (uint8_t vertexComponent = 0; vertexComponent < 3; vertexComponent++)
281  {
282  vertices[vertexIndex * 3 + vertexComponent]
283  = m_originalMesh->getVertexPosition(m_originalMesh->getVerticesOfFace(
284  m_faces[face])[faceVertex])[vertexComponent];
285  }
286 
287  // apply vertex attributes
288  unsigned int attributedVertexIndex
289  = m_originalMesh->getVerticesOfFace(m_faces[face])[faceVertex].idx();
290  if (splitVertices->find(attributedVertexIndex) != splitVertices->end())
291  {
292  attributedVertexIndex = splitVertices->at(attributedVertexIndex);
293  }
294 
295  // vertex channels
296  for(const std::string& name : vertexChannelUChar)
297  {
298  Channel<unsigned char> tmp = mesh->getUCharChannel(name).get();
299  for(size_t component = 0; component < tmp.width(); component++)
300  {
301  tmp.dataPtr()[vertexIndex * tmp.width() + component]
302  = attributedMesh->getUCharHandle(attributedVertexIndex, name)[component];
303 
304 // // alternative way using Handles instead of dataPtr():
305 // mesh->getUCharHandle(vertexIndex, name)[component]
306 // = attributedMesh->getFloatHandle(attributedVertexIndex, name)[component];
307  }
308  }
309  for(const std::string& name : vertexChannelUInt)
310  {
311  Channel<unsigned int> tmp = mesh->getIndexChannel(name).get();
312  for(size_t component = 0; component < tmp.width(); component++)
313  {
314  tmp.dataPtr()[vertexIndex * tmp.width() + component]
315  = attributedMesh->getIndexHandle(attributedVertexIndex, name)[component];
316  }
317  }
318  for(const std::string& name : vertexChannelFloat)
319  {
320  Channel<float> tmp = mesh->getFloatChannel(name).get();
321 
322  for(size_t component = 0; component < tmp.width(); component++)
323  {
324  mesh->getFloatHandle(vertexIndex, name)[component]
325  = attributedMesh->getFloatHandle(attributedVertexIndex, name)[component];
326  }
327  }
328  }
329 
330  // apply face vertex
331  faceIndices[face * 3 + faceVertex] = vertexIndices[static_cast<unsigned int>(
332  m_originalMesh->getVerticesOfFace(m_faces[face])[faceVertex].idx())];
333  }
334 
335  // apply face attributes
336  unsigned int attributedFaceIndex = m_faces[face].idx();
337  if (splitVertices->find(attributedFaceIndex) != splitVertices->end())
338  {
339  attributedFaceIndex = splitVertices->at(attributedFaceIndex);
340  }
341 
342  // face channels
343  for(const std::string& name : faceChannelUChar)
344  {
345  Channel<unsigned char> tmp = mesh->getUCharChannel(name).get();
346  for(size_t component = 0; component < tmp.width(); component++)
347  {
348  tmp.dataPtr()[face * tmp.width() + component]
349  = attributedMesh->getUCharHandle(attributedFaceIndex, name)[component];
350 
351 // // alternative way using Handles instead of dataPtr():
352 // mesh->getUCharHandle(face, name)[component]
353 // = attributedMesh->getFloatHandle(attibutedFaceIndex, name)[component];
354  }
355  }
356  for(const std::string& name : faceChannelUInt)
357  {
358  Channel<unsigned int> tmp = mesh->getIndexChannel(name).get();
359  for(size_t component = 0; component < tmp.width(); component++)
360  {
361  tmp.dataPtr()[face * tmp.width() + component]
362  = attributedMesh->getIndexHandle(attributedFaceIndex, name)[component];
363  }
364  }
365  for(const std::string& name : faceChannelFloat)
366  {
367  Channel<float> tmp = mesh->getFloatChannel(name).get();
368 
369  for(size_t component = 0; component < tmp.width(); component++)
370  {
371  mesh->getFloatHandle(face, name)[component]
372  = attributedMesh->getFloatHandle(attributedFaceIndex, name)[component];
373  }
374  }
375  }
376 
377  // add vertices and face_indices to the mesh
378  mesh->setVertices(vertices, numVertices());
379  mesh->setFaceIndices(faceIndices, numFaces());
380 
381  mesh->addAtomic<unsigned int>(m_duplicateVertices.size(), "num_duplicates");
382 
383  return mesh;
384 }
385 
386 } // namespace lvr2
size_t width() const
std::vector< VertexHandle > m_duplicateVertices
Handle to access vertices of the mesh.
Definition: Handles.hpp:146
HalfEdgeMesh< Vec > mesh
unsigned int numVertices() const
numVertices amount of vertices ot the resulting mesh
std::shared_ptr< std::unordered_map< unsigned int, std::vector< std::weak_ptr< ChunkBuilder > > > > m_vertexUse
std::shared_ptr< MeshBuffer > MeshBufferPtr
Definition: MeshBuffer.hpp:217
const DataPtr dataPtr() const
void addDuplicateVertex(const VertexHandle &index)
addDuplicateVertex marks a vertex as duplicate
boost::shared_array< unsigned int > indexArray
Definition: DataStruct.hpp:128
boost::shared_array< float > floatArr
Definition: DataStruct.hpp:133
Half-edge data structure implementing the BaseMesh interface.
void addFace(const FaceHandle &index)
assigns a face to the chunk this builder is generating
MeshBufferPtr buildMesh(MeshBufferPtr attributedMesh, std::shared_ptr< std::unordered_map< unsigned int, unsigned int >> splitVertices, std::shared_ptr< std::unordered_map< unsigned int, unsigned int >> splitFaces) const
buildMesh builds a chunk by generating a new mesh buffer
std::shared_ptr< HalfEdgeMesh< BaseVector< float > > > m_originalMesh
std::vector< FaceHandle > m_faces
The MeshBuffer Mesh representation for I/O modules.
Definition: MeshBuffer.hpp:41
unsigned int m_numVertices
ChunkBuilder(std::shared_ptr< HalfEdgeMesh< BaseVector< float >>> originalMesh, std::shared_ptr< std::unordered_map< unsigned int, std::vector< std::weak_ptr< ChunkBuilder >>>> vertexUse)
ChunkBuilder constructs a chun builder that can create individual chunks.
unsigned int numFaces() const
numFaces delivers the number of faces for the chunk
Handle to access faces of the mesh.
Definition: Handles.hpp:140


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:06