LVRChunkedMeshBridge.cpp
Go to the documentation of this file.
2 
3 #include <vtkSmartPointer.h>
4 #include <vtkPolyData.h>
5 #include <vtkCellArray.h>
6 #include <vtkPoints.h>
7 #include <vtkActor.h>
8 #include <vtkTriangle.h>
9 #include <vtkProperty.h>
10 #include <vtkImageData.h>
11 #include <vtkTexture.h>
12 #include <vtkFloatArray.h>
13 #include <vtkPointData.h>
14 #include <vtkCellData.h>
15 
16 
17 #include "LVRBoundingBoxBridge.hpp"
18 #include <vtkPolyDataMapper.h>
19 
20 
21 #include <chrono>
22 #include <queue>
23 using namespace lvr2;
24 
25 
26 LVRChunkedMeshBridge::LVRChunkedMeshBridge(std::string file, vtkSmartPointer<vtkRenderer> renderer, std::vector<std::string> layers, size_t cache_size) : m_chunkManager(file, cache_size), m_renderer(renderer), m_layers(layers), m_cacheSize(cache_size)
27 {
28  getNew_ = false;
29  running_ = true;
30  worker = std::thread(&LVRChunkedMeshBridge::highResWorker, this);
31 
32 }
33 
34 
36 {
37  while(running_)
38  {
39  std::unique_lock<std::mutex> l(mutex);
40  while(!getNew_)
41  {
42  cond_.wait(l);
43  }
44  getNew_ = false;
45  std::vector<size_t> visible_indices = m_highResIndices;
46  std::vector<BaseVector<float> > visible_centroids = m_highResCentroids;
47  // delta for new fetch
48  // basically prevents an endless loop of reloads.
50  if(!(std::abs(diff[0]) > 1.0 || std::abs(diff[1]) > 1.0 || std::abs(diff[2]) > 1.0))
51  {
52  l.unlock();
53  continue;
54  }
56  l.unlock();
57 
58  // Needed for consistency for underlying buffers of actors.
59  // see below.
60  auto old_highRes = m_highRes;
61  m_highRes.clear();
62 
63  // check if there is only one layer.
64  // if yes use the chunks from the "lowRes" layer.
65  if(m_layers.size() > 1)
66  {
68  }
69  else
70  {
71  for(auto& index : visible_indices)
72  {
73  m_highRes.insert({index, m_chunks[index]});
74  }
75  }
76 
77  // Consistency for underlying buffers of actors.
78  // The chunkmanagers may have loaded new meshbuffers while we use old ones
79  // Use the old ones otherwise we need to rebuild and copy the actors.
80  // New ones are ignored in that case.
81  for(auto& it : m_highRes)
82  {
83  if(old_highRes.find(it.first) != old_highRes.end())
84  {
85  m_highRes.at(it.first) = old_highRes.at(it.first);
86  // TODO Not clearing may result in duplicates.
87  //old_highRes.erase(it.first);
88  }
89  }
90 
91  // This should be a cache based on 2 queues
92  // and the distance of the centroids of the chunk to the current frustum centroid.
93  size_t numCopy = m_cacheSize - m_highResIndices.size();
94  if(numCopy > 0)
95  {
96  // This is the caching based on the distance of the centroids
97  // to the centroids from the current visible region.
98  // ALL this is far from optimal.
99  typedef std::pair<float, size_t> IndexPair;
100  typedef std::pair<float, BaseVector<float> > CentroidPair;
101  std::priority_queue<IndexPair, std::vector<IndexPair>, CompareDistancePair<size_t> > index_queue;
102  std::priority_queue<CentroidPair, std::vector<CentroidPair>, CompareDistancePair<BaseVector<float> > > centroid_queue;
104  if(m_lastCentroids.size() > 0)
105  {
106  float distance = m_lastCentroids[0].distance(center);
107  index_queue.push({distance, m_lastIndices[0]});
108  centroid_queue.push({distance, m_lastCentroids[0]});
109  for(size_t i = 1; i < m_lastCentroids.size(); ++i)
110  {
111 
112  float distance = m_lastCentroids[i].distance(center);
113  if(index_queue.size() < numCopy)
114  {
115  centroid_queue.push({distance, m_lastCentroids[i]});
116  index_queue.push({distance, m_lastIndices[i]});
117  }
118  else if(index_queue.top().first > distance)
119  {
120  index_queue.pop();
121  index_queue.push({distance, m_lastIndices[i]});
122  centroid_queue.pop();
123  centroid_queue.push({distance, m_lastCentroids[i]});
124  }
125  }
126  }
127 
128  m_lastIndices.clear();
129  m_lastCentroids.clear();
130 
131  // add current visible to cache
132  for(size_t i = 0; i < visible_indices.size(); ++i)
133  {
134  m_lastIndices.push_back(visible_indices[i]);
135  m_lastCentroids.push_back(visible_centroids[i]);
136 
137  }
138 
139  // Build new cache.
140  while(!index_queue.empty())
141  {
142  size_t index = index_queue.top().second;
143  // here is the error it maybe already present in highres
144  // and deleted from old_highres....
145  index_queue.pop();
146  m_highRes.insert({index, old_highRes[index]});
147  m_lastIndices.push_back(index);
148  auto centroid = centroid_queue.top().second;
149  centroid_queue.pop();
150  m_lastCentroids.push_back(centroid);
151  }
152  }
153 
154  // compute and copy actors
155  std::unordered_map<size_t, vtkSmartPointer<vtkActor>> tmp_highResActors;
156  for(auto it = m_highRes.begin(); it != m_highRes.end(); ++it)
157  {
158  auto chunk = *it;
159  size_t id = chunk.first;
160  lvr2::MeshBufferPtr meshbuffer = chunk.second;
161 
162  if(m_highResActors.find(id) == m_highResActors.end())
163  {
164  tmp_highResActors.insert({id, computeMeshActor(id, meshbuffer)});
165  }
166  else
167  {
168  tmp_highResActors.insert({id, m_highResActors[id]});
169  }
170  }
171 
172 
173  // add highres dummies because their maybe lowres chunks
174  // which do not exist in the highres map
175  for(auto& it: visible_indices)
176  {
177  if(tmp_highResActors.find(it) == tmp_highResActors.end())
178  {
179  auto mptr = MeshBufferPtr();
180  tmp_highResActors.insert({it, computeMeshActor(it, mptr)});
181  }
182  }
183 
184  // Syncing with main thread.
185  actorMap remove_actors;
186  actorMap new_actors;
187  for(auto& it: m_highResActors)
188  {
189  if(tmp_highResActors.find(it.first) == tmp_highResActors.end())
190  {
191  //vtkSmartPointer<vtkActor> copy = vtkSmartPointer<vtkActor>::New();
192  //it.second->ShallowCopy(copy);
193  remove_actors.insert({it.first, it.second});
194  }
195  }
196 
197  for(auto& it: tmp_highResActors)
198  {
199  if(m_highResActors.find(it.first) == m_highResActors.end())
200  {
201  //vtkSmartPointer<vtkActor> copy = vtkSmartPointer<vtkActor>::New();
202  //it.second->ShallowCopy(copy);
203  new_actors.insert({it.first, it.second});
204  }
205  }
206 
207  Q_EMIT updateHighRes(remove_actors, new_actors);
208 // while(!release)
209 // {
210 // mw_cond.wait(main_lock);
211 // }
212  m_highResActors = tmp_highResActors;
213  old_highRes.clear();
214  release = false;
215 // l.unlock();
216  }
217 
218 }
219 
221  std::vector<size_t> indices,
222  std::vector<BaseVector<float> > centroids)
223 {
224  // FUCKING SYNCHRONIZATION
225  std::unique_lock<std::mutex> l(mutex);
226  m_region = bb;
227  m_highResIndices = indices;
228  m_highResCentroids = centroids;
229  getNew_ = true;
230  l.unlock();
231  cond_.notify_all();
232 
233 }
234 
235 void LVRChunkedMeshBridge::addInitialActors(vtkSmartPointer<vtkRenderer> renderer)
236 {
237  std::cout << "Generating actors " << std::endl;
238  auto bb = m_chunkManager.getBoundingBox();
239  BaseVector<float> centroid = bb.getCentroid();
240 
241  LVRBoundingBoxBridge bbridge(bb);
242  renderer->AddActor(bbridge.getActor());
243  bbridge.setVisibility(true);
244 
245  auto min = bb.getLongestSide();
246  auto cam_position = centroid + BaseVector<float>(min, min, min);
247 // Vector3d cam_origin(cam_position[0], cam_position[1], cam_position[2]);
248  Vector3d cam_origin(0, 0, 0);
249  Vector3d view_up(1.0, 0.0, 0.0);
250  // Vector3d focal_point(centroid[0], centroid[1], centroid[2]);
251  Vector3d focal_point(centroid[0], centroid[1], centroid[2]);
252 
253  renderer->GetActiveCamera()->SetPosition(cam_origin.x(), cam_origin.y(), cam_origin.z());
254  renderer->GetActiveCamera()->SetFocalPoint(focal_point.x(), focal_point.y(), focal_point.z());
255  renderer->GetActiveCamera()->SetViewUp(view_up.x(), view_up.y(), view_up.z());
256 
257 
258  // maybe use pop back..
259  // maybe copy it..
260  if(m_layers.size() == 1)
261  {
262 
264  }
265  else{
266 
268  }
269 
270  std::vector<size_t> hashes;
271 
272  // THIS MAY NOT GIVE THE EXPECTED RESULT
273  // THE CENTROID OF THE CHUNK...
274  std::vector<BaseVector<float> > centroids;
275  for(auto& chunk:m_chunks)
276  {
277  hashes.push_back(chunk.first);
278  FloatChannel vertices = *(chunk.second->getFloatChannel("vertices"));
279  BaseVector<float> p = vertices[0];
280  float minX = p.x;
281  float minY = p.y;
282  float minZ = p.z;
283  float maxX = p.x;
284  float maxY = p.y;
285  float maxZ = p.z;
286 
287  for(size_t i = 0; i < vertices.numElements(); ++i)
288  {
289  p = vertices[i];
290  minX = std::min(minX, p.x);
291  minY = std::min(minY, p.y);
292  minZ = std::min(minZ, p.z);
293 
294  maxX = std::max(maxX, p.x);
295  maxY = std::max(maxY, p.y);
296  maxZ = std::max(maxZ, p.z);
297  }
298  BaseVector<float> v1(minX, minY, minZ);
299  BaseVector<float> v2(maxX, maxY, maxZ);
300 
301  BoundingBox<BaseVector<float> > chunk_bb(v1, v2);
302  centroids.push_back(chunk_bb.getCentroid());
303  }
304 
305  m_oct = std::make_unique<MeshOctree<BaseVector<float> >> (m_chunkManager.getChunkSize(),
306  hashes, centroids, bb);
307 
308 
309  if(m_layers.size() > 1)
310  {
311  std::cout << "Computing actors " << std::endl;
313  std::cout << "Adding actors." << std::endl;
314  for(auto& actor: m_chunkActors)
315  {
316  renderer->AddActor(actor.second);
317  actor.second->VisibilityOff();
318  }
319  std::cout << "Added " << m_chunkActors.size() << " actors" << std::endl;
320  }
321 }
322 
323 void LVRChunkedMeshBridge::getActors(double planes[24],
324  std::vector<BaseVector<float> >& centroids,
325  std::vector<size_t> & indices)
326 {
327 
328  m_oct->intersect(planes, centroids, indices);
329 
330 }
331 
333 {
334 
335  size_t i = 0;
336  for(auto it = m_chunks.begin(); it != m_chunks.end(); ++it)
337  {
338  auto chunk = *it;
339  size_t id = chunk.first;
340  lvr2::MeshBufferPtr meshbuffer = chunk.second;
341  vtkSmartPointer<vtkActor> actor = computeMeshActor(id, meshbuffer);
342  m_chunkActors.insert({id, actor});
343 
344  }
345 
346 
347  std::cout << lvr2::timestamp << "Done actor computation" << std::endl;
348 }
349 
350 vtkSmartPointer<vtkActor> LVRChunkedMeshBridge::computeMeshActor(size_t& id, MeshBufferPtr& meshbuffer)
351 {
352 
353  vtkSmartPointer<vtkActor> meshActor = vtkSmartPointer<vtkActor>::New();
354  if(meshbuffer)
355  {
356 // meshActor
357  vtkSmartPointer<vtkPolyData> mesh = vtkSmartPointer<vtkPolyData>::New();
358  // Parse vertex and index buffer
359  size_t n_v, n_i, n_c;
360  size_t w_color;
361  n_v = meshbuffer->numVertices();
362  floatArr vertices = meshbuffer->getVertices();
363  n_i = meshbuffer->numFaces();
364  indexArray indices = meshbuffer->getFaceIndices();
365  n_c = n_v;
366  ucharArr colors = meshbuffer->getVertexColors(w_color);
367 
368 
369  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
370  vtkSmartPointer<vtkFloatArray> pts_data = vtkSmartPointer<vtkFloatArray>::New();
371  pts_data->SetNumberOfComponents(3);
372  pts_data->SetVoidArray(meshbuffer->getVertices().get(), n_v * 3, 1);
373  points->SetData(pts_data);
374 
375 
376  vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
377  scalars->SetNumberOfComponents(3);
378  scalars->SetName("Colors");
379 // if(colors)
380 // {
381 // scalars->SetVoidArray(colors.get(), n_v * w_color, 0,);
382 // }
383 
384 
385  // Triangle indices
386  vtkSmartPointer<vtkCellArray> triangles = vtkSmartPointer<vtkCellArray>::New();
387  vtkSmartPointer<vtkIdTypeArray> tri_data = vtkSmartPointer<vtkIdTypeArray>::New();
388 // tri_data->Resize(n_i * 4);
389  vtkIdType* tri_buf = new vtkIdType[n_i * 4];
390  for(size_t i = 0; i < n_i; i++)
391  {
392  size_t index = 3 * i;
393  size_t i2 = 4 * i;
394  tri_buf[i2 + 0] = static_cast<vtkIdType>(3);
395  tri_buf[i2 + 1] = static_cast<vtkIdType>(indices[index + 0]);
396  tri_buf[i2 + 2] = static_cast<vtkIdType>(indices[index + 1]);
397  tri_buf[i2 + 3] = static_cast<vtkIdType>(indices[index + 2]);
398 // (*tri_data).InsertValue(i2 + 0 , static_cast<vtkIdType>(3));
399 // (*tri_data).InsertValue(i2 + 1 , static_cast<vtkIdType>(indices[index + 0]));
400 // (*tri_data).InsertValue(i2 + 2 , static_cast<vtkIdType>(indices[index + 1]));
401 // (*tri_data).InsertValue(i2 + 3 , static_cast<vtkIdType>(indices[index + 2]));
402  }
403 
404  tri_data->SetVoidArray(tri_buf, n_i * 4, 0, vtkIdTypeArray::VTK_DATA_ARRAY_DELETE);
405  //tri_data->SetVoidArray(tri_buf, n_i * 4, 1);
406  triangles->SetCells(n_i, tri_data);
407 
408  // add points, triangles and if given colors
409  mesh->SetPoints(points);
410  mesh->SetPolys(triangles);
411  if(colors)
412  {
413  mesh->GetPointData()->SetScalars(scalars);
414  }
415 
416  vtkSmartPointer<vtkPolyDataMapper> mesh_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
417 
418  #ifdef LVR2_USE_VTK5
419  mesh_mapper->SetInput(mesh);
420  #else
421  mesh_mapper->SetInputData(mesh);
422  #endif
423  meshActor->SetMapper(mesh_mapper);
424  meshActor->GetProperty()->BackfaceCullingOff();
425  vtkSmartPointer<vtkPolyDataMapper> wireframe_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
426 
427  #ifdef LVR2_USE_VTK5
428  wireframe_mapper->SetInput(mesh);
429  #else
430  wireframe_mapper->SetInputData(mesh);
431  #endif
432 
433  // TODO add wireframe stuff
434  //m_wireframeActor = vtkSmartPointer<vtkActor>::New();
435  //m_wireframeActor->ShallowCopy(meshActor);
436  //m_wireframeActor->SetMapper(wireframe_mapper);
437  //vtkSmartPointer<vtkProperty> p = vtkSmartPointer<vtkProperty>::New();
438  //p->DeepCopy(meshActor->GetProperty());
439  //p->SetRepresentationToWireframe();
440  //m_wireframeActor->SetProperty(p);
441 
442  // TODO THIS WAS A FUNCTION SETBASECOLOR
443  vtkSmartPointer<vtkProperty> p = meshActor->GetProperty();
444  p->SetColor(0.9, 0.9, 0.9);
445  meshActor->SetProperty(p);
446  // TODO add wireframe stuff.
447  //p = m_wireframeActor->GetProperty();
448  //float inv_r = (float)1 - r;
449  //float inv_g = (float)1 - g;
450  //float inv_b = (float)1 - b;
451  //p->SetColor(inv_r, inv_g, inv_b);
452  //m_wireframeActor->SetProperty(p);
453  mesh_mapper->Update();
454 
455  //setBaseColor(0.9, 0.9, 0.9);
456  //meshActor->setID(id);
457 
458  }
459 
460  return meshActor;
461 }
462 
const BoundingBox< BaseVector< float > > & getBoundingBox() const
float getChunkSize() const
std::vector< BaseVector< float > > m_lastCentroids
HalfEdgeMesh< Vec > mesh
void addInitialActors(vtkSmartPointer< vtkRenderer > renderer)
std::vector< size_t > m_highResIndices
std::shared_ptr< MeshBuffer > MeshBufferPtr
Definition: MeshBuffer.hpp:217
BoundingBox< BaseVector< float > > m_lastRegion
vtkSmartPointer< vtkActor > getActor()
BoundingBox< BaseVector< float > > m_region
std::unordered_map< size_t, vtkSmartPointer< vtkActor > > actorMap
static Timestamp timestamp
A global time stamp object for program runtime measurement.
Definition: Timestamp.hpp:116
MeshBufferPtr extractArea(const BoundingBox< BaseVector< float >> &area, std::string layer=std::string("mesh"))
extractArea creates and returns MeshBufferPtr of merged chunks for given area.
LVRChunkedMeshBridge(std::string file, vtkSmartPointer< vtkRenderer > renderer, std::vector< std::string > layers, size_t cache_size=1000)
boost::shared_array< unsigned char > ucharArr
Definition: DataStruct.hpp:137
Eigen::Vector3d Vector3d
Eigen 3D vector, double precision.
void fetchHighRes(BoundingBox< BaseVector< float > > bb, std::vector< size_t > indices, std::vector< BaseVector< float >> centroids)
A dynamic bounding box class.
Definition: BoundingBox.hpp:49
BaseVecT getCentroid() const
Returns the center Vector of the bounding box.
std::unique_ptr< MeshOctree< BaseVector< float > > > m_oct
std::vector< std::string > m_layers
vtkSmartPointer< vtkActor > computeMeshActor(size_t &id, MeshBufferPtr &chunk)
boost::shared_array< unsigned int > indexArray
Definition: DataStruct.hpp:128
boost::shared_array< float > floatArr
Definition: DataStruct.hpp:133
SharedPointer p
T abs(T x)
Definition: nanoflann.hpp:237
void getActors(double planes[24], std::vector< BaseVector< float > > &centroids, std::vector< size_t > &indices)
std::unordered_map< size_t, MeshBufferPtr > m_chunks
std::condition_variable cond_
std::unordered_map< size_t, MeshBufferPtr > m_highRes
FILE * file
std::unordered_map< size_t, vtkSmartPointer< vtkActor > > m_highResActors
std::vector< size_t > m_lastIndices
std::unordered_map< size_t, vtkSmartPointer< vtkActor > > m_chunkActors
void updateHighRes(actorMap lowRes, actorMap highRes)
size_t numElements() const
std::vector< BaseVector< float > > m_highResCentroids


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:08