Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Contributor(s): Martin Poirier 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00028 #include <math.h> 00029 #include <string.h> // for memcpy 00030 #include <stdio.h> 00031 #include <stdlib.h> // for qsort 00032 #include <float.h> 00033 00034 #include "DNA_scene_types.h" 00035 #include "DNA_object_types.h" 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "BKE_context.h" 00040 00041 #include "BLI_blenlib.h" 00042 #include "BLI_math.h" 00043 #include "BLI_utildefines.h" 00044 #include "BLI_editVert.h" 00045 #include "BLI_edgehash.h" 00046 #include "BLI_ghash.h" 00047 #include "BLI_heap.h" 00048 00049 //#include "BDR_editobject.h" 00050 00051 //#include "BIF_interface.h" 00052 //#include "BIF_toolbox.h" 00053 //#include "BIF_graphics.h" 00054 00055 00056 //#include "blendef.h" 00057 00058 #include "ONL_opennl.h" 00059 00060 #include "reeb.h" 00061 00062 #if 0 /* UNUSED 2.5 */ 00063 static ReebGraph *GLOBAL_RG = NULL; 00064 static ReebGraph *FILTERED_RG = NULL; 00065 #endif 00066 00067 /* 00068 * Skeleton generation algorithm based on: 00069 * "Harmonic Skeleton for Realistic Character Animation" 00070 * Gregoire Aujay, Franck Hetroy, Francis Lazarus and Christine Depraz 00071 * SIGGRAPH 2007 00072 * 00073 * Reeb graph generation algorithm based on: 00074 * "Robust On-line Computation of Reeb Graphs: Simplicity and Speed" 00075 * Valerio Pascucci, Giorgio Scorzelli, Peer-Timo Bremer and Ajith Mascarenhas 00076 * SIGGRAPH 2007 00077 * 00078 * */ 00079 00080 #define DEBUG_REEB 00081 #define DEBUG_REEB_NODE 00082 00083 typedef struct VertexData 00084 { 00085 float w; /* weight */ 00086 int i; /* index */ 00087 ReebNode *n; 00088 } VertexData; 00089 00090 typedef struct EdgeIndex 00091 { 00092 EditEdge **edges; 00093 int *offset; 00094 } EdgeIndex; 00095 00096 typedef enum { 00097 MERGE_LOWER, 00098 MERGE_HIGHER, 00099 MERGE_APPEND 00100 } MergeDirection; 00101 00102 int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1); 00103 void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction); 00104 int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1); 00105 EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index); 00106 void mergeArcFaces(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc); 00107 void addFacetoArc(ReebArc *arc, EditFace *efa); 00108 00109 void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count); 00110 void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2); 00111 00112 void flipArcBuckets(ReebArc *arc); 00113 00114 00115 /***************************************** UTILS **********************************************/ 00116 00117 static VertexData *allocVertexData(EditMesh *em) 00118 { 00119 VertexData *data; 00120 EditVert *eve; 00121 int totvert, index; 00122 00123 totvert = BLI_countlist(&em->verts); 00124 00125 data = MEM_callocN(sizeof(VertexData) * totvert, "VertexData"); 00126 00127 for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next) 00128 { 00129 data[index].i = index; 00130 data[index].w = 0; 00131 eve->tmp.p = data + index; 00132 } 00133 00134 return data; 00135 } 00136 00137 static int indexData(EditVert *eve) 00138 { 00139 return ((VertexData*)eve->tmp.p)->i; 00140 } 00141 00142 static float weightData(EditVert *eve) 00143 { 00144 return ((VertexData*)eve->tmp.p)->w; 00145 } 00146 00147 static void weightSetData(EditVert *eve, float w) 00148 { 00149 ((VertexData*)eve->tmp.p)->w = w; 00150 } 00151 00152 static ReebNode* nodeData(EditVert *eve) 00153 { 00154 return ((VertexData*)eve->tmp.p)->n; 00155 } 00156 00157 static void nodeSetData(EditVert *eve, ReebNode *n) 00158 { 00159 ((VertexData*)eve->tmp.p)->n = n; 00160 } 00161 00162 void REEB_freeArc(BArc *barc) 00163 { 00164 ReebArc *arc = (ReebArc*)barc; 00165 BLI_freelistN(&arc->edges); 00166 00167 if (arc->buckets) 00168 MEM_freeN(arc->buckets); 00169 00170 if (arc->faces) 00171 BLI_ghash_free(arc->faces, NULL, NULL); 00172 00173 MEM_freeN(arc); 00174 } 00175 00176 void REEB_freeGraph(ReebGraph *rg) 00177 { 00178 ReebArc *arc; 00179 ReebNode *node; 00180 00181 // free nodes 00182 for( node = rg->nodes.first; node; node = node->next ) 00183 { 00184 BLI_freeNode((BGraph*)rg, (BNode*)node); 00185 } 00186 BLI_freelistN(&rg->nodes); 00187 00188 // free arcs 00189 arc = rg->arcs.first; 00190 while( arc ) 00191 { 00192 ReebArc *next = arc->next; 00193 REEB_freeArc((BArc*)arc); 00194 arc = next; 00195 } 00196 00197 // free edge map 00198 BLI_edgehash_free(rg->emap, NULL); 00199 00200 /* free linked graph */ 00201 if (rg->link_up) 00202 { 00203 REEB_freeGraph(rg->link_up); 00204 } 00205 00206 MEM_freeN(rg); 00207 } 00208 00209 ReebGraph * newReebGraph(void) 00210 { 00211 ReebGraph *rg; 00212 rg = MEM_callocN(sizeof(ReebGraph), "reeb graph"); 00213 00214 rg->totnodes = 0; 00215 rg->emap = BLI_edgehash_new(); 00216 00217 00218 rg->free_arc = REEB_freeArc; 00219 rg->free_node = NULL; 00220 rg->radial_symmetry = REEB_RadialSymmetry; 00221 rg->axial_symmetry = REEB_AxialSymmetry; 00222 00223 return rg; 00224 } 00225 00226 void BIF_flagMultiArcs(ReebGraph *rg, int flag) 00227 { 00228 for ( ; rg; rg = rg->link_up) 00229 { 00230 BLI_flagArcs((BGraph*)rg, flag); 00231 } 00232 } 00233 00234 static ReebNode * addNode(ReebGraph *rg, EditVert *eve) 00235 { 00236 float weight; 00237 ReebNode *node = NULL; 00238 00239 weight = weightData(eve); 00240 00241 node = MEM_callocN(sizeof(ReebNode), "reeb node"); 00242 00243 node->flag = 0; // clear flag on init 00244 node->symmetry_level = 0; 00245 node->arcs = NULL; 00246 node->degree = 0; 00247 node->weight = weight; 00248 node->index = rg->totnodes; 00249 VECCOPY(node->p, eve->co); 00250 00251 BLI_addtail(&rg->nodes, node); 00252 rg->totnodes++; 00253 00254 nodeSetData(eve, node); 00255 00256 return node; 00257 } 00258 00259 static ReebNode * copyNode(ReebGraph *rg, ReebNode *node) 00260 { 00261 ReebNode *cp_node = NULL; 00262 00263 cp_node = MEM_callocN(sizeof(ReebNode), "reeb node copy"); 00264 00265 memcpy(cp_node, node, sizeof(ReebNode)); 00266 00267 cp_node->prev = NULL; 00268 cp_node->next = NULL; 00269 cp_node->arcs = NULL; 00270 00271 cp_node->link_up = NULL; 00272 cp_node->link_down = NULL; 00273 00274 BLI_addtail(&rg->nodes, cp_node); 00275 rg->totnodes++; 00276 00277 return cp_node; 00278 } 00279 00280 static void relinkNodes(ReebGraph *low_rg, ReebGraph *high_rg) 00281 { 00282 ReebNode *low_node, *high_node; 00283 00284 if (low_rg == NULL || high_rg == NULL) 00285 { 00286 return; 00287 } 00288 00289 for (low_node = low_rg->nodes.first; low_node; low_node = low_node->next) 00290 { 00291 for (high_node = high_rg->nodes.first; high_node; high_node = high_node->next) 00292 { 00293 if (low_node->index == high_node->index) 00294 { 00295 high_node->link_down = low_node; 00296 low_node->link_up = high_node; 00297 break; 00298 } 00299 } 00300 } 00301 } 00302 00303 ReebNode *BIF_otherNodeFromIndex(ReebArc *arc, ReebNode *node) 00304 { 00305 return (arc->head->index == node->index) ? arc->tail : arc->head; 00306 } 00307 00308 ReebNode *BIF_NodeFromIndex(ReebArc *arc, ReebNode *node) 00309 { 00310 return (arc->head->index == node->index) ? arc->head : arc->tail; 00311 } 00312 00313 ReebNode *BIF_lowestLevelNode(ReebNode *node) 00314 { 00315 while (node->link_down) 00316 { 00317 node = node->link_down; 00318 } 00319 00320 return node; 00321 } 00322 00323 static ReebArc * copyArc(ReebGraph *rg, ReebArc *arc) 00324 { 00325 ReebArc *cp_arc; 00326 ReebNode *node; 00327 00328 cp_arc = MEM_callocN(sizeof(ReebArc), "reeb arc copy"); 00329 00330 memcpy(cp_arc, arc, sizeof(ReebArc)); 00331 00332 cp_arc->link_up = arc; 00333 00334 cp_arc->head = NULL; 00335 cp_arc->tail = NULL; 00336 00337 cp_arc->prev = NULL; 00338 cp_arc->next = NULL; 00339 00340 cp_arc->edges.first = NULL; 00341 cp_arc->edges.last = NULL; 00342 00343 /* copy buckets */ 00344 cp_arc->buckets = MEM_callocN(sizeof(EmbedBucket) * cp_arc->bcount, "embed bucket"); 00345 memcpy(cp_arc->buckets, arc->buckets, sizeof(EmbedBucket) * cp_arc->bcount); 00346 00347 /* copy faces map */ 00348 cp_arc->faces = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "copyArc gh"); 00349 mergeArcFaces(rg, cp_arc, arc); 00350 00351 /* find corresponding head and tail */ 00352 for (node = rg->nodes.first; node && (cp_arc->head == NULL || cp_arc->tail == NULL); node = node->next) 00353 { 00354 if (node->index == arc->head->index) 00355 { 00356 cp_arc->head = node; 00357 } 00358 else if (node->index == arc->tail->index) 00359 { 00360 cp_arc->tail = node; 00361 } 00362 } 00363 00364 BLI_addtail(&rg->arcs, cp_arc); 00365 00366 return cp_arc; 00367 } 00368 00369 static ReebGraph * copyReebGraph(ReebGraph *rg, int level) 00370 { 00371 ReebNode *node; 00372 ReebArc *arc; 00373 ReebGraph *cp_rg = newReebGraph(); 00374 00375 cp_rg->resolution = rg->resolution; 00376 cp_rg->length = rg->length; 00377 cp_rg->link_up = rg; 00378 cp_rg->multi_level = level; 00379 00380 /* Copy nodes */ 00381 for (node = rg->nodes.first; node; node = node->next) 00382 { 00383 ReebNode *cp_node = copyNode(cp_rg, node); 00384 cp_node->multi_level = level; 00385 } 00386 00387 /* Copy arcs */ 00388 for (arc = rg->arcs.first; arc; arc = arc->next) 00389 { 00390 copyArc(cp_rg, arc); 00391 } 00392 00393 BLI_buildAdjacencyList((BGraph*)cp_rg); 00394 00395 return cp_rg; 00396 } 00397 00398 ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node) 00399 { 00400 ReebGraph *multi_rg = rg; 00401 00402 while(multi_rg && multi_rg->multi_level != node->multi_level) 00403 { 00404 multi_rg = multi_rg->link_up; 00405 } 00406 00407 return multi_rg; 00408 } 00409 00410 static ReebEdge * copyEdge(ReebEdge *edge) 00411 { 00412 ReebEdge *newEdge = NULL; 00413 00414 newEdge = MEM_callocN(sizeof(ReebEdge), "reeb edge"); 00415 memcpy(newEdge, edge, sizeof(ReebEdge)); 00416 00417 newEdge->next = NULL; 00418 newEdge->prev = NULL; 00419 00420 return newEdge; 00421 } 00422 00423 static void printArc(ReebArc *arc) 00424 { 00425 ReebEdge *edge; 00426 ReebNode *head = (ReebNode*)arc->head; 00427 ReebNode *tail = (ReebNode*)arc->tail; 00428 printf("arc: (%i) %f -> (%i) %f\n", head->index, head->weight, tail->index, tail->weight); 00429 00430 for(edge = arc->edges.first; edge ; edge = edge->next) 00431 { 00432 printf("\tedge (%i, %i)\n", edge->v1->index, edge->v2->index); 00433 } 00434 } 00435 00436 static void flipArc(ReebArc *arc) 00437 { 00438 ReebNode *tmp; 00439 tmp = arc->head; 00440 arc->head = arc->tail; 00441 arc->tail = tmp; 00442 00443 flipArcBuckets(arc); 00444 } 00445 00446 #ifdef DEBUG_REEB_NODE 00447 static void NodeDegreeDecrement(ReebGraph *UNUSED(rg), ReebNode *node) 00448 { 00449 node->degree--; 00450 00451 // if (node->degree == 0) 00452 // { 00453 // printf("would remove node %i\n", node->index); 00454 // } 00455 } 00456 00457 static void NodeDegreeIncrement(ReebGraph *UNUSED(rg), ReebNode *node) 00458 { 00459 // if (node->degree == 0) 00460 // { 00461 // printf("first connect node %i\n", node->index); 00462 // } 00463 00464 node->degree++; 00465 } 00466 00467 #else 00468 #define NodeDegreeDecrement(rg, node) {node->degree--;} 00469 #define NodeDegreeIncrement(rg, node) {node->degree++;} 00470 #endif 00471 00472 void repositionNodes(ReebGraph *rg) 00473 { 00474 BArc *arc = NULL; 00475 BNode *node = NULL; 00476 00477 // Reset node positions 00478 for(node = rg->nodes.first; node; node = node->next) 00479 { 00480 node->p[0] = node->p[1] = node->p[2] = 0; 00481 } 00482 00483 for(arc = rg->arcs.first; arc; arc = arc->next) 00484 { 00485 if (((ReebArc*)arc)->bcount > 0) 00486 { 00487 float p[3]; 00488 00489 VECCOPY(p, ((ReebArc*)arc)->buckets[0].p); 00490 mul_v3_fl(p, 1.0f / arc->head->degree); 00491 add_v3_v3(arc->head->p, p); 00492 00493 VECCOPY(p, ((ReebArc*)arc)->buckets[((ReebArc*)arc)->bcount - 1].p); 00494 mul_v3_fl(p, 1.0f / arc->tail->degree); 00495 add_v3_v3(arc->tail->p, p); 00496 } 00497 } 00498 } 00499 00500 void verifyNodeDegree(ReebGraph *rg) 00501 { 00502 #ifdef DEBUG_REEB 00503 ReebNode *node = NULL; 00504 ReebArc *arc = NULL; 00505 00506 for(node = rg->nodes.first; node; node = node->next) 00507 { 00508 int count = 0; 00509 for(arc = rg->arcs.first; arc; arc = arc->next) 00510 { 00511 if (arc->head == node || arc->tail == node) 00512 { 00513 count++; 00514 } 00515 } 00516 if (count != node->degree) 00517 { 00518 printf("degree error in node %i: expected %i got %i\n", node->index, count, node->degree); 00519 } 00520 if (node->degree == 0) 00521 { 00522 printf("zero degree node %i with weight %f\n", node->index, node->weight); 00523 } 00524 } 00525 #endif 00526 } 00527 00528 static void verifyBucketsArc(ReebGraph *UNUSED(rg), ReebArc *arc) 00529 { 00530 ReebNode *head = (ReebNode*)arc->head; 00531 ReebNode *tail = (ReebNode*)arc->tail; 00532 00533 if (arc->bcount > 0) 00534 { 00535 int i; 00536 for(i = 0; i < arc->bcount; i++) 00537 { 00538 if (arc->buckets[i].nv == 0) 00539 { 00540 printArc(arc); 00541 printf("count error in bucket %i/%i\n", i+1, arc->bcount); 00542 } 00543 } 00544 00545 if (ceilf(head->weight) != arc->buckets[0].val) 00546 { 00547 printArc(arc); 00548 printf("alloc error in first bucket: %f should be %f \n", arc->buckets[0].val, ceil(head->weight)); 00549 } 00550 if (floorf(tail->weight) != arc->buckets[arc->bcount - 1].val) 00551 { 00552 printArc(arc); 00553 printf("alloc error in last bucket: %f should be %f \n", arc->buckets[arc->bcount - 1].val, floor(tail->weight)); 00554 } 00555 } 00556 } 00557 00558 void verifyBuckets(ReebGraph *rg) 00559 { 00560 #ifdef DEBUG_REEB 00561 ReebArc *arc = NULL; 00562 for(arc = rg->arcs.first; arc; arc = arc->next) 00563 { 00564 verifyBucketsArc(rg, arc); 00565 } 00566 #endif 00567 } 00568 00569 void verifyFaces(ReebGraph *rg) 00570 { 00571 #ifdef DEBUG_REEB 00572 int total = 0; 00573 ReebArc *arc = NULL; 00574 for(arc = rg->arcs.first; arc; arc = arc->next) 00575 { 00576 total += BLI_ghash_size(arc->faces); 00577 } 00578 00579 #endif 00580 } 00581 00582 void verifyArcs(ReebGraph *rg) 00583 { 00584 ReebArc *arc; 00585 00586 for (arc = rg->arcs.first; arc; arc = arc->next) 00587 { 00588 if (arc->head->weight > arc->tail->weight) 00589 { 00590 printf("FLIPPED ARC!\n"); 00591 } 00592 } 00593 } 00594 00595 static void verifyMultiResolutionLinks(ReebGraph *rg, int level) 00596 { 00597 #ifdef DEBUG_REEB 00598 ReebGraph *lower_rg = rg->link_up; 00599 00600 if (lower_rg) 00601 { 00602 ReebArc *arc; 00603 00604 for (arc = rg->arcs.first; arc; arc = arc->next) 00605 { 00606 if (BLI_findindex(&lower_rg->arcs, arc->link_up) == -1) 00607 { 00608 printf("missing arc %p for level %i\n", (void *)arc->link_up, level); 00609 printf("Source arc was ---\n"); 00610 printArc(arc); 00611 00612 arc->link_up = NULL; 00613 } 00614 } 00615 00616 00617 verifyMultiResolutionLinks(lower_rg, level + 1); 00618 } 00619 #endif 00620 } 00621 /***************************************** BUCKET UTILS **********************************************/ 00622 00623 static void addVertToBucket(EmbedBucket *b, float co[3]) 00624 { 00625 b->nv++; 00626 interp_v3_v3v3(b->p, b->p, co, 1.0f / b->nv); 00627 } 00628 00629 #if 0 /* UNUSED 2.5 */ 00630 static void removeVertFromBucket(EmbedBucket *b, float co[3]) 00631 { 00632 mul_v3_fl(b->p, (float)b->nv); 00633 sub_v3_v3(b->p, co); 00634 b->nv--; 00635 mul_v3_fl(b->p, 1.0f / (float)b->nv); 00636 } 00637 #endif 00638 00639 static void mergeBuckets(EmbedBucket *bDst, EmbedBucket *bSrc) 00640 { 00641 if (bDst->nv > 0 && bSrc->nv > 0) 00642 { 00643 bDst->nv += bSrc->nv; 00644 interp_v3_v3v3(bDst->p, bDst->p, bSrc->p, (float)bSrc->nv / (float)(bDst->nv)); 00645 } 00646 else if (bSrc->nv > 0) 00647 { 00648 bDst->nv = bSrc->nv; 00649 VECCOPY(bDst->p, bSrc->p); 00650 } 00651 } 00652 00653 static void mergeArcBuckets(ReebArc *aDst, ReebArc *aSrc, float start, float end) 00654 { 00655 if (aDst->bcount > 0 && aSrc->bcount > 0) 00656 { 00657 int indexDst = 0, indexSrc = 0; 00658 00659 start = MAX3(start, aDst->buckets[0].val, aSrc->buckets[0].val); 00660 00661 while(indexDst < aDst->bcount && aDst->buckets[indexDst].val < start) 00662 { 00663 indexDst++; 00664 } 00665 00666 while(indexSrc < aSrc->bcount && aSrc->buckets[indexSrc].val < start) 00667 { 00668 indexSrc++; 00669 } 00670 00671 for( ; indexDst < aDst->bcount && 00672 indexSrc < aSrc->bcount && 00673 aDst->buckets[indexDst].val <= end && 00674 aSrc->buckets[indexSrc].val <= end 00675 00676 ; indexDst++, indexSrc++) 00677 { 00678 mergeBuckets(aDst->buckets + indexDst, aSrc->buckets + indexSrc); 00679 } 00680 } 00681 } 00682 00683 void flipArcBuckets(ReebArc *arc) 00684 { 00685 int i, j; 00686 00687 for (i = 0, j = arc->bcount - 1; i < j; i++, j--) 00688 { 00689 EmbedBucket tmp; 00690 00691 tmp = arc->buckets[i]; 00692 arc->buckets[i] = arc->buckets[j]; 00693 arc->buckets[j] = tmp; 00694 } 00695 } 00696 00697 static int countArcBuckets(ReebArc *arc) 00698 { 00699 return (int)(floor(arc->tail->weight) - ceil(arc->head->weight)) + 1; 00700 } 00701 00702 static void allocArcBuckets(ReebArc *arc) 00703 { 00704 int i; 00705 float start = ceil(arc->head->weight); 00706 arc->bcount = countArcBuckets(arc); 00707 00708 if (arc->bcount > 0) 00709 { 00710 arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "embed bucket"); 00711 00712 for(i = 0; i < arc->bcount; i++) 00713 { 00714 arc->buckets[i].val = start + i; 00715 } 00716 } 00717 else 00718 { 00719 arc->buckets = NULL; 00720 } 00721 00722 } 00723 00724 static void resizeArcBuckets(ReebArc *arc) 00725 { 00726 EmbedBucket *oldBuckets = arc->buckets; 00727 int oldBCount = arc->bcount; 00728 00729 if (countArcBuckets(arc) == oldBCount) 00730 { 00731 return; 00732 } 00733 00734 allocArcBuckets(arc); 00735 00736 if (oldBCount != 0 && arc->bcount != 0) 00737 { 00738 int oldStart = (int)oldBuckets[0].val; 00739 int oldEnd = (int)oldBuckets[oldBCount - 1].val; 00740 int newStart = (int)arc->buckets[0].val; 00741 int newEnd = (int)arc->buckets[arc->bcount - 1].val; 00742 int oldOffset = 0; 00743 int newOffset = 0; 00744 int len; 00745 00746 if (oldStart < newStart) 00747 { 00748 oldOffset = newStart - oldStart; 00749 } 00750 else 00751 { 00752 newOffset = oldStart - newStart; 00753 } 00754 00755 len = MIN2(oldEnd - (oldStart + oldOffset) + 1, newEnd - (newStart - newOffset) + 1); 00756 00757 memcpy(arc->buckets + newOffset, oldBuckets + oldOffset, len * sizeof(EmbedBucket)); 00758 } 00759 00760 if (oldBuckets != NULL) 00761 { 00762 MEM_freeN(oldBuckets); 00763 } 00764 } 00765 00766 static void reweightBuckets(ReebArc *arc) 00767 { 00768 int i; 00769 float start = ceil((arc->head)->weight); 00770 00771 if (arc->bcount > 0) 00772 { 00773 for(i = 0; i < arc->bcount; i++) 00774 { 00775 arc->buckets[i].val = start + i; 00776 } 00777 } 00778 } 00779 00780 static void interpolateBuckets(ReebArc *arc, float *start_p, float *end_p, int start_index, int end_index) 00781 { 00782 int total; 00783 int j; 00784 00785 total = end_index - start_index + 2; 00786 00787 for (j = start_index; j <= end_index; j++) 00788 { 00789 EmbedBucket *empty = arc->buckets + j; 00790 empty->nv = 1; 00791 interp_v3_v3v3(empty->p, start_p, end_p, (float)(j - start_index + 1) / total); 00792 } 00793 } 00794 00795 static void fillArcEmptyBuckets(ReebArc *arc) 00796 { 00797 float *start_p, *end_p; 00798 int start_index = 0, end_index = 0; 00799 int missing = 0; 00800 int i; 00801 00802 start_p = arc->head->p; 00803 00804 for(i = 0; i < arc->bcount; i++) 00805 { 00806 EmbedBucket *bucket = arc->buckets + i; 00807 00808 if (missing) 00809 { 00810 if (bucket->nv > 0) 00811 { 00812 missing = 0; 00813 00814 end_p = bucket->p; 00815 end_index = i - 1; 00816 00817 interpolateBuckets(arc, start_p, end_p, start_index, end_index); 00818 } 00819 } 00820 else 00821 { 00822 if (bucket->nv == 0) 00823 { 00824 missing = 1; 00825 00826 if (i > 0) 00827 { 00828 start_p = arc->buckets[i - 1].p; 00829 } 00830 start_index = i; 00831 } 00832 } 00833 } 00834 00835 if (missing) 00836 { 00837 end_p = arc->tail->p; 00838 end_index = arc->bcount - 1; 00839 00840 interpolateBuckets(arc, start_p, end_p, start_index, end_index); 00841 } 00842 } 00843 00844 static void ExtendArcBuckets(ReebArc *arc) 00845 { 00846 ReebArcIterator arc_iter; 00847 BArcIterator *iter = (BArcIterator*)&arc_iter; 00848 EmbedBucket *last_bucket, *first_bucket; 00849 float *previous = NULL; 00850 float average_length = 0, length; 00851 int padding_head = 0, padding_tail = 0; 00852 00853 if (arc->bcount == 0) 00854 { 00855 return; /* failsafe, shouldn't happen */ 00856 } 00857 00858 initArcIterator(iter, arc, arc->head); 00859 IT_next(iter); 00860 previous = iter->p; 00861 00862 for ( IT_next(iter); 00863 IT_stopped(iter) == 0; 00864 previous = iter->p, IT_next(iter) 00865 ) 00866 { 00867 average_length += len_v3v3(previous, iter->p); 00868 } 00869 average_length /= (arc->bcount - 1); 00870 00871 first_bucket = arc->buckets; 00872 last_bucket = arc->buckets + (arc->bcount - 1); 00873 00874 length = len_v3v3(first_bucket->p, arc->head->p); 00875 if (length > 2 * average_length) 00876 { 00877 padding_head = (int)floor(length / average_length); 00878 } 00879 00880 length = len_v3v3(last_bucket->p, arc->tail->p); 00881 if (length > 2 * average_length) 00882 { 00883 padding_tail = (int)floor(length / average_length); 00884 } 00885 00886 if (padding_head + padding_tail > 0) 00887 { 00888 EmbedBucket *old_buckets = arc->buckets; 00889 00890 arc->buckets = MEM_callocN(sizeof(EmbedBucket) * (padding_head + arc->bcount + padding_tail), "embed bucket"); 00891 memcpy(arc->buckets + padding_head, old_buckets, arc->bcount * sizeof(EmbedBucket)); 00892 00893 arc->bcount = padding_head + arc->bcount + padding_tail; 00894 00895 MEM_freeN(old_buckets); 00896 } 00897 00898 if (padding_head > 0) 00899 { 00900 interpolateBuckets(arc, arc->head->p, first_bucket->p, 0, padding_head); 00901 } 00902 00903 if (padding_tail > 0) 00904 { 00905 interpolateBuckets(arc, last_bucket->p, arc->tail->p, arc->bcount - padding_tail, arc->bcount - 1); 00906 } 00907 } 00908 00909 /* CALL THIS ONLY AFTER FILTERING, SINCE IT MESSES UP WEIGHT DISTRIBUTION */ 00910 static void extendGraphBuckets(ReebGraph *rg) 00911 { 00912 ReebArc *arc; 00913 00914 for (arc = rg->arcs.first; arc; arc = arc->next) 00915 { 00916 ExtendArcBuckets(arc); 00917 } 00918 } 00919 00920 /**************************************** LENGTH CALCULATIONS ****************************************/ 00921 00922 static void calculateArcLength(ReebArc *arc) 00923 { 00924 ReebArcIterator arc_iter; 00925 BArcIterator *iter = (BArcIterator*)&arc_iter; 00926 float *vec0, *vec1; 00927 00928 arc->length = 0; 00929 00930 initArcIterator(iter, arc, arc->head); 00931 00932 vec0 = arc->head->p; 00933 vec1 = arc->head->p; /* in case there's no embedding */ 00934 00935 while (IT_next(iter)) 00936 { 00937 vec1 = iter->p; 00938 00939 arc->length += len_v3v3(vec0, vec1); 00940 00941 vec0 = vec1; 00942 } 00943 00944 arc->length += len_v3v3(arc->tail->p, vec1); 00945 } 00946 00947 static void calculateGraphLength(ReebGraph *rg) 00948 { 00949 ReebArc *arc; 00950 00951 for (arc = rg->arcs.first; arc; arc = arc->next) 00952 { 00953 calculateArcLength(arc); 00954 } 00955 } 00956 00957 /**************************************** SYMMETRY HANDLING ******************************************/ 00958 00959 void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count) 00960 { 00961 ReebNode *node = (ReebNode*)root_node; 00962 float axis[3]; 00963 int i; 00964 00965 VECCOPY(axis, root_node->symmetry_axis); 00966 00967 /* first pass, merge incrementally */ 00968 for (i = 0; i < count - 1; i++) 00969 { 00970 ReebNode *node1, *node2; 00971 ReebArc *arc1, *arc2; 00972 float tangent[3]; 00973 float normal[3]; 00974 int j = i + 1; 00975 00976 add_v3_v3v3(tangent, ring[i].n, ring[j].n); 00977 cross_v3_v3v3(normal, tangent, axis); 00978 00979 node1 = (ReebNode*)BLI_otherNode(ring[i].arc, root_node); 00980 node2 = (ReebNode*)BLI_otherNode(ring[j].arc, root_node); 00981 00982 arc1 = (ReebArc*)ring[i].arc; 00983 arc2 = (ReebArc*)ring[j].arc; 00984 00985 /* mirror first node and mix with the second */ 00986 BLI_mirrorAlongAxis(node1->p, root_node->p, normal); 00987 interp_v3_v3v3(node2->p, node2->p, node1->p, 1.0f / (j + 1)); 00988 00989 /* Merge buckets 00990 * there shouldn't be any null arcs here, but just to be safe 00991 * */ 00992 if (arc1->bcount > 0 && arc2->bcount > 0) 00993 { 00994 ReebArcIterator arc_iter1, arc_iter2; 00995 BArcIterator *iter1 = (BArcIterator*)&arc_iter1; 00996 BArcIterator *iter2 = (BArcIterator*)&arc_iter2; 00997 EmbedBucket *bucket1 = NULL, *bucket2 = NULL; 00998 00999 initArcIterator(iter1, arc1, (ReebNode*)root_node); 01000 initArcIterator(iter2, arc2, (ReebNode*)root_node); 01001 01002 bucket1 = IT_next(iter1); 01003 bucket2 = IT_next(iter2); 01004 01005 /* Make sure they both start at the same value */ 01006 while(bucket1 && bucket2 && bucket1->val < bucket2->val) 01007 { 01008 bucket1 = IT_next(iter1); 01009 } 01010 01011 while(bucket1 && bucket2 && bucket2->val < bucket1->val) 01012 { 01013 bucket2 = IT_next(iter2); 01014 } 01015 01016 01017 for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) 01018 { 01019 bucket2->nv += bucket1->nv; /* add counts */ 01020 01021 /* mirror on axis */ 01022 BLI_mirrorAlongAxis(bucket1->p, root_node->p, normal); 01023 /* add bucket2 in bucket1 */ 01024 interp_v3_v3v3(bucket2->p, bucket2->p, bucket1->p, (float)bucket1->nv / (float)(bucket2->nv)); 01025 } 01026 } 01027 } 01028 01029 /* second pass, mirror back on previous arcs */ 01030 for (i = count - 1; i > 0; i--) 01031 { 01032 ReebNode *node1, *node2; 01033 ReebArc *arc1, *arc2; 01034 float tangent[3]; 01035 float normal[3]; 01036 int j = i - 1; 01037 01038 add_v3_v3v3(tangent, ring[i].n, ring[j].n); 01039 cross_v3_v3v3(normal, tangent, axis); 01040 01041 node1 = (ReebNode*)BLI_otherNode(ring[i].arc, root_node); 01042 node2 = (ReebNode*)BLI_otherNode(ring[j].arc, root_node); 01043 01044 arc1 = (ReebArc*)ring[i].arc; 01045 arc2 = (ReebArc*)ring[j].arc; 01046 01047 /* copy first node than mirror */ 01048 VECCOPY(node2->p, node1->p); 01049 BLI_mirrorAlongAxis(node2->p, root_node->p, normal); 01050 01051 /* Copy buckets 01052 * there shouldn't be any null arcs here, but just to be safe 01053 * */ 01054 if (arc1->bcount > 0 && arc2->bcount > 0) 01055 { 01056 ReebArcIterator arc_iter1, arc_iter2; 01057 BArcIterator *iter1 = (BArcIterator*)&arc_iter1; 01058 BArcIterator *iter2 = (BArcIterator*)&arc_iter2; 01059 EmbedBucket *bucket1 = NULL, *bucket2 = NULL; 01060 01061 initArcIterator(iter1, arc1, node); 01062 initArcIterator(iter2, arc2, node); 01063 01064 bucket1 = IT_next(iter1); 01065 bucket2 = IT_next(iter2); 01066 01067 /* Make sure they both start at the same value */ 01068 while(bucket1 && bucket1->val < bucket2->val) 01069 { 01070 bucket1 = IT_next(iter1); 01071 } 01072 01073 while(bucket2 && bucket2->val < bucket1->val) 01074 { 01075 bucket2 = IT_next(iter2); 01076 } 01077 01078 01079 for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) 01080 { 01081 /* copy and mirror back to bucket2 */ 01082 bucket2->nv = bucket1->nv; 01083 VECCOPY(bucket2->p, bucket1->p); 01084 BLI_mirrorAlongAxis(bucket2->p, node->p, normal); 01085 } 01086 } 01087 } 01088 } 01089 01090 void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2) 01091 { 01092 ReebArc *arc1, *arc2; 01093 float nor[3], p[3]; 01094 01095 arc1 = (ReebArc*)barc1; 01096 arc2 = (ReebArc*)barc2; 01097 01098 VECCOPY(nor, root_node->symmetry_axis); 01099 01100 /* mirror node2 along axis */ 01101 VECCOPY(p, node2->p); 01102 BLI_mirrorAlongAxis(p, root_node->p, nor); 01103 01104 /* average with node1 */ 01105 add_v3_v3(node1->p, p); 01106 mul_v3_fl(node1->p, 0.5f); 01107 01108 /* mirror back on node2 */ 01109 VECCOPY(node2->p, node1->p); 01110 BLI_mirrorAlongAxis(node2->p, root_node->p, nor); 01111 01112 /* Merge buckets 01113 * there shouldn't be any null arcs here, but just to be safe 01114 * */ 01115 if (arc1->bcount > 0 && arc2->bcount > 0) 01116 { 01117 ReebArcIterator arc_iter1, arc_iter2; 01118 BArcIterator *iter1 = (BArcIterator*)&arc_iter1; 01119 BArcIterator *iter2 = (BArcIterator*)&arc_iter2; 01120 EmbedBucket *bucket1 = NULL, *bucket2 = NULL; 01121 01122 initArcIterator(iter1, arc1, (ReebNode*)root_node); 01123 initArcIterator(iter2, arc2, (ReebNode*)root_node); 01124 01125 bucket1 = IT_next(iter1); 01126 bucket2 = IT_next(iter2); 01127 01128 /* Make sure they both start at the same value */ 01129 while(bucket1 && bucket1->val < bucket2->val) 01130 { 01131 bucket1 = IT_next(iter1); 01132 } 01133 01134 while(bucket2 && bucket2->val < bucket1->val) 01135 { 01136 bucket2 = IT_next(iter2); 01137 } 01138 01139 01140 for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) 01141 { 01142 bucket1->nv += bucket2->nv; /* add counts */ 01143 01144 /* mirror on axis */ 01145 BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor); 01146 /* add bucket2 in bucket1 */ 01147 interp_v3_v3v3(bucket1->p, bucket1->p, bucket2->p, (float)bucket2->nv / (float)(bucket1->nv)); 01148 01149 /* copy and mirror back to bucket2 */ 01150 bucket2->nv = bucket1->nv; 01151 VECCOPY(bucket2->p, bucket1->p); 01152 BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor); 01153 } 01154 } 01155 } 01156 01157 /************************************** ADJACENCY LIST *************************************************/ 01158 01159 01160 /****************************************** SMOOTHING **************************************************/ 01161 01162 void postprocessGraph(ReebGraph *rg, char mode) 01163 { 01164 ReebArc *arc; 01165 float fac1 = 0, fac2 = 1, fac3 = 0; 01166 01167 switch(mode) 01168 { 01169 case SKGEN_AVERAGE: 01170 fac1 = fac2 = fac3 = 1.0f / 3.0f; 01171 break; 01172 case SKGEN_SMOOTH: 01173 fac1 = fac3 = 0.25f; 01174 fac2 = 0.5f; 01175 break; 01176 case SKGEN_SHARPEN: 01177 fac1 = fac2 = -0.25f; 01178 fac2 = 1.5f; 01179 break; 01180 default: 01181 // XXX 01182 // error("Unknown post processing mode"); 01183 return; 01184 } 01185 01186 for(arc = rg->arcs.first; arc; arc = arc->next) 01187 { 01188 EmbedBucket *buckets = arc->buckets; 01189 int bcount = arc->bcount; 01190 int index; 01191 01192 for(index = 1; index < bcount - 1; index++) 01193 { 01194 interp_v3_v3v3(buckets[index].p, buckets[index].p, buckets[index - 1].p, fac1 / (fac1 + fac2)); 01195 interp_v3_v3v3(buckets[index].p, buckets[index].p, buckets[index + 1].p, fac3 / (fac1 + fac2 + fac3)); 01196 } 01197 } 01198 } 01199 01200 /********************************************SORTING****************************************************/ 01201 01202 static int compareNodesWeight(void *vnode1, void *vnode2) 01203 { 01204 ReebNode *node1 = (ReebNode*)vnode1; 01205 ReebNode *node2 = (ReebNode*)vnode2; 01206 01207 if (node1->weight < node2->weight) 01208 { 01209 return -1; 01210 } 01211 if (node1->weight > node2->weight) 01212 { 01213 return 1; 01214 } 01215 else 01216 { 01217 return 0; 01218 } 01219 } 01220 01221 void sortNodes(ReebGraph *rg) 01222 { 01223 BLI_sortlist(&rg->nodes, compareNodesWeight); 01224 } 01225 01226 static int compareArcsWeight(void *varc1, void *varc2) 01227 { 01228 ReebArc *arc1 = (ReebArc*)varc1; 01229 ReebArc *arc2 = (ReebArc*)varc2; 01230 ReebNode *node1 = (ReebNode*)arc1->head; 01231 ReebNode *node2 = (ReebNode*)arc2->head; 01232 01233 if (node1->weight < node2->weight) 01234 { 01235 return -1; 01236 } 01237 if (node1->weight > node2->weight) 01238 { 01239 return 1; 01240 } 01241 else 01242 { 01243 return 0; 01244 } 01245 } 01246 01247 void sortArcs(ReebGraph *rg) 01248 { 01249 BLI_sortlist(&rg->arcs, compareArcsWeight); 01250 } 01251 /******************************************* JOINING ***************************************************/ 01252 01253 static void reweightArc(ReebGraph *rg, ReebArc *arc, ReebNode *start_node, float start_weight) 01254 { 01255 ReebNode *node; 01256 float old_weight; 01257 float end_weight = start_weight + ABS(arc->tail->weight - arc->head->weight); 01258 int i; 01259 01260 node = (ReebNode*)BLI_otherNode((BArc*)arc, (BNode*)start_node); 01261 01262 /* prevent backtracking */ 01263 if (node->flag == 1) 01264 { 01265 return; 01266 } 01267 01268 if (arc->tail == start_node) 01269 { 01270 flipArc(arc); 01271 } 01272 01273 start_node->flag = 1; 01274 01275 for (i = 0; i < node->degree; i++) 01276 { 01277 ReebArc *next_arc = node->arcs[i]; 01278 01279 reweightArc(rg, next_arc, node, end_weight); 01280 } 01281 01282 /* update only if needed */ 01283 if (arc->head->weight != start_weight || arc->tail->weight != end_weight) 01284 { 01285 old_weight = arc->head->weight; /* backup head weight, other arcs need it intact, it will be fixed by the source arc */ 01286 01287 arc->head->weight = start_weight; 01288 arc->tail->weight = end_weight; 01289 01290 reweightBuckets(arc); 01291 resizeArcBuckets(arc); 01292 fillArcEmptyBuckets(arc); 01293 01294 arc->head->weight = old_weight; 01295 } 01296 } 01297 01298 static void reweightSubgraph(ReebGraph *rg, ReebNode *start_node, float start_weight) 01299 { 01300 int i; 01301 01302 BLI_flagNodes((BGraph*)rg, 0); 01303 01304 for (i = 0; i < start_node->degree; i++) 01305 { 01306 ReebArc *next_arc = start_node->arcs[i]; 01307 01308 reweightArc(rg, next_arc, start_node, start_weight); 01309 } 01310 start_node->weight = start_weight; 01311 } 01312 01313 static int joinSubgraphsEnds(ReebGraph *rg, float threshold, int nb_subgraphs) 01314 { 01315 int joined = 0; 01316 int subgraph; 01317 01318 for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++) 01319 { 01320 ReebNode *start_node, *end_node; 01321 ReebNode *min_node_start = NULL, *min_node_end = NULL; 01322 float min_distance = FLT_MAX; 01323 01324 for (start_node = rg->nodes.first; start_node; start_node = start_node->next) 01325 { 01326 if (start_node->subgraph_index == subgraph && start_node->degree == 1) 01327 { 01328 01329 for (end_node = rg->nodes.first; end_node; end_node = end_node->next) 01330 { 01331 if (end_node->subgraph_index != subgraph) 01332 { 01333 float distance = len_v3v3(start_node->p, end_node->p); 01334 01335 if (distance < threshold && distance < min_distance) 01336 { 01337 min_distance = distance; 01338 min_node_end = end_node; 01339 min_node_start = start_node; 01340 } 01341 } 01342 } 01343 } 01344 } 01345 01346 end_node = min_node_end; 01347 start_node = min_node_start; 01348 01349 if (end_node && start_node) 01350 { 01351 ReebArc *start_arc /* , *end_arc */ /* UNUSED */; 01352 int merging = 0; 01353 01354 start_arc = start_node->arcs[0]; 01355 /* end_arc = end_node->arcs[0]; */ /* UNUSED */ 01356 01357 if (start_arc->tail == start_node) 01358 { 01359 reweightSubgraph(rg, end_node, start_node->weight); 01360 01361 start_arc->tail = end_node; 01362 01363 merging = 1; 01364 } 01365 else if (start_arc->head == start_node) 01366 { 01367 reweightSubgraph(rg, start_node, end_node->weight); 01368 01369 start_arc->head = end_node; 01370 01371 merging = 2; 01372 } 01373 01374 if (merging) 01375 { 01376 BLI_ReflagSubgraph((BGraph*)rg, end_node->flag, subgraph); 01377 01378 resizeArcBuckets(start_arc); 01379 fillArcEmptyBuckets(start_arc); 01380 01381 NodeDegreeIncrement(rg, end_node); 01382 BLI_rebuildAdjacencyListForNode((BGraph*)rg, (BNode*)end_node); 01383 01384 BLI_removeNode((BGraph*)rg, (BNode*)start_node); 01385 } 01386 01387 joined = 1; 01388 } 01389 } 01390 01391 return joined; 01392 } 01393 01394 /* Reweight graph from smallest node, fix fliped arcs */ 01395 static void fixSubgraphsOrientation(ReebGraph *rg, int nb_subgraphs) 01396 { 01397 int subgraph; 01398 01399 for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++) 01400 { 01401 ReebNode *node; 01402 ReebNode *start_node = NULL; 01403 01404 for (node = rg->nodes.first; node; node = node->next) 01405 { 01406 if (node->subgraph_index == subgraph) 01407 { 01408 if (start_node == NULL || node->weight < start_node->weight) 01409 { 01410 start_node = node; 01411 } 01412 } 01413 } 01414 01415 if (start_node) 01416 { 01417 reweightSubgraph(rg, start_node, start_node->weight); 01418 } 01419 } 01420 } 01421 01422 static int joinSubgraphs(ReebGraph *rg, float threshold) 01423 { 01424 int nb_subgraphs; 01425 int joined = 0; 01426 01427 BLI_buildAdjacencyList((BGraph*)rg); 01428 01429 if (BLI_isGraphCyclic((BGraph*)rg)) 01430 { 01431 /* don't deal with cyclic graphs YET */ 01432 return 0; 01433 } 01434 01435 /* sort nodes before flagging subgraphs to make sure root node is subgraph 0 */ 01436 sortNodes(rg); 01437 01438 nb_subgraphs = BLI_FlagSubgraphs((BGraph*)rg); 01439 01440 /* Harmonic function can create flipped arcs, take the occasion to fix them */ 01441 // XXX 01442 // if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC) 01443 // { 01444 fixSubgraphsOrientation(rg, nb_subgraphs); 01445 // } 01446 01447 if (nb_subgraphs > 1) 01448 { 01449 joined |= joinSubgraphsEnds(rg, threshold, nb_subgraphs); 01450 01451 if (joined) 01452 { 01453 removeNormalNodes(rg); 01454 BLI_buildAdjacencyList((BGraph*)rg); 01455 } 01456 } 01457 01458 return joined; 01459 } 01460 01461 /****************************************** FILTERING **************************************************/ 01462 01463 static float lengthArc(ReebArc *arc) 01464 { 01465 #if 0 01466 ReebNode *head = (ReebNode*)arc->head; 01467 ReebNode *tail = (ReebNode*)arc->tail; 01468 01469 return tail->weight - head->weight; 01470 #else 01471 return arc->length; 01472 #endif 01473 } 01474 01475 static int compareArcs(void *varc1, void *varc2) 01476 { 01477 ReebArc *arc1 = (ReebArc*)varc1; 01478 ReebArc *arc2 = (ReebArc*)varc2; 01479 float len1 = lengthArc(arc1); 01480 float len2 = lengthArc(arc2); 01481 01482 if (len1 < len2) 01483 { 01484 return -1; 01485 } 01486 if (len1 > len2) 01487 { 01488 return 1; 01489 } 01490 else 01491 { 01492 return 0; 01493 } 01494 } 01495 01496 static void filterArc(ReebGraph *rg, ReebNode *newNode, ReebNode *removedNode, ReebArc * srcArc, int merging) 01497 { 01498 ReebArc *arc = NULL, *nextArc = NULL; 01499 01500 if (merging) 01501 { 01502 /* first pass, merge buckets for arcs that spawned the two nodes into the source arc*/ 01503 for(arc = rg->arcs.first; arc; arc = arc->next) 01504 { 01505 if (arc->head == srcArc->head && arc->tail == srcArc->tail && arc != srcArc) 01506 { 01507 ReebNode *head = srcArc->head; 01508 ReebNode *tail = srcArc->tail; 01509 mergeArcBuckets(srcArc, arc, head->weight, tail->weight); 01510 } 01511 } 01512 } 01513 01514 /* second pass, replace removedNode by newNode, remove arcs that are collapsed in a loop */ 01515 arc = rg->arcs.first; 01516 while(arc) 01517 { 01518 nextArc = arc->next; 01519 01520 if (arc->head == removedNode || arc->tail == removedNode) 01521 { 01522 if (arc->head == removedNode) 01523 { 01524 arc->head = newNode; 01525 } 01526 else 01527 { 01528 arc->tail = newNode; 01529 } 01530 01531 // Remove looped arcs 01532 if (arc->head == arc->tail) 01533 { 01534 // v1 or v2 was already newNode, since we're removing an arc, decrement degree 01535 NodeDegreeDecrement(rg, newNode); 01536 01537 // If it's srcArc, it'll be removed later, so keep it for now 01538 if (arc != srcArc) 01539 { 01540 BLI_remlink(&rg->arcs, arc); 01541 REEB_freeArc((BArc*)arc); 01542 } 01543 } 01544 else 01545 { 01546 /* flip arcs that flipped, can happen on diamond shapes, mostly on null arcs */ 01547 if (arc->head->weight > arc->tail->weight) 01548 { 01549 flipArc(arc); 01550 } 01551 //newNode->degree++; // incrementing degree since we're adding an arc 01552 NodeDegreeIncrement(rg, newNode); 01553 mergeArcFaces(rg, arc, srcArc); 01554 01555 if (merging) 01556 { 01557 ReebNode *head = arc->head; 01558 ReebNode *tail = arc->tail; 01559 01560 // resize bucket list 01561 resizeArcBuckets(arc); 01562 mergeArcBuckets(arc, srcArc, head->weight, tail->weight); 01563 01564 /* update length */ 01565 arc->length += srcArc->length; 01566 } 01567 } 01568 } 01569 01570 arc = nextArc; 01571 } 01572 } 01573 01574 void filterNullReebGraph(ReebGraph *rg) 01575 { 01576 ReebArc *arc = NULL, *nextArc = NULL; 01577 01578 arc = rg->arcs.first; 01579 while(arc) 01580 { 01581 nextArc = arc->next; 01582 // Only collapse arcs too short to have any embed bucket 01583 if (arc->bcount == 0) 01584 { 01585 ReebNode *newNode = (ReebNode*)arc->head; 01586 ReebNode *removedNode = (ReebNode*)arc->tail; 01587 float blend; 01588 01589 blend = (float)newNode->degree / (float)(newNode->degree + removedNode->degree); // blending factors 01590 01591 interp_v3_v3v3(newNode->p, removedNode->p, newNode->p, blend); 01592 01593 filterArc(rg, newNode, removedNode, arc, 0); 01594 01595 // Reset nextArc, it might have changed 01596 nextArc = arc->next; 01597 01598 BLI_remlink(&rg->arcs, arc); 01599 REEB_freeArc((BArc*)arc); 01600 01601 BLI_removeNode((BGraph*)rg, (BNode*)removedNode); 01602 } 01603 01604 arc = nextArc; 01605 } 01606 } 01607 01608 static int filterInternalExternalReebGraph(ReebGraph *rg, float threshold_internal, float threshold_external) 01609 { 01610 ReebArc *arc = NULL, *nextArc = NULL; 01611 int value = 0; 01612 01613 BLI_sortlist(&rg->arcs, compareArcs); 01614 01615 for (arc = rg->arcs.first; arc; arc = nextArc) 01616 { 01617 nextArc = arc->next; 01618 01619 // Only collapse non-terminal arcs that are shorter than threshold 01620 if (threshold_internal > 0 && arc->head->degree > 1 && arc->tail->degree > 1 && (lengthArc(arc) < threshold_internal)) 01621 { 01622 ReebNode *newNode = NULL; 01623 ReebNode *removedNode = NULL; 01624 01625 /* Always remove lower node, so arcs don't flip */ 01626 newNode = arc->head; 01627 removedNode = arc->tail; 01628 01629 filterArc(rg, newNode, removedNode, arc, 1); 01630 01631 // Reset nextArc, it might have changed 01632 nextArc = arc->next; 01633 01634 BLI_remlink(&rg->arcs, arc); 01635 REEB_freeArc((BArc*)arc); 01636 01637 BLI_removeNode((BGraph*)rg, (BNode*)removedNode); 01638 value = 1; 01639 } 01640 01641 // Only collapse terminal arcs that are shorter than threshold 01642 else if (threshold_external > 0 && (arc->head->degree == 1 || arc->tail->degree == 1) && (lengthArc(arc) < threshold_external)) 01643 { 01644 ReebNode *terminalNode = NULL; 01645 ReebNode *middleNode = NULL; 01646 ReebNode *removedNode = NULL; 01647 01648 // Assign terminal and middle nodes 01649 if (arc->head->degree == 1) 01650 { 01651 terminalNode = arc->head; 01652 middleNode = arc->tail; 01653 } 01654 else 01655 { 01656 terminalNode = arc->tail; 01657 middleNode = arc->head; 01658 } 01659 01660 if (middleNode->degree == 2 && middleNode != rg->nodes.first) 01661 { 01662 #if 1 01663 // If middle node is a normal node, it will be removed later 01664 // Only if middle node is not the root node 01665 /* USE THIS IF YOU WANT TO PROLONG ARCS TO THEIR TERMINAL NODES 01666 * FOR HANDS, THIS IS NOT THE BEST RESULT 01667 * */ 01668 continue; 01669 #else 01670 removedNode = terminalNode; 01671 01672 // removing arc, so we need to decrease the degree of the remaining node 01673 NodeDegreeDecrement(rg, middleNode); 01674 #endif 01675 } 01676 // Otherwise, just plain remove of the arc 01677 else 01678 { 01679 removedNode = terminalNode; 01680 01681 // removing arc, so we need to decrease the degree of the remaining node 01682 NodeDegreeDecrement(rg, middleNode); 01683 } 01684 01685 // Reset nextArc, it might have changed 01686 nextArc = arc->next; 01687 01688 BLI_remlink(&rg->arcs, arc); 01689 REEB_freeArc((BArc*)arc); 01690 01691 BLI_removeNode((BGraph*)rg, (BNode*)removedNode); 01692 value = 1; 01693 } 01694 } 01695 01696 return value; 01697 } 01698 01699 static int filterCyclesReebGraph(ReebGraph *rg, float UNUSED(distance_threshold)) 01700 { 01701 ReebArc *arc1, *arc2; 01702 ReebArc *next2; 01703 int filtered = 0; 01704 01705 for (arc1 = rg->arcs.first; arc1; arc1 = arc1->next) 01706 { 01707 for (arc2 = arc1->next; arc2; arc2 = next2) 01708 { 01709 next2 = arc2->next; 01710 if (arc1 != arc2 && arc1->head == arc2->head && arc1->tail == arc2->tail) 01711 { 01712 mergeArcEdges(rg, arc1, arc2, MERGE_APPEND); 01713 mergeArcFaces(rg, arc1, arc2); 01714 mergeArcBuckets(arc1, arc2, arc1->head->weight, arc1->tail->weight); 01715 01716 NodeDegreeDecrement(rg, arc1->head); 01717 NodeDegreeDecrement(rg, arc1->tail); 01718 01719 BLI_remlink(&rg->arcs, arc2); 01720 REEB_freeArc((BArc*)arc2); 01721 01722 filtered = 1; 01723 } 01724 } 01725 } 01726 01727 return filtered; 01728 } 01729 01730 int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold)) 01731 { 01732 int value = 0; 01733 #if 0 //XXX 01734 ReebArc *arc = NULL, *nextArc = NULL; 01735 01736 BLI_sortlist(&rg->arcs, compareArcs); 01737 01738 #ifdef DEBUG_REEB 01739 { 01740 EditFace *efa; 01741 for(efa=G.editMesh->faces.first; efa; efa=efa->next) { 01742 efa->tmp.fp = -1; 01743 } 01744 } 01745 #endif 01746 01747 arc = rg->arcs.first; 01748 while(arc) 01749 { 01750 nextArc = arc->next; 01751 01752 /* need correct normals and center */ 01753 recalc_editnormals(); 01754 01755 // Only test terminal arcs 01756 if (arc->head->degree == 1 || arc->tail->degree == 1) 01757 { 01758 GHashIterator ghi; 01759 int merging = 0; 01760 int total = BLI_ghash_size(arc->faces); 01761 float avg_angle = 0; 01762 float avg_vec[3] = {0,0,0}; 01763 01764 for(BLI_ghashIterator_init(&ghi, arc->faces); 01765 !BLI_ghashIterator_isDone(&ghi); 01766 BLI_ghashIterator_step(&ghi)) 01767 { 01768 EditFace *efa = BLI_ghashIterator_getValue(&ghi); 01769 01770 #if 0 01771 ReebArcIterator arc_iter; 01772 BArcIterator *iter = (BArcIterator*)&arc_iter; 01773 EmbedBucket *bucket = NULL; 01774 EmbedBucket *previous = NULL; 01775 float min_distance = -1; 01776 float angle = 0; 01777 01778 initArcIterator(iter, arc, arc->head); 01779 01780 bucket = nextBucket(iter); 01781 01782 while (bucket != NULL) 01783 { 01784 float *vec0 = NULL; 01785 float *vec1 = bucket->p; 01786 float midpoint[3], tangent[3]; 01787 float distance; 01788 01789 /* first bucket. Previous is head */ 01790 if (previous == NULL) 01791 { 01792 vec0 = arc->head->p; 01793 } 01794 /* Previous is a valid bucket */ 01795 else 01796 { 01797 vec0 = previous->p; 01798 } 01799 01800 VECCOPY(midpoint, vec1); 01801 01802 distance = len_v3v3(midpoint, efa->cent); 01803 01804 if (min_distance == -1 || distance < min_distance) 01805 { 01806 min_distance = distance; 01807 01808 sub_v3_v3v3(tangent, vec1, vec0); 01809 normalize_v3(tangent); 01810 01811 angle = dot_v3v3(tangent, efa->n); 01812 } 01813 01814 previous = bucket; 01815 bucket = nextBucket(iter); 01816 } 01817 01818 avg_angle += saacos(fabs(angle)); 01819 #ifdef DEBUG_REEB 01820 efa->tmp.fp = saacos(fabs(angle)); 01821 #endif 01822 #else 01823 add_v3_v3(avg_vec, efa->n); 01824 #endif 01825 } 01826 01827 01828 #if 0 01829 avg_angle /= total; 01830 #else 01831 mul_v3_fl(avg_vec, 1.0 / total); 01832 avg_angle = dot_v3v3(avg_vec, avg_vec); 01833 #endif 01834 01835 arc->angle = avg_angle; 01836 01837 if (avg_angle > threshold) 01838 merging = 1; 01839 01840 if (merging) 01841 { 01842 ReebNode *terminalNode = NULL; 01843 ReebNode *middleNode = NULL; 01844 ReebNode *newNode = NULL; 01845 ReebNode *removedNode = NULL; 01846 int merging = 0; 01847 01848 // Assign terminal and middle nodes 01849 if (arc->head->degree == 1) 01850 { 01851 terminalNode = arc->head; 01852 middleNode = arc->tail; 01853 } 01854 else 01855 { 01856 terminalNode = arc->tail; 01857 middleNode = arc->head; 01858 } 01859 01860 // If middle node is a normal node, merge to terminal node 01861 if (middleNode->degree == 2) 01862 { 01863 merging = 1; 01864 newNode = terminalNode; 01865 removedNode = middleNode; 01866 } 01867 // Otherwise, just plain remove of the arc 01868 else 01869 { 01870 merging = 0; 01871 newNode = middleNode; 01872 removedNode = terminalNode; 01873 } 01874 01875 // Merging arc 01876 if (merging) 01877 { 01878 filterArc(rg, newNode, removedNode, arc, 1); 01879 } 01880 else 01881 { 01882 // removing arc, so we need to decrease the degree of the remaining node 01883 //newNode->degree--; 01884 NodeDegreeDecrement(rg, newNode); 01885 } 01886 01887 // Reset nextArc, it might have changed 01888 nextArc = arc->next; 01889 01890 BLI_remlink(&rg->arcs, arc); 01891 REEB_freeArc((BArc*)arc); 01892 01893 BLI_freelinkN(&rg->nodes, removedNode); 01894 value = 1; 01895 } 01896 } 01897 01898 arc = nextArc; 01899 } 01900 01901 #endif 01902 01903 return value; 01904 } 01905 01906 static void filterGraph(ReebGraph *rg, short options, float threshold_internal, float threshold_external) 01907 { 01908 int done = 1; 01909 01910 calculateGraphLength(rg); 01911 01912 if ((options & SKGEN_FILTER_EXTERNAL) == 0) 01913 { 01914 threshold_external = 0; 01915 } 01916 01917 if ((options & SKGEN_FILTER_INTERNAL) == 0) 01918 { 01919 threshold_internal = 0; 01920 } 01921 01922 if (threshold_internal > 0 || threshold_external > 0) 01923 { 01924 /* filter until there's nothing more to do */ 01925 while (done == 1) 01926 { 01927 done = 0; /* no work done yet */ 01928 01929 done = filterInternalExternalReebGraph(rg, threshold_internal, threshold_external); 01930 } 01931 } 01932 01933 if (options & SKGEN_FILTER_SMART) 01934 { 01935 filterSmartReebGraph(rg, 0.5); 01936 filterCyclesReebGraph(rg, 0.5); 01937 } 01938 01939 repositionNodes(rg); 01940 01941 /* Filtering might have created degree 2 nodes, so remove them */ 01942 removeNormalNodes(rg); 01943 } 01944 01945 static void finalizeGraph(ReebGraph *rg, char passes, char method) 01946 { 01947 int i; 01948 01949 BLI_buildAdjacencyList((BGraph*)rg); 01950 01951 sortNodes(rg); 01952 01953 sortArcs(rg); 01954 01955 for(i = 0; i < passes; i++) 01956 { 01957 postprocessGraph(rg, method); 01958 } 01959 01960 extendGraphBuckets(rg); 01961 } 01962 01963 /************************************** WEIGHT SPREADING ***********************************************/ 01964 01965 static int compareVerts( const void* a, const void* b ) 01966 { 01967 EditVert *va = *(EditVert**)a; 01968 EditVert *vb = *(EditVert**)b; 01969 int value = 0; 01970 01971 if (weightData(va) < weightData(vb)) 01972 { 01973 value = -1; 01974 } 01975 else if (weightData(va) > weightData(vb)) 01976 { 01977 value = 1; 01978 } 01979 01980 return value; 01981 } 01982 01983 static void spreadWeight(EditMesh *em) 01984 { 01985 EditVert **verts, *eve; 01986 float lastWeight = 0.0f; 01987 int totvert = BLI_countlist(&em->verts); 01988 int i; 01989 int work_needed = 1; 01990 01991 verts = MEM_callocN(sizeof(EditVert*) * totvert, "verts array"); 01992 01993 for(eve = em->verts.first, i = 0; eve; eve = eve->next, i++) 01994 { 01995 verts[i] = eve; 01996 } 01997 01998 while(work_needed == 1) 01999 { 02000 work_needed = 0; 02001 qsort(verts, totvert, sizeof(EditVert*), compareVerts); 02002 02003 for(i = 0; i < totvert; i++) 02004 { 02005 eve = verts[i]; 02006 02007 if (i == 0 || (weightData(eve) - lastWeight) > FLT_EPSILON) 02008 { 02009 lastWeight = weightData(eve); 02010 } 02011 else 02012 { 02013 work_needed = 1; 02014 weightSetData(eve, lastWeight + FLT_EPSILON * 2); 02015 lastWeight = weightData(eve); 02016 } 02017 } 02018 } 02019 02020 MEM_freeN(verts); 02021 } 02022 02023 /******************************************** EXPORT ***************************************************/ 02024 02025 static void exportNode(FILE *f, const char *text, ReebNode *node) 02026 { 02027 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]); 02028 } 02029 02030 void REEB_exportGraph(ReebGraph *rg, int count) 02031 { 02032 ReebArc *arc; 02033 char filename[128]; 02034 FILE *f; 02035 02036 if (count == -1) 02037 { 02038 strcpy(filename, "test.txt"); 02039 } 02040 else { 02041 sprintf(filename, "test%05i.txt", count); 02042 } 02043 f = fopen(filename, "w"); 02044 02045 for(arc = rg->arcs.first; arc; arc = arc->next) 02046 { 02047 int i; 02048 float p[3]; 02049 02050 exportNode(f, "v1", arc->head); 02051 02052 for(i = 0; i < arc->bcount; i++) 02053 { 02054 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]); 02055 } 02056 02057 add_v3_v3v3(p, arc->tail->p, arc->head->p); 02058 mul_v3_fl(p, 0.5f); 02059 02060 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)); 02061 exportNode(f, "v2", arc->tail); 02062 } 02063 02064 fclose(f); 02065 } 02066 02067 /***************************************** MAIN ALGORITHM **********************************************/ 02068 02069 /* edges alone will create zero degree nodes, use this function to remove them */ 02070 static void removeZeroNodes(ReebGraph *rg) 02071 { 02072 ReebNode *node, *next_node; 02073 02074 for (node = rg->nodes.first; node; node = next_node) 02075 { 02076 next_node = node->next; 02077 02078 if (node->degree == 0) 02079 { 02080 BLI_removeNode((BGraph*)rg, (BNode*)node); 02081 } 02082 } 02083 } 02084 02085 void removeNormalNodes(ReebGraph *rg) 02086 { 02087 ReebArc *arc, *nextArc; 02088 02089 // Merge degree 2 nodes 02090 for(arc = rg->arcs.first; arc; arc = nextArc) 02091 { 02092 nextArc = arc->next; 02093 02094 while (arc->head->degree == 2 || arc->tail->degree == 2) 02095 { 02096 // merge at v1 02097 if (arc->head->degree == 2) 02098 { 02099 ReebArc *connectedArc = (ReebArc*)BLI_findConnectedArc((BGraph*)rg, (BArc*)arc, (BNode*)arc->head); 02100 02101 /* If arcs are one after the other */ 02102 if (arc->head == connectedArc->tail) 02103 { 02104 /* remove furthest arc */ 02105 if (arc->tail->weight < connectedArc->head->weight) 02106 { 02107 mergeConnectedArcs(rg, arc, connectedArc); 02108 nextArc = arc->next; 02109 } 02110 else 02111 { 02112 mergeConnectedArcs(rg, connectedArc, arc); 02113 break; /* arc was removed, move to next */ 02114 } 02115 } 02116 /* Otherwise, arcs are side by side */ 02117 else 02118 { 02119 /* Don't do anything, we need to keep the lowest node, even if degree 2 */ 02120 break; 02121 } 02122 } 02123 02124 // merge at v2 02125 if (arc->tail->degree == 2) 02126 { 02127 ReebArc *connectedArc = (ReebArc*)BLI_findConnectedArc((BGraph*)rg, (BArc*)arc, (BNode*)arc->tail); 02128 02129 /* If arcs are one after the other */ 02130 if (arc->tail == connectedArc->head) 02131 { 02132 /* remove furthest arc */ 02133 if (arc->head->weight < connectedArc->tail->weight) 02134 { 02135 mergeConnectedArcs(rg, arc, connectedArc); 02136 nextArc = arc->next; 02137 } 02138 else 02139 { 02140 mergeConnectedArcs(rg, connectedArc, arc); 02141 break; /* arc was removed, move to next */ 02142 } 02143 } 02144 /* Otherwise, arcs are side by side */ 02145 else 02146 { 02147 /* Don't do anything, we need to keep the lowest node, even if degree 2 */ 02148 break; 02149 } 02150 } 02151 } 02152 } 02153 02154 } 02155 02156 static int edgeEquals(ReebEdge *e1, ReebEdge *e2) 02157 { 02158 return (e1->v1 == e2->v1 && e1->v2 == e2->v2); 02159 } 02160 02161 static ReebArc *nextArcMappedToEdge(ReebArc *arc, ReebEdge *e) 02162 { 02163 ReebEdge *nextEdge = NULL; 02164 ReebEdge *edge = NULL; 02165 ReebArc *result = NULL; 02166 02167 /* Find the ReebEdge in the edge list */ 02168 for(edge = arc->edges.first; edge && !edgeEquals(edge, e); edge = edge->next) 02169 { } 02170 02171 nextEdge = edge->nextEdge; 02172 02173 if (nextEdge != NULL) 02174 { 02175 result = nextEdge->arc; 02176 } 02177 02178 return result; 02179 } 02180 02181 void addFacetoArc(ReebArc *arc, EditFace *efa) 02182 { 02183 BLI_ghash_insert(arc->faces, efa, efa); 02184 } 02185 02186 void mergeArcFaces(ReebGraph *UNUSED(rg), ReebArc *aDst, ReebArc *aSrc) 02187 { 02188 GHashIterator ghi; 02189 02190 for(BLI_ghashIterator_init(&ghi, aSrc->faces); 02191 !BLI_ghashIterator_isDone(&ghi); 02192 BLI_ghashIterator_step(&ghi)) 02193 { 02194 EditFace *efa = BLI_ghashIterator_getValue(&ghi); 02195 BLI_ghash_insert(aDst->faces, efa, efa); 02196 } 02197 } 02198 02199 void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction) 02200 { 02201 ReebEdge *e = NULL; 02202 02203 if (direction == MERGE_APPEND) 02204 { 02205 for(e = aSrc->edges.first; e; e = e->next) 02206 { 02207 e->arc = aDst; // Edge is stolen by new arc 02208 } 02209 02210 BLI_movelisttolist(&aDst->edges , &aSrc->edges); 02211 } 02212 else 02213 { 02214 for(e = aSrc->edges.first; e; e = e->next) 02215 { 02216 ReebEdge *newEdge = copyEdge(e); 02217 02218 newEdge->arc = aDst; 02219 02220 BLI_addtail(&aDst->edges, newEdge); 02221 02222 if (direction == MERGE_LOWER) 02223 { 02224 void **p = BLI_edgehash_lookup_p(rg->emap, e->v1->index, e->v2->index); 02225 02226 newEdge->nextEdge = e; 02227 02228 // if edge was the first in the list, point the edit edge to the new reeb edge instead. 02229 if (*p == e) 02230 { 02231 *p = (void*)newEdge; 02232 } 02233 // otherwise, advance in the list until the predecessor is found then insert it there 02234 else 02235 { 02236 ReebEdge *previous = (ReebEdge*)*p; 02237 02238 while(previous->nextEdge != e) 02239 { 02240 previous = previous->nextEdge; 02241 } 02242 02243 previous->nextEdge = newEdge; 02244 } 02245 } 02246 else 02247 { 02248 newEdge->nextEdge = e->nextEdge; 02249 e->nextEdge = newEdge; 02250 } 02251 } 02252 } 02253 } 02254 02255 // return 1 on full merge 02256 int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1) 02257 { 02258 int result = 0; 02259 ReebNode *removedNode = NULL; 02260 02261 a0->length += a1->length; 02262 02263 mergeArcEdges(rg, a0, a1, MERGE_APPEND); 02264 mergeArcFaces(rg, a0, a1); 02265 02266 // Bring a0 to the combine length of both arcs 02267 if (a0->tail == a1->head) 02268 { 02269 removedNode = a0->tail; 02270 a0->tail = a1->tail; 02271 } 02272 else if (a0->head == a1->tail) 02273 { 02274 removedNode = a0->head; 02275 a0->head = a1->head; 02276 } 02277 02278 resizeArcBuckets(a0); 02279 // Merge a1 in a0 02280 mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight); 02281 02282 // remove a1 from graph 02283 BLI_remlink(&rg->arcs, a1); 02284 REEB_freeArc((BArc*)a1); 02285 02286 BLI_removeNode((BGraph*)rg, (BNode*)removedNode); 02287 result = 1; 02288 02289 return result; 02290 } 02291 // return 1 on full merge 02292 int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1) 02293 { 02294 int result = 0; 02295 // TRIANGLE POINTS DOWN 02296 if (a0->head->weight == a1->head->weight) // heads are the same 02297 { 02298 if (a0->tail->weight == a1->tail->weight) // tails also the same, arcs can be totally merge together 02299 { 02300 mergeArcEdges(rg, a0, a1, MERGE_APPEND); 02301 mergeArcFaces(rg, a0, a1); 02302 02303 mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight); 02304 02305 // Adjust node degree 02306 //a1->head->degree--; 02307 NodeDegreeDecrement(rg, a1->head); 02308 //a1->tail->degree--; 02309 NodeDegreeDecrement(rg, a1->tail); 02310 02311 // remove a1 from graph 02312 BLI_remlink(&rg->arcs, a1); 02313 02314 REEB_freeArc((BArc*)a1); 02315 result = 1; 02316 } 02317 else if (a0->tail->weight > a1->tail->weight) // a1->tail->weight is in the middle 02318 { 02319 mergeArcEdges(rg, a1, a0, MERGE_LOWER); 02320 mergeArcFaces(rg, a1, a0); 02321 02322 // Adjust node degree 02323 //a0->head->degree--; 02324 NodeDegreeDecrement(rg, a0->head); 02325 //a1->tail->degree++; 02326 NodeDegreeIncrement(rg, a1->tail); 02327 02328 mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight); 02329 a0->head = a1->tail; 02330 resizeArcBuckets(a0); 02331 } 02332 else // a0>n2 is in the middle 02333 { 02334 mergeArcEdges(rg, a0, a1, MERGE_LOWER); 02335 mergeArcFaces(rg, a0, a1); 02336 02337 // Adjust node degree 02338 //a1->head->degree--; 02339 NodeDegreeDecrement(rg, a1->head); 02340 //a0->tail->degree++; 02341 NodeDegreeIncrement(rg, a0->tail); 02342 02343 mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight); 02344 a1->head = a0->tail; 02345 resizeArcBuckets(a1); 02346 } 02347 } 02348 // TRIANGLE POINTS UP 02349 else if (a0->tail->weight == a1->tail->weight) // tails are the same 02350 { 02351 if (a0->head->weight > a1->head->weight) // a0->head->weight is in the middle 02352 { 02353 mergeArcEdges(rg, a0, a1, MERGE_HIGHER); 02354 mergeArcFaces(rg, a0, a1); 02355 02356 // Adjust node degree 02357 //a1->tail->degree--; 02358 NodeDegreeDecrement(rg, a1->tail); 02359 //a0->head->degree++; 02360 NodeDegreeIncrement(rg, a0->head); 02361 02362 mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight); 02363 a1->tail = a0->head; 02364 resizeArcBuckets(a1); 02365 } 02366 else // a1->head->weight is in the middle 02367 { 02368 mergeArcEdges(rg, a1, a0, MERGE_HIGHER); 02369 mergeArcFaces(rg, a1, a0); 02370 02371 // Adjust node degree 02372 //a0->tail->degree--; 02373 NodeDegreeDecrement(rg, a0->tail); 02374 //a1->head->degree++; 02375 NodeDegreeIncrement(rg, a1->head); 02376 02377 mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight); 02378 a0->tail = a1->head; 02379 resizeArcBuckets(a0); 02380 } 02381 } 02382 else 02383 { 02384 // Need something here (OR NOT) 02385 } 02386 02387 return result; 02388 } 02389 02390 static void glueByMergeSort(ReebGraph *rg, ReebArc *a0, ReebArc *a1, ReebEdge *e0, ReebEdge *e1) 02391 { 02392 int total = 0; 02393 while (total == 0 && a0 != a1 && a0 != NULL && a1 != NULL) 02394 { 02395 total = mergeArcs(rg, a0, a1); 02396 02397 if (total == 0) // if it wasn't a total merge, go forward 02398 { 02399 if (a0->tail->weight < a1->tail->weight) 02400 { 02401 a0 = nextArcMappedToEdge(a0, e0); 02402 } 02403 else 02404 { 02405 a1 = nextArcMappedToEdge(a1, e1); 02406 } 02407 } 02408 } 02409 } 02410 02411 static void mergePaths(ReebGraph *rg, ReebEdge *e0, ReebEdge *e1, ReebEdge *e2) 02412 { 02413 ReebArc *a0, *a1, *a2; 02414 a0 = e0->arc; 02415 a1 = e1->arc; 02416 a2 = e2->arc; 02417 02418 glueByMergeSort(rg, a0, a1, e0, e1); 02419 glueByMergeSort(rg, a0, a2, e0, e2); 02420 } 02421 02422 static ReebEdge * createArc(ReebGraph *rg, ReebNode *node1, ReebNode *node2) 02423 { 02424 ReebEdge *edge; 02425 02426 edge = BLI_edgehash_lookup(rg->emap, node1->index, node2->index); 02427 02428 // Only add existing edges that haven't been added yet 02429 if (edge == NULL) 02430 { 02431 ReebArc *arc; 02432 ReebNode *v1, *v2; 02433 float len, offset; 02434 int i; 02435 02436 arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); 02437 edge = MEM_callocN(sizeof(ReebEdge), "reeb edge"); 02438 02439 arc->flag = 0; // clear flag on init 02440 arc->symmetry_level = 0; 02441 arc->faces = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createArc gh"); 02442 02443 if (node1->weight <= node2->weight) 02444 { 02445 v1 = node1; 02446 v2 = node2; 02447 } 02448 else 02449 { 02450 v1 = node2; 02451 v2 = node1; 02452 } 02453 02454 arc->head = v1; 02455 arc->tail = v2; 02456 02457 // increase node degree 02458 //v1->degree++; 02459 NodeDegreeIncrement(rg, v1); 02460 //v2->degree++; 02461 NodeDegreeIncrement(rg, v2); 02462 02463 BLI_edgehash_insert(rg->emap, node1->index, node2->index, edge); 02464 02465 edge->arc = arc; 02466 edge->nextEdge = NULL; 02467 edge->v1 = v1; 02468 edge->v2 = v2; 02469 02470 BLI_addtail(&rg->arcs, arc); 02471 BLI_addtail(&arc->edges, edge); 02472 02473 /* adding buckets for embedding */ 02474 allocArcBuckets(arc); 02475 02476 offset = arc->head->weight; 02477 len = arc->tail->weight - arc->head->weight; 02478 02479 #if 0 02480 /* This is the actual embedding filling described in the paper 02481 * the problem is that it only works with really dense meshes 02482 */ 02483 if (arc->bcount > 0) 02484 { 02485 addVertToBucket(&(arc->buckets[0]), arc->head->co); 02486 addVertToBucket(&(arc->buckets[arc->bcount - 1]), arc->tail->co); 02487 } 02488 #else 02489 for(i = 0; i < arc->bcount; i++) 02490 { 02491 float co[3]; 02492 float f = (arc->buckets[i].val - offset) / len; 02493 02494 interp_v3_v3v3(co, v1->p, v2->p, f); 02495 addVertToBucket(&(arc->buckets[i]), co); 02496 } 02497 #endif 02498 02499 } 02500 02501 return edge; 02502 } 02503 02504 static void addTriangleToGraph(ReebGraph *rg, ReebNode * n1, ReebNode * n2, ReebNode * n3, EditFace *efa) 02505 { 02506 ReebEdge *re1, *re2, *re3; 02507 ReebEdge *e1, *e2, *e3; 02508 float len1, len2, len3; 02509 02510 re1 = createArc(rg, n1, n2); 02511 re2 = createArc(rg, n2, n3); 02512 re3 = createArc(rg, n3, n1); 02513 02514 addFacetoArc(re1->arc, efa); 02515 addFacetoArc(re2->arc, efa); 02516 addFacetoArc(re3->arc, efa); 02517 02518 len1 = (float)fabs(n1->weight - n2->weight); 02519 len2 = (float)fabs(n2->weight - n3->weight); 02520 len3 = (float)fabs(n3->weight - n1->weight); 02521 02522 /* The rest of the algorithm assumes that e1 is the longest edge */ 02523 02524 if (len1 >= len2 && len1 >= len3) 02525 { 02526 e1 = re1; 02527 e2 = re2; 02528 e3 = re3; 02529 } 02530 else if (len2 >= len1 && len2 >= len3) 02531 { 02532 e1 = re2; 02533 e2 = re1; 02534 e3 = re3; 02535 } 02536 else 02537 { 02538 e1 = re3; 02539 e2 = re2; 02540 e3 = re1; 02541 } 02542 02543 /* And e2 is the lowest edge 02544 * If e3 is lower than e2, swap them 02545 */ 02546 if (e3->v1->weight < e2->v1->weight) 02547 { 02548 ReebEdge *etmp = e2; 02549 e2 = e3; 02550 e3 = etmp; 02551 } 02552 02553 02554 mergePaths(rg, e1, e2, e3); 02555 } 02556 02557 ReebGraph * generateReebGraph(EditMesh *em, int subdivisions) 02558 { 02559 ReebGraph *rg; 02560 EditVert *eve; 02561 EditFace *efa; 02562 int index; 02563 /*int totvert;*/ 02564 02565 #ifdef DEBUG_REEB 02566 int totfaces; 02567 int countfaces = 0; 02568 #endif 02569 02570 rg = newReebGraph(); 02571 02572 rg->resolution = subdivisions; 02573 02574 /*totvert = BLI_countlist(&em->verts);*/ /*UNUSED*/ 02575 #ifdef DEBUG_REEB 02576 totfaces = BLI_countlist(&em->faces); 02577 #endif 02578 02579 renormalizeWeight(em, 1.0f); 02580 02581 /* Spread weight to minimize errors */ 02582 spreadWeight(em); 02583 02584 renormalizeWeight(em, (float)rg->resolution); 02585 02586 /* Adding vertice */ 02587 for(index = 0, eve = em->verts.first; eve; eve = eve->next) 02588 { 02589 if (eve->h == 0) 02590 { 02591 addNode(rg, eve); 02592 eve->f2 = 0; 02593 index++; 02594 } 02595 } 02596 02597 /* Adding face, edge per edge */ 02598 for(efa = em->faces.first; efa; efa = efa->next) 02599 { 02600 if (efa->h == 0) 02601 { 02602 ReebNode *n1, *n2, *n3; 02603 02604 n1 = nodeData(efa->v1); 02605 n2 = nodeData(efa->v2); 02606 n3 = nodeData(efa->v3); 02607 02608 addTriangleToGraph(rg, n1, n2, n3, efa); 02609 02610 if (efa->v4) 02611 { 02612 ReebNode *n4 = nodeData(efa->v4); 02613 addTriangleToGraph(rg, n1, n3, n4, efa); 02614 } 02615 #ifdef DEBUG_REEB 02616 countfaces++; 02617 if (countfaces % 100 == 0) 02618 { 02619 printf("\rface %i of %i", countfaces, totfaces); 02620 } 02621 #endif 02622 } 02623 } 02624 02625 printf("\n"); 02626 02627 removeZeroNodes(rg); 02628 02629 removeNormalNodes(rg); 02630 02631 return rg; 02632 } 02633 02634 /***************************************** WEIGHT UTILS **********************************************/ 02635 02636 void renormalizeWeight(EditMesh *em, float newmax) 02637 { 02638 EditVert *eve; 02639 float minimum, maximum, range; 02640 02641 if (em == NULL || BLI_countlist(&em->verts) == 0) 02642 return; 02643 02644 /* First pass, determine maximum and minimum */ 02645 eve = em->verts.first; 02646 minimum = weightData(eve); 02647 maximum = minimum; 02648 for(; eve; eve = eve->next) 02649 { 02650 maximum = MAX2(maximum, weightData(eve)); 02651 minimum = MIN2(minimum, weightData(eve)); 02652 } 02653 02654 range = maximum - minimum; 02655 02656 /* Normalize weights */ 02657 for(eve = em->verts.first; eve; eve = eve->next) 02658 { 02659 float weight = (weightData(eve) - minimum) / range * newmax; 02660 weightSetData(eve, weight); 02661 } 02662 } 02663 02664 02665 int weightFromLoc(EditMesh *em, int axis) 02666 { 02667 EditVert *eve; 02668 02669 if (em == NULL || BLI_countlist(&em->verts) == 0 || axis < 0 || axis > 2) 02670 return 0; 02671 02672 /* Copy coordinate in weight */ 02673 for(eve = em->verts.first; eve; eve = eve->next) 02674 { 02675 weightSetData(eve, eve->co[axis]); 02676 } 02677 02678 return 1; 02679 } 02680 02681 static float cotan_weight(float *v1, float *v2, float *v3) 02682 { 02683 float a[3], b[3], c[3], clen; 02684 02685 sub_v3_v3v3(a, v2, v1); 02686 sub_v3_v3v3(b, v3, v1); 02687 cross_v3_v3v3(c, a, b); 02688 02689 clen = len_v3(c); 02690 02691 if (clen == 0.0f) 02692 return 0.0f; 02693 02694 return dot_v3v3(a, b)/clen; 02695 } 02696 02697 static void addTriangle(EditVert *v1, EditVert *v2, EditVert *v3, int e1, int e2, int e3) 02698 { 02699 /* Angle opposite e1 */ 02700 float t1= cotan_weight(v1->co, v2->co, v3->co) / e2; 02701 02702 /* Angle opposite e2 */ 02703 float t2 = cotan_weight(v2->co, v3->co, v1->co) / e3; 02704 02705 /* Angle opposite e3 */ 02706 float t3 = cotan_weight(v3->co, v1->co, v2->co) / e1; 02707 02708 int i1 = indexData(v1); 02709 int i2 = indexData(v2); 02710 int i3 = indexData(v3); 02711 02712 nlMatrixAdd(i1, i1, t2+t3); 02713 nlMatrixAdd(i2, i2, t1+t3); 02714 nlMatrixAdd(i3, i3, t1+t2); 02715 02716 nlMatrixAdd(i1, i2, -t3); 02717 nlMatrixAdd(i2, i1, -t3); 02718 02719 nlMatrixAdd(i2, i3, -t1); 02720 nlMatrixAdd(i3, i2, -t1); 02721 02722 nlMatrixAdd(i3, i1, -t2); 02723 nlMatrixAdd(i1, i3, -t2); 02724 } 02725 02726 int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges) 02727 { 02728 NLboolean success; 02729 EditVert *eve; 02730 EditEdge *eed; 02731 EditFace *efa; 02732 int totvert = 0; 02733 int index; 02734 int rval; 02735 02736 /* Find local extrema */ 02737 for(eve = em->verts.first; eve; eve = eve->next) 02738 { 02739 totvert++; 02740 } 02741 02742 /* Solve with openNL */ 02743 02744 nlNewContext(); 02745 02746 nlSolverParameteri(NL_NB_VARIABLES, totvert); 02747 02748 nlBegin(NL_SYSTEM); 02749 02750 /* Find local extrema */ 02751 for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next) 02752 { 02753 if (eve->h == 0) 02754 { 02755 EditEdge *eed; 02756 int maximum = 1; 02757 int minimum = 1; 02758 02759 NextEdgeForVert(indexed_edges, -1); /* Reset next edge */ 02760 for(eed = NextEdgeForVert(indexed_edges, index); eed && (maximum || minimum); eed = NextEdgeForVert(indexed_edges, index)) 02761 { 02762 EditVert *eve2; 02763 02764 if (eed->v1 == eve) 02765 { 02766 eve2 = eed->v2; 02767 } 02768 else 02769 { 02770 eve2 = eed->v1; 02771 } 02772 02773 if (eve2->h == 0) 02774 { 02775 /* Adjacent vertex is bigger, not a local maximum */ 02776 if (weightData(eve2) > weightData(eve)) 02777 { 02778 maximum = 0; 02779 } 02780 /* Adjacent vertex is smaller, not a local minimum */ 02781 else if (weightData(eve2) < weightData(eve)) 02782 { 02783 minimum = 0; 02784 } 02785 } 02786 } 02787 02788 if (maximum || minimum) 02789 { 02790 float w = weightData(eve); 02791 eve->f1 = 0; 02792 nlSetVariable(0, index, w); 02793 nlLockVariable(index); 02794 } 02795 else 02796 { 02797 eve->f1 = 1; 02798 } 02799 } 02800 } 02801 02802 nlBegin(NL_MATRIX); 02803 02804 /* Zero edge weight */ 02805 for(eed = em->edges.first; eed; eed = eed->next) 02806 { 02807 eed->tmp.l = 0; 02808 } 02809 02810 /* Add faces count to the edge weight */ 02811 for(efa = em->faces.first; efa; efa = efa->next) 02812 { 02813 if (efa->h == 0) 02814 { 02815 efa->e1->tmp.l++; 02816 efa->e2->tmp.l++; 02817 efa->e3->tmp.l++; 02818 02819 if (efa->e4) 02820 { 02821 efa->e4->tmp.l++; 02822 } 02823 } 02824 } 02825 02826 /* Add faces angle to the edge weight */ 02827 for(efa = em->faces.first; efa; efa = efa->next) 02828 { 02829 if (efa->h == 0) 02830 { 02831 if (efa->v4 == NULL) 02832 { 02833 addTriangle(efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, efa->e3->tmp.l); 02834 } 02835 else 02836 { 02837 addTriangle(efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, 2); 02838 addTriangle(efa->v3, efa->v4, efa->v1, efa->e3->tmp.l, efa->e4->tmp.l, 2); 02839 } 02840 } 02841 } 02842 02843 nlEnd(NL_MATRIX); 02844 02845 nlEnd(NL_SYSTEM); 02846 02847 success = nlSolveAdvanced(NULL, NL_TRUE); 02848 02849 if (success) 02850 { 02851 rval = 1; 02852 for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next) 02853 { 02854 weightSetData(eve, nlGetVariable(0, index)); 02855 } 02856 } 02857 else 02858 { 02859 rval = 0; 02860 } 02861 02862 nlDeleteContext(nlGetCurrent()); 02863 02864 return rval; 02865 } 02866 02867 02868 EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index) 02869 { 02870 static int offset = -1; 02871 02872 /* Reset method, call with NULL mesh pointer */ 02873 if (index == -1) 02874 { 02875 offset = -1; 02876 return NULL; 02877 } 02878 02879 /* first pass, start at the head of the list */ 02880 if (offset == -1) 02881 { 02882 offset = indexed_edges->offset[index]; 02883 } 02884 /* subsequent passes, start on the next edge */ 02885 else 02886 { 02887 offset++; 02888 } 02889 02890 return indexed_edges->edges[offset]; 02891 } 02892 02893 static void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeIndex *indexed_edges) 02894 { 02895 Heap *edge_heap; 02896 EditVert *current_eve = NULL; 02897 EditEdge *eed = NULL; 02898 EditEdge *select_eed = NULL; 02899 02900 edge_heap = BLI_heap_new(); 02901 02902 current_eve = starting_vert; 02903 02904 /* insert guard in heap, when that is returned, no more edges */ 02905 BLI_heap_insert(edge_heap, FLT_MAX, NULL); 02906 02907 /* Initialize edge flag */ 02908 for(eed= em->edges.first; eed; eed= eed->next) 02909 { 02910 eed->f1 = 0; 02911 } 02912 02913 while (BLI_heap_size(edge_heap) > 0) 02914 { 02915 float current_weight; 02916 02917 current_eve->f1 = 1; /* mark vertex as selected */ 02918 02919 /* Add all new edges connected to current_eve to the list */ 02920 NextEdgeForVert(indexed_edges, -1); // Reset next edge 02921 for(eed = NextEdgeForVert(indexed_edges, indexData(current_eve)); eed; eed = NextEdgeForVert(indexed_edges, indexData(current_eve))) 02922 { 02923 if (eed->f1 == 0) 02924 { 02925 BLI_heap_insert(edge_heap, weightData(current_eve) + eed->tmp.fp, eed); 02926 eed->f1 = 1; 02927 } 02928 } 02929 02930 /* Find next shortest edge with unselected verts */ 02931 do 02932 { 02933 current_weight = BLI_heap_node_value(BLI_heap_top(edge_heap)); 02934 select_eed = BLI_heap_popmin(edge_heap); 02935 } while (select_eed != NULL && select_eed->v1->f1 != 0 && select_eed->v2->f1); 02936 02937 if (select_eed != NULL) 02938 { 02939 select_eed->f1 = 2; 02940 02941 if (select_eed->v1->f1 == 0) /* v1 is the new vertex */ 02942 { 02943 current_eve = select_eed->v1; 02944 } 02945 else /* otherwise, it's v2 */ 02946 { 02947 current_eve = select_eed->v2; 02948 } 02949 02950 weightSetData(current_eve, current_weight); 02951 } 02952 } 02953 02954 BLI_heap_free(edge_heap, NULL); 02955 } 02956 02957 static void freeEdgeIndex(EdgeIndex *indexed_edges) 02958 { 02959 MEM_freeN(indexed_edges->offset); 02960 MEM_freeN(indexed_edges->edges); 02961 } 02962 02963 static void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges) 02964 { 02965 EditVert *eve; 02966 EditEdge *eed; 02967 int totvert = 0; 02968 int tot_indexed = 0; 02969 int offset = 0; 02970 02971 totvert = BLI_countlist(&em->verts); 02972 02973 indexed_edges->offset = MEM_callocN(totvert * sizeof(int), "EdgeIndex offset"); 02974 02975 for(eed = em->edges.first; eed; eed = eed->next) 02976 { 02977 if (eed->v1->h == 0 && eed->v2->h == 0) 02978 { 02979 tot_indexed += 2; 02980 indexed_edges->offset[indexData(eed->v1)]++; 02981 indexed_edges->offset[indexData(eed->v2)]++; 02982 } 02983 } 02984 02985 tot_indexed += totvert; 02986 02987 indexed_edges->edges = MEM_callocN(tot_indexed * sizeof(EditEdge*), "EdgeIndex edges"); 02988 02989 /* setting vert offsets */ 02990 for(eve = em->verts.first; eve; eve = eve->next) 02991 { 02992 if (eve->h == 0) 02993 { 02994 int d = indexed_edges->offset[indexData(eve)]; 02995 indexed_edges->offset[indexData(eve)] = offset; 02996 offset += d + 1; 02997 } 02998 } 02999 03000 /* adding edges in array */ 03001 for(eed = em->edges.first; eed; eed= eed->next) 03002 { 03003 if (eed->v1->h == 0 && eed->v2->h == 0) 03004 { 03005 int i; 03006 for (i = indexed_edges->offset[indexData(eed->v1)]; i < tot_indexed; i++) 03007 { 03008 if (indexed_edges->edges[i] == NULL) 03009 { 03010 indexed_edges->edges[i] = eed; 03011 break; 03012 } 03013 } 03014 03015 for (i = indexed_edges->offset[indexData(eed->v2)]; i < tot_indexed; i++) 03016 { 03017 if (indexed_edges->edges[i] == NULL) 03018 { 03019 indexed_edges->edges[i] = eed; 03020 break; 03021 } 03022 } 03023 } 03024 } 03025 } 03026 03027 int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges) 03028 { 03029 EditVert *eve; 03030 int totedge = 0; 03031 int totvert = 0; 03032 int vCount = 0; 03033 03034 totvert = BLI_countlist(&em->verts); 03035 03036 if (em == NULL || totvert == 0) 03037 { 03038 return 0; 03039 } 03040 03041 totedge = BLI_countlist(&em->edges); 03042 03043 if (totedge == 0) 03044 { 03045 return 0; 03046 } 03047 03048 /* Initialize vertice flag and find at least one selected vertex */ 03049 for(eve = em->verts.first; eve; eve = eve->next) 03050 { 03051 eve->f1 = 0; 03052 if (eve->f & SELECT) 03053 { 03054 vCount = 1; 03055 } 03056 } 03057 03058 if (vCount == 0) 03059 { 03060 return 0; /* no selected vert, failure */ 03061 } 03062 else 03063 { 03064 EditEdge *eed; 03065 int allDone = 0; 03066 03067 /* Calculate edge weight */ 03068 for(eed = em->edges.first; eed; eed= eed->next) 03069 { 03070 if (eed->v1->h == 0 && eed->v2->h == 0) 03071 { 03072 eed->tmp.fp = len_v3v3(eed->v1->co, eed->v2->co); 03073 } 03074 } 03075 03076 /* Apply dijkstra spf for each selected vert */ 03077 for(eve = em->verts.first; eve; eve = eve->next) 03078 { 03079 if (eve->f & SELECT) 03080 { 03081 shortestPathsFromVert(em, eve, indexed_edges); 03082 } 03083 } 03084 03085 /* connect unselected islands */ 03086 while (allDone == 0) 03087 { 03088 EditVert *selected_eve = NULL; 03089 float selected_weight = 0; 03090 float min_distance = FLT_MAX; 03091 03092 allDone = 1; 03093 03094 for (eve = em->verts.first; eve; eve = eve->next) 03095 { 03096 /* for every vertex visible that hasn't been processed yet */ 03097 if (eve->h == 0 && eve->f1 != 1) 03098 { 03099 EditVert *closest_eve; 03100 03101 /* find the closest processed vertex */ 03102 for (closest_eve = em->verts.first; closest_eve; closest_eve = closest_eve->next) 03103 { 03104 /* vertex is already processed and distance is smaller than current minimum */ 03105 if (closest_eve->f1 == 1) 03106 { 03107 float distance = len_v3v3(closest_eve->co, eve->co); 03108 if (distance < min_distance) 03109 { 03110 min_distance = distance; 03111 selected_eve = eve; 03112 selected_weight = weightData(closest_eve); 03113 } 03114 } 03115 } 03116 } 03117 } 03118 03119 if (selected_eve) 03120 { 03121 allDone = 0; 03122 03123 weightSetData(selected_eve, selected_weight + min_distance); 03124 shortestPathsFromVert(em, selected_eve, indexed_edges); 03125 } 03126 } 03127 } 03128 03129 for(eve = em->verts.first; eve && vCount == 0; eve = eve->next) 03130 { 03131 if (eve->f1 == 0) 03132 { 03133 printf("vertex not reached\n"); 03134 break; 03135 } 03136 } 03137 03138 return 1; 03139 } 03140 03141 /****************************************** BUCKET ITERATOR **************************************************/ 03142 03143 static void* headNode(void *arg); 03144 static void* tailNode(void *arg); 03145 static void* nextBucket(void *arg); 03146 static void* nextNBucket(void *arg, int n); 03147 static void* peekBucket(void *arg, int n); 03148 static void* previousBucket(void *arg); 03149 static int iteratorStopped(void *arg); 03150 03151 static void initIteratorFct(ReebArcIterator *iter) 03152 { 03153 iter->head = headNode; 03154 iter->tail = tailNode; 03155 iter->peek = peekBucket; 03156 iter->next = nextBucket; 03157 iter->nextN = nextNBucket; 03158 iter->previous = previousBucket; 03159 iter->stopped = iteratorStopped; 03160 } 03161 03162 static void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) 03163 { 03164 if (bucket) 03165 { 03166 iter->p = bucket->p; 03167 iter->no = bucket->no; 03168 } 03169 else 03170 { 03171 iter->p = NULL; 03172 iter->no = NULL; 03173 } 03174 iter->size = 0; 03175 } 03176 03177 void initArcIterator(BArcIterator *arg, ReebArc *arc, ReebNode *head) 03178 { 03179 ReebArcIterator *iter = (ReebArcIterator*)arg; 03180 03181 initIteratorFct(iter); 03182 iter->arc = arc; 03183 03184 if (head == arc->head) 03185 { 03186 iter->start = 0; 03187 iter->end = arc->bcount - 1; 03188 iter->stride = 1; 03189 } 03190 else 03191 { 03192 iter->start = arc->bcount - 1; 03193 iter->end = 0; 03194 iter->stride = -1; 03195 } 03196 03197 iter->length = arc->bcount; 03198 03199 iter->index = -1; 03200 } 03201 03202 void initArcIteratorStart(BArcIterator *arg, struct ReebArc *arc, struct ReebNode *head, int start) 03203 { 03204 ReebArcIterator *iter = (ReebArcIterator*)arg; 03205 03206 initIteratorFct(iter); 03207 iter->arc = arc; 03208 03209 if (head == arc->head) 03210 { 03211 iter->start = start; 03212 iter->end = arc->bcount - 1; 03213 iter->stride = 1; 03214 } 03215 else 03216 { 03217 iter->start = arc->bcount - 1 - start; 03218 iter->end = 0; 03219 iter->stride = -1; 03220 } 03221 03222 iter->index = -1; 03223 03224 iter->length = arc->bcount - start; 03225 03226 if (start >= arc->bcount) 03227 { 03228 iter->start = iter->end; /* stop iterator since it's past its end */ 03229 } 03230 } 03231 03232 void initArcIterator2(BArcIterator *arg, ReebArc *arc, int start, int end) 03233 { 03234 ReebArcIterator *iter = (ReebArcIterator*)arg; 03235 03236 initIteratorFct(iter); 03237 iter->arc = arc; 03238 03239 iter->start = start; 03240 iter->end = end; 03241 03242 if (end > start) 03243 { 03244 iter->stride = 1; 03245 } 03246 else 03247 { 03248 iter->stride = -1; 03249 } 03250 03251 iter->index = -1; 03252 03253 iter->length = abs(iter->end - iter->start) + 1; 03254 } 03255 03256 static void* headNode(void *arg) 03257 { 03258 ReebArcIterator *iter = (ReebArcIterator*)arg; 03259 ReebNode *node; 03260 03261 if (iter->start < iter->end) 03262 { 03263 node = iter->arc->head; 03264 } 03265 else 03266 { 03267 node = iter->arc->tail; 03268 } 03269 03270 iter->p = node->p; 03271 iter->no = node->no; 03272 iter->size = 0; 03273 03274 return node; 03275 } 03276 03277 static void* tailNode(void *arg) 03278 { 03279 ReebArcIterator *iter = (ReebArcIterator*)arg; 03280 ReebNode *node; 03281 03282 if (iter->start < iter->end) 03283 { 03284 node = iter->arc->tail; 03285 } 03286 else 03287 { 03288 node = iter->arc->head; 03289 } 03290 03291 iter->p = node->p; 03292 iter->no = node->no; 03293 iter->size = 0; 03294 03295 return node; 03296 } 03297 03298 static void* nextBucket(void *arg) 03299 { 03300 ReebArcIterator *iter = (ReebArcIterator*)arg; 03301 EmbedBucket *result = NULL; 03302 03303 iter->index++; 03304 03305 if (iter->index < iter->length) 03306 { 03307 result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); 03308 } 03309 03310 setIteratorValues(iter, result); 03311 return result; 03312 } 03313 03314 static void* nextNBucket(void *arg, int n) 03315 { 03316 ReebArcIterator *iter = (ReebArcIterator*)arg; 03317 EmbedBucket *result = NULL; 03318 03319 iter->index += n; 03320 03321 /* check if passed end */ 03322 if (iter->index < iter->length) 03323 { 03324 result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); 03325 } 03326 03327 setIteratorValues(iter, result); 03328 return result; 03329 } 03330 03331 static void* peekBucket(void *arg, int n) 03332 { 03333 ReebArcIterator *iter = (ReebArcIterator*)arg; 03334 EmbedBucket *result = NULL; 03335 int index = iter->index + n; 03336 03337 /* check if passed end */ 03338 if (index < iter->length) 03339 { 03340 result = &(iter->arc->buckets[iter->start + (iter->stride * index)]); 03341 } 03342 03343 setIteratorValues(iter, result); 03344 return result; 03345 } 03346 03347 static void* previousBucket(void *arg) 03348 { 03349 ReebArcIterator *iter = (ReebArcIterator*)arg; 03350 EmbedBucket *result = NULL; 03351 03352 if (iter->index > 0) 03353 { 03354 iter->index--; 03355 result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); 03356 } 03357 03358 setIteratorValues(iter, result); 03359 return result; 03360 } 03361 03362 static int iteratorStopped(void *arg) 03363 { 03364 ReebArcIterator *iter = (ReebArcIterator*)arg; 03365 03366 if (iter->index >= iter->length) 03367 { 03368 return 1; 03369 } 03370 else 03371 { 03372 return 0; 03373 } 03374 } 03375 03376 /************************ PUBLIC FUNCTIONS *********************************************/ 03377 03378 ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C) 03379 { 03380 Scene *scene = CTX_data_scene(C); 03381 Object *obedit = CTX_data_edit_object(C); 03382 EditMesh *em =( (Mesh*)obedit->data)->edit_mesh; 03383 EdgeIndex indexed_edges; 03384 VertexData *data; 03385 ReebGraph *rg = NULL; 03386 ReebGraph *rgi, *previous; 03387 int i, nb_levels = REEB_MAX_MULTI_LEVEL; 03388 03389 if (em == NULL) 03390 return NULL; 03391 03392 data = allocVertexData(em); 03393 03394 buildIndexedEdges(em, &indexed_edges); 03395 03396 if (weightFromDistance(em, &indexed_edges) == 0) 03397 { 03398 // XXX error("No selected vertex\n"); 03399 freeEdgeIndex(&indexed_edges); 03400 return NULL; 03401 } 03402 03403 renormalizeWeight(em, 1.0f); 03404 03405 if (scene->toolsettings->skgen_options & SKGEN_HARMONIC) 03406 { 03407 weightToHarmonic(em, &indexed_edges); 03408 } 03409 03410 freeEdgeIndex(&indexed_edges); 03411 03412 rg = generateReebGraph(em, scene->toolsettings->skgen_resolution); 03413 03414 /* Remove arcs without embedding */ 03415 filterNullReebGraph(rg); 03416 03417 /* smart filter and loop filter on basic level */ 03418 filterGraph(rg, SKGEN_FILTER_SMART, 0, 0); 03419 03420 repositionNodes(rg); 03421 03422 /* Filtering might have created degree 2 nodes, so remove them */ 03423 removeNormalNodes(rg); 03424 03425 joinSubgraphs(rg, 1.0); 03426 03427 BLI_buildAdjacencyList((BGraph*)rg); 03428 03429 /* calc length before copy, so we have same length on all levels */ 03430 BLI_calcGraphLength((BGraph*)rg); 03431 03432 previous = NULL; 03433 for (i = 0; i <= nb_levels; i++) 03434 { 03435 rgi = rg; 03436 03437 /* don't filter last level */ 03438 if (i > 0) 03439 { 03440 float internal_threshold; 03441 float external_threshold; 03442 03443 /* filter internal progressively in second half only*/ 03444 if (i > nb_levels / 2) 03445 { 03446 internal_threshold = rg->length * scene->toolsettings->skgen_threshold_internal; 03447 } 03448 else 03449 { 03450 internal_threshold = rg->length * scene->toolsettings->skgen_threshold_internal * (2 * i / (float)nb_levels); 03451 } 03452 03453 external_threshold = rg->length * scene->toolsettings->skgen_threshold_external * (i / (float)nb_levels); 03454 03455 filterGraph(rgi, scene->toolsettings->skgen_options, internal_threshold, external_threshold); 03456 } 03457 03458 if (i < nb_levels) 03459 { 03460 rg = copyReebGraph(rgi, i + 1); 03461 } 03462 03463 finalizeGraph(rgi, scene->toolsettings->skgen_postpro_passes, scene->toolsettings->skgen_postpro); 03464 03465 BLI_markdownSymmetry((BGraph*)rgi, rgi->nodes.first, scene->toolsettings->skgen_symmetry_limit); 03466 03467 if (previous != NULL) 03468 { 03469 relinkNodes(rgi, previous); 03470 } 03471 previous = rgi; 03472 } 03473 03474 verifyMultiResolutionLinks(rg, 0); 03475 03476 MEM_freeN(data); 03477 03478 return rg; 03479 } 03480 03481 #if 0 03482 03483 ReebGraph *BIF_ReebGraphFromEditMesh(void) 03484 { 03485 EditMesh *em = G.editMesh; 03486 EdgeIndex indexed_edges; 03487 VertexData *data; 03488 ReebGraph *rg = NULL; 03489 03490 if (em == NULL) 03491 return NULL; 03492 03493 data = allocVertexData(em); 03494 03495 buildIndexedEdges(em, &indexed_edges); 03496 03497 if (weightFromDistance(em, &indexed_edges) == 0) 03498 { 03499 error("No selected vertex\n"); 03500 freeEdgeIndex(&indexed_edges); 03501 freeEdgeIndex(&indexed_edges); 03502 return NULL; 03503 } 03504 03505 renormalizeWeight(em, 1.0f); 03506 03507 if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC) 03508 { 03509 weightToHarmonic(em, &indexed_edges); 03510 } 03511 03512 freeEdgeIndex(&indexed_edges); 03513 03514 #ifdef DEBUG_REEB 03515 weightToVCol(em, 1); 03516 #endif 03517 03518 rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution); 03519 03520 03521 /* Remove arcs without embedding */ 03522 filterNullReebGraph(rg); 03523 03524 /* smart filter and loop filter on basic level */ 03525 filterGraph(rg, SKGEN_FILTER_SMART, 0, 0); 03526 03527 repositionNodes(rg); 03528 03529 /* Filtering might have created degree 2 nodes, so remove them */ 03530 removeNormalNodes(rg); 03531 03532 joinSubgraphs(rg, 1.0); 03533 03534 BLI_buildAdjacencyList((BGraph*)rg); 03535 03536 /* calc length before copy, so we have same length on all levels */ 03537 BLI_calcGraphLength((BGraph*)rg); 03538 03539 filterGraph(rg, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external); 03540 03541 finalizeGraph(rg, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro); 03542 03543 #ifdef DEBUG_REEB 03544 REEB_exportGraph(rg, -1); 03545 03546 arcToVCol(rg, em, 0); 03547 //angleToVCol(em, 1); 03548 #endif 03549 03550 printf("DONE\n"); 03551 printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph*)rg)); 03552 03553 MEM_freeN(data); 03554 03555 return rg; 03556 } 03557 03558 void BIF_GlobalReebFree() 03559 { 03560 if (GLOBAL_RG != NULL) 03561 { 03562 REEB_freeGraph(GLOBAL_RG); 03563 GLOBAL_RG = NULL; 03564 } 03565 } 03566 03567 void BIF_GlobalReebGraphFromEditMesh(void) 03568 { 03569 ReebGraph *rg; 03570 03571 BIF_GlobalReebFree(); 03572 03573 rg = BIF_ReebGraphMultiFromEditMesh(); 03574 03575 GLOBAL_RG = rg; 03576 } 03577 03578 void REEB_draw() 03579 { 03580 ReebGraph *rg; 03581 ReebArc *arc; 03582 int i = 0; 03583 03584 if (GLOBAL_RG == NULL) 03585 { 03586 return; 03587 } 03588 03589 if (GLOBAL_RG->link_up && G.scene->toolsettings->skgen_options & SKGEN_DISP_ORIG) 03590 { 03591 for (rg = GLOBAL_RG; rg->link_up; rg = rg->link_up) ; 03592 } 03593 else 03594 { 03595 i = G.scene->toolsettings->skgen_multi_level; 03596 03597 for (rg = GLOBAL_RG; rg->multi_level != i && rg->link_up; rg = rg->link_up) ; 03598 } 03599 03600 glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE)); 03601 03602 glDisable(GL_DEPTH_TEST); 03603 for (arc = rg->arcs.first; arc; arc = arc->next, i++) 03604 { 03605 ReebArcIterator arc_iter; 03606 BArcIterator *iter = (BArcIterator*)&arc_iter; 03607 float vec[3]; 03608 char text[128]; 03609 char *s = text; 03610 03611 glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE) + 2); 03612 glColor3f(0, 0, 0); 03613 glBegin(GL_LINE_STRIP); 03614 glVertex3fv(arc->head->p); 03615 03616 if (arc->bcount) 03617 { 03618 initArcIterator(iter, arc, arc->head); 03619 for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter)) 03620 { 03621 glVertex3fv(iter->p); 03622 } 03623 } 03624 03625 glVertex3fv(arc->tail->p); 03626 glEnd(); 03627 03628 glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE)); 03629 03630 if (arc->symmetry_level == 1) 03631 { 03632 glColor3f(1, 0, 0); 03633 } 03634 else if (arc->symmetry_flag == SYM_SIDE_POSITIVE || arc->symmetry_flag == SYM_SIDE_NEGATIVE) 03635 { 03636 glColor3f(1, 0.5f, 0); 03637 } 03638 else if (arc->symmetry_flag >= SYM_SIDE_RADIAL) 03639 { 03640 glColor3f(0.5f, 1, 0); 03641 } 03642 else 03643 { 03644 glColor3f(1, 1, 0); 03645 } 03646 glBegin(GL_LINE_STRIP); 03647 glVertex3fv(arc->head->p); 03648 03649 if (arc->bcount) 03650 { 03651 initArcIterator(iter, arc, arc->head); 03652 for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter)) 03653 { 03654 glVertex3fv(iter->p); 03655 } 03656 } 03657 03658 glVertex3fv(arc->tail->p); 03659 glEnd(); 03660 03661 03662 if (G.scene->toolsettings->skgen_options & SKGEN_DISP_EMBED) 03663 { 03664 glColor3f(1, 1, 1); 03665 glBegin(GL_POINTS); 03666 glVertex3fv(arc->head->p); 03667 glVertex3fv(arc->tail->p); 03668 03669 glColor3f(0.5f, 0.5f, 1); 03670 if (arc->bcount) 03671 { 03672 initArcIterator(iter, arc, arc->head); 03673 for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter)) 03674 { 03675 glVertex3fv(iter->p); 03676 } 03677 } 03678 glEnd(); 03679 } 03680 03681 if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX) 03682 { 03683 mid_v3_v3v3(vec, arc->head->p, arc->tail->p); 03684 s += sprintf(s, "%i (%i-%i-%i) ", i, arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group); 03685 03686 if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT) 03687 { 03688 s += sprintf(s, "w:%0.3f ", arc->tail->weight - arc->head->weight); 03689 } 03690 03691 if (G.scene->toolsettings->skgen_options & SKGEN_DISP_LENGTH) 03692 { 03693 s += sprintf(s, "l:%0.3f", arc->length); 03694 } 03695 03696 glColor3f(0, 1, 0); 03697 glRasterPos3fv(vec); 03698 BMF_DrawString( G.fonts, text); 03699 } 03700 03701 if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX) 03702 { 03703 sprintf(text, " %i", arc->head->index); 03704 glRasterPos3fv(arc->head->p); 03705 BMF_DrawString( G.fonts, text); 03706 03707 sprintf(text, " %i", arc->tail->index); 03708 glRasterPos3fv(arc->tail->p); 03709 BMF_DrawString( G.fonts, text); 03710 } 03711 } 03712 glEnable(GL_DEPTH_TEST); 03713 03714 glLineWidth(1.0); 03715 glPointSize(1.0); 03716 } 03717 03718 #endif