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(
33 nb::init<>(),
34 "Creates a new mesh instance with identity transform and mesh_index of 0.")
35 .def_rw(
36 "mesh_index",
37 &MeshInstance3D::mesh_index,
38 "Index of the mesh in the scene's mesh array.")
39 .def_prop_rw(
40 "transform",
41 [](MeshInstance3D& self) {
42 auto& M = self.transform.matrix();
43 using MatrixType = std::decay_t<decltype(M)>;
44 static_assert(!MatrixType::IsRowMajor, "Transformation matrix is not column major");
45
46 span<Scalar> data(M.data(), M.size());
47 size_t shape[2]{static_cast<size_t>(M.rows()), static_cast<size_t>(M.cols())};
48 int64_t stride[2]{1, 4};
49 return span_to_tensor(data, shape, stride, nb::cast(&self));
50 },
51 [](MeshInstance3D& self, Tensor<Scalar> tensor) {
52 auto [values, shape, stride] = tensor_to_span(tensor);
53 auto& M = self.transform.matrix();
54 using MatrixType = std::decay_t<decltype(M)>;
55 static_assert(!MatrixType::IsRowMajor, "Transformation matrix is not column major");
56
57 la_runtime_assert(is_dense(shape, stride));
58 la_runtime_assert(check_shape(shape, 4, 4));
59 if (stride[0] == 1) {
60 // Tensor is col major.
61 std::copy(values.begin(), values.end(), M.data());
62 } else {
63 // Tensor is row major.
64 M(0, 0) = values[0];
65 M(0, 1) = values[1];
66 M(0, 2) = values[2];
67 M(0, 3) = values[3];
68
69 M(1, 0) = values[4];
70 M(1, 1) = values[5];
71 M(1, 2) = values[6];
72 M(1, 3) = values[7];
73
74 M(2, 0) = values[8];
75 M(2, 1) = values[9];
76 M(2, 2) = values[10];
77 M(2, 3) = values[11];
78
79 M(3, 0) = values[12];
80 M(3, 1) = values[13];
81 M(3, 2) = values[14];
82 M(3, 3) = values[15];
83 }
84 },
85 R"(4x4 transformation matrix for this instance.
86
87The transformation matrix is stored in column-major order. Both row-major and column-major
88input tensors are supported for setting the transform.)");
89
90 using SimpleScene3D = lagrange::scene::SimpleScene<Scalar, Index, 3>;
91 nb::class_<SimpleScene3D>(m, "SimpleScene3D", "Simple scene container for instanced meshes")
92 .def(nb::init<>(), "Creates an empty scene with no meshes or instances.")
93 .def_prop_ro("num_meshes", &SimpleScene3D::get_num_meshes, "Number of meshes in the scene")
94 .def(
95 "num_instances",
96 &SimpleScene3D::get_num_instances,
97 "mesh_index"_a,
98 R"(Gets the number of instances for a specific mesh.
99
100:param mesh_index: Index of the mesh.
101
102:return: Number of instances of the specified mesh.)")
103 .def_prop_ro(
104 "total_num_instances",
105 &SimpleScene3D::compute_num_instances,
106 "Total number of instances for all meshes in the scene")
107 .def(
108 "get_mesh",
109 &SimpleScene3D::get_mesh,
110 "mesh_index"_a,
111 R"(Gets a copy of the mesh at the specified index.
112
113:param mesh_index: Index of the mesh.
114
115:return: Copy of the mesh.)")
116 .def(
117 "ref_mesh",
118 &SimpleScene3D::ref_mesh,
119 "mesh_index"_a,
120 R"(Gets a reference to the mesh at the specified index.
121
122:param mesh_index: Index of the mesh.
123
124:return: Reference to the mesh.)")
125 .def(
126 "get_instance",
127 &SimpleScene3D::get_instance,
128 "mesh_index"_a,
129 "instance_index"_a,
130 R"(Gets a specific instance of a mesh.
131
132:param mesh_index: Index of the mesh.
133:param instance_index: Index of the instance for that mesh.
134
135:return: The mesh instance.)")
136 .def(
137 "reserve_meshes",
138 &SimpleScene3D::reserve_meshes,
139 "num_meshes"_a,
140 R"(Reserves storage for meshes.
141
142:param num_meshes: Number of meshes to reserve space for.)")
143 .def(
144 "add_mesh",
145 &SimpleScene3D::add_mesh,
146 "mesh"_a,
147 R"(Adds a mesh to the scene.
148
149:param mesh: Mesh to add.
150
151:return: Index of the newly added mesh.)")
152 .def(
153 "reserve_instances",
154 &SimpleScene3D::reserve_instances,
155 "mesh_index"_a,
156 "num_instances"_a,
157 R"(Reserves storage for instances of a specific mesh.
158
159:param mesh_index: Index of the mesh.
160:param num_instances: Number of instances to reserve space for.)")
161 .def(
162 "add_instance",
163 &SimpleScene3D::add_instance,
164 "instance"_a,
165 R"(Adds an instance to the scene.
166
167:param instance: Mesh instance to add.
168
169:return: Index of the newly added instance for its mesh.)");
170
171 // Mesh to scene + scene to mesh
172
173 m.def(
174 "simple_scene_to_mesh",
175 [](const SimpleScene3D& scene,
176 bool normalize_normals,
177 bool normalize_tangents_bitangents,
178 bool preserve_attributes) {
179 TransformOptions transform_options;
180 transform_options.normalize_normals = normalize_normals;
181 transform_options.normalize_tangents_bitangents = normalize_tangents_bitangents;
182 return scene::simple_scene_to_mesh(scene, transform_options, preserve_attributes);
183 },
184 "scene"_a,
185 "normalize_normals"_a = TransformOptions{}.normalize_normals,
186 "normalize_tangents_bitangents"_a = TransformOptions{}.normalize_tangents_bitangents,
187 "preserve_attributes"_a = true,
188 R"(Converts a scene into a concatenated mesh with all the transforms applied.
189
190:param scene: Scene to convert.
191:param normalize_normals: If enabled, normals are normalized after transformation.
192:param normalize_tangents_bitangents: If enabled, tangents and bitangents are normalized after transformation.
193:param preserve_attributes: Preserve shared attributes and map them to the output mesh.
194
195:return: Concatenated mesh.)");
196
197 using MeshType = lagrange::SurfaceMesh<Scalar, Index>;
198 m.def(
199 "mesh_to_simple_scene",
200 [](const MeshType& mesh) { return scene::mesh_to_simple_scene<3>(mesh); },
201 "mesh"_a,
202 R"(Converts a single mesh into a simple scene with a single identity instance of the input mesh.
203
204:param mesh: Input mesh to convert.
205
206:return: Simple scene containing the input mesh.)");
207
208 m.def(
209 "meshes_to_simple_scene",
210 [](std::vector<MeshType> meshes) {
211 return scene::meshes_to_simple_scene<3>(std::move(meshes));
212 },
213 "meshes"_a,
214 R"(Converts a list of meshes into a simple scene with a single identity instance of each input mesh.
215
216:param meshes: Input meshes to convert.
217
218:return: Simple scene containing the input meshes.)");
219}
220
221} // 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