17 #pragma warning(disable : 4068 4146 4293)
20 #include <filament/IndexBuffer.h>
21 #include <filament/VertexBuffer.h>
39 namespace visualization {
43 struct ColoredVertex {
45 math::float4
next = {0.f, 0.f, 0.f, 1.f};
46 math::float4
color = {1.f, 1.f, 1.f, 1.f};
48 static std::uint32_t GetPositionOffset() {
51 static std::uint32_t GetNextOffset() {
54 static std::uint32_t GetColorOffset() {
58 void SetVertexPosition(
const Eigen::Vector3d& pos) {
59 auto float_pos = pos.cast<
float>();
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);
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);
85 : geometry_(geometry) {}
90 return RenderableManager::PrimitiveType::TRIANGLES;
92 return RenderableManager::PrimitiveType::LINES;
101 LookupKey() =
default;
102 explicit LookupKey(
const Eigen::Vector3d& pos,
103 const Eigen::Vector3d&
color) {
107 values[3] =
color.x();
108 values[4] =
color.y();
109 values[5] =
color.z();
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];
125 const double kEpsilon = 0.00001;
126 double values[6] = {0};
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));
138 const size_t indices_bytes_count = lines_count * 2 *
sizeof(
IndexType);
139 auto* indices =
static_cast<IndexType*
>(malloc(indices_bytes_count));
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];
147 for (
size_t j = 0; j < 2; ++j) {
148 size_t index = line(j);
150 auto&
color = kWhite;
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;
160 auto& element = vertices[vertex_idx];
162 element.SetVertexPosition(pos);
163 element.SetVertexColor(
color);
165 index_lookup[lookup_key] = {
IndexType(index),
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))
194 vb_handle = resource_mgr.AddVertexBuffer(vbuf);
203 VertexBuffer::BufferDescriptor vb_descriptor(
206 vbuf->setBufferAt(engine, 0, std::move(vb_descriptor));
208 const size_t indices_count = lines_count * 2;
210 resource_mgr.CreateIndexBuffer(indices_count,
sizeof(
IndexType));
216 auto ibuf = resource_mgr.GetIndexBuffer(ib_handle).lock();
220 IndexBuffer::BufferDescriptor ib_descriptor(indices, indices_bytes_count);
222 ibuf->setBuffer(engine, std::move(ib_descriptor));
230 return ConstructThinLines();
236 const size_t lines_count = geometry_.
lines_.size();
239 const size_t vertices_bytes_count = lines_count * 4 *
sizeof(ColoredVertex);
240 auto* vertices =
static_cast<ColoredVertex*
>(malloc(vertices_bytes_count));
243 const size_t indices_bytes_count = lines_count * 6 *
sizeof(
IndexType);
244 auto* indices =
static_cast<IndexType*
>(malloc(indices_bytes_count));
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];
253 auto&
color = kWhite;
258 const auto& pos1 = geometry_.
points_[line(0)];
259 const auto& pos2 = geometry_.
points_[line(1)];
261 auto& element1 = vertices[vertex_idx];
262 element1.SetVertexPosition(pos1);
263 element1.SetVertexNext(pos2, 1.f);
264 element1.SetVertexColor(
color);
266 auto& element2 = vertices[vertex_idx + 1];
267 element2.SetVertexPosition(pos1);
268 element2.SetVertexNext(pos2, -1.f);
269 element2.SetVertexColor(
color);
271 auto& element3 = vertices[vertex_idx + 2];
272 element3.SetVertexPosition(pos2);
273 element3.SetVertexNext(pos1, -1.f);
274 element3.SetVertexColor(
color);
276 auto& element4 = vertices[vertex_idx + 3];
277 element4.SetVertexPosition(pos2);
278 element4.SetVertexNext(pos1, 1.f);
279 element4.SetVertexColor(
color);
282 indices[index_idx++] =
IndexType(vertex_idx);
283 indices[index_idx++] =
IndexType(vertex_idx + 1);
284 indices[index_idx++] =
IndexType(vertex_idx + 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);
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))
316 vb_handle = resource_mgr.AddVertexBuffer(vbuf);
325 VertexBuffer::BufferDescriptor vb_descriptor(
328 vbuf->setBufferAt(engine, 0, std::move(vb_descriptor));
331 const size_t indices_count = index_idx;
333 resource_mgr.CreateIndexBuffer(indices_count,
sizeof(
IndexType));
339 auto ibuf = resource_mgr.GetIndexBuffer(ib_handle).lock();
343 IndexBuffer::BufferDescriptor ib_descriptor(indices, indices_bytes_count);
345 ibuf->setBuffer(engine, std::move(ib_descriptor));
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);
368 : geometry_(geometry) {
373 "GPU resident line sets are not currently supported for "
374 "visualization. Copying data to CPU.");
381 "Tensor point cloud points must have DType of Float32 not {}. "
383 pts.GetDtype().ToString());
406 return RenderableManager::PrimitiveType::TRIANGLES;
408 return RenderableManager::PrimitiveType::LINES;
412 void TLineSetBuffersBuilder::ConstructThinLines(uint32_t& n_vertices,
415 uint32_t& indices_bytes,
416 uint32_t** line_indices) {
418 const uint32_t n_elements = 7;
419 const uint32_t vertex_stride = n_elements *
sizeof(float);
436 filament_data.
Slice(1, 0, 3) =
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);
448 n_vertices =
points.GetLength();
449 core::Tensor filament_data =
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);
459 idata =
static_cast<IndexType*
>(malloc(indices_bytes));
464 *vertex_data = vdata;
465 *line_indices = idata;
468 void TLineSetBuffersBuilder::ConstructWideLines(uint32_t& n_vertices,
471 uint32_t& indices_bytes,
472 uint32_t** line_indices) {
476 const uint32_t n_elements = 11;
477 const uint32_t vertex_stride = n_elements *
sizeof(float);
482 core::Tensor filament_data =
485 core::Tensor pos1_data =
486 points.IndexGet({lines.Slice(1, 0, 1)
487 .Reshape({lines.GetLength()})
489 core::Tensor pos2_data =
490 points.IndexGet({lines.Slice(1, 1, 2)
491 .Reshape({lines.GetLength()})
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;
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;
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;
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;
523 filament_data.Slice(1, 7, 11) = 1.f;
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);
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) {
537 idata[i++] = vertex_idx;
538 idata[i++] = vertex_idx + 1;
539 idata[i++] = vertex_idx + 2;
541 idata[i++] = vertex_idx + 3;
542 idata[i++] = vertex_idx + 2;
543 idata[i++] = vertex_idx + 1;
547 *vertex_data = vdata;
548 *line_indices = idata;
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);
562 uint32_t n_vertices = 0;
563 float* vertex_data =
nullptr;
564 uint32_t n_indices = 0;
566 uint32_t indices_bytes = 0;
570 ConstructWideLines(n_vertices, &vertex_data, n_indices, indices_bytes,
573 ConstructThinLines(n_vertices, &vertex_data, n_indices, indices_bytes,
580 vbuf = VertexBuffer::Builder()
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)
594 vbuf = VertexBuffer::Builder()
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)
608 vb_handle = resource_mgr.AddVertexBuffer(vbuf);
614 VertexBuffer::BufferDescriptor vb_descriptor(vertex_data,
615 n_vertices * vertex_stride);
617 vbuf->setBufferAt(engine, 0, std::move(vb_descriptor));
620 resource_mgr.CreateIndexBuffer(n_indices,
sizeof(
IndexType));
625 auto ibuf = resource_mgr.GetIndexBuffer(ib_handle).lock();
626 IndexBuffer::BufferDescriptor ib_descriptor(line_indices, indices_bytes);
628 ibuf->setBuffer(engine, std::move(ib_descriptor));
636 auto* min_bounds_float = min_bounds.
GetDataPtr<
float>();
637 auto* max_bounds_float = max_bounds.GetDataPtr<
float>();
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]);
int64_t GetLength() const
static Tensor Empty(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor with uninitialized values.
Tensor Slice(int64_t dim, int64_t start, int64_t stop, int64_t step=1) const
Tensor To(Dtype dtype, bool copy=false) const
LineSet define a sets of lines in 3D. A typical application is to display the point cloud corresponde...
bool HasColors() const
Returns true if the objects lines contains colors.
virtual ccBBox GetAxisAlignedBoundingBox() const override
Returns an axis-aligned bounding box of the geometry.
std::vector< Eigen::Vector3d > points_
Points coordinates.
std::vector< Eigen::Vector3d > colors_
RGB colors of lines.
std::vector< Eigen::Vector2i > lines_
Lines denoted by the index of points forming the line.
A LineSet contains points and lines joining them and optionally attributes on the points and lines.
core::Tensor & GetLineIndices()
core::Tensor GetMaxBound() const
Returns the max bound for point coordinates.
LineSet To(const core::Device &device, bool copy=false) const
bool HasLineIndices() const
bool HasLineColors() const
core::Tensor & GetPointPositions()
core::Tensor & GetLineColors()
core::Tensor GetMinBound() const
Returns the max bound for point coordinates.
static filament::Engine & GetInstance()
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
Buffers ConstructBuffers() override
filament::Box ComputeAABB() override
filament::Box ComputeAABB() override
Buffers ConstructBuffers() override
TLineSetBuffersBuilder(const t::geometry::LineSet &geometry)
filament::RenderableManager::PrimitiveType GetPrimitiveType() const override
__host__ __device__ int2 abs(int2 v)
void To(const core::Tensor &src, core::Tensor &dst, double scale, double offset)
constexpr bool operator<(const optional< T > &x, const optional< T > &y)
REHandle< EntityType::VertexBuffer > VertexBufferHandle
REHandle< EntityType::IndexBuffer > IndexBufferHandle
Generic file read and write utility for python interface.
#define offsetof(STRUCTURE, FIELD)