diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 245db7e35ff..3018f89178e 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -228,7 +228,7 @@ typedef struct ModifierTypeInfo { * * This function is optional (assumes never disabled if not present). */ - int (*isDisabled)(struct ModifierData *md); + int (*isDisabled)(struct ModifierData *md, int userRenderParams); /* Add the appropriate relations to the DEP graph depending on the * modifier data. diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index a331479cad1..53ead3a5eda 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -39,23 +39,6 @@ typedef struct MultiresSubsurf { int local_mmd; } MultiresSubsurf; -/* MultiresDM */ -struct Object *MultiresDM_get_object(struct DerivedMesh *dm); -struct Mesh *MultiresDM_get_mesh(struct DerivedMesh *dm); -struct DerivedMesh *MultiresDM_new(struct MultiresSubsurf *, struct DerivedMesh*, int, int, int); -void *MultiresDM_get_vertnorm(struct DerivedMesh *); -void *MultiresDM_get_orco(struct DerivedMesh *); -struct MVert *MultiresDM_get_subco(struct DerivedMesh *); -struct ListBase *MultiresDM_get_vert_face_map(struct DerivedMesh *); -struct ListBase *MultiresDM_get_vert_edge_map(struct DerivedMesh *); -int *MultiresDM_get_face_offsets(struct DerivedMesh *); -int MultiresDM_get_totlvl(struct DerivedMesh *); -int MultiresDM_get_lvl(struct DerivedMesh *); -void MultiresDM_set_update(struct DerivedMesh *, void (*)(struct DerivedMesh*)); - -/* The displacements will only be updated when - the MultiresDM has been marked as modified */ -void MultiresDM_mark_as_modified(struct DerivedMesh *); void multires_mark_as_modified(struct Object *ob); void multires_force_update(struct Object *ob); @@ -64,10 +47,9 @@ struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData* struct Object *, int, int); struct MultiresModifierData *find_multires_modifier(struct Object *ob); -int multiresModifier_switch_level(struct Object *, const int); void multiresModifier_join(struct Object *); void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction); -void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int distance, +void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple); int multiresModifier_reshape(struct MultiresModifierData *mmd, struct Object *dst, struct Object *src); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 5a911fcb13b..b715b1531de 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1535,7 +1535,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier md->scene= scene; if (!(md->mode&eModifierMode_Realtime)) return NULL; - if (mti->isDisabled && mti->isDisabled(md)) return NULL; + if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL; if (mti->type==eModifierTypeType_OnlyDeform) { int numVerts; diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 3007564e333..b3e75549028 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1810,215 +1810,3 @@ MFace *CDDM_get_faces(DerivedMesh *dm) return ((CDDerivedMesh*)dm)->mface; } -/* Multires DerivedMesh, extends CDDM */ -typedef struct MultiresDM { - CDDerivedMesh cddm; - - MultiresModifierData *mmd; - int local_mmd; - - int lvl, totlvl; - float (*orco)[3]; - MVert *subco; - - ListBase *vert_face_map, *vert_edge_map; - IndexNode *vert_face_map_mem, *vert_edge_map_mem; - int *face_offsets; - - Object *ob; - int modified; - - void (*update)(DerivedMesh*); -} MultiresDM; - -static void MultiresDM_release(DerivedMesh *dm) -{ - MultiresDM *mrdm = (MultiresDM*)dm; - int mvert_layer; - - /* Before freeing, need to update the displacement map */ - if(dm->needsFree && mrdm->modified) { - /* Check that mmd still exists */ - if(!mrdm->local_mmd && BLI_findindex(&mrdm->ob->modifiers, mrdm->mmd) < 0) - mrdm->mmd = NULL; - if(mrdm->mmd) - mrdm->update(dm); - } - - /* If the MVert data is being used as the sculpt undo store, don't free it */ - mvert_layer = CustomData_get_layer_index(&dm->vertData, CD_MVERT); - if(mvert_layer != -1) { - CustomDataLayer *cd = &dm->vertData.layers[mvert_layer]; - if(mrdm->mmd && cd->data == mrdm->mmd->undo_verts) - cd->flag |= CD_FLAG_NOFREE; - } - - if(DM_release(dm)) { - cdDM_free_internal(&mrdm->cddm); - MEM_freeN(mrdm->subco); - MEM_freeN(mrdm->orco); - if(mrdm->vert_face_map) - MEM_freeN(mrdm->vert_face_map); - if(mrdm->vert_face_map_mem) - MEM_freeN(mrdm->vert_face_map_mem); - if(mrdm->vert_edge_map) - MEM_freeN(mrdm->vert_edge_map); - if(mrdm->vert_edge_map_mem) - MEM_freeN(mrdm->vert_edge_map_mem); - if(mrdm->face_offsets) - MEM_freeN(mrdm->face_offsets); - MEM_freeN(mrdm); - } -} - -DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts, int numEdges, int numFaces) -{ - MultiresDM *mrdm = MEM_callocN(sizeof(MultiresDM), "MultiresDM"); - CDDerivedMesh *cddm = cdDM_create("MultiresDM CDDM"); - DerivedMesh *dm = NULL; - - mrdm->cddm = *cddm; - MEM_freeN(cddm); - dm = &mrdm->cddm.dm; - - mrdm->mmd = ms->mmd; - mrdm->ob = ms->ob; - mrdm->local_mmd = ms->local_mmd; - - if(dm) { - MDisps *disps; - MVert *mvert; - int i; - - DM_from_template(dm, orig, numVerts, numEdges, numFaces); - CustomData_free_layers(&dm->faceData, CD_MDISPS, numFaces); - - disps = CustomData_get_layer(&orig->faceData, CD_MDISPS); - if(disps) - CustomData_add_layer(&dm->faceData, CD_MDISPS, CD_REFERENCE, disps, numFaces); - - - mvert = CustomData_get_layer(&orig->vertData, CD_MVERT); - mrdm->orco = MEM_callocN(sizeof(float) * 3 * orig->getNumVerts(orig), "multires orco"); - for(i = 0; i < orig->getNumVerts(orig); ++i) - copy_v3_v3(mrdm->orco[i], mvert[i].co); - } - else - DM_init(dm, numVerts, numEdges, numFaces); - - if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) - CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); - if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX)) - CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); - if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) - CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); - - CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); - CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); - CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); - - mrdm->cddm.mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); - mrdm->cddm.medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); - mrdm->cddm.mface = CustomData_get_layer(&dm->faceData, CD_MFACE); - - mrdm->lvl = ms->mmd->lvl; - mrdm->totlvl = ms->mmd->totlvl; - mrdm->subco = MEM_callocN(sizeof(MVert)*numVerts, "multires subdivided verts"); - mrdm->modified = 0; - - dm->release = MultiresDM_release; - - return dm; -} - -Mesh *MultiresDM_get_mesh(DerivedMesh *dm) -{ - return get_mesh(((MultiresDM*)dm)->ob); -} - -Object *MultiresDM_get_object(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->ob; -} - -void *MultiresDM_get_orco(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->orco; - -} - -MVert *MultiresDM_get_subco(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->subco; -} - -int MultiresDM_get_totlvl(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->totlvl; -} - -int MultiresDM_get_lvl(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->lvl; -} - -void MultiresDM_set_orco(DerivedMesh *dm, float (*orco)[3]) -{ - ((MultiresDM*)dm)->orco = orco; -} - -void MultiresDM_set_update(DerivedMesh *dm, void (*update)(DerivedMesh*)) -{ - ((MultiresDM*)dm)->update = update; -} - -ListBase *MultiresDM_get_vert_face_map(DerivedMesh *dm) -{ - MultiresDM *mrdm = (MultiresDM*)dm; - Mesh *me = mrdm->ob->data; - - if(!mrdm->vert_face_map) - create_vert_face_map(&mrdm->vert_face_map, &mrdm->vert_face_map_mem, me->mface, - me->totvert, me->totface); - - return mrdm->vert_face_map; -} - -ListBase *MultiresDM_get_vert_edge_map(DerivedMesh *dm) -{ - MultiresDM *mrdm = (MultiresDM*)dm; - Mesh *me = mrdm->ob->data; - - if(!mrdm->vert_edge_map) - create_vert_edge_map(&mrdm->vert_edge_map, &mrdm->vert_edge_map_mem, me->medge, - me->totvert, me->totedge); - - return mrdm->vert_edge_map; -} - -int *MultiresDM_get_face_offsets(DerivedMesh *dm) -{ - MultiresDM *mrdm = (MultiresDM*)dm; - Mesh *me = mrdm->ob->data; - int i, accum = 0; - - if(!mrdm->face_offsets) { - int len = (int)pow(2, mrdm->lvl - 2) - 1; - int area = len * len; - int t = 1 + len * 3 + area * 3, q = t + len + area; - - mrdm->face_offsets = MEM_callocN(sizeof(int) * me->totface, "mrdm face offsets"); - for(i = 0; i < me->totface; ++i) { - mrdm->face_offsets[i] = accum; - - accum += (me->mface[i].v4 ? q : t); - } - } - - return mrdm->face_offsets; -} - -void MultiresDM_mark_as_modified(DerivedMesh *dm) -{ - ((MultiresDM*)dm)->modified = 1; -} diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 7b754025b6c..4844595513f 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -381,6 +381,7 @@ static void layerDefault_origspace_face(void *data, int count) osf[i] = default_osf; } +#if 0 /* Adapted from sculptmode.c */ static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) { @@ -426,9 +427,12 @@ static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, fl add_v3_v3v3(out, d2[0], d2[1]); } +#endif static void layerSwap_mdisps(void *data, int *ci) { + // XXX +#if 0 MDisps *s = data; float (*d)[3] = NULL; int x, y, st; @@ -447,11 +451,14 @@ static void layerSwap_mdisps(void *data, int *ci) if(s->disps) MEM_freeN(s->disps); s->disps = d; +#endif } static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights, int count, void *dest) { + // XXX +#if 0 MDisps *d = dest; MDisps *s = NULL; int st, stl; @@ -496,6 +503,7 @@ static void layerInterp_mdisps(void **sources, float *weights, float *sub_weight copy_v3_v3(d->disps[y * st + x], srcdisp); } } +#endif } static void layerCopy_mdisps(const void *source, void *dest, int count) diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 48fb283c404..b35cf917895 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1225,7 +1225,7 @@ static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int ed ModifierTypeInfo *mti = modifierType_getInfo(md->type); if ((md->mode & required_mode) != required_mode) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { preTesselatePoint = md; @@ -1275,7 +1275,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl md->scene= scene; if ((md->mode & required_mode) != required_mode) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; if (mti->type!=eModifierTypeType_OnlyDeform) continue; if (!deformedVerts) { @@ -1330,7 +1330,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba md->scene= scene; if ((md->mode & required_mode) != required_mode) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; if (mti->type!=eModifierTypeType_OnlyDeform && mti->type!=eModifierTypeType_DeformOrConstruct) continue; /* need to put all verts in 1 block for curve deform */ diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index dc548edbb25..e963b2e9fb6 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -1002,7 +1002,7 @@ void lattice_calc_modifiers(Scene *scene, Object *ob) if (!(md->mode&eModifierMode_Realtime)) continue; if (editmode && !(md->mode&eModifierMode_Editmode)) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, 0)) continue; if (mti->type!=eModifierTypeType_OnlyDeform) continue; if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 50c907fd1ca..d8c05c30cfe 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -187,7 +187,7 @@ static DerivedMesh *get_original_dm(Scene *scene, Object *ob, float (*vertexCos) /***/ -static int noneModifier_isDisabled(ModifierData *md) +static int noneModifier_isDisabled(ModifierData *md, int userRenderParams) { return 1; } @@ -222,7 +222,7 @@ static CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *m return dataMask; } -static int curveModifier_isDisabled(ModifierData *md) +static int curveModifier_isDisabled(ModifierData *md, int userRenderParams) { CurveModifierData *cmd = (CurveModifierData*) md; @@ -298,7 +298,7 @@ static CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData return dataMask; } -static int latticeModifier_isDisabled(ModifierData *md) +static int latticeModifier_isDisabled(ModifierData *md, int userRenderParams) { LatticeModifierData *lmd = (LatticeModifierData*) md; @@ -402,6 +402,13 @@ static void subsurfModifier_freeData(ModifierData *md) } } +static int subsurfModifier_isDisabled(ModifierData *md, int useRenderParams) +{ + SubsurfModifierData *smd = (SubsurfModifierData*) md; + + return (useRenderParams)? (smd->renderLevels == 0): (smd->levels == 0); +} + static DerivedMesh *subsurfModifier_applyModifier( ModifierData *md, Object *ob, DerivedMesh *derivedData, int useRenderParams, int isFinalCalc) @@ -410,8 +417,13 @@ static DerivedMesh *subsurfModifier_applyModifier( DerivedMesh *result; result = subsurf_make_derived_from_derived(derivedData, smd, - useRenderParams, NULL, - isFinalCalc, 0); + useRenderParams, NULL, isFinalCalc, 0); + + if(useRenderParams || !isFinalCalc) { + DerivedMesh *cddm= CDDM_copy(result); + result->release(result); + result= cddm; + } return result; } @@ -3524,7 +3536,7 @@ static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob, displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } -static int displaceModifier_isDisabled(ModifierData *md) +static int displaceModifier_isDisabled(ModifierData *md, int useRenderParams) { DisplaceModifierData *dmd = (DisplaceModifierData*) md; @@ -4268,7 +4280,7 @@ static void smoothModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tsmd->defgrp_name, smd->defgrp_name, 32); } -static int smoothModifier_isDisabled(ModifierData *md) +static int smoothModifier_isDisabled(ModifierData *md, int useRenderParams) { SmoothModifierData *smd = (SmoothModifierData*) md; short flag; @@ -4498,7 +4510,7 @@ static void castModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32); } -static int castModifier_isDisabled(ModifierData *md) +static int castModifier_isDisabled(ModifierData *md, int useRenderParams) { CastModifierData *cmd = (CastModifierData*) md; short flag; @@ -5487,7 +5499,7 @@ static CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData return dataMask; } -static int armatureModifier_isDisabled(ModifierData *md) +static int armatureModifier_isDisabled(ModifierData *md, int useRenderParams) { ArmatureModifierData *amd = (ArmatureModifierData*) md; @@ -5610,7 +5622,7 @@ static void hookModifier_freeData(ModifierData *md) if (hmd->indexar) MEM_freeN(hmd->indexar); } -static int hookModifier_isDisabled(ModifierData *md) +static int hookModifier_isDisabled(ModifierData *md, int useRenderParams) { HookModifierData *hmd = (HookModifierData*) md; @@ -6308,7 +6320,7 @@ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) tbmd->operation = bmd->operation; } -static int booleanModifier_isDisabled(ModifierData *md) +static int booleanModifier_isDisabled(ModifierData *md, int useRenderParams) { BooleanModifierData *bmd = (BooleanModifierData*) md; @@ -7757,7 +7769,7 @@ static CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierDa return dataMask; } -static int meshdeformModifier_isDisabled(ModifierData *md) +static int meshdeformModifier_isDisabled(ModifierData *md, int useRenderParams) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; @@ -8047,15 +8059,10 @@ static void multiresModifier_initData(ModifierData *md) { MultiresModifierData *mmd = (MultiresModifierData*)md; - mmd->lvl = mmd->totlvl = 1; -} - -static void multiresModifier_freeData(ModifierData *md) -{ - MultiresModifierData *mmd = (MultiresModifierData*)md; - - if(mmd->undo_verts) - MEM_freeN(mmd->undo_verts); + mmd->lvl = 0; + mmd->sculptlvl = 0; + mmd->renderlvl = 0; + mmd->totlvl = 0; } static void multiresModifier_copyData(ModifierData *md, ModifierData *target) @@ -8063,37 +8070,35 @@ static void multiresModifier_copyData(ModifierData *md, ModifierData *target) MultiresModifierData *mmd = (MultiresModifierData*) md; MultiresModifierData *tmmd = (MultiresModifierData*) target; - tmmd->totlvl = mmd->totlvl; tmmd->lvl = mmd->lvl; + tmmd->sculptlvl = mmd->sculptlvl; + tmmd->renderlvl = mmd->renderlvl; + tmmd->totlvl = mmd->totlvl; } static DerivedMesh *multiresModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { MultiresModifierData *mmd = (MultiresModifierData*)md; - DerivedMesh *final; + DerivedMesh *result; - /* TODO: for now just skip a level1 mesh */ - if(mmd->lvl == 1) + result = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams, isFinalCalc); + + if(result == dm) return dm; - final = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams, isFinalCalc); - if(mmd->undo_signal && mmd->undo_verts && mmd->undo_verts_tot == final->getNumVerts(final)) { - int i; - MVert *dst = CDDM_get_verts(final); - for(i = 0; i < mmd->undo_verts_tot; ++i) { - copy_v3_v3(dst[i].co, mmd->undo_verts[i].co); - } - CDDM_calc_normals(final); - - MultiresDM_mark_as_modified(final); - - MEM_freeN(mmd->undo_verts); - mmd->undo_signal = 0; - mmd->undo_verts = NULL; + if(useRenderParams || !isFinalCalc) { + DerivedMesh *cddm= CDDM_copy(result); + result->release(result); + result= cddm; + } + else if(ob->mode & OB_MODE_SCULPT) { + /* would be created on the fly too, just nicer this + way on first stroke after e.g. switching levels */ + result->getPBVH(ob, result); } - return final; + return result; } /* Shrinkwrap */ @@ -8142,7 +8147,7 @@ static CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierDa return dataMask; } -static int shrinkwrapModifier_isDisabled(ModifierData *md) +static int shrinkwrapModifier_isDisabled(ModifierData *md, int useRenderParams) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; return !smd->target; @@ -8438,6 +8443,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->initData = subsurfModifier_initData; mti->copyData = subsurfModifier_copyData; mti->freeData = subsurfModifier_freeData; + mti->isDisabled = subsurfModifier_isDisabled; mti->applyModifier = subsurfModifier_applyModifier; mti->applyModifierEM = subsurfModifier_applyModifierEM; @@ -8770,7 +8776,6 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData; mti->initData = multiresModifier_initData; - mti->freeData = multiresModifier_freeData; mti->copyData = multiresModifier_copyData; mti->applyModifier = multiresModifier_applyModifier; @@ -8920,7 +8925,7 @@ int modifier_couldBeCage(ModifierData *md) return ( (md->mode & eModifierMode_Realtime) && (md->mode & eModifierMode_Editmode) && - (!mti->isDisabled || !mti->isDisabled(md)) && + (!mti->isDisabled || !mti->isDisabled(md, 0)) && modifier_supportsMapping(md)); } @@ -8957,7 +8962,7 @@ int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r, int virtual if (!(md->mode & eModifierMode_Realtime)) continue; if (!(md->mode & eModifierMode_Editmode)) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, 0)) continue; if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue; if (md->mode & eModifierMode_DisableTemporary) continue; @@ -8999,7 +9004,7 @@ int modifier_isEnabled(ModifierData *md, int required_mode) ModifierTypeInfo *mti = modifierType_getInfo(md->type); if((md->mode & required_mode) != required_mode) return 0; - if(mti->isDisabled && mti->isDisabled(md)) return 0; + if(mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return 0; if(md->mode & eModifierMode_DisableTemporary) return 0; if(required_mode & eModifierMode_Editmode) if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index fc14afaf07f..2518d4bc3ca 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -40,6 +40,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BKE_btex.h" #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" @@ -50,14 +51,19 @@ #include "BKE_multires.h" #include "BKE_object.h" #include "BKE_subsurf.h" +#include "BKE_utildefines.h" + +#include "CCGSubSurf.h" #include #include /* MULTIRES MODIFIER */ static const int multires_max_levels = 13; -static const int multires_quad_tot[] = {4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; -static const int multires_side_tot[] = {2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; +static const int multires_grid_tot[] = {1, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; +static const int multires_side_tot[] = {1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; + +static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl); MultiresModifierData *find_multires_modifier(Object *ob) { @@ -72,23 +78,32 @@ MultiresModifierData *find_multires_modifier(Object *ob) } return mmd; - } -int multiresModifier_switch_level(Object *ob, const int distance) +static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render) { - MultiresModifierData *mmd = find_multires_modifier(ob); - - if(mmd) { - mmd->lvl += distance; - if(mmd->lvl < 1) mmd->lvl = 1; - else if(mmd->lvl > mmd->totlvl) mmd->lvl = mmd->totlvl; - /* XXX: DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - object_handle_update(ob);*/ - return 1; - } + if(render) + return mmd->renderlvl; + else if(ob->mode == OB_MODE_SCULPT) + return mmd->sculptlvl; else - return 0; + return mmd->lvl; +} + +static void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl) +{ + mmd->totlvl = lvl; + + if(ob->mode != OB_MODE_SCULPT) { + mmd->lvl = MAX2(mmd->lvl, lvl); + CLAMP(mmd->lvl, 0, mmd->totlvl); + } + + mmd->sculptlvl = MAX2(mmd->sculptlvl, lvl); + CLAMP(mmd->sculptlvl, 0, mmd->totlvl); + + mmd->renderlvl = MAX2(mmd->renderlvl, lvl); + CLAMP(mmd->renderlvl, 0, mmd->totlvl); } /* XXX */ @@ -156,6 +171,8 @@ void multiresModifier_join(Object *ob) /* Returns 0 on success, 1 if the src's totvert doesn't match */ int multiresModifier_reshape(MultiresModifierData *mmd, Object *dst, Object *src) { + /* XXX */ +#if 0 Mesh *src_me = get_mesh(src); DerivedMesh *mrdm = dst->derivedFinal; @@ -172,319 +189,139 @@ int multiresModifier_reshape(MultiresModifierData *mmd, Object *dst, Object *src return 0; } +#endif return 1; } -static void Mat3FromColVecs(float mat[][3], float v1[3], float v2[3], float v3[3]) +static void column_vectors_to_mat3(float mat[][3], float v1[3], float v2[3], float v3[3]) { copy_v3_v3(mat[0], v1); copy_v3_v3(mat[1], v2); copy_v3_v3(mat[2], v3); } -static DerivedMesh *multires_subdisp_pre(DerivedMesh *mrdm, int distance, int simple) +static void multires_copy_grid(float (*gridA)[3], float (*gridB)[3], int sizeA, int sizeB) { - DerivedMesh *final; - SubsurfModifierData smd; + int x, y, j, skip; - memset(&smd, 0, sizeof(SubsurfModifierData)); - smd.levels = distance; - if(simple) - smd.subdivType = ME_SIMPLE_SUBSURF; + if(sizeA > sizeB) { + skip = (sizeA-1)/(sizeB-1); - final = NULL; // XXX subsurf_make_derived_from_derived_with_multires(mrdm, &smd, NULL, 0, NULL, 0, 0); + for(j = 0, y = 0; y < sizeB; y++) + for(x = 0; x < sizeB; x++, j++) + copy_v3_v3(gridA[y*skip*sizeA + x*skip], gridB[j]); + } + else { + skip = (sizeB-1)/(sizeA-1); - return final; + for(j = 0, y = 0; y < sizeA; y++) + for(x = 0; x < sizeA; x++, j++) + copy_v3_v3(gridA[j], gridB[y*skip*sizeB + x*skip]); + } } -static void VecAddUf(float a[3], float b[3]) +static void multires_copy_dm_grid(DMGridData *gridA, DMGridData *gridB, int sizeA, int sizeB) { - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; -} + int x, y, j, skip; -static void multires_subdisp(DerivedMesh *orig, Object *ob, DerivedMesh *final, int lvl, int totlvl, - int totsubvert, int totsubedge, int totsubface, int addverts) -{ - DerivedMesh *mrdm; - Mesh *me = ob->data; - MultiresModifierData mmd_sub; - MVert *mvs = CDDM_get_verts(final); - MVert *mvd, *mvd_f1, *mvs_f1, *mvd_f3, *mvd_f4; - MVert *mvd_f2, *mvs_f2, *mvs_e1, *mvd_e1, *mvs_e2; - int totvert; - int slo1 = multires_side_tot[lvl - 1]; - int sll = slo1 / 2; - int slo2 = multires_side_tot[totlvl - 2]; - int shi2 = multires_side_tot[totlvl - 1]; - int skip = multires_side_tot[totlvl - lvl] - 1; - int i, j, k; + if(sizeA > sizeB) { + skip = (sizeA-1)/(sizeB-1); - memset(&mmd_sub, 0, sizeof(MultiresModifierData)); - mmd_sub.lvl = mmd_sub.totlvl = totlvl; - mrdm = multires_dm_create_from_derived(&mmd_sub, 1, orig, ob, 0, 0); - - mvd = CDDM_get_verts(mrdm); - /* Need to map from ccg to mrdm */ - totvert = mrdm->getNumVerts(mrdm); - - if(!addverts) { - for(i = 0; i < totvert; ++i) { - float z[3] = {0,0,0}; - copy_v3_v3(mvd[i].co, z); - } + for(j = 0, y = 0; y < sizeB; y++) + for(x = 0; x < sizeB; x++, j++) + copy_v3_v3(gridA[y*skip*sizeA + x*skip].co, gridB[j].co); } + else { + skip = (sizeB-1)/(sizeA-1); - /* Load base verts */ - for(i = 0; i < me->totvert; ++i) - VecAddUf(mvd[totvert - me->totvert + i].co, mvs[totvert - me->totvert + i].co); - - mvd_f1 = mvd; - mvs_f1 = mvs; - mvd_f2 = mvd; - mvs_f2 = mvs + totvert - totsubvert; - mvs_e1 = mvs + totsubface * (skip-1) * (skip-1); - - for(i = 0; i < me->totface; ++i) { - const int end = me->mface[i].v4 ? 4 : 3; - int x, y, x2, y2, mov= 0; - - mvd_f1 += 1 + end * (slo2-2); //center+edgecross - mvd_f3 = mvd_f4 = mvd_f1; - - for(j = 0; j < end; ++j) { - mvd_f1 += (skip/2 - 1) * (slo2 - 2) + (skip/2 - 1); - /* Update sub faces */ - for(y = 0; y < sll; ++y) { - for(x = 0; x < sll; ++x) { - /* Face center */ - VecAddUf(mvd_f1->co, mvs_f1->co); - mvs_f1 += 1; - - /* Now we hold the center of the subface at mvd_f1 - and offset it to the edge cross and face verts */ - - /* Edge cross */ - for(k = 0; k < 4; ++k) { - if(k == 0) mov = -1; - else if(k == 1) mov = slo2 - 2; - else if(k == 2) mov = 1; - else if(k == 3) mov = -(slo2 - 2); - - for(x2 = 1; x2 < skip/2; ++x2) { - VecAddUf((mvd_f1 + mov * x2)->co, mvs_f1->co); - ++mvs_f1; - } - } - - /* Main face verts */ - for(k = 0; k < 4; ++k) { - int movx= 0, movy= 0; - - if(k == 0) { movx = -1; movy = -(slo2 - 2); } - else if(k == 1) { movx = slo2 - 2; movy = -1; } - else if(k == 2) { movx = 1; movy = slo2 - 2; } - else if(k == 3) { movx = -(slo2 - 2); movy = 1; } - - for(y2 = 1; y2 < skip/2; ++y2) { - for(x2 = 1; x2 < skip/2; ++x2) { - VecAddUf((mvd_f1 + movy * y2 + movx * x2)->co, mvs_f1->co); - ++mvs_f1; - } - } - } - - mvd_f1 += skip; - } - mvd_f1 += (skip - 1) * (slo2 - 2) - 1; - } - mvd_f1 -= (skip - 1) * (slo2 - 2) - 1 + skip; - mvd_f1 += (slo2 - 2) * (skip/2-1) + skip/2-1 + 1; - } - - /* update face center verts */ - VecAddUf(mvd_f2->co, mvs_f2->co); - - mvd_f2 += 1; - mvs_f2 += 1; - - /* update face edge verts */ - for(j = 0; j < end; ++j) { - MVert *restore; - - /* Super-face edge cross */ - for(k = 0; k < skip-1; ++k) { - VecAddUf(mvd_f2->co, mvs_e1->co); - mvd_f2++; - mvs_e1++; - } - for(x = 1; x < sll; ++x) { - VecAddUf(mvd_f2->co, mvs_f2->co); - mvd_f2++; - mvs_f2++; - - for(k = 0; k < skip-1; ++k) { - VecAddUf(mvd_f2->co, mvs_e1->co); - mvd_f2++; - mvs_e1++; - } - } - - restore = mvs_e1; - for(y = 0; y < sll - 1; ++y) { - for(x = 0; x < sll; ++x) { - for(k = 0; k < skip - 1; ++k) { - VecAddUf(mvd_f3[(skip-1)+(y*skip) + (x*skip+k)*(slo2-2)].co, - mvs_e1->co); - ++mvs_e1; - } - mvs_e1 += skip-1; - } - } - - mvs_e1 = restore + skip - 1; - for(y = 0; y < sll - 1; ++y) { - for(x = 0; x < sll; ++x) { - for(k = 0; k < skip - 1; ++k) { - VecAddUf(mvd_f3[(slo2-2)*(skip-1)+(x*skip)+k + y*skip*(slo2-2)].co, - mvs_e1->co); - ++mvs_e1; - } - mvs_e1 += skip - 1; - } - } - - mvd_f3 += (slo2-2)*(slo2-2); - mvs_e1 -= skip - 1; - } - - /* update base (2) face verts */ - for(j = 0; j < end; ++j) { - mvd_f2 += (slo2 - 1) * (skip - 1); - for(y = 0; y < sll - 1; ++y) { - for(x = 0; x < sll - 1; ++x) { - VecAddUf(mvd_f2->co, mvs_f2->co); - mvd_f2 += skip; - ++mvs_f2; - } - mvd_f2 += (slo2 - 1) * (skip - 1); - } - mvd_f2 -= (skip - 1); - } + for(j = 0, y = 0; y < sizeA; y++) + for(x = 0; x < sizeA; x++, j++) + copy_v3_v3(gridA[j].co, gridB[y*skip*sizeB + x*skip].co); } - - /* edges */ - mvd_e1 = mvd + totvert - me->totvert - me->totedge * (shi2-2); - mvs_e2 = mvs + totvert - me->totvert - me->totedge * (slo1-2); - for(i = 0; i < me->totedge; ++i) { - for(j = 0; j < skip - 1; ++j) { - VecAddUf(mvd_e1->co, mvs_e1->co); - mvd_e1++; - mvs_e1++; - } - for(j = 0; j < slo1 - 2; j++) { - VecAddUf(mvd_e1->co, mvs_e2->co); - mvd_e1++; - mvs_e2++; - - for(k = 0; k < skip - 1; ++k) { - VecAddUf(mvd_e1->co, mvs_e1->co); - mvd_e1++; - mvs_e1++; - } - } - } - - final->needsFree = 1; - final->release(final); - mrdm->needsFree = 1; - MultiresDM_mark_as_modified(mrdm); - mrdm->release(mrdm); } /* direction=1 for delete higher, direction=0 for lower (not implemented yet) */ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object *ob, int direction) { Mesh *me = get_mesh(ob); - int distance = mmd->totlvl - mmd->lvl; - MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + int lvl = multires_get_level(ob, mmd, 0); + int levels = mmd->totlvl - lvl; + MDisps *mdisps; + + // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); multires_force_update(ob); - if(mdisps && distance > 0 && direction == 1) { - int skip = multires_side_tot[distance] - 1; - int st = multires_side_tot[mmd->totlvl - 1]; - int totdisp = multires_quad_tot[mmd->lvl - 1]; - int i, j, x, y; + if(mdisps && levels > 0 && direction == 1) { + int nsize = multires_side_tot[lvl]; + int hsize = multires_side_tot[mmd->totlvl]; + int i; for(i = 0; i < me->totface; ++i) { - float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires del disps"); - - for(j = 0, y = 0; y < st; y += skip) { - for(x = 0; x < st; x += skip) { - copy_v3_v3(disps[j], mdisps[i].disps[y * st + x]); - ++j; - } + MDisps *mdisp= &mdisps[i]; + float (*disps)[3], (*ndisps)[3], (*hdisps)[3]; + int nvert = (me->mface[i].v4)? 4: 3; + int totdisp = multires_grid_tot[lvl]*nvert; + int S; + + disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + + ndisps = disps; + hdisps = mdisp->disps; + + for(S = 0; S < nvert; S++) { + multires_copy_grid(ndisps, hdisps, nsize, hsize); + + ndisps += nsize*nsize; + hdisps += hsize*hsize; } - MEM_freeN(mdisps[i].disps); - mdisps[i].disps = disps; - mdisps[i].totdisp = totdisp; + MEM_freeN(mdisp->disps); + mdisp->disps = disps; + mdisp->totdisp = totdisp; } } - mmd->totlvl = mmd->lvl; + multires_set_tot_level(ob, mmd, lvl); } -void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int distance, int updateblock, int simple) +static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple) +{ + MultiresModifierData mmd; + + memset(&mmd, 0, sizeof(MultiresModifierData)); + mmd.lvl = lvl; + mmd.sculptlvl = lvl; + mmd.renderlvl = lvl; + mmd.totlvl = totlvl; + mmd.simple = simple; + + return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0); +} + +static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple) +{ + SubsurfModifierData smd; + + memset(&smd, 0, sizeof(SubsurfModifierData)); + smd.levels = smd.renderLevels = lvl; + smd.flags |= eSubsurfModifierFlag_SubsurfUv; + if(simple) + smd.subdivType = ME_SIMPLE_SUBSURF; + + return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0); +} + +static void multires_reallocate_mdisps(Mesh *me, MDisps *mdisps, int lvl) { - DerivedMesh *final = NULL; - int totsubvert = 0, totsubface = 0, totsubedge = 0; - Mesh *me = get_mesh(ob); - MDisps *mdisps; int i; - if(distance == 0) - return; - - if(mmd->totlvl > multires_max_levels) - mmd->totlvl = multires_max_levels; - if(mmd->lvl > multires_max_levels) - mmd->lvl = multires_max_levels; - - multires_force_update(ob); - - mmd->lvl = mmd->totlvl; - mmd->totlvl += distance; - - mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); - if(!mdisps) - mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); - - if(mdisps->disps && !updateblock && mmd->totlvl > 2) { - DerivedMesh *orig, *mrdm; - MultiresModifierData mmd_sub; - - orig = CDDM_from_mesh(me, NULL); - memset(&mmd_sub, 0, sizeof(MultiresModifierData)); - mmd_sub.lvl = mmd_sub.totlvl = mmd->lvl; - mmd_sub.simple = simple; - mrdm = multires_dm_create_from_derived(&mmd_sub, 1, orig, ob, 0, 0); - totsubvert = mrdm->getNumVerts(mrdm); - totsubedge = mrdm->getNumEdges(mrdm); - totsubface = mrdm->getNumFaces(mrdm); - orig->needsFree = 1; - orig->release(orig); - - final = multires_subdisp_pre(mrdm, distance, simple); - mrdm->needsFree = 1; - mrdm->release(mrdm); - } - + /* reallocate displacements to be filled in */ for(i = 0; i < me->totface; ++i) { - const int totdisp = multires_quad_tot[mmd->totlvl - 1]; + int nvert = (me->mface[i].v4)? 4: 3; + int totdisp = multires_grid_tot[lvl]*nvert; float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); if(mdisps[i].disps) @@ -493,732 +330,353 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int dista mdisps[i].disps = disps; mdisps[i].totdisp = totdisp; } - - - if(final) { - DerivedMesh *orig; - - orig = CDDM_from_mesh(me, NULL); - - multires_subdisp(orig, ob, final, mmd->lvl, mmd->totlvl, totsubvert, totsubedge, totsubface, 0); - - orig->needsFree = 1; - orig->release(orig); - } - - mmd->lvl = mmd->totlvl; } -typedef struct DisplacerEdges { - /* DerivedMesh index at the start of each edge (using face x/y directions to define the start) */ - int base[4]; - /* 1 if edge moves in the positive x or y direction, -1 otherwise */ - int dir[4]; -} DisplacerEdges; - -typedef struct DisplacerSpill { - /* Index of face (in base mesh), -1 for none */ - int face; - - /* Spill flag */ - /* 1 = Negative variable axis */ - /* 2 = Near fixed axis */ - /* 4 = Flip axes */ - int f; - - /* Neighboring edges */ - DisplacerEdges edges; -} DisplacerSpill; - -typedef struct MultiresDisplacer { - Mesh *me; - MDisps *grid; - MFace *face; - - int dm_first_base_vert_index; - - int spacing; - int sidetot, interior_st, disp_st; - int sidendx; - int type; - int invert; - MVert *subco; - int subco_index, face_index; - float weight; - - /* Valence for each corner */ - int valence[4]; - - /* Neighboring edges for current face */ - DisplacerEdges edges_primary; - - /* Neighboring faces */ - DisplacerSpill spill_x, spill_y; - - int *face_offsets; - - int x, y, ax, ay; -} MultiresDisplacer; - -static int mface_v(MFace *f, int v) +void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple) { - return v == 0 ? f->v1 : v == 1 ? f->v2 : v == 2 ? f->v3 : v == 3 ? f->v4 : -1; -} + Mesh *me = ob->data; + MDisps *mdisps; + int lvl= mmd->totlvl; + int totlvl= mmd->totlvl+1; -/* Get the edges (and their directions) */ -static void find_displacer_edges(MultiresDisplacer *d, DerivedMesh *dm, DisplacerEdges *de, MFace *f) -{ - ListBase *emap = MultiresDM_get_vert_edge_map(dm); - IndexNode *n; - int i, end = f->v4 ? 4 : 3; - int offset = dm->getNumVerts(dm) - d->me->totvert - d->me->totedge * d->interior_st; + if(totlvl > multires_max_levels) + return; - for(i = 0; i < end; ++i) { - int vcur = mface_v(f, i); - int vnext = mface_v(f, i == end - 1 ? 0 : i + 1); + multires_force_update(ob); - de->dir[i] = 1; - - for(n = emap[vcur].first; n; n = n->next) { - MEdge *e = &d->me->medge[n->index]; - - if(e->v1 == vnext || e->v2 == vnext) { - de->base[i] = n->index * d->interior_st; - if(((i == 0 || i == 1) && e->v1 == vnext) || - ((i == 2 || i == 3) && e->v2 == vnext)) { - de->dir[i] = -1; - de->base[i] += d->interior_st - 1; - } - de->base[i] += offset; - break; - } + mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + if(!mdisps) + mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); + + if(mdisps->disps && !updateblock && totlvl > 1) { + /* upsample */ + DerivedMesh *lowdm, *cddm, *highdm; + DMGridData **highGridData, **lowGridData, **subGridData; + CCGSubSurf *ss; + int i, numGrids, highGridSize, lowGridSize; + + /* create subsurf DM from original mesh at high level */ + cddm = CDDM_from_mesh(me, NULL); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple); + + /* create multires DM from original mesh at low level */ + lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple); + cddm->release(cddm); + + /* copy subsurf grids and replace them with low displaced grids */ + numGrids = highdm->getNumGrids(highdm); + highGridSize = highdm->getGridSize(highdm); + highGridData = highdm->getGridData(highdm); + lowGridSize = lowdm->getGridSize(lowdm); + lowGridData = lowdm->getGridData(lowdm); + + subGridData = MEM_callocN(sizeof(float*)*numGrids, "subGridData*"); + + for(i = 0; i < numGrids; ++i) { + /* backup subsurf grids */ + subGridData[i] = MEM_callocN(sizeof(DMGridData)*highGridSize*highGridSize, "subGridData"); + memcpy(subGridData[i], highGridData[i], sizeof(DMGridData)*highGridSize*highGridSize); + + /* overwrite with current displaced grids */ + multires_copy_dm_grid(highGridData[i], lowGridData[i], highGridSize, lowGridSize); } - } -} -/* Returns in out the corners [0-3] that use v1 and v2 */ -static void find_face_corners(MFace *f, int v1, int v2, int out[2]) -{ - int i, end = f->v4 ? 4 : 3; + /* low lower level dm no longer needed at this point */ + lowdm->release(lowdm); - for(i = 0; i < end; ++i) { - int corner = mface_v(f, i); - if(corner == v1) - out[0] = i; - if(corner == v2) - out[1] = i; - } -} + /* subsurf higher levels again with displaced data */ + ss= ((CCGDerivedMesh*)highdm)->ss; + ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0); + ccgSubSurf_updateLevels(ss, lvl, NULL, 0); -static void multires_displacer_get_spill_faces(MultiresDisplacer *d, DerivedMesh *dm, MFace *mface) -{ - ListBase *map = MultiresDM_get_vert_face_map(dm); - IndexNode *n1, *n2; - int v4 = d->face->v4 ? d->face->v4 : d->face->v1; - int crn[2], lv; + /* reallocate displacements */ + multires_reallocate_mdisps(me, mdisps, totlvl); - memset(&d->spill_x, 0, sizeof(DisplacerSpill)); - memset(&d->spill_y, 0, sizeof(DisplacerSpill)); - d->spill_x.face = d->spill_y.face = -1; + /* compute displacements */ + multiresModifier_disp_run(highdm, me, 1, 0, subGridData, totlvl); - for(n1 = map[d->face->v3].first; n1; n1 = n1->next) { - if(n1->index == d->face_index) - continue; - - for(n2 = map[d->face->v2].first; n2; n2 = n2->next) { - if(n1->index == n2->index) - d->spill_x.face = n1->index; - } - for(n2 = map[v4].first; n2; n2 = n2->next) { - if(n1->index == n2->index) - d->spill_y.face = n1->index; - } - } - - if(d->spill_x.face != -1) { - /* Neighbor of v2/v3 found, find flip and orientation */ - find_face_corners(&mface[d->spill_x.face], d->face->v2, d->face->v3, crn); - lv = mface[d->spill_x.face].v4 ? 3 : 2; - - if(crn[0] == 0 && crn[1] == lv) - d->spill_x.f = 0+2+0; - else if(crn[0] == lv && crn[1] == 0) - d->spill_x.f = 1+2+0; - else if(crn[0] == 1 && crn[1] == 0) - d->spill_x.f = 1+2+4; - else if(crn[0] == 0 && crn[1] == 1) - d->spill_x.f = 0+2+4; - else if(crn[0] == 2 && crn[1] == 1) - d->spill_x.f = 1+0+0; - else if(crn[0] == 1 && crn[1] == 2) - d->spill_x.f = 0+0+0; - else if(crn[0] == 3 && crn[1] == 2) - d->spill_x.f = 0+0+4; - else if(crn[0] == 2 && crn[1] == 3) - d->spill_x.f = 1+0+4; - - find_displacer_edges(d, dm, &d->spill_x.edges, &mface[d->spill_x.face]); - } - - if(d->spill_y.face != -1) { - /* Neighbor of v3/v4 found, find flip and orientation */ - find_face_corners(&mface[d->spill_y.face], d->face->v3, v4, crn); - lv = mface[d->spill_y.face].v4 ? 3 : 2; - - if(crn[0] == 1 && crn[1] == 0) - d->spill_y.f = 1+2+0; - else if(crn[0] == 0 && crn[1] == 1) - d->spill_y.f = 0+2+0; - else if(crn[0] == 2 && crn[1] == 1) - d->spill_y.f = 1+0+4; - else if(crn[0] == 1 && crn[1] == 2) - d->spill_y.f = 0+0+4; - else if(crn[0] == 3 && crn[1] == 2) - d->spill_y.f = 0+0+0; - else if(crn[0] == 2 && crn[1] == 3) - d->spill_y.f = 1+0+0; - else if(crn[0] == 0 && crn[1] == lv) - d->spill_y.f = 0+2+4; - else if(crn[0] == lv && crn[1] == 0) - d->spill_y.f = 1+2+4; - - find_displacer_edges(d, dm, &d->spill_y.edges, &mface[d->spill_y.face]); - } -} - -static void find_corner_valences(MultiresDisplacer *d, DerivedMesh *dm) -{ - int i; - - d->valence[3] = -1; - - /* Set the vertex valence for the corners */ - for(i = 0; i < (d->face->v4 ? 4 : 3); ++i) - d->valence[i] = BLI_countlist(&MultiresDM_get_vert_edge_map(dm)[mface_v(d->face, i)]); -} - -static void multires_displacer_init(MultiresDisplacer *d, DerivedMesh *dm, - const int face_index, const int invert) -{ - Mesh *me = MultiresDM_get_mesh(dm); - - d->me = me; - d->face = me->mface + face_index; - d->face_index = face_index; - d->face_offsets = MultiresDM_get_face_offsets(dm); - /* Get the multires grid from customdata */ - d->grid = CustomData_get_layer(&me->fdata, CD_MDISPS); - if(d->grid) - d->grid += face_index; - - d->spacing = pow(2, MultiresDM_get_totlvl(dm) - MultiresDM_get_lvl(dm)); - d->sidetot = multires_side_tot[MultiresDM_get_lvl(dm) - 1]; - d->interior_st = d->sidetot - 2; - d->disp_st = multires_side_tot[MultiresDM_get_totlvl(dm) - 1]; - d->invert = invert; - - multires_displacer_get_spill_faces(d, dm, me->mface); - find_displacer_edges(d, dm, &d->edges_primary, d->face); - find_corner_valences(d, dm); - - d->dm_first_base_vert_index = dm->getNumVerts(dm) - me->totvert; -} - -static void multires_displacer_weight(MultiresDisplacer *d, const float w) -{ - d->weight = w; -} - -static void multires_displacer_anchor(MultiresDisplacer *d, const int type, const int side_index) -{ - d->sidendx = side_index; - d->x = d->y = d->sidetot / 2; - d->type = type; - - if(type == 2) { - if(side_index == 0) - d->y -= 1; - else if(side_index == 1) - d->x += 1; - else if(side_index == 2) - d->y += 1; - else if(side_index == 3) - d->x -= 1; - } - else if(type == 3) { - if(side_index == 0) { - d->x -= 1; - d->y -= 1; - } - else if(side_index == 1) { - d->x += 1; - d->y -= 1; - } - else if(side_index == 2) { - d->x += 1; - d->y += 1; - } - else if(side_index == 3) { - d->x -= 1; - d->y += 1; - } - } - - d->ax = d->x; - d->ay = d->y; -} - -static void multires_displacer_anchor_edge(MultiresDisplacer *d, int v1, int v2, int x) -{ - d->type = 4; - - if(v1 == d->face->v1) { - d->x = 0; - d->y = 0; - if(v2 == d->face->v2) - d->x += x; - else if(v2 == d->face->v3) { - if(x < d->sidetot / 2) - d->y = x; - else { - d->x = x; - d->y = d->sidetot - 1; - } - } - else - d->y += x; - } - else if(v1 == d->face->v2) { - d->x = d->sidetot - 1; - d->y = 0; - if(v2 == d->face->v1) - d->x -= x; - else - d->y += x; - } - else if(v1 == d->face->v3) { - d->x = d->sidetot - 1; - d->y = d->sidetot - 1; - if(v2 == d->face->v2) - d->y -= x; - else if(v2 == d->face->v1) { - if(x < d->sidetot / 2) - d->x -= x; - else { - d->x = 0; - d->y -= x; - } - } - else - d->x -= x; - } - else if(v1 == d->face->v4) { - d->x = 0; - d->y = d->sidetot - 1; - if(v2 == d->face->v3) - d->x += x; - else - d->y -= x; - } -} - -static void multires_displacer_anchor_vert(MultiresDisplacer *d, const int v) -{ - const int e = d->sidetot - 1; - - d->type = 5; - - d->x = d->y = 0; - if(v == d->face->v2) - d->x = e; - else if(v == d->face->v3) - d->x = d->y = e; - else if(v == d->face->v4) - d->y = e; -} - -static void multires_displacer_jump(MultiresDisplacer *d) -{ - if(d->sidendx == 0) { - d->x -= 1; - d->y = d->ay; - } - else if(d->sidendx == 1) { - d->x = d->ax; - d->y -= 1; - } - else if(d->sidendx == 2) { - d->x += 1; - d->y = d->ay; - } - else if(d->sidendx == 3) { - d->x = d->ax; - d->y += 1; - } -} - -/* Treating v1 as (0,0) and v3 as (st-1,st-1), - returns the index of the vertex at (x,y). - If x or y is >= st, wraps over to the adjacent face, - or if there is no adjacent face, returns -2. */ -static int multires_index_at_loc(int face_index, int x, int y, MultiresDisplacer *d, DisplacerEdges *de) -{ - int coord_edge = d->sidetot - 1; /* Max value of x/y at edge of grid */ - int mid = d->sidetot / 2; - int lim = mid - 1; - int qtot = lim * lim; - int base = d->face_offsets[face_index]; - - /* Edge spillover */ - if(x == d->sidetot || y == d->sidetot) { - int flags, v_axis, f_axis, lx, ly; - - if(x == d->sidetot && d->spill_x.face != -1) { - flags = d->spill_x.f; - - /* Handle triangle seam between v1 and v3 */ - if(!d->me->mface[d->spill_x.face].v4 && - ((flags == 2 && y >= mid) || (flags == 3 && y < mid))) - flags += 2; - - v_axis = (flags & 1) ? d->sidetot - 1 - y : y; - f_axis = (flags & 2) ? 1 : d->sidetot - 2; - lx = f_axis, ly = v_axis; - - if(flags & 4) { - lx = v_axis; - ly = f_axis; - } - - return multires_index_at_loc(d->spill_x.face, lx, ly, d, &d->spill_x.edges); - } - else if(y == d->sidetot && d->spill_y.face != -1) { - flags = d->spill_y.f; - - /* Handle triangle seam between v1 and v3 */ - if(!d->me->mface[d->spill_y.face].v4 && - ((flags == 6 && x >= mid) || (flags == 7 && x < mid))) - flags = ~flags; - - v_axis = (flags & 1) ? x : d->sidetot - 1 - x; - f_axis = (flags & 2) ? 1 : d->sidetot - 2; - lx = v_axis, ly = f_axis; - - if(flags & 4) { - lx = f_axis; - ly = v_axis; - } - - return multires_index_at_loc(d->spill_y.face, lx, ly, d, &d->spill_y.edges); - } - else - return -2; - } - /* Corners */ - else if(x == 0 && y == 0) - return d->dm_first_base_vert_index + d->face->v1; - else if(x == coord_edge && y == 0) - return d->dm_first_base_vert_index + d->face->v2; - else if(x == coord_edge && y == coord_edge) - return d->dm_first_base_vert_index + d->face->v3; - else if(x == 0 && y == coord_edge) - return d->dm_first_base_vert_index + d->face->v4; - /* Edges */ - else if(x == 0) { - if(d->face->v4) - return de->base[3] + de->dir[3] * (y - 1); - else - return de->base[2] + de->dir[2] * (y - 1); - } - else if(y == 0) - return de->base[0] + de->dir[0] * (x - 1); - else if(x == d->sidetot - 1) - return de->base[1] + de->dir[1] * (y - 1); - else if(y == d->sidetot - 1) - return de->base[2] + de->dir[2] * (x - 1); - /* Face center */ - else if(x == mid && y == mid) - return base; - /* Cross */ - else if(x == mid && y < mid) - return base + (mid - y); - else if(y == mid && x > mid) - return base + lim + (x - mid); - else if(x == mid && y > mid) - return base + lim*2 + (y - mid); - else if(y == mid && x < mid) { - if(d->face->v4) - return base + lim*3 + (mid - x); - else - return base + lim*2 + (mid - x); - } - /* Quarters */ - else { - int offset = base + lim * (d->face->v4 ? 4 : 3); - if(x < mid && y < mid) - return offset + ((mid - x - 1)*lim + (mid - y)); - else if(x > mid && y < mid) - return offset + qtot + ((mid - y - 1)*lim + (x - mid)); - else if(x > mid && y > mid) - return offset + qtot*2 + ((x - mid - 1)*lim + (y - mid)); - else if(x < mid && y > mid) - return offset + qtot*3 + ((y - mid - 1)*lim + (mid - x)); - } - - return -1; -} - -/* Calculate the TS matrix used for applying displacements. - Uses the undisplaced subdivided mesh's curvature to find a - smoothly normal and tangents. */ -static void calc_disp_mat(MultiresDisplacer *d, float mat[3][3]) -{ - int u = multires_index_at_loc(d->face_index, d->x + 1, d->y, d, &d->edges_primary); - int v = multires_index_at_loc(d->face_index, d->x, d->y + 1, d, &d->edges_primary); - float norm[3], t1[3], t2[3], inv[3][3]; - MVert *base = d->subco + d->subco_index; - - //printf("f=%d, x=%d, y=%d, i=%d, u=%d, v=%d ", d->face_index, d->x, d->y, d->subco_index, u, v); - - norm[0] = base->no[0] / 32767.0f; - norm[1] = base->no[1] / 32767.0f; - norm[2] = base->no[2] / 32767.0f; - - /* Special handling for vertices of valence 3 */ - if(d->valence[1] == 3 && d->x == d->sidetot - 1 && d->y == 0) - u = -1; - else if(d->valence[2] == 3 && d->x == d->sidetot - 1 && d->y == d->sidetot - 1) - u = v = -1; - else if(d->valence[3] == 3 && d->x == 0 && d->y == d->sidetot - 1) - v = -1; - - /* If either u or v is -2, it's on a boundary. In this - case, back up by one row/column and use the same - vector as the preceeding sub-edge. */ - - if(u < 0) { - u = multires_index_at_loc(d->face_index, d->x - 1, d->y, d, &d->edges_primary); - sub_v3_v3v3(t1, base->co, d->subco[u].co); - } - else - sub_v3_v3v3(t1, d->subco[u].co, base->co); - - if(v < 0) { - v = multires_index_at_loc(d->face_index, d->x, d->y - 1, d, &d->edges_primary); - sub_v3_v3v3(t2, base->co, d->subco[v].co); - } - else - sub_v3_v3v3(t2, d->subco[v].co, base->co); - - //printf("uu=%d, vv=%d\n", u, v); - - normalize_v3(t1); - normalize_v3(t2); - Mat3FromColVecs(mat, t1, t2, norm); - - if(d->invert) { - invert_m3_m3(inv, mat); - copy_m3_m3(mat, inv); - } -} - -static void multires_displace(MultiresDisplacer *d, float co[3]) -{ - float disp[3], mat[3][3]; - float *data; - MVert *subco = &d->subco[d->subco_index]; - - if(!d->grid || !d->grid->disps) return; - - data = d->grid->disps[(d->y * d->spacing) * d->disp_st + (d->x * d->spacing)]; - - if(d->invert) - sub_v3_v3v3(disp, co, subco->co); - else - copy_v3_v3(disp, data); - - - /* Apply ts matrix to displacement */ - calc_disp_mat(d, mat); - mul_m3_v3(mat, disp); - - if(d->invert) { - copy_v3_v3(data, disp); - + /* free */ + highdm->release(highdm); + for(i = 0; i < numGrids; ++i) + MEM_freeN(subGridData[i]); + MEM_freeN(subGridData); } else { - if(d->type == 4 || d->type == 5) - mul_v3_fl(disp, d->weight); - add_v3_v3v3(co, co, disp); + /* only reallocate, nothing to upsample */ + multires_reallocate_mdisps(me, mdisps, totlvl); } - if(d->type == 2) { - if(d->sidendx == 0) - d->y -= 1; - else if(d->sidendx == 1) - d->x += 1; - else if(d->sidendx == 2) - d->y += 1; - else if(d->sidendx == 3) - d->x -= 1; + multires_set_tot_level(ob, mmd, totlvl); +} + +static void grid_adjacent_rotate(int rotation, int gridSize, int *x, int *y) +{ + /* we rotate (rotation * 90°) counterclockwise around center */ + int nx, ny; + + switch(rotation) { + case 0: nx = *x; ny = *y; break; + case 1: nx = *y; ny = *x; break; + case 2: nx = *x; ny = *y; break; //gridSize - 1 - *x; ny = gridSize - 1 - *y; break; + case 3: nx = *y; ny = *x; break; } - else if(d->type == 3) { - if(d->sidendx == 0) - d->y -= 1; - else if(d->sidendx == 1) - d->x += 1; - else if(d->sidendx == 2) - d->y += 1; - else if(d->sidendx == 3) - d->x -= 1; + + *x = nx; + *y = ny; +} + +static void grid_adjacent_jump(DMGridAdjacency *adj, int gridSize, int *index, int *x, int *y) +{ + if(*x < 0) { + if(adj->index[3] == -1) { + /* no adjacent grid, clamp */ + *x = 0; + } + else { + /* jump to adjacent grid */ + *index = adj->index[3]; + *x += gridSize; + grid_adjacent_rotate(adj->rotation[3], gridSize, x, y); + } + } + else if(*x >= gridSize) { + if(adj->index[1] == -1) { + /* no adjacent grid, take a step back */ + *x = gridSize - 1; + } + else { + /* jump to adjacent grid */ + *index = adj->index[1]; + *x -= gridSize; + grid_adjacent_rotate(adj->rotation[1], gridSize, x, y); + } + } + else if(*y < 0) { + if(adj->index[0] == -1) { + /* no adjacent grid, clamp */ + *y = 0; + } + else { + /* jump to adjacent grid */ + *index = adj->index[0]; + *y += gridSize; + grid_adjacent_rotate(adj->rotation[0], gridSize, x, y); + } + } + else if(*y >= gridSize) { + if(adj->index[2] == -1) { + /* no adjacent grid, take a step back */ + *y = gridSize - 1; + } + else { + /* jump to adjacent grid */ + *index = adj->index[2]; + *y -= gridSize; + grid_adjacent_rotate(adj->rotation[2], gridSize, x, y); + } } } -static void multiresModifier_disp_run(DerivedMesh *dm, MVert *subco, int invert) +static void grid_tangent(DMGridAdjacency *adj, int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3]) { - const int lvl = MultiresDM_get_lvl(dm); - const int gridFaces = multires_side_tot[lvl - 2] - 1; - const int edgeSize = multires_side_tot[lvl - 1] - 1; - MVert *mvert = CDDM_get_verts(dm); - MEdge *medge = MultiresDM_get_mesh(dm)->medge; - MFace *mface = MultiresDM_get_mesh(dm)->mface; - ListBase *map = MultiresDM_get_vert_face_map(dm); - Mesh *me = MultiresDM_get_mesh(dm); - MultiresDisplacer d; - int i, S, x, y; + int jindex = index, jx = x, jy = y; - d.subco = subco; - d.subco_index = 0; + if(axis == 0) { + if(adj->index[1] == -1 && x == gridSize - 1) { + if(adj->index[2] == -1 && y == gridSize - 1) + sub_v3_v3v3(t, gridData[index][x + gridSize*(y - 1)].co, gridData[index][x - 1 + gridSize*(y - 1)].co); + else + sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x - 1 + gridSize*y].co); + } + else { + jx += 1; + grid_adjacent_jump(adj, gridSize, &jindex, &jx, &jy); + sub_v3_v3v3(t, gridData[jindex][jx + gridSize*jy].co, gridData[index][x + gridSize*y].co); + } + } + else if(axis == 1) { + if(adj->index[2] == -1 && y == gridSize - 1) { + if(adj->index[1] == -1 && x == gridSize - 1) { + sub_v3_v3v3(t, gridData[index][x - 1 + gridSize*y].co, gridData[index][x - 1 + gridSize*(y - 1)].co); + } + else { + sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x + gridSize*(y - 1)].co); + } + } + else { + jy += 1; + grid_adjacent_jump(adj, gridSize, &jindex, &jx, &jy); + sub_v3_v3v3(t, gridData[jindex][jx + gridSize*jy].co, gridData[index][x + gridSize*y].co); + } + } +} - for(i = 0; i < me->totface; ++i) { +static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl) +{ + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; + DMGridData **gridData, **subGridData; + DMGridAdjacency *gridAdjacency; + MFace *mface = me->mface; + MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + int i, S, x, y, numGrids, gIndex, gridSize, dGridSize, dSkip; + + numGrids = dm->getNumGrids(dm); + gridSize = dm->getGridSize(dm); + gridData = dm->getGridData(dm); + gridAdjacency = dm->getGridAdjacency(dm); + subGridData = (oldGridData)? oldGridData: gridData; + + dGridSize = multires_side_tot[totlvl]; + dSkip = (dGridSize-1)/(gridSize-1); + + for(gIndex = 0, i = 0; i < me->totface; ++i) { const int numVerts = mface[i].v4 ? 4 : 3; - - /* Center */ - multires_displacer_init(&d, dm, i, invert); - multires_displacer_anchor(&d, 1, 0); - multires_displace(&d, mvert->co); - ++mvert; - ++d.subco_index; + MDisps *mdisp = &mdisps[i]; - /* Cross */ - for(S = 0; S < numVerts; ++S) { - multires_displacer_anchor(&d, 2, S); - for(x = 1; x < gridFaces; ++x) { - multires_displace(&d, mvert->co); - ++mvert; - ++d.subco_index; - } - } + for(S = 0; S < numVerts; ++S, ++gIndex) { + DMGridData *grid = gridData[gIndex]; + DMGridData *subgrid = subGridData[gIndex]; + DMGridAdjacency *adj = &gridAdjacency[gIndex]; + float (*dispgrid)[3] = &mdisp->disps[S*dGridSize*dGridSize]; - /* Quarters */ - for(S = 0; S < numVerts; S++) { - multires_displacer_anchor(&d, 3, S); - for(y = 1; y < gridFaces; y++) { - for(x = 1; x < gridFaces; x++) { - multires_displace(&d, mvert->co); - ++mvert; - ++d.subco_index; - } - multires_displacer_jump(&d); - } - } - } + for(y = 0; y < gridSize; y++) { + for(x = 0; x < gridSize; x++) { + float *co = grid[x + y*gridSize].co; + float *sco = subgrid[x + y*gridSize].co; + float *no = subgrid[x + y*gridSize].no; + float *data = dispgrid[dGridSize*y*dSkip + x*dSkip]; + float mat[3][3], tx[3], ty[3], disp[3], d[3]; - for(i = 0; i < me->totedge; ++i) { - const MEdge *e = &medge[i]; - for(x = 1; x < edgeSize; ++x) { - IndexNode *n1, *n2; - int numFaces = 0; - for(n1 = map[e->v1].first; n1; n1 = n1->next) { - for(n2 = map[e->v2].first; n2; n2 = n2->next) { - if(n1->index == n2->index) - ++numFaces; - } - } - multires_displacer_weight(&d, 1.0f / numFaces); - /* TODO: Better to have these loops outside the x loop */ - for(n1 = map[e->v1].first; n1; n1 = n1->next) { - for(n2 = map[e->v2].first; n2; n2 = n2->next) { - if(n1->index == n2->index) { - multires_displacer_init(&d, dm, n1->index, invert); - multires_displacer_anchor_edge(&d, e->v1, e->v2, x); - multires_displace(&d, mvert->co); + /* construct tangent space matrix */ + grid_tangent(adj, gridSize, gIndex, x, y, 0, subGridData, tx); + normalize_v3(tx); + + grid_tangent(adj, gridSize, gIndex, x, y, 1, subGridData, ty); + normalize_v3(ty); + + column_vectors_to_mat3(mat, tx, ty, no); + + if(!invert) { + /* convert to object space and add */ + mul_v3_m3v3(disp, mat, data); + add_v3_v3v3(co, sco, disp); + } + else if(!add) { + /* convert difference to tangent space */ + sub_v3_v3v3(disp, co, sco); + invert_m3(mat); + mul_v3_m3v3(data, mat, disp); + } + else { + /* convert difference to tangent space */ + invert_m3(mat); + mul_v3_m3v3(d, mat, co); + add_v3_v3(data, d); } } } - ++mvert; - ++d.subco_index; } } - - for(i = 0; i < me->totvert; ++i) { - IndexNode *n; - multires_displacer_weight(&d, 1.0f / BLI_countlist(&map[i])); - for(n = map[i].first; n; n = n->next) { - multires_displacer_init(&d, dm, n->index, invert); - multires_displacer_anchor_vert(&d, i); - multires_displace(&d, mvert->co); - } - ++mvert; - ++d.subco_index; - } - if(!invert) - CDDM_calc_normals(dm); + if(!invert) { + ccgSubSurf_stitchFaces(ccgdm->ss, 0, NULL, 0); + ccgSubSurf_updateNormals(ccgdm->ss, NULL, 0); + } } static void multiresModifier_update(DerivedMesh *dm) { + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; Object *ob; Mesh *me; MDisps *mdisps; + MultiresModifierData *mmd; - ob = MultiresDM_get_object(dm); - me = MultiresDM_get_mesh(dm); + ob = ccgdm->multires.ob; + me = ccgdm->multires.ob->data; + mmd = ccgdm->multires.mmd; + // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); if(mdisps) { - const int lvl = MultiresDM_get_lvl(dm); - const int totlvl = MultiresDM_get_totlvl(dm); + int lvl = ccgdm->multires.lvl; + int totlvl = ccgdm->multires.totlvl; if(lvl < totlvl) { - /* Propagate disps upwards */ - DerivedMesh *final, *subco_dm, *orig; - MVert *verts_new = NULL, *cur_lvl_orig_verts = NULL; - MultiresModifierData mmd; - int i; + Mesh *me = ob->data; + DerivedMesh *lowdm, *cddm, *highdm; + DMGridData **highGridData, **lowGridData, **subGridData, **gridData, *diffGrid; + CCGSubSurf *ss; + int i, j, numGrids, highGridSize, lowGridSize; - orig = CDDM_from_mesh(me, NULL); - - /* Regenerate the current level's vertex coordinates - (includes older displacements but not new sculpts) */ - mmd.totlvl = totlvl; - mmd.lvl = lvl; - subco_dm = multires_dm_create_from_derived(&mmd, 1, orig, ob, 0, 0); - cur_lvl_orig_verts = CDDM_get_verts(subco_dm); + /* create subsurf DM from original mesh at high level */ + cddm = CDDM_from_mesh(me, NULL); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple); - /* Subtract the original vertex cos from the new vertex cos */ - verts_new = CDDM_get_verts(dm); - for(i = 0; i < dm->getNumVerts(dm); ++i) - sub_v3_v3v3(verts_new[i].co, verts_new[i].co, cur_lvl_orig_verts[i].co); + /* create multires DM from original mesh and displacements */ + lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple); + cddm->release(cddm); - final = multires_subdisp_pre(dm, totlvl - lvl, 0); + /* gather grid data */ + numGrids = highdm->getNumGrids(highdm); + highGridSize = highdm->getGridSize(highdm); + highGridData = highdm->getGridData(highdm); + lowGridSize = lowdm->getGridSize(lowdm); + lowGridData = lowdm->getGridData(lowdm); + gridData = dm->getGridData(dm); - multires_subdisp(orig, ob, final, lvl, totlvl, dm->getNumVerts(dm), dm->getNumEdges(dm), - dm->getNumFaces(dm), 1); + subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*"); + diffGrid = MEM_callocN(sizeof(DMGridData)*lowGridSize*lowGridSize, "diff"); - subco_dm->release(subco_dm); - orig->release(orig); + for(i = 0; i < numGrids; ++i) { + /* backup subsurf grids */ + subGridData[i] = MEM_callocN(sizeof(DMGridData)*highGridSize*highGridSize, "subGridData"); + memcpy(subGridData[i], highGridData[i], sizeof(DMGridData)*highGridSize*highGridSize); + + /* write difference of subsurf and displaced low level into high subsurf */ + for(j = 0; j < lowGridSize*lowGridSize; ++j) + sub_v3_v3v3(diffGrid[j].co, gridData[i][j].co, lowGridData[i][j].co); + + multires_copy_dm_grid(highGridData[i], diffGrid, highGridSize, lowGridSize); + } + + /* lower level dm no longer needed at this point */ + MEM_freeN(diffGrid); + lowdm->release(lowdm); + + /* subsurf higher levels again with difference of coordinates */ + ss= ((CCGDerivedMesh*)highdm)->ss; + ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0); + ccgSubSurf_updateLevels(ss, lvl, NULL, 0); + + /* add to displacements */ + multiresModifier_disp_run(highdm, me, 1, 1, subGridData, mmd->totlvl); + + /* free */ + highdm->release(highdm); + for(i = 0; i < numGrids; ++i) + MEM_freeN(subGridData[i]); + MEM_freeN(subGridData); + } + else { + DerivedMesh *cddm, *subdm; + + cddm = CDDM_from_mesh(me, NULL); + subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple); + cddm->release(cddm); + + multiresModifier_disp_run(dm, me, 1, 0, subdm->getGridData(subdm), mmd->totlvl); + + subdm->release(subdm); } - else - multiresModifier_disp_run(dm, MultiresDM_get_subco(dm), 1); } } void multires_mark_as_modified(struct Object *ob) { if(ob && ob->derivedFinal) { - MultiresDM_mark_as_modified(ob->derivedFinal); + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)ob->derivedFinal; + ccgdm->multires.modified = 1; } } @@ -1234,24 +692,47 @@ void multires_force_update(Object *ob) struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob, int useRenderParams, int isFinalCalc) { - SubsurfModifierData smd; - MultiresSubsurf ms; + //Mesh *me= ob->data; DerivedMesh *result; - int i; + CCGDerivedMesh *ccgdm; + DMGridData **gridData, **subGridData; + int lvl= multires_get_level(ob, mmd, useRenderParams); + int i, gridSize, numGrids; - ms.mmd = mmd; - ms.ob = ob; - ms.local_mmd = local_mmd; + if(lvl == 0) + return dm; - memset(&smd, 0, sizeof(SubsurfModifierData)); - smd.levels = smd.renderLevels = mmd->lvl - 1; - smd.flags |= eSubsurfModifierFlag_SubsurfUv; + result = subsurf_dm_create_local(ob, dm, lvl, 0); - result = NULL; // XXX subsurf_make_derived_from_derived_with_multires(dm, &smd, &ms, useRenderParams, NULL, isFinalCalc, 0); - for(i = 0; i < result->getNumVerts(result); ++i) - MultiresDM_get_subco(result)[i] = CDDM_get_verts(result)[i]; - multiresModifier_disp_run(result, MultiresDM_get_subco(result), 0); - MultiresDM_set_update(result, multiresModifier_update); + if(!local_mmd) { + ccgdm = (CCGDerivedMesh*)result; + + ccgdm->multires.ob = ob; + ccgdm->multires.mmd = mmd; + ccgdm->multires.local_mmd = local_mmd; + ccgdm->multires.lvl = lvl; + ccgdm->multires.totlvl = mmd->totlvl; + ccgdm->multires.modified = 0; + ccgdm->multires.update = multiresModifier_update; + } + + numGrids = result->getNumGrids(result); + gridSize = result->getGridSize(result); + gridData = result->getGridData(result); + + subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*"); + + for(i = 0; i < numGrids; i++) { + subGridData[i] = MEM_callocN(sizeof(DMGridData)*gridSize*gridSize, "subGridData"); + memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize); + } + + // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl); + + for(i = 0; i < numGrids; i++) + MEM_freeN(subGridData[i]); + MEM_freeN(subGridData); return result; } @@ -1425,9 +906,9 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) MultiresLevel *lvl, *lvl1; MVert *vsrc, *vdst; int src, dst; - int totlvl = MultiresDM_get_totlvl(dm); - int st = multires_side_tot[totlvl - 2] - 1; - int extedgelen = multires_side_tot[totlvl - 1] - 2; + int totlvl = 2; // XXX MultiresDM_get_totlvl(dm); + int st = multires_side_tot[totlvl - 1] - 1; + int extedgelen = multires_side_tot[totlvl] - 2; int *vvmap; // inorder for dst, map to src int crossedgelen; int i, j, s, x, totvert, tottri, totquad; @@ -1454,9 +935,9 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) lvl = lvl1->next; for(j = 2; j <= mr->level_count; ++j) { - int base = multires_side_tot[totlvl - j] - 2; - int skip = multires_side_tot[totlvl - j + 1] - 1; - int st = multires_side_tot[j - 2] - 1; + int base = multires_side_tot[totlvl - j + 1] - 2; + int skip = multires_side_tot[totlvl - j + 2] - 1; + int st = multires_side_tot[j - 1] - 1; for(x = 0; x < st; ++x) vvmap[ldst + base + x * skip] = lsrc + st * i + x; @@ -1483,7 +964,7 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) /* Face edge cross */ tottri = totquad = 0; - crossedgelen = multires_side_tot[totlvl - 2] - 2; + crossedgelen = multires_side_tot[totlvl - 1] - 2; dst = 0; for(i = 0; i < lvl1->totface; ++i) { int sides = lvl1->faces[i].v[3] ? 4 : 3; @@ -1492,8 +973,8 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) ++dst; for(j = 3; j <= mr->level_count; ++j) { - int base = multires_side_tot[totlvl - j] - 2; - int skip = multires_side_tot[totlvl - j + 1] - 1; + int base = multires_side_tot[totlvl - j + 1] - 2; + int skip = multires_side_tot[totlvl - j + 2] - 1; int st = pow(2, j - 2); int st2 = pow(2, j - 3); int lsrc = lvl->prev->totvert; @@ -1541,8 +1022,8 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) int ldst = dst + 1 + sides * (st - 1); for(s = 0; s < sides; ++s) { - int st2 = multires_side_tot[totlvl - 2] - 2; - int st3 = multires_side_tot[totlvl - 3] - 2; + int st2 = multires_side_tot[totlvl - 1] - 2; + int st3 = multires_side_tot[totlvl - 2] - 2; int st4 = st3 == 0 ? 1 : (st3 + 1) / 2; int mid = ldst + st2 * st3 + st3; int cv = lvl1->faces[j].v[s]; @@ -1583,3 +1064,4 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) MEM_freeN(vvmap); } + diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 1fa9090ba45..a9ceb77ad9f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3922,12 +3922,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) SWITCH_INT(mmd->dynverts[a]) } } - else if (md->type==eModifierType_Multires) { - MultiresModifierData *mmd = (MultiresModifierData*) md; - - mmd->undo_verts = newdataadr(fd, mmd->undo_verts); - mmd->undo_signal = !!mmd->undo_verts; - } } } @@ -9595,7 +9589,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ToolSettings *ts; //PTCacheID *pid; //ListBase pidlist; - int i, a; + int /*i, */a; for(ob = main->object.first; ob; ob = ob->id.next) { //BKE_ptcache_ids_from_object(&pidlist, ob); @@ -9613,6 +9607,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ob->data = me; if(me && me->id.lib==NULL && me->mr) { /* XXX - library meshes crash on loading most yoFrankie levels, the multires pointer gets invalid - Campbell */ + // XXX +#if 0 MultiresLevel *lvl; ModifierData *md; MultiresModifierData *mmd; @@ -9648,7 +9644,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires); BLI_insertlinkbefore(&ob->modifiers, md, mmd); - multiresModifier_subdivide(mmd, ob, me->mr->level_count - 1, 1, 0); + for(i = 0; i < me->mr->level_count - 1; ++i) + multiresModifier_subdivide(mmd, ob, 1, 0); mmd->lvl = mmd->totlvl; orig = CDDM_from_mesh(me, NULL); @@ -9662,6 +9659,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* Remove the old multires */ multires_free(me->mr); +#endif me->mr = NULL; } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index b2147221f9f..b00cd10c6a7 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1214,12 +1214,6 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->dyninfluences); writedata(wd, DATA, sizeof(int)*mmd->totvert, mmd->dynverts); } - else if (md->type==eModifierType_Multires) { - MultiresModifierData *mmd = (MultiresModifierData*) md; - - if(mmd->undo_verts) - writestruct(wd, DATA, "MVert", mmd->undo_verts_tot, mmd->undo_verts); - } } } diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index c4304056017..9da7fa94295 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -373,7 +373,7 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tesselated/bevel vertices"); - if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) { + if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md, 0))) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); return 0; } @@ -684,6 +684,13 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot) /************* multires delete higher levels operator ****************/ +static int multires_poll(bContext *C) +{ + PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier); + ID *id= ptr.id.data; + return (ptr.data && id && !id->lib); +} + static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op) { PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier); @@ -702,8 +709,8 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot) { ot->name= "Delete Higher Levels"; ot->idname= "OBJECT_OT_multires_higher_levels_delete"; - ot->poll= ED_operator_object_active; + ot->poll= multires_poll; ot->exec= multires_higher_levels_delete_exec; /* flags */ @@ -718,7 +725,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) Object *ob= ptr.id.data; MultiresModifierData *mmd= ptr.data; - multiresModifier_subdivide(mmd, ob, 1, 0, mmd->simple); + multiresModifier_subdivide(mmd, ob, 0, mmd->simple); DAG_id_flush_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index c9e351458ad..82893b48af0 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2027,13 +2027,13 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); - //MultiresModifierData *mmd = sculpt_multires_active(ob); + MultiresModifierData *mmd = sculpt_multires_active(ob); if(ob->mode & OB_MODE_SCULPT) { multires_force_update(ob); - /*if(mmd && mmd->sculptlvl != mmd->lvl) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA);*/ + if(mmd && mmd->sculptlvl != mmd->lvl) + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* Leave sculptmode */ ob->mode &= ~OB_MODE_SCULPT; @@ -2044,8 +2044,8 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *op) /* Enter sculptmode */ ob->mode |= OB_MODE_SCULPT; - /*if(mmd && mmd->sculptlvl != mmd->lvl) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA);*/ + if(mmd && mmd->sculptlvl != mmd->lvl) + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* Create persistent sculpt mode data */ if(!ts->sculpt) diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index fe6a5b050e3..d6e7992d435 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -581,12 +581,8 @@ typedef struct ExplodeModifierData { typedef struct MultiresModifierData { ModifierData modifier; - struct MVert *undo_verts; /* Store DerivedMesh vertices for multires undo */ - int undo_verts_tot; /* Length of undo_verts array */ - char undo_signal; /* If true, signals to replace verts with undo verts */ - - char lvl, totlvl; - char simple; + char lvl, sculptlvl, renderlvl, totlvl; + char simple, pad[3]; } MultiresModifierData; typedef struct FluidsimModifierData { diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 93972894ef1..689599c5cdf 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -39,6 +39,7 @@ #include "BKE_animsys.h" #include "BKE_bmesh.h" /* For BevelModifierData */ +#include "BKE_global.h" #include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */ #include "WM_api.h" @@ -335,10 +336,36 @@ static void rna_MultiresModifier_level_range(PointerRNA *ptr, int *min, int *max { MultiresModifierData *mmd = (MultiresModifierData*)ptr->data; - *min = 1; + *min = 0; *max = mmd->totlvl; } +/*static int rna_MultiresModifier_external_get(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + Mesh *me= ob->data; + + return CustomData_external_test(&me->fdata, CD_MDISPS); +} + +static void rna_MultiresModifier_external_set(PointerRNA *ptr, int value) +{ + Object *ob= (Object*)ptr->id.data; + Mesh *me= ob->data; + + if(CustomData_external_test(&me->fdata, CD_MDISPS) && !value) + CustomData_external_remove(&me->fdata, CD_MDISPS, me->totface); + else if(!CustomData_external_test(&me->fdata, CD_MDISPS) && value) + CustomData_external_add(&me->fdata, CD_MDISPS, me->id.name+2, me->totface); +} + +static int rna_MultiresModifier_external_editable(PointerRNA *ptr) +{ + MultiresModifierData *mmd = ptr->data; + + return (G.save_over && mmd->totlvl > 0); +}*/ + static void modifier_object_set(Object *self, Object **ob_p, int type, PointerRNA value) { Object *ob= value.data; @@ -487,17 +514,15 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) rna_def_property_subdivision_common(srna, "subdivType"); - prop= RNA_def_property(srna, "levels", PROP_INT, PROP_NONE); + prop= RNA_def_property(srna, "levels", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "levels"); - RNA_def_property_range(prop, 1, 6); - RNA_def_property_ui_range(prop, 1, 6, 1, 0); + RNA_def_property_ui_range(prop, 0, 6, 1, 0); RNA_def_property_ui_text(prop, "Levels", "Number of subdivisions to perform."); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop= RNA_def_property(srna, "render_levels", PROP_INT, PROP_NONE); + prop= RNA_def_property(srna, "render_levels", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "renderLevels"); - RNA_def_property_range(prop, 1, 6); - RNA_def_property_ui_range(prop, 1, 6, 1, 0); + RNA_def_property_ui_range(prop, 0, 6, 1, 0); RNA_def_property_ui_text(prop, "Render Levels", "Number of subdivisions to perform when rendering."); prop= RNA_def_property(srna, "optimal_draw", PROP_BOOLEAN, PROP_NONE); @@ -523,11 +548,32 @@ static void rna_def_modifier_multires(BlenderRNA *brna) rna_def_property_subdivision_common(srna, "simple"); - prop= RNA_def_property(srna, "level", PROP_INT, PROP_NONE); + prop= RNA_def_property(srna, "levels", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "lvl"); - RNA_def_property_ui_text(prop, "Level", ""); + RNA_def_property_ui_text(prop, "Levels", "Number of subdivisions to use in the viewport."); RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MultiresModifier_level_range"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "sculpt_levels", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "sculptlvl"); + RNA_def_property_ui_text(prop, "Sculpt Levels", "Number of subdivisions to use in sculpt mode."); + RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MultiresModifier_level_range"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "render_levels", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "renderlvl"); + RNA_def_property_ui_text(prop, "Render Levels", ""); + RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MultiresModifier_level_range"); + + prop= RNA_def_property(srna, "total_levels", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "totlvl"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Total Levels", "Number of subdivisions for which displacements are stored."); + + /*prop= RNA_def_property(srna, "external", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_MultiresModifier_external_get", "rna_MultiresModifier_external_set"); + RNA_def_property_editable_func(prop, "rna_MultiresModifier_external_editable"); + RNA_def_property_ui_text(prop, "External", "Store multires displacements outside the .blend file, to save memory.");*/ } static void rna_def_modifier_lattice(BlenderRNA *brna)