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.)",
92 nb::for_setter(nb::sig("def transform(self, arg: numpy.typing.ArrayLike, /) -> None")));
94 using SimpleScene3D = lagrange::scene::SimpleScene<Scalar, Index, 3>;
95 nb::class_<SimpleScene3D>(m,
"SimpleScene3D",
"Simple scene container for instanced meshes")
96 .def(nb::init<>(),
"Creates an empty scene with no meshes or instances.")
97 .def_prop_ro(
"num_meshes", &SimpleScene3D::get_num_meshes,
"Number of meshes in the scene")
100 &SimpleScene3D::get_num_instances,
102 R
"(Gets the number of instances for a specific mesh.
104:param mesh_index: Index of the mesh.
106:return: Number of instances of the specified mesh.)")
108 "total_num_instances",
109 &SimpleScene3D::compute_num_instances,
110 "Total number of instances for all meshes in the scene")
113 &SimpleScene3D::get_mesh,
115 R
"(Gets a copy of the mesh at the specified index.
117:param mesh_index: Index of the mesh.
119:return: Copy of the mesh.)")
122 &SimpleScene3D::ref_mesh,
124 R
"(Gets a reference to the mesh at the specified index.
126:param mesh_index: Index of the mesh.
128:return: Reference to the mesh.)")
131 &SimpleScene3D::get_instance,
134 R
"(Gets a specific instance of a mesh.
136:param mesh_index: Index of the mesh.
137:param instance_index: Index of the instance for that mesh.
139:return: The mesh instance.)")
142 &SimpleScene3D::reserve_meshes,
144 R
"(Reserves storage for meshes.
146:param num_meshes: Number of meshes to reserve space for.)")
149 &SimpleScene3D::add_mesh,
151 R
"(Adds a mesh to the scene.
153:param mesh: Mesh to add.
155:return: Index of the newly added mesh.)")
158 &SimpleScene3D::reserve_instances,
161 R
"(Reserves storage for instances of a specific mesh.
163:param mesh_index: Index of the mesh.
164:param num_instances: Number of instances to reserve space for.)")
167 &SimpleScene3D::add_instance,
169 R
"(Adds an instance to the scene.
171:param instance: Mesh instance to add.
173:return: Index of the newly added instance for its mesh.)");
178 "simple_scene_to_mesh",
179 [](
const SimpleScene3D& scene,
180 bool normalize_normals,
181 bool normalize_tangents_bitangents,
183 bool preserve_attributes) {
184 TransformOptions transform_options;
185 transform_options.normalize_normals = normalize_normals;
186 transform_options.normalize_tangents_bitangents = normalize_tangents_bitangents;
187 transform_options.reorient = reorient;
188 return scene::simple_scene_to_mesh(scene, transform_options, preserve_attributes);
192 "normalize_normals"_a = TransformOptions{}.normalize_normals,
193 "normalize_tangents_bitangents"_a = TransformOptions{}.normalize_tangents_bitangents,
194 "reorient"_a = TransformOptions{}.reorient,
195 "preserve_attributes"_a =
true,
196 R
"(Converts a scene into a concatenated mesh with all the transforms applied.
198:param scene: Scene to convert.
199:param normalize_normals: If enabled, normals are normalized after transformation.
200:param normalize_tangents_bitangents: If enabled, tangents and bitangents are normalized after transformation.
201:param reorient: If enabled, flip facets and reorient attributes for instances with a negative-determinant transform.
202:param preserve_attributes: Preserve shared attributes and map them to the output mesh.
204:return: Concatenated mesh.)");
207 "simple_scene_to_meshes",
208 [](
const SimpleScene3D& scene,
209 bool normalize_normals,
210 bool normalize_tangents_bitangents,
212 TransformOptions transform_options;
213 transform_options.normalize_normals = normalize_normals;
214 transform_options.normalize_tangents_bitangents = normalize_tangents_bitangents;
215 transform_options.reorient = reorient;
216 return scene::simple_scene_to_meshes(scene, transform_options);
220 "normalize_normals"_a = TransformOptions{}.normalize_normals,
221 "normalize_tangents_bitangents"_a = TransformOptions{}.normalize_tangents_bitangents,
222 "reorient"_a = TransformOptions{}.reorient,
223 R
"(Converts a scene into a list of meshes with all the transforms applied.
225:param scene: Scene to convert.
226:param normalize_normals: If enabled, normals are normalized after transformation.
227:param normalize_tangents_bitangents: If enabled, tangents and bitangents are normalized after transformation.
228:param reorient: If enabled, flip facets and reorient attributes for instances with a negative-determinant transform.
230:return: List of transformed meshes.)");
232 using MeshType = lagrange::SurfaceMesh<Scalar, Index>;
234 "mesh_to_simple_scene",
235 [](
const MeshType& mesh) {
return scene::mesh_to_simple_scene<3>(mesh); },
237 R
"(Converts a single mesh into a simple scene with a single identity instance of the input mesh.
239:param mesh: Input mesh to convert.
241:return: Simple scene containing the input mesh.)");
244 "meshes_to_simple_scene",
245 [](std::vector<MeshType> meshes) {
246 return scene::meshes_to_simple_scene<3>(std::move(meshes));
249 R
"(Converts a list of meshes into a simple scene with a single identity instance of each input mesh.
251:param meshes: Input meshes to convert.
253:return: Simple scene containing the input meshes.)");
256 "compute_mesh_weights",
257 [](
const SimpleScene3D& scene, scene::FacetAllocationStrategy facet_allocation_strategy) {
258 return scene::compute_mesh_weights(scene, facet_allocation_strategy);
261 "facet_allocation_strategy"_a = scene::FacetAllocationStrategy::EvenSplit,
262 R
"(Computes mesh weights of a scene.
264:param scene: Input scene. Must contain at least one mesh. For
265 ``RelativeToMeshArea``, if the scene contains no instances (or only
266 degenerate transforms) the total transformed area is zero and all returned
267 weights are zero. For ``RelativeToNumFacets`` the total facet count must be
268 positive, otherwise the returned weights will contain non-finite values.
269:param facet_allocation_strategy: Strategy used to compute the weights distribution. Defaults to
270 ``FacetAllocationStrategy.EvenSplit``. ``FacetAllocationStrategy.Synchronized``
271 is not supported by this function and will raise :class:`RuntimeError`.
273:return: Weights for each mesh of the scene that sum to unity, each in [0, 1].)");
277 [](
const SimpleScene3D& s, std::function<
bool(Index, Index)> keep) {
278 return lagrange::scene::filter_instances<Scalar, Index, 3>(s, keep);
282 R
"(Build a new scene keeping only instances for which ``keep(mesh_index, instance_index)``
283returns True. Meshes with no remaining instances are dropped; mesh indices are compacted.
285:param scene: Input scene.
286:param keep: Callable ``(mesh_index, instance_index) -> bool``.
288:return: Filtered scene.)");
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:177
::nonstd::span< T, Extent > span
A bounds-safe view for sequences of objects.
Definition span.h:27