ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
LineSetBuffers.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 // 4068: Filament has some clang-specific vectorizing pragma's that MSVC flags
9 // 4146: Filament's utils/algorithm.h utils::details::ctz() tries to negate
10 // an unsigned int.
11 // 4293: Filament's utils/algorithm.h utils::details::clz() does strange
12 // things with MSVC. Somehow sizeof(unsigned int) > 4, but its size is
13 // 32 so that x >> 32 gives a warning. (Or maybe the compiler can't
14 // determine the if statement does not run.)
15 #ifdef _MSC_VER
16 #pragma warning(push)
17 #pragma warning(disable : 4068 4146 4293)
18 #endif // _MSC_VER
19 
20 #include <filament/IndexBuffer.h>
21 #include <filament/VertexBuffer.h>
22 
23 #ifdef _MSC_VER
24 #pragma warning(pop)
25 #endif // _MSC_VER
26 
27 #include <LineSet.h>
28 #include <ecvBBox.h>
29 
30 #include <map>
31 
35 
36 using namespace filament;
37 
38 namespace cloudViewer {
39 namespace visualization {
40 namespace rendering {
41 
42 namespace {
43 struct ColoredVertex {
44  math::float3 position = {0.f, 0.f, 0.f};
45  math::float4 next = {0.f, 0.f, 0.f, 1.f};
46  math::float4 color = {1.f, 1.f, 1.f, 1.f};
47 
48  static std::uint32_t GetPositionOffset() {
49  return offsetof(ColoredVertex, position);
50  }
51  static std::uint32_t GetNextOffset() {
52  return offsetof(ColoredVertex, next);
53  }
54  static std::uint32_t GetColorOffset() {
55  return offsetof(ColoredVertex, color);
56  }
57 
58  void SetVertexPosition(const Eigen::Vector3d& pos) {
59  auto float_pos = pos.cast<float>();
60  position.x = float_pos(0);
61  position.y = float_pos(1);
62  position.z = float_pos(2);
63  }
64 
65  void SetVertexNext(const Eigen::Vector3d& pos, float dir) {
66  auto float_pos = pos.cast<float>();
67  next.x = float_pos(0);
68  next.y = float_pos(1);
69  next.z = float_pos(2);
70  next.w = dir;
71  }
72 
73  void SetVertexColor(const Eigen::Vector3d& c) {
74  auto float_color = c.cast<float>();
75  color.x = float_color(0);
76  color.y = float_color(1);
77  color.z = float_color(2);
78  color.w = 1.0f;
79  }
80 };
81 
82 } // namespace
83 
84 LineSetBuffersBuilder::LineSetBuffersBuilder(const geometry::LineSet& geometry)
85  : geometry_(geometry) {}
86 
87 RenderableManager::PrimitiveType LineSetBuffersBuilder::GetPrimitiveType()
88  const {
89  if (wide_lines_) {
90  return RenderableManager::PrimitiveType::TRIANGLES;
91  } else {
92  return RenderableManager::PrimitiveType::LINES;
93  }
94 }
95 
96 LineSetBuffersBuilder::Buffers LineSetBuffersBuilder::ConstructThinLines() {
97  auto& engine = EngineInstance::GetInstance();
98  auto& resource_mgr = EngineInstance::GetResourceManager();
99 
100  struct LookupKey {
101  LookupKey() = default;
102  explicit LookupKey(const Eigen::Vector3d& pos,
103  const Eigen::Vector3d& color) {
104  values[0] = pos.x();
105  values[1] = pos.y();
106  values[2] = pos.z();
107  values[3] = color.x();
108  values[4] = color.y();
109  values[5] = color.z();
110  }
111 
112  // Not necessarily transitive.
113  // TODO: does this break sort and map?
114  bool operator<(const LookupKey& other) const {
115  for (int i = 0; i < 6; ++i) {
116  double diff = abs(values[i] - other.values[i]);
117  if (diff > kEpsilon) {
118  return values[i] < other.values[i];
119  }
120  }
121 
122  return false;
123  }
124 
125  const double kEpsilon = 0.00001;
126  double values[6] = {0};
127  };
128 
129  // <source, real>
130  std::map<LookupKey, std::pair<GeometryBuffersBuilder::IndexType,
132  index_lookup;
133 
134  const size_t lines_count = geometry_.lines_.size();
135  const size_t vertices_bytes_count = lines_count * 2 * sizeof(ColoredVertex);
136  auto* vertices = static_cast<ColoredVertex*>(malloc(vertices_bytes_count));
137 
138  const size_t indices_bytes_count = lines_count * 2 * sizeof(IndexType);
139  auto* indices = static_cast<IndexType*>(malloc(indices_bytes_count));
140 
141  const bool has_colors = geometry_.HasColors();
142  Eigen::Vector3d kWhite(1.0, 1.0, 1.0);
143  size_t vertex_idx = 0;
144  for (size_t i = 0; i < lines_count; ++i) {
145  const auto& line = geometry_.lines_[i];
146 
147  for (size_t j = 0; j < 2; ++j) {
148  size_t index = line(j);
149 
150  auto& color = kWhite;
151  if (has_colors) {
152  color = geometry_.colors_[i];
153  }
154  const auto& pos = geometry_.points_[index];
155  LookupKey lookup_key(pos, color);
156  auto found = index_lookup.find(lookup_key);
157  if (found != index_lookup.end()) {
158  index = found->second.second;
159  } else {
160  auto& element = vertices[vertex_idx];
161 
162  element.SetVertexPosition(pos);
163  element.SetVertexColor(color);
164 
165  index_lookup[lookup_key] = {IndexType(index),
166  IndexType(vertex_idx)};
167  index = vertex_idx;
168 
169  ++vertex_idx;
170  }
171 
172  indices[2 * i + j] = IndexType(index);
173  }
174  }
175 
176  const size_t vertices_count = vertex_idx;
177 
178  VertexBuffer* vbuf = VertexBuffer::Builder()
179  .bufferCount(1)
180  .vertexCount(std::uint32_t(vertices_count))
181  .attribute(VertexAttribute::POSITION, 0,
182  VertexBuffer::AttributeType::FLOAT3,
183  ColoredVertex::GetPositionOffset(),
184  sizeof(ColoredVertex))
185  .normalized(VertexAttribute::COLOR)
186  .attribute(VertexAttribute::COLOR, 0,
187  VertexBuffer::AttributeType::FLOAT4,
188  ColoredVertex::GetColorOffset(),
189  sizeof(ColoredVertex))
190  .build(engine);
191 
192  VertexBufferHandle vb_handle;
193  if (vbuf) {
194  vb_handle = resource_mgr.AddVertexBuffer(vbuf);
195  } else {
196  free(vertices);
197  free(indices);
198  return {};
199  }
200 
201  // Moving `vertices` to VertexBuffer, which will clean them up later
202  // with DeallocateBuffer
203  VertexBuffer::BufferDescriptor vb_descriptor(
204  vertices, vertices_count * sizeof(ColoredVertex));
205  vb_descriptor.setCallback(GeometryBuffersBuilder::DeallocateBuffer);
206  vbuf->setBufferAt(engine, 0, std::move(vb_descriptor));
207 
208  const size_t indices_count = lines_count * 2;
209  auto ib_handle =
210  resource_mgr.CreateIndexBuffer(indices_count, sizeof(IndexType));
211  if (!ib_handle) {
212  free(indices);
213  return {};
214  }
215 
216  auto ibuf = resource_mgr.GetIndexBuffer(ib_handle).lock();
217 
218  // Moving `indices` to IndexBuffer, which will clean them up later
219  // with DeallocateBuffer
220  IndexBuffer::BufferDescriptor ib_descriptor(indices, indices_bytes_count);
221  ib_descriptor.setCallback(GeometryBuffersBuilder::DeallocateBuffer);
222  ibuf->setBuffer(engine, std::move(ib_descriptor));
223 
224  return std::make_tuple(vb_handle, ib_handle, IndexBufferHandle());
225 }
226 
228  // Build lines instead of triangles unless wide lines are specified
229  if (!wide_lines_) {
230  return ConstructThinLines();
231  }
232 
233  auto& engine = EngineInstance::GetInstance();
234  auto& resource_mgr = EngineInstance::GetResourceManager();
235 
236  const size_t lines_count = geometry_.lines_.size();
237  // NOTE: Vertices are duplicated so you need double (x4 instead of x2) the
238  // bytes
239  const size_t vertices_bytes_count = lines_count * 4 * sizeof(ColoredVertex);
240  auto* vertices = static_cast<ColoredVertex*>(malloc(vertices_bytes_count));
241 
242  // NOTE: Each line is 2 triangles
243  const size_t indices_bytes_count = lines_count * 6 * sizeof(IndexType);
244  auto* indices = static_cast<IndexType*>(malloc(indices_bytes_count));
245 
246  const bool has_colors = geometry_.HasColors();
247  Eigen::Vector3d kWhite(1.0, 1.0, 1.0);
248  size_t vertex_idx = 0;
249  size_t index_idx = 0;
250  for (size_t i = 0; i < lines_count; ++i) {
251  const auto& line = geometry_.lines_[i];
252 
253  auto& color = kWhite;
254  if (has_colors) {
255  color = geometry_.colors_[i];
256  }
257 
258  const auto& pos1 = geometry_.points_[line(0)];
259  const auto& pos2 = geometry_.points_[line(1)];
260 
261  auto& element1 = vertices[vertex_idx];
262  element1.SetVertexPosition(pos1);
263  element1.SetVertexNext(pos2, 1.f);
264  element1.SetVertexColor(color);
265 
266  auto& element2 = vertices[vertex_idx + 1];
267  element2.SetVertexPosition(pos1);
268  element2.SetVertexNext(pos2, -1.f);
269  element2.SetVertexColor(color);
270 
271  auto& element3 = vertices[vertex_idx + 2];
272  element3.SetVertexPosition(pos2);
273  element3.SetVertexNext(pos1, -1.f);
274  element3.SetVertexColor(color);
275 
276  auto& element4 = vertices[vertex_idx + 3];
277  element4.SetVertexPosition(pos2);
278  element4.SetVertexNext(pos1, 1.f);
279  element4.SetVertexColor(color);
280 
281  // Triangle 1
282  indices[index_idx++] = IndexType(vertex_idx);
283  indices[index_idx++] = IndexType(vertex_idx + 1);
284  indices[index_idx++] = IndexType(vertex_idx + 2);
285 
286  // Triangle 2
287  indices[index_idx++] = IndexType(vertex_idx + 3);
288  indices[index_idx++] = IndexType(vertex_idx + 2);
289  indices[index_idx++] = IndexType(vertex_idx + 1);
290 
291  vertex_idx += 4;
292  }
293 
294  const size_t vertices_count = vertex_idx;
295 
296  VertexBuffer* vbuf = VertexBuffer::Builder()
297  .bufferCount(1)
298  .vertexCount(std::uint32_t(vertices_count))
299  .attribute(VertexAttribute::POSITION, 0,
300  VertexBuffer::AttributeType::FLOAT3,
301  ColoredVertex::GetPositionOffset(),
302  sizeof(ColoredVertex))
303  .attribute(VertexAttribute::CUSTOM0, 0,
304  VertexBuffer::AttributeType::FLOAT4,
305  ColoredVertex::GetNextOffset(),
306  sizeof(ColoredVertex))
307  .normalized(VertexAttribute::COLOR)
308  .attribute(VertexAttribute::COLOR, 0,
309  VertexBuffer::AttributeType::FLOAT4,
310  ColoredVertex::GetColorOffset(),
311  sizeof(ColoredVertex))
312  .build(engine);
313 
314  VertexBufferHandle vb_handle;
315  if (vbuf) {
316  vb_handle = resource_mgr.AddVertexBuffer(vbuf);
317  } else {
318  free(vertices);
319  free(indices);
320  return {};
321  }
322 
323  // Moving `vertices` to VertexBuffer, which will clean them up later
324  // with DeallocateBuffer
325  VertexBuffer::BufferDescriptor vb_descriptor(
326  vertices, vertices_count * sizeof(ColoredVertex));
327  vb_descriptor.setCallback(GeometryBuffersBuilder::DeallocateBuffer);
328  vbuf->setBufferAt(engine, 0, std::move(vb_descriptor));
329 
330  // const size_t indices_count = lines_count * 6;
331  const size_t indices_count = index_idx;
332  auto ib_handle =
333  resource_mgr.CreateIndexBuffer(indices_count, sizeof(IndexType));
334  if (!ib_handle) {
335  free(indices);
336  return {};
337  }
338 
339  auto ibuf = resource_mgr.GetIndexBuffer(ib_handle).lock();
340 
341  // Moving `indices` to IndexBuffer, which will clean them up later
342  // with DeallocateBuffer
343  IndexBuffer::BufferDescriptor ib_descriptor(indices, indices_bytes_count);
344  ib_descriptor.setCallback(GeometryBuffersBuilder::DeallocateBuffer);
345  ibuf->setBuffer(engine, std::move(ib_descriptor));
346 
347  return std::make_tuple(vb_handle, ib_handle, IndexBufferHandle());
348 }
349 
351  const auto geometry_aabb = geometry_.GetAxisAlignedBoundingBox();
352 
353  const filament::math::float3 min(geometry_aabb.minCorner().x,
354  geometry_aabb.minCorner().y,
355  geometry_aabb.minCorner().z);
356  const filament::math::float3 max(geometry_aabb.maxCorner().x,
357  geometry_aabb.maxCorner().y,
358  geometry_aabb.maxCorner().z);
359 
360  Box aabb;
361  aabb.set(min, max);
362 
363  return aabb;
364 }
365 
367  const t::geometry::LineSet& geometry)
368  : geometry_(geometry) {
369  // Make sure geometry is on CPU
370  auto pts = geometry.GetPointPositions();
371  if (pts.IsCUDA()) {
373  "GPU resident line sets are not currently supported for "
374  "visualization. Copying data to CPU.");
375  geometry_ = geometry.To(core::Device("CPU:0"));
376  }
377 
378  // Make sure data types are Float32 for points
379  if (pts.GetDtype() != core::Float32) {
381  "Tensor point cloud points must have DType of Float32 not {}. "
382  "Converting.",
383  pts.GetDtype().ToString());
384  geometry_.GetPointPositions() = pts.To(core::Float32);
385  }
386  // Colors should be Float32 but will often by UInt8
387  if (geometry_.HasLineColors() &&
388  geometry_.GetLineColors().GetDtype() != core::Float32) {
389  auto colors = geometry_.GetLineColors();
390  geometry_.GetLineColors() = colors.To(core::Float32);
391  if (colors.GetDtype() == core::UInt8) {
392  geometry_.GetLineColors() = geometry_.GetLineColors() / 255.0f;
393  }
394  }
395  // Make sure line indices are Uint32
396  if (geometry_.HasLineIndices() &&
397  geometry_.GetLineIndices().GetDtype() != core::UInt32) {
398  auto indices = geometry_.GetLineIndices();
399  geometry_.GetLineIndices() = indices.To(core::UInt32);
400  }
401 }
402 
403 RenderableManager::PrimitiveType TLineSetBuffersBuilder::GetPrimitiveType()
404  const {
405  if (wide_lines_) {
406  return RenderableManager::PrimitiveType::TRIANGLES;
407  } else {
408  return RenderableManager::PrimitiveType::LINES;
409  }
410 }
411 
412 void TLineSetBuffersBuilder::ConstructThinLines(uint32_t& n_vertices,
413  float** vertex_data,
414  uint32_t& n_indices,
415  uint32_t& indices_bytes,
416  uint32_t** line_indices) {
417  const auto& points = geometry_.GetPointPositions();
418  const uint32_t n_elements = 7;
419  const uint32_t vertex_stride = n_elements * sizeof(float);
420  float* vdata;
421  uint32_t* idata;
422 
423  // Two separate paths for lines with colors and those without
424  if (geometry_.HasLineColors()) {
425  // NOTE: The following code naively duplicates vertex positions for each
426  // line in case there are multiple different colored lines sharing a
427  // vertex. This could be made more intelligent to avoid unnecessary
428  // duplication but as a practical matter there shouldn't be much if any
429  // performance difference. This can be revisited in the future if
430  // necessary.
431  const auto& lines = geometry_.GetLineIndices();
432  const auto& colors = geometry_.GetLineColors();
433  n_vertices = lines.GetLength() * 2;
434  core::Tensor filament_data =
435  core::Tensor::Empty({n_vertices, n_elements}, core::Float32);
436  filament_data.Slice(1, 0, 3) =
437  points.IndexGet({lines.Reshape({n_vertices}).To(core::Int64)});
438  filament_data.Slice(0, 0, n_vertices, 2).Slice(1, 3, 6) = colors;
439  filament_data.Slice(0, 1, n_vertices, 2).Slice(1, 3, 6) = colors;
440  filament_data.Slice(1, 6, 7) = 1.f;
441  vdata = static_cast<float*>(malloc(n_vertices * vertex_stride));
442  memcpy(vdata, filament_data.GetDataPtr(), n_vertices * vertex_stride);
443  indices_bytes = n_vertices * sizeof(IndexType);
444  n_indices = n_vertices;
445  idata = static_cast<IndexType*>(malloc(indices_bytes));
446  std::iota(idata, idata + n_vertices, 0);
447  } else {
448  n_vertices = points.GetLength();
449  core::Tensor filament_data =
450  core::Tensor::Empty({n_vertices, n_elements}, core::Float32);
451  filament_data.Slice(1, 0, 3) = points;
452  filament_data.Slice(1, 3, 7) = 1.f;
453  const auto vertex_array_size = n_vertices * vertex_stride;
454  vdata = static_cast<float*>(malloc(vertex_array_size));
455  memcpy(vdata, filament_data.GetDataPtr(), vertex_array_size);
456  indices_bytes =
457  geometry_.GetLineIndices().GetLength() * 2 * sizeof(IndexType);
458  n_indices = geometry_.GetLineIndices().GetLength() * 2;
459  idata = static_cast<IndexType*>(malloc(indices_bytes));
460  memcpy(idata, geometry_.GetLineIndices().GetDataPtr(), indices_bytes);
461  }
462 
463  // Assign buffers back to inputs
464  *vertex_data = vdata;
465  *line_indices = idata;
466 }
467 
468 void TLineSetBuffersBuilder::ConstructWideLines(uint32_t& n_vertices,
469  float** vertex_data,
470  uint32_t& n_indices,
471  uint32_t& indices_bytes,
472  uint32_t** line_indices) {
473  const auto& points = geometry_.GetPointPositions();
474  const auto& lines = geometry_.GetLineIndices();
475 
476  const uint32_t n_elements = 11;
477  const uint32_t vertex_stride = n_elements * sizeof(float);
478  float* vdata;
479  uint32_t* idata;
480 
481  n_vertices = lines.GetLength() * 4;
482  core::Tensor filament_data =
483  core::Tensor::Empty({n_vertices, n_elements}, core::Float32);
484  // Get the start and end vertex of each line
485  core::Tensor pos1_data =
486  points.IndexGet({lines.Slice(1, 0, 1)
487  .Reshape({lines.GetLength()})
488  .To(core::Int64)});
489  core::Tensor pos2_data =
490  points.IndexGet({lines.Slice(1, 1, 2)
491  .Reshape({lines.GetLength()})
492  .To(core::Int64)});
493  // Fill the vertices. The original vertices get expanded to 4 vertices
494  // for the 4 corners of the line (composed of 2 triangles) as follows:
495  // pos1 pos2 1.0 [color]
496  // pos1 pos2 -1.0 [color]
497  // pos2 pos1 -1.0 [color]
498  // pos2 pos1 1.0 [color]
499  // Vertex
500  filament_data.Slice(0, 0, n_vertices, 4).Slice(1, 0, 3) = pos1_data;
501  filament_data.Slice(0, 1, n_vertices, 4).Slice(1, 0, 3) = pos1_data;
502  filament_data.Slice(0, 2, n_vertices, 4).Slice(1, 0, 3) = pos2_data;
503  filament_data.Slice(0, 3, n_vertices, 4).Slice(1, 0, 3) = pos2_data;
504  // Next parameter
505  filament_data.Slice(0, 0, n_vertices, 4).Slice(1, 3, 6) = pos2_data;
506  filament_data.Slice(0, 1, n_vertices, 4).Slice(1, 3, 6) = pos2_data;
507  filament_data.Slice(0, 2, n_vertices, 4).Slice(1, 3, 6) = pos1_data;
508  filament_data.Slice(0, 3, n_vertices, 4).Slice(1, 3, 6) = pos1_data;
509  // Direction parameter
510  filament_data.Slice(0, 0, n_vertices, 4).Slice(1, 6, 7) = 1.f;
511  filament_data.Slice(0, 1, n_vertices, 4).Slice(1, 6, 7) = -1.f;
512  filament_data.Slice(0, 2, n_vertices, 4).Slice(1, 6, 7) = -1.f;
513  filament_data.Slice(0, 3, n_vertices, 4).Slice(1, 6, 7) = 1.f;
514  // Fill in color
515  if (geometry_.HasLineColors()) {
516  const auto& colors = geometry_.GetLineColors();
517  filament_data.Slice(0, 0, n_vertices, 4).Slice(1, 7, 10) = colors;
518  filament_data.Slice(0, 1, n_vertices, 4).Slice(1, 7, 10) = colors;
519  filament_data.Slice(0, 2, n_vertices, 4).Slice(1, 7, 10) = colors;
520  filament_data.Slice(0, 3, n_vertices, 4).Slice(1, 7, 10) = colors;
521  filament_data.Slice(1, 10, 11) = 1.f; // alpha value
522  } else {
523  filament_data.Slice(1, 7, 11) = 1.f;
524  }
525 
526  // Copy per-vertex data to output array
527  const auto vertex_array_size = n_vertices * vertex_stride;
528  vdata = static_cast<float*>(malloc(vertex_array_size));
529  memcpy(vdata, filament_data.GetDataPtr(), vertex_array_size);
530 
531  // Build the triangles for the wide lines
532  n_indices = geometry_.GetLineIndices().GetLength() * 6;
533  indices_bytes = n_indices * sizeof(IndexType);
534  idata = static_cast<IndexType*>(malloc(indices_bytes));
535  for (uint32_t i = 0, vertex_idx = 0; i < n_indices; vertex_idx += 4) {
536  // Triangle 1
537  idata[i++] = vertex_idx;
538  idata[i++] = vertex_idx + 1;
539  idata[i++] = vertex_idx + 2;
540  // Triangle 2
541  idata[i++] = vertex_idx + 3;
542  idata[i++] = vertex_idx + 2;
543  idata[i++] = vertex_idx + 1;
544  }
545 
546  // Assign buffers back to inputs
547  *vertex_data = vdata;
548  *line_indices = idata;
549 }
550 
552  auto& engine = EngineInstance::GetInstance();
553  auto& resource_mgr = EngineInstance::GetResourceManager();
554 
555  const uint32_t n_elements = wide_lines_ ? 11 : 7;
556  const uint32_t vertex_stride = n_elements * sizeof(float);
557  const uint32_t vertex_start_offset = 0;
558  const uint32_t next_start_offest = 3 * sizeof(float);
559  const uint32_t color_start_offset =
560  wide_lines_ ? 7 * sizeof(float) : 3 * sizeof(float);
561 
562  uint32_t n_vertices = 0;
563  float* vertex_data = nullptr;
564  uint32_t n_indices = 0;
565  IndexType* line_indices = nullptr;
566  uint32_t indices_bytes = 0;
567 
568  // Separate paths for thin and wide lines
569  if (wide_lines_) {
570  ConstructWideLines(n_vertices, &vertex_data, n_indices, indices_bytes,
571  &line_indices);
572  } else {
573  ConstructThinLines(n_vertices, &vertex_data, n_indices, indices_bytes,
574  &line_indices);
575  }
576 
577  VertexBuffer* vbuf;
578  // Different GPU vertex layouts for
579  if (wide_lines_) {
580  vbuf = VertexBuffer::Builder()
581  .bufferCount(1)
582  .vertexCount(n_vertices)
583  .attribute(VertexAttribute::POSITION, 0,
584  VertexBuffer::AttributeType::FLOAT3,
585  vertex_start_offset, vertex_stride)
586  .attribute(VertexAttribute::CUSTOM0, 0,
587  VertexBuffer::AttributeType::FLOAT4,
588  next_start_offest, vertex_stride)
589  .attribute(VertexAttribute::COLOR, 0,
590  VertexBuffer::AttributeType::FLOAT4,
591  color_start_offset, vertex_stride)
592  .build(engine);
593  } else {
594  vbuf = VertexBuffer::Builder()
595  .bufferCount(1)
596  .vertexCount(n_vertices)
597  .attribute(VertexAttribute::POSITION, 0,
598  VertexBuffer::AttributeType::FLOAT3,
599  vertex_start_offset, vertex_stride)
600  .attribute(VertexAttribute::COLOR, 0,
601  VertexBuffer::AttributeType::FLOAT4,
602  color_start_offset, vertex_stride)
603  .build(engine);
604  }
605 
606  VertexBufferHandle vb_handle;
607  if (vbuf) {
608  vb_handle = resource_mgr.AddVertexBuffer(vbuf);
609  } else {
610  return {};
611  }
612 
613  // Create vertex and index buffer
614  VertexBuffer::BufferDescriptor vb_descriptor(vertex_data,
615  n_vertices * vertex_stride);
616  vb_descriptor.setCallback(GeometryBuffersBuilder::DeallocateBuffer);
617  vbuf->setBufferAt(engine, 0, std::move(vb_descriptor));
618 
619  auto ib_handle =
620  resource_mgr.CreateIndexBuffer(n_indices, sizeof(IndexType));
621  if (!ib_handle) {
622  free(line_indices);
623  return {};
624  }
625  auto ibuf = resource_mgr.GetIndexBuffer(ib_handle).lock();
626  IndexBuffer::BufferDescriptor ib_descriptor(line_indices, indices_bytes);
627  ib_descriptor.setCallback(GeometryBuffersBuilder::DeallocateBuffer);
628  ibuf->setBuffer(engine, std::move(ib_descriptor));
629 
630  return {vb_handle, ib_handle, IndexBufferHandle()};
631 }
632 
634  auto min_bounds = geometry_.GetMinBound();
635  auto max_bounds = geometry_.GetMaxBound();
636  auto* min_bounds_float = min_bounds.GetDataPtr<float>();
637  auto* max_bounds_float = max_bounds.GetDataPtr<float>();
638 
639  const filament::math::float3 min(min_bounds_float[0], min_bounds_float[1],
640  min_bounds_float[2]);
641  const filament::math::float3 max(max_bounds_float[0], max_bounds_float[1],
642  max_bounds_float[2]);
643 
644  Box aabb;
645  aabb.set(min, max);
646  return aabb;
647 }
648 
649 } // namespace rendering
650 } // namespace visualization
651 } // namespace cloudViewer
bool has_colors
int points
math::float4 next
math::float4 color
math::float3 position
size_t vertices_count
int64_t GetLength() const
Definition: Tensor.h:1125
Dtype GetDtype() const
Definition: Tensor.h:1164
static Tensor Empty(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor with uninitialized values.
Definition: Tensor.cpp:400
Tensor Slice(int64_t dim, int64_t start, int64_t stop, int64_t step=1) const
Definition: Tensor.cpp:857
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
LineSet define a sets of lines in 3D. A typical application is to display the point cloud corresponde...
Definition: LineSet.h:29
bool HasColors() const
Returns true if the objects lines contains colors.
Definition: LineSet.h:85
virtual ccBBox GetAxisAlignedBoundingBox() const override
Returns an axis-aligned bounding box of the geometry.
std::vector< Eigen::Vector3d > points_
Points coordinates.
Definition: LineSet.h:156
std::vector< Eigen::Vector3d > colors_
RGB colors of lines.
Definition: LineSet.h:160
std::vector< Eigen::Vector2i > lines_
Lines denoted by the index of points forming the line.
Definition: LineSet.h:158
A LineSet contains points and lines joining them and optionally attributes on the points and lines.
Definition: LineSet.h:85
core::Tensor & GetLineIndices()
Definition: LineSet.h:157
core::Tensor GetMaxBound() const
Returns the max bound for point coordinates.
Definition: LineSet.h:293
LineSet To(const core::Device &device, bool copy=false) const
Definition: LineSet.cpp:42
core::Tensor & GetPointPositions()
Definition: LineSet.h:139
core::Tensor & GetLineColors()
Definition: LineSet.h:161
core::Tensor GetMinBound() const
Returns the max bound for point coordinates.
Definition: LineSet.h:290
static FilamentResourceManager & GetResourceManager()
static void DeallocateBuffer(void *buffer, size_t size, void *user_ptr)
std::tuple< VertexBufferHandle, IndexBufferHandle, IndexBufferHandle > Buffers
filament::RenderableManager::PrimitiveType GetPrimitiveType() const override
TLineSetBuffersBuilder(const t::geometry::LineSet &geometry)
filament::RenderableManager::PrimitiveType GetPrimitiveType() const override
double colors[3]
#define LogWarning(...)
Definition: Logging.h:72
int min(int a, int b)
Definition: cutil_math.h:53
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
int max(int a, int b)
Definition: cutil_math.h:48
const Dtype Int64
Definition: Dtype.cpp:47
const Dtype UInt32
Definition: Dtype.cpp:50
const Dtype UInt8
Definition: Dtype.cpp:48
const Dtype Float32
Definition: Dtype.cpp:42
void To(const core::Tensor &src, core::Tensor &dst, double scale, double offset)
Definition: Image.cpp:17
constexpr bool operator<(const optional< T > &x, const optional< T > &y)
Definition: Optional.h:625
REHandle< EntityType::VertexBuffer > VertexBufferHandle
REHandle< EntityType::IndexBuffer > IndexBufferHandle
Generic file read and write utility for python interface.
#define offsetof(STRUCTURE, FIELD)
Definition: sqlite3.c:14241