forked from bartvdbraak/blender
optimize mirror merging, remove array reallocation, replace with fixed size arrays.
This commit is contained in:
parent
44b3735078
commit
a70fa65592
@ -61,7 +61,7 @@ struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, int use_mdisps);
|
||||
DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em, int use_mdisps, int use_tessface);
|
||||
|
||||
/* merge verts */
|
||||
DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap);
|
||||
DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap);
|
||||
|
||||
/* creates a CDDerivedMesh from the given curve object */
|
||||
struct DerivedMesh *CDDM_from_curve(struct Object *ob);
|
||||
|
@ -2308,15 +2308,19 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm)
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* merge verts
|
||||
|
||||
/**
|
||||
* Merge Verts
|
||||
*
|
||||
* vtargetmap is a table that maps vertices to target vertices. a value of -1
|
||||
* \param vtargetmap The table that maps vertices to target vertices. a value of -1
|
||||
* indicates a vertex is a target, and is to be kept.
|
||||
* This array is aligned with 'dm->numVertData'
|
||||
*
|
||||
* \param tot_vtargetmap The number of non '-1' values in vtargetmap.
|
||||
* (not the size )
|
||||
*
|
||||
* this frees dm, and returns a new one.
|
||||
*
|
||||
* this is a really horribly written function. ger. - joeedh
|
||||
*
|
||||
* note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces.
|
||||
*
|
||||
* Note: This function is currently only used by the Mirror modifier, so it
|
||||
@ -2324,49 +2328,66 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm)
|
||||
* of faces sharing the same set of vertices). If used elsewhere, it may
|
||||
* be necessary to make this functionality optional.
|
||||
*/
|
||||
DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
|
||||
DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap)
|
||||
{
|
||||
// #define USE_LOOPS
|
||||
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
|
||||
CDDerivedMesh *cddm2 = NULL;
|
||||
MVert *mv, *mvert = NULL;
|
||||
BLI_array_declare(mvert);
|
||||
MEdge *med, *medge = NULL;
|
||||
BLI_array_declare(medge);
|
||||
MPoly *mp, *mpoly = NULL;
|
||||
BLI_array_declare(mpoly);
|
||||
MLoop *ml, *mloop = NULL;
|
||||
BLI_array_declare(mloop);
|
||||
EdgeHash *ehash = BLI_edgehash_new();
|
||||
int *newv = NULL, *newe = NULL;
|
||||
#ifdef USE_LOOPS
|
||||
int *newl = NULL;
|
||||
#endif
|
||||
int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
|
||||
BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
|
||||
int i, j, c, totpoly;
|
||||
#ifdef USE_LOOPS
|
||||
int totloop;
|
||||
#endif
|
||||
|
||||
const int totvert = dm->numVertData;
|
||||
const int totedge = dm->numEdgeData;
|
||||
const int totloop = dm->numLoopData;
|
||||
const int totpoly = dm->numPolyData;
|
||||
|
||||
const int totvert_final = totvert - tot_vtargetmap;
|
||||
|
||||
MVert *mv, *mvert = MEM_mallocN(sizeof(*mvert) * totvert_final, __func__);
|
||||
int *oldv = MEM_mallocN(sizeof(*oldv) * totvert_final, __func__);
|
||||
int *newv = MEM_mallocN(sizeof(*newv) * totvert, __func__);
|
||||
STACK_DECLARE(mvert);
|
||||
STACK_DECLARE(oldv);
|
||||
|
||||
MEdge *med, *medge = MEM_mallocN(sizeof(*medge) * totedge, __func__);
|
||||
int *olde = MEM_mallocN(sizeof(*olde) * totedge, __func__);
|
||||
int *newe = MEM_mallocN(sizeof(*newe) * totedge, __func__);
|
||||
STACK_DECLARE(medge);
|
||||
STACK_DECLARE(olde);
|
||||
|
||||
MLoop *ml, *mloop = MEM_mallocN(sizeof(*mloop) * totloop, __func__);
|
||||
int *oldl = MEM_mallocN(sizeof(*oldl) * totloop, __func__);
|
||||
#ifdef USE_LOOPS
|
||||
totloop = dm->numLoopData;
|
||||
int newl = MEM_mallocN(sizeof(*newl) * totloop, __func__);
|
||||
#endif
|
||||
totpoly = dm->numPolyData;
|
||||
STACK_DECLARE(mloop);
|
||||
STACK_DECLARE(oldl);
|
||||
|
||||
MPoly *mp, *mpoly = MEM_mallocN(sizeof(*medge) * totpoly, __func__);
|
||||
int *oldp = MEM_mallocN(sizeof(*oldp) * totpoly, __func__);
|
||||
STACK_DECLARE(mpoly);
|
||||
STACK_DECLARE(oldp);
|
||||
|
||||
EdgeHash *ehash = BLI_edgehash_new();
|
||||
|
||||
int i, j, c;
|
||||
|
||||
newv = MEM_mallocN(sizeof(int) * dm->numVertData, "newv vtable CDDM_merge_verts");
|
||||
newe = MEM_mallocN(sizeof(int) * dm->numEdgeData, "newv etable CDDM_merge_verts");
|
||||
#ifdef USE_LOOPS
|
||||
newl = MEM_mallocN(sizeof(int) * totloop, "newv ltable CDDM_merge_verts");
|
||||
#endif
|
||||
STACK_INIT(oldv);
|
||||
STACK_INIT(olde);
|
||||
STACK_INIT(oldl);
|
||||
STACK_INIT(oldp);
|
||||
|
||||
STACK_INIT(mvert);
|
||||
STACK_INIT(medge);
|
||||
STACK_INIT(mloop);
|
||||
STACK_INIT(mpoly);
|
||||
|
||||
/* fill newl with destination vertex indices */
|
||||
mv = cddm->mvert;
|
||||
c = 0;
|
||||
for (i = 0; i < dm->numVertData; i++, mv++) {
|
||||
for (i = 0; i < totvert; i++, mv++) {
|
||||
if (vtargetmap[i] == -1) {
|
||||
BLI_array_append(oldv, i);
|
||||
STACK_PUSH(oldv, i);
|
||||
STACK_PUSH(mvert, *mv);
|
||||
newv[i] = c++;
|
||||
BLI_array_append(mvert, *mv);
|
||||
}
|
||||
else {
|
||||
/* dummy value */
|
||||
@ -2375,7 +2396,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
|
||||
}
|
||||
|
||||
/* now link target vertices to destination indices */
|
||||
for (i = 0; i < dm->numVertData; i++) {
|
||||
for (i = 0; i < totvert; i++) {
|
||||
if (vtargetmap[i] != -1) {
|
||||
newv[i] = newv[vtargetmap[i]];
|
||||
}
|
||||
@ -2389,7 +2410,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
|
||||
/* now go through and fix edges and faces */
|
||||
med = cddm->medge;
|
||||
c = 0;
|
||||
for (i = 0; i < dm->numEdgeData; i++, med++) {
|
||||
for (i = 0; i < totedge; i++, med++) {
|
||||
|
||||
if (LIKELY(med->v1 != med->v2)) {
|
||||
const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
|
||||
@ -2400,9 +2421,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
|
||||
newe[i] = GET_INT_FROM_POINTER(*eh_p);
|
||||
}
|
||||
else {
|
||||
BLI_array_append(olde, i);
|
||||
STACK_PUSH(olde, i);
|
||||
STACK_PUSH(medge, *med);
|
||||
newe[i] = c;
|
||||
BLI_array_append(medge, *med);
|
||||
BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c));
|
||||
c++;
|
||||
}
|
||||
@ -2414,7 +2435,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
|
||||
|
||||
mp = cddm->mpoly;
|
||||
for (i = 0; i < totpoly; i++, mp++) {
|
||||
MPoly *mp2;
|
||||
MPoly *mp_new;
|
||||
|
||||
ml = cddm->mloop + mp->loopstart;
|
||||
|
||||
@ -2441,10 +2462,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
|
||||
med = cddm->medge + ml->e;
|
||||
if (LIKELY(med->v1 != med->v2)) {
|
||||
#ifdef USE_LOOPS
|
||||
newl[j + mp->loopstart] = BLI_array_count(mloop);
|
||||
newl[j + mp->loopstart] = STACK_SIZE(mloop);
|
||||
#endif
|
||||
BLI_array_append(oldl, j + mp->loopstart);
|
||||
BLI_array_append(mloop, *ml);
|
||||
STACK_PUSH(oldl, j + mp->loopstart);
|
||||
STACK_PUSH(mloop, *ml);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
@ -2452,16 +2473,17 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
|
||||
if (UNLIKELY(c == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mp_new = STACK_PUSH_RET_PTR(mpoly);
|
||||
*mp_new = *mp;
|
||||
mp_new->totloop = c;
|
||||
mp_new->loopstart = STACK_SIZE(mloop) - c;
|
||||
|
||||
mp2 = BLI_array_append_r(mpoly, *mp);
|
||||
mp2->totloop = c;
|
||||
mp2->loopstart = BLI_array_count(mloop) - c;
|
||||
|
||||
BLI_array_append(oldp, i);
|
||||
STACK_PUSH(oldp, i);
|
||||
}
|
||||
|
||||
/*create new cddm*/
|
||||
cddm2 = (CDDerivedMesh *) CDDM_from_template((DerivedMesh *)cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly));
|
||||
cddm2 = (CDDerivedMesh *) CDDM_from_template((DerivedMesh *)cddm, STACK_SIZE(mvert), STACK_SIZE(medge), 0, STACK_SIZE(mloop), STACK_SIZE(mpoly));
|
||||
|
||||
/*update edge indices and copy customdata*/
|
||||
med = medge;
|
||||
@ -2498,30 +2520,38 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
|
||||
}
|
||||
|
||||
/*copy over data. CustomData_add_layer can do this, need to look it up.*/
|
||||
memcpy(cddm2->mvert, mvert, sizeof(MVert) * BLI_array_count(mvert));
|
||||
memcpy(cddm2->medge, medge, sizeof(MEdge) * BLI_array_count(medge));
|
||||
memcpy(cddm2->mloop, mloop, sizeof(MLoop) * BLI_array_count(mloop));
|
||||
memcpy(cddm2->mpoly, mpoly, sizeof(MPoly) * BLI_array_count(mpoly));
|
||||
BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly);
|
||||
|
||||
if (newv)
|
||||
MEM_freeN(newv);
|
||||
if (newe)
|
||||
MEM_freeN(newe);
|
||||
memcpy(cddm2->mvert, mvert, sizeof(MVert) * STACK_SIZE(mvert));
|
||||
memcpy(cddm2->medge, medge, sizeof(MEdge) * STACK_SIZE(medge));
|
||||
memcpy(cddm2->mloop, mloop, sizeof(MLoop) * STACK_SIZE(mloop));
|
||||
memcpy(cddm2->mpoly, mpoly, sizeof(MPoly) * STACK_SIZE(mpoly));
|
||||
|
||||
MEM_freeN(mvert);
|
||||
MEM_freeN(medge);
|
||||
MEM_freeN(mloop);
|
||||
MEM_freeN(mpoly);
|
||||
|
||||
MEM_freeN(newv);
|
||||
MEM_freeN(newe);
|
||||
#ifdef USE_LOOPS
|
||||
if (newl)
|
||||
MEM_freeN(newl);
|
||||
MEM_freeN(newl);
|
||||
#endif
|
||||
if (oldv)
|
||||
MEM_freeN(oldv);
|
||||
if (olde)
|
||||
MEM_freeN(olde);
|
||||
if (oldl)
|
||||
MEM_freeN(oldl);
|
||||
if (oldp)
|
||||
MEM_freeN(oldp);
|
||||
if (ehash)
|
||||
BLI_edgehash_free(ehash, NULL);
|
||||
|
||||
MEM_freeN(oldv);
|
||||
MEM_freeN(olde);
|
||||
MEM_freeN(oldl);
|
||||
MEM_freeN(oldp);
|
||||
|
||||
STACK_FREE(oldv);
|
||||
STACK_FREE(olde);
|
||||
STACK_FREE(oldl);
|
||||
STACK_FREE(oldp);
|
||||
|
||||
STACK_FREE(mvert);
|
||||
STACK_FREE(medge);
|
||||
STACK_FREE(mloop);
|
||||
STACK_FREE(mpoly);
|
||||
|
||||
BLI_edgehash_free(ehash, NULL);
|
||||
|
||||
/*free old derivedmesh*/
|
||||
dm->needsFree = 1;
|
||||
|
@ -296,6 +296,7 @@ typedef bool _BLI_Bool;
|
||||
#define STACK_SIZE(stack) ((void)stack, (_##stack##_index))
|
||||
#define STACK_PUSH(stack, val) (void)((stack)[(_##stack##_index)++] = val)
|
||||
#define STACK_PUSH_RET(stack) ((void)stack, ((stack)[(_##stack##_index)++]))
|
||||
#define STACK_PUSH_RET_PTR(stack) ((void)stack, &((stack)[(_##stack##_index)++]))
|
||||
#define STACK_POP(stack) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : NULL)
|
||||
#define STACK_FREE(stack) ((void)stack)
|
||||
|
||||
|
@ -99,7 +99,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|
||||
{
|
||||
const float tolerance_sq = mmd->tolerance * mmd->tolerance;
|
||||
const int do_vtargetmap = !(mmd->flag & MOD_MIR_NO_MERGE);
|
||||
int is_vtargetmap = FALSE; /* true when it should be used */
|
||||
int tot_vtargetmap = 0; /* total merge vertices */
|
||||
|
||||
DerivedMesh *result;
|
||||
const int maxVerts = dm->getNumVerts(dm);
|
||||
@ -187,7 +187,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|
||||
* should be mapped for merging */
|
||||
if (UNLIKELY(len_squared_v3v3(mv_prev->co, mv->co) < tolerance_sq)) {
|
||||
*vtmap_a = maxVerts + i;
|
||||
is_vtargetmap = TRUE;
|
||||
tot_vtargetmap++;
|
||||
}
|
||||
else {
|
||||
*vtmap_a = -1;
|
||||
@ -288,8 +288,8 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|
||||
if (do_vtargetmap) {
|
||||
/* slow - so only call if one or more merge verts are found,
|
||||
* users may leave this on and not realize there is nothing to merge - campbell */
|
||||
if (is_vtargetmap) {
|
||||
result = CDDM_merge_verts(result, vtargetmap);
|
||||
if (tot_vtargetmap) {
|
||||
result = CDDM_merge_verts(result, vtargetmap, tot_vtargetmap);
|
||||
}
|
||||
MEM_freeN(vtargetmap);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user