From cdd727b7ceab5772503b702322e93620b7df651b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 12 Oct 2015 20:12:55 +0200 Subject: Add functions to compute normals (verts, polys and loops ones) for a given shapekey. Title says pretty much everything, we now have BKE and RNA funcs to get vertex, poly and loop normals of a given shapekey. This will be used e.g. in FBX exporter (shapekeys need normal data too). Reviewed By: campbellbarton Differential Revision: https://developer.blender.org/D1510 --- source/blender/blenkernel/BKE_key.h | 2 + source/blender/blenkernel/BKE_mesh.h | 2 +- source/blender/blenkernel/intern/cdderivedmesh.c | 6 +- source/blender/blenkernel/intern/data_transfer.c | 2 +- source/blender/blenkernel/intern/key.c | 61 ++++++++++ source/blender/blenkernel/intern/mesh.c | 5 +- source/blender/blenkernel/intern/mesh_evaluate.c | 31 +++-- source/blender/blenkernel/intern/mesh_remap.c | 4 +- source/blender/makesrna/intern/rna_key.c | 139 +++++++++++++++++++++- source/blender/makesrna/intern/rna_mesh_api.c | 5 +- source/blender/modifiers/intern/MOD_normal_edit.c | 2 +- source/blender/modifiers/intern/MOD_solidify.c | 2 +- 12 files changed, 236 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index d5b3ed4be33..1edbb455ca4 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -103,6 +103,8 @@ void BKE_keyblock_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, st void BKE_keyblock_update_from_mesh(struct Mesh *me, struct KeyBlock *kb); void BKE_keyblock_convert_from_mesh(struct Mesh *me, struct KeyBlock *kb); void BKE_keyblock_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me); +void BKE_keyblock_mesh_calc_normals( + struct KeyBlock *kb, struct Mesh *mesh, float (*r_vertnors)[3], float (*r_polynors)[3], float (*r_loopnors)[3]); void BKE_keyblock_update_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); void BKE_keyblock_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index a27688c1c61..5bd8931ee2e 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -170,7 +170,7 @@ void BKE_mesh_calc_normals_mapping_ex( const struct MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3], const bool only_face_normals); void BKE_mesh_calc_normals_poly( - struct MVert *mverts, int numVerts, + struct MVert *mverts, float (*r_vertnors)[3], int numVerts, const struct MLoop *mloop, const struct MPoly *mpolys, int numLoops, int numPolys, float (*r_polyNors)[3], const bool only_face_normals); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 989e5e3a624..3b86c42d8c9 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2547,7 +2547,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals) /* calculate face normals */ BKE_mesh_calc_normals_poly( - cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), + cddm->mvert, NULL, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), dm->numLoopData, dm->numPolyData, face_nors, only_face_normals); @@ -2597,7 +2597,7 @@ void CDDM_calc_normals(DerivedMesh *dm) /* we don't want to overwrite any referenced layers */ cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); - BKE_mesh_calc_normals_poly(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), + BKE_mesh_calc_normals_poly(cddm->mvert, NULL, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), dm->numLoopData, dm->numPolyData, NULL, false); cddm->dm.dirty &= ~DM_DIRTY_NORMALS; @@ -2646,7 +2646,7 @@ void CDDM_calc_loop_normals_spacearr( if (!pnors) { pnors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, numPolys); } - BKE_mesh_calc_normals_poly(mverts, numVerts, mloops, mpolys, numLoops, numPolys, pnors, + BKE_mesh_calc_normals_poly(mverts, NULL, numVerts, mloops, mpolys, numLoops, numPolys, pnors, (dm->dirty & DM_DIRTY_NORMALS) ? false : true); dm->dirty &= ~DM_DIRTY_NORMALS; diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 53b6f4a1019..28aaec84859 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -291,7 +291,7 @@ static void data_transfer_dtdata_type_preprocess( poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst); CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); } - BKE_mesh_calc_normals_poly(verts_dst, num_verts_dst, loops_dst, polys_dst, + BKE_mesh_calc_normals_poly(verts_dst, NULL, num_verts_dst, loops_dst, polys_dst, num_loops_dst, num_polys_dst, poly_nors_dst, true); } /* Cache loop nors into a temp CDLayer. */ diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 36ba43f1e8a..362f41335d2 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -58,6 +58,7 @@ #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_mesh.h" #include "BKE_editmesh.h" #include "BKE_scene.h" @@ -1799,6 +1800,66 @@ void BKE_keyblock_convert_to_mesh(KeyBlock *kb, Mesh *me) } } +/** + * Computes normals (vertices, polygons and/or loops ones) of given mesh for given shape key. + * + * \param kb the KeyBlock to use to compute normals. + * \param mesh the Mesh to apply keyblock to. + * \param r_vertnors if non-NULL, an array of vectors, same length as number of vertices. + * \param r_polynors if non-NULL, an array of vectors, same length as number of polygons. + * \param r_loopnors if non-NULL, an array of vectors, same length as number of loops. + */ +void BKE_keyblock_mesh_calc_normals( + struct KeyBlock *kb, struct Mesh *mesh, + float (*r_vertnors)[3], float (*r_polynors)[3], float (*r_loopnors)[3]) +{ + /* We use a temp, shallow copy of mesh to work. */ + Mesh me; + bool free_polynors = false; + + if (r_vertnors == NULL && r_polynors == NULL && r_loopnors == NULL) { + return; + } + + me = *mesh; + me.mvert = MEM_dupallocN(mesh->mvert); + CustomData_reset(&me.vdata); + CustomData_reset(&me.edata); + CustomData_reset(&me.pdata); + CustomData_reset(&me.ldata); + CustomData_reset(&me.fdata); + + BKE_keyblock_convert_to_mesh(kb, &me); + + if (r_polynors == NULL && r_loopnors != NULL) { + r_polynors = MEM_mallocN(sizeof(float[3]) * me.totpoly, __func__); + free_polynors = true; + } + BKE_mesh_calc_normals_poly( + me.mvert, r_vertnors, me.totvert, me.mloop, me.mpoly, me.totloop, me.totpoly, r_polynors, false); + + if (r_loopnors) { + short (*clnors)[2] = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); /* May be NULL. */ + + BKE_mesh_normals_loop_split( + me.mvert, me.totvert, me.medge, me.totedge, + me.mloop, r_loopnors, me.totloop, me.mpoly, r_polynors, me.totpoly, + (me.flag & ME_AUTOSMOOTH) != 0, me.smoothresh, NULL, clnors, NULL); + } + + CustomData_free(&me.vdata, me.totvert); + CustomData_free(&me.edata, me.totedge); + CustomData_free(&me.pdata, me.totpoly); + CustomData_free(&me.ldata, me.totloop); + CustomData_free(&me.fdata, me.totface); + MEM_freeN(me.mvert); + + if (free_polynors) { + MEM_freeN(r_polynors); + } +} + + /************************* raw coords ************************/ void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) { diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 8c89a724975..b948ed56c56 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2199,8 +2199,9 @@ void BKE_mesh_calc_normals_split(Mesh *mesh) } 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); + BKE_mesh_calc_normals_poly( + mesh->mvert, NULL, mesh->totvert, + mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, polynors, false); free_polynors = true; } diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 2fc535061ac..a65ac5151a8 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -133,7 +133,7 @@ void BKE_mesh_calc_normals_mapping_ex( if (only_face_normals == false) { /* vertex normals are optional, they require some extra calculations, * so make them optional */ - BKE_mesh_calc_normals_poly(mverts, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false); + BKE_mesh_calc_normals_poly(mverts, NULL, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false); } else { /* only calc poly normals */ @@ -222,18 +222,20 @@ static void mesh_calc_normals_poly_accum( } void BKE_mesh_calc_normals_poly( - MVert *mverts, int numVerts, + MVert *mverts, float (*r_vertnors)[3], int numVerts, const MLoop *mloop, const MPoly *mpolys, int UNUSED(numLoops), int numPolys, float (*r_polynors)[3], const bool only_face_normals) { float (*pnors)[3] = r_polynors; - float (*tnorms)[3]; + float (*vnors)[3] = r_vertnors; + bool free_vnors = false; int i; const MPoly *mp; if (only_face_normals) { BLI_assert((pnors != NULL) || (numPolys == 0)); + BLI_assert(r_vertnors == NULL); #pragma omp parallel for if (numPolys > BKE_MESH_OMP_LIMIT) for (i = 0; i < numPolys; i++) { @@ -243,25 +245,30 @@ void BKE_mesh_calc_normals_poly( } /* first go through and calculate normals for all the polys */ - tnorms = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, __func__); + if (vnors == NULL) { + vnors = MEM_callocN(sizeof(*vnors) * (size_t)numVerts, __func__); + free_vnors = true; + } + else { + memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts); + } + mp = mpolys; if (pnors) { - mp = mpolys; for (i = 0; i < numPolys; i++, mp++) { - mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors[i], tnorms); + mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors[i], vnors); } } else { float tpnor[3]; /* temp poly normal */ - mp = mpolys; for (i = 0; i < numPolys; i++, mp++) { - mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, tpnor, tnorms); + mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, tpnor, vnors); } } for (i = 0; i < numVerts; i++) { MVert *mv = &mverts[i]; - float *no = tnorms[i]; + float *no = vnors[i]; if (UNLIKELY(normalize_v3(no) == 0.0f)) { /* following Mesh convention; we use vertex coordinate itself for normal in this case */ @@ -271,7 +278,9 @@ void BKE_mesh_calc_normals_poly( normal_float_to_short_v3(mv->no, no); } - MEM_freeN(tnorms); + if (free_vnors) { + MEM_freeN(vnors); + } } void BKE_mesh_calc_normals(Mesh *mesh) @@ -279,7 +288,7 @@ void BKE_mesh_calc_normals(Mesh *mesh) #ifdef DEBUG_TIME TIMEIT_START(BKE_mesh_calc_normals); #endif - BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, + BKE_mesh_calc_normals_poly(mesh->mvert, NULL, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, false); #ifdef DEBUG_TIME diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index c3b88b84b8b..0235b7e0380 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -1234,7 +1234,7 @@ void BKE_mesh_remap_calc_loops_from_dm( CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); } if (dirty_nors_dst) { - BKE_mesh_calc_normals_poly(verts_dst, numverts_dst, loops_dst, polys_dst, + BKE_mesh_calc_normals_poly(verts_dst, NULL, numverts_dst, loops_dst, polys_dst, numloops_dst, numpolys_dst, poly_nors_dst, true); } } @@ -1999,7 +1999,7 @@ void BKE_mesh_remap_calc_polys_from_dm( CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); } if (dirty_nors_dst) { - BKE_mesh_calc_normals_poly(verts_dst, numverts_dst, loops_dst, polys_dst, numloops_dst, numpolys_dst, + BKE_mesh_calc_normals_poly(verts_dst, NULL, numverts_dst, loops_dst, polys_dst, numloops_dst, numpolys_dst, poly_nors_dst, true); } } diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index c25566b6e33..b567e0f00f3 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -156,6 +156,112 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value) #undef SHAPEKEY_SLIDER_TOL +/* ***** Normals accessors for shapekeys. ***** */ +/* Note: with this we may recompute several times the same data, should we want to access verts, then polys, then loops + * normals... However, such case looks rather unlikely - and not worth adding some kind of caching in KeyBlocks. + */ + +static Mesh *rna_KeyBlock_normals_get_mesh(PointerRNA *ptr, ID *id) +{ + Key *key = rna_ShapeKey_find_key((id == NULL && ptr != NULL) ? ptr->id.data : id); + id = key ? key->from : NULL; + + if (id != NULL) { + switch (GS(id->name)) { + case ID_ME: + return (Mesh *)id; + case ID_OB: + { + Object *ob = (Object *)id; + if (ob->type == OB_MESH) { + return ob->data; + } + } + } + } + + return NULL; +} + +static int rna_KeyBlock_normals_vert_len(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +{ + Mesh *me = rna_KeyBlock_normals_get_mesh(ptr, NULL); + + length[0] = me ? me->totvert : 0; + length[1] = 3; + + return (length[0] * length[1]); +} + +static void rna_KeyBlock_normals_vert_calc(ID *id, KeyBlock *data, int *normals_len, float **normals) +{ + Mesh *me = rna_KeyBlock_normals_get_mesh(NULL, id); + + *normals_len = (me ? me->totvert : 0) * 3; + + if (ELEM(NULL, me, data) || (me->totvert == 0)) { + *normals = NULL; + return; + } + + *normals = MEM_mallocN(sizeof(**normals) * (size_t)(*normals_len), __func__); + + BKE_keyblock_mesh_calc_normals(data, me, (float (*)[3])(*normals), NULL, NULL); +} + +static int rna_KeyBlock_normals_poly_len(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +{ + Mesh *me = rna_KeyBlock_normals_get_mesh(ptr, NULL); + + length[0] = me ? me->totpoly : 0; + length[1] = 3; + + return (length[0] * length[1]); +} + +static void rna_KeyBlock_normals_poly_calc(ID *id, KeyBlock *data, int *normals_len, float **normals) +{ + Mesh *me = rna_KeyBlock_normals_get_mesh(NULL, id); + + *normals_len = (me ? me->totpoly : 0) * 3; + + if (ELEM(NULL, me, data) || (me->totpoly == 0)) { + *normals = NULL; + return; + } + + *normals = MEM_mallocN(sizeof(**normals) * (size_t)(*normals_len), __func__); + + BKE_keyblock_mesh_calc_normals(data, me, NULL, (float (*)[3])(*normals), NULL); +} + +static int rna_KeyBlock_normals_loop_len(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +{ + Mesh *me = rna_KeyBlock_normals_get_mesh(ptr, NULL); + + length[0] = me ? me->totloop : 0; + length[1] = 3; + + return (length[0] * length[1]); +} + +static void rna_KeyBlock_normals_loop_calc(ID *id, KeyBlock *data, int *normals_len, float **normals) +{ + Mesh *me = rna_KeyBlock_normals_get_mesh(NULL, id); + + *normals_len = (me ? me->totloop : 0) * 3; + + if (ELEM(NULL, me, data) || (me->totloop == 0)) { + *normals = NULL; + return; + } + + *normals = MEM_mallocN(sizeof(**normals) * (size_t)(*normals_len), __func__); + + BKE_keyblock_mesh_calc_normals(data, me, NULL, NULL, (float (*)[3])(*normals)); +} + + PointerRNA rna_object_shapekey_index_get(ID *id, int value) { Key *key = rna_ShapeKey_find_key(id); @@ -558,7 +664,8 @@ static void rna_def_keydata(BlenderRNA *brna) static void rna_def_keyblock(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop; + PropertyRNA *prop, *parm; + FunctionRNA *func; srna = RNA_def_struct(brna, "ShapeKey", NULL); RNA_def_struct_ui_text(srna, "Shape Key", "Shape key in a shape keys datablock"); @@ -633,6 +740,36 @@ static void rna_def_keyblock(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Data", ""); RNA_def_property_collection_funcs(prop, "rna_ShapeKey_data_begin", NULL, NULL, "rna_ShapeKey_data_get", "rna_ShapeKey_data_length", NULL, NULL, NULL); + + /* XXX multi-dim dynamic arrays are very badly supported by (py)rna currently, those are defined for the day + * it works better, for now user will get a 1D tuple... + **/ + func = RNA_def_function(srna, "normals_vertex_get", "rna_KeyBlock_normals_vert_calc"); + RNA_def_function_ui_description(func, "Compute local space vertices' normals for this shape key"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_property(func, "normals", PROP_FLOAT, /* PROP_DIRECTION */ PROP_NONE); + RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_OUTPUT); + RNA_def_property_multi_array(parm, 2, NULL); + RNA_def_property_range(parm, -1.0f, 1.0f); + RNA_def_property_dynamic_array_funcs(parm, "rna_KeyBlock_normals_vert_len"); + + func = RNA_def_function(srna, "normals_polygon_get", "rna_KeyBlock_normals_poly_calc"); + RNA_def_function_ui_description(func, "Compute local space faces' normals for this shape key"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_property(func, "normals", PROP_FLOAT, /* PROP_DIRECTION */ PROP_NONE); + RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_OUTPUT); + RNA_def_property_multi_array(parm, 2, NULL); + RNA_def_property_range(parm, -1.0f, 1.0f); + RNA_def_property_dynamic_array_funcs(parm, "rna_KeyBlock_normals_poly_len"); + + func = RNA_def_function(srna, "normals_split_get", "rna_KeyBlock_normals_loop_calc"); + RNA_def_function_ui_description(func, "Compute local space face corners' normals for this shape key"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_property(func, "normals", PROP_FLOAT, /* PROP_DIRECTION */ PROP_NONE); + RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_OUTPUT); + RNA_def_property_multi_array(parm, 2, NULL); + RNA_def_property_range(parm, -1.0f, 1.0f); + RNA_def_property_dynamic_array_funcs(parm, "rna_KeyBlock_normals_loop_len"); } static void rna_def_key(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 632b07c19ce..1459157112e 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -136,8 +136,9 @@ static void rna_Mesh_normals_split_custom_do(Mesh *mesh, float (*custom_loopnors } 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); + BKE_mesh_calc_normals_poly( + mesh->mvert, NULL, mesh->totvert, + mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, polynors, false); free_polynors = true; } diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 2eccefcc8df..a24ed4d6614 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -388,7 +388,7 @@ static DerivedMesh *normalEditModifier_do(NormalEditModifierData *smd, Object *o polynors = dm->getPolyDataArray(dm, CD_NORMAL); if (!polynors) { polynors = MEM_mallocN(sizeof(*polynors) * num_polys, __func__); - BKE_mesh_calc_normals_poly(mvert, num_verts, mloop, mpoly, num_loops, num_polys, polynors, false); + BKE_mesh_calc_normals_poly(mvert, NULL, num_verts, mloop, mpoly, num_loops, num_polys, polynors, false); free_polynors = true; } diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index ca2dcfec3a3..2695f6675c9 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -272,7 +272,7 @@ static DerivedMesh *applyModifier( /* calculate only face normals */ face_nors = MEM_mallocN(sizeof(*face_nors) * (size_t)numFaces, __func__); BKE_mesh_calc_normals_poly( - orig_mvert, (int)numVerts, + orig_mvert, NULL, (int)numVerts, orig_mloop, orig_mpoly, (int)numLoops, (int)numFaces, face_nors, true); -- cgit v1.2.3