Blender V4.5
randomize.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <algorithm>
6#include <random>
7
8#include "GEO_randomize.hh"
9
10#include "DNA_curves_types.h"
11#include "DNA_mesh_types.h"
13
14#include "BKE_curves.hh"
15#include "BKE_customdata.hh"
16#include "BKE_geometry_set.hh"
17#include "BKE_global.hh"
18#include "BKE_instances.hh"
19
20#include "BLI_array.hh"
21
22namespace blender::geometry {
23
24static Array<int> get_permutation(const int length, const int seed)
25{
27 for (const int i : IndexRange(length)) {
28 data[i] = i;
29 }
30 std::shuffle(data.begin(), data.end(), std::default_random_engine(seed));
31 return data;
32}
33
34static Array<int> invert_permutation(const Span<int> permutation)
35{
36 Array<int> data(permutation.size());
37 for (const int i : permutation.index_range()) {
38 data[permutation[i]] = i;
39 }
40 return data;
41}
42
51static int seed_from_mesh(const Mesh &mesh)
52{
53 return mesh.verts_num;
54}
55
56static int seed_from_pointcloud(const PointCloud &pointcloud)
57{
58 return pointcloud.totpoint;
59}
60
61static int seed_from_curves(const bke::CurvesGeometry &curves)
62{
63 return curves.point_num;
64}
65
66static int seed_from_instances(const bke::Instances &instances)
67{
68 return instances.instances_num();
69}
70
71static void reorder_customdata(CustomData &data, const Span<int> new_by_old_map)
72{
73 CustomData new_data;
74 CustomData_init_layout_from(&data, &new_data, CD_MASK_ALL, CD_CONSTRUCT, new_by_old_map.size());
75
76 for (const int old_i : new_by_old_map.index_range()) {
77 const int new_i = new_by_old_map[old_i];
78 CustomData_copy_data(&data, &new_data, old_i, new_i, 1);
79 }
81 data = new_data;
82}
83
85{
86 if (mesh == nullptr || !use_debug_randomization()) {
87 return;
88 }
89
90 const int seed = seed_from_mesh(*mesh);
91 const Array<int> new_by_old_map = get_permutation(mesh->verts_num, seed);
92
93 reorder_customdata(mesh->vert_data, new_by_old_map);
94
95 for (int &v : mesh->edges_for_write().cast<int>()) {
96 v = new_by_old_map[v];
97 }
98 for (int &v : mesh->corner_verts_for_write()) {
99 v = new_by_old_map[v];
100 }
101
102 mesh->tag_topology_changed();
103}
104
106{
107 if (mesh == nullptr || !use_debug_randomization()) {
108 return;
109 }
110
111 const int seed = seed_from_mesh(*mesh);
112 const Array<int> new_by_old_map = get_permutation(mesh->edges_num, seed);
113
114 reorder_customdata(mesh->edge_data, new_by_old_map);
115
116 for (int &e : mesh->corner_edges_for_write()) {
117 e = new_by_old_map[e];
118 }
119
120 mesh->tag_topology_changed();
121}
122
124 const Span<int> old_by_new_map)
125{
126 Array<int> new_offsets(old_offsets.data().size());
127 new_offsets[0] = 0;
128 for (const int new_i : old_offsets.index_range()) {
129 const int old_i = old_by_new_map[new_i];
130 new_offsets[new_i + 1] = new_offsets[new_i] + old_offsets[old_i].size();
131 }
132 return new_offsets;
133}
134
136 const OffsetIndices<int> old_offsets,
137 const OffsetIndices<int> new_offsets,
138 const Span<int> new_by_old_map)
139{
140 const int elements_num = new_offsets.total_size();
141 const int groups_num = new_by_old_map.size();
142 CustomData new_data;
143 CustomData_init_layout_from(&data, &new_data, CD_MASK_ALL, CD_CONSTRUCT, elements_num);
144 for (const int old_i : IndexRange(groups_num)) {
145 const int new_i = new_by_old_map[old_i];
146 const IndexRange old_range = old_offsets[old_i];
147 const IndexRange new_range = new_offsets[new_i];
148 BLI_assert(old_range.size() == new_range.size());
149 CustomData_copy_data(&data, &new_data, old_range.start(), new_range.start(), old_range.size());
150 }
152 data = new_data;
153}
154
156{
157 if (mesh == nullptr || mesh->faces_num == 0 || !use_debug_randomization()) {
158 return;
159 }
160
161 const int seed = seed_from_mesh(*mesh);
162 const Array<int> new_by_old_map = get_permutation(mesh->faces_num, seed);
163 const Array<int> old_by_new_map = invert_permutation(new_by_old_map);
164
165 reorder_customdata(mesh->face_data, new_by_old_map);
166
167 const OffsetIndices old_faces = mesh->faces();
168 Array<int> new_face_offsets = make_new_offset_indices(old_faces, old_by_new_map);
169 const OffsetIndices<int> new_faces = new_face_offsets.as_span();
170
171 reorder_customdata_groups(mesh->corner_data, old_faces, new_faces, new_by_old_map);
172
173 mesh->face_offsets_for_write().copy_from(new_face_offsets);
174
175 mesh->tag_topology_changed();
176}
177
179{
180 if (pointcloud == nullptr || !use_debug_randomization()) {
181 return;
182 }
183
184 const int seed = seed_from_pointcloud(*pointcloud);
185 const Array<int> new_by_old_map = get_permutation(pointcloud->totpoint, seed);
186
187 reorder_customdata(pointcloud->pdata, new_by_old_map);
188
189 pointcloud->tag_positions_changed();
190 pointcloud->tag_radii_changed();
191}
192
194{
195 if (curves == nullptr || !use_debug_randomization()) {
196 return;
197 }
198
199 const int seed = seed_from_curves(*curves);
200 const Array<int> new_by_old_map = get_permutation(curves->curve_num, seed);
201 const Array<int> old_by_new_map = invert_permutation(new_by_old_map);
202
203 reorder_customdata(curves->curve_data, new_by_old_map);
204
205 const OffsetIndices old_points_by_curve = curves->points_by_curve();
206 Array<int> new_curve_offsets = make_new_offset_indices(old_points_by_curve, old_by_new_map);
207 const OffsetIndices<int> new_points_by_curve = new_curve_offsets.as_span();
208
210 curves->point_data, old_points_by_curve, new_points_by_curve, new_by_old_map);
211
212 curves->offsets_for_write().copy_from(new_curve_offsets);
213
214 curves->tag_topology_changed();
215}
216
218{
219 if (mesh == nullptr || !use_debug_randomization()) {
220 return;
221 }
222
226}
227
229{
230 if (instances == nullptr || !use_debug_randomization()) {
231 return;
232 }
233 const int instances_num = instances->instances_num();
234 const int seed = seed_from_instances(*instances);
235 const Array<int> new_by_old_map = get_permutation(instances_num, seed);
236 reorder_customdata(instances->custom_data_attributes(), new_by_old_map);
237}
238
240{
241 return G.randomize_geometry_element_order;
242}
243
244} // namespace blender::geometry
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
@ CD_CONSTRUCT
void CustomData_free(CustomData *data)
void CustomData_init_layout_from(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
#define BLI_assert(a)
Definition BLI_assert.h:46
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static unsigned long seed
Definition btSoftBody.h:39
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
Span< T > as_span() const
Definition BLI_array.hh:232
constexpr int64_t size() const
constexpr int64_t start() const
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
OffsetIndices< int > points_by_curve() const
MutableSpan< int > offsets_for_write()
int instances_num() const
Definition instances.cc:398
CustomData & custom_data_attributes()
float length(VecOp< float, D >) RET
#define CD_MASK_ALL
#define G(x, y, z)
void debug_randomize_edge_order(Mesh *mesh)
Definition randomize.cc:105
static Array< int > invert_permutation(const Span< int > permutation)
Definition randomize.cc:34
static void reorder_customdata_groups(CustomData &data, const OffsetIndices< int > old_offsets, const OffsetIndices< int > new_offsets, const Span< int > new_by_old_map)
Definition randomize.cc:135
bool use_debug_randomization()
Definition randomize.cc:239
static int seed_from_curves(const bke::CurvesGeometry &curves)
Definition randomize.cc:61
void debug_randomize_mesh_order(Mesh *mesh)
Definition randomize.cc:217
void debug_randomize_curve_order(bke::CurvesGeometry *curves)
Definition randomize.cc:193
static Array< int > make_new_offset_indices(const OffsetIndices< int > old_offsets, const Span< int > old_by_new_map)
Definition randomize.cc:123
static int seed_from_pointcloud(const PointCloud &pointcloud)
Definition randomize.cc:56
void debug_randomize_vert_order(Mesh *mesh)
Definition randomize.cc:84
static Array< int > get_permutation(const int length, const int seed)
Definition randomize.cc:24
void debug_randomize_face_order(Mesh *mesh)
Definition randomize.cc:155
static void reorder_customdata(CustomData &data, const Span< int > new_by_old_map)
Definition randomize.cc:71
void debug_randomize_point_order(PointCloud *pointcloud)
Definition randomize.cc:178
static int seed_from_mesh(const Mesh &mesh)
Definition randomize.cc:51
static int seed_from_instances(const bke::Instances &instances)
Definition randomize.cc:66
void debug_randomize_instance_order(bke::Instances *instances)
Definition randomize.cc:228
CustomData point_data
CustomData curve_data
CustomData edge_data
int edges_num
CustomData corner_data
CustomData face_data
CustomData vert_data
int faces_num
int verts_num
struct CustomData pdata
i
Definition text_draw.cc:230