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/compute_mesh_weights.h>
17#include <lagrange/scene/filter_instances.h>
18#include <lagrange/scene/simple_scene_convert.h>
19#include <lagrange/utils/assert.h>
20
21#include <Eigen/Core>
22
23#include <functional>
24#include <type_traits>
25
26namespace lagrange::python {
27
28namespace nb = nanobind;
29
30template <typename Scalar, typename Index>
31void bind_simple_scene(nb::module_& m)
32{
33 using MeshInstance3D = lagrange::scene::MeshInstance<Scalar, Index, 3>;
34 nb::class_<MeshInstance3D>(m, "MeshInstance3D", "A single mesh instance in a scene")
35 .def(
36 nb::init<>(),
37 "Creates a new mesh instance with identity transform and mesh_index of 0.")
38 .def_rw(
39 "mesh_index",
40 &MeshInstance3D::mesh_index,
41 "Index of the mesh in the scene's mesh array.")
42 .def_prop_rw(
43 "transform",
44 [](MeshInstance3D& self) {
45 auto& M = self.transform.matrix();
46 using MatrixType = std::decay_t<decltype(M)>;
47 static_assert(!MatrixType::IsRowMajor, "Transformation matrix is not column major");
48
49 span<Scalar> data(M.data(), M.size());
50 size_t shape[2]{static_cast<size_t>(M.rows()), static_cast<size_t>(M.cols())};
51 int64_t stride[2]{1, 4};
52 return span_to_tensor(data, shape, stride, nb::cast(&self));
53 },
54 [](MeshInstance3D& self, Tensor<Scalar> tensor) {
55 auto [values, shape, stride] = tensor_to_span(tensor);
56 auto& M = self.transform.matrix();
57 using MatrixType = std::decay_t<decltype(M)>;
58 static_assert(!MatrixType::IsRowMajor, "Transformation matrix is not column major");
59
60 la_runtime_assert(is_dense(shape, stride));
61 la_runtime_assert(check_shape(shape, 4, 4));
62 if (stride[0] == 1) {
63 // Tensor is col major.
64 std::copy(values.begin(), values.end(), M.data());
65 } else {
66 // Tensor is row major.
67 M(0, 0) = values[0];
68 M(0, 1) = values[1];
69 M(0, 2) = values[2];
70 M(0, 3) = values[3];
71
72 M(1, 0) = values[4];
73 M(1, 1) = values[5];
74 M(1, 2) = values[6];
75 M(1, 3) = values[7];
76
77 M(2, 0) = values[8];
78 M(2, 1) = values[9];
79 M(2, 2) = values[10];
80 M(2, 3) = values[11];
81
82 M(3, 0) = values[12];
83 M(3, 1) = values[13];
84 M(3, 2) = values[14];
85 M(3, 3) = values[15];
86 }
87 },
88 R"(4x4 transformation matrix for this instance.
89
90The transformation matrix is stored in column-major order. Both row-major and column-major
91input tensors are supported for setting the transform.)");
92
93 using SimpleScene3D = lagrange::scene::SimpleScene<Scalar, Index, 3>;
94 nb::class_<SimpleScene3D>(m, "SimpleScene3D", "Simple scene container for instanced meshes")
95 .def(nb::init<>(), "Creates an empty scene with no meshes or instances.")
96 .def_prop_ro("num_meshes", &SimpleScene3D::get_num_meshes, "Number of meshes in the scene")
97 .def(
98 "num_instances",
99 &SimpleScene3D::get_num_instances,
100 "mesh_index"_a,
101 R"(Gets the number of instances for a specific mesh.
102
103:param mesh_index: Index of the mesh.
104
105:return: Number of instances of the specified mesh.)")
106 .def_prop_ro(
107 "total_num_instances",
108 &SimpleScene3D::compute_num_instances,
109 "Total number of instances for all meshes in the scene")
110 .def(
111 "get_mesh",
112 &SimpleScene3D::get_mesh,
113 "mesh_index"_a,
114 R"(Gets a copy of the mesh at the specified index.
115
116:param mesh_index: Index of the mesh.
117
118:return: Copy of the mesh.)")
119 .def(
120 "ref_mesh",
121 &SimpleScene3D::ref_mesh,
122 "mesh_index"_a,
123 R"(Gets a reference to the mesh at the specified index.
124
125:param mesh_index: Index of the mesh.
126
127:return: Reference to the mesh.)")
128 .def(
129 "get_instance",
130 &SimpleScene3D::get_instance,
131 "mesh_index"_a,
132 "instance_index"_a,
133 R"(Gets a specific instance of a mesh.
134
135:param mesh_index: Index of the mesh.
136:param instance_index: Index of the instance for that mesh.
137
138:return: The mesh instance.)")
139 .def(
140 "reserve_meshes",
141 &SimpleScene3D::reserve_meshes,
142 "num_meshes"_a,
143 R"(Reserves storage for meshes.
144
145:param num_meshes: Number of meshes to reserve space for.)")
146 .def(
147 "add_mesh",
148 &SimpleScene3D::add_mesh,
149 "mesh"_a,
150 R"(Adds a mesh to the scene.
151
152:param mesh: Mesh to add.
153
154:return: Index of the newly added mesh.)")
155 .def(
156 "reserve_instances",
157 &SimpleScene3D::reserve_instances,
158 "mesh_index"_a,
159 "num_instances"_a,
160 R"(Reserves storage for instances of a specific mesh.
161
162:param mesh_index: Index of the mesh.
163:param num_instances: Number of instances to reserve space for.)")
164 .def(
165 "add_instance",
166 &SimpleScene3D::add_instance,
167 "instance"_a,
168 R"(Adds an instance to the scene.
169
170:param instance: Mesh instance to add.
171
172:return: Index of the newly added instance for its mesh.)");
173
174 // Mesh to scene + scene to mesh
175
176 m.def(
177 "simple_scene_to_mesh",
178 [](const SimpleScene3D& scene,
179 bool normalize_normals,
180 bool normalize_tangents_bitangents,
181 bool preserve_attributes) {
182 TransformOptions transform_options;
183 transform_options.normalize_normals = normalize_normals;
184 transform_options.normalize_tangents_bitangents = normalize_tangents_bitangents;
185 return scene::simple_scene_to_mesh(scene, transform_options, preserve_attributes);
186 },
187 "scene"_a,
188 "normalize_normals"_a = TransformOptions{}.normalize_normals,
189 "normalize_tangents_bitangents"_a = TransformOptions{}.normalize_tangents_bitangents,
190 "preserve_attributes"_a = true,
191 R"(Converts a scene into a concatenated mesh with all the transforms applied.
192
193:param scene: Scene to convert.
194:param normalize_normals: If enabled, normals are normalized after transformation.
195:param normalize_tangents_bitangents: If enabled, tangents and bitangents are normalized after transformation.
196:param preserve_attributes: Preserve shared attributes and map them to the output mesh.
197
198:return: Concatenated mesh.)");
199
200 m.def(
201 "simple_scene_to_meshes",
202 [](const SimpleScene3D& scene, bool normalize_normals, bool normalize_tangents_bitangents) {
203 TransformOptions transform_options;
204 transform_options.normalize_normals = normalize_normals;
205 transform_options.normalize_tangents_bitangents = normalize_tangents_bitangents;
206 return scene::simple_scene_to_meshes(scene, transform_options);
207 },
208 "scene"_a,
209 "normalize_normals"_a = TransformOptions{}.normalize_normals,
210 "normalize_tangents_bitangents"_a = TransformOptions{}.normalize_tangents_bitangents,
211 R"(Converts a scene into a list of meshes with all the transforms applied.
212
213:param scene: Scene to convert.
214:param normalize_normals: If enabled, normals are normalized after transformation.
215:param normalize_tangents_bitangents: If enabled, tangents and bitangents are normalized after transformation.
216
217:return: List of transformed meshes.)");
218
219 using MeshType = lagrange::SurfaceMesh<Scalar, Index>;
220 m.def(
221 "mesh_to_simple_scene",
222 [](const MeshType& mesh) { return scene::mesh_to_simple_scene<3>(mesh); },
223 "mesh"_a,
224 R"(Converts a single mesh into a simple scene with a single identity instance of the input mesh.
225
226:param mesh: Input mesh to convert.
227
228:return: Simple scene containing the input mesh.)");
229
230 m.def(
231 "meshes_to_simple_scene",
232 [](std::vector<MeshType> meshes) {
233 return scene::meshes_to_simple_scene<3>(std::move(meshes));
234 },
235 "meshes"_a,
236 R"(Converts a list of meshes into a simple scene with a single identity instance of each input mesh.
237
238:param meshes: Input meshes to convert.
239
240:return: Simple scene containing the input meshes.)");
241
242 m.def(
243 "compute_mesh_weights",
244 [](const SimpleScene3D& scene, scene::FacetAllocationStrategy facet_allocation_strategy) {
245 return scene::compute_mesh_weights(scene, facet_allocation_strategy);
246 },
247 "scene"_a,
248 "facet_allocation_strategy"_a = scene::FacetAllocationStrategy::EvenSplit,
249 R"(Computes mesh weights of a scene.
250
251:param scene: Input scene. Must contain at least one mesh. For
252 ``RelativeToMeshArea``, if the scene contains no instances (or only
253 degenerate transforms) the total transformed area is zero and all returned
254 weights are zero. For ``RelativeToNumFacets`` the total facet count must be
255 positive, otherwise the returned weights will contain non-finite values.
256:param facet_allocation_strategy: Strategy used to compute the weights distribution. Defaults to
257 ``FacetAllocationStrategy.EvenSplit``. ``FacetAllocationStrategy.Synchronized``
258 is not supported by this function and will raise :class:`RuntimeError`.
259
260:return: Weights for each mesh of the scene that sum to unity, each in [0, 1].)");
261
262 m.def(
263 "filter_instances",
264 [](const SimpleScene3D& s, std::function<bool(Index, Index)> keep) {
265 return lagrange::scene::filter_instances<Scalar, Index, 3>(s, keep);
266 },
267 "scene"_a,
268 "keep"_a,
269 R"(Build a new scene keeping only instances for which ``keep(mesh_index, instance_index)``
270returns True. Meshes with no remaining instances are dropped; mesh indices are compacted.
271
272:param scene: Input scene.
273:param keep: Callable ``(mesh_index, instance_index) -> bool``.
274
275:return: Filtered scene.)");
276}
277
278} // namespace lagrange::python
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:175
::nonstd::span< T, Extent > span
A bounds-safe view for sequences of objects.
Definition span.h:27