diff options
author | Nicholas Bishop <nicholasbishop@gmail.com> | 2008-06-21 22:20:32 +0400 |
---|---|---|
committer | Nicholas Bishop <nicholasbishop@gmail.com> | 2008-06-21 22:20:32 +0400 |
commit | a076ff140863cbca99bad900a9795ba566db3aa8 (patch) | |
tree | 700589c6e4909f671b151334ba2d681a9104736a /source/blender/blenkernel/intern | |
parent | 5de9776575d15e9f2cb13ec174d9a560c52b63e2 (diff) |
Displacements over subdivided edges work correctly now (both for display and updating the highest level.)
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 36 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/multires.c | 117 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 20 |
3 files changed, 156 insertions, 17 deletions
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 73af2c61cf8..281cfabdb2e 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" @@ -1148,9 +1149,15 @@ typedef struct MultiresDM { int lvl, totlvl; float (*orco)[3]; float (*subco)[3]; + MEdge *ored; MFace *orfa; + int totorco; + int totored; int totorfa; + ListBase *vert_face_map; + IndexNode *vert_face_map_mem; + void (*update)(DerivedMesh*); } MultiresDM; @@ -1163,9 +1170,14 @@ static void MultiresDM_release(DerivedMesh *dm) mrdm->update(dm); if(DM_release(dm)) { + MEM_freeN(mrdm->ored); MEM_freeN(mrdm->orfa); 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); MEM_freeN(mrdm); } } @@ -1197,8 +1209,11 @@ DerivedMesh *MultiresDM_new(DerivedMesh *orig, int numVerts, int numEdges, int n 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); + mrdm->totorco = orig->getNumVerts(orig); mrdm->orfa = MEM_dupallocN(CustomData_get_layer(&orig->faceData, CD_MFACE)); mrdm->totorfa = orig->getNumFaces(orig); + mrdm->ored = MEM_dupallocN(CustomData_get_layer(&orig->edgeData, CD_MEDGE)); + mrdm->totored = orig->getNumEdges(orig); } else DM_init(dm, numVerts, numEdges, numFaces); @@ -1241,6 +1256,16 @@ int MultiresDM_get_totorfa(struct DerivedMesh *dm) return ((MultiresDM*)dm)->totorfa; } +MEdge *MultiresDM_get_ored(DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->ored; +} + +int MultiresDM_get_totored(struct DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->totored; +} + int MultiresDM_get_totlvl(DerivedMesh *dm) { return ((MultiresDM*)dm)->totlvl; @@ -1260,3 +1285,14 @@ 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->orfa, + mrdm->totorco, mrdm->totorfa); + + return mrdm->vert_face_map; +} diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index c41e1cce463..7bf9366a2d1 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1309,6 +1309,24 @@ void multires_edge_level_update(Object *ob, Mesh *me) } } +void create_vert_face_map(ListBase **map, IndexNode **mem, const MFace *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].v4?4:3); ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[((unsigned int*)(&mface[i]))[j]], node); + } + } +} + /* 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}; @@ -1414,29 +1432,31 @@ void multiresModifier_setLevel(void *mmd_v, void *ob_v) } void multires_displacer_init(MultiresDisplacer *d, DerivedMesh *dm, - const int face_index, const int sides, const int invert) + const int face_index, const int invert) { - MFace *face; float inv[3][3]; - face = MultiresDM_get_orfa(dm) + face_index; + d->face = MultiresDM_get_orfa(dm) + face_index; /* Get the multires grid from customdata and calculate the TS matrix */ d->grid = (MDisps*)dm->getFaceDataArray(dm, CD_MDISPS); if(d->grid) d->grid += face_index; - d->subco = MultiresDM_get_subco(dm); - calc_face_ts_mat_dm(d->mat, MultiresDM_get_orco(dm), face); + calc_face_ts_mat_dm(d->mat, MultiresDM_get_orco(dm), d->face); if(invert) { Mat3Inv(inv, d->mat); Mat3CpyMat3(d->mat, inv); } - d->sides = sides; d->spacing = pow(2, MultiresDM_get_totlvl(dm) - MultiresDM_get_lvl(dm)); d->sidetot = multires_side_tot[MultiresDM_get_totlvl(dm) - 1]; d->invert = invert; } +void multires_displacer_weight(MultiresDisplacer *d, const float w) +{ + d->weight = w; +} + void multires_displacer_anchor(MultiresDisplacer *d, const int type, const int side_index) { d->sidendx = side_index; @@ -1476,6 +1496,46 @@ void multires_displacer_anchor(MultiresDisplacer *d, const int type, const int s d->ay = d->y; } +void multires_displacer_anchor_edge(MultiresDisplacer *d, int v1, int v2, int x) +{ + const int mov = d->spacing * x; + + d->type = 4; + + if(v1 == d->face->v1) { + d->x = 0; + d->y = 0; + if(v2 == d->face->v2) + d->x += mov; + else + d->y += mov; + } + else if(v1 == d->face->v2) { + d->x = d->sidetot - 1; + d->y = 0; + if(v2 == d->face->v1) + d->x -= mov; + else + d->y += mov; + } + else if(v1 == d->face->v3) { + d->x = d->sidetot - 1; + d->y = d->sidetot - 1; + if(v2 == d->face->v2) + d->y -= mov; + else + d->x -= mov; + } + else if(v1 == d->face->v4) { + d->x = 0; + d->y = d->sidetot - 1; + if(v2 == d->face->v3) + d->x += mov; + else + d->y -= mov; + } +} + void multires_displacer_jump(MultiresDisplacer *d) { if(d->sidendx == 0) { @@ -1505,10 +1565,8 @@ void multires_displace(MultiresDisplacer *d, float co[3]) data = d->grid->disps[d->y * d->sidetot + d->x]; - if(d->invert) { + if(d->invert) VecSubf(disp, co, *d->subco); - ++d->subco; - } else VecCopyf(disp, data); @@ -1518,8 +1576,11 @@ void multires_displace(MultiresDisplacer *d, float co[3]) VecCopyf(data, disp); } - else + else { + if(d->type == 4) + VecMulf(disp, d->weight); VecAddf(co, co, disp); + } if(d->type == 2) { if(d->sidendx == 0) @@ -1547,6 +1608,7 @@ static void multiresModifier_update(DerivedMesh *dm) { MDisps *mdisps; MVert *mvert; + MEdge *medge; MFace *mface; int i; @@ -1557,29 +1619,34 @@ static void multiresModifier_update(DerivedMesh *dm) if(mdisps) { MultiresDisplacer d; - float (*subco)[3] = MultiresDM_get_subco(dm); + const int gridFaces = multires_side_tot[MultiresDM_get_totlvl(dm) - 2] - 1; + const int edgeSize = multires_side_tot[MultiresDM_get_totlvl(dm) - 1] - 1; + ListBase *map = MultiresDM_get_vert_face_map(dm); + int S, x, y; mvert = CDDM_get_verts(dm); + medge = MultiresDM_get_ored(dm); mface = MultiresDM_get_orfa(dm); + d.subco = MultiresDM_get_subco(dm); + /* For now just handle top-level sculpts */ for(i = 0; i < MultiresDM_get_totorfa(dm); ++i) { - int gridFaces = multires_side_tot[MultiresDM_get_totlvl(dm) - 2] - 1; const int numVerts = mface[i].v4 ? 4 : 3; - int S, x, y; // convert from mvert->co to disps - multires_displacer_init(&d, dm, i, numVerts, 1); - d.subco = subco; + multires_displacer_init(&d, dm, i, 1); multires_displacer_anchor(&d, 1, 0); multires_displace(&d, mvert->co); ++mvert; + ++d.subco; 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; } } @@ -1589,12 +1656,30 @@ static void multiresModifier_update(DerivedMesh *dm) for(x = 1; x < gridFaces; x++) { multires_displace(&d, mvert->co); ++mvert; + ++d.subco; } multires_displacer_jump(&d); } } + } - subco = d.subco; + for(i = 0; i < MultiresDM_get_totored(dm); ++i) { + const MEdge *e = &medge[i]; + for(x = 1; x < edgeSize; ++x) { + IndexNode *n1, *n2; + /* 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, 1); + multires_displacer_anchor_edge(&d, e->v1, e->v2, x); + multires_displace(&d, mvert->co); + } + } + } + ++mvert; + ++d.subco; + } } } } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 1b3ce1db57d..a53c6637b3a 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -567,7 +567,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, if(mmd) { VecCopyf(mr_orig, mvert->co); mr_orig += 3; - multires_displacer_init(&d, result, index, numVerts, 0); + multires_displacer_init(&d, result, index, 0); multires_displacer_anchor(&d, 1, 0); multires_displace(&d, mvert->co); } @@ -656,6 +656,24 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, w[0] = 1 - w[1]; DM_interp_vert_data(dm, result, vertIdx, w, 2, i); VecCopyf(mvert->co, ccgSubSurf_getEdgeData(ss, e, x)); + if(mmd) { + int numFaces = ccgSubSurf_getEdgeNumFaces(ss, e); + int edgeface; + + VecCopyf(mr_orig, mvert->co); + mr_orig += 3; + + multires_displacer_weight(&d, 1.0f / numFaces); + /* Could be made more efficient by moving this outside the x loop */ + for(edgeface = 0; edgeface < numFaces; ++edgeface) { + CCGFace *f = ccgSubSurf_getEdgeFace(ss, e, edgeface); + int faceIdx = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); + multires_displacer_init(&d, result, faceIdx, 0); + multires_displacer_anchor_edge(&d, vertIdx[0], vertIdx[1], x); + multires_displace(&d, mvert->co); + } + + } *origIndex = ORIGINDEX_NONE; ++mvert; ++origIndex; |