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>
26namespace lagrange::python {
28namespace nb = nanobind;
30template <
typename Scalar,
typename Index>
31void bind_simple_scene(nb::module_& m)
33 using MeshInstance3D = lagrange::scene::MeshInstance<Scalar, Index, 3>;
34 nb::class_<MeshInstance3D>(m,
"MeshInstance3D",
"A single mesh instance in a scene")
37 "Creates a new mesh instance with identity transform and mesh_index of 0.")
40 &MeshInstance3D::mesh_index,
41 "Index of the mesh in the scene's mesh array.")
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");
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));
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");
64 std::copy(values.begin(), values.end(), M.data());
88 R
"(4x4 transformation matrix for this instance.
90The transformation matrix is stored in column-major order. Both row-major and column-major
91input tensors are supported for setting the transform.)");
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")
99 &SimpleScene3D::get_num_instances,
101 R
"(Gets the number of instances for a specific mesh.
103:param mesh_index: Index of the mesh.
105:return: Number of instances of the specified mesh.)")
107 "total_num_instances",
108 &SimpleScene3D::compute_num_instances,
109 "Total number of instances for all meshes in the scene")
112 &SimpleScene3D::get_mesh,
114 R
"(Gets a copy of the mesh at the specified index.
116:param mesh_index: Index of the mesh.
118:return: Copy of the mesh.)")
121 &SimpleScene3D::ref_mesh,
123 R
"(Gets a reference to the mesh at the specified index.
125:param mesh_index: Index of the mesh.
127:return: Reference to the mesh.)")
130 &SimpleScene3D::get_instance,
133 R
"(Gets a specific instance of a mesh.
135:param mesh_index: Index of the mesh.
136:param instance_index: Index of the instance for that mesh.
138:return: The mesh instance.)")
141 &SimpleScene3D::reserve_meshes,
143 R
"(Reserves storage for meshes.
145:param num_meshes: Number of meshes to reserve space for.)")
148 &SimpleScene3D::add_mesh,
150 R
"(Adds a mesh to the scene.
152:param mesh: Mesh to add.
154:return: Index of the newly added mesh.)")
157 &SimpleScene3D::reserve_instances,
160 R
"(Reserves storage for instances of a specific mesh.
162:param mesh_index: Index of the mesh.
163:param num_instances: Number of instances to reserve space for.)")
166 &SimpleScene3D::add_instance,
168 R
"(Adds an instance to the scene.
170:param instance: Mesh instance to add.
172:return: Index of the newly added instance for its mesh.)");
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);
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.
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.
198:return: Concatenated mesh.)");
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);
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.
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.
217:return: List of transformed meshes.)");
219 using MeshType = lagrange::SurfaceMesh<Scalar, Index>;
221 "mesh_to_simple_scene",
222 [](
const MeshType& mesh) {
return scene::mesh_to_simple_scene<3>(mesh); },
224 R
"(Converts a single mesh into a simple scene with a single identity instance of the input mesh.
226:param mesh: Input mesh to convert.
228:return: Simple scene containing the input mesh.)");
231 "meshes_to_simple_scene",
232 [](std::vector<MeshType> meshes) {
233 return scene::meshes_to_simple_scene<3>(std::move(meshes));
236 R
"(Converts a list of meshes into a simple scene with a single identity instance of each input mesh.
238:param meshes: Input meshes to convert.
240:return: Simple scene containing the input meshes.)");
243 "compute_mesh_weights",
244 [](
const SimpleScene3D& scene, scene::FacetAllocationStrategy facet_allocation_strategy) {
245 return scene::compute_mesh_weights(scene, facet_allocation_strategy);
248 "facet_allocation_strategy"_a = scene::FacetAllocationStrategy::EvenSplit,
249 R
"(Computes mesh weights of a scene.
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`.
260:return: Weights for each mesh of the scene that sum to unity, each in [0, 1].)");
264 [](
const SimpleScene3D& s, std::function<
bool(Index, Index)> keep) {
265 return lagrange::scene::filter_instances<Scalar, Index, 3>(s, keep);
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.
272:param scene: Input scene.
273:param keep: Callable ``(mesh_index, instance_index) -> bool``.
275:return: Filtered scene.)");
#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