14#include <igl/ray_mesh_intersect.h>
15#include <lagrange/attributes/attribute_utils.h>
16#include <lagrange/compute_tangent_bitangent.h>
17#include <lagrange/compute_vertex_normal.h>
18#include <lagrange/select_facets_in_frustum.h>
19#include <lagrange/ui/Entity.h>
20#include <lagrange/ui/types/Camera.h>
21#include <lagrange/ui/types/Color.h>
22#include <lagrange/ui/types/Frustum.h>
23#include <lagrange/ui/types/RayFacetHit.h>
24#include <lagrange/ui/types/VertexBuffer.h>
25#include <lagrange/ui/utils/math.h>
26#include <lagrange/ui/utils/objectid_viewport.h>
27#include <lagrange/utils/tbb.h>
39RowMajorMatrixXf eigen_convert_to_float(
const T& input)
41 return input.template cast<float>().eval();
45RowMajorMatrixXi eigen_convert_to_int(
const T& input)
47 return input.template cast<int>().eval();
50template <
typename MeshType>
51size_t get_num_vertices(
const MeshBase* mesh_base)
53 return reinterpret_cast<const MeshType&
>(*mesh_base).get_num_vertices();
55template <
typename MeshType>
56size_t get_num_facets(
const MeshBase* mesh_base)
58 return reinterpret_cast<const MeshType&
>(*mesh_base).get_num_facets();
60template <
typename MeshType>
61size_t get_num_edges(
const MeshBase* mesh_base)
66template <
typename MeshType>
67RowMajorMatrixXf get_mesh_vertices(
const MeshBase* mesh_base)
69 return reinterpret_cast<const MeshType&
>(*mesh_base).get_vertices().template cast<float>();
73template <
typename MeshType>
74RowMajorMatrixXi get_mesh_facets(
const MeshBase* mesh_base)
76 return reinterpret_cast<const MeshType&
>(*mesh_base).get_facets().template cast<int>();
79template <
typename MeshType>
80RowMajorMatrixXf get_mesh_vertex_attribute(
const MeshBase* mesh_base,
const std::string& name)
82 return reinterpret_cast<const MeshType&
>(*mesh_base)
83 .get_vertex_attribute(name)
84 .template cast<float>();
87template <
typename MeshType>
88RowMajorMatrixXf get_mesh_corner_attribute(
const MeshBase* mesh_base,
const std::string& name)
90 return reinterpret_cast<const MeshType&
>(*mesh_base)
91 .get_corner_attribute(name)
92 .template cast<float>();
95template <
typename MeshType>
96RowMajorMatrixXf get_mesh_facet_attribute(
const MeshBase* mesh_base,
const std::string& name)
98 return reinterpret_cast<const MeshType&
>(*mesh_base)
99 .get_facet_attribute(name)
100 .template cast<float>();
103template <
typename MeshType>
104RowMajorMatrixXf get_mesh_edge_attribute(
const MeshBase* mesh_base,
const std::string& name)
106 return reinterpret_cast<const MeshType&
>(*mesh_base)
107 .get_edge_attribute(name)
108 .template cast<float>();
112template <
typename MeshType>
114get_mesh_attribute(
const MeshBase* mesh_base, IndexingMode mode,
const std::string& name)
117 mode != lagrange::ui::IndexingMode::INDEXED,
118 "Indexed attribute not supported. Map to corner first.");
120 const auto& mesh =
reinterpret_cast<const MeshType&
>(*mesh_base);
122 case lagrange::ui::IndexingMode::VERTEX:
123 return mesh.get_vertex_attribute(name).template cast<float>();
124 case lagrange::ui::IndexingMode::EDGE:
125 return mesh.get_edge_attribute(name).template cast<float>();
126 case lagrange::ui::IndexingMode::FACE:
127 return mesh.get_facet_attribute(name).template cast<float>();
128 case lagrange::ui::IndexingMode::CORNER:
129 return mesh.get_corner_attribute(name).template cast<float>();
132 return RowMajorMatrixXf();
136template <
typename MeshType>
137std::pair<Eigen::VectorXf, Eigen::VectorXf>
138get_mesh_attribute_range(
const MeshBase* mesh_base, IndexingMode mode,
const std::string& name)
140 using AttributeArray =
typename MeshType::AttributeArray;
142 const AttributeArray* aa =
nullptr;
143 const auto& mesh =
reinterpret_cast<const MeshType&
>(*mesh_base);
146 case lagrange::ui::IndexingMode::VERTEX: aa = &mesh.get_vertex_attribute(name);
break;
147 case lagrange::ui::IndexingMode::EDGE: aa = &mesh.get_edge_attribute(name);
break;
148 case lagrange::ui::IndexingMode::FACE: aa = &mesh.get_facet_attribute(name);
break;
149 case lagrange::ui::IndexingMode::CORNER: aa = &mesh.get_corner_attribute(name);
break;
156 aa->colwise().minCoeff().transpose().template cast<float>().eval(),
157 aa->colwise().maxCoeff().transpose().template cast<float>().eval()};
160template <
typename MeshType>
161AABB get_mesh_bounds(
const MeshBase* mesh_base)
163 const auto& mesh =
reinterpret_cast<const MeshType&
>(*mesh_base);
164 if (mesh.get_num_vertices() == 0)
return AABB();
166 const auto& V = mesh.get_vertices();
168 V.colwise().minCoeff().template cast<float>(),
169 V.colwise().maxCoeff().template cast<float>());
176template <
typename MeshType>
177void ensure_uv(MeshBase* d)
179 auto& mesh =
reinterpret_cast<MeshType&
>(*d);
180 if (!mesh.has_corner_attribute(
"uv")) {
181 if (mesh.has_vertex_attribute(
"uv")) {
182 map_vertex_attribute_to_corner_attribute(mesh,
"uv");
183 }
else if (mesh.has_indexed_attribute(
"uv")) {
184 map_indexed_attribute_to_corner_attribute(mesh,
"uv");
191template <
typename MeshType>
192void ensure_normal(MeshBase* d)
194 auto& mesh =
reinterpret_cast<MeshType&
>(*d);
195 if (!mesh.has_corner_attribute(
"normal")) {
196 if (mesh.has_vertex_attribute(
"normal")) {
197 map_vertex_attribute_to_corner_attribute(mesh,
"normal");
198 }
else if (mesh.has_indexed_attribute(
"normal")) {
199 map_indexed_attribute_to_corner_attribute(mesh,
"normal");
202 map_vertex_attribute_to_corner_attribute(mesh,
"normal");
207template <
typename MeshType>
208void ensure_tangent_bitangent(MeshBase* d)
210 auto& mesh =
reinterpret_cast<MeshType&
>(*d);
212 if (!mesh.has_corner_attribute(
"tangent") || !mesh.has_corner_attribute(
"bitangent")) {
213 if (mesh.has_vertex_attribute(
"tangent")) {
214 map_vertex_attribute_to_corner_attribute(mesh,
"tangent");
216 if (mesh.has_vertex_attribute(
"bitangent")) {
217 map_vertex_attribute_to_corner_attribute(mesh,
"bitangent");
221 if (!mesh.has_corner_attribute(
"tangent") || !mesh.has_corner_attribute(
"bitangent")) {
222 if (mesh.has_corner_attribute(
"uv")) {
223 compute_corner_tangent_bitangent(mesh);
231template <
typename MeshType>
232void ensure_is_selected_attribute(MeshBase* d)
234 auto& mesh =
reinterpret_cast<MeshType&
>(*d);
236 const auto attrib_name =
"is_selected";
237 using AttributeArray =
typename MeshType::AttributeArray;
239 if (!mesh.has_corner_attribute(attrib_name)) {
240 mesh.add_corner_attribute(attrib_name);
241 mesh.import_corner_attribute(
243 AttributeArray::Zero(mesh.get_num_facets() * mesh.get_vertex_per_facet(), 1));
246 if (!mesh.has_facet_attribute(attrib_name)) {
247 mesh.add_facet_attribute(attrib_name);
248 mesh.import_facet_attribute(attrib_name, AttributeArray::Zero(mesh.get_num_facets(), 1));
251 if (mesh.is_edge_data_initialized() && !mesh.has_edge_attribute(attrib_name)) {
252 mesh.add_edge_attribute(attrib_name);
253 mesh.import_edge_attribute(attrib_name, AttributeArray::Zero(mesh.get_num_edges(), 1));
256 if (!mesh.has_vertex_attribute(attrib_name)) {
257 mesh.add_vertex_attribute(attrib_name);
258 mesh.import_vertex_attribute(attrib_name, AttributeArray::Zero(mesh.get_num_vertices(), 1));
262template <
typename MeshType>
263void map_indexed_attribute_to_corner_attribute(MeshBase* d,
const std::string& name)
265 auto& mesh =
reinterpret_cast<MeshType&
>(*d);
266 lagrange::map_indexed_attribute_to_corner_attribute(mesh, name);
269template <
typename MeshType>
270void map_corner_attribute_to_vertex_attribute(MeshBase* d,
const std::string& name)
272 auto& mesh =
reinterpret_cast<MeshType&
>(*d);
273 lagrange::map_corner_attribute_to_vertex_attribute(mesh, name);
281template <
typename FacetArray>
282void upload_facets(
const FacetArray& facets, GPUBuffer* gpu)
284 static_assert(
sizeof(
typename FacetArray::Scalar) ==
sizeof(
unsigned int),
"Must be u/int32");
286 GLuint(facets.size() *
sizeof(
unsigned int)),
287 (
const uint8_t*)facets.data(),
288 GLsizei(facets.rows()),
293template <
typename MeshType>
294void upload_mesh_triangles(
const MeshBase* mesh_base, GPUBuffer* gpu)
296 const auto& mesh =
reinterpret_cast<const MeshType&
>(*mesh_base);
299 auto& facets = mesh.get_facets();
300 upload_facets(facets, gpu);
305std::shared_ptr<GPUBuffer> create_gpubuffer_and_upload(T&& data)
307 auto gpubuf = std::make_shared<GPUBuffer>();
308 gpubuf->vbo().upload(std::move(data));
313std::shared_ptr<GPUBuffer> create_gpubuffer_and_upload(
const T& data)
315 auto gpubuf = std::make_shared<GPUBuffer>();
316 gpubuf->vbo().upload(data);
320template <
typename MeshType>
321void upload_mesh_vertex_attribute(
const MeshBase* d,
const RowMajorMatrixXf* data, GPUBuffer* gpu)
323 auto& m =
reinterpret_cast<const MeshType&
>(*d);
325 RowMajorMatrixXf flattened = RowMajorMatrixXf(m.get_num_facets() * 3, data->cols());
327 const auto& F = m.get_facets();
328 for (
auto fi = 0; fi < m.get_num_facets(); fi++) {
329 flattened.row(3 * fi + 0) = data->row(F(fi, 0));
330 flattened.row(3 * fi + 1) = data->row(F(fi, 1));
331 flattened.row(3 * fi + 2) = data->row(F(fi, 2));
334 (*gpu).vbo().upload(std::move(flattened));
337template <
typename MeshType>
338void upload_mesh_corner_attribute(
const MeshBase* d,
const RowMajorMatrixXf* data, GPUBuffer* gpu)
340 auto& m =
reinterpret_cast<const MeshType&
>(*d);
342 (*gpu).vbo().upload(*data);
345template <
typename MeshType>
346void upload_mesh_facet_attribute(
const MeshBase* d,
const RowMajorMatrixXf* data, GPUBuffer* gpu)
348 auto& m =
reinterpret_cast<const MeshType&
>(*d);
351 RowMajorMatrixXf flattened = RowMajorMatrixXf(m.get_num_facets() * 3, data->cols());
353 for (
auto i = 0; i < data->rows(); i++) {
354 flattened.row(3 * i + 0) = data->row(i);
355 flattened.row(3 * i + 1) = data->row(i);
356 flattened.row(3 * i + 2) = data->row(i);
359 (*gpu).vbo().upload(std::move(flattened));
362template <
typename MeshType>
363void upload_mesh_edge_attribute(
const MeshBase* d,
const RowMajorMatrixXf* data, GPUBuffer* gpu)
365 const auto& m =
reinterpret_cast<const MeshType&
>(*d);
366 la_runtime_assert(m.is_edge_data_initialized(),
"Edge data (new) not initialized");
369 const auto& F = m.get_facets();
370 const auto per_facet = m.get_vertex_per_facet();
372 RowMajorMatrixXf flattened = RowMajorMatrixXf(m.get_num_facets() * per_facet, data->cols());
375 for (
auto i = 0; i < F.rows(); i++) {
377 for (
auto k = 0; k < per_facet; k++) {
378 const auto ei = m.get_edge(i, k);
379 flattened.row(per_facet * i + k) = data->row(ei);
383 (*gpu).vbo().upload(std::move(flattened));
386template <
typename MeshType>
387void upload_mesh_vertices(
const MeshBase* mesh_base, GPUBuffer* gpu)
390 auto& m =
reinterpret_cast<const MeshType&
>(*mesh_base);
391 auto& data = m.get_vertices();
393 RowMajorMatrixXf flattened = RowMajorMatrixXf(m.get_num_facets() * 3, data.cols());
395 const auto& F = m.get_facets();
396 for (
auto fi = 0; fi < m.get_num_facets(); fi++) {
397 flattened.row(3 * fi + 0) = data.row(F(fi, 0)).template cast<float>();
398 flattened.row(3 * fi + 1) = data.row(F(fi, 1)).template cast<float>();
399 flattened.row(3 * fi + 2) = data.row(F(fi, 2)).template cast<float>();
402 (*gpu).vbo().upload(std::move(flattened));
405template <
typename MeshType>
406std::unordered_map<entt::id_type, std::shared_ptr<GPUBuffer>> upload_submesh_indices(
407 const MeshBase* mesh_base,
408 const std::string& facet_attrib_name)
410 auto& m =
reinterpret_cast<const MeshType&
>(*mesh_base);
412 const auto& sub_ids = m.get_facet_attribute(facet_attrib_name);
414 using FacetArray =
typename MeshType::FacetArray;
416 std::unordered_map<entt::id_type, std::shared_ptr<GPUBuffer>> result;
417 std::unordered_map<entt::id_type, size_t> sub_counts;
418 std::unordered_map<entt::id_type, FacetArray> submesh_triangles;
421 for (
auto fi = 0; fi < m.get_num_facets(); fi++) {
422 auto id = entt::id_type(sub_ids(fi, 0));
423 auto it = sub_counts.find(
id);
424 if (it == sub_counts.end())
425 sub_counts.insert({id, 1});
431 for (
auto& it : sub_counts) {
432 submesh_triangles.insert({it.first, FacetArray(it.second, 3)});
436 for (
auto fi = m.get_num_facets() - 1; fi >= 0; fi--) {
437 auto id = entt::id_type(sub_ids(fi, 0));
438 auto& counter = sub_counts.at(
id);
439 auto& triangles = submesh_triangles.at(
id);
440 triangles(counter - 1, 0) = 3 * fi + 0;
441 triangles(counter - 1, 1) = 3 * fi + 1;
442 triangles(counter - 1, 2) = 3 * fi + 2;
446 for (
auto& it : sub_counts) {
447 assert(it.second == 0);
451 for (
auto& it : submesh_triangles) {
452 auto buf = std::make_shared<GPUBuffer>(GL_ELEMENT_ARRAY_BUFFER);
453 upload_facets(it.second, buf.get());
454 result.insert({it.first, std::move(buf)});
466template <
typename MeshType>
467bool has_mesh_vertex_attribute(
const MeshBase* d,
const std::string& name)
469 return reinterpret_cast<const MeshType&
>(*d).has_vertex_attribute(name);
471template <
typename MeshType>
472bool has_mesh_corner_attribute(
const MeshBase* d,
const std::string& name)
474 return reinterpret_cast<const MeshType&
>(*d).has_corner_attribute(name);
476template <
typename MeshType>
477bool has_mesh_facet_attribute(
const MeshBase* d,
const std::string& name)
479 return reinterpret_cast<const MeshType&
>(*d).has_facet_attribute(name);
481template <
typename MeshType>
482bool has_mesh_edge_attribute(
const MeshBase* d,
const std::string& name)
484 return reinterpret_cast<const MeshType&
>(*d).has_edge_attribute(name);
486template <
typename MeshType>
487bool has_mesh_indexed_attribute(
const MeshBase* d,
const std::string& name)
489 return reinterpret_cast<const MeshType&
>(*d).has_indexed_attribute(name);
496template <
typename MeshType>
498 const MeshBase* mesh_base,
499 const Eigen::Vector3f& origin,
500 const Eigen::Vector3f& dir,
503 auto& m =
reinterpret_cast<const MeshType&
>(*mesh_base);
504 using Scalar =
typename MeshType::Scalar;
508 bool res = igl::ray_mesh_intersect(
509 origin.cast<Scalar>(),
515 if (!res)
return false;
517 out->facet_id = ihit.id;
519 out->barycentric = Eigen::Vector3f(1.0f - ihit.u - ihit.v, ihit.u, ihit.v);
524template <
typename MeshType>
525bool select_facets_in_frustum(
528 const Frustum* frustum_ptr)
530 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
531 const auto& frustum = *frustum_ptr;
532 using Scalar =
typename MeshType::Scalar;
533 using Point = Eigen::Matrix<Scalar, 3, 1>;
537 return lagrange::select_facets_in_frustum<MeshType, Point>(
539 frustum.planes[FRUSTUM_LEFT].cast<Scalar>().normal().eval(),
540 frustum.planes[FRUSTUM_LEFT].cast<Scalar>().projection(Point::Zero()),
541 frustum.planes[FRUSTUM_BOTTOM].cast<Scalar>().normal().eval(),
542 frustum.planes[FRUSTUM_BOTTOM].cast<Scalar>().projection(Point::Zero()),
543 frustum.planes[FRUSTUM_RIGHT].cast<Scalar>().normal().eval(),
544 frustum.planes[FRUSTUM_RIGHT].cast<Scalar>().projection(Point::Zero()),
545 frustum.planes[FRUSTUM_TOP].cast<Scalar>().normal().eval(),
546 frustum.planes[FRUSTUM_TOP].cast<Scalar>().projection(Point::Zero()));
549template <
typename MeshType>
550void select_vertices_in_frustum(
552 SelectionBehavior sel_behavior,
553 const Frustum* frustum_ptr)
555 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
556 const auto& frustum = *frustum_ptr;
558 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input is not a mesh.");
559 using AttributeArray =
typename MeshType::AttributeArray;
560 using Scalar =
typename MeshType::Scalar;
561 using Index =
typename MeshType::Index;
563 const auto num_vertices = mesh.get_num_vertices();
564 const auto& vertices = mesh.get_vertices();
568 if (!mesh.has_vertex_attribute(
"is_selected")) {
569 mesh.add_vertex_attribute(
"is_selected");
570 attr = AttributeArray(num_vertices, 1);
572 mesh.export_vertex_attribute(
"is_selected", attr);
577 if (sel_behavior == SelectionBehavior::SET) {
580 using Scalar =
typename MeshType::Scalar;
581 const Scalar value = (sel_behavior != SelectionBehavior::ERASE) ? Scalar(1) : Scalar(0);
585 tbb::blocked_range<Index>(0, num_vertices),
586 [&value, &attr, &frustum, &vertices](
const tbb::blocked_range<Index>& tbb_range) {
587 for (
auto vi = tbb_range.begin(); vi != tbb_range.end(); vi++) {
588 if (tbb_utils::is_cancelled()) break;
589 if (frustum.contains(vertices.row(vi).template cast<float>())) {
595 mesh.import_vertex_attribute(
"is_selected", attr);
598template <
typename MeshType>
599void select_edges_in_frustum(
608template <
typename MeshType>
609void propagate_corner_selection(MeshBase* mesh_base,
const std::string& attrib_name)
611 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
613 static_assert(MeshTrait<MeshType>::is_mesh(),
"MeshType is not a mesh");
615 using Index =
typename MeshType::Index;
618 const Index num_facets = mesh.get_num_facets();
619 const Index vertex_per_facet = mesh.get_vertex_per_facet();
621 const auto& facets = mesh.get_facets();
624 typename MeshType::AttributeArray corner_attrib;
625 mesh.export_corner_attribute(attrib_name, corner_attrib);
627 typename MeshType::AttributeArray vertex_attrib;
628 mesh.export_vertex_attribute(attrib_name, vertex_attrib);
630 vertex_attrib.setZero();
635 for (Index i = 0; i < num_facets; i++) {
636 for (Index j = 0; j < vertex_per_facet; j++) {
637 if (corner_attrib(i * vertex_per_facet + j) != 0.0f) {
638 vertex_attrib(facets(i, j)) = 1.0f;
644 for (Index i = 0; i < num_facets; i++) {
645 for (Index j = 0; j < vertex_per_facet; j++) {
646 if (vertex_attrib(facets(i, j)) != 0.0f) {
647 corner_attrib(i * vertex_per_facet + j) = 1.0f;
652 mesh.import_vertex_attribute(attrib_name, vertex_attrib);
653 mesh.import_corner_attribute(attrib_name, corner_attrib);
657template <
typename MeshType>
658void propagate_vertex_selection(MeshBase* mesh_base,
const std::string& attrib_name)
660 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
661 static_assert(MeshTrait<MeshType>::is_mesh(),
"MeshType is not a mesh");
663 using Index =
typename MeshType::Index;
667 const Index num_facets = mesh.get_num_facets();
668 const Index vertex_per_facet = mesh.get_vertex_per_facet();
670 const auto& facets = mesh.get_facets();
672 typename MeshType::AttributeArray corner_attrib;
673 mesh.export_corner_attribute(attrib_name, corner_attrib);
675 const typename MeshType::AttributeArray& vertex_attrib = mesh.get_vertex_attribute(attrib_name);
678 tbb::blocked_range<Index>(0, num_facets),
679 [&](
const tbb::blocked_range<Index>& tbb_range) {
680 for (
auto fi = tbb_range.begin(); fi != tbb_range.end(); fi++) {
681 if (tbb_utils::is_cancelled()) break;
683 for (Index j = 0; j < vertex_per_facet; j++) {
684 if (vertex_attrib(facets(fi, j)) != 0.0f) {
685 corner_attrib(fi * vertex_per_facet + j) = 1.0f;
687 corner_attrib(fi * vertex_per_facet + j) = 0.0f;
693 mesh.import_corner_attribute(attrib_name, corner_attrib);
696template <
typename MeshType>
697void propagate_facet_selection(MeshBase* mesh_base,
const std::string& attrib_name)
699 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
702 const auto per_facet = mesh.get_vertex_per_facet();
703 const auto& facet_attr = mesh.get_facet_attribute(attrib_name);
705 using AttributeArray =
typename MeshType::AttributeArray;
707 AttributeArray vertex_attr;
708 mesh.export_vertex_attribute(attrib_name, vertex_attr);
709 vertex_attr.setZero();
711 const auto& F = mesh.get_facets();
714 for (
auto fi = 0; fi < F.rows(); fi++) {
715 for (
auto j = 0; j < per_facet; j++) {
716 auto val = facet_attr(fi);
718 vertex_attr(F(fi, j)) = val;
722 mesh.import_vertex_attribute(attrib_name, vertex_attr);
725 lagrange::map_vertex_attribute_to_corner_attribute(mesh, attrib_name);
733template <
typename MeshType>
734void combine_vertex_and_corner_selection(MeshBase* mesh_base,
const std::string& attrib_name)
736 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
738 using AttribArray =
typename MeshType::AttributeArray;
740 const auto num_facets = mesh.get_num_facets();
741 const auto vertex_per_facet = mesh.get_vertex_per_facet();
742 const auto& facets = mesh.get_facets();
744 const AttribArray& vertex_attrib = mesh.get_vertex_attribute(attrib_name);
746 AttribArray corner_attrib;
747 mesh.export_corner_attribute(attrib_name, corner_attrib);
749 using Index =
typename MeshType::Index;
750 using Scalar =
typename MeshType::Scalar;
753 tbb::blocked_range<Index>(0, num_facets),
754 [&](
const tbb::blocked_range<Index>& tbb_range) {
755 for (
auto fi = tbb_range.begin(); fi != tbb_range.end(); fi++) {
756 if (tbb_utils::is_cancelled()) break;
757 for (Index j = 0; j < vertex_per_facet; j++) {
758 auto& corner_val = corner_attrib(fi * vertex_per_facet + j);
759 if (vertex_attrib(facets(fi, j)) != Scalar(0) && corner_val != Scalar(0)) {
760 corner_val = Scalar(1);
762 corner_val = Scalar(0);
768 mesh.import_corner_attribute(attrib_name, corner_attrib);
771template <
typename MeshType>
772void select_facets_by_color(
774 const std::string& attrib_name,
775 SelectionBehavior sel_behavior,
776 const unsigned char* color_bytes,
777 size_t colors_byte_size)
779 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
781 using Attr =
typename MeshType::AttributeArray;
783 mesh.export_facet_attribute(attrib_name, attrib);
785 if (sel_behavior == SelectionBehavior::SET) {
788 using Scalar =
typename MeshType::Scalar;
789 const auto value = (sel_behavior != SelectionBehavior::ERASE) ? Scalar(1) : Scalar(0);
791 const size_t pixel_size = 4;
792 for (
size_t i = 0; i < colors_byte_size / pixel_size; i++) {
794 color_bytes[pixel_size * i + 0],
795 color_bytes[pixel_size * i + 1],
796 color_bytes[pixel_size * i + 2]);
801 mesh.import_facet_attribute(attrib_name, attrib);
804template <
typename MeshType>
805void select_edges_by_color(
807 const std::string& attrib_name,
808 SelectionBehavior sel_behavior,
809 const unsigned char* color_bytes,
810 size_t colors_byte_size)
812 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
814 using Attr =
typename MeshType::AttributeArray;
816 mesh.export_corner_attribute(attrib_name, attrib);
819 if (sel_behavior == SelectionBehavior::SET) {
822 using Scalar =
typename MeshType::Scalar;
823 const auto value = (sel_behavior != SelectionBehavior::ERASE) ? Scalar(1) : Scalar(0);
825 const size_t pixel_size = 4;
826 for (
size_t i = 0; i < colors_byte_size / pixel_size; i++) {
828 color_bytes[pixel_size * i + 0],
829 color_bytes[pixel_size * i + 1],
830 color_bytes[pixel_size * i + 2]);
833 const auto face_id =
id / 3;
834 const auto edge_id =
id % 3;
835 attrib(face_id * 3 + (edge_id + 1) % 3) = value;
836 attrib(face_id * 3 + (edge_id + 2) % 3) = value;
838 mesh.import_corner_attribute(attrib_name, attrib);
841template <
typename MeshType>
842void select_vertices_by_color(
844 const std::string& attrib_name,
845 SelectionBehavior sel_behavior,
846 const unsigned char* color_bytes,
847 size_t colors_byte_size)
849 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
851 using Attr =
typename MeshType::AttributeArray;
853 mesh.export_corner_attribute(attrib_name, attrib);
855 if (sel_behavior == SelectionBehavior::SET) {
858 using Scalar =
typename MeshType::Scalar;
859 const auto value = (sel_behavior != SelectionBehavior::ERASE) ? Scalar(1) : Scalar(0);
862 const size_t pixel_size = 4;
863 for (
size_t i = 0; i < colors_byte_size / pixel_size; i++) {
865 color_bytes[pixel_size * i + 0],
866 color_bytes[pixel_size * i + 1],
867 color_bytes[pixel_size * i + 2]);
871 mesh.import_corner_attribute(attrib_name, attrib);
875template <
typename MeshType>
878 SelectionBehavior sel_behavior,
879 const std::vector<int>* facet_indices)
881 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
883 const auto attrib_name =
"is_selected";
884 using Attr =
typename MeshType::AttributeArray;
886 mesh.export_facet_attribute(attrib_name, attrib);
888 if (sel_behavior == SelectionBehavior::SET) {
892 using Scalar =
typename MeshType::Scalar;
893 const auto value = (sel_behavior != SelectionBehavior::ERASE) ? Scalar(1) : Scalar(0);
895 for (
auto i : (*facet_indices)) {
896 attrib(i, 0) = value;
899 mesh.import_facet_attribute(attrib_name, attrib);
903template <
typename MeshType>
904void filter_closest_vertex(
906 const std::string& attrib_name,
907 SelectionBehavior sel_behavior,
908 const Camera& camera,
909 const Eigen::Vector2i& viewport_pos)
911 auto& mesh =
reinterpret_cast<MeshType&
>(*mesh_base);
912 using AttribArray =
typename MeshType::AttributeArray;
914 const auto num_vertices = mesh.get_num_vertices();
915 const auto& vertices = mesh.get_vertices();
917 AttribArray vertex_attrib;
918 mesh.export_vertex_attribute(attrib_name, vertex_attrib);
920 using Index =
typename MeshType::Index;
921 using Scalar =
typename MeshType::Scalar;
925 int screen_diff = std::numeric_limits<int>::max();
926 float min_depth = std::numeric_limits<float>::max();
927 Index min_vi = lagrange::invalid<Index>();
928 std::vector<Index> equivalence = {};
931 tbb::enumerable_thread_specific<LocalBuffer> temp_vars;
934 tbb::blocked_range<Index>(0, num_vertices),
935 [&](
const tbb::blocked_range<Index>& tbb_range) {
936 auto& min_screen_diff = temp_vars.local().screen_diff;
937 auto& min_depth = temp_vars.local().min_depth;
938 auto& min_vi = temp_vars.local().min_vi;
939 auto& equiv = temp_vars.local().equivalence;
941 for (
auto vi = tbb_range.begin(); vi != tbb_range.end(); vi++) {
942 if (tbb_utils::is_cancelled()) break;
944 if (vertex_attrib(vi) == 0.0f) continue;
947 camera.project_with_depth(vertices.row(vi).template cast<float>());
949 (Eigen::Vector2i(int(proj.x()), int(camera.get_window_height() - proj.y())) -
953 if (diff == min_screen_diff && proj.z() == min_depth) {
956 proj.z() < min_depth || (proj.z() == min_depth && diff < min_screen_diff)) {
957 min_screen_diff = diff;
958 min_depth = proj.z();
967 LocalBuffer final_buffer;
968 for (
auto& var : temp_vars) {
969 if (var.min_vi == lagrange::invalid<Index>())
continue;
971 if (var.screen_diff == final_buffer.screen_diff &&
972 var.min_depth == final_buffer.min_depth) {
973 final_buffer.equivalence.push_back(var.min_vi);
974 for (
auto e : var.equivalence) {
975 final_buffer.equivalence.push_back(e);
978 var.min_depth < final_buffer.min_depth ||
979 (var.screen_diff < final_buffer.screen_diff &&
980 var.min_depth == final_buffer.min_depth)) {
981 final_buffer.screen_diff = var.screen_diff;
982 final_buffer.min_depth = var.min_depth;
983 final_buffer.min_vi = var.min_vi;
984 final_buffer.equivalence.clear();
988 if (sel_behavior == SelectionBehavior::SET) {
989 vertex_attrib.setZero();
992 const auto value = (sel_behavior != SelectionBehavior::ERASE) ? Scalar(1) : Scalar(0);
994 if (final_buffer.min_vi != lagrange::invalid<Index>()) {
995 vertex_attrib(final_buffer.min_vi, 0) = value;
996 for (
auto equiv_vi : final_buffer.equivalence) {
997 vertex_attrib(equiv_vi, 0) = value;
1003 mesh.import_vertex_attribute(attrib_name, vertex_attrib);
1010template <
typename MeshType>
1011void register_mesh_type(
1012 [[maybe_unused]]
const std::string& display_name = entt::type_id<MeshType>().name().data())
1014 using namespace entt::literals;
1017 entt::meta<MeshType>().template base<lagrange::MeshBase>();
1020 using VertexArray =
typename MeshType::VertexArray;
1022 entt::meta<RowMajorMatrixXf>().template ctor<&detail::eigen_convert_to_float<VertexArray>>();
1025 entt::meta<MeshType>().template func<&detail::get_num_vertices<MeshType>>(
1026 "get_num_vertices"_hs);
1027 entt::meta<MeshType>().template func<&detail::get_num_edges<MeshType>>(
"get_num_edges"_hs);
1028 entt::meta<MeshType>().template func<&detail::get_num_facets<MeshType>>(
"get_num_facets"_hs);
1030 entt::meta<MeshType>().template func<&detail::get_mesh_vertices<MeshType>>(
1031 "get_mesh_vertices"_hs);
1033 entt::meta<MeshType>().template func<&detail::get_mesh_facets<MeshType>>(
"get_mesh_facets"_hs);
1034 entt::meta<MeshType>().template func<&detail::get_mesh_vertex_attribute<MeshType>>(
1035 "get_mesh_vertex_attribute"_hs);
1036 entt::meta<MeshType>().template func<&detail::get_mesh_corner_attribute<MeshType>>(
1037 "get_mesh_corner_attribute"_hs);
1038 entt::meta<MeshType>().template func<&detail::get_mesh_facet_attribute<MeshType>>(
1039 "get_mesh_facet_attribute"_hs);
1040 entt::meta<MeshType>().template func<&detail::get_mesh_edge_attribute<MeshType>>(
1041 "get_mesh_edge_attribute"_hs);
1042 entt::meta<MeshType>().template func<&detail::get_mesh_attribute<MeshType>>(
1043 "get_mesh_attribute"_hs);
1045 entt::meta<MeshType>().template func<&detail::get_mesh_attribute_range<MeshType>>(
1046 "get_mesh_attribute_range"_hs);
1048 entt::meta<MeshType>().template func<&detail::get_mesh_bounds<MeshType>>(
"get_mesh_bounds"_hs);
1052 entt::meta<MeshType>().template func<&detail::ensure_uv<MeshType>>(
"ensure_uv"_hs);
1053 entt::meta<MeshType>().template func<&detail::ensure_normal<MeshType>>(
"ensure_normal"_hs);
1054 entt::meta<MeshType>().template func<&detail::ensure_tangent_bitangent<MeshType>>(
1055 "ensure_tangent_bitangent"_hs);
1056 entt::meta<MeshType>().template func<&detail::ensure_is_selected_attribute<MeshType>>(
1057 "ensure_is_selected_attribute"_hs);
1058 entt::meta<MeshType>()
1059 .template func<&detail::map_indexed_attribute_to_corner_attribute<MeshType>>(
1060 "map_indexed_attribute_to_corner_attribute"_hs);
1061 entt::meta<MeshType>()
1062 .template func<&detail::map_corner_attribute_to_vertex_attribute<MeshType>>(
1063 "map_corner_attribute_to_vertex_attribute"_hs);
1067 entt::meta<MeshType>().template func<&detail::upload_mesh_vertices<MeshType>>(
1068 "upload_mesh_vertices"_hs);
1069 entt::meta<MeshType>().template func<&detail::upload_mesh_triangles<MeshType>>(
1070 "upload_mesh_triangles"_hs);
1071 entt::meta<MeshType>().template func<&detail::upload_mesh_vertex_attribute<MeshType>>(
1072 "upload_mesh_vertex_attribute"_hs);
1073 entt::meta<MeshType>().template func<&detail::upload_mesh_corner_attribute<MeshType>>(
1074 "upload_mesh_corner_attribute"_hs);
1075 entt::meta<MeshType>().template func<&detail::upload_mesh_facet_attribute<MeshType>>(
1076 "upload_mesh_facet_attribute"_hs);
1077 entt::meta<MeshType>().template func<&detail::upload_mesh_edge_attribute<MeshType>>(
1078 "upload_mesh_edge_attribute"_hs);
1079 entt::meta<MeshType>().template func<&detail::upload_submesh_indices<MeshType>>(
1080 "upload_submesh_indices"_hs);
1084 entt::meta<MeshType>().template func<&detail::has_mesh_vertex_attribute<MeshType>>(
1085 "has_mesh_vertex_attribute"_hs);
1086 entt::meta<MeshType>().template func<&detail::has_mesh_corner_attribute<MeshType>>(
1087 "has_mesh_corner_attribute"_hs);
1088 entt::meta<MeshType>().template func<&detail::has_mesh_facet_attribute<MeshType>>(
1089 "has_mesh_facet_attribute"_hs);
1090 entt::meta<MeshType>().template func<&detail::has_mesh_edge_attribute<MeshType>>(
1091 "has_mesh_edge_attribute"_hs);
1092 entt::meta<MeshType>().template func<&detail::has_mesh_indexed_attribute<MeshType>>(
1093 "has_mesh_indexed_attribute"_hs);
1097 entt::meta<MeshType>().template func<&detail::intersect_ray<MeshType>>(
"intersect_ray"_hs);
1099 entt::meta<MeshType>().template func<&detail::select_vertices_in_frustum<MeshType>>(
1100 "select_vertices_in_frustum"_hs);
1101 entt::meta<MeshType>().template func<&detail::select_facets_in_frustum<MeshType>>(
1102 "select_facets_in_frustum"_hs);
1103 entt::meta<MeshType>().template func<&detail::select_edges_in_frustum<MeshType>>(
1104 "select_edges_in_frustum"_hs);
1107 entt::meta<MeshType>().template func<&detail::propagate_corner_selection<MeshType>>(
1108 "propagate_corner_selection"_hs);
1109 entt::meta<MeshType>().template func<&detail::propagate_vertex_selection<MeshType>>(
1110 "propagate_vertex_selection"_hs);
1111 entt::meta<MeshType>().template func<&detail::propagate_facet_selection<MeshType>>(
1112 "propagate_facet_selection"_hs);
1113 entt::meta<MeshType>().template func<&detail::combine_vertex_and_corner_selection<MeshType>>(
1114 "combine_vertex_and_corner_selection"_hs);
1117 entt::meta<MeshType>().template func<&detail::select_facets_by_color<MeshType>>(
1118 "select_facets_by_color"_hs);
1119 entt::meta<MeshType>().template func<&detail::select_edges_by_color<MeshType>>(
1120 "select_edges_by_color"_hs);
1121 entt::meta<MeshType>().template func<&detail::select_vertices_by_color<MeshType>>(
1122 "select_vertices_by_color"_hs);
1124 entt::meta<MeshType>().template func<&detail::select_facets<MeshType>>(
"select_facets"_hs);
1125 entt::meta<MeshType>().template func<&detail::filter_closest_vertex<MeshType>>(
1126 "filter_closest_vertex"_hs);
Index get_num_edges() const
Gets the number of edges.
Definition: Mesh.h:650
AttributeId compute_vertex_normal(SurfaceMesh< Scalar, Index > &mesh, VertexNormalOptions options={})
Compute per-vertex normals based on specified weighting type.
Definition: compute_vertex_normal.cpp:33
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
Lagrange UI Viewer and mini 3D engine.
Definition: AcceleratedPicking.h:22
LA_UI_API bool is_id_background(int id)
Is numerical ID from shader a background?
Definition: objectid_viewport.cpp:38
LA_UI_API int color_to_id(unsigned char r, unsigned char g, unsigned char b)
Translates shader output color to numerial ID.
Definition: objectid_viewport.cpp:32
LA_UI_API std::optional< std::pair< Entity, RayFacetHit > > intersect_ray(Registry &r, const Eigen::Vector3f &origin, const Eigen::Vector3f &dir, ui::Entity root=ui::NullEntity, Layer visible_layers=Layer(true), Layer hidden_layers=Layer(false))
Intersect ray with meshes in root's hierarchy Returns a pair of intersected entity and the correspond...
Definition: default_entities.cpp:502
Main namespace for Lagrange.
Definition: AABBIGL.h:30