diff options
-rw-r--r-- | source/blender/src/reeb.c | 201 |
1 files changed, 131 insertions, 70 deletions
diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index 54befb85a9b..5f80a2c7227 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -91,6 +91,13 @@ ReebGraph *FILTERED_RG = NULL; #define DEBUG_REEB #define DEBUG_REEB_NODE +typedef struct VertexData +{ + float w; /* weight */ + int i; /* index */ + ReebNode *n; +} VertexData; + typedef struct EdgeIndex { EditEdge **edges; @@ -106,7 +113,7 @@ typedef enum { int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1); void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction); int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1); -EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, EditVert *eve); +EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index); void mergeArcFaces(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc); void addFacetoArc(ReebArc *arc, EditFace *efa); @@ -118,6 +125,51 @@ void flipArcBuckets(ReebArc *arc); /***************************************** UTILS **********************************************/ +VertexData *allocVertexData(EditMesh *em) +{ + VertexData *data; + EditVert *eve; + int totvert, index; + + totvert = BLI_countlist(&em->verts); + + data = MEM_callocN(sizeof(VertexData) * totvert, "VertexData"); + + for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next) + { + data[index].i = index; + data[index].w = 0; + eve->tmp.p = data + index; + } + + return data; +} + +int indexData(EditVert *eve) +{ + return ((VertexData*)eve->tmp.p)->i; +} + +float weightData(EditVert *eve) +{ + return ((VertexData*)eve->tmp.p)->w; +} + +void weightSetData(EditVert *eve, float w) +{ + ((VertexData*)eve->tmp.p)->w = w; +} + +ReebNode* nodeData(EditVert *eve) +{ + return ((VertexData*)eve->tmp.p)->n; +} + +void nodeSetData(EditVert *eve, ReebNode *n) +{ + ((VertexData*)eve->tmp.p)->n = n; +} + void REEB_freeArc(BArc *barc) { ReebArc *arc = (ReebArc*)barc; @@ -190,10 +242,13 @@ void BIF_flagMultiArcs(ReebGraph *rg, int flag) } } -ReebNode * addNode(ReebGraph *rg, EditVert *eve, float weight) +ReebNode * addNode(ReebGraph *rg, EditVert *eve) { + float weight; ReebNode *node = NULL; + weight = weightData(eve); + node = MEM_callocN(sizeof(ReebNode), "reeb node"); node->flag = 0; // clear flag on init @@ -207,6 +262,8 @@ ReebNode * addNode(ReebGraph *rg, EditVert *eve, float weight) BLI_addtail(&rg->nodes, node); rg->totnodes++; + nodeSetData(eve, node); + return node; } @@ -747,7 +804,7 @@ static void interpolateBuckets(ReebArc *arc, float *start_p, float *end_p, int s void fillArcEmptyBuckets(ReebArc *arc) { float *start_p, *end_p; - int start_index, end_index; + int start_index = 0, end_index = 0; int missing = 0; int i; @@ -1262,7 +1319,7 @@ int joinSubgraphsEnds(ReebGraph *rg, float threshold, int nb_subgraphs) for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++) { ReebNode *start_node, *end_node; - ReebNode *min_node_start, *min_node_end = NULL; + ReebNode *min_node_start = NULL, *min_node_end = NULL; float min_distance = FLT_MAX; for (start_node = rg->nodes.first; start_node; start_node = start_node->next) @@ -1906,11 +1963,11 @@ int compareVerts( const void* a, const void* b ) EditVert *vb = *(EditVert**)b; int value = 0; - if (va->tmp.fp < vb->tmp.fp) + if (weightData(va) < weightData(vb)) { value = -1; } - else if (va->tmp.fp > vb->tmp.fp) + else if (weightData(va) > weightData(vb)) { value = 1; } @@ -1942,15 +1999,15 @@ void spreadWeight(EditMesh *em) { eve = verts[i]; - if (i == 0 || (eve->tmp.fp - lastWeight) > FLT_EPSILON) + if (i == 0 || (weightData(eve) - lastWeight) > FLT_EPSILON) { - lastWeight = eve->tmp.fp; + lastWeight = weightData(eve); } else { work_needed = 1; - eve->tmp.fp = lastWeight + FLT_EPSILON * 2; - lastWeight = eve->tmp.fp; + weightSetData(eve, lastWeight + FLT_EPSILON * 2); + lastWeight = weightData(eve); } } } @@ -2496,7 +2553,6 @@ void addTriangleToGraph(ReebGraph *rg, ReebNode * n1, ReebNode * n2, ReebNode * ReebGraph * generateReebGraph(EditMesh *em, int subdivisions) { ReebGraph *rg; - struct DynamicList * dlist; EditVert *eve; EditFace *efa; int index; @@ -2526,16 +2582,12 @@ ReebGraph * generateReebGraph(EditMesh *em, int subdivisions) { if (eve->h == 0) { - eve->hash = index; + addNode(rg, eve); eve->f2 = 0; - eve->tmp.p = addNode(rg, eve, eve->tmp.fp); index++; } } - /* Temporarely convert node list to dynamic list, for indexed access */ - dlist = BLI_dlist_from_listbase(&rg->nodes); - /* Adding face, edge per edge */ for(efa = em->faces.first; efa; efa = efa->next) { @@ -2543,15 +2595,15 @@ ReebGraph * generateReebGraph(EditMesh *em, int subdivisions) { ReebNode *n1, *n2, *n3; - n1 = (ReebNode*)BLI_dlist_find_link(dlist, efa->v1->hash); - n2 = (ReebNode*)BLI_dlist_find_link(dlist, efa->v2->hash); - n3 = (ReebNode*)BLI_dlist_find_link(dlist, efa->v3->hash); + n1 = nodeData(efa->v1); + n2 = nodeData(efa->v2); + n3 = nodeData(efa->v3); addTriangleToGraph(rg, n1, n2, n3, efa); if (efa->v4) { - ReebNode *n4 = (ReebNode*)efa->v4->tmp.p; + ReebNode *n4 = nodeData(efa->v4); addTriangleToGraph(rg, n1, n3, n4, efa); } #ifdef DEBUG_REEB @@ -2566,8 +2618,6 @@ ReebGraph * generateReebGraph(EditMesh *em, int subdivisions) printf("\n"); - BLI_listbase_from_dlist(dlist, &rg->nodes); - removeZeroNodes(rg); removeNormalNodes(rg); @@ -2587,12 +2637,12 @@ void renormalizeWeight(EditMesh *em, float newmax) /* First pass, determine maximum and minimum */ eve = em->verts.first; - minimum = eve->tmp.fp; - maximum = eve->tmp.fp; + minimum = weightData(eve); + maximum = minimum; for(eve = em->verts.first; eve; eve = eve->next) { - maximum = MAX2(maximum, eve->tmp.fp); - minimum = MIN2(minimum, eve->tmp.fp); + maximum = MAX2(maximum, weightData(eve)); + minimum = MIN2(minimum, weightData(eve)); } range = maximum - minimum; @@ -2600,7 +2650,8 @@ void renormalizeWeight(EditMesh *em, float newmax) /* Normalize weights */ for(eve = em->verts.first; eve; eve = eve->next) { - eve->tmp.fp = (eve->tmp.fp - minimum) / range * newmax; + float weight = (weightData(eve) - minimum) / range * newmax; + weightSetData(eve, weight); } } @@ -2615,7 +2666,7 @@ int weightFromLoc(EditMesh *em, int axis) /* Copy coordinate in weight */ for(eve = em->verts.first; eve; eve = eve->next) { - eve->tmp.fp = eve->co[axis]; + weightSetData(eve, eve->co[axis]); } return 1; @@ -2648,9 +2699,9 @@ void addTriangle(EditVert *v1, EditVert *v2, EditVert *v3, long e1, long e2, lon /* Angle opposite e3 */ float t3 = cotan_weight(v3->co, v1->co, v2->co) / e1; - int i1 = v1->hash; - int i2 = v2->hash; - int i3 = v3->hash; + int i1 = indexData(v1); + int i2 = indexData(v2); + int i3 = indexData(v3); nlMatrixAdd(i1, i1, t2+t3); nlMatrixAdd(i2, i2, t1+t3); @@ -2699,8 +2750,8 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges) int maximum = 1; int minimum = 1; - NextEdgeForVert(indexed_edges, NULL); /* Reset next edge */ - for(eed = NextEdgeForVert(indexed_edges, eve); eed && (maximum || minimum); eed = NextEdgeForVert(indexed_edges, eve)) + NextEdgeForVert(indexed_edges, -1); /* Reset next edge */ + for(eed = NextEdgeForVert(indexed_edges, index); eed && (maximum || minimum); eed = NextEdgeForVert(indexed_edges, index)) { EditVert *eve2; @@ -2716,12 +2767,12 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges) if (eve2->h == 0) { /* Adjacent vertex is bigger, not a local maximum */ - if (eve2->tmp.fp > eve->tmp.fp) + if (weightData(eve2) > weightData(eve)) { maximum = 0; } /* Adjacent vertex is smaller, not a local minimum */ - else if (eve2->tmp.fp < eve->tmp.fp) + else if (weightData(eve2) < weightData(eve)) { minimum = 0; } @@ -2730,7 +2781,7 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges) if (maximum || minimum) { - float w = eve->tmp.fp; + float w = weightData(eve); eve->f1 = 0; nlSetVariable(0, index, w); nlLockVariable(index); @@ -2794,7 +2845,7 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges) rval = 1; for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next) { - eve->tmp.fp = nlGetVariable(0, index); + weightSetData(eve, nlGetVariable(0, index)); } } else @@ -2808,12 +2859,12 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges) } -EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, EditVert *eve) +EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index) { static int offset = -1; /* Reset method, call with NULL mesh pointer */ - if (eve == NULL) + if (index == -1) { offset = -1; return NULL; @@ -2822,7 +2873,7 @@ EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, EditVert *eve) /* first pass, start at the head of the list */ if (offset == -1) { - offset = indexed_edges->offset[eve->hash]; + offset = indexed_edges->offset[index]; } /* subsequent passes, start on the next edge */ else @@ -2860,12 +2911,12 @@ void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeIndex *ind current_eve->f1 = 1; /* mark vertex as selected */ /* Add all new edges connected to current_eve to the list */ - NextEdgeForVert(indexed_edges, NULL); // Reset next edge - for(eed = NextEdgeForVert(indexed_edges, current_eve); eed; eed = NextEdgeForVert(indexed_edges, current_eve)) + NextEdgeForVert(indexed_edges, -1); // Reset next edge + for(eed = NextEdgeForVert(indexed_edges, indexData(current_eve)); eed; eed = NextEdgeForVert(indexed_edges, indexData(current_eve))) { if (eed->f1 == 0) { - BLI_heap_insert(edge_heap, current_eve->tmp.fp + eed->tmp.fp, eed); + BLI_heap_insert(edge_heap, weightData(current_eve) + eed->tmp.fp, eed); eed->f1 = 1; } } @@ -2888,8 +2939,9 @@ void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeIndex *ind else /* otherwise, it's v2 */ { current_eve = select_eed->v2; - } - current_eve->tmp.fp = current_weight; + } + + weightSetData(current_eve, current_weight); } } @@ -2906,28 +2958,25 @@ void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges) { EditVert *eve; EditEdge *eed; - int tot_vert = 0; + int totvert = 0; int tot_indexed = 0; int offset = 0; - for(tot_vert = 0, eve = em->verts.first; eve; tot_vert++, eve = eve->next) - { - eve->hash = tot_vert; - } + totvert = BLI_countlist(&em->verts); - indexed_edges->offset = MEM_callocN(tot_vert * sizeof(int), "EdgeIndex offset"); + indexed_edges->offset = MEM_callocN(totvert * sizeof(int), "EdgeIndex offset"); - for(eed = em->edges.first; eed; eed= eed->next) + for(eed = em->edges.first; eed; eed = eed->next) { if (eed->v1->h == 0 && eed->v2->h == 0) { tot_indexed += 2; - indexed_edges->offset[eed->v1->hash]++; - indexed_edges->offset[eed->v2->hash]++; + indexed_edges->offset[indexData(eed->v1)]++; + indexed_edges->offset[indexData(eed->v2)]++; } } - tot_indexed += tot_vert; + tot_indexed += totvert; indexed_edges->edges = MEM_callocN(tot_indexed * sizeof(EditEdge*), "EdgeIndex edges"); @@ -2936,8 +2985,8 @@ void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges) { if (eve->h == 0) { - int d = indexed_edges->offset[eve->hash]; - indexed_edges->offset[eve->hash] = offset; + int d = indexed_edges->offset[indexData(eve)]; + indexed_edges->offset[indexData(eve)] = offset; offset += d + 1; } } @@ -2948,7 +2997,7 @@ void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges) if (eed->v1->h == 0 && eed->v2->h == 0) { int i; - for (i = indexed_edges->offset[eed->v1->hash]; i < tot_indexed; i++) + for (i = indexed_edges->offset[indexData(eed->v1)]; i < tot_indexed; i++) { if (indexed_edges->edges[i] == NULL) { @@ -2957,7 +3006,7 @@ void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges) } } - for (i = indexed_edges->offset[eed->v2->hash]; i < tot_indexed; i++) + for (i = indexed_edges->offset[indexData(eed->v2)]; i < tot_indexed; i++) { if (indexed_edges->edges[i] == NULL) { @@ -2973,9 +3022,12 @@ int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges) { EditVert *eve; int totedge = 0; + int totvert = 0; int vCount = 0; - if (em == NULL || BLI_countlist(&em->verts) == 0) + totvert = BLI_countlist(&em->verts); + + if (em == NULL || totvert == 0) { return 0; } @@ -2986,11 +3038,10 @@ int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges) { return 0; } - + /* Initialize vertice flag and find at least one selected vertex */ for(eve = em->verts.first; eve; eve = eve->next) { - eve->tmp.fp = 0; eve->f1 = 0; if (eve->f & SELECT) { @@ -3052,7 +3103,7 @@ int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges) { min_distance = distance; selected_eve = eve; - selected_weight = closest_eve->tmp.fp; + selected_weight = weightData(closest_eve); } } } @@ -3063,7 +3114,7 @@ int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges) { allDone = 0; - selected_eve->tmp.fp = selected_weight + min_distance; + weightSetData(selected_eve, selected_weight + min_distance); shortestPathsFromVert(em, selected_eve, indexed_edges); } } @@ -3077,7 +3128,7 @@ int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges) break; } } - + return 1; } @@ -3104,12 +3155,12 @@ void weightToVCol(EditMesh *em, int index) if (mcol) { - mcol[0] = MColFromVal(efa->v1->tmp.fp); - mcol[1] = MColFromVal(efa->v2->tmp.fp); - mcol[2] = MColFromVal(efa->v3->tmp.fp); + mcol[0] = MColFromVal(weightData(efa->v1)); + mcol[1] = MColFromVal(weightData(efa->v2)); + mcol[2] = MColFromVal(weightData(efa->v3)); if(efa->v4) { - mcol[3] = MColFromVal(efa->v4->tmp.fp); + mcol[3] = MColFromVal(weightData(efa->v4)); } } } @@ -3410,6 +3461,7 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(void) { EditMesh *em = G.editMesh; EdgeIndex indexed_edges; + VertexData *data; ReebGraph *rg = NULL; ReebGraph *rgi, *previous; int i, nb_levels = REEB_MAX_MULTI_LEVEL; @@ -3417,6 +3469,8 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(void) if (em == NULL) return NULL; + data = allocVertexData(em); + buildIndexedEdges(em, &indexed_edges); if (weightFromDistance(em, &indexed_edges) == 0) @@ -3502,6 +3556,8 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(void) } verifyMultiResolutionLinks(rg, 0); + + MEM_freeN(data); return rg; } @@ -3510,13 +3566,16 @@ ReebGraph *BIF_ReebGraphFromEditMesh(void) { EditMesh *em = G.editMesh; EdgeIndex indexed_edges; + VertexData *data; ReebGraph *rg = NULL; if (em == NULL) return NULL; - buildIndexedEdges(em, &indexed_edges); + data = allocVertexData(em); + buildIndexedEdges(em, &indexed_edges); + if (weightFromDistance(em, &indexed_edges) == 0) { error("No selected vertex\n"); @@ -3566,6 +3625,8 @@ ReebGraph *BIF_ReebGraphFromEditMesh(void) printf("DONE\n"); printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph*)rg)); + + MEM_freeN(data); return rg; } |