diff options
Diffstat (limited to 'source/blender/makesrna')
-rw-r--r-- | source/blender/makesrna/intern/rna_mesh.c | 35 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_mesh_api.c | 115 |
2 files changed, 142 insertions, 8 deletions
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 3d6eab2bc88..44bae770186 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -207,6 +207,11 @@ static void rna_MeshAnyLayer_name_set(PointerRNA *ptr, const char *value) rna_cd_layer_name_set(cd, (CustomDataLayer *)ptr->data, value); } +static int rna_Mesh_has_custom_normals_get(PointerRNA *ptr) +{ + Mesh *me = ptr->data; + return (int)BKE_mesh_has_custom_loop_normals(me); +} /* -------------------------------------------------------------------- */ /* Update Callbacks */ @@ -338,6 +343,17 @@ static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values) } } +static void rna_MeshLoop_normal_set(PointerRNA *ptr, const float *values) +{ + Mesh *me = rna_mesh(ptr); + MLoop *ml = (MLoop *)ptr->data; + float (*vec)[3] = CustomData_get(&me->ldata, (int)(ml - me->mloop), CD_NORMAL); + + if (vec) { + normalize_v3_v3(*vec, values); + } +} + static void rna_MeshLoop_tangent_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); @@ -1974,8 +1990,7 @@ static void rna_def_mloop(BlenderRNA *brna) prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", NULL, NULL); + RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", "rna_MeshLoop_normal_set", NULL); RNA_def_property_ui_text(prop, "Normal", "Local space unit length split normal vector of this vertex for this polygon " "(must be computed beforehand using calc_normals_split or calc_tangents)"); @@ -3186,8 +3201,8 @@ static void rna_def_mesh(BlenderRNA *brna) prop = RNA_def_property(srna, "use_auto_smooth", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH); RNA_def_property_ui_text(prop, "Auto Smooth", - "Treat all set-smoothed faces with angles less than the specified angle " - "as 'smooth', unless they are linked by a sharp edge"); + "Auto smooth (based on smooth/sharp faces/edges and angle between faces), " + "or use custom split normals data if available"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); prop = RNA_def_property(srna, "auto_smooth_angle", PROP_FLOAT, PROP_ANGLE); @@ -3196,9 +3211,19 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f)); RNA_def_property_ui_range(prop, DEG2RADF(0.0f), DEG2RADF(180.0f), 1.0, 1); RNA_def_property_ui_text(prop, "Auto Smooth Angle", - "Maximum angle between face normals that 'Auto Smooth' will operate on"); + "Maximum angle between face normals that will be considered as smooth " + "(unused if custom split normals data are available)"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + RNA_define_verify_sdna(false); + prop = RNA_def_property(srna, "has_custom_normals", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "", 0); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Has Custom Normals", + "True if there are custom split normals data in this mesh"); + RNA_def_property_boolean_funcs(prop, "rna_Mesh_has_custom_normals_get", NULL); + RNA_define_verify_sdna(true); + prop = RNA_def_property(srna, "show_double_sided", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_TWOSIDED); RNA_def_property_ui_text(prop, "Double Sided", "Render/display the mesh with double or single sided lighting"); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 09f12f6a4af..40dad902eae 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -61,10 +61,19 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, struct Mesh *me return ret; } +static void rna_Mesh_create_normals_split(Mesh *mesh) +{ + if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { + CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop); + CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + } +} + static void rna_Mesh_calc_normals_split(Mesh *mesh) { float (*r_loopnors)[3]; float (*polynors)[3]; + short (*clnors)[2] = NULL; bool free_polynors = false; if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { @@ -76,6 +85,9 @@ static void rna_Mesh_calc_normals_split(Mesh *mesh) CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } + /* may be NULL */ + clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); + if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { /* This assume that layer is always up to date, not sure this is the case (esp. in Edit mode?)... */ polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL); @@ -88,9 +100,10 @@ static void rna_Mesh_calc_normals_split(Mesh *mesh) free_polynors = true; } - BKE_mesh_normals_loop_split(mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, - mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, polynors, mesh->totpoly, - (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh); + BKE_mesh_normals_loop_split( + mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, + mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, + (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, NULL, clnors, NULL); if (free_polynors) { MEM_freeN(polynors); @@ -139,6 +152,78 @@ static void rna_Mesh_calc_smooth_groups(Mesh *mesh, int use_bitflags, int *r_pol r_group_total, use_bitflags); } +static void rna_Mesh_normals_split_custom_do(Mesh *mesh, float (*custom_loopnors)[3], const bool use_vertices) +{ + float (*polynors)[3]; + short (*clnors)[2]; + const int numloops = mesh->totloop; + bool free_polynors = false; + + clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); + if (clnors) { + memset(clnors, 0, sizeof(*clnors) * numloops); + } + else { + clnors = CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, numloops); + } + + if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { + polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL); + } + else { + polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__); + BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, + polynors, false); + free_polynors = true; + } + + if (use_vertices) { + BKE_mesh_normals_loop_custom_from_vertices_set( + mesh->mvert, custom_loopnors, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, mesh->totloop, + mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, clnors); + } + else { + BKE_mesh_normals_loop_custom_set( + mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, custom_loopnors, mesh->totloop, + mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, clnors); + } + + if (free_polynors) { + MEM_freeN(polynors); + } +} + +static void rna_Mesh_normals_split_custom_set(Mesh *mesh, ReportList *reports, int normals_len, float *normals) +{ + float (*loopnors)[3] = (float (*)[3])normals; + const int numloops = mesh->totloop; + + if (normals_len != numloops * 3) { + BKE_reportf(reports, RPT_ERROR, + "number of custom normals is not number of loops (%f / %d)", + (float)normals_len / 3.0f, numloops); + return; + } + + rna_Mesh_normals_split_custom_do(mesh, loopnors, false); +} + +static void rna_Mesh_normals_split_custom_set_from_vertices( + Mesh *mesh, ReportList *reports, int normals_len, float *normals) +{ + float (*vertnors)[3] = (float (*)[3])normals; + const int numverts = mesh->totvert; + + if (normals_len != numverts * 3) { + BKE_reportf(reports, RPT_ERROR, + "number of custom normals is not number of vertices (%f / %d)", + (float)normals_len / 3.0f, numverts); + return; + } + + rna_Mesh_normals_split_custom_do(mesh, vertnors, true); +} + static void rna_Mesh_transform(Mesh *mesh, float *mat, int shape_keys) { BKE_mesh_transform(mesh, (float (*)[4])mat, shape_keys); @@ -152,6 +237,7 @@ void RNA_api_mesh(StructRNA *srna) { FunctionRNA *func; PropertyRNA *parm; + const int normals_array_dim[] = {1, 3}; func = RNA_def_function(srna, "transform", "rna_Mesh_transform"); RNA_def_function_ui_description(func, "Transform mesh vertices by a matrix"); @@ -162,6 +248,9 @@ void RNA_api_mesh(StructRNA *srna) func = RNA_def_function(srna, "calc_normals", "BKE_mesh_calc_normals"); RNA_def_function_ui_description(func, "Calculate vertex normals"); + func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split"); + RNA_def_function_ui_description(func, "Empty split vertex normals"); + func = RNA_def_function(srna, "calc_normals_split", "rna_Mesh_calc_normals_split"); RNA_def_function_ui_description(func, "Calculate split vertex normals, which preserve sharp edges"); @@ -192,6 +281,26 @@ void RNA_api_mesh(StructRNA *srna) parm = RNA_def_int(func, "groups", 0, 0, INT_MAX, "groups", "Total number of groups", 0, INT_MAX); RNA_def_property_flag(parm, PROP_OUTPUT); + func = RNA_def_function(srna, "normals_split_custom_set", "rna_Mesh_normals_split_custom_set"); + RNA_def_function_ui_description(func, + "Define custom split normals of this mesh " + "(use zero-vectors to keep auto ones)"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + /* TODO, see how array size of 0 works, this shouldnt be used */ + parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f); + RNA_def_property_multi_array(parm, 2, normals_array_dim); + RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_REQUIRED); + + func = RNA_def_function(srna, "normals_split_custom_set_from_vertices", + "rna_Mesh_normals_split_custom_set_from_vertices"); + RNA_def_function_ui_description(func, + "Define custom split normals of this mesh, from vertices' normals " + "(use zero-vectors to keep auto ones)"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + /* TODO, see how array size of 0 works, this shouldnt be used */ + parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f); + RNA_def_property_multi_array(parm, 2, normals_array_dim); + RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_REQUIRED); func = RNA_def_function(srna, "update", "ED_mesh_update"); RNA_def_boolean(func, "calc_edges", 0, "Calculate Edges", "Force recalculation of edges"); |