diff options
Diffstat (limited to 'source/blender/blenkernel/intern/DerivedMesh.c')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 242 |
1 files changed, 171 insertions, 71 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index de7b962e38a..be9cda6c58f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -43,6 +43,7 @@ #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_pbvh.h" +#include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_displist.h" @@ -52,7 +53,8 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_texture.h" -#include "BKE_utildefines.h" +#include "BKE_multires.h" + #include "BLO_sys_types.h" // for intptr_t support @@ -64,6 +66,8 @@ #include "GPU_extensions.h" #include "GPU_material.h" +#include "ED_sculpt.h" /* for ED_sculpt_modifiers_changed */ + /////////////////////////////////// /////////////////////////////////// @@ -239,6 +243,15 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me) if(!CustomData_has_layer(&tmp.fdata, CD_MFACE)) CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupFaceArray(dm), totface); + /* object had got displacement layer, should copy this layer to save sculpted data */ + /* NOTE: maybe some other layers should be copied? nazgul */ + if(CustomData_has_layer(&me->fdata, CD_MDISPS)) { + if (totface == me->totface) { + MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + CustomData_add_layer(&tmp.fdata, CD_MDISPS, CD_DUPLICATE, mdisps, totface); + } + } + mesh_update_customdata_pointers(&tmp); CustomData_free(&me->vdata, me->totvert); @@ -419,7 +432,7 @@ void DM_swap_face_data(DerivedMesh *dm, int index, const int *corner_indices) /// -static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]) +DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) { DerivedMesh *dm = CDDM_from_mesh(me, ob); @@ -508,7 +521,7 @@ static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *us glEnd(); } } -static void emDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges) +static void emDM_drawEdges(DerivedMesh *dm, int UNUSED(drawLooseEdges), int UNUSED(drawAllEdges)) { emDM_drawMappedEdges(dm, NULL, NULL); } @@ -617,11 +630,15 @@ static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *use func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n); } } -static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) + +/* note, material function is ignored for now. */ +static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int UNUSED(useColors), int (*setMaterial)(int, void *attribs)) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; EditFace *efa; int i, draw; + + (void)setMaterial; /* unused */ if (emdm->vertexCos) { EditVert *eve; @@ -1105,8 +1122,7 @@ static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) vert_r->no[1] = ev->no[1] * 32767.0; vert_r->no[2] = ev->no[2] * 32767.0; - /* TODO what to do with vert_r->flag and vert_r->mat_nr? */ - vert_r->mat_nr = 0; + /* TODO what to do with vert_r->flag? */ vert_r->bweight = (unsigned char) (ev->bweight*255.0f); } @@ -1203,8 +1219,7 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) vert_r->no[1] = ev->no[1] * 32767.0; vert_r->no[2] = ev->no[2] * 32767.0; - /* TODO what to do with vert_r->flag and vert_r->mat_nr? */ - vert_r->mat_nr = 0; + /* TODO what to do with vert_r->flag? */ vert_r->flag = 0; vert_r->bweight = (unsigned char) (ev->bweight*255.0f); } @@ -1270,7 +1285,7 @@ static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) EditFace *efa; char *data, *emdata; void *datalayer; - int index, offset, size; + int index, size; datalayer = DM_get_face_data_layer(dm, type); if(datalayer) @@ -1282,7 +1297,7 @@ static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) index = CustomData_get_layer_index(&em->fdata, type); if(index != -1) { - offset = em->fdata.layers[index].offset; + /* int offset = em->fdata.layers[index].offset; */ /* UNUSED */ size = CustomData_sizeof(type); DM_add_face_layer(dm, type, CD_CALLOC, NULL); @@ -1315,8 +1330,7 @@ static void emDM_release(DerivedMesh *dm) } } -static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, - float (*vertexCos)[3]) +DerivedMesh *editmesh_get_derived(EditMesh *em, float (*vertexCos)[3]) { EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm"); @@ -1433,11 +1447,11 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts); mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0); - dm = getMeshDerivedMesh(me, ob, deformedVerts); + dm = mesh_create_derived(me, ob, deformedVerts); MEM_freeN(deformedVerts); } else { - DerivedMesh *tdm = getMeshDerivedMesh(me, ob, NULL); + DerivedMesh *tdm = mesh_create_derived(me, ob, NULL); dm = mti->applyModifier(md, ob, tdm, 0, 0); if(tdm != dm) tdm->release(tdm); @@ -1661,17 +1675,32 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos DerivedMesh *dm, *orcodm, *clothorcodm, *finaldm; int numVerts = me->totvert; int required_mode; + int isPrevDeform= FALSE; + int skipVirtualArmature = (useDeform < 0); + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0); + int has_multires = mmd != NULL, multires_applied = 0; + int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt; + + if(mmd && !mmd->sculptlvl) + has_multires = 0; + + if(!skipVirtualArmature) { + firstmd = modifiers_getVirtualModifierList(ob); + } + else { + /* game engine exception */ + firstmd = ob->modifiers.first; + if(firstmd && firstmd->type == eModifierType_Armature) + firstmd = firstmd->next; + } - md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob); + md = firstmd; modifiers_clearErrors(ob); if(useRenderParams) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; - /* we always want to keep original indices */ - dataMask |= CD_MASK_ORIGINDEX; - datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode); curr = datamasks; @@ -1692,6 +1721,12 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; if(mti->type == eModifierTypeType_OnlyDeform) { + if(sculpt_mode && !has_multires) + if(!ELEM(md->type, eModifierType_Armature, eModifierType_ShapeKey)) { + modifier_setError(md, "Not supported in sculpt mode."); + continue; + } + if(!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts); @@ -1737,13 +1772,18 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene= scene; - + if(!modifier_isEnabled(scene, md, required_mode)) continue; if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue; if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { modifier_setError(md, "Modifier requires original data, bad stack position."); continue; } + if(sculpt_mode && (!has_multires || multires_applied)) + if(md->type != eModifierType_Armature || multires_applied) { + modifier_setError(md, "Not supported in sculpt mode."); + continue; + } if(needMapping && !modifier_supportsMapping(md)) continue; if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; @@ -1778,10 +1818,26 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } } + /* if this is not the last modifier in the stack then recalculate the normals + * 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->type == DM_TYPE_CDDM) { + CDDM_apply_vert_coords(dm, deformedVerts); + CDDM_calc_normals(dm); + } + } + mti->deformVerts(md, ob, dm, deformedVerts, numVerts, useRenderParams, useDeform); } else { DerivedMesh *ndm; + /* determine which data layers are needed by following modifiers */ + if(curr->next) + nextmask= (CustomDataMask)GET_INT_FROM_POINTER(curr->next->link); + else + nextmask= dataMask; + /* apply vertex coordinates or build a DerivedMesh as necessary */ if(dm) { if(deformedVerts) { @@ -1803,28 +1859,25 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) add_weight_mcol_dm(ob, dm); - /* constructive modifiers need to have an origindex - * otherwise they wont have anywhere to copy the data from */ - if(needMapping) { - int *index, i; + /* Constructive modifiers need to have an origindex + * otherwise they wont have anywhere to copy the data from. + * + * Also create ORIGINDEX data if any of the following modifiers + * requests it, this way Mirror, Solidify etc will keep ORIGINDEX + * data by using generic DM_copy_vert_data() functions. + */ + if(needMapping || (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_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - index = DM_get_vert_data_layer(dm, CD_ORIGINDEX); - for(i=0; i<dm->numVertData; i++) *index++= i; - index = DM_get_edge_data_layer(dm, CD_ORIGINDEX); - for(i=0; i<dm->numEdgeData; i++) *index++= i; - index = DM_get_face_data_layer(dm, CD_ORIGINDEX); - for(i=0; i<dm->numFaceData; i++) *index++= i; + range_vni(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); + range_vni(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); + range_vni(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numFaceData, 0); } } - /* determine which data layers are needed by following modifiers */ - if(curr->next) - nextmask= (CustomDataMask)GET_INT_FROM_POINTER(curr->next->link); - else - nextmask= dataMask; /* set the DerivedMesh to only copy needed data */ mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); @@ -1861,7 +1914,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos orcodm= create_orco_dm(ob, me, NULL, CD_ORCO); nextmask &= ~CD_MASK_ORCO; - DM_set_only_copy(orcodm, nextmask); + DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX); ndm = mti->applyModifier(md, ob, orcodm, useRenderParams, 0); if(ndm) { @@ -1877,7 +1930,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos clothorcodm= create_orco_dm(ob, me, NULL, CD_CLOTH_ORCO); nextmask &= ~CD_MASK_CLOTH_ORCO; - DM_set_only_copy(clothorcodm, nextmask); + DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX); ndm = mti->applyModifier(md, ob, clothorcodm, useRenderParams, 0); if(ndm) { @@ -1888,9 +1941,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } } + isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform); + /* grab modifiers until index i */ if((index >= 0) && (modifiers_indexInObject(ob, md) >= index)) break; + + if(sculpt_mode && md->type == eModifierType_Multires) + multires_applied = 1; } for(md=firstmd; md; md=md->next) @@ -1945,7 +2003,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos BLI_linklist_free(datamasks, NULL); } -static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3] +float (*editmesh_get_vertex_cos(EditMesh *em, int *numVerts_r))[3] { int i, numVerts = *numVerts_r = BLI_countlist(&em->verts); float (*cos)[3]; @@ -1959,7 +2017,7 @@ static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3] return cos; } -static int editmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm) +int editmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; @@ -1988,14 +2046,11 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri modifiers_clearErrors(ob); if(cage_r && cageIndex == -1) { - *cage_r = getEditMeshDerivedMesh(em, ob, NULL); + *cage_r = editmesh_get_derived(em, NULL); } dm = NULL; md = modifiers_getVirtualModifierList(ob); - - /* we always want to keep original indices */ - dataMask |= CD_MASK_ORIGINDEX; datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode); @@ -2033,7 +2088,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv"); dm->getVertCos(dm, deformedVerts); } else { - deformedVerts = editmesh_getVertexCos(em, &numVerts); + deformedVerts = editmesh_get_vertex_cos(em, &numVerts); } } @@ -2074,7 +2129,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri orcodm= create_orco_dm(ob, ob->data, em, CD_ORCO); mask &= ~CD_MASK_ORCO; - DM_set_only_copy(orcodm, mask); + DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX); if (mti->applyModifierEM) ndm = mti->applyModifierEM(md, ob, em, orcodm); @@ -2089,9 +2144,11 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri } /* set the DerivedMesh to only copy needed data */ - DM_set_only_copy(dm, (CustomDataMask)GET_INT_FROM_POINTER(curr->link)); + mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); /* CD_MASK_ORCO may have been cleared above */ - if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE) + DM_set_only_copy(dm, mask | CD_MASK_ORIGINDEX); + + if(mask & CD_MASK_ORIGSPACE) if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE)) DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); @@ -2121,7 +2178,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri *cage_r = dm; } else { *cage_r = - getEditMeshDerivedMesh(em, ob, + editmesh_get_derived(em, deformedVerts ? MEM_dupallocN(deformedVerts) : NULL); } } @@ -2145,7 +2202,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri } else if (!deformedVerts && cage_r && *cage_r) { *final_r = *cage_r; } else { - *final_r = getEditMeshDerivedMesh(em, ob, deformedVerts); + *final_r = editmesh_get_derived(em, deformedVerts); deformedVerts = NULL; } @@ -2186,14 +2243,9 @@ static void clear_mesh_caches(Object *ob) ob->derivedDeform->release(ob->derivedDeform); ob->derivedDeform= NULL; } - /* we free pbvh on changes, except during sculpt since it can't deal with - changing PVBH node organization, we hope topology does not change in - the meantime .. weak */ - if(ob->sculpt && ob->sculpt->pbvh) { - if(!ob->sculpt->cache) { - BLI_pbvh_free(ob->sculpt->pbvh); - ob->sculpt->pbvh= NULL; - } + + if(ob->sculpt) { + ED_sculpt_modifiers_changed(ob); } } @@ -2201,8 +2253,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) { Object *obact = scene->basact?scene->basact->object:NULL; int editing = paint_facesel_test(ob); - /* weight paint and face select need original indicies because of selection buffer drawing */ - int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)) || editing); + /* weight paint and face select need original indices because of selection buffer drawing */ + int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT))); clear_mesh_caches(ob); @@ -2322,6 +2374,16 @@ DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*ve return final; } +DerivedMesh *mesh_create_derived_physics(Scene *scene, Object *ob, float (*vertCos)[3], + CustomDataMask dataMask) +{ + DerivedMesh *final; + + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0); + + return final; +} + DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob, float (*vertCos)[3], CustomDataMask dataMask) @@ -2361,9 +2423,9 @@ DerivedMesh *editmesh_get_derived_cage(Scene *scene, Object *obedit, EditMesh *e return em->derivedCage; } -DerivedMesh *editmesh_get_derived_base(Object *obedit, EditMesh *em) +DerivedMesh *editmesh_get_derived_base(Object *UNUSED(obedit), EditMesh *em) { - return getEditMeshDerivedMesh(em, obedit, NULL); + return editmesh_get_derived(em, NULL); } @@ -2449,8 +2511,8 @@ int editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *em, f if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) { if(!defmats) { - dm= getEditMeshDerivedMesh(em, ob, NULL); - deformedVerts= editmesh_getVertexCos(em, &numVerts); + dm= editmesh_get_derived(em, NULL); + deformedVerts= editmesh_get_vertex_cos(em, &numVerts); defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats"); for(a=0; a<numVerts; a++) @@ -2477,6 +2539,51 @@ int editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *em, f return numleft; } +void sculpt_get_deform_matrices(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) +{ + ModifierData *md; + DerivedMesh *dm; + int a, numVerts= 0; + float (*defmats)[3][3]= NULL, (*deformedVerts)[3]= NULL; + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0); + int has_multires = mmd != NULL && mmd->sculptlvl > 0; + + if(has_multires) { + *deformmats= NULL; + *deformcos= NULL; + return; + } + + dm= NULL; + md= modifiers_getVirtualModifierList(ob); + + for(; md; md= md->next) { + ModifierTypeInfo *mti= modifierType_getInfo(md->type); + + if(!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; + + if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatrices) { + if(!defmats) { + Mesh *me= (Mesh*)ob->data; + dm= mesh_create_derived(me, ob, NULL); + deformedVerts= mesh_getVertexCos(me, &numVerts); + defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats"); + + for(a=0; a<numVerts; a++) + unit_m3(defmats[a]); + } + + mti->deformMatrices(md, ob, dm, deformedVerts, defmats, numVerts); + } + } + + if(dm) + dm->release(dm); + + *deformmats= defmats; + *deformcos= deformedVerts; +} + /* ******************* GLSL ******************** */ void DM_add_tangent_layer(DerivedMesh *dm) @@ -2566,15 +2673,8 @@ void DM_add_tangent_layer(DerivedMesh *dm) /* write tangent to layer */ for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) { len= (mf->v4)? 4 : 3; - - if(mtface) { - uv1= tf->uv[0]; - uv2= tf->uv[1]; - uv3= tf->uv[2]; - uv4= tf->uv[3]; - } - else { - uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; + + if(mtface == NULL) { map_to_sphere( &uv[0][0], &uv[0][1],orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]); map_to_sphere( &uv[1][0], &uv[1][1],orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]); map_to_sphere( &uv[2][0], &uv[2][1],orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]); |