Blender V4.3
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
9#include <cstdio>
10#include <cstdlib>
11
12#include "RNA_define.hh"
13
15
16#include "BLI_math_base.h"
17#include "BLI_sys_types.h"
18#include "BLI_utildefines.h"
19
20#include "rna_internal.hh" /* own include */
21
22#ifdef RNA_RUNTIME
23
24# include "DNA_mesh_types.h"
25
26# include "BKE_anim_data.hh"
27# include "BKE_attribute.hh"
28# include "BKE_mesh.h"
29# include "BKE_mesh.hh"
30# include "BKE_mesh_compare.hh"
31# include "BKE_mesh_mapping.hh"
32# include "BKE_mesh_runtime.hh"
33# include "BKE_mesh_tangent.hh"
34# include "BKE_report.hh"
35
36# include "ED_mesh.hh"
37
38# include "DEG_depsgraph.hh"
39
40# include "WM_api.hh"
41
42static const char *rna_Mesh_unit_test_compare(Mesh *mesh, Mesh *mesh2, float threshold)
43{
44 using namespace blender::bke::compare_meshes;
45 const std::optional<MeshMismatch> mismatch = compare_meshes(*mesh, *mesh2, threshold);
46
47 if (!mismatch) {
48 return "Same";
49 }
50
51 return mismatch_to_string(mismatch.value());
52}
53
54static void rna_Mesh_sharp_from_angle_set(Mesh *mesh, const float angle)
55{
56 mesh->attributes_for_write().remove("sharp_edge");
57 mesh->attributes_for_write().remove("sharp_face");
60}
61
62static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap)
63{
64 float(*r_looptangents)[4];
65
66 if (CustomData_has_layer(&mesh->corner_data, CD_MLOOPTANGENT)) {
67 r_looptangents = static_cast<float(*)[4]>(
68 CustomData_get_layer_for_write(&mesh->corner_data, CD_MLOOPTANGENT, mesh->corners_num));
69 memset(r_looptangents, 0, sizeof(float[4]) * mesh->corners_num);
70 }
71 else {
72 r_looptangents = static_cast<float(*)[4]>(CustomData_add_layer(
73 &mesh->corner_data, CD_MLOOPTANGENT, CD_SET_DEFAULT, mesh->corners_num));
75 }
76
77 BKE_mesh_calc_loop_tangent_single(mesh, uvmap, r_looptangents, reports);
78}
79
80static void rna_Mesh_free_tangents(Mesh *mesh)
81{
82 CustomData_free_layers(&mesh->corner_data, CD_MLOOPTANGENT, mesh->corners_num);
83}
84
85static void rna_Mesh_calc_corner_tri(Mesh *mesh)
86{
87 mesh->corner_tris();
88}
89
90static void rna_Mesh_calc_smooth_groups(
91 Mesh *mesh, bool use_bitflags, int **r_poly_group, int *r_poly_group_num, int *r_group_total)
92{
93 using namespace blender;
94 *r_poly_group_num = mesh->faces_num;
95 const bke::AttributeAccessor attributes = mesh->attributes();
96 const VArraySpan sharp_edges = *attributes.lookup<bool>("sharp_edge", bke::AttrDomain::Edge);
97 const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
98 *r_poly_group = BKE_mesh_calc_smoothgroups(mesh->edges_num,
99 mesh->faces(),
100 mesh->corner_edges(),
101 sharp_edges,
102 sharp_faces,
103 r_group_total,
104 use_bitflags);
105}
106
107static void rna_Mesh_normals_split_custom_set(Mesh *mesh,
108 ReportList *reports,
109 const float *normals,
110 int normals_num)
111{
112 float(*corner_normals)[3] = (float(*)[3])normals;
113 const int numloops = mesh->corners_num;
114 if (normals_num != numloops * 3) {
115 BKE_reportf(reports,
116 RPT_ERROR,
117 "Number of custom normals is not number of loops (%f / %d)",
118 float(normals_num) / 3.0f,
119 numloops);
120 return;
121 }
122
123 BKE_mesh_set_custom_normals(mesh, corner_normals);
124
125 DEG_id_tag_update(&mesh->id, 0);
126}
127
128static void rna_Mesh_normals_split_custom_set_from_vertices(Mesh *mesh,
129 ReportList *reports,
130 const float *normals,
131 int normals_num)
132{
133 float(*vert_normals)[3] = (float(*)[3])normals;
134 const int numverts = mesh->verts_num;
135 if (normals_num != numverts * 3) {
136 BKE_reportf(reports,
137 RPT_ERROR,
138 "Number of custom normals is not number of vertices (%f / %d)",
139 float(normals_num) / 3.0f,
140 numverts);
141 return;
142 }
143
144 BKE_mesh_set_custom_normals_from_verts(mesh, vert_normals);
145
146 DEG_id_tag_update(&mesh->id, 0);
147}
148
149static void rna_Mesh_transform(Mesh *mesh, const float mat[16], bool shape_keys)
150{
151 BKE_mesh_transform(mesh, (const float(*)[4])mat, shape_keys);
152
153 DEG_id_tag_update(&mesh->id, 0);
154}
155
156static void rna_Mesh_flip_normals(Mesh *mesh)
157{
158 using namespace blender;
159 bke::mesh_flip_faces(*mesh, IndexMask(mesh->faces_num));
162 DEG_id_tag_update(&mesh->id, 0);
163}
164
165static void rna_Mesh_update(Mesh *mesh,
166 bContext *C,
167 const bool calc_edges,
168 const bool calc_edges_loose)
169{
170 if (calc_edges || ((mesh->faces_num || mesh->totface_legacy) && mesh->edges_num == 0)) {
171 blender::bke::mesh_calc_edges(*mesh, calc_edges, true);
172 }
173
174 if (calc_edges_loose) {
175 mesh->runtime->loose_edges_cache.tag_dirty();
176 }
177
178 /* Default state is not to have tessface's so make sure this is the case. */
180
181 mesh->runtime->vert_normals_cache.tag_dirty();
182 mesh->runtime->face_normals_cache.tag_dirty();
183 mesh->runtime->corner_normals_cache.tag_dirty();
184
185 DEG_id_tag_update(&mesh->id, 0);
187}
188
189static void rna_Mesh_update_gpu_tag(Mesh *mesh)
190{
192}
193
194static void rna_Mesh_count_selected_items(Mesh *mesh, int r_count[3])
195{
196 BKE_mesh_count_selected_items(mesh, r_count);
197}
198
199static void rna_Mesh_clear_geometry(Mesh *mesh)
200{
202 BKE_animdata_free(&mesh->id, false);
203
205
208}
209
210#else
211
213{
214 FunctionRNA *func;
215 PropertyRNA *parm;
216 const int normals_array_dim[] = {1, 3};
217
218 func = RNA_def_function(srna, "transform", "rna_Mesh_transform");
220 "Transform mesh vertices by a matrix "
221 "(Warning: inverts normals if matrix is negative)");
222 parm = RNA_def_float_matrix(func, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
224 RNA_def_boolean(func, "shape_keys", false, "", "Transform Shape Keys");
225
226 func = RNA_def_function(srna, "flip_normals", "rna_Mesh_flip_normals");
228 "Invert winding of all polygons "
229 "(clears tessellation, does not handle custom normals)");
230
231 func = RNA_def_function(srna, "set_sharp_from_angle", "rna_Mesh_sharp_from_angle_set");
233 "Reset and fill the \"sharp_edge\" attribute based on the angle "
234 "of faces neighboring manifold edges");
235 RNA_def_float(func,
236 "angle",
237 M_PI,
238 0.0f,
239 M_PI,
240 "Angle",
241 "Angle between faces beyond which edges are marked sharp",
242 0.0f,
243 M_PI);
244
245 func = RNA_def_function(srna, "split_faces", "ED_mesh_split_faces");
246 RNA_def_function_ui_description(func, "Split faces based on the edge angle");
247
248 func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
251 func,
252 "Compute tangents and bitangent signs, to be used together with the split normals "
253 "to get a complete tangent space for normal mapping "
254 "(split normals are also computed if not yet present)");
255 RNA_def_string(func,
256 "uvmap",
257 nullptr,
259 "",
260 "Name of the UV map to use for tangent space computation");
261
262 func = RNA_def_function(srna, "free_tangents", "rna_Mesh_free_tangents");
263 RNA_def_function_ui_description(func, "Free tangents");
264
265 func = RNA_def_function(srna, "calc_loop_triangles", "rna_Mesh_calc_corner_tri");
267 "Calculate loop triangle tessellation (supports editmode too)");
268
269 func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
270 RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
272 func, "use_bitflags", false, "", "Produce bitflags groups instead of simple numeric values");
273 /* return values */
274 parm = RNA_def_int_array(func, "poly_groups", 1, nullptr, 0, 0, "", "Smooth Groups", 0, 0);
276 parm = RNA_def_int(
277 func, "groups", 0, 0, INT_MAX, "groups", "Total number of groups", 0, INT_MAX);
279
280 func = RNA_def_function(srna, "normals_split_custom_set", "rna_Mesh_normals_split_custom_set");
282 "Define custom split normals of this mesh "
283 "(use zero-vectors to keep auto ones)");
285 /* TODO: see how array size of 0 works, this shouldn't be used. */
286 parm = RNA_def_float_array(func, "normals", 1, nullptr, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
287 RNA_def_property_multi_array(parm, 2, normals_array_dim);
289
290 func = RNA_def_function(srna,
291 "normals_split_custom_set_from_vertices",
292 "rna_Mesh_normals_split_custom_set_from_vertices");
294 func,
295 "Define custom split normals of this mesh, from vertices' normals "
296 "(use zero-vectors to keep auto ones)");
298 /* TODO: see how array size of 0 works, this shouldn't be used. */
299 parm = RNA_def_float_array(func, "normals", 1, nullptr, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
300 RNA_def_property_multi_array(parm, 2, normals_array_dim);
302
303 func = RNA_def_function(srna, "update", "rna_Mesh_update");
304 RNA_def_boolean(func, "calc_edges", false, "Calculate Edges", "Force recalculation of edges");
305 RNA_def_boolean(func,
306 "calc_edges_loose",
307 false,
308 "Calculate Loose Edges",
309 "Calculate the loose state of each edge");
311
312 RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag");
313
314 func = RNA_def_function(srna, "unit_test_compare", "rna_Mesh_unit_test_compare");
315 RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to compare to");
317 "threshold",
318 FLT_EPSILON * 60,
319 0.0f,
320 FLT_MAX,
321 "Threshold",
322 "Comparison tolerance threshold",
323 0.0f,
324 FLT_MAX);
325 /* return value */
326 parm = RNA_def_string(
327 func, "result", "nothing", 64, "Return value", "String description of result of comparison");
328 RNA_def_function_return(func, parm);
329
330 func = RNA_def_function(srna, "clear_geometry", "rna_Mesh_clear_geometry");
332 func,
333 "Remove all geometry from the mesh. Note that this does not free shape keys or materials.");
334
335 func = RNA_def_function(srna, "validate", "BKE_mesh_validate");
337 "Validate geometry, return True when the mesh has had "
338 "invalid geometry corrected/removed");
339 RNA_def_boolean(func, "verbose", false, "Verbose", "Output information about the errors found");
340 RNA_def_boolean(func,
341 "clean_customdata",
342 true,
343 "Clean Custom Data",
344 "Remove temp/cached custom-data layers, like e.g. normals...");
345 parm = RNA_def_boolean(func, "result", false, "Result", "");
346 RNA_def_function_return(func, parm);
347
348 func = RNA_def_function(srna, "validate_material_indices", "BKE_mesh_validate_material_indices");
350 func,
351 "Validate material indices of polygons, return True when the mesh has had "
352 "invalid indices corrected (to default 0)");
353 parm = RNA_def_boolean(func, "result", false, "Result", "");
354 RNA_def_function_return(func, parm);
355
356 func = RNA_def_function(srna, "count_selected_items", "rna_Mesh_count_selected_items ");
357 RNA_def_function_ui_description(func, "Return the number of selected items (vert, edge, face)");
358 parm = RNA_def_int_vector(func, "result", 3, nullptr, 0, INT_MAX, "Result", nullptr, 0, INT_MAX);
359 RNA_def_function_output(func, parm);
360}
361
362#endif
void BKE_animdata_free(ID *id, bool do_id_user)
Definition anim_data.cc:263
void CustomData_set_layer_flag(CustomData *data, eCustomDataType type, int flag)
@ CD_SET_DEFAULT
void CustomData_free_layers(CustomData *data, eCustomDataType type, int totelem)
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_set_custom_normals(Mesh *mesh, float(*r_custom_loop_normals)[3])
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
void BKE_mesh_set_custom_normals_from_verts(Mesh *mesh, float(*r_custom_vert_normals)[3])
void BKE_mesh_transform(Mesh *mesh, const float mat[4][4], bool do_keys)
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, bool use_bitflags)
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:1148
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ CD_FLAG_TEMPORARY
@ CD_MLOOPTANGENT
#define MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX
@ PARM_REQUIRED
Definition RNA_types.hh:397
@ PARM_OUTPUT
Definition RNA_types.hh:398
@ FUNC_USE_REPORTS
Definition RNA_types.hh:680
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:679
PropertyFlag
Definition RNA_types.hh:201
@ PROP_DYNAMIC
Definition RNA_types.hh:317
#define NC_GEOM
Definition WM_types.hh:360
#define ND_DATA
Definition WM_types.hh:475
draw_view in_light_buf[] float
const char * mismatch_to_string(const MeshMismatch &mismatch)
std::optional< MeshMismatch > 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...
void mesh_sharp_edges_set_from_angle(Mesh &mesh, float angle, bool keep_sharp_edges=false)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
void mesh_ensure_required_data_layers(Mesh &mesh)
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)