Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2008-08-14 03:26:25 +0400
committerNicholas Bishop <nicholasbishop@gmail.com>2008-08-14 03:26:25 +0400
commit877f1518ecda9e7542dfe43264ab69f5655f1cfe (patch)
tree10f66545deeb24eb6801a5e79a08345e8754eebb /source/blender
parent2882148a3d814c5d8043b838fae092fb2d11fbdd (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.h2
-rw-r--r--source/blender/blenkernel/intern/multires.c291
-rw-r--r--source/blender/blenloader/intern/readfile.c80
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! */