diff options
author | Nicholas Bishop <nicholasbishop@gmail.com> | 2009-01-06 21:59:03 +0300 |
---|---|---|
committer | Nicholas Bishop <nicholasbishop@gmail.com> | 2009-01-06 21:59:03 +0300 |
commit | 25e5765f47979484065c18eb1af010a8f23ddcf3 (patch) | |
tree | f07aeb5d5d066a5cd77c7f8c2386f0002c0a468d /source | |
parent | 02003021a6abff3b7afee5ccd390c6d7a7ae336b (diff) |
Got rid of old multires code, brought in multires modifier from
soc-2008-nicholasbishop branch.
Note: any old code with multires_test() or multires_level1_test() can
just be deleted, not needed by the multires modifier.
Diffstat (limited to 'source')
27 files changed, 2189 insertions, 1854 deletions
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 64221897680..8ee1d15d0f3 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -27,42 +27,58 @@ * ***** END GPL LICENSE BLOCK ***** */ -struct CustomData; -struct EditMesh; -struct Multires; -struct MultiresLevel; +struct DerivedMesh; struct Mesh; +struct MFace; +struct MultiresModifierData; struct Object; -/* Level access */ -struct MultiresLevel *current_level(struct Multires *mr); -struct MultiresLevel *multires_level_n(struct Multires *mr, int n); +typedef struct MultiresSubsurf { + struct MultiresModifierData *mmd; + struct Mesh *me; +} MultiresSubsurf; + +typedef struct IndexNode { + struct IndexNode *next, *prev; + int index; +} IndexNode; + +void create_vert_face_map(ListBase **map, IndexNode **mem, const struct MFace *mface, + const int totvert, const int totface); +void create_vert_edge_map(ListBase **map, IndexNode **mem, const struct MEdge *medge, + const int totvert, const int totedge); -/* Level control */ -void multires_add_level(struct Object *ob, struct Mesh *me, const char subdiv_type); -void multires_set_level(struct Object *ob, struct Mesh *me, const int render); -void multires_free_level(struct MultiresLevel *lvl); +/* MultiresDM */ +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*)); +int *MultiresDM_get_flags(struct DerivedMesh *); -void multires_edge_level_update(struct Object *ob, struct Mesh *me); +#define MULTIRES_DM_UPDATE_BLOCK 1 +#define MULTIRES_DM_UPDATE_ALWAYS 2 -void multires_free(struct Multires *mr); -struct Multires *multires_copy(struct Multires *orig); -void multires_create(struct Object *ob, struct Mesh *me); +void multires_force_update(struct Object *ob); -/* CustomData */ -void multires_delete_layer(struct Object *ob, struct CustomData *cd, const int type, int n); -void multires_add_layer(struct Object *ob, struct CustomData *cd, const int type, const int n); -void multires_del_lower_customdata(struct Multires *mr, struct MultiresLevel *cr_lvl); -void multires_to_mcol(struct MultiresColFace *f, MCol mcol[4]); -/* After adding or removing vcolor layers, run this */ -void multires_load_cols(struct Mesh *me); +struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*, struct DerivedMesh*, + struct Mesh *, int, int); -/* Private (used in multires-firstlevel.c) */ -void multires_level_to_mesh(struct Object *ob, struct Mesh *me, const int render); -void multires_update_levels(struct Mesh *me, const int render); -void multires_update_first_level(struct Mesh *me, struct EditMesh *em); -void multires_update_customdata(struct MultiresLevel *lvl1, struct EditMesh *em, struct CustomData *src, - struct CustomData *dst, const int type); -void multires_customdata_to_mesh(struct Mesh *me, struct EditMesh *em, - struct MultiresLevel *lvl, struct CustomData *src, - struct CustomData *dst, const int type); +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, + int updateblock, int simple); +void multiresModifier_setLevel(void *mmd_v, void *ob_v); +int multiresModifier_reshape(struct MultiresModifierData *mmd, struct Object *dst, struct Object *src); + +/* Related to the old multires */ +struct Multires; +void multires_load_old(struct DerivedMesh *, struct Multires *); +void multires_free(struct Multires*); diff --git a/source/blender/blenkernel/BKE_sculpt.h b/source/blender/blenkernel/BKE_sculpt.h index 5d7ed28f561..ec66fca6f38 100644 --- a/source/blender/blenkernel/BKE_sculpt.h +++ b/source/blender/blenkernel/BKE_sculpt.h @@ -30,6 +30,8 @@ #ifndef BKE_SCULPT_H #define BKE_SCULPT_H +struct MFace; +struct MVert; struct NumInput; struct RadialControl; struct Scene; @@ -40,6 +42,13 @@ typedef struct SculptSession { struct ProjVert *projverts; struct bglMats *mats; + + int multires; + int totvert; + int totface; + struct MVert *mvert; + struct MFace *mface; + float *face_normals; /* An array of lists; array is sized as large as the number of verts in the mesh, diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index c3c6b8d9edd..f6dc22f650a 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -32,6 +32,7 @@ struct Mesh; struct Object; struct DerivedMesh; struct EditMesh; +struct MultiresSubsurf; struct SubsurfModifierData; struct DerivedMesh *subsurf_make_derived_from_derived( @@ -40,6 +41,13 @@ struct DerivedMesh *subsurf_make_derived_from_derived( int useRenderParams, float (*vertCos)[3], int isFinalCalc, int editMode); +struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( + struct DerivedMesh *dm, + struct SubsurfModifierData *smd, + struct MultiresSubsurf *ms, + int useRenderParams, float (*vertCos)[3], + int isFinalCalc, int editMode); + void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]); #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index f056d1fa61b..2c8a013c5ee 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -71,7 +71,6 @@ #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_mesh.h" -#include "BKE_multires.h" #include "BKE_object.h" #include "BKE_subsurf.h" #include "BKE_texture.h" @@ -83,8 +82,6 @@ #include "BIF_gl.h" #include "BIF_glutil.h" -//XXX #include "multires.h" -// #include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_material.h" @@ -1448,6 +1445,9 @@ CustomDataMask get_viewedit_datamask() if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT) mask |= CD_MASK_MCOL; + if(G.f & G_SCULPTMODE) + mask |= CD_MASK_MDISPS; + return mask; #endif return 0; @@ -2210,93 +2210,11 @@ DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask da return ob->derivedDeform; } -/* Move to multires Pin level, returns a copy of the original vertex coords. */ -float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl) -{ - float *vert_copy= NULL; - - if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) { - MultiresLevel *lvl= NULL; - int i; - - /* Make sure all mesh edits are properly stored in the multires data*/ - //XXX multires_update_levels(me, 1); - - /* Copy the highest level of multires verts */ - *orig_lvl= me->mr->current; - //XXX lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels)); - vert_copy= MEM_callocN(sizeof(float)*3*lvl->totvert, "multires vert_copy"); - for(i=0; i<lvl->totvert; ++i) - VecCopyf(&vert_copy[i*3], me->mr->verts[i].co); - - /* Goto the pin level for multires */ - me->mr->newlvl= me->mr->pinlvl; - //XXX multires_set_level(ob, me, 1); - } - - return vert_copy; -} - -/* Propagate the changes to render level - fails if mesh topology changed */ -void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy, - const int orig_lvl, CustomDataMask dataMask) -{ - if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) { - if((*dm)->getNumVerts(*dm) == me->totvert && - (*dm)->getNumFaces(*dm) == me->totface) { - //XXX MultiresLevel *lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels)); - DerivedMesh *old= NULL; - MVert *vertdup= NULL; - int i; - - /* Copy the verts into the mesh */ - vertdup= (*dm)->dupVertArray(*dm); - (*dm)->release(*dm); - for(i=0; i<me->totvert; ++i) - me->mvert[i]= vertdup[i]; - /* Free vertdup after use*/ - MEM_freeN(vertdup); - /* Go to the render level */ - me->mr->newlvl= me->mr->renderlvl; - //XXX multires_set_level(ob, me, 1); - (*dm)= getMeshDerivedMesh(me, ob, NULL); - - /* Some of the data in dm is referenced externally, so make a copy */ - old= *dm; - (*dm)= CDDM_copy(old); - old->release(old); - - if(dataMask & CD_MASK_ORCO) - add_orco_dm(ob, NULL, *dm, NULL); - - /* Restore the original verts */ - me->mr->newlvl= BLI_countlist(&me->mr->levels); - //XXX multires_set_level(ob, me, 1); - //XXX for(i=0; i<lvl->totvert; ++i) - //XXX VecCopyf(me->mvert[i].co, &vert_copy[i*3]); - } - - if(vert_copy) - MEM_freeN(vert_copy); - - me->mr->newlvl= orig_lvl; - //XXX multires_set_level(ob, me, 1); - } -} - -/* Multires note - if mesh has multires enabled, mesh is first set to the Pin level, - where all modifiers are applied, then if the topology hasn't changed, the changes - from modifiers are propagated up to the Render level. */ DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask dataMask) { DerivedMesh *final; - Mesh *me= get_mesh(ob); - float *vert_copy= NULL; - int orig_lvl= 0; - vert_copy= multires_render_pin(ob, me, &orig_lvl); mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1); - multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); return final; } @@ -2304,13 +2222,8 @@ DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index) { DerivedMesh *final; - Mesh *me= get_mesh(ob); - float *vert_copy= NULL; - int orig_lvl= 0; - vert_copy= multires_render_pin(ob, me, &orig_lvl); mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index); - multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); return final; } @@ -2339,13 +2252,8 @@ DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob, CustomDataMask dataMask) { DerivedMesh *final; - Mesh *me= get_mesh(ob); - float *vert_copy= NULL; - int orig_lvl= 0; - vert_copy= multires_render_pin(ob, me, &orig_lvl); mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1); - multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); return final; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index aca25237337..538e65bfdc9 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -42,6 +42,7 @@ #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_mesh.h" +#include "BKE_multires.h" #include "BKE_utildefines.h" #include "BLI_arithb.h" @@ -52,6 +53,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_fluidsim.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -64,6 +66,7 @@ #include <string.h> #include <limits.h> +#include <math.h> typedef struct { DerivedMesh dm; @@ -885,6 +888,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) { CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm"); DerivedMesh *dm = &cddm->dm; + CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS); int i, *index, alloctype; /* this does a referenced copy, the only new layers being ORIGINDEX, @@ -900,11 +904,11 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) alloctype= CD_REFERENCE; - CustomData_merge(&mesh->vdata, &dm->vertData, CD_MASK_MESH, alloctype, + CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype, mesh->totvert); - CustomData_merge(&mesh->edata, &dm->edgeData, CD_MASK_MESH, alloctype, + CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype, mesh->totedge); - CustomData_merge(&mesh->fdata, &dm->faceData, CD_MASK_MESH, alloctype, + CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype, mesh->totface); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); @@ -1282,3 +1286,192 @@ MFace *CDDM_get_faces(DerivedMesh *dm) return ((CDDerivedMesh*)dm)->mface; } +/* Multires DerivedMesh, extends CDDM */ +typedef struct MultiresDM { + CDDerivedMesh cddm; + + MultiresModifierData *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; + + Mesh *me; + int flags; + + 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->flags & MULTIRES_DM_UPDATE_BLOCK)) + 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(cd->data == mrdm->mmd->undo_verts) + cd->flag |= CD_FLAG_NOFREE; + } + + if(DM_release(dm)) { + 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->me = ms->me; + + 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) + VecCopyf(mrdm->orco[i], mvert[i].co); + } + else + DM_init(dm, numVerts, numEdges, 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->flags = 0; + + dm->release = MultiresDM_release; + + return dm; +} + +Mesh *MultiresDM_get_mesh(DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->me; +} + +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; + + if(!mrdm->vert_face_map) + create_vert_face_map(&mrdm->vert_face_map, &mrdm->vert_face_map_mem, mrdm->me->mface, + mrdm->me->totvert, mrdm->me->totface); + + return mrdm->vert_face_map; +} + +ListBase *MultiresDM_get_vert_edge_map(DerivedMesh *dm) +{ + MultiresDM *mrdm = (MultiresDM*)dm; + + if(!mrdm->vert_edge_map) + create_vert_edge_map(&mrdm->vert_edge_map, &mrdm->vert_edge_map_mem, mrdm->me->medge, + mrdm->me->totvert, mrdm->me->totedge); + + return mrdm->vert_edge_map; +} + +int *MultiresDM_get_face_offsets(DerivedMesh *dm) +{ + MultiresDM *mrdm = (MultiresDM*)dm; + 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) * mrdm->me->totface, "mrdm face offsets"); + for(i = 0; i < mrdm->me->totface; ++i) { + mrdm->face_offsets[i] = accum; + + accum += (mrdm->me->mface[i].v4 ? q : t); + } + } + + return mrdm->face_offsets; +} + +int *MultiresDM_get_flags(DerivedMesh *dm) +{ + return &((MultiresDM*)dm)->flags; +} diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 05271aa59a7..d9f76256529 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -34,6 +34,7 @@ #include "BKE_customdata.h" +#include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_mempool.h" @@ -44,6 +45,7 @@ #include "MEM_guardedalloc.h" +#include <math.h> #include <string.h> /* number of layers to add when growing a CustomData object */ @@ -378,6 +380,156 @@ static void layerDefault_origspace_face(void *data, int count) for(i = 0; i < count; i++) osf[i] = default_osf; } + +/* Adapted from sculptmode.c */ +static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) +{ + int x, y, x2, y2; + const int st_max = st - 1; + float urat, vrat, uopp; + float d[4][3], d2[2][3]; + + if(u < 0) + u = 0; + else if(u >= st) + u = st_max; + if(v < 0) + v = 0; + else if(v >= st) + v = st_max; + + x = floor(u); + y = floor(v); + x2 = x + 1; + y2 = y + 1; + + if(x2 >= st) x2 = st_max; + if(y2 >= st) y2 = st_max; + + urat = u - x; + vrat = v - y; + uopp = 1 - urat; + + VecCopyf(d[0], disps[y * st + x]); + VecCopyf(d[1], disps[y * st + x2]); + VecCopyf(d[2], disps[y2 * st + x]); + VecCopyf(d[3], disps[y2 * st + x2]); + VecMulf(d[0], uopp); + VecMulf(d[1], urat); + VecMulf(d[2], uopp); + VecMulf(d[3], urat); + + VecAddf(d2[0], d[0], d[1]); + VecAddf(d2[1], d[2], d[3]); + VecMulf(d2[0], 1 - vrat); + VecMulf(d2[1], vrat); + + VecAddf(out, d2[0], d2[1]); +} + +static void layerSwap_mdisps(void *data, int *ci) +{ + MDisps *s = data; + float (*d)[3] = NULL; + int x, y, st; + + if(!(ci[0] == 2 && ci[1] == 3 && ci[2] == 0 && ci[3] == 1)) return; + + d = MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); + st = sqrt(s->totdisp); + + for(y = 0; y < st; ++y) { + for(x = 0; x < st; ++x) { + VecCopyf(d[(st - y - 1) * st + (st - x - 1)], s->disps[y * st + x]); + } + } + + if(s->disps) + MEM_freeN(s->disps); + s->disps = d; +} + +static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights, + int count, void *dest) +{ + MDisps *d = dest; + MDisps *s = NULL; + int st, stl; + int i, x, y; + float crn[4][2]; + float (*sw)[4] = NULL; + + /* Initialize the destination */ + for(i = 0; i < d->totdisp; ++i) { + float z[3] = {0,0,0}; + VecCopyf(d->disps[i], z); + } + + /* For now, some restrictions on the input */ + if(count != 1 || !sub_weights) return; + + st = sqrt(d->totdisp); + stl = st - 1; + + sw = (void*)sub_weights; + for(i = 0; i < 4; ++i) { + crn[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3]; + crn[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3]; + } + + s = sources[0]; + for(y = 0; y < st; ++y) { + for(x = 0; x < st; ++x) { + /* One suspects this code could be cleaner. */ + float xl = (float)x / (st - 1); + float yl = (float)y / (st - 1); + float mid1[2] = {crn[0][0] * (1 - xl) + crn[1][0] * xl, + crn[0][1] * (1 - xl) + crn[1][1] * xl}; + float mid2[2] = {crn[3][0] * (1 - xl) + crn[2][0] * xl, + crn[3][1] * (1 - xl) + crn[2][1] * xl}; + float mid3[2] = {mid1[0] * (1 - yl) + mid2[0] * yl, + mid1[1] * (1 - yl) + mid2[1] * yl}; + + float srcdisp[3]; + + mdisps_bilinear(srcdisp, s->disps, st, mid3[0], mid3[1]); + VecCopyf(d->disps[y * st + x], srcdisp); + } + } +} + +static void layerCopy_mdisps(const void *source, void *dest, int count) +{ + int i; + const MDisps *s = source; + MDisps *d = dest; + + for(i = 0; i < count; ++i) { + if(s[i].disps) { + d[i].disps = MEM_dupallocN(s[i].disps); + d[i].totdisp = s[i].totdisp; + } + else { + d[i].disps = NULL; + d[i].totdisp = 0; + } + + } +} + +static void layerFree_mdisps(void *data, int count, int size) +{ + int i; + MDisps *d = data; + + for(i = 0; i < count; ++i) { + if(d[i].disps) + MEM_freeN(d[i].disps); + d[i].disps = NULL; + d[i].totdisp = 0; + } +} + /* --------- */ static void layerDefault_mloopcol(void *data, int count) @@ -553,23 +705,26 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, - {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL} + {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL} }; const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty", - "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent"}; + "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", + "CDMloopCol", "CDTangent", "CDMDisps"}; const CustomDataMask CD_MASK_BAREMESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE; const CustomDataMask CD_MASK_MESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | - CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; + CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; const CustomDataMask CD_MASK_EDITMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | - CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; + CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 3f35e70114a..7ba8fb47740 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -56,7 +56,6 @@ #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_mesh.h" -#include "BKE_multires.h" #include "BKE_subsurf.h" #include "BKE_displist.h" #include "BKE_library.h" @@ -137,8 +136,6 @@ void free_mesh(Mesh *me) if(me->bb) MEM_freeN(me->bb); if(me->mselect) MEM_freeN(me->mselect); if(me->edit_mesh) MEM_freeN(me->edit_mesh); - - if(me->mr) multires_free(me->mr); } void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount) @@ -222,9 +219,6 @@ Mesh *copy_mesh(Mesh *me) } } - if(me->mr) - men->mr= multires_copy(me->mr); - men->mselect= NULL; men->bb= MEM_dupallocN(men->bb); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index b4e683afeb8..737361c34c4 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -86,6 +86,7 @@ #include "BKE_displist.h" #include "BKE_fluidsim.h" #include "BKE_global.h" +#include "BKE_multires.h" #include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_material.h" @@ -6173,7 +6174,6 @@ static void particleSystemModifier_deformVerts( DerivedMesh *dm = derivedData; ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; ParticleSystem * psys=0; - Mesh *me; int needsFree=0; if(ob->particlesystem.first) @@ -6181,14 +6181,6 @@ static void particleSystemModifier_deformVerts( else return; - /* multires check */ - if(ob->type == OB_MESH) { - me= (Mesh*)ob->data; - if(me->mr && me->mr->current != 1) - modifier_setError(md, - "Particles only supported on first multires level."); - } - if(!psys_check_enabled(ob, psys)) return; @@ -7738,6 +7730,58 @@ static void meshdeformModifier_deformVertsEM( dm->release(dm); } +/* Multires */ +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); +} + +static void multiresModifier_copyData(ModifierData *md, ModifierData *target) +{ + MultiresModifierData *mmd = (MultiresModifierData*) md; + MultiresModifierData *tmmd = (MultiresModifierData*) target; + + tmmd->totlvl = mmd->totlvl; + tmmd->lvl = mmd->lvl; +} + +static DerivedMesh *multiresModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, + int useRenderParams, int isFinalCalc) +{ + MultiresModifierData *mmd = (MultiresModifierData*)md; + Mesh *me = get_mesh(ob); + DerivedMesh *final; + + /* TODO: for now just skip a level1 mesh */ + if(mmd->lvl == 1) + return dm; + + final = multires_dm_create_from_derived(mmd, dm, me, 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) { + VecCopyf(dst[i].co, mmd->undo_verts[i].co); + } + CDDM_calc_normals(final); + + MEM_freeN(mmd->undo_verts); + mmd->undo_signal = 0; + mmd->undo_verts = NULL; + } + + return final; +} /* Shrinkwrap */ @@ -8338,6 +8382,14 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->foreachObjectLink = simpledeformModifier_foreachObjectLink; mti->updateDepgraph = simpledeformModifier_updateDepgraph; + mti = INIT_TYPE(Multires); + 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; + typeArrInit = 0; #undef INIT_TYPE } diff --git a/source/blender/blenkernel/intern/multires-firstlevel.c b/source/blender/blenkernel/intern/multires-firstlevel.c deleted file mode 100644 index 30bb8c9c28d..00000000000 --- a/source/blender/blenkernel/intern/multires-firstlevel.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2006 by Nicholas Bishop - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - * - * Deals with the first-level data in multires (edge flags, weights, and UVs) - * - * multires.h - * - */ - -#include "DNA_customdata_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - -//XXX #include "BIF_editmesh.h" - -#include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_mesh.h" -#include "BKE_multires.h" - -#include "BLI_editVert.h" - -#include "MEM_guardedalloc.h" - -#include <string.h> - -MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl); -MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl); -void multires_update_edge_flags(Mesh *me, EditMesh *em); -void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease); - -/*********** Generic ***********/ - -CustomDataMask cdmask(const int type) -{ - if(type == CD_MDEFORMVERT) - return CD_MASK_MDEFORMVERT; - else if(type == CD_MTFACE) - return CD_MASK_MTFACE; - return -1; -} - -char type_ok(const int type) -{ - return (type == CD_MDEFORMVERT) || (type == CD_MTFACE); -} - -/* Copy vdata or fdata from Mesh or EditMesh to Multires. */ -void multires_update_customdata(MultiresLevel *lvl1, EditMesh *em, CustomData *src, CustomData *dst, const int type) -{ - if(src && dst && type_ok(type)) { - const int tot= (type == CD_MDEFORMVERT ? lvl1->totvert : lvl1->totface); - int i; - - CustomData_free(dst, tot); - - if(CustomData_has_layer(src, type)) { - if(em) { - EditVert *eve= em->verts.first; - EditFace *efa= em->faces.first; - CustomData_copy(src, dst, cdmask(type), CD_CALLOC, tot); - for(i=0; i<tot; ++i) { - if(type == CD_MDEFORMVERT) { - CustomData_from_em_block(&em->vdata, dst, eve->data, i); - eve= eve->next; - } - else if(type == CD_MTFACE) { - CustomData_from_em_block(&em->fdata, dst, efa->data, i); - efa= efa->next; - } - } - } - else - CustomData_copy(src, dst, cdmask(type), CD_DUPLICATE, tot); - } - } -} - -/* Uses subdivide_dverts or subdivide_mtfaces to subdivide src to match lvl_end. Does not free src. */ -void *subdivide_customdata_to_level(void *src, MultiresLevel *lvl_start, - MultiresLevel *lvl_end, const int type) -{ - if(src && lvl_start && lvl_end && type_ok(type)) { - MultiresLevel *lvl; - void *cr_data= NULL, *pr_data= NULL; - - pr_data= src; - for(lvl= lvl_start; lvl && lvl != lvl_end; lvl= lvl->next) { - if(type == CD_MDEFORMVERT) - cr_data= subdivide_dverts(pr_data, lvl); - else if(type == CD_MTFACE) - cr_data= subdivide_mtfaces(pr_data, lvl); - - /* Free previous subdivision level's data */ - if(lvl != lvl_start) { - if(type == CD_MDEFORMVERT) - free_dverts(pr_data, lvl->totvert); - else if(type == CD_MTFACE) - MEM_freeN(pr_data); - } - - pr_data= cr_data; - cr_data= NULL; - } - - return pr_data; - } - - return NULL; -} - -/* Directly copy src into dst (handles both Mesh and EditMesh) */ -void customdata_to_mesh(Mesh *me, EditMesh *em, CustomData *src, CustomData *dst, const int tot, const int type) -{ - if(me && me->mr && src && dst && type_ok(type)) { - if(em) { - int i; - EditVert *eve= em->verts.first; - EditFace *efa= em->faces.first; - CustomData_copy(src, dst, cdmask(type), CD_CALLOC, 0); - - for(i=0; i<tot; ++i) { - if(type == CD_MDEFORMVERT) { - CustomData_to_em_block(src, dst, i, &eve->data); - eve= eve->next; - } - else if(type == CD_MTFACE) { - CustomData_to_em_block(src, dst, i, &efa->data); - efa= efa->next; - } - } - } else { - CustomData_merge(src, dst, cdmask(type), CD_DUPLICATE, tot); - } - } -} - -/* Subdivide vdata or fdata from Multires into either Mesh or EditMesh. */ -void multires_customdata_to_mesh(Mesh *me, EditMesh *em, MultiresLevel *lvl, CustomData *src, - CustomData *dst, const int type) -{ - if(me && me->mr && lvl && src && dst && type_ok(type) && - CustomData_has_layer(src, type)) { - const int tot= (type == CD_MDEFORMVERT ? lvl->totvert : lvl->totface); - if(lvl == me->mr->levels.first) { - customdata_to_mesh(me, em, src, dst, tot, type); - } - else { - CustomData cdf; - const int count = CustomData_number_of_layers(src, type); - int i; - - /* Construct a new CustomData containing the subdivided data */ - CustomData_copy(src, &cdf, cdmask(type), CD_ASSIGN, tot); - for(i=0; i<count; ++i) { - void *layer= CustomData_get_layer_n(&cdf, type, i); - CustomData_set_layer_n(&cdf, type, i, - subdivide_customdata_to_level(layer, me->mr->levels.first, lvl, type)); - } - - customdata_to_mesh(me, em, &cdf, dst, tot, type); - CustomData_free(&cdf, tot); - } - } -} - -/* Subdivide the first-level customdata up to cr_lvl, then delete the original data */ -void multires_del_lower_customdata(Multires *mr, MultiresLevel *cr_lvl) -{ - MultiresLevel *lvl1= mr->levels.first; - MDeformVert *dverts= NULL; - CustomData cdf; - int i; - - /* dverts */ - dverts= subdivide_customdata_to_level(CustomData_get(&mr->vdata, 0, CD_MDEFORMVERT), - lvl1, cr_lvl, CD_MDEFORMVERT); - if(dverts) { - CustomData_free_layers(&mr->vdata, CD_MDEFORMVERT, lvl1->totvert); - CustomData_add_layer(&mr->vdata, CD_MDEFORMVERT, CD_ASSIGN, dverts, cr_lvl->totvert); - } - - /* mtfaces */ - CustomData_copy(&mr->fdata, &cdf, CD_MASK_MTFACE, CD_ASSIGN, cr_lvl->totface); - for(i=0; i<CustomData_number_of_layers(&mr->fdata, CD_MTFACE); ++i) { - MTFace *mtfaces= - subdivide_customdata_to_level(CustomData_get_layer_n(&mr->fdata, CD_MTFACE, i), - lvl1, cr_lvl, CD_MTFACE); - if(mtfaces) - CustomData_set_layer_n(&cdf, CD_MTFACE, i, mtfaces); - } - - CustomData_free(&mr->fdata, lvl1->totface); - mr->fdata= cdf; -} - -/* Update all special first-level data, if the first-level is active */ -void multires_update_first_level(Mesh *me, EditMesh *em) -{ - if(me && me->mr && me->mr->current == 1) { - multires_update_customdata(me->mr->levels.first, em, em ? &em->vdata : &me->vdata, - &me->mr->vdata, CD_MDEFORMVERT); - multires_update_customdata(me->mr->levels.first, em, em ? &em->fdata : &me->fdata, - &me->mr->fdata, CD_MTFACE); - multires_update_edge_flags(me, em); - } -} - -/*********** Multires.edge_flags ***********/ -void multires_update_edge_flags(Mesh *me, EditMesh *em) -{ - MultiresLevel *lvl= me->mr->levels.first; - EditEdge *eed= NULL; - int i; - - if(em) eed= em->edges.first; - for(i=0; i<lvl->totedge; ++i) { - if(em) { - me->mr->edge_flags[i]= 0; - eed_to_medge_flag(eed, &me->mr->edge_flags[i], &me->mr->edge_creases[i]); - eed= eed->next; - } - else { - me->mr->edge_flags[i]= me->medge[i].flag; - me->mr->edge_creases[i]= me->medge[i].crease; - } - } -} - - - -/*********** Multires.vdata ***********/ - -/* MDeformVert */ - -/* Add each weight from in to out. Scale each weight by w. */ -void multires_add_dvert(MDeformVert *out, const MDeformVert *in, const float w) -{ - if(out && in) { - int i, j; - char found; - - for(i=0; i<in->totweight; ++i) { - found= 0; - for(j=0; j<out->totweight; ++j) { - if(out->dw[j].def_nr==in->dw[i].def_nr) { - out->dw[j].weight += in->dw[i].weight * w; - found= 1; - } - } - if(!found) { - MDeformWeight *newdw= MEM_callocN(sizeof(MDeformWeight)*(out->totweight+1), - "multires dvert"); - if(out->dw) { - memcpy(newdw, out->dw, sizeof(MDeformWeight)*out->totweight); - MEM_freeN(out->dw); - } - - out->dw= newdw; - out->dw[out->totweight].weight= in->dw[i].weight * w; - out->dw[out->totweight].def_nr= in->dw[i].def_nr; - - ++out->totweight; - } - } - } -} - -/* Takes an input array of dverts and subdivides them (linear) using the topology of lvl */ -MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl) -{ - if(lvl && lvl->next) { - MDeformVert *out = MEM_callocN(sizeof(MDeformVert)*lvl->next->totvert, "dvert prop array"); - int i, j; - - /* Copy lower level */ - for(i=0; i<lvl->totvert; ++i) - multires_add_dvert(&out[i], &src[i], 1); - /* Edge verts */ - for(i=0; i<lvl->totedge; ++i) { - for(j=0; j<2; ++j) - multires_add_dvert(&out[lvl->totvert+i], &src[lvl->edges[i].v[j]],0.5); - } - - /* Face verts */ - for(i=0; i<lvl->totface; ++i) { - for(j=0; j<(lvl->faces[i].v[3]?4:3); ++j) - multires_add_dvert(&out[lvl->totvert + lvl->totedge + i], - &src[lvl->faces[i].v[j]], - lvl->faces[i].v[3]?0.25:(1.0f/3.0f)); - } - - return out; - } - - return NULL; -} - - - -/*********** Multires.fdata ***********/ - -/* MTFace */ - -void multires_uv_avg2(float out[2], const float a[2], const float b[2]) -{ - int i; - for(i=0; i<2; ++i) - out[i] = (a[i] + b[i]) / 2.0f; -} - -/* Takes an input array of mtfaces and subdivides them (linear) using the topology of lvl */ -MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl) -{ - if(lvl && lvl->next) { - MTFace *out= MEM_callocN(sizeof(MultiresColFace)*lvl->next->totface,"Multirescolfaces"); - int i, j, curf; - - for(i=0, curf=0; i<lvl->totface; ++i) { - const char sides= lvl->faces[i].v[3]?4:3; - float cntr[2]= {0, 0}; - - /* Find average uv coord of the current face */ - for(j=0; j<sides; ++j) { - cntr[0]+= src[i].uv[j][0]; - cntr[1]+= src[i].uv[j][1]; - } - cntr[0]/= sides; - cntr[1]/= sides; - - for(j=0; j<sides; ++j, ++curf) { - out[curf]= src[i]; - - multires_uv_avg2(out[curf].uv[0], src[i].uv[j], src[i].uv[j==0?sides-1:j-1]); - - out[curf].uv[1][0]= src[i].uv[j][0]; - out[curf].uv[1][1]= src[i].uv[j][1]; - - multires_uv_avg2(out[curf].uv[2], src[i].uv[j], src[i].uv[j==sides-1?0:j+1]); - - out[curf].uv[3][0]= cntr[0]; - out[curf].uv[3][1]= cntr[1]; - } - } - - return out; - } - - return NULL; -} - -void multires_delete_layer(Object *ob, CustomData *cd, const int type, int n) -{ - Mesh *me= ob->data; - - if(me && me->mr && cd) { - MultiresLevel *lvl1= me->mr->levels.first; - - multires_update_levels(me, 0); - - CustomData_set_layer_active(cd, type, n); - CustomData_free_layer_active(cd, type, lvl1->totface); - - multires_level_to_mesh(ob, me, 0); - } -} - -void multires_add_layer(Object *ob, CustomData *cd, const int type, const int n) -{ - Mesh *me= ob->data; - - if(me && me->mr && cd) { - multires_update_levels(me, 0); - - if(CustomData_has_layer(cd, type)) - CustomData_add_layer(cd, type, CD_DUPLICATE, CustomData_get_layer(cd, type), - current_level(me->mr)->totface); - else - CustomData_add_layer(cd, type, CD_DEFAULT, NULL, current_level(me->mr)->totface); - - CustomData_set_layer_active(cd, type, n); - multires_level_to_mesh(ob, me, 0); - } -} diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 7b9711f48de..1227dcdded3 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -32,1276 +32,1567 @@ #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" -#include "DNA_vec_types.h" +#include "DNA_scene_types.h" +#include "DNA_view3d_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" -#include "BLI_editVert.h" +#include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_multires.h" - -//XXX #include "editmesh.h" +#include "BKE_object.h" +#include "BKE_subsurf.h" #include <math.h> +#include <string.h> -/* Returns the active multires level (currently applied to the mesh) */ -MultiresLevel *current_level(Multires *mr) +void create_vert_face_map(ListBase **map, IndexNode **mem, const MFace *mface, const int totvert, const int totface) { - return BLI_findlink(&mr->levels, mr->current - 1); + int i,j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem"); + node = *mem; + + /* Find the users */ + for(i = 0; i < totface; ++i){ + for(j = 0; j < (mface[i].v4?4:3); ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[((unsigned int*)(&mface[i]))[j]], node); + } + } } -/* Returns the nth multires level, starting at 1 */ -MultiresLevel *multires_level_n(Multires *mr, int n) +void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, const int totvert, const int totedge) { - if(mr) - return BLI_findlink(&mr->levels, n - 1); - else - return NULL; + int i, j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totedge * 2, "vert edge map mem"); + node = *mem; + + /* Find the users */ + for(i = 0; i < totedge; ++i){ + for(j = 0; j < 2; ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[((unsigned int*)(&medge[i].v1))[j]], node); + } + } } -/* Free and clear the temporary connectivity data */ -static void multires_free_temp_data(MultiresLevel *lvl) +/* 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}; + +int multiresModifier_switch_level(Object *ob, const int distance) { - if(lvl) { - if(lvl->edge_boundary_states) MEM_freeN(lvl->edge_boundary_states); - if(lvl->vert_edge_map) MEM_freeN(lvl->vert_edge_map); - if(lvl->vert_face_map) MEM_freeN(lvl->vert_face_map); - if(lvl->map_mem) MEM_freeN(lvl->map_mem); - - lvl->edge_boundary_states = NULL; - lvl->vert_edge_map = lvl->vert_face_map = NULL; - lvl->map_mem = NULL; + ModifierData *md = NULL; + MultiresModifierData *mmd = NULL; + + for(md = ob->modifiers.first; md; md = md->next) { + if(md->type == eModifierType_Multires) + mmd = (MultiresModifierData*)md; } -} -/* Does not actually free lvl itself */ -void multires_free_level(MultiresLevel *lvl) -{ - if(lvl) { - if(lvl->faces) MEM_freeN(lvl->faces); - if(lvl->edges) MEM_freeN(lvl->edges); - if(lvl->colfaces) MEM_freeN(lvl->colfaces); - - multires_free_temp_data(lvl); + if(mmd) { + mmd->lvl += distance; + if(mmd->lvl < 1) mmd->lvl = 1; + else if(mmd->lvl > mmd->totlvl) mmd->lvl = mmd->totlvl; + /* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + object_handle_update(ob);*/ + return 1; } + else + return 0; } -void multires_free(Multires *mr) +/* XXX */ +#if 0 +void multiresModifier_join(Object *ob) { - if(mr) { - MultiresLevel* lvl= mr->levels.first; - - /* Free the first-level data */ - if(lvl) { - CustomData_free(&mr->vdata, lvl->totvert); - CustomData_free(&mr->fdata, lvl->totface); - MEM_freeN(mr->edge_flags); - MEM_freeN(mr->edge_creases); + Base *base = NULL; + int highest_lvl = 0; + + /* First find the highest level of subdivision */ + base = FIRSTBASE; + while(base) { + if(TESTBASELIB_BGMODE(base) && base->object->type==OB_MESH) { + ModifierData *md; + for(md = base->object->modifiers.first; md; md = md->next) { + if(md->type == eModifierType_Multires) { + int totlvl = ((MultiresModifierData*)md)->totlvl; + if(totlvl > highest_lvl) + highest_lvl = totlvl; + + /* Ensure that all updates are processed */ + multires_force_update(base->object); + } + } } + base = base->next; + } - while(lvl) { - multires_free_level(lvl); - lvl= lvl->next; - } + /* No multires meshes selected */ + if(highest_lvl == 0) + return; - MEM_freeN(mr->verts); + /* Subdivide all the displacements to the highest level */ + base = FIRSTBASE; + while(base) { + if(TESTBASELIB_BGMODE(base) && base->object->type==OB_MESH) { + ModifierData *md = NULL; + MultiresModifierData *mmd = NULL; - BLI_freelistN(&mr->levels); + for(md = base->object->modifiers.first; md; md = md->next) { + if(md->type == eModifierType_Multires) + mmd = (MultiresModifierData*)md; + } - MEM_freeN(mr); - } -} + /* If the object didn't have multires enabled, give it a new modifier */ + if(!mmd) { + md = base->object->modifiers.first; + + while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) + md = md->next; + + mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires); + BLI_insertlinkbefore(&base->object->modifiers, md, mmd); + } -static MultiresLevel *multires_level_copy(MultiresLevel *orig) -{ - if(orig) { - MultiresLevel *lvl= MEM_dupallocN(orig); - - lvl->next= lvl->prev= NULL; - lvl->faces= MEM_dupallocN(orig->faces); - lvl->colfaces= MEM_dupallocN(orig->colfaces); - lvl->edges= MEM_dupallocN(orig->edges); - lvl->edge_boundary_states = NULL; - lvl->vert_edge_map= lvl->vert_face_map= NULL; - lvl->map_mem= NULL; - - return lvl; + if(mmd) + multiresModifier_subdivide(mmd, base->object, highest_lvl - mmd->totlvl, 0, 0); + } + base = base->next; } - return NULL; } +#endif -Multires *multires_copy(Multires *orig) +/* Returns 0 on success, 1 if the src's totvert doesn't match */ +int multiresModifier_reshape(MultiresModifierData *mmd, Object *dst, Object *src) { - const CustomDataMask vdata_mask= CD_MASK_MDEFORMVERT; + Mesh *src_me = get_mesh(src); + DerivedMesh *mrdm = dst->derivedFinal; - if(orig) { - Multires *mr= MEM_dupallocN(orig); - MultiresLevel *lvl; - - mr->levels.first= mr->levels.last= NULL; - - for(lvl= orig->levels.first; lvl; lvl= lvl->next) - BLI_addtail(&mr->levels, multires_level_copy(lvl)); + if(mrdm && mrdm->getNumVerts(mrdm) == src_me->totvert) { + MVert *mvert = CDDM_get_verts(mrdm); + int i; - mr->verts= MEM_dupallocN(orig->verts); - - lvl= mr->levels.first; - if(lvl) { - CustomData_copy(&orig->vdata, &mr->vdata, vdata_mask, CD_DUPLICATE, lvl->totvert); - CustomData_copy(&orig->fdata, &mr->fdata, CD_MASK_MTFACE, CD_DUPLICATE, lvl->totface); - mr->edge_flags= MEM_dupallocN(orig->edge_flags); - mr->edge_creases= MEM_dupallocN(orig->edge_creases); - } - - return mr; - } - return NULL; -} + for(i = 0; i < src_me->totvert; ++i) + VecCopyf(mvert[i].co, src_me->mvert[i].co); + mrdm->needsFree = 1; + *MultiresDM_get_flags(mrdm) |= MULTIRES_DM_UPDATE_ALWAYS; + mrdm->release(mrdm); + dst->derivedFinal = NULL; -static void multires_get_vert(MVert *out, EditVert *eve, MVert *m, int i) -{ - if(eve) { - VecCopyf(out->co, eve->co); - out->flag= 0; - if(eve->f & SELECT) out->flag |= 1; - if(eve->h) out->flag |= ME_HIDE; - eve->tmp.l= i; + return 0; } - else - *out= *m; -} -void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease) -{ - if(!eed || !flag) return; - - /* Would be nice if EditMesh edge flags could be unified with Mesh flags! */ - *flag= (eed->f & SELECT) | ME_EDGERENDER; - if(eed->f2<2) *flag |= ME_EDGEDRAW; - if(eed->f2==0) *flag |= ME_LOOSEEDGE; - if(eed->sharp) *flag |= ME_SHARP; - if(eed->seam) *flag |= ME_SEAM; - //XXX if(eed->h & EM_FGON) *flag |= ME_FGON; - if(eed->h & 1) *flag |= ME_HIDE; - - *crease= (char)(255.0*eed->crease); + return 1; } -static void multires_get_edge(MultiresEdge *e, EditEdge *eed, MEdge *m, short *flag, char *crease) +static void Mat3FromColVecs(float mat[][3], float v1[3], float v2[3], float v3[3]) { - if(eed) { - e->v[0]= eed->v1->tmp.l; - e->v[1]= eed->v2->tmp.l; - eed_to_medge_flag(eed, flag, crease); - } else { - e->v[0]= m->v1; - e->v[1]= m->v2; - *flag= m->flag; - *crease= m->crease; - } + VecCopyf(mat[0], v1); + VecCopyf(mat[1], v2); + VecCopyf(mat[2], v3); } -static void multires_get_face(MultiresFace *f, CustomData *fdata, int findex, EditFace *efa, MFace *m) +static DerivedMesh *multires_subdisp_pre(DerivedMesh *mrdm, int distance, int simple) { - if(efa) { - MFace tmp; - int j; - tmp.v1= efa->v1->tmp.l; - tmp.v2= efa->v2->tmp.l; - tmp.v3= efa->v3->tmp.l; - tmp.v4= 0; - if(efa->v4) tmp.v4= efa->v4->tmp.l; - test_index_face(&tmp, fdata, findex, efa->v4?4:3); - for(j=0; j<4; ++j) f->v[j]= (&tmp.v1)[j]; - - /* Flags */ - f->flag= efa->flag; - if(efa->f & 1) f->flag |= ME_FACE_SEL; - else f->flag &= ~ME_FACE_SEL; - if(efa->h) f->flag |= ME_HIDE; - f->mat_nr= efa->mat_nr; - } else { - f->v[0]= m->v1; - f->v[1]= m->v2; - f->v[2]= m->v3; - f->v[3]= m->v4; - f->flag= m->flag; - f->mat_nr= m->mat_nr; - } + DerivedMesh *final; + SubsurfModifierData smd; + + memset(&smd, 0, sizeof(SubsurfModifierData)); + smd.levels = distance; + if(simple) + smd.subdivType = ME_SIMPLE_SUBSURF; + + final = subsurf_make_derived_from_derived_with_multires(mrdm, &smd, NULL, 0, NULL, 0, 0); + + return final; } -/* For manipulating vertex colors / uvs */ -static void mcol_to_multires(MultiresColFace *mrf, MCol *mcol) +static void VecAddUf(float a[3], float b[3]) { - char i; - for(i=0; i<4; ++i) { - mrf->col[i].a= mcol[i].a; - mrf->col[i].r= mcol[i].r; - mrf->col[i].g= mcol[i].g; - mrf->col[i].b= mcol[i].b; - } + a[0] += b[0]; + a[1] += b[1]; + a[2] += b[2]; } -/* 1 <= count <= 4 */ -static void multires_col_avg(MultiresCol *avg, MultiresCol cols[4], char count) +static void multires_subdisp(DerivedMesh *orig, Mesh *me, DerivedMesh *final, int lvl, int totlvl, + int totsubvert, int totsubedge, int totsubface, int addverts) { - unsigned i; - avg->a= avg->r= avg->g= avg->b= 0; - for(i=0; i<count; ++i) { - avg->a+= cols[i].a; - avg->r+= cols[i].r; - avg->g+= cols[i].g; - avg->b+= cols[i].b; + DerivedMesh *mrdm; + 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; + + mmd_sub.lvl = mmd_sub.totlvl = totlvl; + mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 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}; + VecCopyf(mvd[i].co, z); + } } - avg->a/= count; - avg->r/= count; - avg->g/= count; - avg->b/= count; -} -static void multires_col_avg2(MultiresCol *avg, MultiresCol *c1, MultiresCol *c2) -{ - MultiresCol in[2]; - in[0]= *c1; - in[1]= *c2; - multires_col_avg(avg,in,2); -} + /* 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; + + 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; + } + } -void multires_load_cols(Mesh *me) -{ - MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1), *cur; - EditMesh *em= me->edit_mesh; - CustomData *src= em ? &em->fdata : &me->fdata; - EditFace *efa= NULL; - unsigned i,j; + /* Main face verts */ + for(k = 0; k < 4; ++k) { + int movx, movy; + + 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; + } - if(!CustomData_has_layer(src, CD_MCOL) && !CustomData_has_layer(src, CD_MTFACE)) return; + /* update face center verts */ + VecAddUf(mvd_f2->co, mvs_f2->co); - /* Add texcol data */ - for(cur= me->mr->levels.first; cur; cur= cur->next) - if(!cur->colfaces) - cur->colfaces= MEM_callocN(sizeof(MultiresColFace)*cur->totface,"ColFaces"); + mvd_f2 += 1; + mvs_f2 += 1; - me->mr->use_col= CustomData_has_layer(src, CD_MCOL); + /* update face edge verts */ + for(j = 0; j < end; ++j) { + MVert *restore; - if(em) efa= em->faces.first; - for(i=0; i<lvl->totface; ++i) { - MultiresColFace *f= &lvl->colfaces[i]; + /* 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++; + } + } - if(me->mr->use_col) - mcol_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]); - - if(em) efa= efa->next; + 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); + } } - /* Update higher levels */ - lvl= lvl->next; - while(lvl) { - MultiresColFace *cf= lvl->colfaces; - for(i=0; i<lvl->prev->totface; ++i) { - const char sides= lvl->prev->faces[i].v[3]?4:3; - MultiresCol cntr; - - /* Find average color of 4 (or 3 for triangle) verts */ - multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides); + /* 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(j=0; j<sides; ++j) { - MultiresColFace *pf= &lvl->prev->colfaces[i]; - - multires_col_avg2(&cf->col[0], - &pf->col[j], - &pf->col[j==0?sides-1:j-1]); - cf->col[1]= pf->col[j]; - multires_col_avg2(&cf->col[2], - &pf->col[j], - &pf->col[j==sides-1?0:j+1]); - cf->col[3]= cntr; - - ++cf; + for(k = 0; k < skip - 1; ++k) { + VecAddUf(mvd_e1->co, mvs_e1->co); + mvd_e1++; + mvs_e1++; } } - lvl= lvl->next; } - /* Update lower levels */ - lvl= me->mr->levels.last; - lvl= lvl->prev; - while(lvl) { - unsigned curf= 0; - for(i=0; i<lvl->totface; ++i) { - MultiresFace *f= &lvl->faces[i]; - for(j=0; j<(f->v[3]?4:3); ++j) { - lvl->colfaces[i].col[j]= lvl->next->colfaces[curf].col[1]; - ++curf; + final->needsFree = 1; + final->release(final); + mrdm->needsFree = 1; + *MultiresDM_get_flags(mrdm) |= MULTIRES_DM_UPDATE_ALWAYS; + 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); + + 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; + + 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) { + VecCopyf(disps[j], mdisps[i].disps[y * st + x]); + ++j; + } } + + MEM_freeN(mdisps[i].disps); + mdisps[i].disps = disps; + mdisps[i].totdisp = totdisp; } - lvl= lvl->prev; } + + mmd->totlvl = mmd->lvl; } -void multires_create(Object *ob, Mesh *me) +void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int distance, int updateblock, int simple) { - MultiresLevel *lvl; - EditMesh *em= me->edit_mesh; - EditVert *eve= NULL; - EditFace *efa= NULL; - EditEdge *eed= NULL; + DerivedMesh *final = NULL; + int totsubvert, totsubface, totsubedge; + Mesh *me = get_mesh(ob); + MDisps *mdisps; int i; - - lvl= MEM_callocN(sizeof(MultiresLevel), "multires level"); - if(me->pv) mesh_pmv_off(ob, me); + if(distance == 0) + return; - me->mr= MEM_callocN(sizeof(Multires), "multires data"); - - BLI_addtail(&me->mr->levels,lvl); - me->mr->current= 1; - me->mr->level_count= 1; - me->mr->edgelvl= 1; - me->mr->pinlvl= 1; - me->mr->renderlvl= 1; - - /* Load mesh (or editmesh) into multires data */ - - /* Load vertices and vdata (MDeformVerts) */ - lvl->totvert= em ? BLI_countlist(&em->verts) : me->totvert; - me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts"); - multires_update_customdata(me->mr->levels.first, em, em ? &em->vdata : &me->vdata, - &me->mr->vdata, CD_MDEFORMVERT); - if(em) eve= em->verts.first; - for(i=0; i<lvl->totvert; ++i) { - multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i); - if(em) eve= eve->next; + 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); + mmd_sub.lvl = mmd_sub.totlvl = mmd->lvl; + mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 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; + *MultiresDM_get_flags(mrdm) |= MULTIRES_DM_UPDATE_BLOCK; + mrdm->release(mrdm); } - /* Load faces and fdata (MTFaces) */ - lvl->totface= em ? BLI_countlist(&em->faces) : me->totface; - lvl->faces= MEM_callocN(sizeof(MultiresFace)*lvl->totface,"multires faces"); - multires_update_customdata(me->mr->levels.first, em, em ? &em->fdata : &me->fdata, - &me->mr->fdata, CD_MTFACE); - if(em) efa= em->faces.first; - for(i=0; i<lvl->totface; ++i) { - multires_get_face(&lvl->faces[i], &me->mr->fdata, i, efa, &me->mface[i]); - if(em) efa= efa->next; + for(i = 0; i < me->totface; ++i) { + const int totdisp = multires_quad_tot[mmd->totlvl - 1]; + float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + + if(mdisps[i].disps) + MEM_freeN(mdisps[i].disps); + + mdisps[i].disps = disps; + mdisps[i].totdisp = totdisp; } - /* Load edges and edge_flags */ - lvl->totedge= em ? BLI_countlist(&em->edges) : me->totedge; - lvl->edges= MEM_callocN(sizeof(MultiresEdge)*lvl->totedge,"multires edges"); - me->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "multires edge flags"); - me->mr->edge_creases= MEM_callocN(sizeof(short)*lvl->totedge, "multires edge creases"); - if(em) eed= em->edges.first; - for(i=0; i<lvl->totedge; ++i) { - multires_get_edge(&lvl->edges[i], eed, &me->medge[i], &me->mr->edge_flags[i], &me->mr->edge_creases[i]); - if(em) eed= eed->next; + + if(final) { + DerivedMesh *orig; + + orig = CDDM_from_mesh(me, NULL); + + multires_subdisp(orig, me, final, mmd->lvl, mmd->totlvl, totsubvert, totsubedge, totsubface, 0); + + orig->needsFree = 1; + orig->release(orig); } - multires_load_cols(me); + mmd->lvl = mmd->totlvl; } -typedef struct MultiresMapNode { - struct MultiresMapNode *next, *prev; - unsigned Index; -} MultiresMapNode; +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]; -/* Produces temporary connectivity data for the multires lvl */ -static void multires_calc_temp_data(MultiresLevel *lvl) + /* 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) { - unsigned i, j, emax; - MultiresMapNode *indexnode= NULL; + return v == 0 ? f->v1 : v == 1 ? f->v2 : v == 2 ? f->v3 : v == 3 ? f->v4 : -1; +} - lvl->map_mem= MEM_mallocN(sizeof(MultiresMapNode)*(lvl->totedge*2 + lvl->totface*4), "map_mem"); - indexnode= lvl->map_mem; - - /* edge map */ - lvl->vert_edge_map= MEM_callocN(sizeof(ListBase)*lvl->totvert,"vert_edge_map"); - for(i=0; i<lvl->totedge; ++i) { - for(j=0; j<2; ++j, ++indexnode) { - indexnode->Index= i; - BLI_addtail(&lvl->vert_edge_map[lvl->edges[i].v[j]], indexnode); - } - } +/* 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; - /* face map */ - lvl->vert_face_map= MEM_callocN(sizeof(ListBase)*lvl->totvert,"vert_face_map"); - for(i=0; i<lvl->totface; ++i){ - for(j=0; j<(lvl->faces[i].v[3]?4:3); ++j, ++indexnode) { - indexnode->Index= i; - BLI_addtail(&lvl->vert_face_map[lvl->faces[i].v[j]], indexnode); - } - } + for(i = 0; i < end; ++i) { + int vcur = mface_v(f, i); + int vnext = mface_v(f, i == end - 1 ? 0 : i + 1); - /* edge boundaries */ - emax = (lvl->prev ? (lvl->prev->totedge * 2) : lvl->totedge); - lvl->edge_boundary_states= MEM_callocN(sizeof(char)*lvl->totedge, "edge_boundary_states"); - for(i=0; i<emax; ++i) { - MultiresMapNode *n1= lvl->vert_face_map[lvl->edges[i].v[0]].first; - unsigned total= 0; + de->dir[i] = 1; - lvl->edge_boundary_states[i] = 1; - while(n1 && lvl->edge_boundary_states[i] == 1) { - MultiresMapNode *n2= lvl->vert_face_map[lvl->edges[i].v[1]].first; - while(n2) { - if(n1->Index == n2->Index) { - ++total; - - if(total > 1) { - lvl->edge_boundary_states[i] = 0; - break; - } + 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; } - - n2= n2->next; + de->base[i] += offset; + break; } - n1= n1->next; } } } -/* CATMULL-CLARK - ============= */ - -typedef struct MultiApplyData { - /* Smooth faces */ - float *corner1, *corner2, *corner3, *corner4; - char quad; - - /* Smooth edges */ - char boundary; - float edge_face_neighbor_midpoints_accum[3]; - unsigned edge_face_neighbor_midpoints_total; - float *endpoint1, *endpoint2; - - /* Smooth verts */ - /* uses 'char boundary' */ - float *original; - int edge_count; - float vert_face_neighbor_midpoints_average[3]; - float vert_edge_neighbor_midpoints_average[3]; - float boundary_edges_average[3]; -} MultiApplyData; - -/* Simply averages the four corners of a polygon. */ -static float catmullclark_smooth_face(MultiApplyData *data, const unsigned i) +/* Returns in out the corners [0-3] that use v1 and v2 */ +void find_face_corners(MFace *f, int v1, int v2, int out[2]) { - const float total= data->corner1[i]+data->corner2[i]+data->corner3[i]; - return data->quad ? (total+data->corner4[i])/4 : total/3; + int i, end = f->v4 ? 4 : 3; + + for(i = 0; i < end; ++i) { + int corner = mface_v(f, i); + if(corner == v1) + out[0] = i; + if(corner == v2) + out[1] = i; + } } -static float catmullclark_smooth_edge(MultiApplyData *data, const unsigned i) +static void multires_displacer_get_spill_faces(MultiresDisplacer *d, DerivedMesh *dm, MFace *mface) { - float accum= 0; - unsigned count= 2; - - accum+= data->endpoint1[i] + data->endpoint2[i]; + 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; + + memset(&d->spill_x, 0, sizeof(DisplacerSpill)); + memset(&d->spill_y, 0, sizeof(DisplacerSpill)); + d->spill_x.face = d->spill_y.face = -1; + + 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(!data->boundary) { - accum+= data->edge_face_neighbor_midpoints_accum[i]; - count+= data->edge_face_neighbor_midpoints_total; + 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]); } - return accum / count; + 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 float catmullclark_smooth_vert(MultiApplyData *data, const unsigned i) +static void find_corner_valences(MultiresDisplacer *d, DerivedMesh *dm) { - if(data->boundary) { - return data->original[i]*0.75 + data->boundary_edges_average[i]*0.25; - } else { - return (data->vert_face_neighbor_midpoints_average[i] + - 2*data->vert_edge_neighbor_midpoints_average[i] + - data->original[i]*(data->edge_count-3))/data->edge_count; - } -} + 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; +} -/* Call func count times, passing in[i] as the input and storing the output in out[i] */ -static void multi_apply(float *out, MultiApplyData *data, - const unsigned count, float (*func)(MultiApplyData *, const unsigned)) +static void multires_displacer_weight(MultiresDisplacer *d, const float w) { - unsigned i; - for(i=0; i<count; ++i) - out[i]= func(data,i); + d->weight = w; } -static short multires_vert_is_boundary(MultiresLevel *lvl, unsigned v) +static void multires_displacer_anchor(MultiresDisplacer *d, const int type, const int side_index) { - MultiresMapNode *node= lvl->vert_edge_map[v].first; - while(node) { - if(lvl->edge_boundary_states[node->Index]) - return 1; - node= node->next; + 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; + } } - return 0; -} -#define GET_FLOAT(array, i, j, stride) (((float*)((char*)(array)+((i)*(stride))))[(j)]) + d->ax = d->x; + d->ay = d->y; +} -static void edge_face_neighbor_midpoints_accum(MultiApplyData *data, MultiresLevel *lvl, - void *array, const char stride, const MultiresEdge *e) +static void multires_displacer_anchor_edge(MultiresDisplacer *d, int v1, int v2, int x) { - ListBase *neighbors1= &lvl->vert_face_map[e->v[0]]; - ListBase *neighbors2= &lvl->vert_face_map[e->v[1]]; - MultiresMapNode *n1, *n2; - unsigned j,count= 0; - float *out= data->edge_face_neighbor_midpoints_accum; - - out[0]=out[1]=out[2]= 0; - - for(n1= neighbors1->first; n1; n1= n1->next) { - for(n2= neighbors2->first; n2; n2= n2->next) { - if(n1->Index == n2->Index) { - for(j=0; j<3; ++j) - out[j]+= GET_FLOAT(array,lvl->faces[n1->Index].mid,j,stride); - ++count; + 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; } - - data->edge_face_neighbor_midpoints_total= count; } -static void vert_face_neighbor_midpoints_average(MultiApplyData *data, MultiresLevel *lvl, - void *array, const char stride, const unsigned i) +static void multires_displacer_anchor_vert(MultiresDisplacer *d, const int v) { - ListBase *neighbors= &lvl->vert_face_map[i]; - MultiresMapNode *n1; - unsigned j,count= 0; - float *out= data->vert_face_neighbor_midpoints_average; + const int e = d->sidetot - 1; - out[0]=out[1]=out[2]= 0; + d->type = 5; - for(n1= neighbors->first; n1; n1= n1->next) { - for(j=0; j<3; ++j) - out[j]+= GET_FLOAT(array,lvl->faces[n1->Index].mid,j,stride); - ++count; - } - for(j=0; j<3; ++j) out[j]/= count; + 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 vert_edge_neighbor_midpoints_average(MultiApplyData *data, MultiresLevel *lvl, - void *array, const char stride, const unsigned i) +static void multires_displacer_jump(MultiresDisplacer *d) { - ListBase *neighbors= &lvl->vert_edge_map[i]; - MultiresMapNode *n1; - unsigned j,count= 0; - float *out= data->vert_edge_neighbor_midpoints_average; - - out[0]=out[1]=out[2]= 0; - - for(n1= neighbors->first; n1; n1= n1->next) { - for(j=0; j<3; ++j) - out[j]+= (GET_FLOAT(array,lvl->edges[n1->Index].v[0],j,stride) + - GET_FLOAT(array,lvl->edges[n1->Index].v[1],j,stride)) / 2; - ++count; + 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; } - for(j=0; j<3; ++j) out[j]/= count; } -static void boundary_edges_average(MultiApplyData *data, MultiresLevel *lvl, - void *array, const char stride, const unsigned i) +/* 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) { - ListBase *neighbors= &lvl->vert_edge_map[i]; - MultiresMapNode *n1; - unsigned j,count= 0; - float *out= data->boundary_edges_average; + 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; + } - out[0]=out[1]=out[2]= 0; - - for(n1= neighbors->first; n1; n1= n1->next) { - const MultiresEdge *e= &lvl->edges[n1->Index]; - const unsigned end= e->v[0]==i ? e->v[1] : e->v[0]; - - if(lvl->edge_boundary_states[n1->Index]) { - for(j=0; j<3; ++j) - out[j]+= GET_FLOAT(array,end,j,stride); - ++count; + 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); } - for(j=0; j<3; ++j) out[j]/= count; + 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; } -/* END CATMULL-CLARK - ================= */ - -/* Update vertex locations and vertex flags */ -static void multires_update_vertices(Mesh *me, EditMesh *em) +/* 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]) { - MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL, - *last_lvl= me->mr->levels.last; - vec3f *pr_deltas= NULL, *cr_deltas= NULL, *swap_deltas= NULL; - EditVert *eve= NULL; - MultiApplyData data; - int i, j; + 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; - /* XXX added this to prevent crash, but if it works? (ton) */ - if(me->mr->verts==NULL) - return; + //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); - /* Prepare deltas */ - pr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 1"); - cr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 2"); - - /* Calculate initial deltas -- current mesh subtracted from current level*/ - if(em) eve= em->verts.first; - for(i=0; i<cr_lvl->totvert; ++i) { - if(em) { - VecSubf(&cr_deltas[i].x, eve->co, me->mr->verts[i].co); - eve= eve->next; - } else - VecSubf(&cr_deltas[i].x, me->mvert[i].co, me->mr->verts[i].co); + 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); + VecSubf(t1, base->co, d->subco[u].co); } + else + VecSubf(t1, d->subco[u].co, base->co); - - /* Copy current level's vertex flags and clear the rest */ - if(em) eve= em->verts.first; - for(i=0; i < last_lvl->totvert; ++i) { - if(i < cr_lvl->totvert) { - MVert mvflag; - multires_get_vert(&mvflag, eve, &me->mvert[i], i); - if(em) eve= eve->next; - me->mr->verts[i].flag= mvflag.flag; - } - else - me->mr->verts[i].flag= 0; + if(v < 0) { + v = multires_index_at_loc(d->face_index, d->x, d->y - 1, d, &d->edges_primary); + VecSubf(t2, base->co, d->subco[v].co); } + else + VecSubf(t2, d->subco[v].co, base->co); - /* If already on the highest level, copy current verts (including flags) into current level */ - if(cr_lvl == last_lvl) { - if(em) - eve= em->verts.first; - for(i=0; i<cr_lvl->totvert; ++i) { - multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i); - if(em) eve= eve->next; - } + //printf("uu=%d, vv=%d\n", u, v); + + Normalize(t1); + Normalize(t2); + Mat3FromColVecs(mat, t1, t2, norm); + + if(d->invert) { + Mat3Inv(inv, mat); + Mat3CpyMat3(mat, inv); } +} - /* Update higher levels */ - pr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); - cr_lvl= pr_lvl->next; - while(cr_lvl) { - multires_calc_temp_data(pr_lvl); - - /* Swap the old/new deltas */ - swap_deltas= pr_deltas; - pr_deltas= cr_deltas; - cr_deltas= swap_deltas; - - /* Calculate and add new deltas - ============================ */ - for(i=0; i<pr_lvl->totface; ++i) { - const MultiresFace *f= &pr_lvl->faces[i]; - data.corner1= &pr_deltas[f->v[0]].x; - data.corner2= &pr_deltas[f->v[1]].x; - data.corner3= &pr_deltas[f->v[2]].x; - data.corner4= &pr_deltas[f->v[3]].x; - data.quad= f->v[3] ? 1 : 0; - multi_apply(&cr_deltas[f->mid].x, &data, 3, catmullclark_smooth_face); - - for(j=0; j<(data.quad?4:3); ++j) - me->mr->verts[f->mid].flag |= me->mr->verts[f->v[j]].flag; - } +static void multires_displace(MultiresDisplacer *d, float co[3]) +{ + float disp[3], mat[3][3]; + float *data; + MVert *subco = &d->subco[d->subco_index]; - for(i=0; i<pr_lvl->totedge; ++i) { - const MultiresEdge *e= &pr_lvl->edges[i]; - data.boundary= pr_lvl->edge_boundary_states[i]; - edge_face_neighbor_midpoints_accum(&data,pr_lvl,cr_deltas,sizeof(vec3f),e); - data.endpoint1= &pr_deltas[e->v[0]].x; - data.endpoint2= &pr_deltas[e->v[1]].x; - multi_apply(&cr_deltas[e->mid].x, &data, 3, catmullclark_smooth_edge); - - for(j=0; j<2; ++j) - me->mr->verts[e->mid].flag |= me->mr->verts[e->v[j]].flag; - } + if(!d->grid || !d->grid->disps) return; - for(i=0; i<pr_lvl->totvert; ++i) { - data.boundary= multires_vert_is_boundary(pr_lvl,i); - data.original= &pr_deltas[i].x; - data.edge_count= BLI_countlist(&pr_lvl->vert_edge_map[i]); - if(data.boundary) - boundary_edges_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i); - else { - vert_face_neighbor_midpoints_average(&data,pr_lvl,cr_deltas,sizeof(vec3f),i); - vert_edge_neighbor_midpoints_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i); - } - multi_apply(&cr_deltas[i].x, &data, 3, catmullclark_smooth_vert); - } + data = d->grid->disps[(d->y * d->spacing) * d->disp_st + (d->x * d->spacing)]; + + if(d->invert) + VecSubf(disp, co, subco->co); + else + VecCopyf(disp, data); - /* Apply deltas to vertex locations */ - for(i=0; (cr_lvl == last_lvl) && (i < cr_lvl->totvert); ++i) { - VecAddf(me->mr->verts[i].co, - me->mr->verts[i].co, - &cr_deltas[i].x); - } - multires_free_temp_data(pr_lvl); + /* Apply ts matrix to displacement */ + calc_disp_mat(d, mat); + Mat3MulVecfl(mat, disp); - pr_lvl= pr_lvl->next; - cr_lvl= cr_lvl->next; + if(d->invert) { + VecCopyf(data, disp); + + } + else { + if(d->type == 4 || d->type == 5) + VecMulf(disp, d->weight); + VecAddf(co, co, disp); } - if(pr_deltas) MEM_freeN(pr_deltas); - if(cr_deltas) MEM_freeN(cr_deltas); + 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; + } + 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; + } } -static void multires_update_faces(Mesh *me, EditMesh *em) +static void multiresModifier_disp_run(DerivedMesh *dm, MVert *subco, int invert) { - MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL, - *last_lvl= me->mr->levels.last; - char *pr_flag_damaged= NULL, *cr_flag_damaged= NULL, *or_flag_damaged= NULL, - *pr_mat_damaged= NULL, *cr_mat_damaged= NULL, *or_mat_damaged= NULL, *swap= NULL; - EditFace *efa= NULL; - unsigned i,j,curf; - - /* Find for each face whether flag/mat has changed */ - pr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1"); - cr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1"); - pr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1"); - cr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1"); - if(em) efa= em->faces.first; - for(i=0; i<cr_lvl->totface; ++i) { - MultiresFace mftmp; - multires_get_face(&mftmp, &me->mr->fdata, i, efa, &me->mface[i]); - if(cr_lvl->faces[i].flag != mftmp.flag) - cr_flag_damaged[i]= 1; - if(cr_lvl->faces[i].mat_nr != mftmp.mat_nr) - cr_mat_damaged[i]= 1; - - /* Update current level */ - cr_lvl->faces[i].flag= mftmp.flag; - cr_lvl->faces[i].mat_nr= mftmp.mat_nr; - - if(em) efa= efa->next; - } - or_flag_damaged= MEM_dupallocN(cr_flag_damaged); - or_mat_damaged= MEM_dupallocN(cr_mat_damaged); - - /* Update lower levels */ - cr_lvl= cr_lvl->prev; - while(cr_lvl) { - swap= pr_flag_damaged; - pr_flag_damaged= cr_flag_damaged; - cr_flag_damaged= swap; - - swap= pr_mat_damaged; - pr_mat_damaged= cr_mat_damaged; - cr_mat_damaged= swap; - - curf= 0; - for(i=0; i<cr_lvl->totface; ++i) { - const int sides= cr_lvl->faces[i].v[3] ? 4 : 3; - - /* Check damages */ - for(j=0; j<sides; ++j, ++curf) { - if(pr_flag_damaged[curf]) { - cr_lvl->faces[i].flag= cr_lvl->next->faces[curf].flag; - cr_flag_damaged[i]= 1; - } - if(pr_mat_damaged[curf]) { - cr_lvl->faces[i].mat_nr= cr_lvl->next->faces[curf].mat_nr; - cr_mat_damaged[i]= 1; - } + 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; + + d.subco = subco; + d.subco_index = 0; + + for(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; + + /* 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; } } - cr_lvl= cr_lvl->prev; + /* 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); + } + } } - - /* Clear to original damages */ - if(cr_flag_damaged) MEM_freeN(cr_flag_damaged); - if(cr_mat_damaged) MEM_freeN(cr_mat_damaged); - cr_flag_damaged= or_flag_damaged; - cr_mat_damaged= or_mat_damaged; - - /* Update higher levels */ - pr_lvl= current_level(me->mr); - cr_lvl= pr_lvl->next; - while(cr_lvl) { - swap= pr_flag_damaged; - pr_flag_damaged= cr_flag_damaged; - cr_flag_damaged= swap; - - swap= pr_mat_damaged; - pr_mat_damaged= cr_mat_damaged; - cr_mat_damaged= swap; - - /* Update faces */ - for(i=0, curf= 0; i<pr_lvl->totface; ++i) { - const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3; - for(j=0; j<sides; ++j, ++curf) { - if(pr_flag_damaged[i]) { - cr_lvl->faces[curf].flag= pr_lvl->faces[i].flag; - cr_flag_damaged[curf]= 1; + + 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; } - if(pr_mat_damaged[i]) { - cr_lvl->faces[curf].mat_nr= pr_lvl->faces[i].mat_nr; - cr_mat_damaged[curf]= 1; + } + 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); + } } } + ++mvert; + ++d.subco_index; } - - pr_lvl= pr_lvl->next; - cr_lvl= cr_lvl->next; + } + + 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(pr_flag_damaged) MEM_freeN(pr_flag_damaged); - if(cr_flag_damaged) MEM_freeN(cr_flag_damaged); - if(pr_mat_damaged) MEM_freeN(pr_mat_damaged); - if(cr_mat_damaged) MEM_freeN(cr_mat_damaged); + if(!invert) + CDDM_calc_normals(dm); } -static void multires_update_colors(Mesh *me, EditMesh *em) +static void multiresModifier_update(DerivedMesh *dm) { - MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); - MultiresCol *pr_deltas= NULL, *cr_deltas= NULL; - CustomData *src= em ? &em->fdata : &me->fdata; - EditFace *efa= NULL; - unsigned i,j,curf= 0; - - if(me->mr->use_col) { - /* Calc initial deltas */ - cr_deltas= MEM_callocN(sizeof(MultiresCol)*lvl->totface*4,"initial color/uv deltas"); - - if(em) efa= em->faces.first; - for(i=0; i<lvl->totface; ++i) { - MCol *col= em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]; - for(j=0; j<4; ++j) { - if(me->mr->use_col) { - cr_deltas[i*4+j].a= col[j].a - lvl->colfaces[i].col[j].a; - cr_deltas[i*4+j].r= col[j].r - lvl->colfaces[i].col[j].r; - cr_deltas[i*4+j].g= col[j].g - lvl->colfaces[i].col[j].g; - cr_deltas[i*4+j].b= col[j].b - lvl->colfaces[i].col[j].b; - } - } - if(em) efa= efa->next; - } - - /* Update current level */ - if(em) efa= em->faces.first; - for(i=0; i<lvl->totface; ++i) { - MultiresColFace *f= &lvl->colfaces[i]; + Mesh *me; + MDisps *mdisps; - if(me->mr->use_col) - mcol_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]); - - if(em) efa= efa->next; - } - - /* Update higher levels */ - lvl= lvl->next; - while(lvl) { - /* Set up new deltas, but keep the ones from the previous level */ - if(pr_deltas) MEM_freeN(pr_deltas); - pr_deltas= cr_deltas; - cr_deltas= MEM_callocN(sizeof(MultiresCol)*lvl->totface*4,"color deltas"); - - curf= 0; - for(i=0; i<lvl->prev->totface; ++i) { - const char sides= lvl->prev->faces[i].v[3]?4:3; - MultiresCol cntr; - - /* Find average color of 4 (or 3 for triangle) verts */ - multires_col_avg(&cntr,&pr_deltas[i*4],sides); - - for(j=0; j<sides; ++j) { - multires_col_avg2(&cr_deltas[curf*4], - &pr_deltas[i*4+j], - &pr_deltas[i*4+(j==0?sides-1:j-1)]); - cr_deltas[curf*4+1]= pr_deltas[i*4+j]; - multires_col_avg2(&cr_deltas[curf*4+2], - &pr_deltas[i*4+j], - &pr_deltas[i*4+(j==sides-1?0:j+1)]); - cr_deltas[curf*4+3]= cntr; - ++curf; - } - } + if(!(G.f & G_SCULPTMODE) && !(*MultiresDM_get_flags(dm) & MULTIRES_DM_UPDATE_ALWAYS)) return; - for(i=0; i<lvl->totface; ++i) { - for(j=0; j<4; ++j) { - lvl->colfaces[i].col[j].a+= cr_deltas[i*4+j].a; - lvl->colfaces[i].col[j].r+= cr_deltas[i*4+j].r; - lvl->colfaces[i].col[j].g+= cr_deltas[i*4+j].g; - lvl->colfaces[i].col[j].b+= cr_deltas[i*4+j].b; - } - } + me = MultiresDM_get_mesh(dm); + mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); - lvl= lvl->next; - } - if(pr_deltas) MEM_freeN(pr_deltas); - if(cr_deltas) MEM_freeN(cr_deltas); + if(mdisps) { + const int lvl = MultiresDM_get_lvl(dm); + const int totlvl = MultiresDM_get_totlvl(dm); - /* Update lower levels */ - lvl= me->mr->levels.last; - lvl= lvl->prev; - while(lvl) { - MultiresColFace *nf= lvl->next->colfaces; - for(i=0; i<lvl->totface; ++i) { - MultiresFace *f= &lvl->faces[i]; - for(j=0; j<(f->v[3]?4:3); ++j) { - lvl->colfaces[i].col[j]= nf->col[1]; - ++nf; - } - } - lvl= lvl->prev; + if(lvl < totlvl) { + /* Propagate disps upwards */ + DerivedMesh *final, *subco_dm, *orig; + MVert *verts_new = NULL, *cur_lvl_orig_verts = NULL; + MultiresModifierData mmd; + int i; + + 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, orig, me, 0, 0); + *MultiresDM_get_flags(subco_dm) |= MULTIRES_DM_UPDATE_BLOCK; + cur_lvl_orig_verts = CDDM_get_verts(subco_dm); + + /* Subtract the original vertex cos from the new vertex cos */ + verts_new = CDDM_get_verts(dm); + for(i = 0; i < dm->getNumVerts(dm); ++i) + VecSubf(verts_new[i].co, verts_new[i].co, cur_lvl_orig_verts[i].co); + + final = multires_subdisp_pre(dm, totlvl - lvl, 0); + + multires_subdisp(orig, me, final, lvl, totlvl, dm->getNumVerts(dm), dm->getNumEdges(dm), + dm->getNumFaces(dm), 1); + + subco_dm->release(subco_dm); + orig->release(orig); } + else + multiresModifier_disp_run(dm, MultiresDM_get_subco(dm), 1); + } +} + +void multires_force_update(Object *ob) +{ + if(ob->derivedFinal) { + ob->derivedFinal->needsFree =1; + ob->derivedFinal->release(ob->derivedFinal); + ob->derivedFinal = NULL; } } -void multires_update_levels(Mesh *me, const int render) +struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, DerivedMesh *dm, Mesh *me, + int useRenderParams, int isFinalCalc) { - EditMesh *em= render ? NULL : me->edit_mesh; + SubsurfModifierData smd; + MultiresSubsurf ms; + DerivedMesh *result; + int i; - multires_update_first_level(me, em); - multires_update_vertices(me, em); - multires_update_faces(me, em); - multires_update_colors(me, em); + ms.mmd = mmd; + ms.me = me; + + memset(&smd, 0, sizeof(SubsurfModifierData)); + smd.levels = smd.renderLevels = mmd->lvl - 1; + smd.flags |= eSubsurfModifierFlag_SubsurfUv; + + result = 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); + + return result; } -static void check_colors(Mesh *me) +/**** Old Multires code **** +***************************/ + +/* Does not actually free lvl itself */ +void multires_free_level(MultiresLevel *lvl) { - CustomData *src= me->edit_mesh ? &me->edit_mesh->fdata : &me->fdata; - const char col= CustomData_has_layer(src, CD_MCOL); - - /* Check if vertex colors have been deleted or added */ - if(me->mr->use_col && !col) - me->mr->use_col= 0; - else if(!me->mr->use_col && col) { - me->mr->use_col= 1; - multires_load_cols(me); + if(lvl) { + if(lvl->faces) MEM_freeN(lvl->faces); + if(lvl->edges) MEM_freeN(lvl->edges); + if(lvl->colfaces) MEM_freeN(lvl->colfaces); } } -static unsigned int find_mid_edge(ListBase *vert_edge_map, - MultiresLevel *lvl, - const unsigned int v1, - const unsigned int v2 ) +void multires_free(Multires *mr) { - MultiresMapNode *n= vert_edge_map[v1].first; - while(n) { - if(lvl->edges[n->Index].v[0]==v2 || - lvl->edges[n->Index].v[1]==v2) - return lvl->edges[n->Index].mid; + if(mr) { + MultiresLevel* lvl= mr->levels.first; + + /* Free the first-level data */ + if(lvl) { + CustomData_free(&mr->vdata, lvl->totvert); + CustomData_free(&mr->fdata, lvl->totface); + MEM_freeN(mr->edge_flags); + MEM_freeN(mr->edge_creases); + } - n= n->next; + while(lvl) { + multires_free_level(lvl); + lvl= lvl->next; + } + + MEM_freeN(mr->verts); + + BLI_freelistN(&mr->levels); + + MEM_freeN(mr); } - return -1; } -static float clamp_component(const float c) +static void create_old_vert_face_map(ListBase **map, IndexNode **mem, const MultiresFace *mface, + const int totvert, const int totface) { - if(c<0) return 0; - else if(c>255) return 255; - else return c; + int i,j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem"); + node = *mem; + + /* Find the users */ + for(i = 0; i < totface; ++i){ + for(j = 0; j < (mface[i].v[3]?4:3); ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[mface[i].v[j]], node); + } + } } -void multires_to_mcol(MultiresColFace *f, MCol mcol[4]) +static void create_old_vert_edge_map(ListBase **map, IndexNode **mem, const MultiresEdge *medge, + const int totvert, const int totedge) { - unsigned char j; - for(j=0; j<4; ++j) { - mcol->a= clamp_component(f->col[j].a); - mcol->r= clamp_component(f->col[j].r); - mcol->g= clamp_component(f->col[j].g); - mcol->b= clamp_component(f->col[j].b); - ++mcol; + int i,j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totedge*2, "vert edge map mem"); + node = *mem; + + /* Find the users */ + for(i = 0; i < totedge; ++i){ + for(j = 0; j < 2; ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[medge[i].v[j]], node); + } } } -void multires_level_to_mesh(Object *ob, Mesh *me, const int render) +static MultiresFace *find_old_face(ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4) { - MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); - EditMesh *em= render ? NULL : me->edit_mesh; - int i; - - if(em) - return; + IndexNode *n1; + int v[4] = {v1, v2, v3, v4}, i, j; - CustomData_free_layer_active(&me->vdata, CD_MVERT, me->totvert); - CustomData_free_layer_active(&me->edata, CD_MEDGE, me->totedge); - CustomData_free_layer_active(&me->fdata, CD_MFACE, me->totface); - CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); - CustomData_free_layers(&me->fdata, CD_MTFACE, me->totface); - CustomData_free_layers(&me->fdata, CD_MCOL, me->totface); - - me->totvert= lvl->totvert; - me->totface= lvl->totface; - me->totedge= lvl->totedge; + for(n1 = map[v1].first; n1; n1 = n1->next) { + int fnd[4] = {0, 0, 0, 0}; - CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); - CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge); - CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); - mesh_update_customdata_pointers(me); - - /* Vertices/Edges/Faces */ - - for(i=0; i<lvl->totvert; ++i) { - me->mvert[i]= me->mr->verts[i]; - } - for(i=0; i<lvl->totedge; ++i) { - me->medge[i].v1= lvl->edges[i].v[0]; - me->medge[i].v2= lvl->edges[i].v[1]; - me->medge[i].flag &= ~ME_HIDE; - } - for(i=0; i<lvl->totface; ++i) { - me->mface[i].v1= lvl->faces[i].v[0]; - me->mface[i].v2= lvl->faces[i].v[1]; - me->mface[i].v3= lvl->faces[i].v[2]; - me->mface[i].v4= lvl->faces[i].v[3]; - me->mface[i].flag= lvl->faces[i].flag; - me->mface[i].flag &= ~ME_HIDE; - me->mface[i].mat_nr= lvl->faces[i].mat_nr; - } - - /* Edge flags */ - if(lvl==me->mr->levels.first) { - for(i=0; i<lvl->totedge; ++i) { - me->medge[i].flag= me->mr->edge_flags[i]; - me->medge[i].crease= me->mr->edge_creases[i]; - } - } else { - MultiresLevel *lvl1= me->mr->levels.first; - const int last= lvl1->totedge * pow(2, me->mr->current-1); - for(i=0; i<last; ++i) { - const int ndx= i / pow(2, me->mr->current-1); - - me->medge[i].flag= me->mr->edge_flags[ndx]; - me->medge[i].crease= me->mr->edge_creases[ndx]; + for(i = 0; i < 4; ++i) { + for(j = 0; j < 4; ++j) { + if(v[i] == faces[n1->index].v[j]) + fnd[i] = 1; + } } + + if(fnd[0] && fnd[1] && fnd[2] && fnd[3]) + return &faces[n1->index]; } - multires_customdata_to_mesh(me, em, lvl, &me->mr->vdata, em ? &em->vdata : &me->vdata, CD_MDEFORMVERT); - multires_customdata_to_mesh(me, em, lvl, &me->mr->fdata, em ? &em->fdata : &me->fdata, CD_MTFACE); + return NULL; +} + +static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2) +{ + IndexNode *n1, *n2; - /* Colors */ - if(me->mr->use_col) { - CustomData *src= &me->fdata; - - if(me->mr->use_col) me->mcol= CustomData_add_layer(src, CD_MCOL, CD_CALLOC, NULL, me->totface); - - for(i=0; i<lvl->totface; ++i) { - if(me->mr->use_col) - multires_to_mcol(&lvl->colfaces[i], &me->mcol[i*4]); + for(n1 = map[v1].first; n1; n1 = n1->next) { + for(n2 = map[v2].first; n2; n2 = n2->next) { + if(n1->index == n2->index) + return &edges[n1->index]; } - } - - mesh_update_customdata_pointers(me); - - multires_edge_level_update(ob,me); -// XXX do this in caller DAG_object_flush_update(scene, ob, OB_RECALC_DATA); - mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); + + return NULL; } -void multires_add_level(Object *ob, Mesh *me, const char subdiv_type) +static void multires_load_old_edges(ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov) { - int i,j, curf, cure; - MultiresLevel *lvl= NULL; - MultiApplyData data; - MVert *oldverts= NULL; - - lvl= MEM_callocN(sizeof(MultiresLevel), "multireslevel"); - if(me->pv) mesh_pmv_off(ob, me); - - check_colors(me); - multires_update_levels(me, 0); - - ++me->mr->level_count; - BLI_addtail(&me->mr->levels,lvl); - - /* Create vertices - =============== */ - lvl->totvert= lvl->prev->totvert + lvl->prev->totedge + lvl->prev->totface; - oldverts= me->mr->verts; - me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert, "multitres verts"); - /* Copy old verts */ - for(i=0; i<lvl->prev->totvert; ++i) - me->mr->verts[i]= oldverts[i]; - /* Create new edge verts */ - for(i=0; i<lvl->prev->totedge; ++i) { - VecMidf(me->mr->verts[lvl->prev->totvert + i].co, - oldverts[lvl->prev->edges[i].v[0]].co, - oldverts[lvl->prev->edges[i].v[1]].co); - lvl->prev->edges[i].mid= lvl->prev->totvert + i; - } - /* Create new face verts */ - for(i=0; i<lvl->prev->totface; ++i) { - lvl->prev->faces[i].mid= lvl->prev->totvert + lvl->prev->totedge + i; + int emid = find_old_edge(emap[2], lvl->edges, v1, v2)->mid; + vvmap[dst + mov] = emid; + + if(lvl->next->next) { + multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v1, emid, mov / 2); + multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v2, emid, -mov / 2); } +} - multires_calc_temp_data(lvl->prev); +static void multires_load_old_faces(ListBase **fmap, ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, + int v1, int v2, int v3, int v4, int st2, int st3) +{ + int fmid; + int emid13, emid14, emid23, emid24; - /* Create faces - ============ */ - /* Allocate all the new faces (each triangle creates three, and - each quad creates four */ - lvl->totface= 0; - for(i=0; i<lvl->prev->totface; ++i) - lvl->totface+= lvl->prev->faces[i].v[3] ? 4 : 3; - lvl->faces= MEM_callocN(sizeof(MultiresFace)*lvl->totface,"multires faces"); + if(lvl && lvl->next) { + fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid; + vvmap[dst] = fmid; - curf= 0; - for(i=0; i<lvl->prev->totface; ++i) { - const int max= lvl->prev->faces[i].v[3] ? 3 : 2; - - for(j=0; j<max+1; ++j) { - lvl->faces[curf].v[0]= find_mid_edge(lvl->prev->vert_edge_map,lvl->prev, - lvl->prev->faces[i].v[j], - lvl->prev->faces[i].v[j==0?max:j-1]); - lvl->faces[curf].v[1]= lvl->prev->faces[i].v[j]; - lvl->faces[curf].v[2]= find_mid_edge(lvl->prev->vert_edge_map,lvl->prev, - lvl->prev->faces[i].v[j], - lvl->prev->faces[i].v[j==max?0:j+1]); - lvl->faces[curf].v[3]= lvl->prev->totvert + lvl->prev->totedge + i; - lvl->faces[curf].flag= lvl->prev->faces[i].flag; - lvl->faces[curf].mat_nr= lvl->prev->faces[i].mat_nr; - - ++curf; - } - } + emid13 = find_old_edge(emap[1], lvl->edges, v1, v3)->mid; + emid14 = find_old_edge(emap[1], lvl->edges, v1, v4)->mid; + emid23 = find_old_edge(emap[1], lvl->edges, v2, v3)->mid; + emid24 = find_old_edge(emap[1], lvl->edges, v2, v4)->mid; - /* Create edges - ============ */ - /* Figure out how many edges to allocate */ - lvl->totedge= lvl->prev->totedge*2; - for(i=0; i<lvl->prev->totface; ++i) - lvl->totedge+= lvl->prev->faces[i].v[3]?4:3; - lvl->edges= MEM_callocN(sizeof(MultiresEdge)*lvl->totedge,"multires edges"); - - for(i=0; i<lvl->prev->totedge; ++i) { - lvl->edges[i*2].v[0]= lvl->prev->edges[i].v[0]; - lvl->edges[i*2].v[1]= lvl->prev->edges[i].mid; - lvl->edges[i*2+1].v[0]= lvl->prev->edges[i].mid; - lvl->edges[i*2+1].v[1]= lvl->prev->edges[i].v[1]; - } - /* Add edges inside of old polygons */ - curf= 0; - cure= lvl->prev->totedge*2; - for(i=0; i<lvl->prev->totface; ++i) { - for(j=0; j<(lvl->prev->faces[i].v[3]?4:3); ++j) { - lvl->edges[cure].v[0]= lvl->faces[curf].v[2]; - lvl->edges[cure].v[1]= lvl->faces[curf].v[3]; - ++cure; - ++curf; + + multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst + st2 * st3 + st3, + fmid, v2, emid23, emid24, st2, st3 / 2); + + multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst - st2 * st3 + st3, + emid14, emid24, fmid, v4, st2, st3 / 2); + + multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst + st2 * st3 - st3, + emid13, emid23, v3, fmid, st2, st3 / 2); + + multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst - st2 * st3 - st3, + v1, fmid, emid13, emid14, st2, st3 / 2); + + if(lvl->next->next) { + multires_load_old_edges(emap, lvl->next, vvmap, dst, emid24, fmid, st3); + multires_load_old_edges(emap, lvl->next, vvmap, dst, emid13, fmid, -st3); + multires_load_old_edges(emap, lvl->next, vvmap, dst, emid14, fmid, -st2 * st3); + multires_load_old_edges(emap, lvl->next, vvmap, dst, emid23, fmid, st2 * st3); } } +} - /* Smooth vertices - =============== */ - for(i=0; i<lvl->prev->totface; ++i) { - const MultiresFace *f= &lvl->prev->faces[i]; - data.corner1= oldverts[f->v[0]].co; - data.corner2= oldverts[f->v[1]].co; - data.corner3= oldverts[f->v[2]].co; - data.corner4= oldverts[f->v[3]].co; - data.quad= f->v[3] ? 1 : 0; - multi_apply(me->mr->verts[f->mid].co, &data, 3, catmullclark_smooth_face); +/* Loads a multires object stored in the old Multires struct into the new format */ +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 *vvmap; // inorder for dst, map to src + int crossedgelen; + int i, j, s, x, totvert, tottri, totquad; + + src = 0; + dst = 0; + vsrc = mr->verts; + vdst = CDDM_get_verts(dm); + totvert = dm->getNumVerts(dm); + vvmap = MEM_callocN(sizeof(int) * totvert, "multires vvmap"); + + lvl1 = mr->levels.first; + /* Load base verts */ + for(i = 0; i < lvl1->totvert; ++i) { + vvmap[totvert - lvl1->totvert + i] = src; + ++src; } - if(subdiv_type == 0) { - for(i=0; i<lvl->prev->totedge; ++i) { - const MultiresEdge *e= &lvl->prev->edges[i]; - data.boundary= lvl->prev->edge_boundary_states[i]; - edge_face_neighbor_midpoints_accum(&data,lvl->prev, me->mr->verts, sizeof(MVert),e); - data.endpoint1= oldverts[e->v[0]].co; - data.endpoint2= oldverts[e->v[1]].co; - multi_apply(me->mr->verts[e->mid].co, &data, 3, catmullclark_smooth_edge); - } - - for(i=0; i<lvl->prev->totvert; ++i) { - data.boundary= multires_vert_is_boundary(lvl->prev,i); - data.original= oldverts[i].co; - data.edge_count= BLI_countlist(&lvl->prev->vert_edge_map[i]); - if(data.boundary) - boundary_edges_average(&data,lvl->prev, oldverts, sizeof(MVert),i); - else { - vert_face_neighbor_midpoints_average(&data,lvl->prev, me->mr->verts, - sizeof(MVert),i); - vert_edge_neighbor_midpoints_average(&data,lvl->prev, oldverts, - sizeof(MVert),i); - } - multi_apply(me->mr->verts[i].co, &data, 3, catmullclark_smooth_vert); + /* Original edges */ + dst = totvert - lvl1->totvert - extedgelen * lvl1->totedge; + for(i = 0; i < lvl1->totedge; ++i) { + int ldst = dst + extedgelen * i; + int lsrc = src; + 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; + + for(x = 0; x < st; ++x) + vvmap[ldst + base + x * skip] = lsrc + st * i + x; + + lsrc += lvl->totvert - lvl->prev->totvert; + lvl = lvl->next; } } - multires_free_temp_data(lvl->prev); - MEM_freeN(oldverts); - - /* Vertex Colors - ============= */ - curf= 0; - if(me->mr->use_col) { - MultiresColFace *cf= MEM_callocN(sizeof(MultiresColFace)*lvl->totface,"Multirescolfaces"); - lvl->colfaces= cf; - for(i=0; i<lvl->prev->totface; ++i) { - const char sides= lvl->prev->faces[i].v[3]?4:3; - MultiresCol cntr; - - /* Find average color of 4 (or 3 for triangle) verts */ - multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides); - - for(j=0; j<sides; ++j) { - multires_col_avg2(&cf->col[0], - &lvl->prev->colfaces[i].col[j], - &lvl->prev->colfaces[i].col[j==0?sides-1:j-1]); - cf->col[1]= lvl->prev->colfaces[i].col[j]; - multires_col_avg2(&cf->col[2], - &lvl->prev->colfaces[i].col[j], - &lvl->prev->colfaces[i].col[j==sides-1?0:j+1]); - cf->col[3]= cntr; - - ++cf; - } - } + /* Center points */ + dst = 0; + for(i = 0; i < lvl1->totface; ++i) { + int sides = lvl1->faces[i].v[3] ? 4 : 3; + + vvmap[dst] = src + lvl1->totedge + i; + dst += 1 + sides * (st - 1) * st; } - me->mr->newlvl= me->mr->level_count; - me->mr->current= me->mr->newlvl; - /* Unless the render level has been set to something other than the - highest level (by the user), increment the render level to match - the highest available level */ - if(me->mr->renderlvl == me->mr->level_count - 1) me->mr->renderlvl= me->mr->level_count; - multires_level_to_mesh(ob, me, 0); -} + /* The rest is only for level 3 and up */ + if(lvl1->next && lvl1->next->next) { + ListBase **fmap, **emap; + IndexNode **fmem, **emem; -void multires_set_level(Object *ob, Mesh *me, const int render) -{ - if(me->pv) mesh_pmv_off(ob, me); + /* Face edge cross */ + tottri = totquad = 0; + crossedgelen = multires_side_tot[totlvl - 2] - 2; + dst = 0; + for(i = 0; i < lvl1->totface; ++i) { + int sides = lvl1->faces[i].v[3] ? 4 : 3; - check_colors(me); - multires_update_levels(me, render); + lvl = lvl1->next->next; + ++dst; - me->mr->current= me->mr->newlvl; - if(me->mr->current<1) me->mr->current= 1; - else if(me->mr->current>me->mr->level_count) me->mr->current= me->mr->level_count; + 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 st = pow(2, j - 2); + int st2 = pow(2, j - 3); + int lsrc = lvl->prev->totvert; - multires_level_to_mesh(ob, me, render); -} + /* Skip exterior edge verts */ + lsrc += lvl1->totedge * st; -/* Update the edge visibility flags to only show edges on or below the edgelvl */ -void multires_edge_level_update(Object *ob, Mesh *me) -{ - if(!me->edit_mesh) { - MultiresLevel *cr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); - MultiresLevel *edge_lvl= BLI_findlink(&me->mr->levels,me->mr->edgelvl-1); - const int threshold= edge_lvl->totedge * pow(2, me->mr->current - me->mr->edgelvl); - unsigned i; - - for(i=0; i<cr_lvl->totedge; ++i) { - const int ndx= me->pv ? me->pv->edge_map[i] : i; - if(ndx != -1) { /* -1= hidden edge */ - if(me->mr->edgelvl >= me->mr->current || i<threshold) - me->medge[ndx].flag |= ME_EDGEDRAW | ME_EDGERENDER; - else - me->medge[ndx].flag &= ~ME_EDGEDRAW & ~ME_EDGERENDER; + /* Skip earlier face edge crosses */ + lsrc += st2 * (tottri * 3 + totquad * 4); + + for(s = 0; s < sides; ++s) { + for(x = 0; x < st2; ++x) { + vvmap[dst + crossedgelen * (s + 1) - base - x * skip - 1] = lsrc; + ++lsrc; + } + } + + lvl = lvl->next; } + + dst += sides * (st - 1) * st; + + if(sides == 4) ++totquad; + else ++tottri; + } - -// XXX do this in caller DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + + /* calculate vert to edge/face maps for each level (except the last) */ + fmap = MEM_callocN(sizeof(ListBase*) * (mr->level_count-1), "multires fmap"); + emap = MEM_callocN(sizeof(ListBase*) * (mr->level_count-1), "multires emap"); + fmem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires fmem"); + emem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires emem"); + lvl = lvl1; + for(i = 0; i < mr->level_count - 1; ++i) { + create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface); + create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge); + lvl = lvl->next; + } + + /* Interior face verts */ + lvl = lvl1->next->next; + dst = 0; + for(j = 0; j < lvl1->totface; ++j) { + int sides = lvl1->faces[j].v[3] ? 4 : 3; + 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 st4 = st3 == 0 ? 1 : (st3 + 1) / 2; + int mid = ldst + st2 * st3 + st3; + int cv = lvl1->faces[j].v[s]; + int nv = lvl1->faces[j].v[s == sides - 1 ? 0 : s + 1]; + int pv = lvl1->faces[j].v[s == 0 ? sides - 1 : s - 1]; + + multires_load_old_faces(fmap, emap, lvl1->next, vvmap, mid, + vvmap[dst], cv, + find_old_edge(emap[0], lvl1->edges, pv, cv)->mid, + find_old_edge(emap[0], lvl1->edges, cv, nv)->mid, + st2, st4); + + ldst += (st - 1) * (st - 1); + } + + + dst = ldst; + } + + lvl = lvl->next; + + for(i = 0; i < mr->level_count - 1; ++i) { + MEM_freeN(fmap[i]); + MEM_freeN(fmem[i]); + MEM_freeN(emap[i]); + MEM_freeN(emem[i]); + } + + MEM_freeN(fmap); + MEM_freeN(emap); + MEM_freeN(fmem); + MEM_freeN(emem); } + + /* Transfer verts */ + for(i = 0; i < totvert; ++i) + VecCopyf(vdst[i].co, vsrc[vvmap[i]].co); + + MEM_freeN(vvmap); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index a59f1872263..49597f49759 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -707,7 +707,6 @@ void sculptsession_free(Scene *sce) } } -/* Default curve approximates 0.5 * (cos(pi * x) + 1), with 0 <= x <= 1 */ void sculpt_reset_curve(SculptData *sd) { CurveMap *cm = NULL; @@ -719,21 +718,15 @@ void sculpt_reset_curve(SculptData *sd) if(cm->curve) MEM_freeN(cm->curve); - cm->curve= MEM_callocN(6*sizeof(CurveMapPoint), "curve points"); + cm->curve= MEM_callocN(3*sizeof(CurveMapPoint), "curve points"); cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - cm->totpoint= 6; + cm->totpoint= 3; cm->curve[0].x= 0; cm->curve[0].y= 1; - cm->curve[1].x= 0.1; - cm->curve[1].y= 0.97553; - cm->curve[2].x= 0.3; - cm->curve[2].y= 0.79389; - cm->curve[3].x= 0.9; - cm->curve[3].y= 0.02447; - cm->curve[4].x= 0.7; - cm->curve[4].y= 0.20611; - cm->curve[5].x= 1; - cm->curve[5].y= 0; + cm->curve[1].x= 0.33; + cm->curve[1].y= 0.33; + cm->curve[2].x= 1; + cm->curve[2].y= 0; curvemapping_changed(sd->cumap, 0); } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 577a5ee5308..4f57470a586 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -48,6 +48,7 @@ #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_mesh.h" +#include "BKE_multires.h" #include "BKE_scene.h" #include "BKE_subsurf.h" @@ -471,7 +472,7 @@ static void calc_ss_weights(int gridFaces, static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, int drawInteriorEdges, int useSubsurfUv, - DerivedMesh *dm) + DerivedMesh *dm, MultiresSubsurf *ms) { DerivedMesh *result; int edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -524,14 +525,21 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, } ccgFaceIterator_free(fi); - if(dm) { - result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss), - ccgSubSurf_getNumFinalEdges(ss), - ccgSubSurf_getNumFinalFaces(ss)); - } else { - result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss), - ccgSubSurf_getNumFinalEdges(ss), - ccgSubSurf_getNumFinalFaces(ss)); + if(ms) { + result = MultiresDM_new(ms, dm, ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss)); + } + else { + if(dm) { + result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss)); + } else { + result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss)); + } } // load verts @@ -557,11 +565,12 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, ++mvert; ++origIndex; i++; - + for(S = 0; S < numVerts; S++) { int prevS = (S - 1 + numVerts) % numVerts; int nextS = (S + 1) % numVerts; int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + for(x = 1; x < gridFaces; x++) { float w[4]; w[prevS] = weight[x][0][0]; @@ -571,6 +580,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i); VecCopyf(mvert->co, ccgSubSurf_getFaceGridEdgeData(ss, f, S, x)); + *origIndex = ORIGINDEX_NONE; ++mvert; ++origIndex; @@ -582,6 +592,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, int prevS = (S - 1 + numVerts) % numVerts; int nextS = (S + 1) % numVerts; int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + for(y = 1; y < gridFaces; y++) { for(x = 1; x < gridFaces; x++) { float w[4]; @@ -2565,9 +2576,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, /***/ -struct DerivedMesh *subsurf_make_derived_from_derived( +struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( struct DerivedMesh *dm, struct SubsurfModifierData *smd, + struct MultiresSubsurf *ms, int useRenderParams, float (*vertCos)[3], int isFinalCalc, int editMode) { @@ -2599,7 +2611,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm); + useSubsurfUv, dm, ms); ccgSubSurf_free(ss); @@ -2630,7 +2642,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( return ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm); + useSubsurfUv, dm, ms); /*return (DerivedMesh *)getCCGDerivedMesh(smd->mCache, drawInteriorEdges, @@ -2650,7 +2662,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( useSubsurfUv, dm);*/ result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm); + useSubsurfUv, dm, ms); ccgSubSurf_free(ss); @@ -2659,6 +2671,15 @@ struct DerivedMesh *subsurf_make_derived_from_derived( } } +struct DerivedMesh *subsurf_make_derived_from_derived( + struct DerivedMesh *dm, + struct SubsurfModifierData *smd, + int useRenderParams, float (*vertCos)[3], + int isFinalCalc, int editMode) +{ + return subsurf_make_derived_from_derived_with_multires(dm, smd, NULL, useRenderParams, vertCos, isFinalCalc, editMode); +} + void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) { /* Finds the subsurf limit positions for the verts in a mesh diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 490e91fce15..5602f90c443 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -125,6 +125,7 @@ #include "BKE_main.h" // for Main #include "BKE_mesh.h" // for ME_ defines (patching) #include "BKE_modifier.h" +#include "BKE_multires.h" #include "BKE_node.h" // for tree type defines #include "BKE_object.h" #include "BKE_particle.h" @@ -2803,6 +2804,19 @@ static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts) } } +static void direct_link_mdisps(FileData *fd, int count, MDisps *mdisps) +{ + if(mdisps) { + int i; + + for(i = 0; i < count; ++i) { + mdisps[i].disps = newdataadr(fd, mdisps[i].disps); + if(!mdisps[i].disps) + mdisps[i].totdisp = 0; + } + } +} + static void direct_link_customdata(FileData *fd, CustomData *data, int count) { int i = 0; @@ -2814,6 +2828,8 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count) if (CustomData_verify_versions(data, i)) { layer->data = newdataadr(fd, layer->data); + if(layer->type == CD_MDISPS) + direct_link_mdisps(fd, count, layer->data); i++; } } @@ -2866,11 +2882,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) direct_link_dverts(fd, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT)); direct_link_customdata(fd, &mesh->mr->fdata, lvl->totface); - if(mesh->mr->edge_flags) - mesh->mr->edge_flags= newdataadr(fd, mesh->mr->edge_flags); - if(mesh->mr->edge_creases) - mesh->mr->edge_creases= newdataadr(fd, mesh->mr->edge_creases); - if(!mesh->mr->edge_flags) mesh->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "Multires Edge Flags"); if(!mesh->mr->edge_creases) @@ -2883,9 +2894,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) lvl->faces= newdataadr(fd, lvl->faces); lvl->edges= newdataadr(fd, lvl->edges); lvl->colfaces= newdataadr(fd, lvl->colfaces); - lvl->edge_boundary_states= NULL; - lvl->vert_face_map = lvl->vert_edge_map = NULL; - lvl->map_mem= NULL; } } @@ -3273,6 +3281,12 @@ 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; + } } } @@ -8491,8 +8505,78 @@ static void do_versions(FileData *fd, Library *lib, Main *main) strcpy(tx->nodetree->id.name, "NTTexture Nodetree"); } } - - + + /* TODO: should be moved into one of the version blocks once this branch moves to trunk and we can + bump the version (or sub-version.) */ + { + Object *ob; + int i; + + for(ob = main->object.first; ob; ob = ob->id.next) { + + if(ob->type == OB_MESH) { + Mesh *me = newlibadr(fd, lib, ob->data); + void *olddata = ob->data; + ob->data = me; + + if(me && me->mr) { + MultiresLevel *lvl; + ModifierData *md; + MultiresModifierData *mmd; + DerivedMesh *dm, *orig; + + /* Load original level into the mesh */ + lvl = me->mr->levels.first; + CustomData_free_layers(&me->vdata, CD_MVERT, lvl->totvert); + CustomData_free_layers(&me->edata, CD_MEDGE, lvl->totedge); + CustomData_free_layers(&me->fdata, CD_MFACE, lvl->totface); + me->totvert = lvl->totvert; + me->totedge = lvl->totedge; + me->totface = lvl->totface; + me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); + me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge); + me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); + memcpy(me->mvert, me->mr->verts, sizeof(MVert) * me->totvert); + for(i = 0; i < me->totedge; ++i) { + me->medge[i].v1 = lvl->edges[i].v[0]; + me->medge[i].v2 = lvl->edges[i].v[1]; + } + for(i = 0; i < me->totface; ++i) { + me->mface[i].v1 = lvl->faces[i].v[0]; + me->mface[i].v2 = lvl->faces[i].v[1]; + me->mface[i].v3 = lvl->faces[i].v[2]; + me->mface[i].v4 = lvl->faces[i].v[3]; + } + + /* Add a multires modifier to the object */ + md = ob->modifiers.first; + while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) + md = md->next; + mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires); + BLI_insertlinkbefore(&ob->modifiers, md, mmd); + + multiresModifier_subdivide(mmd, ob, me->mr->level_count - 1, 1, 0); + + mmd->lvl = mmd->totlvl; + orig = CDDM_from_mesh(me, NULL); + dm = multires_dm_create_from_derived(mmd, orig, me, 0, 0); + + multires_load_old(dm, me->mr); + + *MultiresDM_get_flags(dm) |= MULTIRES_DM_UPDATE_ALWAYS; + dm->release(dm); + orig->release(orig); + + /* Remove the old multires */ + multires_free(me->mr); + me->mr = NULL; + } + + ob->data = olddata; + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index ebc6cb4dcbd..1d17b471b0e 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -852,7 +852,7 @@ static void write_constraint_channels(WriteData *wd, ListBase *chanbase) } -static void write_modifiers(WriteData *wd, ListBase *modbase) +static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo) { ModifierData *md; @@ -903,10 +903,16 @@ 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 && write_undo) + writestruct(wd, DATA, "MVert", mmd->undo_verts_tot, mmd->undo_verts); + } } } -static void write_objects(WriteData *wd, ListBase *idbase) +static void write_objects(WriteData *wd, ListBase *idbase, int write_undo) { Object *ob; @@ -940,7 +946,7 @@ static void write_objects(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft); write_particlesystems(wd, &ob->particlesystem); - write_modifiers(wd, &ob->modifiers); + write_modifiers(wd, &ob->modifiers, write_undo); } ob= ob->id.next; } @@ -1138,7 +1144,7 @@ static void write_curves(WriteData *wd, ListBase *idbase) static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist) { if (dvlist) { - int i; + int i; /* Write the dvert list */ writestruct(wd, DATA, "MDeformVert", count, dvlist); @@ -1151,6 +1157,19 @@ static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist) } } +static void write_mdisps(WriteData *wd, int count, MDisps *mdlist) +{ + if(mdlist) { + int i; + + writestruct(wd, DATA, "MDisps", count, mdlist); + for(i = 0; i < count; ++i) { + if(mdlist[i].disps) + writedata(wd, DATA, sizeof(float)*3*mdlist[i].totdisp, mdlist[i].disps); + } + } +} + static void write_customdata(WriteData *wd, int count, CustomData *data, int partial_type, int partial_count) { int i; @@ -1166,6 +1185,9 @@ static void write_customdata(WriteData *wd, int count, CustomData *data, int par /* layer types that allocate own memory need special handling */ write_dverts(wd, count, layer->data); } + else if (layer->type == CD_MDISPS) { + write_mdisps(wd, count, layer->data); + } else { CustomData_file_write_info(layer->type, &structname, &structnum); if (structnum) { @@ -1186,7 +1208,6 @@ static void write_customdata(WriteData *wd, int count, CustomData *data, int par static void write_meshs(WriteData *wd, ListBase *idbase) { Mesh *mesh; - MultiresLevel *lvl; mesh= idbase->first; while(mesh) { @@ -1212,29 +1233,6 @@ static void write_meshs(WriteData *wd, ListBase *idbase) write_customdata(wd, mesh->totface, &mesh->fdata, -1, 0); } - /* Multires data */ - writestruct(wd, DATA, "Multires", 1, mesh->mr); - if(mesh->mr) { - lvl= mesh->mr->levels.first; - if(lvl) { - write_customdata(wd, lvl->totvert, &mesh->mr->vdata, -1, 0); - write_customdata(wd, lvl->totface, &mesh->mr->fdata, -1, 0); - writedata(wd, DATA, sizeof(short)*lvl->totedge, mesh->mr->edge_flags); - writedata(wd, DATA, sizeof(char)*lvl->totedge, mesh->mr->edge_creases); - } - - for(; lvl; lvl= lvl->next) { - writestruct(wd, DATA, "MultiresLevel", 1, lvl); - writestruct(wd, DATA, "MultiresFace", lvl->totface, lvl->faces); - writestruct(wd, DATA, "MultiresEdge", lvl->totedge, lvl->edges); - writestruct(wd, DATA, "MultiresColFace", lvl->totface, lvl->colfaces); - } - - lvl= mesh->mr->levels.last; - if(lvl) - writestruct(wd, DATA, "MVert", lvl->totvert, mesh->mr->verts); - } - /* PMV data */ if(mesh->pv) { writestruct(wd, DATA, "PartialVisibility", 1, mesh->pv); @@ -2098,7 +2096,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil write_groups (wd, &mainvar->group); write_armatures(wd, &mainvar->armature); write_actions (wd, &mainvar->action); - write_objects (wd, &mainvar->object); + write_objects (wd, &mainvar->object, (current != NULL)); write_materials(wd, &mainvar->mat); write_textures (wd, &mainvar->tex); write_meshs (wd, &mainvar->mesh); diff --git a/source/blender/editors/include/ED_multires.h b/source/blender/editors/include/ED_multires.h deleted file mode 100644 index e4726c02d7e..00000000000 --- a/source/blender/editors/include/ED_multires.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2006 by Nicholas Bishop - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef MULTIRES_H -#define MULTIRES_H - -struct CustomData; -struct EditMesh; -struct Object; -struct MDeformVert; -struct Mesh; -struct MultiresLevel; -struct Multires; -struct uiBlock; - -/* For canceling operations that don't work with multires on or on a non-base level */ -int multires_test(); -int multires_level1_test(); - -void multires_draw_interface(struct uiBlock *block, unsigned short cx, unsigned short cy); - -void multires_make(void *ob, void *me); -void multires_delete(void *ob, void *me); -void multires_level_to_editmesh(struct Object *ob, struct Mesh *me, const int render); -void multires_finish_mesh_update(struct Object *ob); -void multires_subdivide(void *ob, void *me); -void multires_del_lower(void *ob, void *me); -void multires_del_higher(void *ob, void *me); -void multires_set_level_cb(void *ob, void *me); -void multires_edge_level_update_cb(void *ob, void *me); -int multires_modifier_warning(); - -#endif diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index e1a358a9e06..49c8fe648d7 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -56,7 +56,6 @@ #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_mesh.h" -#include "BKE_multires.h" #include "BKE_object.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -628,14 +627,8 @@ static void make_tfaces(Object *ob) Mesh *me= ob->data; if(!me->mtface) { - if(me->mr) { - multires_add_layer(ob, &me->mr->fdata, CD_MTFACE, - CustomData_number_of_layers(&me->fdata, CD_MTFACE)); - } - else { - me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, - NULL, me->totface); - } + me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, + NULL, me->totface); } } diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c index b7ffe65d6ef..b91fc0e1d01 100644 --- a/source/blender/editors/mesh/editmesh.c +++ b/source/blender/editors/mesh/editmesh.c @@ -66,7 +66,6 @@ #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_modifier.h" -#include "BKE_multires.h" #include "BKE_object.h" #include "BKE_pointcache.h" #include "BKE_softbody.h" @@ -97,7 +96,6 @@ static void waitcursor() {} static void error() {} static int pupmenu() {return 0;} static void key_to_mesh() {} -static int multires_test() {return 0;} static void adduplicate() {} @@ -1443,7 +1441,6 @@ void separate_mesh(Scene *scene, Object *obedit) ListBase edve, eded, edvl; if(obedit==NULL) return; - if(multires_test()) return; waitcursor(1); @@ -1572,8 +1569,6 @@ void separate_material(Scene *scene, Object *obedit) EditMesh *em; unsigned char curr_mat; - if(multires_test()) return; - me= obedit->data; em= me->edit_mesh; if(me->key) { @@ -1620,7 +1615,6 @@ void separate_mesh_loose(Scene *scene, Object *obedit) return; } - if(multires_test()) return; waitcursor(1); /* we are going to abuse the system as follows: @@ -1830,11 +1824,6 @@ typedef struct EditSelectionC{ int index; }EditSelectionC; -typedef struct EM_MultiresUndo { - int users; - Multires *mr; -} EM_MultiresUndo; - typedef struct UndoMesh { EditVertC *verts; EditEdgeC *edges; @@ -1845,7 +1834,6 @@ typedef struct UndoMesh { RetopoPaintData *retopo_paint_data; char retopo_mode; CustomData vdata, edata, fdata; - EM_MultiresUndo *mru; } UndoMesh; /* for callbacks */ @@ -1865,14 +1853,6 @@ static void free_undoMesh(void *umv) CustomData_free(&um->vdata, um->totvert); CustomData_free(&um->edata, um->totedge); CustomData_free(&um->fdata, um->totface); - if(um->mru) { - --um->mru->users; - if(um->mru->users==0) { - multires_free(um->mru->mr); - um->mru->mr= NULL; - MEM_freeN(um->mru); - } - } MEM_freeN(um); } @@ -1973,25 +1953,6 @@ static void *editMesh_to_undoMesh(void *emv) // XXX um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data); // um->retopo_mode= scene->toolsettings->retopo_mode; - { - Multires *mr= NULL; // XXX old-style multires - UndoMesh *prev= NULL; // XXX undo_editmode_get_prev(obedit); - - um->mru= NULL; - - if(mr) { - if(prev && prev->mru && prev->mru->mr && prev->mru->mr->current == mr->current) { - um->mru= prev->mru; - ++um->mru->users; - } - else { - um->mru= MEM_callocN(sizeof(EM_MultiresUndo), "EM_MultiresUndo"); - um->mru->users= 1; - um->mru->mr= multires_copy(mr); - } - } - } - return um; } @@ -2101,12 +2062,6 @@ static void undoMesh_to_editMesh(void *umv, void *emv) // retopo_paint_view_update(G.vd); // } - { - Mesh *me= NULL; // XXX; - multires_free(me->mr); - me->mr= NULL; - if(um->mru && um->mru->mr) me->mr= multires_copy(um->mru->mr); - } } static void *getEditMesh(bContext *C) diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 91e1997a8f5..d186d264e9c 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -58,7 +58,6 @@ #include "BIF_retopo.h" #include "ED_mesh.h" -#include "ED_multires.h" #include "ED_view3d.h" #include "mesh_intern.h" @@ -138,8 +137,6 @@ void add_click_mesh(Scene *scene, Object *obedit, EditMesh *em) float min[3], max[3]; int done= 0; - if(multires_test()) return; - INIT_MINMAX(min, max); for(v1= em->verts.first;v1; v1=v1->next) { @@ -610,8 +607,6 @@ void addedgeface_mesh(EditMesh *em) EditFace *efa; short amount=0; - if(multires_test()) return; - /* how many selected ? */ if(em->selectmode & SCE_SELECT_EDGE) { /* in edge mode finding selected vertices means flushing down edge codes... */ @@ -741,8 +736,6 @@ void addedgeface_mesh(EditMesh *em) void adduplicate_mesh(Scene *scene, Object *obedit, EditMesh *em) { - if(multires_test()) return; - waitcursor(1); adduplicateflag(em, SELECT); @@ -1250,8 +1243,6 @@ void add_primitiveMesh(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, /* this function also comes from an info window */ // XXX if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return; - if (obedit && obedit->type==OB_MESH && multires_test()) return; - /* if editmode exists for other type, it exits */ check_editmode(OB_MESH); diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index 375ebde5f52..d5855325354 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -79,7 +79,6 @@ editmesh_mods.c, UI level access, no geometry changes #include "RNA_access.h" #include "RNA_define.h" -#include "ED_multires.h" #include "ED_mesh.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -3346,8 +3345,6 @@ void editmesh_mark_seam(EditMesh *em, int clear) { EditEdge *eed; -// XXX if(multires_level1_test()) return; - /* auto-enable seams drawing */ if(clear==0) { if(!(G.f & G_DRAWSEAMS)) { @@ -3391,8 +3388,6 @@ void editmesh_mark_sharp(EditMesh *em, int set) } #endif -// XXX if(multires_level1_test()) return; - if(set) { eed= em->edges.first; while(eed) { diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 024ef433f1b..4257480d96d 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -78,7 +78,6 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise #include "BMF_Api.h" -#include "ED_multires.h" #include "ED_mesh.h" #include "ED_view3d.h" @@ -143,8 +142,6 @@ void convert_to_triface(EditMesh *em, int direction) EditFace *efa, *efan, *next; float fac; - if(multires_test()) return; - efa= em->faces.last; while(efa) { next= efa->prev; @@ -196,8 +193,6 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) / struct facesort *vlsortblock, *vsb, *vsb1; int a, b, test, amount; - if(multires_test()) return 0; - /* flag 128 is cleared, count */ @@ -499,8 +494,6 @@ void xsortvert_flag(bContext *C, int flag) ListBase tbase; int i, amount; - if(multires_test()) return; - em_setup_viewcontext(C, &vc); amount = BLI_countlist(&vc.em->verts); @@ -540,8 +533,6 @@ void hashvert_flag(EditMesh *em, int flag) ListBase tbase; int amount, a, b; - if(multires_test()) return; - /* count */ eve= em->verts.first; amount= 0; @@ -600,8 +591,6 @@ void extrude_mesh(Object *obedit, EditMesh *em) float nor[3]= {0.0, 0.0, 0.0}; short nr, transmode= 0; - if(multires_test()) return; - if(em->selectmode & SCE_SELECT_VERTEX) { if(G.totvertsel==0) nr= 0; else if(G.totvertsel==1) nr= 4; @@ -673,8 +662,6 @@ void extrude_mesh(Object *obedit, EditMesh *em) void split_mesh(EditMesh *em) { - if(multires_test()) return; - if(okee(" Split ")==0) return; waitcursor(1); @@ -698,8 +685,6 @@ void extrude_repeat_mesh(View3D *v3d, Object *obedit, EditMesh *em, int steps, f float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0}; short a; - if(multires_test()) return; - /* dvec */ dvec[0]= v3d->persinv[2][0]; dvec[1]= v3d->persinv[2][1]; @@ -737,8 +722,6 @@ void spin_mesh(View3D *v3d, Object *obedit, EditMesh *em, int steps, float degr, float phi; short a,ok; - if(multires_test()) return; - /* imat and center and size */ Mat3CpyMat4(bmat, obedit->obmat); Mat3Inv(imat,bmat); @@ -821,8 +804,6 @@ void screw_mesh(Object *obedit, EditMesh *em, int steps, int turns) EditEdge *eed; float dvec[3], nor[3]; - if(multires_test()) return; - /* clear flags */ eve= em->verts.first; while(eve) { @@ -933,8 +914,6 @@ void delete_mesh(Object *obedit, EditMesh *em) int count; char *str="Erase"; - if(multires_test()) return; - event= pupmenu("Erase %t|Vertices%x10|Edges%x1|Faces%x2|All%x3|Edges & Faces%x4|Only Faces%x5|Edge Loop%x6"); if(event<1) return; @@ -1078,8 +1057,6 @@ void fill_mesh(EditMesh *em) short ok; if(em==NULL) return; - if(multires_test()) return; - waitcursor(1); /* copy all selected vertices */ @@ -2372,8 +2349,6 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float rad, int beaut ModifierData *md= obedit->modifiers.first; int ctrl= 0; // XXX - if(multires_test()) return; - //Set faces f1 to 0 cause we need it later for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0; for(eve=em->verts.first; eve; eve=eve->next) { @@ -2930,8 +2905,6 @@ void beauty_fill(EditMesh *em) float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2; int totedge, ok, notbeauty=8, onedone, vindex[4]; - if(multires_test()) return; - /* - all selected edges with two faces * - find the faces: store them in edges (using datablock) * - per edge: - test convex @@ -3238,9 +3211,6 @@ void join_triangles(EditMesh *em) float limit = 0.0f; // XXX scene->toolsettings->jointrilimit; int i, ok, totedge=0, totseledge=0, complexedges, vindex[4]; - /*test for multi-resolution data*/ - if(multires_test()) return; - /*if we take a long time on very dense meshes we want waitcursor to display*/ waitcursor(1); @@ -5586,8 +5556,6 @@ int collapseEdges(EditMesh *em) mergecount = 0; - if(multires_test()) return 0; - build_edgecollection(em, &allcollections); groupcount = BLI_countlist(&allcollections); @@ -5646,8 +5614,6 @@ int merge_firstlast(EditMesh *em, int first, int uvmerge) EditVert *eve,*mergevert; EditSelection *ese; - if(multires_test()) return 0; - /* do sanity check in mergemenu in edit.c ?*/ if(first == 0){ ese = em->selected.last; @@ -5681,8 +5647,6 @@ int merge_target(EditMesh *em, int target, int uvmerge) { EditVert *eve; - if(multires_test()) return 0; - if(target) snap_sel_to_curs(); else snap_to_center(); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index c92b3754e2a..8b749b3e829 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -98,7 +98,6 @@ #include "BKE_material.h" #include "BKE_mball.h" #include "BKE_mesh.h" -#include "BKE_multires.h" #include "BKE_nla.h" #include "BKE_object.h" #include "BKE_particle.h" @@ -2285,9 +2284,6 @@ void ED_object_exit_editmode(bContext *C, int flag) if(freedata) obedit= NULL; scene->obedit= obedit; // XXX for context - if(ob->type==OB_MESH && get_mesh(ob)->mr) - multires_edge_level_update(ob, get_mesh(ob)); - /* also flush ob recalc, doesn't take much overhead, but used for particles */ DAG_object_flush_update(scene, ob, OB_RECALC_OB|OB_RECALC_DATA); diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 7995ce44ec3..510ccfb67fc 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -74,7 +74,8 @@ typedef struct CustomData { #define CD_MLOOPUV 16 #define CD_MLOOPCOL 17 #define CD_TANGENT 18 -#define CD_NUMTYPES 19 +#define CD_MDISPS 19 +#define CD_NUMTYPES 20 /* fake type, derivedmesh wants CustomDataMask for weightpaint too, is not stored */ #define CD_WEIGHTPAINT 30 @@ -98,6 +99,7 @@ typedef struct CustomData { #define CD_MASK_MLOOPUV (1 << CD_MLOOPUV) #define CD_MASK_MLOOPCOL (1 << CD_MLOOPCOL) #define CD_MASK_TANGENT (1 << CD_TANGENT) +#define CD_MASK_MDISPS (1 << CD_MDISPS) /* derivedmesh wants CustomDataMask for weightpaint too, is not customdata though */ #define CD_MASK_WEIGHTPAINT (1 << CD_WEIGHTPAINT) diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 9504c3c6322..c07989b2ce6 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -117,7 +117,14 @@ typedef struct OrigSpaceFace { float uv[4][2]; } OrigSpaceFace; -/* Multiresolution modeling */ +typedef struct MDisps { + /* Strange bug in SDNA: if disps pointer comes first, it fails to see totdisp */ + int totdisp; + char pad[4]; + float (*disps)[3]; +} MDisps; + +/** Multires structs kept for compatibility with old files **/ typedef struct MultiresCol { float a, r, g, b; } MultiresCol; @@ -143,15 +150,9 @@ typedef struct MultiresLevel { MultiresColFace *colfaces; MultiresEdge *edges; - /* Temporary connectivity data */ - char *edge_boundary_states; - struct ListBase *vert_edge_map; - struct ListBase *vert_face_map; - struct MultiresMapNode *map_mem; - unsigned int totvert, totface, totedge, pad; - /* Kept for compatibility with older files */ + /* Kept for compatibility with even older files */ MVert *verts; } MultiresLevel; @@ -169,6 +170,8 @@ typedef struct Multires { char *edge_creases; } Multires; +/** End Multires **/ + typedef struct PartialVisibility { unsigned int *vert_map; /* vert_map[Old Index]= New Index */ int *edge_map; /* edge_map[Old Index]= New Index, -1= hidden */ @@ -266,7 +269,4 @@ typedef struct PartialVisibility { #define TF_PIN3 64 #define TF_PIN4 128 -/* multires->flag */ -#define MULTIRES_NO_RENDER 1 - #endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 88c75f1bccd..68d68d79db9 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -39,6 +39,7 @@ typedef enum ModifierType { eModifierType_Fluidsim, eModifierType_Mask, eModifierType_SimpleDeform, + eModifierType_Multires, NUM_MODIFIER_TYPES } ModifierType; @@ -517,6 +518,17 @@ typedef struct ExplodeModifierData { float protect; } 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; +} MultiresModifierData; + typedef struct FluidsimModifierData { ModifierData modifier; diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 3c6872ae2e7..ea06ca0b640 100755 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -30,10 +30,194 @@ #include "rna_internal.h" #include "DNA_action_types.h" +#include "DNA_armature_types.h" #ifdef RNA_RUNTIME -#endif +static float rna_IK_Min_X_get(PointerRNA *ptr) +{ + bPoseChannel *pchan= (bPoseChannel*)ptr->id.data; + + return pchan->limitmin[0]; +} + +static float rna_IK_Min_Y_get(PointerRNA *ptr) +{ + bPoseChannel *pchan= (bPoseChannel*)ptr->id.data; + + return pchan->limitmin[1]; +} + +static float rna_IK_Min_Z_get(PointerRNA *ptr) +{ + bPoseChannel *pchan= (bPoseChannel*)ptr->id.data; + + return pchan->limitmin[2]; +} + +static void rna_IK_Min_X_set(PointerRNA *ptr, float value) +{ + bPoseChannel *pchan= (bPoseChannel*)ptr->id.data; + + pchan->limitmin[0] = value; +} + +static void rna_IK_Min_Y_set(PointerRNA *ptr, float value) +{ + bPoseChannel *pchan= (bPoseChannel*)ptr->id.data; + + pchan->limitmin[1] = value; +} + +static void rna_IK_Min_Z_set(PointerRNA *ptr, float value) +{ + bPoseChannel *pchan= (bPoseChannel*)ptr->id.data; + + pchan->limitmin[2] = value; +} + +#else + +/* users shouldn't be editing pose channel data directly -- better to set ipos and let blender calc pose_channel stuff */ +/* it's going to be weird for users to find IK flags and other such here, instead of in bone where they would expect them + -- is there any way to put a doc in bone, pointing them here? */ + +static void RNA_def_pose_channel(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem prop_iklimit_items[] = { + {BONE_IK_NO_XDOF, "IKNOXDOF", "No X DoF", "Prevent motion around X axis."}, + {BONE_IK_NO_YDOF, "IKNOYDOF", "No Y DoF", "Prevent motion around Y axis."}, + {BONE_IK_NO_ZDOF, "IKNOZDOF", "No Z DoF", "Prevent motion around Z axis."}, + {BONE_IK_XLIMIT, "IKXLIMIT", "X Limit", "Limit motion around X axis."}, + {BONE_IK_YLIMIT, "IKYLIMIT", "Y Limit", "Limit motion around Y axis."}, + {BONE_IK_ZLIMIT, "IKZLIMIT", "Z Limit", "Limit motion around Z axis."}, + {0, NULL, NULL, NULL}}; + + srna= RNA_def_struct(brna, "bPoseChannel", NULL); + RNA_def_struct_ui_text(srna, "Pose Channel", "Member of the 'Pose' type."); + + /* cosntraints (collection) */ + prop= RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "constraints", NULL); + RNA_def_property_struct_type(prop, "bConstraint"); + RNA_def_property_ui_text(prop, "Constraints", "Constraints that act on this PoseChannel."); + + prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Name", ""); + RNA_def_struct_name_property(srna, prop); + + prop= RNA_def_property(srna, "ikflag", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_iklimit_items); + RNA_def_property_ui_text(prop, "IK Limits", ""); + + prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "selectflag", BONE_SELECTED); + RNA_def_property_ui_text(prop, "Selected", ""); + + prop= RNA_def_property(srna, "protected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "protectflag", POSE_LOCKED); + RNA_def_property_ui_text(prop, "Protected", "Protect channel from being transformed."); + + prop= RNA_def_property(srna, "action_group_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "agrp_index"); + RNA_def_property_ui_text(prop, "Action Group Index", "Action Group this pose channel belogs to (0=no group)."); + + prop= RNA_def_property(srna, "path_start_frame", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "pathsf"); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Bone Paths Calculation Start Frame", "Starting frame of range of frames to use for Bone Path calculations."); + + prop= RNA_def_property(srna, "path_end_frame", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "pathef"); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Bone Paths Calculation End Frame", "End frame of range of frames to use for Bone Path calculations."); + + prop= RNA_def_property(srna, "bone", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Bone"); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Bone", "Bone associated with this Pose Channel."); + + prop= RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "bPoseChannel"); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Parent", "Parent of this pose channel."); + + prop= RNA_def_property(srna, "child", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "bPoseChannel"); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Parent", "Child of this pose channel."); + + prop= RNA_def_property(srna, "channel_matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_struct_type(prop, "chan_mat"); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Channel Matrix", "4x4 matrix, before constraints."); + + /* kaito says this should be not user-editable; I disagree; power users should be able to force this in python; he's the boss. */ + prop= RNA_def_property(srna, "pose_matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_struct_type(prop, "pose_mat"); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Pose Matrix", "Final 4x4 matrix for this channel."); + + prop= RNA_def_property(srna, "constraint_inverse_matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_struct_type(prop, "constinv"); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Constraint Inverse Matrix", "4x4 matrix, defines transform from final position to unconstrained position."); + + prop= RNA_def_property(srna, "pose_head", PROP_FLOAT, PROP_VECTOR); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Pose Head Position", "Location of head of the channel's bone."); + + prop= RNA_def_property(srna, "pose_tail", PROP_FLOAT, PROP_VECTOR); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_ui_text(prop, "Pose Tail Position", "Location of tail of the channel's bone."); + + prop= RNA_def_property(srna, "ik_min_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "limitmin"); + RNA_def_property_range(prop, -180.0f, 180.0f); + RNA_def_property_float_funcs(prop, "rna_IK_Min_X_get", "rna_IK_Min_X_set", NULL); + RNA_def_property_ui_text(prop, "IK Minimum Limit X", "Minimum X angle for IK Limit"); + + prop= RNA_def_property(srna, "ik_min_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "limitmin"); + RNA_def_property_range(prop, -180.0f, 180.0f); + RNA_def_property_float_funcs(prop, "rna_IK_Min_Y_get", "rna_IK_Min_Y_set", NULL); + RNA_def_property_ui_text(prop, "IK Minimum Limit Y", "Minimum Y angle for IK Limit"); + + prop= RNA_def_property(srna, "ik_min_z", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "limitmin"); + RNA_def_property_range(prop, -180.0f, 180.0f); + RNA_def_property_float_funcs(prop, "rna_IK_Min_Z_get", "rna_IK_Min_Z_set", NULL); + RNA_def_property_ui_text(prop, "IK Minimum Limit Z", "Minimum Z angle for IK Limit"); + + prop= RNA_def_property(srna, "ik_max_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "limitmax"); + RNA_def_property_range(prop, -180.0f, 180.0f); + RNA_def_property_float_funcs(prop, "rna_IK_Max_X_get", "rna_IK_Max_X_set", NULL); + RNA_def_property_ui_text(prop, "IK Maximum Limit X", "Maximum X angle for IK Limit"); + + prop= RNA_def_property(srna, "ik_max_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "limitmax"); + RNA_def_property_range(prop, -180.0f, 180.0f); + RNA_def_property_float_funcs(prop, "rna_IK_Max_Y_get", "rna_IK_Max_Y_set", NULL); + RNA_def_property_ui_text(prop, "IK Maximum Limit Y", "Maximum Y angle for IK Limit"); + + prop= RNA_def_property(srna, "ik_max_z", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "limitmax"); + RNA_def_property_range(prop, -180.0f, 180.0f); + RNA_def_property_float_funcs(prop, "rna_IK_Max_Z_get", "rna_IK_Max_Z_set", NULL); + RNA_def_property_ui_text(prop, "IK Maximum Limit Z", "Maximum Z angle for IK Limit"); + +// float limitmin[3], limitmax[3]; /* DOF constraint */ +// float stiffness[3]; /* DOF stiffness */ +// float ikstretch; + +// float *path; /* totpath x 3 x float */ +// struct Object *custom; /* draws custom object instead of this channel */ +}; void RNA_def_action(BlenderRNA *brna) { @@ -45,3 +229,5 @@ void RNA_def_action(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Action", "DOC_BROKEN"); } + +#endif diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 1768b052b54..34553208574 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -505,7 +505,6 @@ typedef struct LampRen { #define R_LAMPHALO 8 #define R_GLOB_NOPUNOFLIP 16 #define R_NEED_TANGENT 32 -#define R_SKIP_MULTIRES 64 #define R_BAKE_TRACE 128 #define R_BAKING 256 diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index b36f4337235..3149b711a27 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -99,7 +99,6 @@ #include "IMB_imbuf_types.h" #include "envmap.h" -//XXX #include "multires.h" #include "occlusion.h" #include "render_types.h" #include "rendercore.h" @@ -3077,13 +3076,6 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if(need_orco) mask |= CD_MASK_ORCO; - if(me->mr) { - if(re->flag & R_SKIP_MULTIRES) - me->mr->flag |= MULTIRES_NO_RENDER; - else - me->mr->flag &= ~MULTIRES_NO_RENDER; - } - dm= mesh_create_derived_render(re->scene, ob, mask); if(dm==NULL) return; /* in case duplicated object fails? */ @@ -5432,8 +5424,6 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) re->flag |= R_GLOB_NOPUNOFLIP; re->flag |= R_BAKING; re->excludeob= actob; - if(type == RE_BAKE_LIGHT) - re->flag |= R_SKIP_MULTIRES; if(actob) re->flag |= R_BAKE_TRACE; |