Geometry: add utility to check for bad geometry element index dependence #113030
@ -129,6 +129,15 @@ typedef struct Global {
|
||||
*/
|
||||
int debug;
|
||||
|
||||
/**
|
||||
* When true, various geometry processing algorithms randomize the order of elements (e.g.
|
||||
* vertices or edges) in the output. In many cases, we don't make guarantees about the exact
|
||||
* order of elements. So if users depend on the indices with e.g. geometry nodes, their file can
|
||||
* break in a different Blender version. Explicitly turning on randomization can help protect
|
||||
* oneself against such breakages.
|
||||
*/
|
||||
bool randomize_geometry_element_order;
|
||||
|
||||
/**
|
||||
* Control behavior of file reading/writing.
|
||||
*
|
||||
|
@ -24,6 +24,7 @@ set(INC_SYS
|
||||
set(SRC
|
||||
geometry_attributes.cc
|
||||
geometry_ops.cc
|
||||
geometry_randomization.cc
|
||||
node_group_operator.cc
|
||||
|
||||
geometry_intern.hh
|
||||
|
@ -21,6 +21,7 @@ void GEOMETRY_OT_color_attribute_render_set(wmOperatorType *ot);
|
||||
void GEOMETRY_OT_color_attribute_duplicate(wmOperatorType *ot);
|
||||
void GEOMETRY_OT_attribute_convert(wmOperatorType *ot);
|
||||
void GEOMETRY_OT_color_attribute_convert(wmOperatorType *ot);
|
||||
void GEOMETRY_OT_geometry_randomization(wmOperatorType *ot);
|
||||
|
||||
void GEOMETRY_OT_execute_node_group(wmOperatorType *ot);
|
||||
|
||||
|
@ -27,4 +27,5 @@ void ED_operatortypes_geometry()
|
||||
WM_operatortype_append(GEOMETRY_OT_attribute_convert);
|
||||
WM_operatortype_append(GEOMETRY_OT_color_attribute_convert);
|
||||
WM_operatortype_append(GEOMETRY_OT_execute_node_group);
|
||||
WM_operatortype_append(GEOMETRY_OT_geometry_randomization);
|
||||
}
|
||||
|
58
source/blender/editors/geometry/geometry_randomization.cc
Normal file
58
source/blender/editors/geometry/geometry_randomization.cc
Normal file
@ -0,0 +1,58 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
|
||||
#include "geometry_intern.hh"
|
||||
|
||||
namespace blender::ed::geometry {
|
||||
|
||||
static int geometry_randomization_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
RNA_boolean_set(op->ptr, "value", G.randomize_geometry_element_order);
|
||||
return WM_operator_props_popup(C, op, event);
|
||||
}
|
||||
|
||||
static int geometry_randomization_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
G.randomize_geometry_element_order = RNA_boolean_get(op->ptr, "value");
|
||||
|
||||
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
|
||||
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
WM_event_add_notifier(C, NC_WINDOW, nullptr);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GEOMETRY_OT_geometry_randomization(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Set Geometry Randomization";
|
||||
ot->idname = "GEOMETRY_OT_geometry_randomization";
|
||||
ot->description = "Toggle geometry randomization for debugging purposes";
|
||||
|
||||
ot->exec = geometry_randomization_exec;
|
||||
ot->invoke = geometry_randomization_invoke;
|
||||
ot->flag |= OPTYPE_UNDO | OPTYPE_REGISTER;
|
||||
|
||||
RNA_def_boolean(ot->srna,
|
||||
"value",
|
||||
false,
|
||||
"Value",
|
||||
"Randomize the order of geometry elements (e.g. vertices or edges) after some "
|
||||
"operations where there are no guarantees about the order. This avoids "
|
||||
"accidentally depending on something that may change in the future");
|
||||
JacquesLucke marked this conversation as resolved
Outdated
|
||||
}
|
||||
|
||||
} // namespace blender::ed::geometry
|
@ -30,6 +30,7 @@ set(SRC
|
||||
intern/mesh_to_volume.cc
|
||||
intern/point_merge_by_distance.cc
|
||||
intern/points_to_volume.cc
|
||||
intern/randomize.cc
|
||||
intern/realize_instances.cc
|
||||
intern/resample_curves.cc
|
||||
intern/reverse_uv_sampler.cc
|
||||
@ -54,6 +55,7 @@ set(SRC
|
||||
GEO_mesh_to_volume.hh
|
||||
GEO_point_merge_by_distance.hh
|
||||
GEO_points_to_volume.hh
|
||||
GEO_randomize.hh
|
||||
GEO_realize_instances.hh
|
||||
GEO_resample_curves.hh
|
||||
GEO_reverse_uv_sampler.hh
|
||||
|
24
source/blender/geometry/GEO_randomize.hh
Normal file
24
source/blender/geometry/GEO_randomize.hh
Normal file
@ -0,0 +1,24 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
struct Mesh;
|
||||
struct PointCloud;
|
||||
namespace blender::bke {
|
||||
class CurvesGeometry;
|
||||
}
|
||||
|
||||
namespace blender::geometry {
|
||||
|
||||
bool use_debug_randomization();
|
||||
JacquesLucke marked this conversation as resolved
Hans Goudey
commented
I guess this is mostly an aesthetic thing, but I'd like to see see these functions have a I guess this is mostly an aesthetic thing, but I'd like to see see these functions have a `debug_` prefix, and do the `use_debug_randomization` themselves. That way the calling code can be nicer without the if statements.
|
||||
|
||||
void debug_randomize_vertex_order(Mesh *mesh);
|
||||
void debug_randomize_edge_order(Mesh *mesh);
|
||||
void debug_randomize_face_order(Mesh *mesh);
|
||||
void debug_randomize_mesh_order(Mesh *mesh);
|
||||
void debug_randomize_point_order(PointCloud *pointcloud);
|
||||
void debug_randomize_curve_order(bke::CurvesGeometry *curves);
|
||||
|
||||
}; // namespace blender::geometry
|
@ -21,6 +21,7 @@
|
||||
#include "BKE_mesh.hh"
|
||||
|
||||
#include "GEO_mesh_merge_by_distance.hh"
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#ifdef USE_WELD_DEBUG_TIME
|
||||
# include "BLI_timeit.hh"
|
||||
@ -1680,6 +1681,8 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
|
||||
BLI_assert(int(r_i) == result_nfaces);
|
||||
BLI_assert(loop_cur == result_nloops);
|
||||
|
||||
debug_randomize_mesh_order(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "BKE_mesh_mapping.hh"
|
||||
|
||||
#include "GEO_mesh_split_edges.hh"
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
namespace blender::geometry {
|
||||
|
||||
@ -591,6 +592,8 @@ void split_edges(Mesh &mesh,
|
||||
propagate_vert_attributes(mesh, vert_map);
|
||||
|
||||
BKE_mesh_tag_edges_split(&mesh);
|
||||
|
||||
debug_randomize_mesh_order(&mesh);
|
||||
}
|
||||
|
||||
} // namespace blender::geometry
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "BKE_mesh.hh"
|
||||
|
||||
#include "GEO_mesh_to_curve.hh"
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
namespace blender::geometry {
|
||||
|
||||
@ -74,6 +75,8 @@ BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
|
||||
return true;
|
||||
});
|
||||
|
||||
debug_randomize_curve_order(&curves);
|
||||
|
||||
return curves;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "BKE_pointcloud.h"
|
||||
|
||||
#include "GEO_point_merge_by_distance.hh"
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
namespace blender::geometry {
|
||||
|
||||
@ -154,6 +155,8 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points,
|
||||
});
|
||||
}
|
||||
|
||||
debug_randomize_point_order(dst_pointcloud);
|
||||
|
||||
return dst_pointcloud;
|
||||
}
|
||||
|
||||
|
231
source/blender/geometry/intern/randomize.cc
Normal file
231
source/blender/geometry/intern/randomize.cc
Normal file
@ -0,0 +1,231 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "DNA_curves_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_pointcloud_types.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.hh"
|
||||
|
||||
#include "BLI_array.hh"
|
||||
|
||||
namespace blender::geometry {
|
||||
|
||||
static Array<int> get_permutation(const int length, const int seed)
|
||||
{
|
||||
Array<int> data(length);
|
||||
for (const int i : IndexRange(length)) {
|
||||
data[i] = i;
|
||||
}
|
||||
std::shuffle(data.begin(), data.end(), std::default_random_engine(seed));
|
||||
return data;
|
||||
}
|
||||
|
||||
static Array<int> invert_permutation(const Span<int> permutation)
|
||||
{
|
||||
Array<int> data(permutation.size());
|
||||
for (const int i : permutation.index_range()) {
|
||||
data[permutation[i]] = i;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* We can't use a fully random seed, because then the randomization wouldn't be deterministic,
|
||||
* which is important to avoid causing issues when determinism is expected. Using a single constant
|
||||
* seed is not ideal either, because then two geometries might be randomized equally or very
|
||||
* similar. Ideally, the seed would be a hash of everything that feeds into the geometry processing
|
||||
* algorithm before the randomization, but that's too expensive. Just use something simple but
|
||||
* correct for now.
|
||||
*/
|
||||
static int seed_from_mesh(const Mesh &mesh)
|
||||
{
|
||||
return mesh.totvert;
|
||||
}
|
||||
|
||||
static int seed_from_pointcloud(const PointCloud &pointcloud)
|
||||
{
|
||||
return pointcloud.totpoint;
|
||||
}
|
||||
|
||||
static int seed_from_curves(const bke::CurvesGeometry &curves)
|
||||
{
|
||||
return curves.point_num;
|
||||
}
|
||||
|
||||
static void reorder_customdata(CustomData &data, const Span<int> new_by_old_map)
|
||||
{
|
||||
CustomData new_data;
|
||||
CustomData_copy_layout(&data, &new_data, CD_MASK_ALL, CD_CONSTRUCT, new_by_old_map.size());
|
||||
|
||||
for (const int old_i : new_by_old_map.index_range()) {
|
||||
const int new_i = new_by_old_map[old_i];
|
||||
CustomData_copy_data(&data, &new_data, old_i, new_i, 1);
|
||||
}
|
||||
CustomData_free(&data, new_by_old_map.size());
|
||||
data = new_data;
|
||||
}
|
||||
|
||||
void debug_randomize_vertex_order(Mesh *mesh)
|
||||
{
|
||||
if (mesh == nullptr || !use_debug_randomization()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int seed = seed_from_mesh(*mesh);
|
||||
const Array<int> new_by_old_map = get_permutation(mesh->totvert, seed);
|
||||
|
||||
reorder_customdata(mesh->vert_data, new_by_old_map);
|
||||
|
||||
for (int &v : mesh->edges_for_write().cast<int>()) {
|
||||
v = new_by_old_map[v];
|
||||
}
|
||||
for (int &v : mesh->corner_verts_for_write()) {
|
||||
v = new_by_old_map[v];
|
||||
}
|
||||
|
||||
BKE_mesh_tag_topology_changed(mesh);
|
||||
}
|
||||
|
||||
void debug_randomize_edge_order(Mesh *mesh)
|
||||
{
|
||||
if (mesh == nullptr || !use_debug_randomization()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int seed = seed_from_mesh(*mesh);
|
||||
const Array<int> new_by_old_map = get_permutation(mesh->totedge, seed);
|
||||
|
||||
reorder_customdata(mesh->edge_data, new_by_old_map);
|
||||
|
||||
for (int &e : mesh->corner_edges_for_write()) {
|
||||
e = new_by_old_map[e];
|
||||
}
|
||||
|
||||
BKE_mesh_tag_topology_changed(mesh);
|
||||
}
|
||||
|
||||
static Array<int> make_new_offset_indices(const OffsetIndices<int> old_offsets,
|
||||
const Span<int> old_by_new_map)
|
||||
{
|
||||
Array<int> new_offsets(old_offsets.data().size());
|
||||
new_offsets[0] = 0;
|
||||
for (const int new_i : old_offsets.index_range()) {
|
||||
const int old_i = old_by_new_map[new_i];
|
||||
new_offsets[new_i + 1] = new_offsets[new_i] + old_offsets[old_i].size();
|
||||
}
|
||||
return new_offsets;
|
||||
}
|
||||
|
||||
static void reorder_customdata_groups(CustomData &data,
|
||||
const OffsetIndices<int> old_offsets,
|
||||
const OffsetIndices<int> new_offsets,
|
||||
const Span<int> new_by_old_map)
|
||||
{
|
||||
const int elements_num = new_offsets.total_size();
|
||||
const int groups_num = new_by_old_map.size();
|
||||
CustomData new_data;
|
||||
CustomData_copy_layout(&data, &new_data, CD_MASK_ALL, CD_CONSTRUCT, elements_num);
|
||||
for (const int old_i : IndexRange(groups_num)) {
|
||||
const int new_i = new_by_old_map[old_i];
|
||||
const IndexRange old_range = old_offsets[old_i];
|
||||
const IndexRange new_range = new_offsets[new_i];
|
||||
BLI_assert(old_range.size() == new_range.size());
|
||||
CustomData_copy_data(&data, &new_data, old_range.start(), new_range.start(), old_range.size());
|
||||
}
|
||||
CustomData_free(&data, elements_num);
|
||||
data = new_data;
|
||||
}
|
||||
|
||||
void debug_randomize_face_order(Mesh *mesh)
|
||||
{
|
||||
if (mesh == nullptr || !use_debug_randomization()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int seed = seed_from_mesh(*mesh);
|
||||
const Array<int> new_by_old_map = get_permutation(mesh->faces_num, seed);
|
||||
const Array<int> old_by_new_map = invert_permutation(new_by_old_map);
|
||||
|
||||
reorder_customdata(mesh->face_data, new_by_old_map);
|
||||
|
||||
const OffsetIndices old_faces = mesh->faces();
|
||||
Array<int> new_face_offsets = make_new_offset_indices(old_faces, old_by_new_map);
|
||||
const OffsetIndices<int> new_faces = new_face_offsets.as_span();
|
||||
|
||||
reorder_customdata_groups(mesh->loop_data, old_faces, new_faces, new_by_old_map);
|
||||
|
||||
mesh->face_offsets_for_write().copy_from(new_face_offsets);
|
||||
|
||||
BKE_mesh_tag_topology_changed(mesh);
|
||||
}
|
||||
|
||||
void debug_randomize_point_order(PointCloud *pointcloud)
|
||||
{
|
||||
if (pointcloud == nullptr || !use_debug_randomization()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int seed = seed_from_pointcloud(*pointcloud);
|
||||
const Array<int> new_by_old_map = get_permutation(pointcloud->totpoint, seed);
|
||||
|
||||
reorder_customdata(pointcloud->pdata, new_by_old_map);
|
||||
|
||||
pointcloud->tag_positions_changed();
|
||||
pointcloud->tag_radii_changed();
|
||||
}
|
||||
|
||||
void debug_randomize_curve_order(bke::CurvesGeometry *curves)
|
||||
{
|
||||
if (curves == nullptr || !use_debug_randomization()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int seed = seed_from_curves(*curves);
|
||||
const Array<int> new_by_old_map = get_permutation(curves->curve_num, seed);
|
||||
const Array<int> old_by_new_map = invert_permutation(new_by_old_map);
|
||||
|
||||
reorder_customdata(curves->curve_data, new_by_old_map);
|
||||
|
||||
const OffsetIndices old_points_by_curve = curves->points_by_curve();
|
||||
Array<int> new_curve_offsets = make_new_offset_indices(old_points_by_curve, old_by_new_map);
|
||||
const OffsetIndices<int> new_points_by_curve = new_curve_offsets.as_span();
|
||||
|
||||
reorder_customdata_groups(
|
||||
curves->point_data, old_points_by_curve, new_points_by_curve, new_by_old_map);
|
||||
|
||||
curves->offsets_for_write().copy_from(new_curve_offsets);
|
||||
|
||||
curves->tag_topology_changed();
|
||||
}
|
||||
|
||||
void debug_randomize_mesh_order(Mesh *mesh)
|
||||
{
|
||||
if (mesh == nullptr || !use_debug_randomization()) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug_randomize_vertex_order(mesh);
|
||||
debug_randomize_edge_order(mesh);
|
||||
debug_randomize_face_order(mesh);
|
||||
}
|
||||
|
||||
bool use_debug_randomization()
|
||||
{
|
||||
return G.randomize_geometry_element_order;
|
||||
}
|
||||
|
||||
} // namespace blender::geometry
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "bmesh_tools.h"
|
||||
|
||||
@ -230,6 +232,8 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
|
||||
|
||||
BM_mesh_free(bm);
|
||||
|
||||
blender::geometry::debug_randomize_mesh_order(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,8 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "bmesh_tools.h"
|
||||
#include "tools/bmesh_boolean.h"
|
||||
@ -501,6 +503,8 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
|
||||
MutableSpan(result->mat, result->totcol).copy_from(materials);
|
||||
}
|
||||
|
||||
blender::geometry::debug_randomize_mesh_order(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@ -598,6 +602,8 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
|
||||
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
|
||||
}
|
||||
|
||||
blender::geometry::debug_randomize_mesh_order(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "bmesh_tools.h"
|
||||
|
||||
@ -207,6 +209,8 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
|
||||
|
||||
BM_mesh_free(bm);
|
||||
|
||||
blender::geometry::debug_randomize_mesh_order(result);
|
||||
|
||||
#ifdef USE_TIMEIT
|
||||
TIMEIT_END(decim);
|
||||
#endif
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include "MOD_modifiertypes.hh"
|
||||
#include "MOD_ui_common.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
/* For edge split modifier node. */
|
||||
Mesh *doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd);
|
||||
|
||||
@ -103,6 +105,8 @@ Mesh *doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd)
|
||||
result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh);
|
||||
BM_mesh_free(bm);
|
||||
|
||||
blender::geometry::debug_randomize_mesh_order(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include "MOD_modifiertypes.hh"
|
||||
#include "MOD_ui_common.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
@ -198,6 +200,9 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext * /*ctx*/,
|
||||
|
||||
BKE_mesh_copy_parameters_for_eval(result, mesh);
|
||||
BKE_mesh_calc_edges(result, true, false);
|
||||
|
||||
blender::geometry::debug_randomize_mesh_order(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_boolean_cc {
|
||||
@ -145,6 +147,8 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
selection.finish();
|
||||
}
|
||||
|
||||
geometry::debug_randomize_mesh_order(result);
|
||||
|
||||
params.set_output("Mesh", GeometrySet::from_mesh(result));
|
||||
#else
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
#ifdef WITH_BULLET
|
||||
@ -215,6 +217,9 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
|
||||
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
|
||||
Mesh *mesh = compute_hull(geometry_set);
|
||||
if (mesh) {
|
||||
geometry::debug_randomize_mesh_order(mesh);
|
||||
}
|
||||
geometry_set.replace_mesh(mesh);
|
||||
geometry_set.keep_only_during_modify({GeometryComponent::Type::Mesh});
|
||||
});
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_curve_to_mesh_cc {
|
||||
@ -37,11 +39,13 @@ static void geometry_set_curve_to_mesh(GeometrySet &geometry_set,
|
||||
|
||||
if (profile_curves == nullptr) {
|
||||
Mesh *mesh = bke::curve_to_wire_mesh(curves.geometry.wrap(), propagation_info);
|
||||
geometry::debug_randomize_mesh_order(mesh);
|
||||
geometry_set.replace_mesh(mesh);
|
||||
}
|
||||
else {
|
||||
Mesh *mesh = bke::curve_to_mesh_sweep(
|
||||
curves.geometry.wrap(), profile_curves->geometry.wrap(), fill_caps, propagation_info);
|
||||
geometry::debug_randomize_mesh_order(mesh);
|
||||
geometry_set.replace_mesh(mesh);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_distribute_points_in_volume_cc {
|
||||
@ -253,6 +255,8 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
point_radii.span.fill(0.05f);
|
||||
point_radii.finish();
|
||||
|
||||
geometry::debug_randomize_point_order(pointcloud);
|
||||
|
||||
geometry_set.replace_pointcloud(pointcloud);
|
||||
geometry_set.keep_only_during_modify({GeometryComponent::Type::PointCloud});
|
||||
});
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_distribute_points_on_faces_cc {
|
||||
@ -556,6 +558,8 @@ static void point_distribution_calculate(GeometrySet &geometry_set,
|
||||
const bool use_legacy_normal = params.node().custom2 != 0;
|
||||
compute_attribute_outputs(
|
||||
mesh, *pointcloud, bary_coords, looptri_indices, attribute_outputs, use_legacy_normal);
|
||||
|
||||
geometry::debug_randomize_point_order(pointcloud);
|
||||
}
|
||||
|
||||
static void node_geo_exec(GeoNodeExecParams params)
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_mesh_mapping.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_dual_mesh_cc {
|
||||
@ -921,6 +923,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
if (const Mesh *mesh = geometry_set.get_mesh()) {
|
||||
Mesh *new_mesh = calc_dual_mesh(
|
||||
*mesh, keep_boundaries, params.get_output_propagation_info("Dual Mesh"));
|
||||
geometry::debug_randomize_mesh_order(new_mesh);
|
||||
geometry_set.replace_mesh(new_mesh);
|
||||
}
|
||||
});
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "BKE_mesh_mapping.hh"
|
||||
#include "BKE_mesh_runtime.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "NOD_rna_define.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
@ -1431,6 +1433,8 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
geometry::debug_randomize_mesh_order(mesh);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_curves_utils.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "DNA_pointcloud_types.h"
|
||||
|
||||
namespace blender::nodes::node_geo_interpolate_curves_cc {
|
||||
@ -759,6 +761,8 @@ static GeometrySet generate_interpolated_curves(
|
||||
child_curves_id->totcol = guide_curves_id.totcol;
|
||||
}
|
||||
|
||||
geometry::debug_randomize_curve_order(&child_curves);
|
||||
|
||||
return GeometrySet::from_curves(child_curves_id);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "bmesh.h"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
@ -107,6 +109,8 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions,
|
||||
}
|
||||
attributes.remove("UVMap");
|
||||
|
||||
geometry::debug_randomize_mesh_order(mesh);
|
||||
|
||||
mesh->bounds_set_eager(calculate_bounds_ico_sphere(radius, subdivisions));
|
||||
|
||||
return mesh;
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_mesh_subdivide_cc {
|
||||
@ -48,6 +50,7 @@ static Mesh *simple_subdivide_mesh(const Mesh &mesh, const int level)
|
||||
|
||||
BKE_subdiv_free(subdiv);
|
||||
|
||||
geometry::debug_randomize_mesh_order(result);
|
||||
return result;
|
||||
}
|
||||
#endif /* WITH_OPENSUBDIV */
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "BLI_sort.hh"
|
||||
#include "BLI_task.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "BKE_geometry_set.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_points_to_curves_cc {
|
||||
@ -151,6 +153,8 @@ static Curves *curves_from_points(const PointCloud &points,
|
||||
{},
|
||||
indices,
|
||||
curves.attributes_for_write());
|
||||
|
||||
geometry::debug_randomize_curve_order(&curves);
|
||||
return curves_id;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_string_to_curves_cc {
|
||||
@ -296,6 +298,8 @@ static Map<int, int> create_curve_instances(GeoNodeExecParams ¶ms,
|
||||
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
BKE_nurbList_free(&cu.nurb);
|
||||
|
||||
geometry::debug_randomize_curve_order(&curves);
|
||||
|
||||
float4x4 size_matrix = math::from_scale<float4x4>(float3(layout.final_font_size));
|
||||
curves.transform(size_matrix);
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "NOD_rna_define.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_subdivision_surface_cc {
|
||||
@ -159,6 +161,8 @@ static Mesh *mesh_subsurf_calc(const Mesh *mesh,
|
||||
BKE_id_free(nullptr, mesh_copy);
|
||||
}
|
||||
|
||||
geometry::debug_randomize_mesh_order(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_triangulate_cc {
|
||||
@ -67,6 +69,10 @@ static Mesh *triangulate_mesh_selection(const Mesh &mesh,
|
||||
/* Positions are not changed by the triangulation operation, so the bounds are the same. */
|
||||
result->runtime->bounds_cache = mesh.runtime->bounds_cache;
|
||||
|
||||
/* Vertex order is not affected. */
|
||||
geometry::debug_randomize_edge_order(result);
|
||||
geometry::debug_randomize_face_order(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_volume_to_mesh_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodeGeometryVolumeToMesh)
|
||||
@ -151,6 +153,8 @@ static Mesh *create_mesh_from_volume_grids(Span<openvdb::GridBase::ConstPtr> gri
|
||||
BKE_mesh_calc_edges(mesh, false, false);
|
||||
BKE_mesh_smooth_flag_set(mesh, false);
|
||||
|
||||
geometry::debug_randomize_mesh_order(mesh);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
is likely to
->may
?