Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2014-04-13 14:18:51 +0400
committerBastien Montagne <montagne29@wanadoo.fr>2014-04-13 14:19:00 +0400
commit18e4224142261cd8a1086c5872efb406b82f8330 (patch)
treea1a9f7680ab45158ec2c2755f76a966532cad8b8 /source/blender/blenkernel
parenta872d0b414f406a7d53ce77f7b43e7a831a68fa7 (diff)
Split Normals I (1/5): basis for split normals (nearly nothing user-visible here):
* Add a new calcLoopNormals function to DerivedMesh struct, and implement it for CDDM and CCGDM (subsurf). EditDerivedBMesh (edit mode DM) only gets a dummy one in this commit. * Add a tessellated version of CD_LOOPNORMAL layer (CD_TESSLOOPNORMAL), with relevant code to handle it (tessellation, rna access, etc.). * Change auto_smooth options of Mesh (angle now in radian internaly, and toggle is now used to enable/disable split normals in DM creation process). Note BI render code is not touched here, hence its behavior regarding this option is now incoherent, will be addressed in a separate commit. Reviewers: campbellbarton CC: brecht Differential Revision: https://developer.blender.org/D365
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h3
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h2
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c71
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c49
-rw-r--r--source/blender/blenkernel/intern/customdata.c18
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c6
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c39
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c1
10 files changed, 167 insertions, 26 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 3afd7d851cb..5206f8bf299 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -193,6 +193,9 @@ struct DerivedMesh {
/** Calculate vert and face normals */
void (*calcNormals)(DerivedMesh *dm);
+ /** Calculate loop (split) normals */
+ void (*calcLoopNormals)(DerivedMesh *dm, const float split_angle);
+
/** Recalculates mesh tessellation */
void (*recalcTessellation)(DerivedMesh *dm);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 3eb2fabdd56..9a67284304c 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 270
-#define BLENDER_SUBVERSION 1
+#define BLENDER_SUBVERSION 2
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index 4e6d69503c0..dffc2b665c2 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -100,6 +100,8 @@ void CDDM_calc_normals_mapping(struct DerivedMesh *dm);
void CDDM_calc_normals(struct DerivedMesh *dm);
void CDDM_calc_normals_tessface(struct DerivedMesh *dm);
+void CDDM_calc_loop_normals(struct DerivedMesh *dm, const float split_angle);
+
/* calculates edges for a CDDerivedMesh (from face data)
* this completely replaces the current edge data in the DerivedMesh
* builds edges from the tessellated face data.
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 9c57b7c9a71..d6c3734fa2d 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -215,7 +215,7 @@ void BKE_mesh_loops_to_mface_corners(
struct CustomData *pdata, unsigned int lindex[4], int findex,
const int polyindex, const int mf_len,
const int numTex, const int numCol,
- const bool hasPCol, const bool hasOrigSpace);
+ const bool hasPCol, const bool hasOrigSpace, const bool hasLNor);
void BKE_mesh_loops_to_tessdata(
struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MFace *mface,
int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 84b54ff2b84..0c4e71448cd 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -399,6 +399,11 @@ void DM_ensure_normals(DerivedMesh *dm)
BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
}
+static void DM_calc_loop_normals(DerivedMesh *dm, float split_angle)
+{
+ dm->calcLoopNormals(dm, split_angle);
+}
+
/* note: until all modifiers can take MPoly's as input,
* use this at the start of modifiers */
void DM_ensure_tessface(DerivedMesh *dm)
@@ -453,7 +458,8 @@ void DM_update_tessface_data(DerivedMesh *dm)
if (CustomData_has_layer(fdata, CD_MTFACE) ||
CustomData_has_layer(fdata, CD_MCOL) ||
CustomData_has_layer(fdata, CD_PREVIEW_MCOL) ||
- CustomData_has_layer(fdata, CD_ORIGSPACE))
+ CustomData_has_layer(fdata, CD_ORIGSPACE) ||
+ CustomData_has_layer(fdata, CD_TESSLOOPNORMAL))
{
loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
@@ -1471,6 +1477,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* XXX Same as above... For now, only weights preview in WPaint mode. */
const bool do_mod_wmcol = do_init_wmcol;
+ const bool do_loop_normals = (me->flag & ME_AUTOSMOOTH);
+ const float loop_normals_split_angle = me->smoothresh;
+
VirtualModifierData virtualModifierData;
ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0;
@@ -1865,7 +1874,21 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
add_orco_dm(ob, NULL, *deform_r, NULL, CD_ORCO);
}
- {
+ if (do_loop_normals) {
+ /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */
+ DM_calc_loop_normals(finaldm, loop_normals_split_angle);
+
+ if (finaldm->getNumTessFaces(finaldm) == 0) {
+ finaldm->recalcTessellation(finaldm);
+ }
+ /* Even if tessellation is not needed, we have for sure modified loop normals layer! */
+ else {
+ /* A tessellation already exists, it should always have a CD_ORIGINDEX. */
+ BLI_assert(CustomData_has_layer(&finaldm->faceData, CD_ORIGINDEX));
+ DM_update_tessface_data(finaldm);
+ }
+ }
+ else {
/* calculating normals can re-calculate tessfaces in some cases */
#if 0
int num_tessface = finaldm->getNumTessFaces(finaldm);
@@ -1982,7 +2005,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
ModifierData *md, *previewmd = NULL;
float (*deformedVerts)[3] = NULL;
CustomDataMask mask, previewmask = 0, append_mask = 0;
- DerivedMesh *dm, *orcodm = NULL;
+ DerivedMesh *dm = NULL, *orcodm = NULL;
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
CDMaskLink *datamasks, *curr;
int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
@@ -1998,13 +2021,15 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
const bool do_mod_wmcol = do_init_wmcol;
VirtualModifierData virtualModifierData;
+ const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH);
+ const float loop_normals_split_angle = ((Mesh *)(ob->data))->smoothresh;
+
modifiers_clearErrors(ob);
if (cage_r && cageIndex == -1) {
*cage_r = getEditDerivedBMesh(em, ob, NULL);
}
- dm = NULL;
md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* copied from mesh_calc_modifiers */
@@ -2212,6 +2237,14 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
DM_update_statvis_color(scene, ob, *final_r);
}
+ if (do_loop_normals) {
+ /* Compute loop normals */
+ DM_calc_loop_normals(*final_r, loop_normals_split_angle);
+ if (cage_r && *cage_r && (*cage_r != *final_r)) {
+ DM_calc_loop_normals(*cage_r, loop_normals_split_angle);
+ }
+ }
+
/* --- */
/* BMESH_ONLY, ensure tessface's used for drawing,
* but don't recalculate if the last modifier in the stack gives us tessfaces
@@ -2229,8 +2262,10 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
}
/* --- */
- /* same as mesh_calc_modifiers */
- dm_ensure_display_normals(*final_r);
+ /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
+ if (!do_loop_normals) {
+ dm_ensure_display_normals(*final_r);
+ }
/* add an orco layer if needed */
if (dataMask & CD_MASK_ORCO)
@@ -2542,7 +2577,8 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
/* ******************* GLSL ******************** */
typedef struct {
- float *precomputedFaceNormals;
+ float (*precomputedFaceNormals)[3];
+ short (*precomputedLoopNormals)[4][3];
MTFace *mtface; /* texture coordinates */
MFace *mface; /* indices */
MVert *mvert; /* vertices & normals */
@@ -2594,11 +2630,14 @@ static void GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const i
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ const bool smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH) != 0;
- const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH);
- if (!smoothnormal) { // flat
+ if (pMesh->precomputedLoopNormals) {
+ normal_short_to_float_v3(r_no, pMesh->precomputedLoopNormals[face_num][vert_index]);
+ }
+ else if (!smoothnormal) { // flat
if (pMesh->precomputedFaceNormals) {
- copy_v3_v3(r_no, &pMesh->precomputedFaceNormals[3 * face_num]);
+ copy_v3_v3(r_no, pMesh->precomputedFaceNormals[face_num]);
}
else {
MFace *mf = &pMesh->mface[face_num];
@@ -2638,12 +2677,17 @@ void DM_add_tangent_layer(DerivedMesh *dm)
MFace *mface;
float (*orco)[3] = NULL, (*tangent)[4];
int /* totvert, */ totface;
- float *nors;
+ float (*fnors)[3];
+ short (*tlnors)[4][3];
if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
return;
- nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ fnors = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
+ * have to check this is valid...
+ */
+ tlnors = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
/* check we have all the needed layers */
/* totvert = dm->getNumVerts(dm); */ /* UNUSED */
@@ -2669,7 +2713,8 @@ void DM_add_tangent_layer(DerivedMesh *dm)
SMikkTSpaceContext sContext = {NULL};
SMikkTSpaceInterface sInterface = {NULL};
- mesh2tangent.precomputedFaceNormals = nors;
+ mesh2tangent.precomputedFaceNormals = fnors;
+ mesh2tangent.precomputedLoopNormals = tlnors;
mesh2tangent.mtface = mtface;
mesh2tangent.mface = mface;
mesh2tangent.mvert = mvert;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 0c58b7e66e7..9af6220e4b2 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1738,6 +1738,7 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
dm->calcNormals = CDDM_calc_normals;
+ dm->calcLoopNormals = CDDM_calc_loop_normals;
dm->recalcTessellation = CDDM_recalc_tessellation;
dm->getVertCos = cdDM_getVertCos;
@@ -2289,8 +2290,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData);
}
-
- face_nors = MEM_mallocN(sizeof(float) * 3 * dm->numTessFaceData, "face_nors");
+ face_nors = MEM_mallocN(sizeof(*face_nors) * dm->numTessFaceData, "face_nors");
/* calculate face normals */
BKE_mesh_calc_normals_mapping_ex(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
@@ -2298,8 +2298,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors,
only_face_normals);
- CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN,
- face_nors, dm->numTessFaceData);
+ CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numTessFaceData);
cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
}
@@ -2353,6 +2352,48 @@ void CDDM_calc_normals(DerivedMesh *dm)
#endif
+void CDDM_calc_loop_normals(DerivedMesh *dm, const float split_angle)
+{
+ MVert *mverts = dm->getVertArray(dm);
+ MEdge *medges = dm->getEdgeArray(dm);
+ MLoop *mloops = dm->getLoopArray(dm);
+ MPoly *mpolys = dm->getPolyArray(dm);
+
+ CustomData *ldata, *pdata;
+
+ float (*lnors)[3];
+ float (*pnors)[3];
+
+ const int numVerts = dm->getNumVerts(dm);
+ const int numEdges = dm->getNumEdges(dm);
+ const int numLoops = dm->getNumLoops(dm);
+ const int numPolys = dm->getNumPolys(dm);
+
+ ldata = dm->getLoopDataLayout(dm);
+ if (CustomData_has_layer(ldata, CD_NORMAL)) {
+ lnors = CustomData_get_layer(ldata, CD_NORMAL);
+ }
+ else {
+ lnors = CustomData_add_layer(ldata, CD_NORMAL, CD_CALLOC, NULL, numLoops);
+ }
+
+ /* Compute poly (always needed) and vert normals. */
+ /* Note we can't use DM_ensure_normals, since it won't keep computed poly nors... */
+ pdata = dm->getPolyDataLayout(dm);
+ pnors = CustomData_get_layer(pdata, CD_NORMAL);
+ 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,
+ (dm->dirty & DM_DIRTY_NORMALS) ? false : true);
+
+ dm->dirty &= ~DM_DIRTY_NORMALS;
+
+ BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
+ mpolys, pnors, numPolys, split_angle);
+}
+
+
void CDDM_calc_normals_tessface(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 41eb2f5982e..61261959ea8 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -1170,6 +1170,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(FreestyleFace), "FreestyleFace", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 39: CD_MLOOPTANGENT */
{sizeof(float[4]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* 40: CD_TESSLOOPNORMAL */
+ {sizeof(short[4][3]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
};
/* note, numbers are from trunk and need updating for bmesh */
@@ -1185,7 +1187,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight",
/* 30-34 */ "CDSubSurfCrease", "CDOrigSpaceLoop", "CDPreviewLoopCol", "CDBMElemPyPtr", "CDPaintMask",
/* 35-36 */ "CDGridPaintMask", "CDMVertSkin",
- /* 37-38 */ "CDFreestyleEdge", "CDFreestyleFace", "CDMLoopTangent",
+ /* 37-40 */ "CDFreestyleEdge", "CDFreestyleFace", "CDMLoopTangent", "CDTessLoopNormal",
};
@@ -1217,9 +1219,9 @@ const CustomDataMask CD_MASK_BMESH =
CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS |
CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
-const CustomDataMask CD_MASK_FACECORNERS =
+const CustomDataMask CD_MASK_FACECORNERS = /* XXX Not used anywhere! */
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
- CD_MASK_MLOOPCOL;
+ CD_MASK_MLOOPCOL | CD_MASK_NORMAL | CD_MASK_MLOOPTANGENT;
const CustomDataMask CD_MASK_EVERYTHING =
CD_MASK_MVERT | CD_MASK_MSTICKY /* DEPRECATED */ | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT |
@@ -1229,7 +1231,9 @@ const CustomDataMask CD_MASK_EVERYTHING =
CD_MASK_MPOLY | CD_MASK_MLOOP | CD_MASK_SHAPE_KEYINDEX | CD_MASK_SHAPEKEY | CD_MASK_BWEIGHT | CD_MASK_CREASE |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_BM_ELEM_PYPTR |
/* BMESH ONLY END */
- CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
+ CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN |
+ CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
+ CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL;
static const LayerTypeInfo *layerType_getInfo(int type)
{
@@ -2283,6 +2287,9 @@ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l
else if (fdata->layers[i].type == CD_MDISPS) {
CustomData_add_layer_named(ldata, CD_MDISPS, CD_CALLOC, NULL, totloop, fdata->layers[i].name);
}
+ else if (fdata->layers[i].type == CD_TESSLOOPNORMAL) {
+ CustomData_add_layer_named(ldata, CD_NORMAL, CD_CALLOC, NULL, totloop, fdata->layers[i].name);
+ }
}
}
@@ -2304,6 +2311,9 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) {
CustomData_add_layer_named(fdata, CD_ORIGSPACE, CD_CALLOC, NULL, total, ldata->layers[i].name);
}
+ else if (ldata->layers[i].type == CD_NORMAL) {
+ CustomData_add_layer_named(fdata, CD_TESSLOOPNORMAL, CD_CALLOC, NULL, total, ldata->layers[i].name);
+ }
}
CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index b7c5c605254..152540041f7 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -171,6 +171,11 @@ static void emDM_calcNormals(DerivedMesh *dm)
dm->dirty &= ~DM_DIRTY_NORMALS;
}
+static void emDM_calcLoopNormals(DerivedMesh *dm, const float split_angle)
+{
+ /* Do nothing for now! */
+}
+
static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
{
/* do nothing */
@@ -1654,6 +1659,7 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
bmdm->dm.calcNormals = emDM_calcNormals;
+ bmdm->dm.calcLoopNormals = emDM_calcLoopNormals;
bmdm->dm.recalcTessellation = emDM_recalcTessellation;
bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 5d10c12b8e0..edd0a8540e3 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -574,6 +574,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
#undef IS_EDGE_SHARP
}
+
/** \} */
@@ -1103,7 +1104,8 @@ void BKE_mesh_loops_to_mface_corners(
const int numTex, /* CustomData_number_of_layers(pdata, CD_MTEXPOLY) */
const int numCol, /* CustomData_number_of_layers(ldata, CD_MLOOPCOL) */
const bool hasPCol, /* CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL) */
- const bool hasOrigSpace /* CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP) */
+ const bool hasOrigSpace, /* CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP) */
+ const bool hasLNor /* CustomData_has_layer(ldata, CD_NORMAL) */
)
{
MTFace *texface;
@@ -1152,6 +1154,14 @@ void BKE_mesh_loops_to_mface_corners(
copy_v2_v2(of->uv[j], lof->uv);
}
}
+
+ if (hasLNor) {
+ short (*tlnors)[3] = CustomData_get(fdata, findex, CD_TESSLOOPNORMAL);
+
+ for (j = 0; j < mf_len; j++) {
+ normal_float_to_short_v3(tlnors[j], CustomData_get(ldata, (int)lindex[j], CD_NORMAL));
+ }
+ }
}
/**
@@ -1172,6 +1182,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
+ const bool hasLoopNormal = CustomData_has_layer(ldata, CD_NORMAL);
int findex, i, j;
int *pidx;
unsigned int (*lidx)[4];
@@ -1225,6 +1236,17 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
}
}
}
+
+ if (hasLoopNormal) {
+ short (*fnors)[4][3] = CustomData_get_layer(fdata, CD_TESSLOOPNORMAL);
+ float (*lnors)[3] = CustomData_get_layer(ldata, CD_NORMAL);
+
+ for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, fnors++) {
+ for (j = (*lidx)[3] ? 4 : 3; j--;) {
+ normal_float_to_short_v3((*fnors)[j], lnors[(*lidx)[j]]);
+ }
+ }
+ }
}
/**
@@ -1516,6 +1538,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
+ const bool hasLNor = CustomData_has_layer(ldata, CD_NORMAL);
/* over-alloc, ngons will be skipped */
mface = MEM_mallocN(sizeof(*mface) * (size_t)totpoly, __func__);
@@ -1575,7 +1598,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
lindex, k, i, 3,
- numTex, numCol, hasPCol, hasOrigSpace);
+ numTex, numCol, hasPCol, hasOrigSpace, hasLNor);
test_index_face(mf, fdata, k, 3);
}
else {
@@ -1595,7 +1618,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
lindex, k, i, 4,
- numTex, numCol, hasPCol, hasOrigSpace);
+ numTex, numCol, hasPCol, hasOrigSpace, hasLNor);
test_index_face(mf, fdata, k, 4);
}
@@ -1651,6 +1674,16 @@ static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata,
}
}
+ if (CustomData_has_layer(fdata, CD_TESSLOOPNORMAL)) {
+ float (*lnors)[3] = CustomData_get(ldata, loopstart, CD_NORMAL);
+ short (*tlnors)[3] = CustomData_get(fdata, findex, CD_TESSLOOPNORMAL);
+ const int max = mf->v4 ? 4 : 3;
+
+ for (i = 0; i < max; i++, lnors++, tlnors++) {
+ normal_short_to_float_v3(*lnors, *tlnors);
+ }
+ }
+
if (CustomData_has_layer(fdata, CD_MDISPS)) {
MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS);
MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 87de748eace..0b2d772978d 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -3243,6 +3243,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.getPBVH = ccgDM_getPBVH;
ccgdm->dm.calcNormals = ccgDM_calcNormals;
+ ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
ccgdm->dm.getVertCos = ccgdm_getVertCos;