4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * Contributor(s): Martin Poirier
25 * ***** END GPL LICENSE BLOCK *****
29 #include <string.h> // for memcpy
31 #include <stdlib.h> // for qsort
36 #include "DNA_listBase.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_space_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_armature_types.h"
43 #include "BKE_context.h"
45 #include "MEM_guardedalloc.h"
47 #include "BLI_blenlib.h"
48 #include "BLI_arithb.h"
49 #include "BLI_editVert.h"
50 #include "BLI_edgehash.h"
51 #include "BLI_ghash.h"
54 //#include "BDR_editobject.h"
57 #include "ED_armature.h"
58 //#include "BIF_interface.h"
59 //#include "BIF_toolbox.h"
60 //#include "BIF_graphics.h"
62 #include "UI_resources.h"
64 #include "BKE_global.h"
65 #include "BKE_utildefines.h"
66 #include "BKE_customdata.h"
68 //#include "blendef.h"
70 #include "ONL_opennl.h"
75 ReebGraph *GLOBAL_RG = NULL;
76 ReebGraph *FILTERED_RG = NULL;
79 * Skeleton generation algorithm based on:
80 * "Harmonic Skeleton for Realistic Character Animation"
81 * Gregoire Aujay, Franck Hetroy, Francis Lazarus and Christine Depraz
84 * Reeb graph generation algorithm based on:
85 * "Robust On-line Computation of Reeb Graphs: Simplicity and Speed"
86 * Valerio Pascucci, Giorgio Scorzelli, Peer-Timo Bremer and Ajith Mascarenhas
92 #define DEBUG_REEB_NODE
94 typedef struct VertexData
101 typedef struct EdgeIndex
113 int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1);
114 void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction);
115 int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1);
116 EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index);
117 void mergeArcFaces(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc);
118 void addFacetoArc(ReebArc *arc, EditFace *efa);
120 void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count);
121 void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2);
123 void flipArcBuckets(ReebArc *arc);
126 /***************************************** UTILS **********************************************/
128 VertexData *allocVertexData(EditMesh *em)
134 totvert = BLI_countlist(&em->verts);
136 data = MEM_callocN(sizeof(VertexData) * totvert, "VertexData");
138 for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
140 data[index].i = index;
142 eve->tmp.p = data + index;
148 int indexData(EditVert *eve)
150 return ((VertexData*)eve->tmp.p)->i;
153 float weightData(EditVert *eve)
155 return ((VertexData*)eve->tmp.p)->w;
158 void weightSetData(EditVert *eve, float w)
160 ((VertexData*)eve->tmp.p)->w = w;
163 ReebNode* nodeData(EditVert *eve)
165 return ((VertexData*)eve->tmp.p)->n;
168 void nodeSetData(EditVert *eve, ReebNode *n)
170 ((VertexData*)eve->tmp.p)->n = n;
173 void REEB_freeArc(BArc *barc)
175 ReebArc *arc = (ReebArc*)barc;
176 BLI_freelistN(&arc->edges);
179 MEM_freeN(arc->buckets);
182 BLI_ghash_free(arc->faces, NULL, NULL);
187 void REEB_freeGraph(ReebGraph *rg)
193 for( node = rg->nodes.first; node; node = node->next )
195 BLI_freeNode((BGraph*)rg, (BNode*)node);
197 BLI_freelistN(&rg->nodes);
200 arc = rg->arcs.first;
203 ReebArc *next = arc->next;
204 REEB_freeArc((BArc*)arc);
209 BLI_edgehash_free(rg->emap, NULL);
211 /* free linked graph */
214 REEB_freeGraph(rg->link_up);
220 ReebGraph * newReebGraph()
223 rg = MEM_callocN(sizeof(ReebGraph), "reeb graph");
226 rg->emap = BLI_edgehash_new();
229 rg->free_arc = REEB_freeArc;
230 rg->free_node = NULL;
231 rg->radial_symmetry = REEB_RadialSymmetry;
232 rg->axial_symmetry = REEB_AxialSymmetry;
237 void BIF_flagMultiArcs(ReebGraph *rg, int flag)
239 for ( ; rg; rg = rg->link_up)
241 BLI_flagArcs((BGraph*)rg, flag);
245 ReebNode * addNode(ReebGraph *rg, EditVert *eve)
248 ReebNode *node = NULL;
250 weight = weightData(eve);
252 node = MEM_callocN(sizeof(ReebNode), "reeb node");
254 node->flag = 0; // clear flag on init
255 node->symmetry_level = 0;
258 node->weight = weight;
259 node->index = rg->totnodes;
260 VECCOPY(node->p, eve->co);
262 BLI_addtail(&rg->nodes, node);
265 nodeSetData(eve, node);
270 ReebNode * copyNode(ReebGraph *rg, ReebNode *node)
272 ReebNode *cp_node = NULL;
274 cp_node = MEM_callocN(sizeof(ReebNode), "reeb node copy");
276 memcpy(cp_node, node, sizeof(ReebNode));
278 cp_node->prev = NULL;
279 cp_node->next = NULL;
280 cp_node->arcs = NULL;
282 cp_node->link_up = NULL;
283 cp_node->link_down = NULL;
285 BLI_addtail(&rg->nodes, cp_node);
291 void relinkNodes(ReebGraph *low_rg, ReebGraph *high_rg)
293 ReebNode *low_node, *high_node;
295 if (low_rg == NULL || high_rg == NULL)
300 for (low_node = low_rg->nodes.first; low_node; low_node = low_node->next)
302 for (high_node = high_rg->nodes.first; high_node; high_node = high_node->next)
304 if (low_node->index == high_node->index)
306 high_node->link_down = low_node;
307 low_node->link_up = high_node;
314 ReebNode *BIF_otherNodeFromIndex(ReebArc *arc, ReebNode *node)
316 return (arc->head->index == node->index) ? arc->tail : arc->head;
319 ReebNode *BIF_NodeFromIndex(ReebArc *arc, ReebNode *node)
321 return (arc->head->index == node->index) ? arc->head : arc->tail;
324 ReebNode *BIF_lowestLevelNode(ReebNode *node)
326 while (node->link_down)
328 node = node->link_down;
334 ReebArc * copyArc(ReebGraph *rg, ReebArc *arc)
339 cp_arc = MEM_callocN(sizeof(ReebArc), "reeb arc copy");
341 memcpy(cp_arc, arc, sizeof(ReebArc));
343 cp_arc->link_up = arc;
351 cp_arc->edges.first = NULL;
352 cp_arc->edges.last = NULL;
355 cp_arc->buckets = MEM_callocN(sizeof(EmbedBucket) * cp_arc->bcount, "embed bucket");
356 memcpy(cp_arc->buckets, arc->buckets, sizeof(EmbedBucket) * cp_arc->bcount);
359 cp_arc->faces = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
360 mergeArcFaces(rg, cp_arc, arc);
362 /* find corresponding head and tail */
363 for (node = rg->nodes.first; node && (cp_arc->head == NULL || cp_arc->tail == NULL); node = node->next)
365 if (node->index == arc->head->index)
369 else if (node->index == arc->tail->index)
375 BLI_addtail(&rg->arcs, cp_arc);
380 ReebGraph * copyReebGraph(ReebGraph *rg, int level)
384 ReebGraph *cp_rg = newReebGraph();
386 cp_rg->resolution = rg->resolution;
387 cp_rg->length = rg->length;
389 cp_rg->multi_level = level;
392 for (node = rg->nodes.first; node; node = node->next)
394 ReebNode *cp_node = copyNode(cp_rg, node);
395 cp_node->multi_level = level;
399 for (arc = rg->arcs.first; arc; arc = arc->next)
404 BLI_buildAdjacencyList((BGraph*)cp_rg);
409 ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node)
411 ReebGraph *multi_rg = rg;
413 while(multi_rg && multi_rg->multi_level != node->multi_level)
415 multi_rg = multi_rg->link_up;
421 ReebEdge * copyEdge(ReebEdge *edge)
423 ReebEdge *newEdge = NULL;
425 newEdge = MEM_callocN(sizeof(ReebEdge), "reeb edge");
426 memcpy(newEdge, edge, sizeof(ReebEdge));
428 newEdge->next = NULL;
429 newEdge->prev = NULL;
434 void printArc(ReebArc *arc)
437 ReebNode *head = (ReebNode*)arc->head;
438 ReebNode *tail = (ReebNode*)arc->tail;
439 printf("arc: (%i) %f -> (%i) %f\n", head->index, head->weight, tail->index, tail->weight);
441 for(edge = arc->edges.first; edge ; edge = edge->next)
443 printf("\tedge (%i, %i)\n", edge->v1->index, edge->v2->index);
447 void flipArc(ReebArc *arc)
451 arc->head = arc->tail;
457 #ifdef DEBUG_REEB_NODE
458 void NodeDegreeDecrement(ReebGraph *rg, ReebNode *node)
462 // if (node->degree == 0)
464 // printf("would remove node %i\n", node->index);
468 void NodeDegreeIncrement(ReebGraph *rg, ReebNode *node)
470 // if (node->degree == 0)
472 // printf("first connect node %i\n", node->index);
479 #define NodeDegreeDecrement(rg, node) {node->degree--;}
480 #define NodeDegreeIncrement(rg, node) {node->degree++;}
483 void repositionNodes(ReebGraph *rg)
488 // Reset node positions
489 for(node = rg->nodes.first; node; node = node->next)
491 node->p[0] = node->p[1] = node->p[2] = 0;
494 for(arc = rg->arcs.first; arc; arc = arc->next)
496 if (((ReebArc*)arc)->bcount > 0)
500 VECCOPY(p, ((ReebArc*)arc)->buckets[0].p);
501 VecMulf(p, 1.0f / arc->head->degree);
502 VecAddf(arc->head->p, arc->head->p, p);
504 VECCOPY(p, ((ReebArc*)arc)->buckets[((ReebArc*)arc)->bcount - 1].p);
505 VecMulf(p, 1.0f / arc->tail->degree);
506 VecAddf(arc->tail->p, arc->tail->p, p);
511 void verifyNodeDegree(ReebGraph *rg)
514 ReebNode *node = NULL;
517 for(node = rg->nodes.first; node; node = node->next)
520 for(arc = rg->arcs.first; arc; arc = arc->next)
522 if (arc->head == node || arc->tail == node)
527 if (count != node->degree)
529 printf("degree error in node %i: expected %i got %i\n", node->index, count, node->degree);
531 if (node->degree == 0)
533 printf("zero degree node %i with weight %f\n", node->index, node->weight);
539 void verifyBucketsArc(ReebGraph *rg, ReebArc *arc)
541 ReebNode *head = (ReebNode*)arc->head;
542 ReebNode *tail = (ReebNode*)arc->tail;
547 for(i = 0; i < arc->bcount; i++)
549 if (arc->buckets[i].nv == 0)
552 printf("count error in bucket %i/%i\n", i+1, arc->bcount);
556 if (ceil(head->weight) != arc->buckets[0].val)
559 printf("alloc error in first bucket: %f should be %f \n", arc->buckets[0].val, ceil(head->weight));
561 if (floor(tail->weight) != arc->buckets[arc->bcount - 1].val)
564 printf("alloc error in last bucket: %f should be %f \n", arc->buckets[arc->bcount - 1].val, floor(tail->weight));
569 void verifyBuckets(ReebGraph *rg)
573 for(arc = rg->arcs.first; arc; arc = arc->next)
575 verifyBucketsArc(rg, arc);
580 void verifyFaces(ReebGraph *rg)
585 for(arc = rg->arcs.first; arc; arc = arc->next)
587 total += BLI_ghash_size(arc->faces);
593 void verifyArcs(ReebGraph *rg)
597 for (arc = rg->arcs.first; arc; arc = arc->next)
599 if (arc->head->weight > arc->tail->weight)
601 printf("FLIPPED ARC!\n");
606 void verifyMultiResolutionLinks(ReebGraph *rg, int level)
609 ReebGraph *lower_rg = rg->link_up;
615 for (arc = rg->arcs.first; arc; arc = arc->next)
617 if (BLI_findindex(&lower_rg->arcs, arc->link_up) == -1)
619 printf("missing arc %p for level %i\n", arc->link_up, level);
620 printf("Source arc was ---\n");
628 verifyMultiResolutionLinks(lower_rg, level + 1);
632 /***************************************** BUCKET UTILS **********************************************/
634 void addVertToBucket(EmbedBucket *b, float co[3])
637 VecLerpf(b->p, b->p, co, 1.0f / b->nv);
640 void removeVertFromBucket(EmbedBucket *b, float co[3])
642 VecMulf(b->p, (float)b->nv);
643 VecSubf(b->p, b->p, co);
645 VecMulf(b->p, 1.0f / (float)b->nv);
648 void mergeBuckets(EmbedBucket *bDst, EmbedBucket *bSrc)
650 if (bDst->nv > 0 && bSrc->nv > 0)
652 bDst->nv += bSrc->nv;
653 VecLerpf(bDst->p, bDst->p, bSrc->p, (float)bSrc->nv / (float)(bDst->nv));
655 else if (bSrc->nv > 0)
658 VECCOPY(bDst->p, bSrc->p);
662 void mergeArcBuckets(ReebArc *aDst, ReebArc *aSrc, float start, float end)
664 if (aDst->bcount > 0 && aSrc->bcount > 0)
666 int indexDst = 0, indexSrc = 0;
668 start = MAX3(start, aDst->buckets[0].val, aSrc->buckets[0].val);
670 while(indexDst < aDst->bcount && aDst->buckets[indexDst].val < start)
675 while(indexSrc < aSrc->bcount && aSrc->buckets[indexSrc].val < start)
680 for( ; indexDst < aDst->bcount &&
681 indexSrc < aSrc->bcount &&
682 aDst->buckets[indexDst].val <= end &&
683 aSrc->buckets[indexSrc].val <= end
685 ; indexDst++, indexSrc++)
687 mergeBuckets(aDst->buckets + indexDst, aSrc->buckets + indexSrc);
692 void flipArcBuckets(ReebArc *arc)
696 for (i = 0, j = arc->bcount - 1; i < j; i++, j--)
700 tmp = arc->buckets[i];
701 arc->buckets[i] = arc->buckets[j];
702 arc->buckets[j] = tmp;
706 int countArcBuckets(ReebArc *arc)
708 return (int)(floor(arc->tail->weight) - ceil(arc->head->weight)) + 1;
711 void allocArcBuckets(ReebArc *arc)
714 float start = ceil(arc->head->weight);
715 arc->bcount = countArcBuckets(arc);
719 arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "embed bucket");
721 for(i = 0; i < arc->bcount; i++)
723 arc->buckets[i].val = start + i;
733 void resizeArcBuckets(ReebArc *arc)
735 EmbedBucket *oldBuckets = arc->buckets;
736 int oldBCount = arc->bcount;
738 if (countArcBuckets(arc) == oldBCount)
743 allocArcBuckets(arc);
745 if (oldBCount != 0 && arc->bcount != 0)
747 int oldStart = (int)oldBuckets[0].val;
748 int oldEnd = (int)oldBuckets[oldBCount - 1].val;
749 int newStart = (int)arc->buckets[0].val;
750 int newEnd = (int)arc->buckets[arc->bcount - 1].val;
755 if (oldStart < newStart)
757 oldOffset = newStart - oldStart;
761 newOffset = oldStart - newStart;
764 len = MIN2(oldEnd - (oldStart + oldOffset) + 1, newEnd - (newStart - newOffset) + 1);
766 memcpy(arc->buckets + newOffset, oldBuckets + oldOffset, len * sizeof(EmbedBucket));
769 if (oldBuckets != NULL)
771 MEM_freeN(oldBuckets);
775 void reweightBuckets(ReebArc *arc)
778 float start = ceil((arc->head)->weight);
782 for(i = 0; i < arc->bcount; i++)
784 arc->buckets[i].val = start + i;
789 static void interpolateBuckets(ReebArc *arc, float *start_p, float *end_p, int start_index, int end_index)
794 total = end_index - start_index + 2;
796 for (j = start_index; j <= end_index; j++)
798 EmbedBucket *empty = arc->buckets + j;
800 VecLerpf(empty->p, start_p, end_p, (float)(j - start_index + 1) / total);
804 void fillArcEmptyBuckets(ReebArc *arc)
806 float *start_p, *end_p;
807 int start_index = 0, end_index = 0;
811 start_p = arc->head->p;
813 for(i = 0; i < arc->bcount; i++)
815 EmbedBucket *bucket = arc->buckets + i;
826 interpolateBuckets(arc, start_p, end_p, start_index, end_index);
837 start_p = arc->buckets[i - 1].p;
846 end_p = arc->tail->p;
847 end_index = arc->bcount - 1;
849 interpolateBuckets(arc, start_p, end_p, start_index, end_index);
853 static void ExtendArcBuckets(ReebArc *arc)
855 ReebArcIterator arc_iter;
856 BArcIterator *iter = (BArcIterator*)&arc_iter;
857 EmbedBucket *last_bucket, *first_bucket;
858 float *previous = NULL;
859 float average_length = 0, length;
860 int padding_head = 0, padding_tail = 0;
862 if (arc->bcount == 0)
864 return; /* failsafe, shouldn't happen */
867 initArcIterator(iter, arc, arc->head);
872 IT_stopped(iter) == 0;
873 previous = iter->p, IT_next(iter)
876 average_length += VecLenf(previous, iter->p);
878 average_length /= (arc->bcount - 1);
880 first_bucket = arc->buckets;
881 last_bucket = arc->buckets + (arc->bcount - 1);
883 length = VecLenf(first_bucket->p, arc->head->p);
884 if (length > 2 * average_length)
886 padding_head = (int)floor(length / average_length);
889 length = VecLenf(last_bucket->p, arc->tail->p);
890 if (length > 2 * average_length)
892 padding_tail = (int)floor(length / average_length);
895 if (padding_head + padding_tail > 0)
897 EmbedBucket *old_buckets = arc->buckets;
899 arc->buckets = MEM_callocN(sizeof(EmbedBucket) * (padding_head + arc->bcount + padding_tail), "embed bucket");
900 memcpy(arc->buckets + padding_head, old_buckets, arc->bcount * sizeof(EmbedBucket));
902 arc->bcount = padding_head + arc->bcount + padding_tail;
904 MEM_freeN(old_buckets);
907 if (padding_head > 0)
909 interpolateBuckets(arc, arc->head->p, first_bucket->p, 0, padding_head);
912 if (padding_tail > 0)
914 interpolateBuckets(arc, last_bucket->p, arc->tail->p, arc->bcount - padding_tail, arc->bcount - 1);
918 /* CALL THIS ONLY AFTER FILTERING, SINCE IT MESSES UP WEIGHT DISTRIBUTION */
919 void extendGraphBuckets(ReebGraph *rg)
923 for (arc = rg->arcs.first; arc; arc = arc->next)
925 ExtendArcBuckets(arc);
929 /**************************************** LENGTH CALCULATIONS ****************************************/
931 void calculateArcLength(ReebArc *arc)
933 ReebArcIterator arc_iter;
934 BArcIterator *iter = (BArcIterator*)&arc_iter;
939 initArcIterator(iter, arc, arc->head);
942 vec1 = arc->head->p; /* in case there's no embedding */
944 while (IT_next(iter))
948 arc->length += VecLenf(vec0, vec1);
953 arc->length += VecLenf(arc->tail->p, vec1);
956 void calculateGraphLength(ReebGraph *rg)
960 for (arc = rg->arcs.first; arc; arc = arc->next)
962 calculateArcLength(arc);
966 /**************************************** SYMMETRY HANDLING ******************************************/
968 void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count)
970 ReebNode *node = (ReebNode*)root_node;
974 VECCOPY(axis, root_node->symmetry_axis);
976 /* first pass, merge incrementally */
977 for (i = 0; i < count - 1; i++)
979 ReebNode *node1, *node2;
980 ReebArc *arc1, *arc2;
985 VecAddf(tangent, ring[i].n, ring[j].n);
986 Crossf(normal, tangent, axis);
988 node1 = (ReebNode*)BLI_otherNode(ring[i].arc, root_node);
989 node2 = (ReebNode*)BLI_otherNode(ring[j].arc, root_node);
991 arc1 = (ReebArc*)ring[i].arc;
992 arc2 = (ReebArc*)ring[j].arc;
994 /* mirror first node and mix with the second */
995 BLI_mirrorAlongAxis(node1->p, root_node->p, normal);
996 VecLerpf(node2->p, node2->p, node1->p, 1.0f / (j + 1));
999 * there shouldn't be any null arcs here, but just to be safe
1001 if (arc1->bcount > 0 && arc2->bcount > 0)
1003 ReebArcIterator arc_iter1, arc_iter2;
1004 BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
1005 BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
1006 EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
1008 initArcIterator(iter1, arc1, (ReebNode*)root_node);
1009 initArcIterator(iter2, arc2, (ReebNode*)root_node);
1011 bucket1 = IT_next(iter1);
1012 bucket2 = IT_next(iter2);
1014 /* Make sure they both start at the same value */
1015 while(bucket1 && bucket2 && bucket1->val < bucket2->val)
1017 bucket1 = IT_next(iter1);
1020 while(bucket1 && bucket2 && bucket2->val < bucket1->val)
1022 bucket2 = IT_next(iter2);
1026 for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
1028 bucket2->nv += bucket1->nv; /* add counts */
1030 /* mirror on axis */
1031 BLI_mirrorAlongAxis(bucket1->p, root_node->p, normal);
1032 /* add bucket2 in bucket1 */
1033 VecLerpf(bucket2->p, bucket2->p, bucket1->p, (float)bucket1->nv / (float)(bucket2->nv));
1038 /* second pass, mirror back on previous arcs */
1039 for (i = count - 1; i > 0; i--)
1041 ReebNode *node1, *node2;
1042 ReebArc *arc1, *arc2;
1047 VecAddf(tangent, ring[i].n, ring[j].n);
1048 Crossf(normal, tangent, axis);
1050 node1 = (ReebNode*)BLI_otherNode(ring[i].arc, root_node);
1051 node2 = (ReebNode*)BLI_otherNode(ring[j].arc, root_node);
1053 arc1 = (ReebArc*)ring[i].arc;
1054 arc2 = (ReebArc*)ring[j].arc;
1056 /* copy first node than mirror */
1057 VECCOPY(node2->p, node1->p);
1058 BLI_mirrorAlongAxis(node2->p, root_node->p, normal);
1061 * there shouldn't be any null arcs here, but just to be safe
1063 if (arc1->bcount > 0 && arc2->bcount > 0)
1065 ReebArcIterator arc_iter1, arc_iter2;
1066 BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
1067 BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
1068 EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
1070 initArcIterator(iter1, arc1, node);
1071 initArcIterator(iter2, arc2, node);
1073 bucket1 = IT_next(iter1);
1074 bucket2 = IT_next(iter2);
1076 /* Make sure they both start at the same value */
1077 while(bucket1 && bucket1->val < bucket2->val)
1079 bucket1 = IT_next(iter1);
1082 while(bucket2 && bucket2->val < bucket1->val)
1084 bucket2 = IT_next(iter2);
1088 for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
1090 /* copy and mirror back to bucket2 */
1091 bucket2->nv = bucket1->nv;
1092 VECCOPY(bucket2->p, bucket1->p);
1093 BLI_mirrorAlongAxis(bucket2->p, node->p, normal);
1099 void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2)
1101 ReebArc *arc1, *arc2;
1104 arc1 = (ReebArc*)barc1;
1105 arc2 = (ReebArc*)barc2;
1107 VECCOPY(nor, root_node->symmetry_axis);
1109 /* mirror node2 along axis */
1110 VECCOPY(p, node2->p);
1111 BLI_mirrorAlongAxis(p, root_node->p, nor);
1113 /* average with node1 */
1114 VecAddf(node1->p, node1->p, p);
1115 VecMulf(node1->p, 0.5f);
1117 /* mirror back on node2 */
1118 VECCOPY(node2->p, node1->p);
1119 BLI_mirrorAlongAxis(node2->p, root_node->p, nor);
1122 * there shouldn't be any null arcs here, but just to be safe
1124 if (arc1->bcount > 0 && arc2->bcount > 0)
1126 ReebArcIterator arc_iter1, arc_iter2;
1127 BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
1128 BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
1129 EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
1131 initArcIterator(iter1, arc1, (ReebNode*)root_node);
1132 initArcIterator(iter2, arc2, (ReebNode*)root_node);
1134 bucket1 = IT_next(iter1);
1135 bucket2 = IT_next(iter2);
1137 /* Make sure they both start at the same value */
1138 while(bucket1 && bucket1->val < bucket2->val)
1140 bucket1 = IT_next(iter1);
1143 while(bucket2 && bucket2->val < bucket1->val)
1145 bucket2 = IT_next(iter2);
1149 for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
1151 bucket1->nv += bucket2->nv; /* add counts */
1153 /* mirror on axis */
1154 BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor);
1155 /* add bucket2 in bucket1 */
1156 VecLerpf(bucket1->p, bucket1->p, bucket2->p, (float)bucket2->nv / (float)(bucket1->nv));
1158 /* copy and mirror back to bucket2 */
1159 bucket2->nv = bucket1->nv;
1160 VECCOPY(bucket2->p, bucket1->p);
1161 BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor);
1166 /************************************** ADJACENCY LIST *************************************************/
1169 /****************************************** SMOOTHING **************************************************/
1171 void postprocessGraph(ReebGraph *rg, char mode)
1174 float fac1 = 0, fac2 = 1, fac3 = 0;
1179 fac1 = fac2 = fac3 = 1.0f / 3.0f;
1182 fac1 = fac3 = 0.25f;
1186 fac1 = fac2 = -0.25f;
1191 // error("Unknown post processing mode");
1195 for(arc = rg->arcs.first; arc; arc = arc->next)
1197 EmbedBucket *buckets = arc->buckets;
1198 int bcount = arc->bcount;
1201 for(index = 1; index < bcount - 1; index++)
1203 VecLerpf(buckets[index].p, buckets[index].p, buckets[index - 1].p, fac1 / (fac1 + fac2));
1204 VecLerpf(buckets[index].p, buckets[index].p, buckets[index + 1].p, fac3 / (fac1 + fac2 + fac3));
1209 /********************************************SORTING****************************************************/
1211 int compareNodesWeight(void *vnode1, void *vnode2)
1213 ReebNode *node1 = (ReebNode*)vnode1;
1214 ReebNode *node2 = (ReebNode*)vnode2;
1216 if (node1->weight < node2->weight)
1220 if (node1->weight > node2->weight)
1230 void sortNodes(ReebGraph *rg)
1232 BLI_sortlist(&rg->nodes, compareNodesWeight);
1235 int compareArcsWeight(void *varc1, void *varc2)
1237 ReebArc *arc1 = (ReebArc*)varc1;
1238 ReebArc *arc2 = (ReebArc*)varc2;
1239 ReebNode *node1 = (ReebNode*)arc1->head;
1240 ReebNode *node2 = (ReebNode*)arc2->head;
1242 if (node1->weight < node2->weight)
1246 if (node1->weight > node2->weight)
1256 void sortArcs(ReebGraph *rg)
1258 BLI_sortlist(&rg->arcs, compareArcsWeight);
1260 /******************************************* JOINING ***************************************************/
1262 void reweightArc(ReebGraph *rg, ReebArc *arc, ReebNode *start_node, float start_weight)
1266 float end_weight = start_weight + ABS(arc->tail->weight - arc->head->weight);
1269 node = (ReebNode*)BLI_otherNode((BArc*)arc, (BNode*)start_node);
1271 /* prevent backtracking */
1272 if (node->flag == 1)
1277 if (arc->tail == start_node)
1282 start_node->flag = 1;
1284 for (i = 0; i < node->degree; i++)
1286 ReebArc *next_arc = node->arcs[i];
1288 reweightArc(rg, next_arc, node, end_weight);
1291 /* update only if needed */
1292 if (arc->head->weight != start_weight || arc->tail->weight != end_weight)
1294 old_weight = arc->head->weight; /* backup head weight, other arcs need it intact, it will be fixed by the source arc */
1296 arc->head->weight = start_weight;
1297 arc->tail->weight = end_weight;
1299 reweightBuckets(arc);
1300 resizeArcBuckets(arc);
1301 fillArcEmptyBuckets(arc);
1303 arc->head->weight = old_weight;
1307 void reweightSubgraph(ReebGraph *rg, ReebNode *start_node, float start_weight)
1311 BLI_flagNodes((BGraph*)rg, 0);
1313 for (i = 0; i < start_node->degree; i++)
1315 ReebArc *next_arc = start_node->arcs[i];
1317 reweightArc(rg, next_arc, start_node, start_weight);
1319 start_node->weight = start_weight;
1322 int joinSubgraphsEnds(ReebGraph *rg, float threshold, int nb_subgraphs)
1327 for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++)
1329 ReebNode *start_node, *end_node;
1330 ReebNode *min_node_start = NULL, *min_node_end = NULL;
1331 float min_distance = FLT_MAX;
1333 for (start_node = rg->nodes.first; start_node; start_node = start_node->next)
1335 if (start_node->subgraph_index == subgraph && start_node->degree == 1)
1338 for (end_node = rg->nodes.first; end_node; end_node = end_node->next)
1340 if (end_node->subgraph_index != subgraph)
1342 float distance = VecLenf(start_node->p, end_node->p);
1344 if (distance < threshold && distance < min_distance)
1346 min_distance = distance;
1347 min_node_end = end_node;
1348 min_node_start = start_node;
1355 end_node = min_node_end;
1356 start_node = min_node_start;
1358 if (end_node && start_node)
1360 ReebArc *start_arc, *end_arc;
1363 start_arc = start_node->arcs[0];
1364 end_arc = end_node->arcs[0];
1366 if (start_arc->tail == start_node)
1368 reweightSubgraph(rg, end_node, start_node->weight);
1370 start_arc->tail = end_node;
1374 else if (start_arc->head == start_node)
1376 reweightSubgraph(rg, start_node, end_node->weight);
1378 start_arc->head = end_node;
1385 BLI_ReflagSubgraph((BGraph*)rg, end_node->flag, subgraph);
1387 resizeArcBuckets(start_arc);
1388 fillArcEmptyBuckets(start_arc);
1390 NodeDegreeIncrement(rg, end_node);
1391 BLI_rebuildAdjacencyListForNode((BGraph*)rg, (BNode*)end_node);
1393 BLI_removeNode((BGraph*)rg, (BNode*)start_node);
1403 /* Reweight graph from smallest node, fix fliped arcs */
1404 void fixSubgraphsOrientation(ReebGraph *rg, int nb_subgraphs)
1408 for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++)
1411 ReebNode *start_node = NULL;
1413 for (node = rg->nodes.first; node; node = node->next)
1415 if (node->subgraph_index == subgraph)
1417 if (start_node == NULL || node->weight < start_node->weight)
1426 reweightSubgraph(rg, start_node, start_node->weight);
1431 int joinSubgraphs(ReebGraph *rg, float threshold)
1436 BLI_buildAdjacencyList((BGraph*)rg);
1438 if (BLI_isGraphCyclic((BGraph*)rg))
1440 /* don't deal with cyclic graphs YET */
1444 /* sort nodes before flagging subgraphs to make sure root node is subgraph 0 */
1447 nb_subgraphs = BLI_FlagSubgraphs((BGraph*)rg);
1449 /* Harmonic function can create flipped arcs, take the occasion to fix them */
1451 // if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC)
1453 fixSubgraphsOrientation(rg, nb_subgraphs);
1456 if (nb_subgraphs > 1)
1458 joined |= joinSubgraphsEnds(rg, threshold, nb_subgraphs);
1462 removeNormalNodes(rg);
1463 BLI_buildAdjacencyList((BGraph*)rg);
1470 /****************************************** FILTERING **************************************************/
1472 float lengthArc(ReebArc *arc)
1475 ReebNode *head = (ReebNode*)arc->head;
1476 ReebNode *tail = (ReebNode*)arc->tail;
1478 return tail->weight - head->weight;
1484 int compareArcs(void *varc1, void *varc2)
1486 ReebArc *arc1 = (ReebArc*)varc1;
1487 ReebArc *arc2 = (ReebArc*)varc2;
1488 float len1 = lengthArc(arc1);
1489 float len2 = lengthArc(arc2);
1505 void filterArc(ReebGraph *rg, ReebNode *newNode, ReebNode *removedNode, ReebArc * srcArc, int merging)
1507 ReebArc *arc = NULL, *nextArc = NULL;
1511 /* first pass, merge buckets for arcs that spawned the two nodes into the source arc*/
1512 for(arc = rg->arcs.first; arc; arc = arc->next)
1514 if (arc->head == srcArc->head && arc->tail == srcArc->tail && arc != srcArc)
1516 ReebNode *head = srcArc->head;
1517 ReebNode *tail = srcArc->tail;
1518 mergeArcBuckets(srcArc, arc, head->weight, tail->weight);
1523 /* second pass, replace removedNode by newNode, remove arcs that are collapsed in a loop */
1524 arc = rg->arcs.first;
1527 nextArc = arc->next;
1529 if (arc->head == removedNode || arc->tail == removedNode)
1531 if (arc->head == removedNode)
1533 arc->head = newNode;
1537 arc->tail = newNode;
1540 // Remove looped arcs
1541 if (arc->head == arc->tail)
1543 // v1 or v2 was already newNode, since we're removing an arc, decrement degree
1544 NodeDegreeDecrement(rg, newNode);
1546 // If it's srcArc, it'll be removed later, so keep it for now
1549 BLI_remlink(&rg->arcs, arc);
1550 REEB_freeArc((BArc*)arc);
1555 /* flip arcs that flipped, can happen on diamond shapes, mostly on null arcs */
1556 if (arc->head->weight > arc->tail->weight)
1560 //newNode->degree++; // incrementing degree since we're adding an arc
1561 NodeDegreeIncrement(rg, newNode);
1562 mergeArcFaces(rg, arc, srcArc);
1566 ReebNode *head = arc->head;
1567 ReebNode *tail = arc->tail;
1569 // resize bucket list
1570 resizeArcBuckets(arc);
1571 mergeArcBuckets(arc, srcArc, head->weight, tail->weight);
1574 arc->length += srcArc->length;
1583 void filterNullReebGraph(ReebGraph *rg)
1585 ReebArc *arc = NULL, *nextArc = NULL;
1587 arc = rg->arcs.first;
1590 nextArc = arc->next;
1591 // Only collapse arcs too short to have any embed bucket
1592 if (arc->bcount == 0)
1594 ReebNode *newNode = (ReebNode*)arc->head;
1595 ReebNode *removedNode = (ReebNode*)arc->tail;
1598 blend = (float)newNode->degree / (float)(newNode->degree + removedNode->degree); // blending factors
1600 VecLerpf(newNode->p, removedNode->p, newNode->p, blend);
1602 filterArc(rg, newNode, removedNode, arc, 0);
1604 // Reset nextArc, it might have changed
1605 nextArc = arc->next;
1607 BLI_remlink(&rg->arcs, arc);
1608 REEB_freeArc((BArc*)arc);
1610 BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
1617 int filterInternalExternalReebGraph(ReebGraph *rg, float threshold_internal, float threshold_external)
1619 ReebArc *arc = NULL, *nextArc = NULL;
1622 BLI_sortlist(&rg->arcs, compareArcs);
1624 for (arc = rg->arcs.first; arc; arc = nextArc)
1626 nextArc = arc->next;
1628 // Only collapse non-terminal arcs that are shorter than threshold
1629 if (threshold_internal > 0 && arc->head->degree > 1 && arc->tail->degree > 1 && (lengthArc(arc) < threshold_internal))
1631 ReebNode *newNode = NULL;
1632 ReebNode *removedNode = NULL;
1634 /* Always remove lower node, so arcs don't flip */
1635 newNode = arc->head;
1636 removedNode = arc->tail;
1638 filterArc(rg, newNode, removedNode, arc, 1);
1640 // Reset nextArc, it might have changed
1641 nextArc = arc->next;
1643 BLI_remlink(&rg->arcs, arc);
1644 REEB_freeArc((BArc*)arc);
1646 BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
1650 // Only collapse terminal arcs that are shorter than threshold
1651 else if (threshold_external > 0 && (arc->head->degree == 1 || arc->tail->degree == 1) && (lengthArc(arc) < threshold_external))
1653 ReebNode *terminalNode = NULL;
1654 ReebNode *middleNode = NULL;
1655 ReebNode *removedNode = NULL;
1657 // Assign terminal and middle nodes
1658 if (arc->head->degree == 1)
1660 terminalNode = arc->head;
1661 middleNode = arc->tail;
1665 terminalNode = arc->tail;
1666 middleNode = arc->head;
1669 if (middleNode->degree == 2 && middleNode != rg->nodes.first)
1672 // If middle node is a normal node, it will be removed later
1673 // Only if middle node is not the root node
1674 /* USE THIS IF YOU WANT TO PROLONG ARCS TO THEIR TERMINAL NODES
1675 * FOR HANDS, THIS IS NOT THE BEST RESULT
1679 removedNode = terminalNode;
1681 // removing arc, so we need to decrease the degree of the remaining node
1682 NodeDegreeDecrement(rg, middleNode);
1685 // Otherwise, just plain remove of the arc
1688 removedNode = terminalNode;
1690 // removing arc, so we need to decrease the degree of the remaining node
1691 NodeDegreeDecrement(rg, middleNode);
1694 // Reset nextArc, it might have changed
1695 nextArc = arc->next;
1697 BLI_remlink(&rg->arcs, arc);
1698 REEB_freeArc((BArc*)arc);
1700 BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
1708 int filterCyclesReebGraph(ReebGraph *rg, float distance_threshold)
1710 ReebArc *arc1, *arc2;
1714 for (arc1 = rg->arcs.first; arc1; arc1 = arc1->next)
1716 for (arc2 = arc1->next; arc2; arc2 = next2)
1719 if (arc1 != arc2 && arc1->head == arc2->head && arc1->tail == arc2->tail)
1721 mergeArcEdges(rg, arc1, arc2, MERGE_APPEND);
1722 mergeArcFaces(rg, arc1, arc2);
1723 mergeArcBuckets(arc1, arc2, arc1->head->weight, arc1->tail->weight);
1725 NodeDegreeDecrement(rg, arc1->head);
1726 NodeDegreeDecrement(rg, arc1->tail);
1728 BLI_remlink(&rg->arcs, arc2);
1729 REEB_freeArc((BArc*)arc2);
1739 int filterSmartReebGraph(ReebGraph *rg, float threshold)
1743 ReebArc *arc = NULL, *nextArc = NULL;
1745 BLI_sortlist(&rg->arcs, compareArcs);
1750 for(efa=G.editMesh->faces.first; efa; efa=efa->next) {
1756 arc = rg->arcs.first;
1759 nextArc = arc->next;
1761 /* need correct normals and center */
1762 recalc_editnormals();
1764 // Only test terminal arcs
1765 if (arc->head->degree == 1 || arc->tail->degree == 1)
1769 int total = BLI_ghash_size(arc->faces);
1770 float avg_angle = 0;
1771 float avg_vec[3] = {0,0,0};
1773 for(BLI_ghashIterator_init(&ghi, arc->faces);
1774 !BLI_ghashIterator_isDone(&ghi);
1775 BLI_ghashIterator_step(&ghi))
1777 EditFace *efa = BLI_ghashIterator_getValue(&ghi);
1780 ReebArcIterator arc_iter;
1781 BArcIterator *iter = (BArcIterator*)&arc_iter;
1782 EmbedBucket *bucket = NULL;
1783 EmbedBucket *previous = NULL;
1784 float min_distance = -1;
1787 initArcIterator(iter, arc, arc->head);
1789 bucket = nextBucket(iter);
1791 while (bucket != NULL)
1794 float *vec1 = bucket->p;
1795 float midpoint[3], tangent[3];
1798 /* first bucket. Previous is head */
1799 if (previous == NULL)
1801 vec0 = arc->head->p;
1803 /* Previous is a valid bucket */
1809 VECCOPY(midpoint, vec1);
1811 distance = VecLenf(midpoint, efa->cent);
1813 if (min_distance == -1 || distance < min_distance)
1815 min_distance = distance;
1817 VecSubf(tangent, vec1, vec0);
1820 angle = Inpf(tangent, efa->n);
1824 bucket = nextBucket(iter);
1827 avg_angle += saacos(fabs(angle));
1829 efa->tmp.fp = saacos(fabs(angle));
1832 VecAddf(avg_vec, avg_vec, efa->n);
1840 VecMulf(avg_vec, 1.0 / total);
1841 avg_angle = Inpf(avg_vec, avg_vec);
1844 arc->angle = avg_angle;
1846 if (avg_angle > threshold)
1851 ReebNode *terminalNode = NULL;
1852 ReebNode *middleNode = NULL;
1853 ReebNode *newNode = NULL;
1854 ReebNode *removedNode = NULL;
1857 // Assign terminal and middle nodes
1858 if (arc->head->degree == 1)
1860 terminalNode = arc->head;
1861 middleNode = arc->tail;
1865 terminalNode = arc->tail;
1866 middleNode = arc->head;
1869 // If middle node is a normal node, merge to terminal node
1870 if (middleNode->degree == 2)
1873 newNode = terminalNode;
1874 removedNode = middleNode;
1876 // Otherwise, just plain remove of the arc
1880 newNode = middleNode;
1881 removedNode = terminalNode;
1887 filterArc(rg, newNode, removedNode, arc, 1);
1891 // removing arc, so we need to decrease the degree of the remaining node
1892 //newNode->degree--;
1893 NodeDegreeDecrement(rg, newNode);
1896 // Reset nextArc, it might have changed
1897 nextArc = arc->next;
1899 BLI_remlink(&rg->arcs, arc);
1900 REEB_freeArc((BArc*)arc);
1902 BLI_freelinkN(&rg->nodes, removedNode);
1915 void filterGraph(ReebGraph *rg, short options, float threshold_internal, float threshold_external)
1919 calculateGraphLength(rg);
1921 if ((options & SKGEN_FILTER_EXTERNAL) == 0)
1923 threshold_external = 0;
1926 if ((options & SKGEN_FILTER_INTERNAL) == 0)
1928 threshold_internal = 0;
1931 if (threshold_internal > 0 || threshold_external > 0)
1933 /* filter until there's nothing more to do */
1936 done = 0; /* no work done yet */
1938 done = filterInternalExternalReebGraph(rg, threshold_internal, threshold_external);
1942 if (options & SKGEN_FILTER_SMART)
1944 filterSmartReebGraph(rg, 0.5);
1945 filterCyclesReebGraph(rg, 0.5);
1948 repositionNodes(rg);
1950 /* Filtering might have created degree 2 nodes, so remove them */
1951 removeNormalNodes(rg);
1954 void finalizeGraph(ReebGraph *rg, char passes, char method)
1958 BLI_buildAdjacencyList((BGraph*)rg);
1964 for(i = 0; i < passes; i++)
1966 postprocessGraph(rg, method);
1969 extendGraphBuckets(rg);
1972 /************************************** WEIGHT SPREADING ***********************************************/
1974 int compareVerts( const void* a, const void* b )
1976 EditVert *va = *(EditVert**)a;
1977 EditVert *vb = *(EditVert**)b;
1980 if (weightData(va) < weightData(vb))
1984 else if (weightData(va) > weightData(vb))
1992 void spreadWeight(EditMesh *em)
1994 EditVert **verts, *eve;
1995 float lastWeight = 0.0f;
1996 int totvert = BLI_countlist(&em->verts);
1998 int work_needed = 1;
2000 verts = MEM_callocN(sizeof(EditVert*) * totvert, "verts array");
2002 for(eve = em->verts.first, i = 0; eve; eve = eve->next, i++)
2007 while(work_needed == 1)
2010 qsort(verts, totvert, sizeof(EditVert*), compareVerts);
2012 for(i = 0; i < totvert; i++)
2016 if (i == 0 || (weightData(eve) - lastWeight) > FLT_EPSILON)
2018 lastWeight = weightData(eve);
2023 weightSetData(eve, lastWeight + FLT_EPSILON * 2);
2024 lastWeight = weightData(eve);
2032 /******************************************** EXPORT ***************************************************/
2034 void exportNode(FILE *f, char *text, ReebNode *node)
2036 fprintf(f, "%s i:%i w:%f d:%i %f %f %f\n", text, node->index, node->weight, node->degree, node->p[0], node->p[1], node->p[2]);
2039 void REEB_exportGraph(ReebGraph *rg, int count)
2047 sprintf(filename, "test.txt");
2051 sprintf(filename, "test%05i.txt", count);
2053 f = fopen(filename, "w");
2055 for(arc = rg->arcs.first; arc; arc = arc->next)
2060 exportNode(f, "v1", arc->head);
2062 for(i = 0; i < arc->bcount; i++)
2064 fprintf(f, "b nv:%i %f %f %f\n", arc->buckets[i].nv, arc->buckets[i].p[0], arc->buckets[i].p[1], arc->buckets[i].p[2]);
2067 VecAddf(p, arc->tail->p, arc->head->p);
2070 fprintf(f, "angle %0.3f %0.3f %0.3f %0.3f %i\n", p[0], p[1], p[2], arc->angle, BLI_ghash_size(arc->faces));
2071 exportNode(f, "v2", arc->tail);
2077 /***************************************** MAIN ALGORITHM **********************************************/
2079 /* edges alone will create zero degree nodes, use this function to remove them */
2080 void removeZeroNodes(ReebGraph *rg)
2082 ReebNode *node, *next_node;
2084 for (node = rg->nodes.first; node; node = next_node)
2086 next_node = node->next;
2088 if (node->degree == 0)
2090 BLI_removeNode((BGraph*)rg, (BNode*)node);
2095 void removeNormalNodes(ReebGraph *rg)
2097 ReebArc *arc, *nextArc;
2099 // Merge degree 2 nodes
2100 for(arc = rg->arcs.first; arc; arc = nextArc)
2102 nextArc = arc->next;
2104 while (arc->head->degree == 2 || arc->tail->degree == 2)
2107 if (arc->head->degree == 2)
2109 ReebArc *connectedArc = (ReebArc*)BLI_findConnectedArc((BGraph*)rg, (BArc*)arc, (BNode*)arc->head);
2111 /* If arcs are one after the other */
2112 if (arc->head == connectedArc->tail)
2114 /* remove furthest arc */
2115 if (arc->tail->weight < connectedArc->head->weight)
2117 mergeConnectedArcs(rg, arc, connectedArc);
2118 nextArc = arc->next;
2122 mergeConnectedArcs(rg, connectedArc, arc);
2123 break; /* arc was removed, move to next */
2126 /* Otherwise, arcs are side by side */
2129 /* Don't do anything, we need to keep the lowest node, even if degree 2 */
2135 if (arc->tail->degree == 2)
2137 ReebArc *connectedArc = (ReebArc*)BLI_findConnectedArc((BGraph*)rg, (BArc*)arc, (BNode*)arc->tail);
2139 /* If arcs are one after the other */
2140 if (arc->tail == connectedArc->head)
2142 /* remove furthest arc */
2143 if (arc->head->weight < connectedArc->tail->weight)
2145 mergeConnectedArcs(rg, arc, connectedArc);
2146 nextArc = arc->next;
2150 mergeConnectedArcs(rg, connectedArc, arc);
2151 break; /* arc was removed, move to next */
2154 /* Otherwise, arcs are side by side */
2157 /* Don't do anything, we need to keep the lowest node, even if degree 2 */
2166 int edgeEquals(ReebEdge *e1, ReebEdge *e2)
2168 return (e1->v1 == e2->v1 && e1->v2 == e2->v2);
2171 ReebArc *nextArcMappedToEdge(ReebArc *arc, ReebEdge *e)
2173 ReebEdge *nextEdge = NULL;
2174 ReebEdge *edge = NULL;
2175 ReebArc *result = NULL;
2177 /* Find the ReebEdge in the edge list */
2178 for(edge = arc->edges.first; edge && !edgeEquals(edge, e); edge = edge->next)
2181 nextEdge = edge->nextEdge;
2183 if (nextEdge != NULL)
2185 result = nextEdge->arc;
2191 void addFacetoArc(ReebArc *arc, EditFace *efa)
2193 BLI_ghash_insert(arc->faces, efa, efa);
2196 void mergeArcFaces(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc)
2200 for(BLI_ghashIterator_init(&ghi, aSrc->faces);
2201 !BLI_ghashIterator_isDone(&ghi);
2202 BLI_ghashIterator_step(&ghi))
2204 EditFace *efa = BLI_ghashIterator_getValue(&ghi);
2205 BLI_ghash_insert(aDst->faces, efa, efa);
2209 void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction)
2213 if (direction == MERGE_APPEND)
2215 for(e = aSrc->edges.first; e; e = e->next)
2217 e->arc = aDst; // Edge is stolen by new arc
2220 addlisttolist(&aDst->edges , &aSrc->edges);
2224 for(e = aSrc->edges.first; e; e = e->next)
2226 ReebEdge *newEdge = copyEdge(e);
2228 newEdge->arc = aDst;
2230 BLI_addtail(&aDst->edges, newEdge);
2232 if (direction == MERGE_LOWER)
2234 void **p = BLI_edgehash_lookup_p(rg->emap, e->v1->index, e->v2->index);
2236 newEdge->nextEdge = e;
2238 // if edge was the first in the list, point the edit edge to the new reeb edge instead.
2241 *p = (void*)newEdge;
2243 // otherwise, advance in the list until the predecessor is found then insert it there
2246 ReebEdge *previous = (ReebEdge*)*p;
2248 while(previous->nextEdge != e)
2250 previous = previous->nextEdge;
2253 previous->nextEdge = newEdge;
2258 newEdge->nextEdge = e->nextEdge;
2259 e->nextEdge = newEdge;
2265 // return 1 on full merge
2266 int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1)
2269 ReebNode *removedNode = NULL;
2271 a0->length += a1->length;
2273 mergeArcEdges(rg, a0, a1, MERGE_APPEND);
2274 mergeArcFaces(rg, a0, a1);
2276 // Bring a0 to the combine length of both arcs
2277 if (a0->tail == a1->head)
2279 removedNode = a0->tail;
2280 a0->tail = a1->tail;
2282 else if (a0->head == a1->tail)
2284 removedNode = a0->head;
2285 a0->head = a1->head;
2288 resizeArcBuckets(a0);
2290 mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
2292 // remove a1 from graph
2293 BLI_remlink(&rg->arcs, a1);
2294 REEB_freeArc((BArc*)a1);
2296 BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
2301 // return 1 on full merge
2302 int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1)
2305 // TRIANGLE POINTS DOWN
2306 if (a0->head->weight == a1->head->weight) // heads are the same
2308 if (a0->tail->weight == a1->tail->weight) // tails also the same, arcs can be totally merge together
2310 mergeArcEdges(rg, a0, a1, MERGE_APPEND);
2311 mergeArcFaces(rg, a0, a1);
2313 mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
2315 // Adjust node degree
2316 //a1->head->degree--;
2317 NodeDegreeDecrement(rg, a1->head);
2318 //a1->tail->degree--;
2319 NodeDegreeDecrement(rg, a1->tail);
2321 // remove a1 from graph
2322 BLI_remlink(&rg->arcs, a1);
2324 REEB_freeArc((BArc*)a1);
2327 else if (a0->tail->weight > a1->tail->weight) // a1->tail->weight is in the middle
2329 mergeArcEdges(rg, a1, a0, MERGE_LOWER);
2330 mergeArcFaces(rg, a1, a0);
2332 // Adjust node degree
2333 //a0->head->degree--;
2334 NodeDegreeDecrement(rg, a0->head);
2335 //a1->tail->degree++;
2336 NodeDegreeIncrement(rg, a1->tail);
2338 mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight);
2339 a0->head = a1->tail;
2340 resizeArcBuckets(a0);
2342 else // a0>n2 is in the middle
2344 mergeArcEdges(rg, a0, a1, MERGE_LOWER);
2345 mergeArcFaces(rg, a0, a1);
2347 // Adjust node degree
2348 //a1->head->degree--;
2349 NodeDegreeDecrement(rg, a1->head);
2350 //a0->tail->degree++;
2351 NodeDegreeIncrement(rg, a0->tail);
2353 mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
2354 a1->head = a0->tail;
2355 resizeArcBuckets(a1);
2358 // TRIANGLE POINTS UP
2359 else if (a0->tail->weight == a1->tail->weight) // tails are the same
2361 if (a0->head->weight > a1->head->weight) // a0->head->weight is in the middle
2363 mergeArcEdges(rg, a0, a1, MERGE_HIGHER);
2364 mergeArcFaces(rg, a0, a1);
2366 // Adjust node degree
2367 //a1->tail->degree--;
2368 NodeDegreeDecrement(rg, a1->tail);
2369 //a0->head->degree++;
2370 NodeDegreeIncrement(rg, a0->head);
2372 mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
2373 a1->tail = a0->head;
2374 resizeArcBuckets(a1);
2376 else // a1->head->weight is in the middle
2378 mergeArcEdges(rg, a1, a0, MERGE_HIGHER);
2379 mergeArcFaces(rg, a1, a0);
2381 // Adjust node degree
2382 //a0->tail->degree--;
2383 NodeDegreeDecrement(rg, a0->tail);
2384 //a1->head->degree++;
2385 NodeDegreeIncrement(rg, a1->head);
2387 mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight);
2388 a0->tail = a1->head;
2389 resizeArcBuckets(a0);
2394 // Need something here (OR NOT)
2400 void glueByMergeSort(ReebGraph *rg, ReebArc *a0, ReebArc *a1, ReebEdge *e0, ReebEdge *e1)
2403 while (total == 0 && a0 != a1 && a0 != NULL && a1 != NULL)
2405 total = mergeArcs(rg, a0, a1);
2407 if (total == 0) // if it wasn't a total merge, go forward
2409 if (a0->tail->weight < a1->tail->weight)
2411 a0 = nextArcMappedToEdge(a0, e0);
2415 a1 = nextArcMappedToEdge(a1, e1);
2421 void mergePaths(ReebGraph *rg, ReebEdge *e0, ReebEdge *e1, ReebEdge *e2)
2423 ReebArc *a0, *a1, *a2;
2428 glueByMergeSort(rg, a0, a1, e0, e1);
2429 glueByMergeSort(rg, a0, a2, e0, e2);
2432 ReebEdge * createArc(ReebGraph *rg, ReebNode *node1, ReebNode *node2)
2436 edge = BLI_edgehash_lookup(rg->emap, node1->index, node2->index);
2438 // Only add existing edges that haven't been added yet
2446 arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
2447 edge = MEM_callocN(sizeof(ReebEdge), "reeb edge");
2449 arc->flag = 0; // clear flag on init
2450 arc->symmetry_level = 0;
2451 arc->faces = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
2453 if (node1->weight <= node2->weight)
2467 // increase node degree
2469 NodeDegreeIncrement(rg, v1);
2471 NodeDegreeIncrement(rg, v2);
2473 BLI_edgehash_insert(rg->emap, node1->index, node2->index, edge);
2476 edge->nextEdge = NULL;
2480 BLI_addtail(&rg->arcs, arc);
2481 BLI_addtail(&arc->edges, edge);
2483 /* adding buckets for embedding */
2484 allocArcBuckets(arc);
2486 offset = arc->head->weight;
2487 len = arc->tail->weight - arc->head->weight;
2490 /* This is the actual embedding filling described in the paper
2491 * the problem is that it only works with really dense meshes
2493 if (arc->bcount > 0)
2495 addVertToBucket(&(arc->buckets[0]), arc->head->co);
2496 addVertToBucket(&(arc->buckets[arc->bcount - 1]), arc->tail->co);
2499 for(i = 0; i < arc->bcount; i++)
2502 float f = (arc->buckets[i].val - offset) / len;
2504 VecLerpf(co, v1->p, v2->p, f);
2505 addVertToBucket(&(arc->buckets[i]), co);
2514 void addTriangleToGraph(ReebGraph *rg, ReebNode * n1, ReebNode * n2, ReebNode * n3, EditFace *efa)
2516 ReebEdge *re1, *re2, *re3;
2517 ReebEdge *e1, *e2, *e3;
2518 float len1, len2, len3;
2520 re1 = createArc(rg, n1, n2);
2521 re2 = createArc(rg, n2, n3);
2522 re3 = createArc(rg, n3, n1);
2524 addFacetoArc(re1->arc, efa);
2525 addFacetoArc(re2->arc, efa);
2526 addFacetoArc(re3->arc, efa);
2528 len1 = (float)fabs(n1->weight - n2->weight);
2529 len2 = (float)fabs(n2->weight - n3->weight);
2530 len3 = (float)fabs(n3->weight - n1->weight);
2532 /* The rest of the algorithm assumes that e1 is the longest edge */
2534 if (len1 >= len2 && len1 >= len3)
2540 else if (len2 >= len1 && len2 >= len3)
2553 /* And e2 is the lowest edge
2554 * If e3 is lower than e2, swap them
2556 if (e3->v1->weight < e2->v1->weight)
2558 ReebEdge *etmp = e2;
2564 mergePaths(rg, e1, e2, e3);
2567 ReebGraph * generateReebGraph(EditMesh *em, int subdivisions)
2580 rg = newReebGraph();
2582 rg->resolution = subdivisions;
2584 totvert = BLI_countlist(&em->verts);
2585 totfaces = BLI_countlist(&em->faces);
2587 renormalizeWeight(em, 1.0f);
2589 /* Spread weight to minimize errors */
2592 renormalizeWeight(em, (float)rg->resolution);
2594 /* Adding vertice */
2595 for(index = 0, eve = em->verts.first; eve; eve = eve->next)
2605 /* Adding face, edge per edge */
2606 for(efa = em->faces.first; efa; efa = efa->next)
2610 ReebNode *n1, *n2, *n3;
2612 n1 = nodeData(efa->v1);
2613 n2 = nodeData(efa->v2);
2614 n3 = nodeData(efa->v3);
2616 addTriangleToGraph(rg, n1, n2, n3, efa);
2620 ReebNode *n4 = nodeData(efa->v4);
2621 addTriangleToGraph(rg, n1, n3, n4, efa);
2625 if (countfaces % 100 == 0)
2627 printf("\rface %i of %i", countfaces, totfaces);
2635 removeZeroNodes(rg);
2637 removeNormalNodes(rg);
2642 /***************************************** WEIGHT UTILS **********************************************/
2644 void renormalizeWeight(EditMesh *em, float newmax)
2647 float minimum, maximum, range;
2649 if (em == NULL || BLI_countlist(&em->verts) == 0)
2652 /* First pass, determine maximum and minimum */
2653 eve = em->verts.first;
2654 minimum = weightData(eve);
2656 for(eve = em->verts.first; eve; eve = eve->next)
2658 maximum = MAX2(maximum, weightData(eve));
2659 minimum = MIN2(minimum, weightData(eve));
2662 range = maximum - minimum;
2664 /* Normalize weights */
2665 for(eve = em->verts.first; eve; eve = eve->next)
2667 float weight = (weightData(eve) - minimum) / range * newmax;
2668 weightSetData(eve, weight);
2673 int weightFromLoc(EditMesh *em, int axis)
2677 if (em == NULL || BLI_countlist(&em->verts) == 0 || axis < 0 || axis > 2)
2680 /* Copy coordinate in weight */
2681 for(eve = em->verts.first; eve; eve = eve->next)
2683 weightSetData(eve, eve->co[axis]);
2689 static float cotan_weight(float *v1, float *v2, float *v3)
2691 float a[3], b[3], c[3], clen;
2697 clen = VecLength(c);
2702 return Inpf(a, b)/clen;
2705 void addTriangle(EditVert *v1, EditVert *v2, EditVert *v3, int e1, int e2, int e3)
2707 /* Angle opposite e1 */
2708 float t1= cotan_weight(v1->co, v2->co, v3->co) / e2;
2710 /* Angle opposite e2 */
2711 float t2 = cotan_weight(v2->co, v3->co, v1->co) / e3;
2713 /* Angle opposite e3 */
2714 float t3 = cotan_weight(v3->co, v1->co, v2->co) / e1;
2716 int i1 = indexData(v1);
2717 int i2 = indexData(v2);
2718 int i3 = indexData(v3);
2720 nlMatrixAdd(i1, i1, t2+t3);
2721 nlMatrixAdd(i2, i2, t1+t3);
2722 nlMatrixAdd(i3, i3, t1+t2);
2724 nlMatrixAdd(i1, i2, -t3);
2725 nlMatrixAdd(i2, i1, -t3);
2727 nlMatrixAdd(i2, i3, -t1);
2728 nlMatrixAdd(i3, i2, -t1);
2730 nlMatrixAdd(i3, i1, -t2);
2731 nlMatrixAdd(i1, i3, -t2);
2734 int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges)
2744 /* Find local extrema */
2745 for(eve = em->verts.first; eve; eve = eve->next)
2750 /* Solve with openNL */
2754 nlSolverParameteri(NL_NB_VARIABLES, totvert);
2758 /* Find local extrema */
2759 for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
2767 NextEdgeForVert(indexed_edges, -1); /* Reset next edge */
2768 for(eed = NextEdgeForVert(indexed_edges, index); eed && (maximum || minimum); eed = NextEdgeForVert(indexed_edges, index))
2783 /* Adjacent vertex is bigger, not a local maximum */
2784 if (weightData(eve2) > weightData(eve))
2788 /* Adjacent vertex is smaller, not a local minimum */
2789 else if (weightData(eve2) < weightData(eve))
2796 if (maximum || minimum)
2798 float w = weightData(eve);
2800 nlSetVariable(0, index, w);
2801 nlLockVariable(index);
2812 /* Zero edge weight */
2813 for(eed = em->edges.first; eed; eed = eed->next)
2818 /* Add faces count to the edge weight */
2819 for(efa = em->faces.first; efa; efa = efa->next)
2834 /* Add faces angle to the edge weight */
2835 for(efa = em->faces.first; efa; efa = efa->next)
2839 if (efa->v4 == NULL)
2841 addTriangle(efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, efa->e3->tmp.l);
2845 addTriangle(efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, 2);
2846 addTriangle(efa->v3, efa->v4, efa->v1, efa->e3->tmp.l, efa->e4->tmp.l, 2);
2855 success = nlSolveAdvanced(NULL, NL_TRUE);
2860 for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
2862 weightSetData(eve, nlGetVariable(0, index));
2870 nlDeleteContext(nlGetCurrent());
2876 EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index)
2878 static int offset = -1;
2880 /* Reset method, call with NULL mesh pointer */
2887 /* first pass, start at the head of the list */
2890 offset = indexed_edges->offset[index];
2892 /* subsequent passes, start on the next edge */
2898 return indexed_edges->edges[offset];
2901 void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeIndex *indexed_edges)
2904 EditVert *current_eve = NULL;
2905 EditEdge *eed = NULL;
2906 EditEdge *select_eed = NULL;
2908 edge_heap = BLI_heap_new();
2910 current_eve = starting_vert;
2912 /* insert guard in heap, when that is returned, no more edges */
2913 BLI_heap_insert(edge_heap, FLT_MAX, NULL);
2915 /* Initialize edge flag */
2916 for(eed= em->edges.first; eed; eed= eed->next)
2921 while (BLI_heap_size(edge_heap) > 0)
2923 float current_weight;
2925 current_eve->f1 = 1; /* mark vertex as selected */
2927 /* Add all new edges connected to current_eve to the list */
2928 NextEdgeForVert(indexed_edges, -1); // Reset next edge
2929 for(eed = NextEdgeForVert(indexed_edges, indexData(current_eve)); eed; eed = NextEdgeForVert(indexed_edges, indexData(current_eve)))
2933 BLI_heap_insert(edge_heap, weightData(current_eve) + eed->tmp.fp, eed);
2938 /* Find next shortest edge with unselected verts */
2941 current_weight = BLI_heap_node_value(BLI_heap_top(edge_heap));
2942 select_eed = BLI_heap_popmin(edge_heap);
2943 } while (select_eed != NULL && select_eed->v1->f1 != 0 && select_eed->v2->f1);
2945 if (select_eed != NULL)
2949 if (select_eed->v1->f1 == 0) /* v1 is the new vertex */
2951 current_eve = select_eed->v1;
2953 else /* otherwise, it's v2 */
2955 current_eve = select_eed->v2;
2958 weightSetData(current_eve, current_weight);
2962 BLI_heap_free(edge_heap, NULL);
2965 void freeEdgeIndex(EdgeIndex *indexed_edges)
2967 MEM_freeN(indexed_edges->offset);
2968 MEM_freeN(indexed_edges->edges);
2971 void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges)
2976 int tot_indexed = 0;
2979 totvert = BLI_countlist(&em->verts);
2981 indexed_edges->offset = MEM_callocN(totvert * sizeof(int), "EdgeIndex offset");
2983 for(eed = em->edges.first; eed; eed = eed->next)
2985 if (eed->v1->h == 0 && eed->v2->h == 0)
2988 indexed_edges->offset[indexData(eed->v1)]++;
2989 indexed_edges->offset[indexData(eed->v2)]++;
2993 tot_indexed += totvert;
2995 indexed_edges->edges = MEM_callocN(tot_indexed * sizeof(EditEdge*), "EdgeIndex edges");
2997 /* setting vert offsets */
2998 for(eve = em->verts.first; eve; eve = eve->next)
3002 int d = indexed_edges->offset[indexData(eve)];
3003 indexed_edges->offset[indexData(eve)] = offset;
3008 /* adding edges in array */
3009 for(eed = em->edges.first; eed; eed= eed->next)
3011 if (eed->v1->h == 0 && eed->v2->h == 0)
3014 for (i = indexed_edges->offset[indexData(eed->v1)]; i < tot_indexed; i++)
3016 if (indexed_edges->edges[i] == NULL)
3018 indexed_edges->edges[i] = eed;
3023 for (i = indexed_edges->offset[indexData(eed->v2)]; i < tot_indexed; i++)
3025 if (indexed_edges->edges[i] == NULL)
3027 indexed_edges->edges[i] = eed;
3035 int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges)
3042 totvert = BLI_countlist(&em->verts);
3044 if (em == NULL || totvert == 0)
3049 totedge = BLI_countlist(&em->edges);
3056 /* Initialize vertice flag and find at least one selected vertex */
3057 for(eve = em->verts.first; eve; eve = eve->next)
3060 if (eve->f & SELECT)
3068 return 0; /* no selected vert, failure */
3075 /* Calculate edge weight */
3076 for(eed = em->edges.first; eed; eed= eed->next)
3078 if (eed->v1->h == 0 && eed->v2->h == 0)
3080 eed->tmp.fp = VecLenf(eed->v1->co, eed->v2->co);
3084 /* Apply dijkstra spf for each selected vert */
3085 for(eve = em->verts.first; eve; eve = eve->next)
3087 if (eve->f & SELECT)
3089 shortestPathsFromVert(em, eve, indexed_edges);
3093 /* connect unselected islands */
3094 while (allDone == 0)
3096 EditVert *selected_eve = NULL;
3097 float selected_weight = 0;
3098 float min_distance = FLT_MAX;
3102 for (eve = em->verts.first; eve; eve = eve->next)
3104 /* for every vertex visible that hasn't been processed yet */
3105 if (eve->h == 0 && eve->f1 != 1)
3107 EditVert *closest_eve;
3109 /* find the closest processed vertex */
3110 for (closest_eve = em->verts.first; closest_eve; closest_eve = closest_eve->next)
3112 /* vertex is already processed and distance is smaller than current minimum */
3113 if (closest_eve->f1 == 1)
3115 float distance = VecLenf(closest_eve->co, eve->co);
3116 if (distance < min_distance)
3118 min_distance = distance;
3120 selected_weight = weightData(closest_eve);
3131 weightSetData(selected_eve, selected_weight + min_distance);
3132 shortestPathsFromVert(em, selected_eve, indexed_edges);
3137 for(eve = em->verts.first; eve && vCount == 0; eve = eve->next)