diff options
author | Nicholas Bishop <nicholasbishop@gmail.com> | 2008-08-14 03:26:25 +0400 |
---|---|---|
committer | Nicholas Bishop <nicholasbishop@gmail.com> | 2008-08-14 03:26:25 +0400 |
commit | 877f1518ecda9e7542dfe43264ab69f5655f1cfe (patch) | |
tree | 10f66545deeb24eb6801a5e79a08345e8754eebb /source/blender | |
parent | 2882148a3d814c5d8043b838fae092fb2d11fbdd (diff) |
_Finally_ got the conversion from old multires files to the new kind working. Still some cleanups to do, and a couple of performance fixes, but it works OK now.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_multires.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/multires.c | 291 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 80 |
3 files changed, 368 insertions, 5 deletions
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 91417591d98..3273c484a33 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -126,6 +126,8 @@ typedef struct MultiresDisplacer { int x, y, ax, ay; } MultiresDisplacer; + +void multires_load_old(struct DerivedMesh *, struct Multires *); void multires_force_update(struct Object *ob); struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*, struct DerivedMesh*, diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 8f23c8f60fa..24a42f7f838 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -817,6 +817,297 @@ static const int multires_quad_tot[] = {4, 9, 25, 81, 289, 1089, 4225, 16641, 66 static const int multires_tri_tot[] = {3, 7, 19, 61, 217, 817, 3169, 12481, 49537, 197377, 787969, 3148801, 12589057}; static const int multires_side_tot[] = {2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; +static void create_old_vert_face_map(ListBase **map, IndexNode **mem, const MultiresFace *mface, + const int totvert, const int totface) +{ + 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); + } + } +} + +static void create_old_vert_edge_map(ListBase **map, IndexNode **mem, const MultiresEdge *medge, + const int totvert, const int totedge) +{ + 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); + } + } +} + +static MultiresFace *find_old_face(ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4) +{ + IndexNode *n1; + int v[4] = {v1, v2, v3, v4}, i, j; + + for(n1 = map[v1].first; n1; n1 = n1->next) { + int fnd[4] = {0, 0, 0, 0}; + + 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]; + } + + return NULL; +} + +static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2) +{ + IndexNode *n1, *n2; + + 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]; + } + } + + return NULL; +} + +static void multires_load_old_edges(ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov) +{ + 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); + } +} + +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; + + if(lvl && lvl->next) { + fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid; + vvmap[dst] = fmid; + + 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; + + + 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); + } + } +} + +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; + } + + /* 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; + } + } + + /* 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; + } + + + /* The rest is only for level 3 and up */ + if(lvl1->next && lvl1->next->next) { + ListBase **fmap, **emap; + IndexNode **fmem, **emem; + + /* 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; + + lvl = lvl1->next->next; + ++dst; + + for(j = 3; j <= mr->level_count; ++j) { + int base = multires_side_tot[totlvl - j] - 2; + int skip = multires_side_tot[totlvl - j + 1] - 1; + int st = pow(2, j - 2); + int st2 = pow(2, j - 3); + int lsrc = lvl->prev->totvert; + + /* Skip exterior edge verts */ + lsrc += lvl1->totedge * st; + + /* 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; + + } + + /* calculate vert to edge/face maps for each level */ + fmap = MEM_callocN(sizeof(ListBase*) * mr->level_count, "multires fmap"); + emap = MEM_callocN(sizeof(ListBase*) * mr->level_count, "multires emap"); + fmem = MEM_callocN(sizeof(IndexNode*) * mr->level_count, "multires fmem"); + emem = MEM_callocN(sizeof(IndexNode*) * mr->level_count, "multires emem"); + lvl = lvl1; + for(i = 0; i < mr->level_count; ++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; + for(i = 3; i <= 3/*(mr->level_count*/; ++i) { + tottri = totquad = 0; + 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; + if(sides == 4) ++totquad; + else ++tottri; + } + + lvl = lvl->next; + } + + for(i = 0; i < mr->level_count; ++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); +} + int multiresModifier_switch_level(Object *ob, const int distance) { ModifierData *md = NULL; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 914bc39a0bd..c7893bcfaf0 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -115,6 +115,7 @@ #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_cdderivedmesh.h" #include "BKE_cloth.h" #include "BKE_colortools.h" #include "BKE_constraint.h" @@ -132,6 +133,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" @@ -2812,11 +2814,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) 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) - mesh->mr->edge_creases= MEM_callocN(sizeof(char)*lvl->totedge, "Multires Edge Creases"); - mesh->mr->verts = newdataadr(fd, mesh->mr->verts); for(; lvl; lvl= lvl->next) { @@ -7746,6 +7743,79 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + /* 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); + + for(i = 1; i < me->mr->level_count; ++i) + multiresModifier_subdivide(mmd, ob); + + 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! */ |