Lagrange
Loading...
Searching...
No Matches
bind_simple_scene.h
1/*
2 * Copyright 2023 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/python/tensor_utils.h>
15#include <lagrange/scene/SimpleScene.h>
16#include <lagrange/scene/simple_scene_convert.h>
17#include <lagrange/utils/assert.h>
18
19#include <Eigen/Core>
20
21#include <type_traits>
22
23namespace lagrange::python {
24
25namespace nb = nanobind;
26
27template <typename Scalar, typename Index>
28void bind_simple_scene(nb::module_& m)
29{
30 using MeshInstance3D = lagrange::scene::MeshInstance<Scalar, Index, 3>;
31 nb::class_<MeshInstance3D>(m, "MeshInstance3D", "A single mesh instance in a scene")
32 .def(nb::init<>())
33 .def_rw("mesh_index", &MeshInstance3D::mesh_index)
34 .def_prop_rw(
35 "transform",
36 [](MeshInstance3D& self) {
37 auto& M = self.transform.matrix();
38 using MatrixType = std::decay_t<decltype(M)>;
39 static_assert(!MatrixType::IsRowMajor, "Transformation matrix is not column major");
40
41 span<Scalar> data(M.data(), M.size());
42 size_t shape[2]{static_cast<size_t>(M.rows()), static_cast<size_t>(M.cols())};
43 int64_t stride[2]{1, 4};
44 return span_to_tensor(data, shape, stride, nb::cast(&self));
45 },
46 [](MeshInstance3D& self, Tensor<Scalar> tensor) {
47 auto [values, shape, stride] = tensor_to_span(tensor);
48 auto& M = self.transform.matrix();
49 using MatrixType = std::decay_t<decltype(M)>;
50 static_assert(!MatrixType::IsRowMajor, "Transformation matrix is not column major");
51
52 la_runtime_assert(is_dense(shape, stride));
53 la_runtime_assert(check_shape(shape, 4, 4));
54 if (stride[0] == 1) {
55 // Tensor is col major.
56 std::copy(values.begin(), values.end(), M.data());
57 } else {
58 // Tensor is row major.
59 M(0, 0) = values[0];
60 M(0, 1) = values[1];
61 M(0, 2) = values[2];
62 M(0, 3) = values[3];
63
64 M(1, 0) = values[4];
65 M(1, 1) = values[5];
66 M(1, 2) = values[6];
67 M(1, 3) = values[7];
68
69 M(2, 0) = values[8];
70 M(2, 1) = values[9];
71 M(2, 2) = values[10];
72 M(2, 3) = values[11];
73
74 M(3, 0) = values[12];
75 M(3, 1) = values[13];
76 M(3, 2) = values[14];
77 M(3, 3) = values[15];
78 }
79 });
80
81 using SimpleScene3D = lagrange::scene::SimpleScene<Scalar, Index, 3>;
82 nb::class_<SimpleScene3D>(m, "SimpleScene3D", "Simple scene container for instanced meshes")
83 .def(nb::init<>())
84 .def_prop_ro("num_meshes", &SimpleScene3D::get_num_meshes, "Number of meshes in the scene")
85 .def("num_instances", &SimpleScene3D::get_num_instances, "mesh_index"_a)
86 .def_prop_ro(
87 "total_num_instances",
88 &SimpleScene3D::compute_num_instances,
89 "Total number of instances for all meshes in the scene")
90 .def("get_mesh", &SimpleScene3D::get_mesh, "mesh_index"_a)
91 .def("ref_mesh", &SimpleScene3D::ref_mesh, "mesh_index"_a)
92 .def("get_instance", &SimpleScene3D::get_instance, "mesh_index"_a, "instance_index"_a)
93 .def("reserve_meshes", &SimpleScene3D::reserve_meshes, "num_meshes"_a)
94 .def("add_mesh", &SimpleScene3D::add_mesh, "mesh"_a)
95 .def(
96 "reserve_instances",
97 &SimpleScene3D::reserve_instances,
98 "mesh_index"_a,
99 "num_instances"_a)
100 .def("add_instance", &SimpleScene3D::add_instance, "instance"_a);
101
102 // Mesh to scene + scene to mesh
103
104 m.def(
105 "simple_scene_to_mesh",
106 [](const SimpleScene3D& scene,
107 bool normalize_normals,
108 bool normalize_tangents_bitangents,
109 bool preserve_attributes) {
110 TransformOptions transform_options;
111 transform_options.normalize_normals = normalize_normals;
112 transform_options.normalize_tangents_bitangents = normalize_tangents_bitangents;
113 return scene::simple_scene_to_mesh(scene, transform_options, preserve_attributes);
114 },
115 "scene"_a,
116 "normalize_normals"_a = TransformOptions{}.normalize_normals,
117 "normalize_tangents_bitangents"_a = TransformOptions{}.normalize_tangents_bitangents,
118 "preserve_attributes"_a = true,
119 R"(Converts a scene into a concatenated mesh with all the transforms applied.
120
121:param scene: Scene to convert.
122:param normalize_normals: If enabled, normals are normalized after transformation.
123:param normalize_tangents_bitangents: If enabled, tangents and bitangents are normalized after transformation.
124:param preserve_attributes: Preserve shared attributes and map them to the output mesh.
125
126:return: Concatenated mesh.)");
127
128 using MeshType = lagrange::SurfaceMesh<Scalar, Index>;
129 m.def(
130 "mesh_to_simple_scene",
131 [](const MeshType& mesh) { return scene::mesh_to_simple_scene<3>(mesh); },
132 "mesh"_a,
133 R"(Converts a single mesh into a simple scene with a single identity instance of the input mesh.
134
135:param mesh: Input mesh to convert.
136
137:return: Simple scene containing the input mesh.)");
138
139 m.def(
140 "meshes_to_simple_scene",
141 [](std::vector<MeshType> meshes) {
142 return scene::meshes_to_simple_scene<3>(std::move(meshes));
143 },
144 "meshes"_a,
145 R"(Converts a list of meshes into a simple scene with a single identity instance of each input mesh.
146
147:param meshes: Input meshes to convert.
148
149:return: Simple scene containing the input meshes.)");
150}
151
152} // namespace lagrange::python
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
::nonstd::span< T, Extent > span
A bounds-safe view for sequences of objects.
Definition span.h:27