diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2014-04-13 14:18:51 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2014-04-13 14:19:00 +0400 |
commit | 18e4224142261cd8a1086c5872efb406b82f8330 (patch) | |
tree | a1a9f7680ab45158ec2c2755f76a966532cad8b8 /source/blender/blenkernel | |
parent | a872d0b414f406a7d53ce77f7b43e7a831a68fa7 (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.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_blender.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_cdderivedmesh.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 71 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 49 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 18 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/editderivedmesh.c | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_evaluate.c | 39 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 1 |
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; |