Blender V5.0
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 using namespace blender;
62 float4 *r_looptangents;
63 if (CustomData_has_layer(&mesh->corner_data, CD_MLOOPTANGENT)) {
64 r_looptangents = static_cast<float4 *>(
65 CustomData_get_layer_for_write(&mesh->corner_data, CD_MLOOPTANGENT, mesh->corners_num));
66 memset(r_looptangents, 0, sizeof(float4) * mesh->corners_num);
67 }
68 else {
69 r_looptangents = static_cast<float4 *>(CustomData_add_layer(
70 &mesh->corner_data, CD_MLOOPTANGENT, CD_SET_DEFAULT, mesh->corners_num));
72 }
73
74 if (!uvmap) {
76 }
77
78 const bke::AttributeAccessor attributes = mesh->attributes();
79 const VArraySpan uv_map = *attributes.lookup<float2>(uvmap, bke::AttrDomain::Corner);
80 if (uv_map.is_empty()) {
81 BKE_reportf(reports,
83 "Tangent space computation needs a UV Map, \"%s\" not found, aborting",
84 uvmap);
85 return;
86 }
87
89 mesh->faces(),
90 mesh->corner_verts(),
91 mesh->corner_normals(),
92 uv_map,
93 {r_looptangents, mesh->corners_num},
94 reports);
95}
96
97static void rna_Mesh_free_tangents(Mesh *mesh)
98{
100}
101
102static void rna_Mesh_calc_corner_tri(Mesh *mesh)
103{
104 mesh->corner_tris();
105}
106
107static void rna_Mesh_calc_smooth_groups(Mesh *mesh,
108 bool use_bitflags,
109 bool use_boundary_vertices_for_bitflags,
110 int **r_poly_group,
111 int *r_poly_group_num,
112 int *r_group_total)
113{
114 using namespace blender;
115 *r_poly_group_num = mesh->faces_num;
116 const bke::AttributeAccessor attributes = mesh->attributes();
117 const VArraySpan sharp_edges = *attributes.lookup<bool>("sharp_edge", bke::AttrDomain::Edge);
118 const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
119 if (use_bitflags) {
120 *r_poly_group = BKE_mesh_calc_smoothgroups_bitflags(mesh->edges_num,
121 mesh->verts_num,
122 mesh->faces(),
123 mesh->corner_edges(),
124 mesh->corner_verts(),
125 sharp_edges,
126 sharp_faces,
127 use_boundary_vertices_for_bitflags,
128 r_group_total);
129 }
130 else {
131 *r_poly_group = BKE_mesh_calc_smoothgroups(mesh->edges_num,
132 mesh->faces(),
133 mesh->corner_edges(),
134 sharp_edges,
135 sharp_faces,
136 r_group_total);
137 }
138}
139
140static void rna_Mesh_normals_split_custom_set(Mesh *mesh,
141 ReportList *reports,
142 const float *normals,
143 int normals_num)
144{
145 using namespace blender;
146 float3 *corner_normals = (float3 *)normals;
147 const int numloops = mesh->corners_num;
148 if (normals_num != numloops * 3) {
149 BKE_reportf(reports,
150 RPT_ERROR,
151 "Number of custom normals is not number of loops (%f / %d)",
152 float(normals_num) / 3.0f,
153 numloops);
154 return;
155 }
156
157 bke::mesh_set_custom_normals(*mesh, {corner_normals, numloops});
158
159 DEG_id_tag_update(&mesh->id, 0);
160}
161
162static void rna_Mesh_normals_split_custom_set_from_vertices(Mesh *mesh,
163 ReportList *reports,
164 const float *normals,
165 int normals_num)
166{
167 using namespace blender;
168 float3 *vert_normals = (float3 *)normals;
169 const int numverts = mesh->verts_num;
170 if (normals_num != numverts * 3) {
171 BKE_reportf(reports,
172 RPT_ERROR,
173 "Number of custom normals is not number of vertices (%f / %d)",
174 float(normals_num) / 3.0f,
175 numverts);
176 return;
177 }
178
179 bke::mesh_set_custom_normals_from_verts(*mesh, {vert_normals, numverts});
180
181 DEG_id_tag_update(&mesh->id, 0);
182}
183
184static void rna_Mesh_transform(Mesh *mesh, const float mat[16], bool shape_keys)
185{
187
188 DEG_id_tag_update(&mesh->id, 0);
189}
190
191static void rna_Mesh_flip_normals(Mesh *mesh)
192{
193 using namespace blender;
197 DEG_id_tag_update(&mesh->id, 0);
198}
199
200static void rna_Mesh_update(Mesh *mesh,
201 bContext *C,
202 const bool calc_edges,
203 const bool calc_edges_loose)
204{
205 if (calc_edges || ((mesh->faces_num || mesh->totface_legacy) && mesh->edges_num == 0)) {
207 }
208
209 if (calc_edges_loose) {
210 mesh->runtime->loose_edges_cache.tag_dirty();
211 }
212
213 /* Default state is not to have tessface's so make sure this is the case. */
215
216 mesh->runtime->vert_normals_cache.tag_dirty();
217 mesh->runtime->face_normals_cache.tag_dirty();
218 mesh->runtime->corner_normals_cache.tag_dirty();
219 mesh->runtime->vert_normals_true_cache.tag_dirty();
220 mesh->runtime->face_normals_true_cache.tag_dirty();
221
222 DEG_id_tag_update(&mesh->id, 0);
224}
225
226static void rna_Mesh_update_gpu_tag(Mesh *mesh)
227{
229}
230
231static void rna_Mesh_count_selected_items(Mesh *mesh, int r_count[3])
232{
234}
235
236static void rna_Mesh_clear_geometry(Mesh *mesh)
237{
239 BKE_animdata_free(&mesh->id, false);
240
242
245}
246
247#else
248
250{
251 FunctionRNA *func;
252 PropertyRNA *parm;
253 const int normals_array_dim[] = {1, 3};
254
255 func = RNA_def_function(srna, "transform", "rna_Mesh_transform");
257 "Transform mesh vertices by a matrix "
258 "(Warning: inverts normals if matrix is negative)");
259 parm = RNA_def_float_matrix(func, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
261 RNA_def_boolean(func, "shape_keys", false, "", "Transform Shape Keys");
262
263 func = RNA_def_function(srna, "flip_normals", "rna_Mesh_flip_normals");
265 "Invert winding of all polygons "
266 "(clears tessellation, does not handle custom normals)");
267
268 func = RNA_def_function(srna, "set_sharp_from_angle", "rna_Mesh_sharp_from_angle_set");
270 "Reset and fill the \"sharp_edge\" attribute based on the angle "
271 "of faces neighboring manifold edges");
272 RNA_def_float(func,
273 "angle",
274 M_PI,
275 0.0f,
276 M_PI,
277 "Angle",
278 "Angle between faces beyond which edges are marked sharp",
279 0.0f,
280 M_PI);
281
282 func = RNA_def_function(srna, "split_faces", "ED_mesh_split_faces");
283 RNA_def_function_ui_description(func, "Split faces based on the edge angle");
284
285 func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
288 func,
289 "Compute tangents and bitangent signs, to be used together with the custom normals "
290 "to get a complete tangent space for normal mapping "
291 "(custom normals are also computed if not yet present)");
292 RNA_def_string(func,
293 "uvmap",
294 nullptr,
296 "",
297 "Name of the UV map to use for tangent space computation");
298
299 func = RNA_def_function(srna, "free_tangents", "rna_Mesh_free_tangents");
300 RNA_def_function_ui_description(func, "Free tangents");
301
302 func = RNA_def_function(srna, "calc_loop_triangles", "rna_Mesh_calc_corner_tri");
304 "Calculate loop triangle tessellation (supports editmode too)");
305
306 func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
307 RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
309 func, "use_bitflags", false, "", "Produce bitflags groups instead of simple numeric values");
311 func,
312 "use_boundary_vertices_for_bitflags",
313 false,
314 "",
315 "Also consider different smoothgroups sharing only vertices (but without any common edge) "
316 "as neighbors, preventing them from sharing the same bitflag value. Only effective when "
317 "``use_bitflags`` is set. "
318 "WARNING: Will overflow (run out of available bits) easily with some types of topology, "
319 "e.g. large fans of sharp edges");
320 /* return values */
321 parm = RNA_def_int_array(func, "poly_groups", 1, nullptr, 0, 0, "", "Smooth Groups", 0, 0);
323 parm = RNA_def_int(
324 func, "groups", 0, 0, INT_MAX, "groups", "Total number of groups", 0, INT_MAX);
326
327 func = RNA_def_function(srna, "normals_split_custom_set", "rna_Mesh_normals_split_custom_set");
329 "Define custom normals of this mesh "
330 "(use zero-vectors to keep auto ones)");
332 /* TODO: see how array size of 0 works, this shouldn't be used. */
333 parm = RNA_def_float_array(func, "normals", 1, nullptr, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
334 RNA_def_property_multi_array(parm, 2, normals_array_dim);
336
337 func = RNA_def_function(srna,
338 "normals_split_custom_set_from_vertices",
339 "rna_Mesh_normals_split_custom_set_from_vertices");
341 "Define custom normals of this mesh, from vertices' normals "
342 "(use zero-vectors to keep auto ones)");
344 /* TODO: see how array size of 0 works, this shouldn't be used. */
345 parm = RNA_def_float_array(func, "normals", 1, nullptr, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
346 RNA_def_property_multi_array(parm, 2, normals_array_dim);
348
349 func = RNA_def_function(srna, "update", "rna_Mesh_update");
350 RNA_def_boolean(func, "calc_edges", false, "Calculate Edges", "Force recalculation of edges");
351 RNA_def_boolean(func,
352 "calc_edges_loose",
353 false,
354 "Calculate Loose Edges",
355 "Calculate the loose state of each edge");
357
358 RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag");
359
360 func = RNA_def_function(srna, "unit_test_compare", "rna_Mesh_unit_test_compare");
361 RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to compare to");
363 "threshold",
364 FLT_EPSILON * 60,
365 0.0f,
366 FLT_MAX,
367 "Threshold",
368 "Comparison tolerance threshold",
369 0.0f,
370 FLT_MAX);
371 /* return value */
372 parm = RNA_def_string(
373 func, "result", "nothing", 64, "Return value", "String description of result of comparison");
374 RNA_def_function_return(func, parm);
375
376 func = RNA_def_function(srna, "clear_geometry", "rna_Mesh_clear_geometry");
378 func,
379 "Remove all geometry from the mesh. Note that this does not free shape keys or materials.");
380
381 func = RNA_def_function(srna, "validate", "BKE_mesh_validate");
383 "Validate geometry, return True when the mesh has had "
384 "invalid geometry corrected/removed");
385 RNA_def_boolean(func, "verbose", false, "Verbose", "Output information about the errors found");
386 RNA_def_boolean(func,
387 "clean_customdata",
388 true,
389 "Clean Custom Data",
390 "Remove temp/cached custom-data layers, like e.g. normals...");
391 parm = RNA_def_boolean(func, "result", false, "Result", "");
392 RNA_def_function_return(func, parm);
393
394 func = RNA_def_function(srna, "validate_material_indices", "BKE_mesh_validate_material_indices");
396 func,
397 "Validate material indices of polygons, return True when the mesh has had "
398 "invalid indices corrected (to default 0)");
399 parm = RNA_def_boolean(func, "result", false, "Result", "");
400 RNA_def_function_return(func, parm);
401
402 func = RNA_def_function(srna, "count_selected_items", "rna_Mesh_count_selected_items ");
403 RNA_def_function_ui_description(func, "Return the number of selected items (vert, edge, face)");
404 parm = RNA_def_int_vector(func, "result", 3, nullptr, 0, INT_MAX, "Result", nullptr, 0, INT_MAX);
405 RNA_def_function_output(func, parm);
406}
407
408#endif
void BKE_animdata_free(ID *id, bool do_id_user)
Definition anim_data.cc:188
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)
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
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_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR
Definition BKE_report.hh:39
#define M_PI
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY_ALL_MODES
Definition DNA_ID.h:1181
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ CD_MLOOPTANGENT
@ CD_PROP_FLOAT2
@ CD_FLAG_TEMPORARY
#define MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
@ PARM_REQUIRED
Definition RNA_types.hh:545
@ PARM_OUTPUT
Definition RNA_types.hh:546
@ FUNC_USE_REPORTS
Definition RNA_types.hh:914
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:913
PropertyFlag
Definition RNA_types.hh:300
@ PROP_DYNAMIC
Definition RNA_types.hh:428
#define C
Definition RandGen.cpp:29
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DATA
Definition WM_types.hh:509
constexpr bool is_empty() const
Definition BLI_span.hh:260
GAttributeReader lookup(const StringRef attribute_id) const
static float normals[][3]
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 calc_uv_tangent_tris_quads(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, Span< float3 > corner_normals, Span< float2 > uv_map, MutableSpan< float4 > results, ReportList *reports)
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)