Blender V4.5
rna_mesh_api.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10
11#include "RNA_define.hh"
12
14
15#include "BLI_math_base.h"
16
17#include "rna_internal.hh" /* own include */
18
19#ifdef RNA_RUNTIME
20
21# include "DNA_mesh_types.h"
22
23# include "BKE_anim_data.hh"
24# include "BKE_attribute.hh"
26# include "BKE_mesh.h"
27# include "BKE_mesh.hh"
28# include "BKE_mesh_mapping.hh"
29# include "BKE_mesh_runtime.hh"
30# include "BKE_mesh_tangent.hh"
31# include "BKE_report.hh"
32
33# include "ED_mesh.hh"
34
35# include "DEG_depsgraph.hh"
36
37# include "WM_api.hh"
38
39static const char *rna_Mesh_unit_test_compare(Mesh *mesh, Mesh *mesh2, float threshold)
40{
41 using namespace blender::bke::compare_geometry;
42 const std::optional<GeoMismatch> mismatch = compare_meshes(*mesh, *mesh2, threshold);
43
44 if (!mismatch) {
45 return "Same";
46 }
47
48 return mismatch_to_string(mismatch.value());
49}
50
51static void rna_Mesh_sharp_from_angle_set(Mesh *mesh, const float angle)
52{
53 mesh->attributes_for_write().remove("sharp_edge");
54 mesh->attributes_for_write().remove("sharp_face");
57}
58
59static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap)
60{
61 float(*r_looptangents)[4];
62
63 if (CustomData_has_layer(&mesh->corner_data, CD_MLOOPTANGENT)) {
64 r_looptangents = static_cast<float(*)[4]>(
65 CustomData_get_layer_for_write(&mesh->corner_data, CD_MLOOPTANGENT, mesh->corners_num));
66 memset(r_looptangents, 0, sizeof(float[4]) * mesh->corners_num);
67 }
68 else {
69 r_looptangents = static_cast<float(*)[4]>(CustomData_add_layer(
70 &mesh->corner_data, CD_MLOOPTANGENT, CD_SET_DEFAULT, mesh->corners_num));
72 }
73
74 BKE_mesh_calc_loop_tangent_single(mesh, uvmap, r_looptangents, reports);
75}
76
77static void rna_Mesh_free_tangents(Mesh *mesh)
78{
80}
81
82static void rna_Mesh_calc_corner_tri(Mesh *mesh)
83{
84 mesh->corner_tris();
85}
86
87static void rna_Mesh_calc_smooth_groups(Mesh *mesh,
88 bool use_bitflags,
89 bool use_boundary_vertices_for_bitflags,
90 int **r_poly_group,
91 int *r_poly_group_num,
92 int *r_group_total)
93{
94 using namespace blender;
95 *r_poly_group_num = mesh->faces_num;
96 const bke::AttributeAccessor attributes = mesh->attributes();
97 const VArraySpan sharp_edges = *attributes.lookup<bool>("sharp_edge", bke::AttrDomain::Edge);
98 const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
99 if (use_bitflags) {
100 *r_poly_group = BKE_mesh_calc_smoothgroups_bitflags(mesh->edges_num,
101 mesh->verts_num,
102 mesh->faces(),
103 mesh->corner_edges(),
104 mesh->corner_verts(),
105 sharp_edges,
106 sharp_faces,
107 use_boundary_vertices_for_bitflags,
108 r_group_total);
109 }
110 else {
111 *r_poly_group = BKE_mesh_calc_smoothgroups(mesh->edges_num,
112 mesh->faces(),
113 mesh->corner_edges(),
114 sharp_edges,
115 sharp_faces,
116 r_group_total);
117 }
118}
119
120static void rna_Mesh_normals_split_custom_set(Mesh *mesh,
122 const float *normals,
123 int normals_num)
124{
125 using namespace blender;
126 float3 *corner_normals = (float3 *)normals;
127 const int numloops = mesh->corners_num;
128 if (normals_num != numloops * 3) {
130 RPT_ERROR,
131 "Number of custom normals is not number of loops (%f / %d)",
132 float(normals_num) / 3.0f,
133 numloops);
134 return;
135 }
136
137 bke::mesh_set_custom_normals(*mesh, {corner_normals, numloops});
138
139 DEG_id_tag_update(&mesh->id, 0);
140}
141
142static void rna_Mesh_normals_split_custom_set_from_vertices(Mesh *mesh,
144 const float *normals,
145 int normals_num)
146{
147 using namespace blender;
148 float3 *vert_normals = (float3 *)normals;
149 const int numverts = mesh->verts_num;
150 if (normals_num != numverts * 3) {
152 RPT_ERROR,
153 "Number of custom normals is not number of vertices (%f / %d)",
154 float(normals_num) / 3.0f,
155 numverts);
156 return;
157 }
158
159 bke::mesh_set_custom_normals_from_verts(*mesh, {vert_normals, numverts});
160
161 DEG_id_tag_update(&mesh->id, 0);
162}
163
164static void rna_Mesh_transform(Mesh *mesh, const float mat[16], bool shape_keys)
165{
167
168 DEG_id_tag_update(&mesh->id, 0);
169}
170
171static void rna_Mesh_flip_normals(Mesh *mesh)
172{
173 using namespace blender;
177 DEG_id_tag_update(&mesh->id, 0);
178}
179
180static void rna_Mesh_update(Mesh *mesh,
181 bContext *C,
182 const bool calc_edges,
183 const bool calc_edges_loose)
184{
185 if (calc_edges || ((mesh->faces_num || mesh->totface_legacy) && mesh->edges_num == 0)) {
187 }
188
189 if (calc_edges_loose) {
190 mesh->runtime->loose_edges_cache.tag_dirty();
191 }
192
193 /* Default state is not to have tessface's so make sure this is the case. */
195
196 mesh->runtime->vert_normals_cache.tag_dirty();
197 mesh->runtime->face_normals_cache.tag_dirty();
198 mesh->runtime->corner_normals_cache.tag_dirty();
199 mesh->runtime->vert_normals_true_cache.tag_dirty();
200 mesh->runtime->face_normals_true_cache.tag_dirty();
201
202 DEG_id_tag_update(&mesh->id, 0);
204}
205
206static void rna_Mesh_update_gpu_tag(Mesh *mesh)
207{
209}
210
211static void rna_Mesh_count_selected_items(Mesh *mesh, int r_count[3])
212{
214}
215
216static void rna_Mesh_clear_geometry(Mesh *mesh)
217{
219 BKE_animdata_free(&mesh->id, false);
220
222
225}
226
227#else
228
230{
231 FunctionRNA *func;
232 PropertyRNA *parm;
233 const int normals_array_dim[] = {1, 3};
234
235 func = RNA_def_function(srna, "transform", "rna_Mesh_transform");
237 "Transform mesh vertices by a matrix "
238 "(Warning: inverts normals if matrix is negative)");
239 parm = RNA_def_float_matrix(func, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
241 RNA_def_boolean(func, "shape_keys", false, "", "Transform Shape Keys");
242
243 func = RNA_def_function(srna, "flip_normals", "rna_Mesh_flip_normals");
245 "Invert winding of all polygons "
246 "(clears tessellation, does not handle custom normals)");
247
248 func = RNA_def_function(srna, "set_sharp_from_angle", "rna_Mesh_sharp_from_angle_set");
250 "Reset and fill the \"sharp_edge\" attribute based on the angle "
251 "of faces neighboring manifold edges");
252 RNA_def_float(func,
253 "angle",
254 M_PI,
255 0.0f,
256 M_PI,
257 "Angle",
258 "Angle between faces beyond which edges are marked sharp",
259 0.0f,
260 M_PI);
261
262 func = RNA_def_function(srna, "split_faces", "ED_mesh_split_faces");
263 RNA_def_function_ui_description(func, "Split faces based on the edge angle");
264
265 func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
268 func,
269 "Compute tangents and bitangent signs, to be used together with the split normals "
270 "to get a complete tangent space for normal mapping "
271 "(split normals are also computed if not yet present)");
272 RNA_def_string(func,
273 "uvmap",
274 nullptr,
276 "",
277 "Name of the UV map to use for tangent space computation");
278
279 func = RNA_def_function(srna, "free_tangents", "rna_Mesh_free_tangents");
280 RNA_def_function_ui_description(func, "Free tangents");
281
282 func = RNA_def_function(srna, "calc_loop_triangles", "rna_Mesh_calc_corner_tri");
284 "Calculate loop triangle tessellation (supports editmode too)");
285
286 func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
287 RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
289 func, "use_bitflags", false, "", "Produce bitflags groups instead of simple numeric values");
291 func,
292 "use_boundary_vertices_for_bitflags",
293 false,
294 "",
295 "Also consider different smoothgroups sharing only vertices (but without any common edge) "
296 "as neighbors, preventing them from sharing the same bitflag value. Only effective when "
297 "`use_bitflags` is set. WARNING: Will overflow (run out of available bits) easily with some "
298 "types of topology, e.g. large fans of sharp edges");
299 /* return values */
300 parm = RNA_def_int_array(func, "poly_groups", 1, nullptr, 0, 0, "", "Smooth Groups", 0, 0);
302 parm = RNA_def_int(
303 func, "groups", 0, 0, INT_MAX, "groups", "Total number of groups", 0, INT_MAX);
305
306 func = RNA_def_function(srna, "normals_split_custom_set", "rna_Mesh_normals_split_custom_set");
308 "Define custom split normals of this mesh "
309 "(use zero-vectors to keep auto ones)");
311 /* TODO: see how array size of 0 works, this shouldn't be used. */
312 parm = RNA_def_float_array(func, "normals", 1, nullptr, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
313 RNA_def_property_multi_array(parm, 2, normals_array_dim);
315
316 func = RNA_def_function(srna,
317 "normals_split_custom_set_from_vertices",
318 "rna_Mesh_normals_split_custom_set_from_vertices");
320 func,
321 "Define custom split normals of this mesh, from vertices' normals "
322 "(use zero-vectors to keep auto ones)");
324 /* TODO: see how array size of 0 works, this shouldn't be used. */
325 parm = RNA_def_float_array(func, "normals", 1, nullptr, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
326 RNA_def_property_multi_array(parm, 2, normals_array_dim);
328
329 func = RNA_def_function(srna, "update", "rna_Mesh_update");
330 RNA_def_boolean(func, "calc_edges", false, "Calculate Edges", "Force recalculation of edges");
331 RNA_def_boolean(func,
332 "calc_edges_loose",
333 false,
334 "Calculate Loose Edges",
335 "Calculate the loose state of each edge");
337
338 RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag");
339
340 func = RNA_def_function(srna, "unit_test_compare", "rna_Mesh_unit_test_compare");
341 RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to compare to");
343 "threshold",
344 FLT_EPSILON * 60,
345 0.0f,
346 FLT_MAX,
347 "Threshold",
348 "Comparison tolerance threshold",
349 0.0f,
350 FLT_MAX);
351 /* return value */
352 parm = RNA_def_string(
353 func, "result", "nothing", 64, "Return value", "String description of result of comparison");
354 RNA_def_function_return(func, parm);
355
356 func = RNA_def_function(srna, "clear_geometry", "rna_Mesh_clear_geometry");
358 func,
359 "Remove all geometry from the mesh. Note that this does not free shape keys or materials.");
360
361 func = RNA_def_function(srna, "validate", "BKE_mesh_validate");
363 "Validate geometry, return True when the mesh has had "
364 "invalid geometry corrected/removed");
365 RNA_def_boolean(func, "verbose", false, "Verbose", "Output information about the errors found");
366 RNA_def_boolean(func,
367 "clean_customdata",
368 true,
369 "Clean Custom Data",
370 "Remove temp/cached custom-data layers, like e.g. normals...");
371 parm = RNA_def_boolean(func, "result", false, "Result", "");
372 RNA_def_function_return(func, parm);
373
374 func = RNA_def_function(srna, "validate_material_indices", "BKE_mesh_validate_material_indices");
376 func,
377 "Validate material indices of polygons, return True when the mesh has had "
378 "invalid indices corrected (to default 0)");
379 parm = RNA_def_boolean(func, "result", false, "Result", "");
380 RNA_def_function_return(func, parm);
381
382 func = RNA_def_function(srna, "count_selected_items", "rna_Mesh_count_selected_items ");
383 RNA_def_function_ui_description(func, "Return the number of selected items (vert, edge, face)");
384 parm = RNA_def_int_vector(func, "result", 3, nullptr, 0, INT_MAX, "Result", nullptr, 0, INT_MAX);
385 RNA_def_function_output(func, parm);
386}
387
388#endif
void BKE_animdata_free(ID *id, bool do_id_user)
Definition anim_data.cc:187
void CustomData_set_layer_flag(CustomData *data, eCustomDataType type, int flag)
@ CD_SET_DEFAULT
void CustomData_free_layers(CustomData *data, eCustomDataType type)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
void BKE_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode)
void BKE_mesh_tessface_clear(Mesh *mesh)
void BKE_mesh_clear_geometry_and_metadata(Mesh *mesh)
void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3])
@ BKE_MESH_BATCH_DIRTY_ALL
Definition BKE_mesh.h:38
int * BKE_mesh_calc_smoothgroups(int edges_num, blender::OffsetIndices< int > faces, blender::Span< int > corner_edges, blender::Span< bool > sharp_edges, blender::Span< bool > sharp_faces, int *r_totgroup)
int * BKE_mesh_calc_smoothgroups_bitflags(int edges_num, int verts_num, blender::OffsetIndices< int > faces, blender::Span< int > corner_edges, blender::Span< int > corner_verts, blender::Span< bool > sharp_edges, blender::Span< bool > sharp_faces, bool use_boundary_vertices_for_bitflags, int *r_totgroup)
void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, const char *uvmap, float(*r_looptangents)[4], ReportList *reports)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define M_PI
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY_ALL_MODES
Definition DNA_ID.h:1089
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ CD_MLOOPTANGENT
@ CD_FLAG_TEMPORARY
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
@ PARM_REQUIRED
Definition RNA_types.hh:511
@ PARM_OUTPUT
Definition RNA_types.hh:512
@ FUNC_USE_REPORTS
Definition RNA_types.hh:805
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:804
PropertyFlag
Definition RNA_types.hh:286
@ PROP_DYNAMIC
Definition RNA_types.hh:402
#define C
Definition RandGen.cpp:29
#define NC_GEOM
Definition WM_types.hh:390
#define ND_DATA
Definition WM_types.hh:506
ReportList * reports
Definition WM_types.hh:1025
GAttributeReader lookup(const StringRef attribute_id) const
static float normals[][3]
#define MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX
std::optional< GeoMismatch > compare_meshes(const Mesh &mesh1, const Mesh &mesh2, float threshold)
Checks if the two meshes are different, returning the type of mismatch if any. Changes in index order...
const char * mismatch_to_string(const GeoMismatch &mismatch)
void mesh_sharp_edges_set_from_angle(Mesh &mesh, float angle, bool keep_sharp_edges=false)
void mesh_flip_faces(Mesh &mesh, const IndexMask &selection)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
void mesh_transform(Mesh &mesh, const float4x4 &transform, bool do_shape_keys)
void mesh_set_custom_normals_from_verts(Mesh &mesh, MutableSpan< float3 > vert_normals)
void mesh_ensure_required_data_layers(Mesh &mesh)
void mesh_set_custom_normals(Mesh &mesh, MutableSpan< float3 > corner_normals)
MatBase< float, 4, 4 > float4x4
PropertyRNA * RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const int *default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret)
PropertyRNA * RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identifier, const int rows, const int columns, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int length[])
PropertyRNA * RNA_def_int_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const int *default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
FunctionRNA * RNA_def_function(StructRNA *srna, const char *identifier, const char *call)
PropertyRNA * RNA_def_pointer(StructOrFunctionRNA *cont_, const char *identifier, const char *type, const char *ui_name, const char *ui_description)
void RNA_def_function_ui_description(FunctionRNA *func, const char *description)
void RNA_def_function_flag(FunctionRNA *func, int flag)
PropertyRNA * RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_function_output(FunctionRNA *, PropertyRNA *ret)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
void RNA_def_parameter_flags(PropertyRNA *prop, PropertyFlag flag_property, ParameterFlag flag_parameter)
void RNA_api_mesh(StructRNA *srna)
#define FLT_MAX
Definition stdcycles.h:14
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)