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
This commit is contained in:
parent
ee688e24a7
commit
cdd727b7ce
Notes:
blender-bot
2023-02-14 19:53:10 +01:00
Referenced by issue blender/blender-addons#46019, Blender fbx does not export normals correctly for blendshapes
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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])
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue