26 b.add_input<
decl::Geometry>(
"Geometry").description(
"Points to compute the convex hull of");
27 b.add_output<
decl::Geometry>(
"Convex Hull").propagate_all_instance_attributes();
40 const int edges_num = verts_num == 2 ? 1 : verts_num < 2 ? 0 : loops_num / 2;
64 dst_positions[
i] = coords[original_index];
72 Array<int> corner_verts(loops_num);
73 Array<int> corner_edges(loops_num);
75 MutableSpan<int2> edges =
result->edges_for_write();
77 for (
const int i : IndexRange(loops_num)) {
82 corner_verts[
i] = v_from;
85 edges[edge_index] =
int2(v_from, v_to);
89 corner_edges[
i] = edge_index;
90 corner_edges[reverse_index] = edge_index;
96 edges[0] =
int2(0, 1);
104 MutableSpan<int> face_offsets =
result->face_offsets_for_write();
105 MutableSpan<int> mesh_corner_verts =
result->corner_verts_for_write();
106 MutableSpan<int> mesh_corner_edges =
result->corner_edges_for_write();
109 for (
const int i : IndexRange(faces_num)) {
119 for (
const int k : IndexRange(
len)) {
120 mesh_corner_verts[dst_corner] = corner_verts[loops[k]];
121 mesh_corner_edges[dst_corner] = corner_edges[loops[k]];
131static Mesh *compute_hull(
const GeometrySet &geometry_set)
137 Span<float3> positions_span;
141 if (
const VArray positions = *mesh->
attributes().lookup<
float3>(
"position")) {
142 if (positions.is_span()) {
144 positions_span = positions.get_internal_span();
146 total_num += positions.size();
152 if (
const VArray positions = *points->attributes().lookup<
float3>(
"position")) {
153 if (positions.is_span()) {
155 positions_span = positions.get_internal_span();
157 total_num += positions.size();
164 const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
165 positions_span = curves.evaluated_positions();
166 total_num += positions_span.
size();
175 if (span_count == 1 &&
count == 1) {
176 return hull_from_bullet(geometry_set.
get_mesh(), positions_span);
179 Array<float3> positions(total_num);
184 varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
185 offset += varray.size();
190 if (
const VArray varray = *points->attributes().lookup<
float3>(
"position")) {
191 varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
192 offset += varray.size();
197 const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
198 Span<float3> array = curves.evaluated_positions();
199 positions.as_mutable_span().slice(offset, array.
size()).copy_from(array);
200 offset += array.
size();
203 return hull_from_bullet(geometry_set.
get_mesh(), positions);
206static void convex_hull_grease_pencil(GeometrySet &geometry_set)
208 using namespace blender::bke::greasepencil;
211 Array<Mesh *> mesh_by_layer(grease_pencil.layers().size(),
nullptr);
213 for (
const int layer_index : grease_pencil.layers().index_range()) {
214 const Drawing *drawing = grease_pencil.get_eval_drawing(grease_pencil.layer(layer_index));
215 if (drawing ==
nullptr) {
218 const bke::CurvesGeometry &curves = drawing->
strokes();
223 mesh_by_layer[layer_index] = hull_from_bullet(
nullptr, positions_span);
226 if (mesh_by_layer.is_empty()) {
230 InstancesComponent &instances_component =
232 bke::Instances *instances = instances_component.
get_for_write();
233 if (instances ==
nullptr) {
234 instances =
new bke::Instances();
235 instances_component.
replace(instances);
237 for (
Mesh *mesh : mesh_by_layer) {
242 const int handle = instances->add_reference(bke::InstanceReference());
247 const int handle = instances->add_reference(bke::InstanceReference{temp_set});
262 Mesh *
mesh = compute_hull(geometry_set);
268 convex_hull_grease_pencil(geometry_set);
275 params.set_output(
"Convex Hull", std::move(geometry_set));
278 TIP_(
"Disabled, Blender was compiled without Bullet"));
279 params.set_default_remaining_outputs();
289 "Create a mesh that encloses all points in the input geometry with the smallest number of "