diff options
Diffstat (limited to 'source/blender/blenkernel/intern/DerivedMesh.c')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 617 |
1 files changed, 487 insertions, 130 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 769c109cc31..abbfa4b7ff1 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -84,8 +84,10 @@ #ifdef USE_MODIFIER_VALIDATE # define ASSERT_IS_VALID_DM(dm) (BLI_assert((dm == NULL) || (DM_is_valid(dm) == true))) +# define ASSERT_IS_VALID_MESH(mesh) (BLI_assert((mesh == NULL) || (BKE_mesh_is_valid(mesh) == true))) #else # define ASSERT_IS_VALID_DM(dm) +# define ASSERT_IS_VALID_MESH(mesh) #endif @@ -95,6 +97,8 @@ static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob); static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid); +static void mesh_init_origspace(Mesh *mesh); + /* -------------------------------------------------------------------- */ @@ -745,6 +749,7 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask, bool CustomData_copy(&dm->loopData, &tmp.ldata, mask, alloctype, totloop); CustomData_copy(&dm->polyData, &tmp.pdata, mask, alloctype, totpoly); tmp.cd_flag = dm->cd_flag; + tmp.runtime.deformed_only = dm->deformedOnly; if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) { KeyBlock *kb; @@ -891,6 +896,20 @@ void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask) #endif } +static void mesh_set_only_copy(Mesh *mesh, CustomDataMask mask) +{ + CustomData_set_only_copy(&mesh->vdata, mask); + CustomData_set_only_copy(&mesh->edata, mask); + CustomData_set_only_copy(&mesh->fdata, mask); + /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with + * weight paint mode when there are modifiers applied, needs further investigation, + * see replies to r50969, Campbell */ +#if 0 + CustomData_set_only_copy(&mesh->ldata, mask); + CustomData_set_only_copy(&mesh->pdata, mask); +#endif +} + void DM_add_vert_layer(DerivedMesh *dm, int type, int alloctype, void *layer) { CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData); @@ -1265,6 +1284,30 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em, int lay return dm; } +static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer) +{ + Mesh *mesh; + float (*orco)[3]; + int free; + + if (em) { + mesh = BKE_bmesh_to_mesh_nomain(em->bm, &(struct BMeshToMeshParams){0}); + } + else { + BKE_id_copy_ex(NULL, &me->id, (ID**)&mesh, + LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_DEG_TAG, false); + } + + orco = get_orco_coords_dm(ob, em, layer, &free); + + if (orco) { + BKE_mesh_apply_vert_coords(mesh, orco); + if (free) MEM_freeN(orco); + } + + return mesh; +} + static void add_orco_dm( Object *ob, BMEditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm, int layer) @@ -1303,6 +1346,48 @@ static void add_orco_dm( } } +static void add_orco_mesh( + Object *ob, BMEditMesh *em, Mesh *mesh, + Mesh *orco_mesh, int layer) +{ + float (*orco)[3], (*layerorco)[3]; + int totvert, free; + + totvert = mesh->totvert; + + if (orco_mesh) { + free = 1; + + if (orco_mesh->totvert == totvert) { + orco = BKE_mesh_vertexCos_get(orco_mesh, NULL); + } + else { + orco = BKE_mesh_vertexCos_get(mesh, NULL); + } + } + else { + /* TODO(sybren): totvert should potentially change here, as ob->data + * or em may have a different number of vertices than dm. */ + orco = get_orco_coords_dm(ob, em, layer, &free); + } + + if (orco) { + if (layer == CD_ORCO) { + BKE_mesh_orco_verts_transform(ob->data, orco, totvert, 0); + } + + if (!(layerorco = CustomData_get_layer(&mesh->vdata, layer))) { + CustomData_add_layer(&mesh->vdata, layer, CD_CALLOC, NULL, mesh->totvert); + BKE_mesh_update_customdata_pointers(mesh, false); + + layerorco = CustomData_get_layer(&mesh->vdata, layer); + } + + memcpy(layerorco, orco, sizeof(float) * 3 * totvert); + if (free) MEM_freeN(orco); + } +} + /* weight paint colors */ /* Something of a hack, at the moment deal with weightpaint @@ -1528,6 +1613,81 @@ static void calc_weightpaint_vert_array( } } +static void calc_weightpaint_vert_array_mesh( + Object *ob, Mesh *mesh, int const draw_flag, DMWeightColorInfo *dm_wcinfo, + unsigned char (*r_wtcol_v)[4]) +{ + BMEditMesh *em = BKE_editmesh_from_object(ob); + const int numVerts = mesh->totvert; + + if ((ob->actdef != 0) && + (CustomData_has_layer(em ? &em->bm->vdata : &mesh->vdata, CD_MDEFORMVERT))) + { + unsigned char (*wc)[4] = r_wtcol_v; + unsigned int i; + + /* variables for multipaint */ + const int defbase_tot = BLI_listbase_count(&ob->defbase); + const int defbase_act = ob->actdef - 1; + + int defbase_sel_tot = 0; + bool *defbase_sel = NULL; + + if (draw_flag & CALC_WP_MULTIPAINT) { + defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_sel_tot); + + if (defbase_sel_tot > 1 && (draw_flag & CALC_WP_MIRROR_X)) { + BKE_object_defgroup_mirror_selection(ob, defbase_tot, defbase_sel, defbase_sel, &defbase_sel_tot); + } + } + + /* editmesh won't have deform verts unless modifiers require it, + * avoid having to create an array of deform-verts only for drawing + * by reading from the bmesh directly. */ + if (em) { + BMIter iter; + BMVert *eve; + const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT); + BLI_assert(cd_dvert_offset != -1); + + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + const MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + calc_weightpaint_vert_color( + (unsigned char *)wc, dv, dm_wcinfo, + defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag); + wc++; + } + } + else { + const MDeformVert *dv = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT); + for (i = numVerts; i != 0; i--, wc++, dv++) { + calc_weightpaint_vert_color( + (unsigned char *)wc, dv, dm_wcinfo, + defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag); + } + } + + if (defbase_sel) { + MEM_freeN(defbase_sel); + } + } + else { + unsigned char col[4]; + if ((ob->actdef == 0) && !BLI_listbase_is_empty(&ob->defbase)) { + /* color-code for missing data (full brightness isn't easy on the eye). */ + ARRAY_SET_ITEMS(col, 0xa0, 0, 0xa0, 0xff); + } + else if (draw_flag & (CALC_WP_GROUP_USER_ACTIVE | CALC_WP_GROUP_USER_ALL)) { + copy_v3_v3_char((char *)col, dm_wcinfo->alert_color); + col[3] = 255; + } + else { + weightpaint_color(col, dm_wcinfo, 0.0f); + } + copy_vn_i((int *)r_wtcol_v, numVerts, *((int *)col)); + } +} + /** return an array of vertex weight colors from given weights, caller must free. * * \note that we could save some memory and allocate RGB only but then we'd need to @@ -1620,6 +1780,80 @@ void DM_update_weight_mcol( } } +static void mesh_update_weight_mcol( + Object *ob, Mesh *mesh, int const draw_flag, + float *weights, int num, const int *indices) +{ + BMEditMesh *em = BKE_editmesh_from_object(ob); + unsigned char (*wtcol_v)[4]; + int numVerts = mesh->totvert; + int i; + + if (em) { + BKE_editmesh_color_ensure(em, BM_VERT); + wtcol_v = em->derivedVertColor; + } + else { + wtcol_v = MEM_malloc_arrayN(numVerts, sizeof(*wtcol_v), __func__); + } + + /* Weights are given by caller. */ + if (weights) { + float *w = weights; + /* If indices is not NULL, it means we do not have weights for all vertices, + * so we must create them (and set them to zero)... */ + if (indices) { + w = MEM_calloc_arrayN(numVerts, sizeof(float), "Temp weight array DM_update_weight_mcol"); + i = num; + while (i--) + w[indices[i]] = weights[i]; + } + + /* Convert float weights to colors. */ + calc_colors_from_weights_array(numVerts, w, wtcol_v); + + if (indices) + MEM_freeN(w); + } + else { + /* No weights given, take them from active vgroup(s). */ + calc_weightpaint_vert_array_mesh(ob, mesh, draw_flag, &G_dm_wcinfo, wtcol_v); + } + + if (em) { + /* editmesh draw function checks specifically for this */ + } + else { + const int totpoly = mesh->totpoly; + const int totloop = mesh->totloop; + unsigned char(*wtcol_l)[4] = CustomData_get_layer(&mesh->ldata, CD_PREVIEW_MLOOPCOL); + MLoop *mloop = mesh->mloop, *ml; + MPoly *mp = mesh->mpoly; + int l_index; + int j; + + /* now add to loops, so the data can be passed through the modifier stack + * If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */ + if (!wtcol_l) { + wtcol_l = MEM_malloc_arrayN(totloop, sizeof(*wtcol_l), __func__); + CustomData_add_layer(&mesh->ldata, CD_PREVIEW_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop); + } + + l_index = 0; + for (i = 0; i < totpoly; i++, mp++) { + ml = mloop + mp->loopstart; + + for (j = 0; j < mp->totloop; j++, ml++, l_index++) { + copy_v4_v4_uchar(&wtcol_l[l_index][0], + &wtcol_v[ml->v][0]); + } + } + MEM_freeN(wtcol_v); + + //dm->dirty |= DM_DIRTY_TESS_CDLAYERS; // XXX: Does Mesh need this? + } +} + static void DM_update_statvis_color(const Scene *scene, Object *ob, DerivedMesh *dm) { BMEditMesh *em = BKE_editmesh_from_object(ob); @@ -1742,6 +1976,32 @@ static void dm_ensure_display_normals(DerivedMesh *dm) } } +static void mesh_ensure_display_normals(Mesh *mesh) +{ + /* Note: mesh *may* have a poly CD_NORMAL layer (generated by a modifier needing poly normals e.g.). + * We do not use it here, though. And it should be tagged as temp! + */ + /* BLI_assert((CustomData_has_layer(&mesh->pdata, CD_NORMAL) == false)); */ + + if(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL || !CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { + float (*face_nors)[3] = NULL; + face_nors = MEM_malloc_arrayN(mesh->totpoly, sizeof(*face_nors), "face_nors"); + + /* if normals are dirty we want to calculate vertex normals too */ + bool only_face_normals = !(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL); + + /* calculate face normals */ + BKE_mesh_calc_normals_poly( + mesh->mvert, NULL, mesh->totvert, mesh->mloop, mesh->mpoly, + mesh->totloop, mesh->totpoly, face_nors, + only_face_normals); + + CustomData_add_layer(&mesh->pdata, CD_NORMAL, CD_ASSIGN, face_nors, mesh->totpoly); + + mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; + } +} + static void mesh_calc_modifiers( struct Depsgraph *depsgraph, Scene *scene, Object *ob, float (*inputVertexCos)[3], const bool useRenderParams, int useDeform, @@ -1749,7 +2009,7 @@ static void mesh_calc_modifiers( const int index, const bool useCache, const bool build_shapekey_layers, const bool allow_gpu, /* return args */ - DerivedMesh **r_deform, DerivedMesh **r_final) + Mesh **r_deform_mesh, Mesh **r_final_mesh) { Mesh *me = ob->data; /* Always get the vertex coordinates from the original mesh. Otherwise @@ -1760,7 +2020,6 @@ static void mesh_calc_modifiers( /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ CustomDataMask mask, nextmask, previewmask = 0, append_mask = CD_MASK_ORIGINDEX; float (*deformedVerts)[3] = NULL; - DerivedMesh *dm = NULL, *orcodm, *clothorcodm, *finaldm; int numVerts = me->totvert; const int required_mode = useRenderParams ? eModifierMode_Render : eModifierMode_Realtime; bool isPrevDeform = false; @@ -1782,7 +2041,6 @@ static void mesh_calc_modifiers( const bool do_mod_wmcol = do_init_wmcol; const bool do_loop_normals = (me->flag & ME_AUTOSMOOTH) != 0; - const float loop_normals_split_angle = me->smoothresh; VirtualModifierData virtualModifierData; @@ -1825,10 +2083,10 @@ static void mesh_calc_modifiers( datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, previewmd, previewmask); curr = datamasks; - if (r_deform) { - *r_deform = NULL; + if (r_deform_mesh) { + *r_deform_mesh = NULL; } - *r_final = NULL; + *r_final_mesh = NULL; if (useDeform) { if (inputVertexCos) @@ -1852,7 +2110,7 @@ static void mesh_calc_modifiers( if (!deformedVerts) deformedVerts = BKE_mesh_vertexCos_get(mesh_orig_id, &numVerts); - modwrap_deformVerts(md, &mectx_deform, NULL, deformedVerts, numVerts); + modifier_deformVerts_ensure_normals(md, &mectx_deform, NULL, deformedVerts, numVerts); } else { break; @@ -1867,14 +2125,17 @@ static void mesh_calc_modifiers( * places that wish to use the original mesh but with deformed * coordinates (vpaint, etc.) */ - if (r_deform) { - *r_deform = CDDM_from_mesh(me); - - if (build_shapekey_layers) - add_shapekey_layers(dm, me, ob); + if (r_deform_mesh) { + BKE_id_copy_ex(NULL, &me->id, (ID**)r_deform_mesh, + LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_DEG_TAG, false); + + /* XXX: Is build_shapekey_layers ever even true? This should have crashed long ago... */ + BLI_assert(!build_shapekey_layers); + //if (build_shapekey_layers) + // add_shapekey_layers(*r_deform_mesh, me, ob); if (deformedVerts) { - CDDM_apply_vert_coords(*r_deform, deformedVerts); + BKE_mesh_apply_vert_coords(*r_deform_mesh, deformedVerts); } } } @@ -1890,9 +2151,9 @@ static void mesh_calc_modifiers( /* Now apply all remaining modifiers. If useDeform is off then skip * OnlyDeform ones. */ - dm = NULL; - orcodm = NULL; - clothorcodm = NULL; + Mesh *mesh = NULL; + Mesh *orco_mesh = NULL; + Mesh *cloth_orco_mesh = NULL; for (; md; md = md->next, curr = curr->next) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -1907,7 +2168,7 @@ static void mesh_calc_modifiers( continue; } - if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { + if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && mesh) { modifier_setError(md, "Modifier requires original data, bad stack position"); continue; } @@ -1958,26 +2219,24 @@ static void mesh_calc_modifiers( else mask = 0; - if (dm && (mask & CD_MASK_ORCO)) - add_orco_dm(ob, NULL, dm, orcodm, CD_ORCO); + if (mesh && (mask & CD_MASK_ORCO)) { + add_orco_mesh(ob, NULL, mesh, orco_mesh, CD_ORCO); + } /* How to apply modifier depends on (a) what we already have as - * a result of previous modifiers (could be a DerivedMesh or just + * a result of previous modifiers (could be a Mesh or just * deformed vertices) and (b) what type the modifier is. */ if (mti->type == eModifierTypeType_OnlyDeform) { /* No existing verts to deform, need to build them. */ if (!deformedVerts) { - if (dm) { - /* Deforming a derived mesh, read the vertex locations + if (mesh) { + /* Deforming a mesh, read the vertex locations * out of the mesh and deform them. Once done with this * run of deformers verts will be written back. */ - numVerts = dm->getNumVerts(dm); - deformedVerts = - MEM_malloc_arrayN(numVerts, sizeof(*deformedVerts), "dfmv"); - dm->getVertCos(dm, deformedVerts); + deformedVerts = BKE_mesh_vertexCos_get(mesh, &numVerts); } else { deformedVerts = BKE_mesh_vertexCos_get(mesh_orig_id, &numVerts); @@ -1988,45 +2247,41 @@ static void mesh_calc_modifiers( * to avoid giving bogus normals to the next modifier see: [#23673] */ if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { /* XXX, this covers bug #23673, but we may need normal calc for other types */ - if (dm && dm->type == DM_TYPE_CDDM) { - CDDM_apply_vert_coords(dm, deformedVerts); + if (mesh) { + BKE_mesh_apply_vert_coords(mesh, deformedVerts); } } - modwrap_deformVerts(md, &mectx_deform, dm, deformedVerts, numVerts); + modifier_deformVerts_ensure_normals(md, &mectx_deform, mesh, deformedVerts, numVerts); } else { - DerivedMesh *ndm; - /* determine which data layers are needed by following modifiers */ if (curr->next) nextmask = curr->next->mask; else nextmask = dataMask; - /* apply vertex coordinates or build a DerivedMesh as necessary */ - if (dm) { + /* apply vertex coordinates or build a Mesh as necessary */ + if (mesh) { if (deformedVerts) { - DerivedMesh *tdm = CDDM_copy(dm); - dm->release(dm); - dm = tdm; - - CDDM_apply_vert_coords(dm, deformedVerts); + BKE_mesh_apply_vert_coords(mesh, deformedVerts); } } else { - dm = CDDM_from_mesh(me); - ASSERT_IS_VALID_DM(dm); + BKE_id_copy_ex(NULL, &me->id, (ID**)&mesh, + LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_DEG_TAG, false); + ASSERT_IS_VALID_MESH(mesh); - if (build_shapekey_layers) - add_shapekey_layers(dm, me, ob); + // XXX: port to Mesh if build_shapekey_layers can ever be true + //if (build_shapekey_layers) + // add_shapekey_layers(mesh, me, ob); if (deformedVerts) { - CDDM_apply_vert_coords(dm, deformedVerts); + BKE_mesh_apply_vert_coords(mesh, deformedVerts); } if (do_init_wmcol) - DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); + mesh_update_weight_mcol(ob, mesh, draw_flag, NULL, 0, NULL); /* Constructive modifiers need to have an origindex * otherwise they wont have anywhere to copy the data from. @@ -2037,45 +2292,48 @@ static void mesh_calc_modifiers( */ if (need_mapping || (nextmask & CD_MASK_ORIGINDEX)) { /* calc */ - DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); + CustomData_add_layer(&mesh->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totvert); + CustomData_add_layer(&mesh->edata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totedge); + CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totpoly); /* Not worth parallelizing this, gives less than 0.1% overall speedup in best of best cases... */ - range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); - range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); - range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); + range_vn_i(CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX), mesh->totvert, 0); + range_vn_i(CustomData_get_layer(&mesh->edata, CD_ORIGINDEX), mesh->totedge, 0); + range_vn_i(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX), mesh->totpoly, 0); } } - /* set the DerivedMesh to only copy needed data */ + /* set the Mesh to only copy needed data */ mask = curr->mask; /* needMapping check here fixes bug [#28112], otherwise it's * possible that it won't be copied */ mask |= append_mask; - DM_set_only_copy(dm, mask | (need_mapping ? CD_MASK_ORIGINDEX : 0)); - + mesh_set_only_copy(mesh, mask | (need_mapping ? CD_MASK_ORIGINDEX : 0)); + /* add cloth rest shape key if needed */ if (mask & CD_MASK_CLOTH_ORCO) - add_orco_dm(ob, NULL, dm, clothorcodm, CD_CLOTH_ORCO); + add_orco_mesh(ob, NULL, mesh, orco_mesh, CD_CLOTH_ORCO); /* add an origspace layer if needed */ if ((curr->mask) & CD_MASK_ORIGSPACE_MLOOP) { - if (!CustomData_has_layer(&dm->loopData, CD_ORIGSPACE_MLOOP)) { - DM_add_loop_layer(dm, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL); - DM_init_origspace(dm); + if (!CustomData_has_layer(&mesh->ldata, CD_ORIGSPACE_MLOOP)) { + CustomData_add_layer(&mesh->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh->totloop); + mesh_init_origspace(mesh); } } - ndm = modwrap_applyModifier(md, &mectx_apply, dm); - ASSERT_IS_VALID_DM(ndm); + Mesh *new_mesh = modifier_applyModifier_ensure_normals(md, &mectx_apply, mesh); + ASSERT_IS_VALID_MESH(new_mesh); - if (ndm) { - /* if the modifier returned a new dm, release the old one */ - if (dm && dm != ndm) dm->release(dm); + if (new_mesh) { + /* if the modifier returned a new mesh, release the old one */ + if (mesh && mesh != new_mesh) { + BLI_assert(mesh != me); + BKE_id_free(NULL, mesh); + } - dm = ndm; + mesh = new_mesh; if (deformedVerts) { if (deformedVerts != inputVertexCos) @@ -2085,43 +2343,51 @@ static void mesh_calc_modifiers( } } - /* create an orco derivedmesh in parallel */ + /* create an orco mesh in parallel */ if (nextmask & CD_MASK_ORCO) { - if (!orcodm) - orcodm = create_orco_dm(ob, me, NULL, CD_ORCO); + if (!orco_mesh) { + orco_mesh = create_orco_mesh(ob, me, NULL, CD_ORCO); + } nextmask &= ~CD_MASK_ORCO; - DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX | + mesh_set_only_copy(orco_mesh, nextmask | CD_MASK_ORIGINDEX | (mti->requiredDataMask ? mti->requiredDataMask(ob, md) : 0)); - ndm = modwrap_applyModifier(md, &mectx_orco, orcodm); - ASSERT_IS_VALID_DM(ndm); + new_mesh = modifier_applyModifier_ensure_normals(md, &mectx_orco, orco_mesh); + ASSERT_IS_VALID_MESH(new_mesh); - if (ndm) { - /* if the modifier returned a new dm, release the old one */ - if (orcodm && orcodm != ndm) orcodm->release(orcodm); - orcodm = ndm; + if (new_mesh) { + /* if the modifier returned a new mesh, release the old one */ + if (orco_mesh && orco_mesh != new_mesh) { + BLI_assert(orco_mesh != me); + BKE_id_free(NULL, orco_mesh); + } + + orco_mesh = new_mesh; } } - /* create cloth orco derivedmesh in parallel */ + /* create cloth orco mesh in parallel */ if (nextmask & CD_MASK_CLOTH_ORCO) { - if (!clothorcodm) - clothorcodm = create_orco_dm(ob, me, NULL, CD_CLOTH_ORCO); + if (!cloth_orco_mesh) { + cloth_orco_mesh = create_orco_mesh(ob, me, NULL, CD_CLOTH_ORCO); + } nextmask &= ~CD_MASK_CLOTH_ORCO; - DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX); + mesh_set_only_copy(cloth_orco_mesh, nextmask | CD_MASK_ORIGINDEX); - ndm = modwrap_applyModifier(md, &mectx_orco, clothorcodm); - ASSERT_IS_VALID_DM(ndm); + new_mesh = modifier_applyModifier_ensure_normals(md, &mectx_orco, cloth_orco_mesh); + ASSERT_IS_VALID_DM(new_mesh); - if (ndm) { - /* if the modifier returned a new dm, release the old one */ - if (clothorcodm && clothorcodm != ndm) { - clothorcodm->release(clothorcodm); + if (new_mesh) { + /* if the modifier returned a new mesh, release the old one */ + if (cloth_orco_mesh && cloth_orco_mesh != new_mesh) { + BLI_assert(orco_mesh != me); + BKE_id_free(NULL, cloth_orco_mesh); } - clothorcodm = ndm; + + cloth_orco_mesh = new_mesh; } } @@ -2131,11 +2397,11 @@ static void mesh_calc_modifiers( append_mask |= CD_MASK_PREVIEW_MLOOPCOL; /* In case of active preview modifier, make sure preview mask remains for following modifiers. */ else if ((md == previewmd) && (do_mod_wmcol)) { - DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); + mesh_update_weight_mcol(ob, mesh, draw_flag, NULL, 0, NULL); append_mask |= CD_MASK_PREVIEW_MLOOPCOL; } - dm->deformedOnly = false; + mesh->runtime.deformed_only = false; } isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); @@ -2152,65 +2418,60 @@ static void mesh_calc_modifiers( for (md = firstmd; md; md = md->next) modifier_freeTemporaryData(md); - /* Yay, we are done. If we have a DerivedMesh and deformed vertices - * need to apply these back onto the DerivedMesh. If we have no - * DerivedMesh then we need to build one. + /* Yay, we are done. If we have a Mesh and deformed vertices + * need to apply these back onto the Mesh. If we have no + * Mesh then we need to build one. */ - if (dm && deformedVerts) { - finaldm = CDDM_copy(dm); - - dm->release(dm); + Mesh *final_mesh; - CDDM_apply_vert_coords(finaldm, deformedVerts); + if (mesh) { + final_mesh = mesh; -#if 0 /* For later nice mod preview! */ - /* In case we need modified weights in CD_PREVIEW_MCOL, we have to re-compute it. */ - if (do_final_wmcol) - DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); -#endif - } - else if (dm) { - finaldm = dm; + if (deformedVerts) { + BKE_mesh_apply_vert_coords(final_mesh, deformedVerts); + } #if 0 /* For later nice mod preview! */ /* In case we need modified weights in CD_PREVIEW_MCOL, we have to re-compute it. */ if (do_final_wmcol) - DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); + mesh_update_weight_mcol(ob, final_mesh, draw_flag, NULL, 0, NULL); #endif } else { - finaldm = CDDM_from_mesh(me); - - if (build_shapekey_layers) { - add_shapekey_layers(finaldm, me, ob); - } - + BKE_id_copy_ex(NULL, &me->id, (ID**)&final_mesh, + LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_DEG_TAG, false); + + //if (build_shapekey_layers) { + // add_shapekey_layers(final_mesh, me, ob); + //} + if (deformedVerts) { - CDDM_apply_vert_coords(finaldm, deformedVerts); + BKE_mesh_apply_vert_coords(final_mesh, deformedVerts); } /* In this case, we should never have weight-modifying modifiers in stack... */ if (do_init_wmcol) - DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); + mesh_update_weight_mcol(ob, final_mesh, draw_flag, NULL, 0, NULL); } /* add an orco layer if needed */ if (dataMask & CD_MASK_ORCO) { - add_orco_dm(ob, NULL, finaldm, orcodm, CD_ORCO); + add_orco_mesh(ob, NULL, final_mesh, orco_mesh, CD_ORCO); - if (r_deform && *r_deform) - add_orco_dm(ob, NULL, *r_deform, NULL, CD_ORCO); + if (r_deform_mesh && *r_deform_mesh) + add_orco_mesh(ob, NULL, *r_deform_mesh, 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, do_loop_normals, loop_normals_split_angle); + BKE_mesh_calc_normals_split(final_mesh); + // dm->dirty |= DM_DIRTY_TESS_CDLAYERS; XXX } if (sculpt_dyntopo == false) { /* watch this! after 2.75a we move to from tessface to looptri (by default) */ if (dataMask & CD_MASK_MFACE) { - DM_ensure_tessface(finaldm); + // DM_ensure_tessface(final_mesh); // XXX: port? } /* without this, drawing ngon tri's faces will show ugly tessellated face @@ -2223,22 +2484,24 @@ static void mesh_calc_modifiers( * If using loop normals, poly nors have already been computed. */ if (!do_loop_normals) { - dm_ensure_display_normals(finaldm); + mesh_ensure_display_normals(final_mesh); } } /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them, * as they are used by display code when available (i.e. even if autosmooth is disabled). */ - if (!do_loop_normals && CustomData_has_layer(&finaldm->loopData, CD_NORMAL)) { - CustomData_free_layers(&finaldm->loopData, CD_NORMAL, finaldm->numLoopData); + if (!do_loop_normals && CustomData_has_layer(&final_mesh->ldata, CD_NORMAL)) { + CustomData_free_layers(&final_mesh->ldata, CD_NORMAL, final_mesh->totloop); } - *r_final = finaldm; + *r_final_mesh = final_mesh; - if (orcodm) - orcodm->release(orcodm); - if (clothorcodm) - clothorcodm->release(clothorcodm); + if (orco_mesh) { + BKE_id_free(NULL, orco_mesh); + } + if (cloth_orco_mesh) { + BKE_id_free(NULL, cloth_orco_mesh); + } if (deformedVerts && deformedVerts != inputVertexCos) MEM_freeN(deformedVerts); @@ -2246,6 +2509,30 @@ static void mesh_calc_modifiers( BLI_linklist_free((LinkNode *)datamasks, NULL); } +static void mesh_calc_modifiers_dm( + struct Depsgraph *depsgraph, Scene *scene, Object *ob, float (*inputVertexCos)[3], + const bool useRenderParams, int useDeform, + const bool need_mapping, CustomDataMask dataMask, + const int index, const bool useCache, const bool build_shapekey_layers, + const bool allow_gpu, + /* return args */ + DerivedMesh **r_deformdm, DerivedMesh **r_finaldm) +{ + Mesh *deform_mesh = NULL, *final_mesh = NULL; + + mesh_calc_modifiers(depsgraph, scene, ob, inputVertexCos, useRenderParams, useDeform, + need_mapping, dataMask, index, useCache, build_shapekey_layers, allow_gpu, + (r_deformdm ? &deform_mesh : NULL), &final_mesh); + + if(deform_mesh) { + *r_deformdm = CDDM_from_mesh_ex(deform_mesh, CD_DUPLICATE); + BKE_id_free(NULL, deform_mesh); + } + + *r_finaldm = CDDM_from_mesh_ex(final_mesh, CD_DUPLICATE); + BKE_id_free(NULL, final_mesh); +} + float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *r_numVerts))[3] { BMIter iter; @@ -2643,7 +2930,7 @@ static void mesh_build_data( } #endif - mesh_calc_modifiers( + mesh_calc_modifiers_dm( depsgraph, scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers, true, &ob->derivedDeform, &ob->derivedFinal); @@ -2792,7 +3079,7 @@ DerivedMesh *mesh_create_derived_render(struct Depsgraph *depsgraph, Scene *scen { DerivedMesh *final; - mesh_calc_modifiers( + mesh_calc_modifiers_dm( depsgraph, scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false, NULL, &final); @@ -2803,7 +3090,7 @@ DerivedMesh *mesh_create_derived_index_render(struct Depsgraph *depsgraph, Scene { DerivedMesh *final; - mesh_calc_modifiers( + mesh_calc_modifiers_dm( depsgraph, scene, ob, NULL, true, 1, false, dataMask, index, false, false, false, NULL, &final); @@ -2822,7 +3109,7 @@ DerivedMesh *mesh_create_derived_view( */ ob->transflag |= OB_NO_PSYS_UPDATE; - mesh_calc_modifiers( + mesh_calc_modifiers_dm( depsgraph, scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false, NULL, &final); @@ -2837,7 +3124,7 @@ DerivedMesh *mesh_create_derived_no_deform( { DerivedMesh *final; - mesh_calc_modifiers( + mesh_calc_modifiers_dm( depsgraph, scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false, NULL, &final); @@ -2851,7 +3138,7 @@ DerivedMesh *mesh_create_derived_no_deform_render( { DerivedMesh *final; - mesh_calc_modifiers( + mesh_calc_modifiers_dm( depsgraph, scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false, NULL, &final); @@ -3149,6 +3436,76 @@ void DM_init_origspace(DerivedMesh *dm) BLI_array_free(vcos_2d); } +static void mesh_init_origspace(Mesh *mesh) +{ + const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + + OrigSpaceLoop *lof_array = CustomData_get_layer(&mesh->ldata, CD_ORIGSPACE_MLOOP); + const int numpoly = mesh->totpoly; + // const int numloop = mesh->totloop; + MVert *mv = mesh->mvert; + MLoop *ml = mesh->mloop; + MPoly *mp = mesh->mpoly; + int i, j, k; + + float (*vcos_2d)[2] = NULL; + BLI_array_staticdeclare(vcos_2d, 64); + + for (i = 0; i < numpoly; i++, mp++) { + OrigSpaceLoop *lof = lof_array + mp->loopstart; + + if (mp->totloop == 3 || mp->totloop == 4) { + for (j = 0; j < mp->totloop; j++, lof++) { + copy_v2_v2(lof->uv, default_osf[j]); + } + } + else { + MLoop *l = &ml[mp->loopstart]; + float p_nor[3], co[3]; + float mat[3][3]; + + float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; + float translate[2], scale[2]; + + BKE_mesh_calc_poly_normal(mp, l, mv, p_nor); + axis_dominant_v3_to_m3(mat, p_nor); + + BLI_array_clear(vcos_2d); + BLI_array_reserve(vcos_2d, mp->totloop); + for (j = 0; j < mp->totloop; j++, l++) { + mul_v3_m3v3(co, mat, mv[l->v].co); + copy_v2_v2(vcos_2d[j], co); + + for (k = 0; k < 2; k++) { + if (co[k] > max[k]) + max[k] = co[k]; + else if (co[k] < min[k]) + min[k] = co[k]; + } + } + + /* Brings min to (0, 0). */ + negate_v2_v2(translate, min); + + /* Scale will bring max to (1, 1). */ + sub_v2_v2v2(scale, max, min); + if (scale[0] == 0.0f) + scale[0] = 1e-9f; + if (scale[1] == 0.0f) + scale[1] = 1e-9f; + invert_v2(scale); + + /* Finally, transform all vcos_2d into ((0, 0), (1, 1)) square and assing them as origspace. */ + for (j = 0; j < mp->totloop; j++, lof++) { + add_v2_v2v2(lof->uv, vcos_2d[j], translate); + mul_v2_v2(lof->uv, scale); + } + } + } + + //mesh->dirty |= DM_DIRTY_TESS_CDLAYERS; // XXX: Needed for Mesh? + BLI_array_free(vcos_2d); +} /* derivedmesh info printing function, |