00001
00002 #include <OSGConfig.h>
00003
00004
00005 #include <iostream>
00006 #include <stdlib.h>
00007
00008 #include <OSGGL.h>
00009
00010
00011
00012
00013
00014 #include "OSGNodeGraph.h"
00015
00016
00017 using namespace std;
00018
00019 OSG_USING_NAMESPACE
00020
00021
00022 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_DEV)
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 NodeGraph::NodeGraph (void)
00036 {
00037 ;
00038 }
00039
00040
00041
00042
00043
00044
00045
00046
00047 NodeGraph::NodeGraph (const NodeGraph &obj )
00048 : _nodeVec(obj._nodeVec), _edgeMapVec(obj._edgeMapVec)
00049 {
00050 return;
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060 NodeGraph::~NodeGraph (void )
00061 {
00062 clear();
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072 void NodeGraph::init ( int vertexNum, int nodeNum, int reserveEdges )
00073 {
00074 int i;
00075
00076 _nodeVec .resize(nodeNum );
00077 _edgeMapVec.resize(vertexNum);
00078
00079 if(reserveEdges > 0)
00080 {
00081 for(i = 0; i < vertexNum; i++)
00082 {
00083 _edgeMapVec[i].reserve(reserveEdges);
00084 }
00085 }
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 bool NodeGraph::verify (bool printInfo )
00097 {
00098 bool retCode = true;
00099 int i, n = _nodeVec.size();
00100 vector<int> nodeDegree(5,0);
00101 int edgeCount = 0;
00102 map< int, int > connectionMap;
00103 map< int, int >::iterator connectionI;
00104 unsigned nonManifoldCount = 0;
00105
00106 for (i = 0; i < n; i++)
00107 if (_nodeVec[i].index == i)
00108 {
00109 if(_nodeVec[i].degree >= 0 && _nodeVec[i].degree < 4)
00110 {
00111 nodeDegree[_nodeVec[i].degree]++;
00112 }
00113 else
00114 {
00115 if (_nodeVec[i].degree == -1)
00116 nonManifoldCount++;
00117 else
00118 {
00119 FFATAL (( "Invalid degree %d in node %d\n",
00120 _nodeVec[i].degree, i ));
00121 }
00122 }
00123 }
00124 else
00125 if (_nodeVec[i].index == -1)
00126 nodeDegree[4]++;
00127 else {
00128 FFATAL (( "Invalid node index %d for face %d\n",
00129 _nodeVec[i].index, i ));
00130 retCode = false;
00131 }
00132
00133 if (printInfo) {
00134 FNOTICE (( "NodeDegree Count: %d %d %d %d (%d)\n",
00135 nodeDegree[0], nodeDegree[1], nodeDegree[2], nodeDegree[3],
00136 nodeDegree[4] ));
00137
00138 n = _edgeMapVec.size();
00139 for (i = 0; i < n; i++)
00140 edgeCount += _edgeMapVec[i].size();
00141
00142 FNOTICE (( "NonManifold split: %d\n", nonManifoldCount ));
00143 FNOTICE (( "HalfEdgeCount: %d\n", edgeCount ));
00144 }
00145
00146 return retCode;
00147 }
00148
00149
00150 #ifndef WIN32
00151 #define RANDBOOL (random() & 1)
00152 #else
00153 #define RANDBOOL (rand() & 1)
00154 #endif
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 int NodeGraph::createPathVec (vector<Path> &pathVec,
00166 bool OSG_CHECK_ARG(createStrips ),
00167 bool OSG_CHECK_ARG(createFans ),
00168 int OSG_CHECK_ARG(minFanEdgeCount))
00169 {
00170 NodeList nodeList[4], nonManifoldList, *down = 0;
00171 int i,n = _nodeVec.size();
00172 int frontToBackCost, backToFrontCost, cost = 0, nodeLeft = 0;
00173 WalkCase walkCase = START, firstTurn = START;
00174 int degree, lowDegree, entrySide, exitSide;
00175 int pathI = -1;
00176 Node *currentNode = 0, *nextNode = 0;
00177 Edge *firstEdge = 0, *lastEdge = 0, *brotherEdge = 0;
00178 bool tryFlip = true;
00179 int stayCounter = 0, reverseCounter = 0;
00180 list<int>::iterator listI;
00181 list<int>::reverse_iterator listRI;
00182 int pathCost = 0;
00183 int pathEntrySide, pathExitSide;
00184 bool pathWalkRight;
00185
00186 down = 0;
00187 for (i = 0; i < 4; i++) {
00188 nodeList[i].setDown(down);
00189 nodeList[i].setDegree(i);
00190 down = &nodeList[i];
00191 }
00192
00193 for (i = 0; i < n; i++)
00194 if (_nodeVec[i].index >= 0) {
00195 degree = _nodeVec[i].degree;
00196 if (degree >= 0) {
00197 nodeList[degree].add( _nodeVec[i], RANDBOOL );
00198 nodeLeft++;
00199 }
00200 else {
00201 nonManifoldList.push_back( _nodeVec[i] );
00202 }
00203 }
00204
00205 if ((nodeList[1].size() + nodeList[2].size() + nodeList[3].size()) == 0) {
00206 FINFO (("Geometry without any shared vertex, skipping opt.\n"));
00207 nodeLeft = 0;
00208 }
00209
00210 while(nodeLeft || (walkCase == NEW) || (walkCase == FINISH)) {
00211 switch (walkCase) {
00212 case START:
00213 pathI++;
00214 tryFlip = true;
00215 pathVec[pathI].clear();
00216
00217 for (lowDegree = 0; lowDegree < 4; lowDegree++)
00218 if ((currentNode = nodeList[lowDegree].first()))
00219 break;
00220
00221 pathVec[pathI].add(currentNode->index);
00222 currentNode->release();
00223 currentNode->dropNeighbors( RANDBOOL );
00224 cost += 3;
00225 walkCase = NEW;
00226 nodeLeft--;
00227 break;
00228 case NEW:
00229 nextNode = 0;
00230 for (i = 0; i < 3; i++) {
00231 brotherEdge = currentNode->edgeVec[i]->brotherEdge;
00232 if (brotherEdge)
00233 if ( brotherEdge->node->list &&
00234 (!nextNode || (nextNode->list->degree()
00235 > brotherEdge->node->list->degree()))) {
00236 nextNode = brotherEdge->node;
00237 lastEdge = brotherEdge;
00238 firstEdge = lastEdge->brotherEdge;
00239 }
00240 }
00241 if (nextNode) {
00242
00243 pathVec[pathI].type = GL_TRIANGLE_STRIP;
00244 pathVec[pathI].add(firstEdge->edgeSide);
00245 pathVec[pathI].add(lastEdge->edgeSide);
00246 pathVec[pathI].add(nextNode->index);
00247 nextNode->release();
00248 nextNode->dropNeighbors( RANDBOOL );
00249 cost++;
00250 walkCase = RIGHT;
00251 nodeLeft--;
00252 firstTurn = START;
00253 }
00254 else {
00255
00256 pathVec[pathI].type = GL_TRIANGLES;
00257 walkCase = START;
00258 }
00259 break;
00260 case LEFT:
00261 case RIGHT:
00262 currentNode = lastEdge->node;
00263 entrySide = lastEdge->edgeSide;
00264 for (i = 0; i < 2; i++) {
00265 exitSide = ( entrySide + 1 + ((i + int(walkCase)) & 1) ) % 3;
00266 if ( (brotherEdge = currentNode->edgeVec[exitSide]->brotherEdge) &&
00267 (nextNode = brotherEdge->node) && nextNode->list ) {
00268
00269 lastEdge = currentNode->edgeVec[exitSide]->brotherEdge;
00270 pathVec[pathI].add(exitSide);
00271 pathVec[pathI].add(lastEdge->edgeSide);
00272 pathVec[pathI].add(nextNode->index);
00273 nextNode->release();
00274 nextNode->dropNeighbors( RANDBOOL );
00275 walkCase = i ? walkCase : WalkCase((int(walkCase)+1) & 1);
00276 nodeLeft--;
00277 if (firstTurn == START)
00278 firstTurn = ((exitSide+2)%3 == entrySide) ? LEFT : RIGHT;
00279 break;
00280 }
00281 }
00282 if (i == 2) {
00283 if (tryFlip) {
00284 walkCase = firstTurn;
00285 lastEdge = firstEdge;
00286 pathVec[pathI].flip = true;
00287 tryFlip = false;
00288 }
00289 else
00290 walkCase = FINISH;
00291 }
00292 else
00293 if (!nodeLeft)
00294 walkCase = FINISH;
00295 break;
00296 case FINISH:
00297
00298 pathCost = 0;
00299 listI = pathVec[pathI].path.begin();
00300 listI++;
00301 listI++;
00302 pathEntrySide = *listI++;
00303 listI++;
00304 pathWalkRight = true;
00305 pathCost += 3;
00306 while ( listI != pathVec[pathI].path.end()) {
00307 pathCost++;
00308 pathExitSide = *listI++;
00309 if (pathWalkRight == true) {
00310 if (((pathEntrySide+1)%3 == pathExitSide))
00311 pathCost++;
00312 else
00313 pathWalkRight = false;
00314 }
00315 else {
00316 if ((pathEntrySide+1)%3 == pathExitSide)
00317 pathWalkRight = true;
00318 else
00319 pathCost++;
00320 }
00321 pathEntrySide = *listI++;
00322 *listI++;
00323 }
00324 frontToBackCost = ++pathCost;
00325
00326
00327 pathCost = 0;
00328 listRI = pathVec[pathI].path.rbegin();
00329 listRI++;
00330 listRI++;
00331 pathEntrySide = *listRI++;
00332 listRI++;
00333 pathWalkRight = true;
00334 pathCost += 3;
00335 while ( listRI != pathVec[pathI].path.rend()) {
00336 pathCost++;
00337 pathExitSide = *listRI++;
00338 if (pathWalkRight == true) {
00339 if (((pathEntrySide+1)%3 == pathExitSide))
00340 pathCost++;
00341 else
00342 pathWalkRight = false;
00343 }
00344 else {
00345 if ((pathEntrySide+1)%3 == pathExitSide)
00346 pathWalkRight = true;
00347 else
00348 pathCost++;
00349 }
00350 pathEntrySide = *listRI++;
00351 *listRI++;
00352 }
00353 backToFrontCost = ++pathCost;
00354
00355
00356 if (frontToBackCost > backToFrontCost) {
00357 reverseCounter++;
00358 pathVec[pathI].flip = true;
00359
00360 cost += backToFrontCost - 4;
00361 }
00362 else {
00363 stayCounter++;
00364 pathVec[pathI].flip = false;
00365 cost += frontToBackCost - 4;
00366 }
00367 walkCase = START;
00368 break;
00369 default:
00370 break;
00371 }
00372 }
00373
00374 if (cost) {
00375 if ((currentNode = nonManifoldList.first())) {
00376 FNOTICE (( "Optimize nonmanifold mesh: buffer %d triangles\n",
00377 nonManifoldList.size() ));
00378 pathVec[++pathI].type = GL_TRIANGLES;
00379 for ( ; currentNode; currentNode = currentNode->next ) {
00380 cost += 3;
00381 pathVec[pathI].path.push_back(currentNode->index);
00382 }
00383 }
00384 pathVec[++pathI].clear();
00385 }
00386
00387 return cost;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397 int NodeGraph::getPrimitive ( Path &path, vector< int > & primitive )
00398 {
00399 int pi;
00400 unsigned j, cost = 0;
00401 int index, firstIndex, firstSide, entrySide, exitSide;
00402 Node *node;
00403 bool walkRight;
00404 list<int>::iterator listI;
00405 list<int>::reverse_iterator listRI;
00406
00407 primitive.clear();
00408
00409 if (path.path.empty())
00410 cost = 0;
00411 else {
00412
00413 if (path.type == GL_TRIANGLES) {
00414
00415
00416 for (listI = path.path.begin(); listI != path.path.end(); ++listI) {
00417 node = &(_nodeVec[*listI]);
00418 primitive.push_back(node->vertex[0]);
00419 primitive.push_back(node->vertex[1]);
00420 primitive.push_back(node->vertex[2]);
00421 cost += 3;
00422 }
00423 }
00424 else {
00425
00426
00427 if (path.flip) {
00428 listRI = path.path.rbegin();
00429 firstIndex = *listRI++;
00430 firstSide = *listRI++;
00431 entrySide = *listRI++;
00432 index = *listRI++;
00433 walkRight = true;
00434 cost += 3;
00435 for (j = 0; j < 3; j++) {
00436 pi = getEndOfEdge(firstIndex,(firstSide+1+j) % 3);
00437 primitive.push_back(pi);
00438 }
00439 while ( listRI != path.path.rend()) {
00440 exitSide = *listRI++;
00441 if (walkRight == true) {
00442 if (((entrySide+1)%3 == exitSide)) {
00443 pi = getEndOfEdge(index,entrySide);
00444 primitive.push_back(pi);
00445 pi = getEndOfEdge(index,exitSide);
00446 primitive.push_back(pi);
00447 cost += 2;
00448 }
00449 else
00450 if (((entrySide+2)%3 == exitSide)) {
00451 walkRight = false;
00452 pi = getStartOfEdge(index,exitSide);
00453 primitive.push_back(pi);
00454 cost++;
00455 }
00456 else
00457 cerr << "ERROR: entrySide == exitSide" << endl;
00458 }
00459 else {
00460 if ((entrySide+1)%3 == exitSide) {
00461 walkRight = true;
00462 pi = getEndOfEdge(index,exitSide);
00463 primitive.push_back(pi);
00464 cost++;
00465 }
00466 else
00467 if ((entrySide+2)%3 == exitSide) {
00468 pi = getStartOfEdge(index,entrySide);
00469 primitive.push_back(pi);
00470 pi = getStartOfEdge(index,exitSide);
00471 primitive.push_back(pi);
00472 cost += 2;
00473 }
00474 else
00475 cerr << "ERROR: entrySide == exitSide" << endl;
00476 }
00477 entrySide = *listRI++;
00478 index = *listRI++;
00479 }
00480 pi = getEndOfEdge(index,(entrySide+1)%3);
00481 primitive.push_back(pi);
00482 cost++;
00483 }
00484 else {
00485 listI = path.path.begin();
00486 firstIndex = *listI++;
00487 firstSide = *listI++;
00488 entrySide = *listI++;
00489 index = *listI++;
00490 walkRight = true;
00491 cost += 3;
00492 for (j = 0; j < 3; j++) {
00493 pi = getEndOfEdge(firstIndex,(firstSide+1+j) % 3);
00494 primitive.push_back(pi);
00495 }
00496 while ( listI != path.path.end()) {
00497 exitSide = *listI++;
00498 if (walkRight == true) {
00499 if (((entrySide+1)%3 == exitSide)) {
00500 pi = getEndOfEdge(index,entrySide);
00501 primitive.push_back(pi);
00502 pi = getEndOfEdge(index,exitSide);
00503 primitive.push_back(pi);
00504 cost += 2;
00505 }
00506 else
00507 if (((entrySide+2)%3 == exitSide)) {
00508 walkRight = false;
00509 pi = getStartOfEdge(index,exitSide);
00510 primitive.push_back(pi);
00511 cost++;
00512 }
00513 else
00514 cerr << "ERROR: entrySide == exitSide" << endl;
00515 }
00516 else {
00517 if ((entrySide+1)%3 == exitSide) {
00518 walkRight = true;
00519 pi = getEndOfEdge(index,exitSide);
00520 primitive.push_back(pi);
00521 cost++;
00522 }
00523 else
00524 if ((entrySide+2)%3 == exitSide) {
00525 pi = getStartOfEdge(index,entrySide);
00526 primitive.push_back(pi);
00527 pi = getStartOfEdge(index,exitSide);
00528 primitive.push_back(pi);
00529 cost += 2;
00530 }
00531 else
00532 cerr << "ERROR: entrySide == exitSide" << endl;
00533 }
00534 entrySide = *listI++;
00535 index = *listI++;
00536 }
00537 pi = getEndOfEdge(index,(entrySide+1)%3);
00538 primitive.push_back(pi);
00539 cost++;
00540 }
00541 }
00542 }
00543
00544 return cost;
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 int NodeGraph::getEdges (list <IndexEdge> & edgeList)
00556 {
00557 int i, n;
00558 EdgeMap::iterator eMI;
00559 int vs, ve;
00560 n = _edgeMapVec.size();
00561 int edgeCount = 0;
00562
00563 for (i = 0; i < n; i++)
00564 for ( eMI = _edgeMapVec[i].begin(); eMI != _edgeMapVec[i].end(); ++eMI) {
00565 vs = (*eMI)->vertexStart;
00566 ve = (*eMI)->vertexEnd;
00567
00568 if (!(*eMI)->brotherEdge || (ve < vs)) {
00569 edgeList.push_back ( IndexEdge(ve,vs) );
00570 edgeCount++;
00571 }
00572 }
00573
00574 return edgeCount;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584 void NodeGraph::clear (void)
00585 {
00586 EdgeMap::iterator eI;
00587 int i, n = _edgeMapVec.size();
00588
00589 for (i = 0; i < n; i++) {
00590 for (eI = _edgeMapVec[i].begin(); eI != _edgeMapVec[i].end(); ++eI)
00591 delete (*eI);
00592 }
00593
00594 _edgeMapVec.clear();
00595 _nodeVec.clear();
00596 }
00597
00598
00599 #endif // remove from all but dev docs