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): Tao Ju 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00023 #include "octree.h" 00024 #include <Eigen/Dense> 00025 #include <limits> 00026 #include <time.h> 00027 00034 /* set to non-zero value to enable debugging output */ 00035 #define DC_DEBUG 0 00036 00037 #if DC_DEBUG 00038 /* enable debug printfs */ 00039 #define dc_printf printf 00040 #else 00041 /* disable debug printfs */ 00042 #define dc_printf(...) do {} while(0) 00043 #endif 00044 00045 Octree::Octree( ModelReader* mr, 00046 DualConAllocOutput alloc_output_func, 00047 DualConAddVert add_vert_func, 00048 DualConAddQuad add_quad_func, 00049 DualConFlags flags, DualConMode dualcon_mode, int depth, 00050 float threshold, float sharpness ) 00051 : use_flood_fill(flags & DUALCON_FLOOD_FILL), 00052 /* note on `use_manifold': 00053 00054 After playing around with this option, the only case I could 00055 find where this option gives different results is on 00056 relatively thin corners. Sometimes along these corners two 00057 vertices from seperate sides will be placed in the same 00058 position, so hole gets filled with a 5-sided face, where two 00059 of those vertices are in the same 3D location. If 00060 `use_manifold' is disabled, then the modifier doesn't 00061 generate two separate vertices so the results end up as all 00062 quads. 00063 00064 Since the results are just as good with all quads, there 00065 doesn't seem any reason to allow this to be toggled in 00066 Blender. -nicholasbishop 00067 */ 00068 use_manifold(false), 00069 hermite_num(sharpness), 00070 mode(dualcon_mode), 00071 alloc_output(alloc_output_func), 00072 add_vert(add_vert_func), 00073 add_quad(add_quad_func) 00074 { 00075 this->thresh = threshold ; 00076 this->reader = mr ; 00077 this->dimen = 1 << GRID_DIMENSION ; 00078 this->range = reader->getBoundingBox( this->origin ) ; 00079 this->nodeCount = this->nodeSpace = 0; 00080 this->maxDepth = depth ; 00081 this->mindimen = ( dimen >> maxDepth ) ; 00082 this->minshift = ( GRID_DIMENSION - maxDepth ) ; 00083 this->buildTable( ) ; 00084 00085 flood_bytes = use_flood_fill ? FLOOD_FILL_BYTES : 0; 00086 leaf_extra_bytes = flood_bytes + CINDY_BYTES; 00087 00088 #ifdef USE_HERMIT 00089 leaf_node_bytes = 7 + leaf_extra_bytes; 00090 #else 00091 leaf_node_bytes = 3 + leaf_extra_bytes; 00092 #endif 00093 00094 #ifdef QIANYI 00095 dc_printf("Origin: (%f %f %f), Dimension: %f\n", origin[0], origin[1], origin[2], range) ; 00096 #endif 00097 00098 this->maxTrianglePerCell = 0 ; 00099 00100 // Initialize memory 00101 #ifdef IN_VERBOSE_MODE 00102 dc_printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2] ) ; 00103 dc_printf("Initialize memory...\n") ; 00104 #endif 00105 initMemory( ) ; 00106 this->root = createInternal( 0 ) ; 00107 00108 // Read MC table 00109 #ifdef IN_VERBOSE_MODE 00110 dc_printf("Reading contour table...\n") ; 00111 #endif 00112 this->cubes = new Cubes(); 00113 00114 } 00115 00116 Octree::~Octree( ) 00117 { 00118 freeMemory( ) ; 00119 } 00120 00121 void Octree::scanConvert() 00122 { 00123 // Scan triangles 00124 #if DC_DEBUG 00125 clock_t start, finish ; 00126 start = clock( ) ; 00127 #endif 00128 00129 this->addTrian( ) ; 00130 this->resetMinimalEdges( ) ; 00131 this->preparePrimalEdgesMask( this->root ) ; 00132 00133 #if DC_DEBUG 00134 finish = clock( ) ; 00135 dc_printf("Time taken: %f seconds \n", 00136 (double)(finish - start) / CLOCKS_PER_SEC ) ; 00137 #endif 00138 00139 // Generate signs 00140 // Find holes 00141 #if DC_DEBUG 00142 dc_printf("Patching...\n") ; 00143 start = clock( ) ; 00144 #endif 00145 this->trace( ) ; 00146 #if DC_DEBUG 00147 finish = clock( ) ; 00148 dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ; 00149 #ifdef IN_VERBOSE_MODE 00150 dc_printf("Holes: %d Average Length: %f Max Length: %d \n", numRings, (float)totRingLengths / (float) numRings, maxRingLength ) ; 00151 #endif 00152 #endif 00153 00154 // Check again 00155 int tnumRings = numRings ; 00156 this->trace( ) ; 00157 #ifdef IN_VERBOSE_MODE 00158 dc_printf("Holes after patching: %d \n", numRings) ; 00159 #endif 00160 numRings = tnumRings ; 00161 00162 #if DC_DEBUG 00163 dc_printf("Building signs...\n") ; 00164 start = clock( ) ; 00165 #endif 00166 this->buildSigns( ) ; 00167 #if DC_DEBUG 00168 finish = clock( ) ; 00169 dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ; 00170 #endif 00171 00172 if(use_flood_fill) { 00173 /* 00174 start = clock( ) ; 00175 this->floodFill( ) ; 00176 // Check again 00177 tnumRings = numRings ; 00178 this->trace( ) ; 00179 dc_printf("Holes after filling: %d \n", numRings) ; 00180 numRings = tnumRings ; 00181 this->buildSigns( ) ; 00182 finish = clock( ) ; 00183 dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ; 00184 */ 00185 #if DC_DEBUG 00186 start = clock( ) ; 00187 dc_printf("Removing components...\n"); 00188 #endif 00189 this->floodFill( ) ; 00190 this->buildSigns( ) ; 00191 // dc_printf("Checking...\n"); 00192 // this->floodFill( ) ; 00193 #if DC_DEBUG 00194 finish = clock( ) ; 00195 dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ; 00196 #endif 00197 } 00198 00199 // Output 00200 #ifdef OUTPUT_REPAIRED 00201 #if DC_DEBUG 00202 start = clock( ) ; 00203 #endif 00204 writeOut(); 00205 #if DC_DEBUG 00206 finish = clock( ) ; 00207 #endif 00208 // dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ; 00209 #ifdef CINDY 00210 this->writeTags( "tags.txt" ) ; 00211 dc_printf("Tags output to tags.txt\n") ; 00212 #endif 00213 00214 #endif 00215 00216 // Print info 00217 #ifdef IN_VERBOSE_MODE 00218 printMemUsage( ) ; 00219 #endif 00220 } 00221 00222 #if 0 00223 void Octree::writeOut( char* fname ) 00224 { 00225 dc_printf( "\n" ) ; 00226 if ( strstr( fname, ".ply" ) != NULL ) 00227 { 00228 dc_printf("Writing PLY file format.\n") ; 00229 this->outType = 1 ; 00230 writePLY( fname ) ; 00231 } 00232 else if ( strstr( fname, ".off" ) != NULL ) 00233 { 00234 dc_printf("Writing OFF file format.\n") ; 00235 this->outType = 0 ; 00236 writeOFF( fname ) ; 00237 } 00238 else if ( strstr( fname, ".sof" ) != NULL ) 00239 { 00240 dc_printf("Writing Signed Octree File format.\n") ; 00241 this->outType = 2 ; 00242 writeOctree( fname ) ; 00243 } 00244 else if ( strstr( fname, ".dcf" ) != NULL ) 00245 { 00246 #ifdef USE_HERMIT 00247 dc_printf("Writing Dual Contouring File format.\n") ; 00248 this->outType = 3 ; 00249 writeDCF( fname ) ; 00250 #else 00251 dc_printf("Can not write Dual Contouring File format in non-DC mode.\n") ; 00252 #endif 00253 } 00254 #ifdef USE_HERMIT 00255 else if ( strstr( fname, ".sog" ) != NULL ) 00256 { 00257 dc_printf("Writing signed octree with geometry.\n") ; 00258 this->outType = 4 ; 00259 writeOctreeGeom( fname ) ; 00260 } 00261 #endif 00262 /* 00263 else if ( strstr( fname, ".sof" ) != NULL ) 00264 { 00265 dc_printf("Writing SOF file format.\n") ; 00266 this->outType = 2 ; 00267 writeOctree( fname ) ; 00268 } 00269 */ 00270 else 00271 { 00272 dc_printf("Unknown output format.\n") ; 00273 } 00274 00275 } 00276 #endif 00277 00278 void Octree::initMemory( ) 00279 { 00280 #ifdef USE_HERMIT 00281 const int leaf_node_bytes = 7; 00282 #else 00283 const int leaf_node_bytes = 3; 00284 #endif 00285 00286 if(use_flood_fill) { 00287 const int bytes = leaf_node_bytes + CINDY_BYTES + FLOOD_FILL_BYTES; 00288 this->leafalloc[ 0 ] = new MemoryAllocator< bytes > ( ) ; 00289 this->leafalloc[ 1 ] = new MemoryAllocator< bytes + EDGE_BYTES > ( ) ; 00290 this->leafalloc[ 2 ] = new MemoryAllocator< bytes + EDGE_BYTES * 2 > ( ) ; 00291 this->leafalloc[ 3 ] = new MemoryAllocator< bytes + EDGE_BYTES * 3 > ( ) ; 00292 } 00293 else { 00294 const int bytes = leaf_node_bytes + CINDY_BYTES; 00295 this->leafalloc[ 0 ] = new MemoryAllocator< bytes > ( ) ; 00296 this->leafalloc[ 1 ] = new MemoryAllocator< bytes + EDGE_BYTES > ( ) ; 00297 this->leafalloc[ 2 ] = new MemoryAllocator< bytes + EDGE_BYTES * 2 > ( ) ; 00298 this->leafalloc[ 3 ] = new MemoryAllocator< bytes + EDGE_BYTES * 3 > ( ) ; 00299 } 00300 00301 this->alloc[ 0 ] = new MemoryAllocator< INTERNAL_NODE_BYTES > ( ) ; 00302 this->alloc[ 1 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES > ( ) ; 00303 this->alloc[ 2 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*2 > ( ) ; 00304 this->alloc[ 3 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*3 > ( ) ; 00305 this->alloc[ 4 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*4 > ( ) ; 00306 this->alloc[ 5 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*5 > ( ) ; 00307 this->alloc[ 6 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*6 > ( ) ; 00308 this->alloc[ 7 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*7 > ( ) ; 00309 this->alloc[ 8 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*8 > ( ) ; 00310 } 00311 00312 void Octree::freeMemory( ) 00313 { 00314 for ( int i = 0 ; i < 9 ; i ++ ) 00315 { 00316 alloc[i]->destroy() ; 00317 delete alloc[i] ; 00318 } 00319 00320 for ( int i = 0 ; i < 4 ; i ++ ) 00321 { 00322 leafalloc[i]->destroy() ; 00323 delete leafalloc[i] ; 00324 } 00325 } 00326 00327 void Octree::printMemUsage( ) 00328 { 00329 int totalbytes = 0 ; 00330 dc_printf("********* Internal nodes: \n") ; 00331 for ( int i = 0 ; i < 9 ; i ++ ) 00332 { 00333 this->alloc[ i ]->printInfo() ; 00334 00335 totalbytes += alloc[i]->getAll( ) * alloc[i]->getBytes() ; 00336 } 00337 dc_printf("********* Leaf nodes: \n") ; 00338 int totalLeafs = 0 ; 00339 for ( int i = 0 ; i < 4 ; i ++ ) 00340 { 00341 this->leafalloc[ i ]->printInfo() ; 00342 00343 totalbytes += leafalloc[i]->getAll( ) * leafalloc[i]->getBytes() ; 00344 totalLeafs += leafalloc[i]->getAllocated() ; 00345 } 00346 00347 dc_printf("Total allocated bytes on disk: %d \n", totalbytes) ; 00348 dc_printf("Total leaf nodes: %d\n", totalLeafs ) ; 00349 } 00350 00351 void Octree::resetMinimalEdges( ) 00352 { 00353 this->cellProcParity( this->root, 0, maxDepth ) ; 00354 } 00355 00356 void Octree::writeModel( char* fname ) 00357 { 00358 reader->reset() ; 00359 00360 int nFace = reader->getNumTriangles() ; 00361 Triangle* trian ; 00362 // int unitcount = 10000; 00363 int count = 0 ; 00364 int nVert = nFace * 3 ; 00365 FILE* modelfout = fopen( "model.off", "w" ) ; 00366 fprintf( modelfout, "OFF\n" ) ; 00367 fprintf( modelfout, "%d %d 0\n", nVert, nFace ) ; 00368 00369 //int total = this->reader->getNumTriangles() ; 00370 dc_printf( "Start writing model to OFF...\n" ) ; 00371 srand(0) ; 00372 while ( ( trian = reader->getNextTriangle() ) != NULL ) 00373 { 00374 // Drop polygons 00375 { 00376 int i, j ; 00377 00378 // Blow up the triangle 00379 float mid[3] = {0, 0, 0} ; 00380 for ( i = 0 ; i < 3 ; i ++ ) 00381 for ( j = 0 ; j < 3 ; j ++ ) 00382 { 00383 trian->vt[i][j] = dimen * ( trian->vt[i][j] - origin[j] ) / range ; 00384 00385 mid[j] += trian->vt[i][j] / 3 ; 00386 } 00387 00388 // Generate projections 00389 // LONG cube[2][3] = { { 0, 0, 0 }, { dimen, dimen, dimen } } ; 00390 int trig[3][3] ; 00391 00392 // Blowing up the triangle to the grid 00393 for ( i = 0 ; i < 3 ; i ++ ) 00394 for ( j = 0 ; j < 3 ; j ++ ) 00395 { 00396 trig[i][j] = (int) (trian->vt[i][j]) ; 00397 // Perturb end points, if set so 00398 } 00399 00400 00401 for ( i = 0 ; i < 3 ; i ++ ) 00402 { 00403 fprintf( modelfout, "%f %f %f\n", 00404 (float)(((double) trig[i][0] / dimen) * range + origin[0]) , 00405 (float)(((double) trig[i][1] / dimen) * range + origin[1]) , 00406 (float)(((double) trig[i][2] / dimen) * range + origin[2]) ) ; 00407 } 00408 } 00409 delete trian ; 00410 00411 count ++ ; 00412 00413 } 00414 00415 for ( int i = 0 ; i < nFace ; i ++ ) 00416 { 00417 fprintf( modelfout, "3 %d %d %d\n", 3 * i + 2, 3 * i + 1, 3 * i ) ; 00418 } 00419 00420 fclose( modelfout ) ; 00421 00422 } 00423 00424 #ifdef CINDY 00425 void Octree::writeTags( char* fname ) 00426 { 00427 FILE* fout = fopen( fname, "w" ) ; 00428 00429 clearCindyBits( root, maxDepth ) ; 00430 readVertices() ; 00431 outputTags( root, maxDepth, fout ) ; 00432 00433 fclose ( fout ) ; 00434 } 00435 00436 void Octree::readVertices( ) 00437 { 00438 int total = this->reader->getNumVertices() ; 00439 reader->reset() ; 00440 float v[3] ; 00441 int st[3] = {0,0,0}; 00442 int unitcount = 1000 ; 00443 dc_printf( "\nRead in original %d vertices...\n", total ) ; 00444 00445 for ( int i = 0 ; i < total ; i ++ ) 00446 { 00447 reader->getNextVertex( v ) ; 00448 // Blowing up the triangle to the grid 00449 float mid[3] = {0, 0, 0} ; 00450 for ( int j = 0 ; j < 3 ; j ++ ) 00451 { 00452 v[j] = dimen * ( v[j] - origin[j] ) / range ; 00453 } 00454 00455 // dc_printf("vertex: %f %f %f, dimen: %d\n", v[0], v[1], v[2], dimen ) ; 00456 readVertex ( root, st, dimen, maxDepth, v, i ) ; 00457 00458 00459 if ( i % unitcount == 0 ) 00460 { 00461 putchar ( 13 ) ; 00462 00463 switch ( ( i / unitcount ) % 4 ) 00464 { 00465 case 0 : dc_printf("-"); 00466 break ; 00467 case 1 : dc_printf("/") ; 00468 break ; 00469 case 2 : dc_printf("|"); 00470 break ; 00471 case 3 : dc_printf("\\") ; 00472 break ; 00473 } 00474 00475 float percent = (float) i / total ; 00476 /* 00477 int totbars = 50 ; 00478 int bars = (int)( percent * totbars ) ; 00479 for ( int i = 0 ; i < bars ; i ++ ) 00480 { 00481 putchar( 219 ) ; 00482 } 00483 for ( i = bars ; i < totbars ; i ++ ) 00484 { 00485 putchar( 176 ) ; 00486 } 00487 */ 00488 00489 dc_printf(" %d vertices: ", i ) ; 00490 dc_printf( " %f%% complete.", 100 * percent ) ; 00491 } 00492 00493 } 00494 putchar ( 13 ) ; 00495 dc_printf(" \n"); 00496 } 00497 00498 void Octree::readVertex( UCHAR* node, int st[3], int len, int height, float v[3], int index ) 00499 { 00500 int nst[3] ; 00501 nst[0] = ( (int) v[0] / mindimen ) * mindimen ; 00502 nst[1] = ( (int) v[1] / mindimen ) * mindimen ; 00503 nst[2] = ( (int) v[2] / mindimen ) * mindimen ; 00504 00505 UCHAR* cell = this->locateLeafCheck( nst ) ; 00506 if ( cell == NULL ) 00507 { 00508 dc_printf("Cell %d %d %d is not found!\n", nst[0]/ mindimen, nst[1]/ mindimen, nst[2]/ mindimen) ; 00509 return ; 00510 } 00511 00512 setOriginalIndex( cell, index ) ; 00513 00514 00515 /* 00516 int i ; 00517 if ( height == 0 ) 00518 { 00519 // Leaf cell, assign index 00520 dc_printf("Setting: %d\n", index ) ; 00521 setOriginalIndex( node, index ) ; 00522 } 00523 else 00524 { 00525 len >>= 1 ; 00526 // Internal cell, check and recur 00527 int x = ( v[0] > st[0] + len ) ? 1 : 0 ; 00528 int y = ( v[1] > st[1] + len ) ? 1 : 0 ; 00529 int z = ( v[2] > st[2] + len ) ? 1 : 0 ; 00530 int child = x * 4 + y * 2 + z ; 00531 00532 int count = 0 ; 00533 for ( i = 0 ; i < 8 ; i ++ ) 00534 { 00535 if ( i == child && hasChild( node, i ) ) 00536 { 00537 int nst[3] ; 00538 nst[0] = st[0] + vertmap[i][0] * len ; 00539 nst[1] = st[1] + vertmap[i][1] * len ; 00540 nst[2] = st[2] + vertmap[i][2] * len ; 00541 00542 dc_printf("Depth: %d -- child %d vertex: %f %f %f in %f %f %f\n", height - 1, child, v[0]/mindimen, v[1]/mindimen, v[2]/mindimen, 00543 nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, len/mindimen ) ; 00544 00545 readVertex( getChild( node, count ), nst, len, height - 1, v, index ) ; 00546 count ++ ; 00547 } 00548 } 00549 } 00550 */ 00551 } 00552 00553 void Octree::outputTags( UCHAR* node, int height, FILE* fout ) 00554 { 00555 int i ; 00556 00557 if ( height == 0 ) 00558 { 00559 // Leaf cell, generate 00560 int smask = getSignMask( node ) ; 00561 00562 if(use_manifold) { 00563 int comps = manifold_table[ smask ].comps ; 00564 if ( comps != 1 ) 00565 { 00566 return ; 00567 } 00568 } 00569 else 00570 { 00571 if ( smask == 0 || smask == 255 ) 00572 { 00573 return ; 00574 } 00575 } 00576 00577 int rindex = getMinimizerIndex( node ) ; 00578 int oindex = getOriginalIndex( node ) ; 00579 00580 if ( oindex >= 0 ) 00581 { 00582 fprintf( fout, "%d: %d\n", rindex, oindex ) ; 00583 } 00584 00585 } 00586 else 00587 { 00588 // Internal cell, recur 00589 int count = 0 ; 00590 for ( i = 0 ; i < 8 ; i ++ ) 00591 { 00592 if ( hasChild( node, i ) ) 00593 { 00594 outputTags( getChild( node, count ), height - 1, fout ) ; 00595 count ++ ; 00596 } 00597 } 00598 } 00599 } 00600 00601 void Octree::clearCindyBits( UCHAR* node, int height ) 00602 { 00603 int i; 00604 00605 if ( height == 0 ) 00606 { 00607 // Leaf cell, 00608 { 00609 setOriginalIndex( node, - 1 ) ; 00610 } 00611 } 00612 else 00613 { 00614 // Internal cell, recur 00615 int count = 0 ; 00616 for ( i = 0 ; i < 8 ; i ++ ) 00617 { 00618 if ( hasChild( node, i ) ) 00619 { 00620 clearCindyBits( getChild( node, count ), height - 1 ) ; 00621 count ++ ; 00622 } 00623 } 00624 } 00625 } 00626 #endif 00627 00628 void Octree::addTrian( ) 00629 { 00630 Triangle* trian ; 00631 int count = 0 ; 00632 00633 #if DC_DEBUG 00634 int total = this->reader->getNumTriangles() ; 00635 int unitcount = 1000 ; 00636 dc_printf( "\nScan converting to depth %d...\n", maxDepth ) ; 00637 #endif 00638 00639 srand(0) ; 00640 00641 while ( ( trian = reader->getNextTriangle() ) != NULL ) 00642 { 00643 // Drop triangles 00644 { 00645 addTrian ( trian, count ) ; 00646 } 00647 delete trian ; 00648 00649 count ++ ; 00650 00651 #if DC_DEBUG 00652 if ( count % unitcount == 0 ) 00653 { 00654 putchar ( 13 ) ; 00655 00656 switch ( ( count / unitcount ) % 4 ) 00657 { 00658 case 0 : dc_printf("-"); 00659 break ; 00660 case 1 : dc_printf("/") ; 00661 break ; 00662 case 2 : dc_printf("|"); 00663 break ; 00664 case 3 : dc_printf("\\") ; 00665 break ; 00666 } 00667 00668 float percent = (float) count / total ; 00669 00670 /* 00671 int totbars = 50 ; 00672 int bars = (int)( percent * totbars ) ; 00673 for ( int i = 0 ; i < bars ; i ++ ) 00674 { 00675 putchar( 219 ) ; 00676 } 00677 for ( i = bars ; i < totbars ; i ++ ) 00678 { 00679 putchar( 176 ) ; 00680 } 00681 */ 00682 00683 dc_printf(" %d triangles: ", count ) ; 00684 dc_printf( " %f%% complete.", 100 * percent ) ; 00685 } 00686 #endif 00687 00688 } 00689 putchar ( 13 ) ; 00690 } 00691 00692 void Octree::addTrian( Triangle* trian, int triind ) 00693 { 00694 int i, j ; 00695 00696 // Blowing up the triangle to the grid 00697 float mid[3] = {0, 0, 0} ; 00698 for ( i = 0 ; i < 3 ; i ++ ) 00699 for ( j = 0 ; j < 3 ; j ++ ) 00700 { 00701 trian->vt[i][j] = dimen * ( trian->vt[i][j] - origin[j] ) / range ; 00702 mid[j] += trian->vt[i][j] / 3 ; 00703 } 00704 00705 // Generate projections 00706 LONG cube[2][3] = { { 0, 0, 0 }, { dimen, dimen, dimen } } ; 00707 LONG trig[3][3] ; 00708 00709 for ( i = 0 ; i < 3 ; i ++ ) 00710 for ( j = 0 ; j < 3 ; j ++ ) 00711 { 00712 trig[i][j] = (LONG) (trian->vt[i][j]) ; 00713 // Perturb end points, if set so 00714 } 00715 00716 // Add to the octree 00717 // int start[3] = { 0, 0, 0 } ; 00718 LONG errorvec = (LONG) ( 0 ) ; 00719 Projections* proj = new Projections( cube, trig, errorvec, triind ) ; 00720 root = addTrian( root, proj, maxDepth ) ; 00721 00722 delete proj->inherit ; 00723 delete proj ; 00724 } 00725 00726 00727 UCHAR* Octree::addTrian( UCHAR* node, Projections* p, int height ) 00728 { 00729 int i ; 00730 int vertdiff[8][3] = {{0,0,0},{0,0,1},{0,1,-1},{0,0,1},{1,-1,-1},{0,0,1},{0,1,-1},{0,0,1}} ; 00731 UCHAR boxmask = p->getBoxMask( ) ; 00732 Projections* subp = new Projections( p ) ; 00733 00734 int count = 0 ; 00735 int tempdiff[3] = {0,0,0} ; 00736 for ( i = 0 ; i < 8 ; i ++ ) 00737 { 00738 tempdiff[0] += vertdiff[i][0] ; 00739 tempdiff[1] += vertdiff[i][1] ; 00740 tempdiff[2] += vertdiff[i][2] ; 00741 00742 /* Quick pruning using bounding box */ 00743 if ( boxmask & ( 1 << i ) ) 00744 { 00745 subp->shift( tempdiff ) ; 00746 tempdiff[0] = tempdiff[1] = tempdiff[2] = 0 ; 00747 00748 /* Pruning using intersection test */ 00749 if ( subp->isIntersecting() ) 00750 // if ( subp->getIntersectionMasks( cedgemask, edgemask ) ) 00751 { 00752 if ( ! hasChild( node, i ) ) 00753 { 00754 if ( height == 1 ) 00755 { 00756 node = addLeafChild( node, i, count, createLeaf(0) ) ; 00757 } 00758 else 00759 { 00760 node = addInternalChild( node, i, count, createInternal(0) ) ; 00761 } 00762 } 00763 UCHAR* chd = getChild( node, count ) ; 00764 00765 if ( ! isLeaf( node, i ) ) 00766 { 00767 // setChild( node, count, addTrian ( chd, subp, height - 1, vertmask[i], edgemask ) ) ; 00768 setChild( node, count, addTrian ( chd, subp, height - 1 ) ) ; 00769 } 00770 else 00771 { 00772 setChild( node, count, updateCell( chd, subp ) ) ; 00773 } 00774 } 00775 } 00776 00777 if ( hasChild( node, i ) ) 00778 { 00779 count ++ ; 00780 } 00781 } 00782 00783 delete subp ; 00784 return node ; 00785 } 00786 00787 UCHAR* Octree::updateCell( UCHAR* node, Projections* p ) 00788 { 00789 int i ; 00790 00791 // Edge connectivity 00792 int mask[3] = { 0, 4, 8 } ; 00793 int oldc = 0, newc = 0 ; 00794 float offs[3] ; 00795 #ifdef USE_HERMIT 00796 float a[3], b[3], c[3] ; 00797 #endif 00798 00799 for ( i = 0 ; i < 3 ; i ++ ) 00800 { 00801 if ( ! getEdgeParity( node, mask[i] ) ) 00802 { 00803 if ( p->isIntersectingPrimary( i ) ) 00804 { 00805 // this->actualQuads ++ ; 00806 setEdge( node, mask[i] ) ; 00807 offs[ newc ] = p->getIntersectionPrimary( i ) ; 00808 #ifdef USE_HERMIT 00809 a[ newc ] = (float) p->inherit->norm[0] ; 00810 b[ newc ] = (float) p->inherit->norm[1] ; 00811 c[ newc ] = (float) p->inherit->norm[2] ; 00812 #endif 00813 newc ++ ; 00814 } 00815 } 00816 else 00817 { 00818 #ifndef USE_HERMIT 00819 offs[ newc ] = getEdgeOffset( node, oldc ) ; 00820 #else 00821 offs[ newc ] = getEdgeOffsetNormal( node, oldc, a[ newc ], b[ newc ], c[ newc ] ) ; 00822 #endif 00823 00824 // if ( p->isIntersectingPrimary( i ) ) 00825 { 00826 // dc_printf("Multiple intersections!\n") ; 00827 00828 // setPatchEdge( node, i ) ; 00829 } 00830 00831 oldc ++ ; 00832 newc ++ ; 00833 } 00834 } 00835 00836 if ( newc > oldc ) 00837 { 00838 // New offsets added, update this node 00839 #ifndef USE_HERMIT 00840 node = updateEdgeOffsets( node, oldc, newc, offs ) ; 00841 #else 00842 node = updateEdgeOffsetsNormals( node, oldc, newc, offs, a, b, c ) ; 00843 #endif 00844 } 00845 00846 00847 00848 return node ; 00849 } 00850 00851 void Octree::preparePrimalEdgesMask( UCHAR* node ) 00852 { 00853 int count = 0 ; 00854 for ( int i = 0 ; i < 8 ; i ++ ) 00855 { 00856 if ( hasChild( node, i ) ) 00857 { 00858 if ( isLeaf( node, i ) ) 00859 { 00860 createPrimalEdgesMask( getChild( node, count ) ) ; 00861 } 00862 else 00863 { 00864 preparePrimalEdgesMask( getChild( node, count ) ) ; 00865 } 00866 00867 count ++ ; 00868 } 00869 } 00870 } 00871 00872 void Octree::trace( ) 00873 { 00874 int st[3] = { 0, 0, 0, } ; 00875 this->numRings = 0 ; 00876 this->totRingLengths = 0 ; 00877 this->maxRingLength = 0 ; 00878 00879 PathList* chdpath = NULL ; 00880 this->root = trace( this->root, st, dimen, maxDepth, chdpath ) ; 00881 00882 if ( chdpath != NULL ) 00883 { 00884 dc_printf("there are incomplete rings.\n") ; 00885 printPaths( chdpath ) ; 00886 }; 00887 } 00888 00889 UCHAR* Octree::trace( UCHAR* node, int* st, int len, int depth, PathList*& paths) 00890 { 00891 UCHAR* newnode = node ; 00892 len >>= 1 ; 00893 PathList* chdpaths[ 8 ] ; 00894 UCHAR* chd[ 8 ] ; 00895 int nst[ 8 ][ 3 ] ; 00896 int i, j ; 00897 00898 // Get children paths 00899 int chdleaf[ 8 ] ; 00900 fillChildren( newnode, chd, chdleaf ) ; 00901 00902 // int count = 0 ; 00903 for ( i = 0 ; i < 8 ; i ++ ) 00904 { 00905 for ( j = 0 ; j < 3 ; j ++ ) 00906 { 00907 nst[ i ][ j ] = st[ j ] + len * vertmap[ i ][ j ] ; 00908 } 00909 00910 if ( chd[ i ] == NULL || isLeaf( node, i ) ) 00911 { 00912 chdpaths[ i ] = NULL ; 00913 } 00914 else 00915 { 00916 trace( chd[ i ], nst[i], len, depth - 1, chdpaths[ i ] ) ; 00917 } 00918 } 00919 00920 // Get connectors on the faces 00921 PathList* conn[ 12 ] ; 00922 UCHAR* nf[2] ; 00923 int lf[2] ; 00924 int df[2] = { depth - 1, depth - 1 } ; 00925 int* nstf[ 2 ]; 00926 00927 fillChildren( newnode, chd, chdleaf ) ; 00928 00929 for ( i = 0 ; i < 12 ; i ++ ) 00930 { 00931 int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] }; 00932 00933 for ( int j = 0 ; j < 2 ; j ++ ) 00934 { 00935 lf[j] = chdleaf[ c[j] ] ; 00936 nf[j] = chd[ c[j] ] ; 00937 nstf[j] = nst[ c[j] ] ; 00938 } 00939 00940 conn[ i ] = NULL ; 00941 00942 findPaths( nf, lf, df, nstf, depth - 1, cellProcFaceMask[ i ][ 2 ], conn[ i ] ) ; 00943 00944 //if ( conn[i] ) 00945 //{ 00946 // printPath( conn[i] ) ; 00947 //} 00948 } 00949 00950 // Connect paths 00951 PathList* rings = NULL ; 00952 combinePaths( chdpaths[0], chdpaths[1], conn[8], rings ) ; 00953 combinePaths( chdpaths[2], chdpaths[3], conn[9], rings ) ; 00954 combinePaths( chdpaths[4], chdpaths[5], conn[10], rings ) ; 00955 combinePaths( chdpaths[6], chdpaths[7], conn[11], rings ) ; 00956 00957 combinePaths( chdpaths[0], chdpaths[2], conn[4], rings ) ; 00958 combinePaths( chdpaths[4], chdpaths[6], conn[5], rings ) ; 00959 combinePaths( chdpaths[0], NULL, conn[6], rings ) ; 00960 combinePaths( chdpaths[4], NULL, conn[7], rings ) ; 00961 00962 combinePaths( chdpaths[0], chdpaths[4], conn[0], rings ) ; 00963 combinePaths( chdpaths[0], NULL, conn[1], rings ) ; 00964 combinePaths( chdpaths[0], NULL, conn[2], rings ) ; 00965 combinePaths( chdpaths[0], NULL, conn[3], rings ) ; 00966 00967 // By now, only chdpaths[0] and rings have contents 00968 00969 // Process rings 00970 if ( rings ) 00971 { 00972 // printPath( rings ) ; 00973 00974 /* Let's count first */ 00975 PathList* trings = rings ; 00976 while ( trings ) 00977 { 00978 this->numRings ++ ; 00979 this->totRingLengths += trings->length ; 00980 if ( trings->length > this->maxRingLength ) 00981 { 00982 this->maxRingLength = trings->length ; 00983 } 00984 trings = trings->next ; 00985 } 00986 00987 // printPath( rings ) ; 00988 newnode = patch( newnode, st, ( len << 1 ), rings ) ; 00989 } 00990 00991 // Return incomplete paths 00992 paths = chdpaths[0] ; 00993 return newnode ; 00994 } 00995 00996 void Octree::findPaths( UCHAR* node[2], int leaf[2], int depth[2], int* st[2], int maxdep, int dir, PathList*& paths ) 00997 { 00998 if ( ! ( node[0] && node[1] ) ) 00999 { 01000 return ; 01001 } 01002 01003 if ( ! ( leaf[0] && leaf[1] ) ) 01004 { 01005 // Not at the bottom, recur 01006 01007 // Fill children nodes 01008 int i, j ; 01009 UCHAR* chd[ 2 ][ 8 ] ; 01010 int chdleaf[ 2 ][ 8 ] ; 01011 int nst[ 2 ][ 8 ][ 3 ] ; 01012 01013 for ( j = 0 ; j < 2 ; j ++ ) 01014 { 01015 if ( ! leaf[j] ) 01016 { 01017 fillChildren( node[j], chd[j], chdleaf[j] ) ; 01018 01019 int len = ( dimen >> ( maxDepth - depth[j] + 1 ) ) ; 01020 for ( i = 0 ; i < 8 ; i ++ ) 01021 { 01022 for ( int k = 0 ; k < 3 ; k ++ ) 01023 { 01024 nst[ j ][ i ][ k ] = st[ j ][ k ] + len * vertmap[ i ][ k ] ; 01025 } 01026 } 01027 01028 } 01029 } 01030 01031 // 4 face calls 01032 UCHAR* nf[2] ; 01033 int df[2] ; 01034 int lf[2] ; 01035 int* nstf[2] ; 01036 for ( i = 0 ; i < 4 ; i ++ ) 01037 { 01038 int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] }; 01039 for ( int j = 0 ; j < 2 ; j ++ ) 01040 { 01041 if ( leaf[j] ) 01042 { 01043 lf[j] = leaf[j] ; 01044 nf[j] = node[j] ; 01045 df[j] = depth[j] ; 01046 nstf[j] = st[j] ; 01047 } 01048 else 01049 { 01050 lf[j] = chdleaf[ j ][ c[j] ] ; 01051 nf[j] = chd[ j ][ c[j] ] ; 01052 df[j] = depth[j] - 1 ; 01053 nstf[j] = nst[ j ][ c[j] ] ; 01054 } 01055 } 01056 findPaths( nf, lf, df, nstf, maxdep - 1, faceProcFaceMask[ dir ][ i ][ 2 ], paths ) ; 01057 } 01058 01059 } 01060 else 01061 { 01062 // At the bottom, check this face 01063 int ind = ( depth[0] == maxdep ? 0 : 1 ) ; 01064 int fcind = 2 * dir + ( 1 - ind ) ; 01065 if ( getFaceParity( node[ ind ], fcind ) ) 01066 { 01067 // Add into path 01068 PathElement* ele1 = new PathElement ; 01069 PathElement* ele2 = new PathElement ; 01070 01071 ele1->pos[0] = st[0][0] ; 01072 ele1->pos[1] = st[0][1] ; 01073 ele1->pos[2] = st[0][2] ; 01074 01075 ele2->pos[0] = st[1][0] ; 01076 ele2->pos[1] = st[1][1] ; 01077 ele2->pos[2] = st[1][2] ; 01078 01079 ele1->next = ele2 ; 01080 ele2->next = NULL ; 01081 01082 PathList* lst = new PathList ; 01083 lst->head = ele1 ; 01084 lst->tail = ele2 ; 01085 lst->length = 2 ; 01086 lst->next = paths ; 01087 paths = lst ; 01088 01089 // int l = ( dimen >> maxDepth ) ; 01090 } 01091 } 01092 01093 } 01094 01095 void Octree::combinePaths( PathList*& list1, PathList* list2, PathList* paths, PathList*& rings ) 01096 { 01097 // Make new list of paths 01098 PathList* nlist = NULL ; 01099 01100 // Search for each connectors in paths 01101 PathList* tpaths = paths ; 01102 PathList* tlist, * pre ; 01103 while ( tpaths ) 01104 { 01105 PathList* singlist = tpaths ; 01106 PathList* templist ; 01107 tpaths = tpaths->next ; 01108 singlist->next = NULL ; 01109 01110 // Look for hookup in list1 01111 tlist = list1 ; 01112 pre = NULL ; 01113 while ( tlist ) 01114 { 01115 if ( (templist = combineSinglePath( list1, pre, tlist, singlist, NULL, singlist )) != NULL ) 01116 { 01117 singlist = templist ; 01118 continue ; 01119 } 01120 pre = tlist ; 01121 tlist = tlist->next ; 01122 } 01123 01124 // Look for hookup in list2 01125 tlist = list2 ; 01126 pre = NULL ; 01127 while ( tlist ) 01128 { 01129 if ( (templist = combineSinglePath( list2, pre, tlist, singlist, NULL, singlist )) != NULL ) 01130 { 01131 singlist = templist ; 01132 continue ; 01133 } 01134 pre = tlist ; 01135 tlist = tlist->next ; 01136 } 01137 01138 // Look for hookup in nlist 01139 tlist = nlist ; 01140 pre = NULL ; 01141 while ( tlist ) 01142 { 01143 if ( (templist = combineSinglePath( nlist, pre, tlist, singlist, NULL, singlist )) != NULL ) 01144 { 01145 singlist = templist ; 01146 continue ; 01147 } 01148 pre = tlist ; 01149 tlist = tlist->next ; 01150 } 01151 01152 // Add to nlist or rings 01153 if ( isEqual( singlist->head, singlist->tail ) ) 01154 { 01155 PathElement* temp = singlist->head ; 01156 singlist->head = temp->next ; 01157 delete temp ; 01158 singlist->length -- ; 01159 singlist->tail->next = singlist->head ; 01160 01161 singlist->next = rings ; 01162 rings = singlist ; 01163 } 01164 else 01165 { 01166 singlist->next = nlist ; 01167 nlist = singlist ; 01168 } 01169 01170 } 01171 01172 // Append list2 and nlist to the end of list1 01173 tlist = list1 ; 01174 if ( tlist != NULL ) 01175 { 01176 while ( tlist->next != NULL ) 01177 { 01178 tlist = tlist->next ; 01179 } 01180 tlist->next = list2 ; 01181 } 01182 else 01183 { 01184 tlist = list2 ; 01185 list1 = list2 ; 01186 } 01187 01188 if ( tlist != NULL ) 01189 { 01190 while ( tlist->next != NULL ) 01191 { 01192 tlist = tlist->next ; 01193 } 01194 tlist->next = nlist ; 01195 } 01196 else 01197 { 01198 tlist = nlist ; 01199 list1 = nlist ; 01200 } 01201 01202 } 01203 01204 PathList* Octree::combineSinglePath( PathList*& head1, PathList* pre1, PathList*& list1, PathList*& head2, PathList* pre2, PathList*& list2 ) 01205 { 01206 if ( isEqual( list1->head, list2->head ) || isEqual( list1->tail, list2->tail ) ) 01207 { 01208 // Reverse the list 01209 if ( list1->length < list2->length ) 01210 { 01211 // Reverse list1 01212 PathElement* prev = list1->head ; 01213 PathElement* next = prev->next ; 01214 prev->next = NULL ; 01215 while ( next != NULL ) 01216 { 01217 PathElement* tnext = next->next ; 01218 next->next = prev ; 01219 01220 prev = next ; 01221 next = tnext ; 01222 } 01223 01224 list1->tail = list1->head ; 01225 list1->head = prev ; 01226 } 01227 else 01228 { 01229 // Reverse list2 01230 PathElement* prev = list2->head ; 01231 PathElement* next = prev->next ; 01232 prev->next = NULL ; 01233 while ( next != NULL ) 01234 { 01235 PathElement* tnext = next->next ; 01236 next->next = prev ; 01237 01238 prev = next ; 01239 next = tnext ; 01240 } 01241 01242 list2->tail = list2->head ; 01243 list2->head = prev ; 01244 } 01245 } 01246 01247 if ( isEqual( list1->head, list2->tail ) ) 01248 { 01249 01250 // Easy case 01251 PathElement* temp = list1->head->next ; 01252 delete list1->head ; 01253 list2->tail->next = temp ; 01254 01255 PathList* nlist = new PathList ; 01256 nlist->length = list1->length + list2->length - 1 ; 01257 nlist->head = list2->head ; 01258 nlist->tail = list1->tail ; 01259 nlist->next = NULL ; 01260 01261 deletePath( head1, pre1, list1 ) ; 01262 deletePath( head2, pre2, list2 ) ; 01263 01264 return nlist ; 01265 } 01266 else if ( isEqual( list1->tail, list2->head ) ) 01267 { 01268 // Easy case 01269 PathElement* temp = list2->head->next ; 01270 delete list2->head ; 01271 list1->tail->next = temp ; 01272 01273 PathList* nlist = new PathList ; 01274 nlist->length = list1->length + list2->length - 1 ; 01275 nlist->head = list1->head ; 01276 nlist->tail = list2->tail ; 01277 nlist->next = NULL ; 01278 01279 deletePath( head1, pre1, list1 ) ; 01280 deletePath( head2, pre2, list2 ) ; 01281 01282 return nlist ; 01283 } 01284 01285 return NULL ; 01286 } 01287 01288 void Octree::deletePath( PathList*& head, PathList* pre, PathList*& curr ) 01289 { 01290 PathList* temp = curr ; 01291 curr = temp->next ; 01292 delete temp ; 01293 01294 if ( pre == NULL ) 01295 { 01296 head = curr ; 01297 } 01298 else 01299 { 01300 pre->next = curr ; 01301 } 01302 } 01303 01304 void Octree::printElement( PathElement* ele ) 01305 { 01306 if ( ele != NULL ) 01307 { 01308 dc_printf( " (%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2] ) ; 01309 } 01310 } 01311 01312 void Octree::printPath( PathList* path ) 01313 { 01314 PathElement* n = path->head; 01315 int same = 0 ; 01316 01317 #if DC_DEBUG 01318 int len = ( dimen >> maxDepth ) ; 01319 #endif 01320 while ( n && ( same == 0 || n != path->head ) ) 01321 { 01322 same ++ ; 01323 dc_printf( " (%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len ) ; 01324 n = n->next ; 01325 } 01326 01327 if ( n == path->head ) 01328 { 01329 dc_printf(" Ring!\n") ; 01330 } 01331 else 01332 { 01333 dc_printf(" %p end!\n", n) ; 01334 } 01335 } 01336 01337 void Octree::printPath( PathElement* path ) 01338 { 01339 PathElement *n = path; 01340 int same = 0 ; 01341 #if DC_DEBUG 01342 int len = ( dimen >> maxDepth ) ; 01343 #endif 01344 while ( n && ( same == 0 || n != path ) ) 01345 { 01346 same ++ ; 01347 dc_printf( " (%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len ) ; 01348 n = n->next ; 01349 } 01350 01351 if ( n == path ) 01352 { 01353 dc_printf(" Ring!\n") ; 01354 } 01355 else 01356 { 01357 dc_printf(" %p end!\n", n) ; 01358 } 01359 01360 } 01361 01362 01363 void Octree::printPaths( PathList* path ) 01364 { 01365 PathList* iter = path ; 01366 int i = 0 ; 01367 while ( iter != NULL ) 01368 { 01369 dc_printf("Path %d:\n", i) ; 01370 printPath( iter ) ; 01371 iter = iter->next ; 01372 i ++ ; 01373 } 01374 } 01375 01376 UCHAR* Octree::patch( UCHAR* node, int st[3], int len, PathList* rings ) 01377 { 01378 #ifdef IN_DEBUG_MODE 01379 dc_printf("Call to PATCH with rings: \n"); 01380 printPaths( rings ) ; 01381 #endif 01382 01383 /* Do nothing but couting 01384 PathList* tlist = rings ; 01385 PathList* ttlist ; 01386 PathElement* telem, * ttelem ; 01387 while ( tlist!= NULL ) 01388 { 01389 // printPath( tlist ) ; 01390 this->numRings ++ ; 01391 this->totRingLengths += tlist->length ; 01392 if ( tlist->length > this->maxRingLength ) 01393 { 01394 this->maxRingLength = tlist->length ; 01395 } 01396 ttlist = tlist ; 01397 tlist = tlist->next ; 01398 } 01399 return node ; 01400 */ 01401 01402 01403 /* Pass onto separate calls in each direction */ 01404 UCHAR* newnode = node ; 01405 if ( len == mindimen ) 01406 { 01407 dc_printf("Error! should have no list by now.\n") ; 01408 exit(0) ; 01409 } 01410 01411 // YZ plane 01412 PathList* xlists[2] ; 01413 newnode = patchSplit( newnode, st, len, rings, 0, xlists[0], xlists[1] ) ; 01414 01415 // XZ plane 01416 PathList* ylists[4] ; 01417 newnode = patchSplit( newnode, st, len, xlists[0], 1, ylists[0], ylists[1] ) ; 01418 newnode = patchSplit( newnode, st, len, xlists[1], 1, ylists[2], ylists[3] ) ; 01419 01420 // XY plane 01421 PathList* zlists[8] ; 01422 newnode = patchSplit( newnode, st, len, ylists[0], 2, zlists[0], zlists[1] ) ; 01423 newnode = patchSplit( newnode, st, len, ylists[1], 2, zlists[2], zlists[3] ) ; 01424 newnode = patchSplit( newnode, st, len, ylists[2], 2, zlists[4], zlists[5] ) ; 01425 newnode = patchSplit( newnode, st, len, ylists[3], 2, zlists[6], zlists[7] ) ; 01426 01427 // Recur 01428 len >>= 1 ; 01429 int count = 0 ; 01430 for ( int i = 0 ; i < 8 ; i ++ ) 01431 { 01432 if ( zlists[i] != NULL ) 01433 { 01434 int nori[3] = { 01435 st[0] + len * vertmap[i][0] , 01436 st[1] + len * vertmap[i][1] , 01437 st[2] + len * vertmap[i][2] } ; 01438 patch( getChild( newnode , count ), nori, len, zlists[i] ) ; 01439 } 01440 01441 if ( hasChild( newnode, i ) ) 01442 { 01443 count ++ ; 01444 } 01445 } 01446 #ifdef IN_DEBUG_MODE 01447 dc_printf("Return from PATCH\n") ; 01448 #endif 01449 return newnode ; 01450 01451 } 01452 01453 01454 UCHAR* Octree::patchSplit( UCHAR* node, int st[3], int len, PathList* rings, int dir, PathList*& nrings1, PathList*& nrings2 ) 01455 { 01456 #ifdef IN_DEBUG_MODE 01457 dc_printf("Call to PATCHSPLIT with direction %d and rings: \n", dir); 01458 printPaths( rings ) ; 01459 #endif 01460 01461 UCHAR* newnode = node ; 01462 nrings1 = NULL ; 01463 nrings2 = NULL ; 01464 PathList* tmp ; 01465 while ( rings != NULL ) 01466 { 01467 // Process this ring 01468 newnode = patchSplitSingle( newnode, st, len, rings->head, dir, nrings1, nrings2 ) ; 01469 01470 // Delete this ring from the group 01471 tmp = rings ; 01472 rings = rings->next ; 01473 delete tmp ; 01474 } 01475 01476 #ifdef IN_DEBUG_MODE 01477 dc_printf("Return from PATCHSPLIT with \n"); 01478 dc_printf("Rings gourp 1:\n") ; 01479 printPaths( nrings1 ) ; 01480 dc_printf("Rings group 2:\n") ; 01481 printPaths( nrings2 ) ; 01482 #endif 01483 01484 return newnode ; 01485 } 01486 01487 UCHAR* Octree::patchSplitSingle( UCHAR* node, int st[3], int len, PathElement* head, int dir, PathList*& nrings1, PathList*& nrings2 ) 01488 { 01489 #ifdef IN_DEBUG_MODE 01490 dc_printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir ); 01491 printPath( head ) ; 01492 #endif 01493 01494 UCHAR* newnode = node ; 01495 01496 if ( head == NULL ) 01497 { 01498 #ifdef IN_DEBUG_MODE 01499 dc_printf("Return from PATCHSPLITSINGLE with head==NULL.\n") ; 01500 #endif 01501 return newnode; 01502 } 01503 else 01504 { 01505 // printPath( head ) ; 01506 } 01507 01508 // Walk along the ring to find pair of intersections 01509 PathElement* pre1 = NULL ; 01510 PathElement* pre2 = NULL ; 01511 int side = findPair ( head, st[ dir ] + len / 2 , dir, pre1, pre2 ) ; 01512 01513 /* 01514 if ( pre1 == pre2 ) 01515 { 01516 int edgelen = ( dimen >> maxDepth ) ; 01517 dc_printf("Location: %d %d %d Direction: %d Reso: %d\n", st[0]/edgelen, st[1]/edgelen, st[2]/edgelen, dir, len/edgelen) ; 01518 printPath( head ) ; 01519 exit( 0 ) ; 01520 } 01521 */ 01522 01523 if ( side ) 01524 { 01525 // Entirely on one side 01526 PathList* nring = new PathList( ) ; 01527 nring->head = head ; 01528 01529 if ( side == -1 ) 01530 { 01531 nring->next = nrings1 ; 01532 nrings1 = nring ; 01533 } 01534 else 01535 { 01536 nring->next = nrings2 ; 01537 nrings2 = nring ; 01538 } 01539 } 01540 else 01541 { 01542 // Break into two parts 01543 PathElement* nxt1 = pre1->next ; 01544 PathElement* nxt2 = pre2->next ; 01545 pre1->next = nxt2 ; 01546 pre2->next = nxt1 ; 01547 01548 newnode = connectFace( newnode, st, len, dir, pre1, pre2 ) ; 01549 01550 if ( isEqual( pre1, pre1->next ) ) 01551 { 01552 if ( pre1 == pre1->next ) 01553 { 01554 delete pre1 ; 01555 pre1 = NULL ; 01556 } 01557 else 01558 { 01559 PathElement* temp = pre1->next ; 01560 pre1->next = temp->next ; 01561 delete temp ; 01562 } 01563 } 01564 if ( isEqual( pre2, pre2->next ) ) 01565 { 01566 if ( pre2 == pre2->next ) 01567 { 01568 delete pre2 ; 01569 pre2 = NULL ; 01570 } 01571 else 01572 { 01573 PathElement* temp = pre2->next ; 01574 pre2->next = temp->next ; 01575 delete temp ; 01576 } 01577 } 01578 01579 compressRing ( pre1 ) ; 01580 compressRing ( pre2 ) ; 01581 01582 // Recur 01583 newnode = patchSplitSingle( newnode, st, len, pre1, dir, nrings1, nrings2 ) ; 01584 newnode = patchSplitSingle( newnode, st, len, pre2, dir, nrings1, nrings2 ) ; 01585 01586 } 01587 01588 #ifdef IN_DEBUG_MODE 01589 dc_printf("Return from PATCHSPLITSINGLE with \n"); 01590 dc_printf("Rings gourp 1:\n") ; 01591 printPaths( nrings1 ) ; 01592 dc_printf("Rings group 2:\n") ; 01593 printPaths( nrings2 ) ; 01594 #endif 01595 01596 return newnode ; 01597 } 01598 01599 UCHAR* Octree::connectFace( UCHAR* node, int st[3], int len, int dir, PathElement* f1, PathElement* f2 ) 01600 { 01601 #ifdef IN_DEBUG_MODE 01602 dc_printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len ); 01603 dc_printf("Path (low side): \n" ) ; 01604 printPath( f1 ) ; 01605 // checkPath( f1 ) ; 01606 dc_printf("Path (high side): \n" ) ; 01607 printPath( f2 ) ; 01608 // checkPath( f2 ) ; 01609 #endif 01610 01611 UCHAR* newnode = node ; 01612 01613 // Setup 2D 01614 int pos = st[ dir ] + len / 2 ; 01615 int xdir = ( dir + 1 ) % 3 ; 01616 int ydir = ( dir + 2 ) % 3 ; 01617 01618 // Use existing intersections on f1 and f2 01619 int x1, y1, x2, y2 ; 01620 float p1, q1, p2, q2 ; 01621 01622 getFacePoint( f2->next, dir, x1, y1, p1, q1 ) ; 01623 getFacePoint( f2, dir, x2, y2, p2, q2 ) ; 01624 01625 float dx = x2 + p2 - x1 - p1 ; 01626 float dy = y2 + q2 - y1 - q1 ; 01627 01628 // Do adapted Bresenham line drawing 01629 float rx = p1, ry = q1 ; 01630 int incx = 1, incy = 1 ; 01631 int lx = x1, ly = y1 ; 01632 int hx = x2, hy = y2 ; 01633 int choice ; 01634 if ( x2 < x1 ) 01635 { 01636 incx = -1 ; 01637 rx = 1 - rx ; 01638 lx = x2 ; 01639 hx = x1 ; 01640 } 01641 if ( y2 < y1 ) 01642 { 01643 incy = -1 ; 01644 ry = 1 - ry ; 01645 ly = y2 ; 01646 hy = y1 ; 01647 } 01648 01649 float sx = dx * incx ; 01650 float sy = dy * incy ; 01651 01652 int ori[3] ; 01653 ori[ dir ] = pos / mindimen ; 01654 ori[ xdir ] = x1 ; 01655 ori[ ydir ] = y1 ; 01656 int walkdir ; 01657 int inc ; 01658 float alpha ; 01659 01660 PathElement* curEleN = f1 ; 01661 PathElement* curEleP = f2->next ; 01662 UCHAR *nodeN = NULL, *nodeP = NULL ; 01663 UCHAR *curN = locateLeaf( newnode, len, f1->pos ) ; 01664 UCHAR *curP = locateLeaf( newnode, len, f2->next->pos ) ; 01665 if ( curN == NULL || curP == NULL ) 01666 { 01667 exit(0) ; 01668 } 01669 int stN[3], stP[3] ; 01670 int lenN, lenP ; 01671 01672 /* Unused code, leaving for posterity 01673 01674 float stpt[3], edpt[3] ; 01675 stpt[ dir ] = edpt[ dir ] = (float) pos ; 01676 stpt[ xdir ] = ( x1 + p1 ) * mindimen ; 01677 stpt[ ydir ] = ( y1 + q1 ) * mindimen ; 01678 edpt[ xdir ] = ( x2 + p2 ) * mindimen ; 01679 edpt[ ydir ] = ( y2 + q2 ) * mindimen ; 01680 */ 01681 while( ori[ xdir ] != x2 || ori[ ydir ] != y2 ) 01682 { 01683 int next ; 01684 if ( sy * (1 - rx) > sx * (1 - ry) ) 01685 { 01686 choice = 1 ; 01687 next = ori[ ydir ] + incy ; 01688 if ( next < ly || next > hy ) 01689 { 01690 choice = 4 ; 01691 next = ori[ xdir ] + incx ; 01692 } 01693 } 01694 else 01695 { 01696 choice = 2 ; 01697 next = ori[ xdir ] + incx ; 01698 if ( next < lx || next > hx ) 01699 { 01700 choice = 3 ; 01701 next = ori[ ydir ] + incy ; 01702 } 01703 } 01704 01705 if ( choice & 1 ) 01706 { 01707 ori[ ydir ] = next ; 01708 if ( choice == 1 ) 01709 { 01710 rx += ( sy == 0 ? 0 : (1 - ry) * sx / sy ) ; 01711 ry = 0 ; 01712 } 01713 01714 walkdir = 2 ; 01715 inc = incy ; 01716 alpha = x2 < x1 ? 1 - rx : rx ; 01717 } 01718 else 01719 { 01720 ori[ xdir ] = next ; 01721 if ( choice == 2 ) 01722 { 01723 ry += ( sx == 0 ? 0 : (1 - rx) * sy / sx ) ; 01724 rx = 0 ; 01725 } 01726 01727 walkdir = 1 ; 01728 inc = incx ; 01729 alpha = y2 < y1 ? 1 - ry : ry ; 01730 } 01731 01732 01733 01734 // Get the exact location of the marcher 01735 int nori[3] = { ori[0] * mindimen, ori[1] * mindimen, ori[2] * mindimen } ; 01736 float spt[3] = { (float) nori[0], (float) nori[1], (float) nori[2] } ; 01737 spt[ ( dir + ( 3 - walkdir ) ) % 3 ] += alpha * mindimen ; 01738 if ( inc < 0 ) 01739 { 01740 spt[ ( dir + walkdir ) % 3 ] += mindimen ; 01741 } 01742 01743 // dc_printf("new x,y: %d %d\n", ori[ xdir ] / edgelen, ori[ ydir ] / edgelen ) ; 01744 // dc_printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir ) ; 01745 // dc_printf("%f %f %f\n", spt[0], spt[1], spt[2] ) ; 01746 01747 // Locate the current cells on both sides 01748 newnode = locateCell( newnode, st, len, nori, dir, 1, nodeN, stN, lenN ) ; 01749 newnode = locateCell( newnode, st, len, nori, dir, 0, nodeP, stP, lenP ) ; 01750 01751 updateParent( newnode, len, st ) ; 01752 01753 int flag = 0 ; 01754 // Add the cells to the rings and fill in the patch 01755 PathElement* newEleN ; 01756 if ( curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2] ) 01757 { 01758 if ( curEleN->next->pos[0] != stN[0] || curEleN->next->pos[1] != stN[1] || curEleN->next->pos[2] != stN[2] ) 01759 { 01760 newEleN = new PathElement ; 01761 newEleN->next = curEleN->next ; 01762 newEleN->pos[0] = stN[0] ; 01763 newEleN->pos[1] = stN[1] ; 01764 newEleN->pos[2] = stN[2] ; 01765 01766 curEleN->next = newEleN ; 01767 } 01768 else 01769 { 01770 newEleN = curEleN->next ; 01771 } 01772 curN = patchAdjacent( newnode, len, curEleN->pos, curN, newEleN->pos, nodeN, walkdir, inc, dir, 1, alpha ) ; 01773 01774 curEleN = newEleN ; 01775 flag ++ ; 01776 } 01777 01778 PathElement* newEleP ; 01779 if ( curEleP->pos[0] != stP[0] || curEleP->pos[1] != stP[1] || curEleP->pos[2] != stP[2] ) 01780 { 01781 if ( f2->pos[0] != stP[0] || f2->pos[1] != stP[1] || f2->pos[2] != stP[2] ) 01782 { 01783 newEleP = new PathElement ; 01784 newEleP->next = curEleP ; 01785 newEleP->pos[0] = stP[0] ; 01786 newEleP->pos[1] = stP[1] ; 01787 newEleP->pos[2] = stP[2] ; 01788 01789 f2->next = newEleP ; 01790 } 01791 else 01792 { 01793 newEleP = f2 ; 01794 } 01795 curP = patchAdjacent( newnode, len, curEleP->pos, curP, newEleP->pos, nodeP, walkdir, inc, dir, 0, alpha ) ; 01796 01797 01798 01799 curEleP = newEleP ; 01800 flag ++ ; 01801 } 01802 01803 01804 /* 01805 if ( flag == 0 ) 01806 { 01807 dc_printf("error: non-synchronized patching! at \n") ; 01808 } 01809 */ 01810 } 01811 01812 #ifdef IN_DEBUG_MODE 01813 dc_printf("Return from CONNECTFACE with \n"); 01814 dc_printf("Path (low side):\n") ; 01815 printPath( f1 ) ; 01816 checkPath( f1 ) ; 01817 dc_printf("Path (high side):\n") ; 01818 printPath( f2 ) ; 01819 checkPath( f2 ) ; 01820 #endif 01821 01822 01823 return newnode ; 01824 } 01825 01826 UCHAR* Octree::patchAdjacent( UCHAR* node, int len, int st1[3], UCHAR* leaf1, int st2[3], UCHAR* leaf2, int walkdir, int inc, int dir, int side, float alpha ) 01827 { 01828 #ifdef IN_DEBUG_MODE 01829 dc_printf("Before patching.\n") ; 01830 printInfo( st1 ) ; 01831 printInfo( st2 ) ; 01832 dc_printf("-----------------%d %d %d ; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2] ) ; 01833 #endif 01834 01835 // Get edge index on each leaf 01836 int edgedir = ( dir + ( 3 - walkdir ) ) % 3 ; 01837 int incdir = ( dir + walkdir ) % 3 ; 01838 int ind1 = ( edgedir == 1 ? ( dir + 3 - edgedir ) % 3 - 1 : 2 - ( dir + 3 - edgedir ) % 3 ) ; 01839 int ind2 = ( edgedir == 1 ? ( incdir + 3 - edgedir ) % 3 - 1 : 2 - ( incdir + 3 - edgedir ) % 3 ) ; 01840 01841 int eind1 = ( ( edgedir << 2 ) | ( side << ind1 ) | ( ( inc > 0 ? 1 : 0 ) << ind2 ) ) ; 01842 int eind2 = ( ( edgedir << 2 ) | ( side << ind1 ) | ( ( inc > 0 ? 0 : 1 ) << ind2 ) ) ; 01843 01844 #ifdef IN_DEBUG_MODE 01845 dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha ) ; 01846 /* 01847 if ( alpha < 0 || alpha > 1 ) 01848 { 01849 dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha ) ; 01850 printInfo( st1 ) ; 01851 printInfo( st2 ) ; 01852 } 01853 */ 01854 #endif 01855 01856 // Flip edge parity 01857 UCHAR* nleaf1 = flipEdge( leaf1, eind1, alpha ) ; 01858 UCHAR* nleaf2 = flipEdge( leaf2, eind2, alpha ) ; 01859 01860 // Update parent link 01861 updateParent( node, len, st1, nleaf1 ) ; 01862 updateParent( node, len, st2, nleaf2 ) ; 01863 // updateParent( nleaf1, mindimen, st1 ) ; 01864 // updateParent( nleaf2, mindimen, st2 ) ; 01865 01866 /* 01867 float m[3] ; 01868 dc_printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2] ) ; 01869 getMinimizer( leaf1, m ) ; 01870 dc_printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2] ) ; 01871 getMinimizer( leaf2, m ) ; 01872 dc_printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2] ) ; 01873 */ 01874 01875 #ifdef IN_DEBUG_MODE 01876 dc_printf("After patching.\n") ; 01877 printInfo( st1 ) ; 01878 printInfo( st2 ) ; 01879 #endif 01880 return nleaf2 ; 01881 } 01882 01883 UCHAR* Octree::locateCell( UCHAR* node, int st[3], int len, int ori[3], int dir, int side, UCHAR*& rleaf, int rst[3], int& rlen ) 01884 { 01885 #ifdef IN_DEBUG_MODE 01886 // dc_printf("Call to LOCATECELL with node ") ; 01887 // printNode( node ) ; 01888 #endif 01889 UCHAR* newnode = node ; 01890 int i ; 01891 len >>= 1 ; 01892 int ind = 0 ; 01893 for ( i = 0 ; i < 3 ; i ++ ) 01894 { 01895 ind <<= 1 ; 01896 if ( i == dir && side == 1 ) 01897 { 01898 ind |= ( ori[ i ] <= ( st[ i ] + len ) ? 0 : 1 ) ; 01899 } 01900 else 01901 { 01902 ind |= ( ori[ i ] < ( st[ i ] + len ) ? 0 : 1 ) ; 01903 } 01904 } 01905 01906 #ifdef IN_DEBUG_MODE 01907 // dc_printf("In LOCATECELL index of ori (%d %d %d) with dir %d side %d in st (%d %d %d, %d) is: %d\n", 01908 // ori[0], ori[1], ori[2], dir, side, st[0], st[1], st[2], len, ind ) ; 01909 #endif 01910 01911 rst[0] = st[0] + vertmap[ ind ][ 0 ] * len ; 01912 rst[1] = st[1] + vertmap[ ind ][ 1 ] * len ; 01913 rst[2] = st[2] + vertmap[ ind ][ 2 ] * len ; 01914 01915 if ( hasChild( newnode, ind ) ) 01916 { 01917 int count = getChildCount( newnode, ind ) ; 01918 UCHAR* chd = getChild( newnode, count ) ; 01919 if ( isLeaf( newnode, ind ) ) 01920 { 01921 rleaf = chd ; 01922 rlen = len ; 01923 } 01924 else 01925 { 01926 // Recur 01927 setChild( newnode, count, locateCell( chd, rst, len, ori, dir, side, rleaf, rst, rlen ) ) ; 01928 } 01929 } 01930 else 01931 { 01932 // Create a new child here 01933 if ( len == this->mindimen ) 01934 { 01935 UCHAR* chd = createLeaf( 0 ) ; 01936 newnode = addChild( newnode, ind, chd, 1 ) ; 01937 rleaf = chd ; 01938 rlen = len ; 01939 } 01940 else 01941 { 01942 // Subdivide the empty cube 01943 UCHAR* chd = createInternal( 0 ) ; 01944 newnode = addChild( newnode, ind, locateCell( chd, rst, len, ori, dir, side, rleaf, rst, rlen ), 0 ) ; 01945 } 01946 } 01947 01948 #ifdef IN_DEBUG_MODE 01949 // dc_printf("Return from LOCATECELL with node ") ; 01950 // printNode( newnode ) ; 01951 #endif 01952 return newnode ; 01953 } 01954 01955 void Octree::checkElement( PathElement* ele ) 01956 { 01957 /* 01958 if ( ele != NULL && locateLeafCheck( ele->pos ) != ele->node ) 01959 { 01960 dc_printf("Screwed! at pos: %d %d %d\n", ele->pos[0]>>minshift, ele->pos[1]>>minshift, ele->pos[2]>>minshift); 01961 exit( 0 ) ; 01962 } 01963 */ 01964 } 01965 01966 void Octree::checkPath( PathElement* path ) 01967 { 01968 PathElement *n = path ; 01969 int same = 0 ; 01970 while ( n && ( same == 0 || n != path ) ) 01971 { 01972 same ++ ; 01973 checkElement( n ) ; 01974 n = n->next ; 01975 } 01976 01977 } 01978 01979 void Octree::testFacePoint( PathElement* e1, PathElement* e2 ) 01980 { 01981 int i ; 01982 PathElement * e = NULL ; 01983 for ( i = 0 ; i < 3 ; i ++ ) 01984 { 01985 if ( e1->pos[i] != e2->pos[i] ) 01986 { 01987 if ( e1->pos[i] < e2->pos[i] ) 01988 { 01989 e = e2 ; 01990 } 01991 else 01992 { 01993 e = e1 ; 01994 } 01995 break ; 01996 } 01997 } 01998 01999 int x, y ; 02000 float p, q ; 02001 dc_printf("Test.") ; 02002 getFacePoint( e, i, x, y, p, q ) ; 02003 } 02004 02005 void Octree::getFacePoint( PathElement* leaf, int dir, int& x, int& y, float& p, float& q ) 02006 { 02007 // Find average intersections 02008 float avg[3] = {0, 0, 0} ; 02009 float off[3] ; 02010 int num = 0, num2 = 0 ; 02011 02012 UCHAR* leafnode = locateLeaf( leaf->pos ) ; 02013 for ( int i = 0 ; i < 4 ; i ++ ) 02014 { 02015 int edgeind = faceMap[ dir * 2 ][ i ] ; 02016 int nst[3] ; 02017 for ( int j = 0 ; j < 3 ; j ++ ) 02018 { 02019 nst[j] = leaf->pos[j] + mindimen * vertmap[ edgemap[ edgeind][ 0 ] ][ j ] ; 02020 } 02021 02022 if ( getEdgeIntersectionByIndex( nst, edgeind / 4, off, 1 ) ) 02023 { 02024 avg[0] += off[0] ; 02025 avg[1] += off[1] ; 02026 avg[2] += off[2] ; 02027 num ++ ; 02028 } 02029 if ( getEdgeParity( leafnode, edgeind ) ) 02030 { 02031 num2 ++ ; 02032 } 02033 } 02034 if ( num == 0 ) 02035 { 02036 dc_printf("Wrong! dir: %d pos: %d %d %d num: %d\n", dir, leaf->pos[0]>>minshift, leaf->pos[1]>>minshift, leaf->pos[2]>>minshift, num2); 02037 avg[0] = (float) leaf->pos[0] ; 02038 avg[1] = (float) leaf->pos[1] ; 02039 avg[2] = (float) leaf->pos[2] ; 02040 } 02041 else 02042 { 02043 02044 avg[0] /= num ; 02045 avg[1] /= num ; 02046 avg[2] /= num ; 02047 02048 //avg[0] = (float) leaf->pos[0]; 02049 //avg[1] = (float) leaf->pos[1]; 02050 //avg[2] = (float) leaf->pos[2]; 02051 } 02052 02053 int xdir = ( dir + 1 ) % 3 ; 02054 int ydir = ( dir + 2 ) % 3 ; 02055 02056 float xf = avg[ xdir ] ; 02057 float yf = avg[ ydir ] ; 02058 02059 #ifdef IN_DEBUG_MODE 02060 // Is it outside? 02061 // PathElement* leaf = leaf1->len < leaf2->len ? leaf1 : leaf2 ; 02062 /* 02063 float* m = ( leaf == leaf1 ? m1 : m2 ) ; 02064 if ( xf < leaf->pos[ xdir ] || 02065 yf < leaf->pos[ ydir ] || 02066 xf > leaf->pos[ xdir ] + leaf->len || 02067 yf > leaf->pos[ ydir ] + leaf->len) 02068 { 02069 dc_printf("Outside cube (%d %d %d), %d : %d %d %f %f\n", leaf->pos[ 0 ], leaf->pos[1], leaf->pos[2], leaf->len, 02070 pos, dir, xf, yf) ; 02071 02072 // For now, snap to cell 02073 xf = m[ xdir ] ; 02074 yf = m[ ydir ] ; 02075 } 02076 */ 02077 02078 /* 02079 if ( alpha < 0 || alpha > 1 || 02080 xf < leaf->pos[xdir] || xf > leaf->pos[xdir] + leaf->len || 02081 yf < leaf->pos[ydir] || yf > leaf->pos[ydir] + leaf->len ) 02082 { 02083 dc_printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node ) ; 02084 dc_printf("GETFACEPOINT result: (%d %d %d) %d min: (%f %f %f) ;(%d %d %d) %d min: (%f %f %f).\n", 02085 leaf1->pos[0], leaf1->pos[1], leaf1->pos[2], leaf1->len, m1[0], m1[1], m1[2], 02086 leaf2->pos[0], leaf2->pos[1], leaf2->pos[2], leaf2->len, m2[0], m2[1], m2[2]); 02087 dc_printf("Face point at dir %d pos %d: %f %f\n", dir, pos, xf, yf ) ; 02088 } 02089 */ 02090 #endif 02091 02092 02093 // Get the integer and float part 02094 x = ( ( leaf->pos[ xdir ] ) >> minshift ) ; 02095 y = ( ( leaf->pos[ ydir ] ) >> minshift ) ; 02096 02097 p = ( xf - leaf->pos[ xdir ] ) / mindimen ; 02098 q = ( yf - leaf->pos[ ydir ] ) / mindimen ; 02099 02100 02101 #ifdef IN_DEBUG_MODE 02102 dc_printf("Face point at dir %d : %f %f\n", dir, xf, yf ) ; 02103 #endif 02104 } 02105 02106 int Octree::findPair( PathElement* head, int pos, int dir, PathElement*& pre1, PathElement*& pre2 ) 02107 { 02108 int side = getSide ( head, pos, dir ) ; 02109 PathElement* cur = head ; 02110 PathElement* anchor ; 02111 PathElement* ppre1, *ppre2 ; 02112 02113 // Start from this face, find a pair 02114 anchor = cur ; 02115 ppre1 = cur ; 02116 cur = cur->next ; 02117 while ( cur != anchor && ( getSide( cur, pos, dir ) == side ) ) 02118 { 02119 ppre1 = cur ; 02120 cur = cur->next ; 02121 } 02122 if ( cur == anchor ) 02123 { 02124 // No pair found 02125 return side ; 02126 } 02127 02128 side = getSide( cur, pos, dir ) ; 02129 ppre2 = cur ; 02130 cur = cur->next ; 02131 while ( getSide( cur, pos, dir ) == side ) 02132 { 02133 ppre2 = cur ; 02134 cur = cur->next ; 02135 } 02136 02137 02138 // Switch pre1 and pre2 if we start from the higher side 02139 if ( side == -1 ) 02140 { 02141 cur = ppre1 ; 02142 ppre1 = ppre2 ; 02143 ppre2 = cur ; 02144 } 02145 02146 pre1 = ppre1 ; 02147 pre2 = ppre2 ; 02148 02149 return 0 ; 02150 } 02151 02152 int Octree::getSide( PathElement* e, int pos, int dir ) 02153 { 02154 return ( e->pos[ dir ] < pos ? -1 : 1 ) ; 02155 } 02156 02157 int Octree::isEqual( PathElement* e1, PathElement* e2 ) 02158 { 02159 return ( e1->pos[0] == e2->pos[0] && e1->pos[1] == e2->pos[1] && e1->pos[2] == e2->pos[2] ) ; 02160 } 02161 02162 void Octree::compressRing( PathElement*& ring ) 02163 { 02164 if ( ring == NULL ) 02165 { 02166 return ; 02167 } 02168 #ifdef IN_DEBUG_MODE 02169 dc_printf("Call to COMPRESSRING with path: \n" ); 02170 printPath( ring ) ; 02171 #endif 02172 02173 PathElement* cur = ring->next->next ; 02174 PathElement* pre = ring->next ; 02175 PathElement* prepre = ring ; 02176 PathElement* anchor = prepre ; 02177 02178 do 02179 { 02180 while ( isEqual( cur, prepre ) ) 02181 { 02182 // Delete 02183 if ( cur == prepre ) 02184 { 02185 // The ring has shrinked to a point 02186 delete pre ; 02187 delete cur ; 02188 anchor = NULL ; 02189 break ; 02190 } 02191 else 02192 { 02193 prepre->next = cur->next ; 02194 delete pre ; 02195 delete cur ; 02196 pre = prepre->next ; 02197 cur = pre->next ; 02198 anchor = prepre ; 02199 } 02200 } 02201 02202 if ( anchor == NULL ) 02203 { 02204 break ; 02205 } 02206 02207 prepre = pre ; 02208 pre = cur ; 02209 cur = cur->next ; 02210 } while ( prepre != anchor ) ; 02211 02212 ring = anchor ; 02213 02214 #ifdef IN_DEBUG_MODE 02215 dc_printf("Return from COMPRESSRING with path: \n" ); 02216 printPath( ring ) ; 02217 #endif 02218 } 02219 02220 void Octree::buildSigns( ) 02221 { 02222 // First build a lookup table 02223 // dc_printf("Building up look up table...\n") ; 02224 int size = 1 << 12 ; 02225 unsigned char table[ 1 << 12 ] ; 02226 for ( int i = 0 ; i < size ; i ++ ) 02227 { 02228 table[i] = 0 ; 02229 } 02230 for ( int i = 0 ; i < 256 ; i ++ ) 02231 { 02232 int ind = 0 ; 02233 for ( int j = 11 ; j >= 0 ; j -- ) 02234 { 02235 ind <<= 1 ; 02236 if ( ( ( i >> edgemap[j][0] ) & 1 ) ^ ( ( i >> edgemap[j][1] ) & 1 ) ) 02237 { 02238 ind |= 1 ; 02239 } 02240 } 02241 02242 table[ ind ] = i ; 02243 } 02244 02245 // Next, traverse the grid 02246 int sg = 1 ; 02247 int cube[8] ; 02248 buildSigns( table, this->root, 0, sg, cube ) ; 02249 } 02250 02251 void Octree::buildSigns( unsigned char table[], UCHAR* node, int isLeaf, int sg, int rvalue[8] ) 02252 { 02253 if ( node == NULL ) 02254 { 02255 for ( int i = 0 ; i < 8 ; i ++ ) 02256 { 02257 rvalue[i] = sg ; 02258 } 02259 return ; 02260 } 02261 02262 if ( isLeaf == 0 ) 02263 { 02264 // Internal node 02265 UCHAR* chd[8] ; 02266 int leaf[8] ; 02267 fillChildren( node, chd, leaf ) ; 02268 02269 // Get the signs at the corners of the first cube 02270 rvalue[0] = sg ; 02271 int oris[8] ; 02272 buildSigns( table, chd[0], leaf[0], sg, oris ) ; 02273 02274 // Get the rest 02275 int cube[8] ; 02276 for ( int i = 1 ; i < 8 ; i ++ ) 02277 { 02278 buildSigns( table, chd[i], leaf[i], oris[i], cube ) ; 02279 rvalue[i] = cube[i] ; 02280 } 02281 02282 } 02283 else 02284 { 02285 // Leaf node 02286 generateSigns( node, table, sg ) ; 02287 02288 for ( int i = 0 ; i < 8 ; i ++ ) 02289 { 02290 rvalue[i] = getSign( node, i ) ; 02291 } 02292 } 02293 } 02294 02295 void Octree::floodFill( ) 02296 { 02297 // int threshold = (int) ((dimen/mindimen) * (dimen/mindimen) * 0.5f) ; 02298 int st[3] = { 0, 0, 0 } ; 02299 02300 // First, check for largest component 02301 // size stored in -threshold 02302 this->clearProcessBits( root, maxDepth ) ; 02303 int threshold = this->floodFill( root, st, dimen, maxDepth, 0 ) ; 02304 02305 // Next remove 02306 dc_printf("Largest component: %d\n", threshold); 02307 threshold *= thresh ; 02308 dc_printf("Removing all components smaller than %d\n", threshold) ; 02309 02310 int st2[3] = { 0, 0, 0 } ; 02311 this->clearProcessBits( root, maxDepth ) ; 02312 this->floodFill( root, st2, dimen, maxDepth, threshold ) ; 02313 02314 } 02315 02316 void Octree::clearProcessBits( UCHAR* node, int height ) 02317 { 02318 int i; 02319 02320 if ( height == 0 ) 02321 { 02322 // Leaf cell, 02323 for ( i = 0 ; i < 12 ; i ++ ) 02324 { 02325 setOutProcess( node, i ) ; 02326 } 02327 } 02328 else 02329 { 02330 // Internal cell, recur 02331 int count = 0 ; 02332 for ( i = 0 ; i < 8 ; i ++ ) 02333 { 02334 if ( hasChild( node, i ) ) 02335 { 02336 clearProcessBits( getChild( node, count ), height - 1 ) ; 02337 count ++ ; 02338 } 02339 } 02340 } 02341 } 02342 02343 /* 02344 void Octree::floodFill( UCHAR* node, int st[3], int len, int height, int threshold ) 02345 { 02346 int i, j; 02347 02348 if ( height == 0 ) 02349 { 02350 // Leaf cell, 02351 int par, inp ; 02352 02353 // Test if the leaf has intersection edges 02354 for ( i = 0 ; i < 12 ; i ++ ) 02355 { 02356 par = getEdgeParity( node, i ) ; 02357 inp = isInProcess( node, i ) ; 02358 02359 if ( par == 1 && inp == 0 ) 02360 { 02361 // Intersection edge, hasn't been processed 02362 // Let's start filling 02363 GridQueue* queue = new GridQueue() ; 02364 int total = 1 ; 02365 02366 // Set to in process 02367 int mst[3] ; 02368 mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len ; 02369 mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len ; 02370 mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len; 02371 int mdir = i / 4 ; 02372 setInProcessAll( mst, mdir ) ; 02373 02374 // Put this edge into queue 02375 queue->pushQueue( mst, mdir ) ; 02376 02377 // Queue processing 02378 int nst[3], dir ; 02379 while ( queue->popQueue( nst, dir ) == 1 ) 02380 { 02381 // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ; 02382 // locations 02383 int stMask[3][3] = { 02384 { 0, 0 - len, 0 - len }, 02385 { 0 - len, 0, 0 - len }, 02386 { 0 - len, 0 - len, 0 } 02387 }; 02388 int cst[2][3] ; 02389 for ( j = 0 ; j < 3 ; j ++ ) 02390 { 02391 cst[0][j] = nst[j] ; 02392 cst[1][j] = nst[j] + stMask[ dir ][ j ] ; 02393 } 02394 02395 // cells 02396 UCHAR* cs[2] ; 02397 for ( j = 0 ; j < 2 ; j ++ ) 02398 { 02399 cs[ j ] = locateLeaf( cst[j] ) ; 02400 } 02401 02402 // Middle sign 02403 int s = getSign( cs[0], 0 ) ; 02404 02405 // Masks 02406 int fcCells[4] = {1,0,1,0}; 02407 int fcEdges[3][4][3] = { 02408 {{9,2,11},{8,1,10},{5,1,7},{4,2,6}}, 02409 {{10,6,11},{8,5,9},{1,5,3},{0,6,2}}, 02410 {{6,10,7},{4,9,5},{2,9,3},{0,10,1}} 02411 }; 02412 02413 // Search for neighboring connected intersection edges 02414 for ( int find = 0 ; find < 4 ; find ++ ) 02415 { 02416 int cind = fcCells[find] ; 02417 int eind, edge ; 02418 if ( s == 0 ) 02419 { 02420 // Original order 02421 for ( eind = 0 ; eind < 3 ; eind ++ ) 02422 { 02423 edge = fcEdges[dir][find][eind] ; 02424 if ( getEdgeParity( cs[cind], edge ) == 1 ) 02425 { 02426 break ; 02427 } 02428 } 02429 } 02430 else 02431 { 02432 // Inverse order 02433 for ( eind = 2 ; eind >= 0 ; eind -- ) 02434 { 02435 edge = fcEdges[dir][find][eind] ; 02436 if ( getEdgeParity( cs[cind], edge ) == 1 ) 02437 { 02438 break ; 02439 } 02440 } 02441 } 02442 02443 if ( eind == 3 || eind == -1 ) 02444 { 02445 dc_printf("Wrong! this is not a consistent sign. %d\n", eind ); 02446 } 02447 else 02448 { 02449 int est[3] ; 02450 est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ; 02451 est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ; 02452 est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ; 02453 int edir = edge / 4 ; 02454 02455 if ( isInProcess( cs[cind], edge ) == 0 ) 02456 { 02457 setInProcessAll( est, edir ) ; 02458 queue->pushQueue( est, edir ) ; 02459 // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ; 02460 total ++ ; 02461 } 02462 else 02463 { 02464 // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ; 02465 } 02466 } 02467 02468 } 02469 02470 } 02471 02472 dc_printf("Size of component: %d ", total) ; 02473 02474 if ( total > threshold ) 02475 { 02476 dc_printf("Maintained.\n") ; 02477 continue ; 02478 } 02479 dc_printf("Less then %d, removing...\n", threshold) ; 02480 02481 // We have to remove this noise 02482 02483 // Flip parity 02484 // setOutProcessAll( mst, mdir ) ; 02485 flipParityAll( mst, mdir ) ; 02486 02487 // Put this edge into queue 02488 queue->pushQueue( mst, mdir ) ; 02489 02490 // Queue processing 02491 while ( queue->popQueue( nst, dir ) == 1 ) 02492 { 02493 // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ; 02494 // locations 02495 int stMask[3][3] = { 02496 { 0, 0 - len, 0 - len }, 02497 { 0 - len, 0, 0 - len }, 02498 { 0 - len, 0 - len, 0 } 02499 }; 02500 int cst[2][3] ; 02501 for ( j = 0 ; j < 3 ; j ++ ) 02502 { 02503 cst[0][j] = nst[j] ; 02504 cst[1][j] = nst[j] + stMask[ dir ][ j ] ; 02505 } 02506 02507 // cells 02508 UCHAR* cs[2] ; 02509 for ( j = 0 ; j < 2 ; j ++ ) 02510 { 02511 cs[ j ] = locateLeaf( cst[j] ) ; 02512 } 02513 02514 // Middle sign 02515 int s = getSign( cs[0], 0 ) ; 02516 02517 // Masks 02518 int fcCells[4] = {1,0,1,0}; 02519 int fcEdges[3][4][3] = { 02520 {{9,2,11},{8,1,10},{5,1,7},{4,2,6}}, 02521 {{10,6,11},{8,5,9},{1,5,3},{0,6,2}}, 02522 {{6,10,7},{4,9,5},{2,9,3},{0,10,1}} 02523 }; 02524 02525 // Search for neighboring connected intersection edges 02526 for ( int find = 0 ; find < 4 ; find ++ ) 02527 { 02528 int cind = fcCells[find] ; 02529 int eind, edge ; 02530 if ( s == 0 ) 02531 { 02532 // Original order 02533 for ( eind = 0 ; eind < 3 ; eind ++ ) 02534 { 02535 edge = fcEdges[dir][find][eind] ; 02536 if ( isInProcess( cs[cind], edge ) == 1 ) 02537 { 02538 break ; 02539 } 02540 } 02541 } 02542 else 02543 { 02544 // Inverse order 02545 for ( eind = 2 ; eind >= 0 ; eind -- ) 02546 { 02547 edge = fcEdges[dir][find][eind] ; 02548 if ( isInProcess( cs[cind], edge ) == 1 ) 02549 { 02550 break ; 02551 } 02552 } 02553 } 02554 02555 if ( eind == 3 || eind == -1 ) 02556 { 02557 dc_printf("Wrong! this is not a consistent sign. %d\n", eind ); 02558 } 02559 else 02560 { 02561 int est[3] ; 02562 est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ; 02563 est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ; 02564 est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ; 02565 int edir = edge / 4 ; 02566 02567 if ( getEdgeParity( cs[cind], edge ) == 1 ) 02568 { 02569 flipParityAll( est, edir ) ; 02570 queue->pushQueue( est, edir ) ; 02571 // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ; 02572 total ++ ; 02573 } 02574 else 02575 { 02576 // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ; 02577 } 02578 } 02579 02580 } 02581 02582 } 02583 02584 } 02585 } 02586 } 02587 else 02588 { 02589 // Internal cell, recur 02590 int count = 0 ; 02591 len >>= 1 ; 02592 for ( i = 0 ; i < 8 ; i ++ ) 02593 { 02594 if ( hasChild( node, i ) ) 02595 { 02596 int nst[3] ; 02597 nst[0] = st[0] + vertmap[i][0] * len ; 02598 nst[1] = st[1] + vertmap[i][1] * len ; 02599 nst[2] = st[2] + vertmap[i][2] * len ; 02600 02601 floodFill( getChild( node, count ), nst, len, height - 1, threshold ) ; 02602 count ++ ; 02603 } 02604 } 02605 } 02606 } 02607 */ 02608 02609 int Octree::floodFill( UCHAR* node, int st[3], int len, int height, int threshold ) 02610 { 02611 int i, j; 02612 int maxtotal = 0 ; 02613 02614 if ( height == 0 ) 02615 { 02616 // Leaf cell, 02617 int par, inp ; 02618 02619 // Test if the leaf has intersection edges 02620 for ( i = 0 ; i < 12 ; i ++ ) 02621 { 02622 par = getEdgeParity( node, i ) ; 02623 inp = isInProcess( node, i ) ; 02624 02625 if ( par == 1 && inp == 0 ) 02626 { 02627 // Intersection edge, hasn't been processed 02628 // Let's start filling 02629 GridQueue* queue = new GridQueue() ; 02630 int total = 1 ; 02631 02632 // Set to in process 02633 int mst[3] ; 02634 mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len ; 02635 mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len ; 02636 mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len; 02637 int mdir = i / 4 ; 02638 setInProcessAll( mst, mdir ) ; 02639 02640 // Put this edge into queue 02641 queue->pushQueue( mst, mdir ) ; 02642 02643 // Queue processing 02644 int nst[3], dir ; 02645 while ( queue->popQueue( nst, dir ) == 1 ) 02646 { 02647 // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ; 02648 // locations 02649 int stMask[3][3] = { 02650 { 0, 0 - len, 0 - len }, 02651 { 0 - len, 0, 0 - len }, 02652 { 0 - len, 0 - len, 0 } 02653 }; 02654 int cst[2][3] ; 02655 for ( j = 0 ; j < 3 ; j ++ ) 02656 { 02657 cst[0][j] = nst[j] ; 02658 cst[1][j] = nst[j] + stMask[ dir ][ j ] ; 02659 } 02660 02661 // cells 02662 UCHAR* cs[2] ; 02663 for ( j = 0 ; j < 2 ; j ++ ) 02664 { 02665 cs[ j ] = locateLeaf( cst[j] ) ; 02666 } 02667 02668 // Middle sign 02669 int s = getSign( cs[0], 0 ) ; 02670 02671 // Masks 02672 int fcCells[4] = {1,0,1,0}; 02673 int fcEdges[3][4][3] = { 02674 {{9,2,11},{8,1,10},{5,1,7},{4,2,6}}, 02675 {{10,6,11},{8,5,9},{1,5,3},{0,6,2}}, 02676 {{6,10,7},{4,9,5},{2,9,3},{0,10,1}} 02677 }; 02678 02679 // Search for neighboring connected intersection edges 02680 for ( int find = 0 ; find < 4 ; find ++ ) 02681 { 02682 int cind = fcCells[find] ; 02683 int eind, edge ; 02684 if ( s == 0 ) 02685 { 02686 // Original order 02687 for ( eind = 0 ; eind < 3 ; eind ++ ) 02688 { 02689 edge = fcEdges[dir][find][eind] ; 02690 if ( getEdgeParity( cs[cind], edge ) == 1 ) 02691 { 02692 break ; 02693 } 02694 } 02695 } 02696 else 02697 { 02698 // Inverse order 02699 for ( eind = 2 ; eind >= 0 ; eind -- ) 02700 { 02701 edge = fcEdges[dir][find][eind] ; 02702 if ( getEdgeParity( cs[cind], edge ) == 1 ) 02703 { 02704 break ; 02705 } 02706 } 02707 } 02708 02709 if ( eind == 3 || eind == -1 ) 02710 { 02711 dc_printf("Wrong! this is not a consistent sign. %d\n", eind ); 02712 } 02713 else 02714 { 02715 int est[3] ; 02716 est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ; 02717 est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ; 02718 est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ; 02719 int edir = edge / 4 ; 02720 02721 if ( isInProcess( cs[cind], edge ) == 0 ) 02722 { 02723 setInProcessAll( est, edir ) ; 02724 queue->pushQueue( est, edir ) ; 02725 // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ; 02726 total ++ ; 02727 } 02728 else 02729 { 02730 // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ; 02731 } 02732 } 02733 02734 } 02735 02736 } 02737 02738 dc_printf("Size of component: %d ", total) ; 02739 02740 if ( threshold == 0 ) 02741 { 02742 // Measuring stage 02743 if ( total > maxtotal ) 02744 { 02745 maxtotal = total ; 02746 } 02747 dc_printf(".\n") ; 02748 continue ; 02749 } 02750 02751 if ( total >= threshold ) 02752 { 02753 dc_printf("Maintained.\n") ; 02754 continue ; 02755 } 02756 dc_printf("Less then %d, removing...\n", threshold) ; 02757 02758 // We have to remove this noise 02759 02760 // Flip parity 02761 // setOutProcessAll( mst, mdir ) ; 02762 flipParityAll( mst, mdir ) ; 02763 02764 // Put this edge into queue 02765 queue->pushQueue( mst, mdir ) ; 02766 02767 // Queue processing 02768 while ( queue->popQueue( nst, dir ) == 1 ) 02769 { 02770 // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ; 02771 // locations 02772 int stMask[3][3] = { 02773 { 0, 0 - len, 0 - len }, 02774 { 0 - len, 0, 0 - len }, 02775 { 0 - len, 0 - len, 0 } 02776 }; 02777 int cst[2][3] ; 02778 for ( j = 0 ; j < 3 ; j ++ ) 02779 { 02780 cst[0][j] = nst[j] ; 02781 cst[1][j] = nst[j] + stMask[ dir ][ j ] ; 02782 } 02783 02784 // cells 02785 UCHAR* cs[2] ; 02786 for ( j = 0 ; j < 2 ; j ++ ) 02787 { 02788 cs[ j ] = locateLeaf( cst[j] ) ; 02789 } 02790 02791 // Middle sign 02792 int s = getSign( cs[0], 0 ) ; 02793 02794 // Masks 02795 int fcCells[4] = {1,0,1,0}; 02796 int fcEdges[3][4][3] = { 02797 {{9,2,11},{8,1,10},{5,1,7},{4,2,6}}, 02798 {{10,6,11},{8,5,9},{1,5,3},{0,6,2}}, 02799 {{6,10,7},{4,9,5},{2,9,3},{0,10,1}} 02800 }; 02801 02802 // Search for neighboring connected intersection edges 02803 for ( int find = 0 ; find < 4 ; find ++ ) 02804 { 02805 int cind = fcCells[find] ; 02806 int eind, edge ; 02807 if ( s == 0 ) 02808 { 02809 // Original order 02810 for ( eind = 0 ; eind < 3 ; eind ++ ) 02811 { 02812 edge = fcEdges[dir][find][eind] ; 02813 if ( isInProcess( cs[cind], edge ) == 1 ) 02814 { 02815 break ; 02816 } 02817 } 02818 } 02819 else 02820 { 02821 // Inverse order 02822 for ( eind = 2 ; eind >= 0 ; eind -- ) 02823 { 02824 edge = fcEdges[dir][find][eind] ; 02825 if ( isInProcess( cs[cind], edge ) == 1 ) 02826 { 02827 break ; 02828 } 02829 } 02830 } 02831 02832 if ( eind == 3 || eind == -1 ) 02833 { 02834 dc_printf("Wrong! this is not a consistent sign. %d\n", eind ); 02835 } 02836 else 02837 { 02838 int est[3] ; 02839 est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ; 02840 est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ; 02841 est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ; 02842 int edir = edge / 4 ; 02843 02844 if ( getEdgeParity( cs[cind], edge ) == 1 ) 02845 { 02846 flipParityAll( est, edir ) ; 02847 queue->pushQueue( est, edir ) ; 02848 // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ; 02849 total ++ ; 02850 } 02851 else 02852 { 02853 // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ; 02854 } 02855 } 02856 02857 } 02858 02859 } 02860 02861 } 02862 } 02863 02864 } 02865 else 02866 { 02867 // Internal cell, recur 02868 int count = 0 ; 02869 len >>= 1 ; 02870 for ( i = 0 ; i < 8 ; i ++ ) 02871 { 02872 if ( hasChild( node, i ) ) 02873 { 02874 int nst[3] ; 02875 nst[0] = st[0] + vertmap[i][0] * len ; 02876 nst[1] = st[1] + vertmap[i][1] * len ; 02877 nst[2] = st[2] + vertmap[i][2] * len ; 02878 02879 int d = floodFill( getChild( node, count ), nst, len, height - 1, threshold ) ; 02880 if ( d > maxtotal) 02881 { 02882 maxtotal = d ; 02883 } 02884 count ++ ; 02885 } 02886 } 02887 } 02888 02889 02890 return maxtotal ; 02891 02892 } 02893 02894 void Octree::writeOut() 02895 { 02896 int numQuads = 0 ; 02897 int numVertices = 0 ; 02898 int numEdges = 0 ; 02899 #ifdef USE_HERMIT 02900 countIntersection( root, maxDepth, numQuads, numVertices, numEdges ) ; 02901 #else 02902 countIntersection( root, maxDepth, numQuads, numVertices ) ; 02903 numEdges = numQuads * 3 / 2 ; 02904 #endif 02905 dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads ) ; 02906 output_mesh = alloc_output(numVertices, numQuads); 02907 int offset = 0 ; 02908 int st[3] = { 0, 0, 0 } ; 02909 02910 // First, output vertices 02911 offset = 0 ; 02912 actualVerts = 0 ; 02913 actualQuads = 0 ; 02914 #ifdef USE_HERMIT 02915 generateMinimizer( root, st, dimen, maxDepth, offset ) ; 02916 cellProcContour( this->root, 0, maxDepth ) ; 02917 dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads ) ; 02918 #else 02919 writeVertex( root, st, dimen, maxDepth, offset, out ) ; 02920 writeQuad( root, st, dimen, maxDepth, out ) ; 02921 dc_printf("Vertices written: %d Triangles written: %d \n", offset, actualQuads ) ; 02922 #endif 02923 } 02924 02925 #if 0 02926 void Octree::writePLY( char* fname ) 02927 { 02928 int numQuads = 0 ; 02929 int numVertices = 0 ; 02930 int numEdges = 0 ; 02931 #ifdef USE_HERMIT 02932 countIntersection( root, maxDepth, numQuads, numVertices, numEdges ) ; 02933 #else 02934 countIntersection( root, maxDepth, numQuads, numVertices ) ; 02935 numEdges = numQuads * 3 / 2 ; 02936 #endif 02937 // int euler = numVertices + numQuads - numEdges ; 02938 // int genus = ( 2 - euler ) / 2 ; 02939 // dc_printf("%d vertices %d quads %d edges\n", numVertices, numQuads, numEdges ) ; 02940 // dc_printf("Genus: %d Euler: %d\n", genus, euler ) ; 02941 02942 FILE* fout = fopen ( fname, "wb" ) ; 02943 dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads ) ; 02944 PLYWriter::writeHeader( fout, numVertices, numQuads ) ; 02945 int offset = 0 ; 02946 int st[3] = { 0, 0, 0 } ; 02947 02948 // First, output vertices 02949 offset = 0 ; 02950 actualVerts = 0 ; 02951 actualQuads = 0 ; 02952 #ifdef USE_HERMIT 02953 generateMinimizer( root, st, dimen, maxDepth, offset, fout ) ; 02954 #ifdef TESTMANIFOLD 02955 testfout = fopen("test.txt", "w"); 02956 fprintf(testfout, "{"); 02957 #endif 02958 cellProcContour( this->root, 0, maxDepth, fout ) ; 02959 #ifdef TESTMANIFOLD 02960 fprintf(testfout, "}"); 02961 fclose( testfout ) ; 02962 #endif 02963 dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads ) ; 02964 #else 02965 writeVertex( root, st, dimen, maxDepth, offset, fout ) ; 02966 writeQuad( root, st, dimen, maxDepth, fout ) ; 02967 dc_printf("Vertices written: %d Triangles written: %d \n", offset, actualQuads ) ; 02968 #endif 02969 02970 02971 fclose( fout ) ; 02972 } 02973 #endif 02974 02975 void Octree::writeOctree( char* fname ) 02976 { 02977 FILE* fout = fopen ( fname, "wb" ) ; 02978 02979 int sized = ( 1 << maxDepth ) ; 02980 fwrite( &sized, sizeof( int ), 1, fout ) ; 02981 writeOctree( fout, root, maxDepth ) ; 02982 dc_printf("Grid dimension: %d\n", sized ) ; 02983 02984 02985 fclose( fout ) ; 02986 } 02987 void Octree::writeOctree( FILE* fout, UCHAR* node, int depth ) 02988 { 02989 char type ; 02990 if ( depth > 0 ) 02991 { 02992 type = 0 ; 02993 fwrite( &type, sizeof( char ), 1, fout ) ; 02994 02995 // Get sign at the center 02996 char sg = (char) getSign( getChild( node, 0 ), depth - 1, 7 - getChildIndex( node, 0 ) ) ; 02997 02998 int t = 0 ; 02999 for ( int i = 0 ; i < 8 ; i ++ ) 03000 { 03001 if ( hasChild( node, i ) ) 03002 { 03003 writeOctree( fout, getChild( node, t ), depth - 1 ) ; 03004 t ++ ; 03005 } 03006 else 03007 { 03008 type = 1 ; 03009 fwrite( &type, sizeof( char ), 1, fout ) ; 03010 fwrite( &sg, sizeof( char ), 1, fout ) ; 03011 } 03012 } 03013 } 03014 else 03015 { 03016 type = 2 ; 03017 fwrite( &type, sizeof( char ), 1, fout ) ; 03018 fwrite( &(node[2]), sizeof ( UCHAR ), 1, fout ); 03019 } 03020 } 03021 03022 #ifdef USE_HERMIT 03023 #if 0 03024 void Octree::writeOctreeGeom( char* fname ) 03025 { 03026 FILE* fout = fopen ( fname, "wb" ) ; 03027 03028 // Write header 03029 char header[]="SOG.Format 1.0"; 03030 int nlen = 128 - 4 * 4 - strlen(header) - 1 ; 03031 char* header2 = new char[ nlen ]; 03032 for ( int i = 0 ; i < nlen ; i ++ ) 03033 { 03034 header2[i] = '\0'; 03035 } 03036 fwrite( header, sizeof( char ), strlen(header) + 1, fout ) ; 03037 fwrite( origin, sizeof( float ), 3, fout ) ; 03038 fwrite( &range, sizeof( float ), 1, fout ) ; 03039 fwrite( header2, sizeof( char ), nlen, fout ) ; 03040 03041 03042 int sized = ( 1 << maxDepth ) ; 03043 int st[3] = {0,0,0}; 03044 fwrite( &sized, sizeof( int ), 1, fout ) ; 03045 03046 writeOctreeGeom( fout, root, st, dimen, maxDepth ) ; 03047 dc_printf("Grid dimension: %d\n", sized ) ; 03048 03049 03050 fclose( fout ) ; 03051 } 03052 #endif 03053 void Octree::writeOctreeGeom( FILE* fout, UCHAR* node, int st[3], int len, int depth ) 03054 { 03055 char type ; 03056 if ( depth > 0 ) 03057 { 03058 type = 0 ; 03059 fwrite( &type, sizeof( char ), 1, fout ) ; 03060 03061 // Get sign at the center 03062 char sg = (char) getSign( getChild( node, 0 ), depth - 1, 7 - getChildIndex( node, 0 ) ) ; 03063 03064 int t = 0 ; 03065 len >>= 1 ; 03066 for ( int i = 0 ; i < 8 ; i ++ ) 03067 { 03068 if ( hasChild( node, i ) ) 03069 { 03070 int nst[3] ; 03071 nst[0] = st[0] + vertmap[i][0] * len ; 03072 nst[1] = st[1] + vertmap[i][1] * len ; 03073 nst[2] = st[2] + vertmap[i][2] * len ; 03074 writeOctreeGeom( fout, getChild( node, t ), nst, len, depth - 1 ) ; 03075 t ++ ; 03076 } 03077 else 03078 { 03079 type = 1 ; 03080 fwrite( &type, sizeof( char ), 1, fout ) ; 03081 fwrite( &sg, sizeof( char ), 1, fout ) ; 03082 } 03083 } 03084 } 03085 else 03086 { 03087 type = 2 ; 03088 fwrite( &type, sizeof( char ), 1, fout ) ; 03089 fwrite( &(node[2]), sizeof ( UCHAR ), 1, fout ); 03090 03091 // Compute minimizer 03092 // First, find minimizer 03093 float rvalue[3] ; 03094 rvalue[0] = (float) st[0] + len / 2 ; 03095 rvalue[1] = (float) st[1] + len / 2 ; 03096 rvalue[2] = (float) st[2] + len / 2 ; 03097 computeMinimizer( node, st, len, rvalue ) ; 03098 03099 // Update 03100 // float flen = len * range / dimen ; 03101 for ( int j = 0 ; j < 3 ; j ++ ) 03102 { 03103 rvalue[ j ] = rvalue[ j ] * range / dimen + origin[ j ] ; 03104 } 03105 03106 fwrite( rvalue, sizeof ( float ), 3, fout ); 03107 } 03108 } 03109 #endif 03110 03111 #ifdef USE_HERMIT 03112 void Octree::writeDCF( char* fname ) 03113 { 03114 FILE* fout = fopen ( fname, "wb" ) ; 03115 03116 // Writing out version 03117 char version[10] = "multisign"; 03118 fwrite ( &version, sizeof ( char ), 10, fout ); 03119 03120 // Writing out size 03121 int sized = ( 1 << maxDepth ) ; 03122 fwrite( &sized, sizeof( int ), 1, fout ) ; 03123 fwrite( &sized, sizeof( int ), 1, fout ) ; 03124 fwrite( &sized, sizeof( int ), 1, fout ) ; 03125 03126 int st[3] = {0, 0, 0} ; 03127 writeDCF( fout, root, maxDepth, st, dimen ) ; 03128 03129 dc_printf("Grid dimension: %d\n", sized ) ; 03130 fclose( fout ) ; 03131 } 03132 03133 void Octree::writeDCF( FILE* fout, UCHAR* node, int height, int st[3], int len ) 03134 { 03135 nodetype type ; 03136 if ( height > 0 ) 03137 { 03138 type = 0 ; 03139 len >>= 1 ; 03140 fwrite( &type, sizeof( nodetype ), 1, fout ) ; 03141 03142 // Get sign at the center 03143 signtype sg = 1 - (signtype) getSign( getChild( node, 0 ), height - 1, 7 - getChildIndex( node, 0 ) ) ; 03144 03145 int t = 0 ; 03146 for ( int i = 0 ; i < 8 ; i ++ ) 03147 { 03148 if ( hasChild( node, i ) ) 03149 { 03150 int nst[3] ; 03151 nst[0] = st[0] + vertmap[i][0] * len ; 03152 nst[1] = st[1] + vertmap[i][1] * len ; 03153 nst[2] = st[2] + vertmap[i][2] * len ; 03154 03155 03156 writeDCF( fout, getChild( node, t ), height - 1, nst, len ) ; 03157 t ++ ; 03158 } 03159 else 03160 { 03161 type = 1 ; 03162 fwrite( &type, sizeof( nodetype ), 1, fout ) ; 03163 fwrite ( &(sg), sizeof ( signtype ), 1, fout ); 03164 } 03165 } 03166 } 03167 else 03168 { 03169 type = 2 ; 03170 fwrite( &type, sizeof( nodetype ), 1, fout ) ; 03171 03172 // Write signs 03173 signtype sgn[8] ; 03174 for ( int i = 0 ; i < 8 ; i ++ ) 03175 { 03176 sgn[ i ] = 1 - (signtype) getSign( node, i ) ; 03177 } 03178 fwrite (sgn, sizeof (signtype), 8, fout ); 03179 03180 // Write edge data 03181 float pts[12], norms[12][3] ; 03182 int parity[12] ; 03183 fillEdgeOffsetsNormals( node, st, len, pts, norms, parity ) ; 03184 03185 numtype zero = 0, one = 1 ; 03186 for ( int i = 0 ; i < 12 ; i ++ ) 03187 { 03188 int par = getEdgeParity( node, i ) ; 03189 // Let's check first 03190 if ( par ) 03191 { 03192 if ( sgn[ edgemap[i][0] ] == sgn[ edgemap[i][1] ] ) 03193 { 03194 dc_printf("Wrong! Parity: %d Sign: %d %d\n", parity[i], sgn[ edgemap[i][0] ], sgn[ edgemap[i][1] ]); 03195 exit(0) ; 03196 } 03197 if ( parity[ i ] == 0 ) 03198 { 03199 dc_printf("Wrong! No intersection found.\n"); 03200 exit(0) ; 03201 } 03202 fwrite( &one, sizeof ( numtype ) , 1, fout ) ; 03203 fwrite( &(pts[i]), sizeof( float ), 1, fout ) ; 03204 fwrite( norms[i], sizeof( float ), 3, fout ) ; 03205 03206 } 03207 else 03208 { 03209 if ( sgn[ edgemap[i][0] ] != sgn[ edgemap[i][1] ] ) 03210 { 03211 dc_printf("Wrong! Parity: %d Sign: %d %d\n", parity[i], sgn[ edgemap[i][0] ], sgn[ edgemap[i][1] ]); 03212 exit(0) ; 03213 } 03214 fwrite ( &zero, sizeof ( numtype ) , 1, fout ); 03215 } 03216 } 03217 } 03218 } 03219 #endif 03220 03221 03222 void Octree::writeOpenEdges( FILE* fout ) 03223 { 03224 // Total number of rings 03225 fprintf( fout, "%d\n", numRings ) ; 03226 dc_printf("Number of rings to write: %d\n", numRings) ; 03227 03228 // Write each ring 03229 PathList* tlist = ringList ; 03230 for ( int i = 0 ; i < numRings ; i ++ ) 03231 { 03232 fprintf(fout, "%d\n", tlist->length) ; 03233 // dc_printf("Ring length: %d\n", tlist->length ) ; 03234 PathElement* cur = tlist->head ; 03235 for ( int j = 0 ; j < tlist->length ; j ++ ) 03236 { 03237 float cent[3] ; 03238 float flen = mindimen * range / dimen ; 03239 for ( int k = 0 ; k < 3 ; k ++ ) 03240 { 03241 cent[ k ] = cur->pos[ k ] * range / dimen + origin[ k ] + flen / 2 ; 03242 } 03243 fprintf(fout, "%f %f %f\n", cent[0], cent[1], cent[2]) ; 03244 cur = cur->next ; 03245 } 03246 03247 tlist = tlist->next ; 03248 } 03249 } 03250 03251 #ifndef USE_HERMIT 03252 void Octree::countIntersection( UCHAR* node, int height, int& nquad, int& nvert ) 03253 { 03254 if ( height > 0 ) 03255 { 03256 int total = getNumChildren( node ) ; 03257 for ( int i = 0 ; i < total ; i ++ ) 03258 { 03259 countIntersection( getChild( node, i ), height - 1, nquad, nvert ) ; 03260 } 03261 } 03262 else 03263 { 03264 int mask = getSignMask( node ) ; 03265 nvert += getNumEdges2( node ) ; 03266 nquad += cubes->getNumTriangle( mask ) ; 03267 03268 } 03269 } 03270 03271 void Octree::writeVertex( UCHAR* node, int st[3], int len, int height, int& offset, FILE* fout ) 03272 { 03273 int i ; 03274 03275 if ( height == 0 ) 03276 { 03277 // Leaf cell, generate 03278 int emap[] = { 0, 4, 8 } ; 03279 for ( int i = 0 ; i < 3 ; i ++ ) 03280 { 03281 if ( getEdgeParity( node, emap[i] ) ) 03282 { 03283 // Get intersection location 03284 int count = getEdgeCount( node, i ) ; 03285 float off = getEdgeOffset( node, count ) ; 03286 03287 float rvalue[3] ; 03288 rvalue[0] = (float) st[0] ; 03289 rvalue[1] = (float) st[1] ; 03290 rvalue[2] = (float) st[2] ; 03291 rvalue[i] += off * mindimen ; 03292 03293 // Update 03294 float fnst[3] ; 03295 float flen = len * range / dimen ; 03296 for ( int j = 0 ; j < 3 ; j ++ ) 03297 { 03298 rvalue[ j ] = rvalue[ j ] * range / dimen + origin[ j ] ; 03299 fnst[ j ] = st[ j ] * range / dimen + origin[ j ] ; 03300 } 03301 03302 if ( this->outType == 0 ) 03303 { 03304 fprintf( fout, "%f %f %f\n", rvalue[0], rvalue[1], rvalue[2] ) ; 03305 } 03306 else if ( this->outType == 1 ) 03307 { 03308 PLYWriter::writeVertex( fout, rvalue ) ; 03309 } 03310 03311 // Store the index 03312 setEdgeIntersectionIndex( node, count, offset ) ; 03313 offset ++ ; 03314 } 03315 } 03316 03317 } 03318 else 03319 { 03320 // Internal cell, recur 03321 int count = 0 ; 03322 len >>= 1 ; 03323 for ( i = 0 ; i < 8 ; i ++ ) 03324 { 03325 if ( hasChild( node, i ) ) 03326 { 03327 int nst[3] ; 03328 nst[0] = st[0] + vertmap[i][0] * len ; 03329 nst[1] = st[1] + vertmap[i][1] * len ; 03330 nst[2] = st[2] + vertmap[i][2] * len ; 03331 03332 writeVertex( getChild( node, count ), nst, len, height - 1, offset, fout ) ; 03333 count ++ ; 03334 } 03335 } 03336 } 03337 } 03338 03339 void Octree::writeQuad( UCHAR* node, int st[3], int len, int height, FILE* fout ) 03340 { 03341 int i ; 03342 if ( height == 0 ) 03343 { 03344 int mask = getSignMask( node ) ; 03345 int num = cubes->getNumTriangle( mask ) ; 03346 int indices[12] ; 03347 fillEdgeIntersectionIndices( node, st, len, indices ) ; 03348 int einds[3], ind[3] ; 03349 03350 //int flag1 = 0 ; 03351 //int flag2 = 0 ; 03352 for ( i = 0 ; i < num ; i ++ ) 03353 { 03354 int color = 0 ; 03355 cubes->getTriangle( mask, i, einds ) ; 03356 // dc_printf("(%d %d %d) ", einds[0], einds[1], einds[2] ) ; 03357 03358 for ( int j = 0 ; j < 3 ; j ++ ) 03359 { 03360 ind[j] = indices[ einds[j] ] ; 03361 /* 03362 if ( ind[j] == 78381 ) 03363 { 03364 flag1 = 1 ; 03365 } 03366 if ( ind[j] == 78384 ) 03367 { 03368 flag2 = 1 ; 03369 } 03370 */ 03371 } 03372 03373 if ( this->outType == 0 ) 03374 { 03375 // OFF 03376 int numpoly = ( color ? -3 : 3 ) ; 03377 fprintf(fout, "%d %d %d %d\n", numpoly, ind[0], ind[1], ind[2] ) ; 03378 actualQuads ++ ; 03379 } 03380 else if ( this->outType == 1 ) 03381 { 03382 // PLY 03383 PLYWriter::writeFace( fout, 3, ind ) ; 03384 actualQuads ++ ; 03385 } 03386 } 03387 03388 /* 03389 if (flag1 && flag2) 03390 { 03391 dc_printf("%d\n", mask); 03392 cubes->printTriangles( mask ) ; 03393 } 03394 */ 03395 } 03396 else 03397 { 03398 // Internal cell, recur 03399 int count = 0 ; 03400 len >>= 1 ; 03401 for ( i = 0 ; i < 8 ; i ++ ) 03402 { 03403 if ( hasChild( node, i ) ) 03404 { 03405 int nst[3] ; 03406 nst[0] = st[0] + vertmap[i][0] * len ; 03407 nst[1] = st[1] + vertmap[i][1] * len ; 03408 nst[2] = st[2] + vertmap[i][2] * len ; 03409 03410 writeQuad( getChild( node, count ), nst, len, height - 1, fout ) ; 03411 count ++ ; 03412 } 03413 } 03414 } 03415 } 03416 03417 #endif 03418 03419 03420 #ifdef USE_HERMIT 03421 void Octree::countIntersection( UCHAR* node, int height, int& nedge, int& ncell, int& nface ) 03422 { 03423 if ( height > 0 ) 03424 { 03425 int total = getNumChildren( node ) ; 03426 for ( int i = 0 ; i < total ; i ++ ) 03427 { 03428 countIntersection( getChild( node, i ), height - 1, nedge, ncell, nface ) ; 03429 } 03430 } 03431 else 03432 { 03433 nedge += getNumEdges2( node ) ; 03434 03435 int smask = getSignMask( node ) ; 03436 03437 if(use_manifold) 03438 { 03439 int comps = manifold_table[ smask ].comps ; 03440 ncell += comps ; 03441 } 03442 else { 03443 if ( smask > 0 && smask < 255 ) 03444 { 03445 ncell ++ ; 03446 } 03447 } 03448 03449 for ( int i = 0 ; i < 3 ; i ++ ) 03450 { 03451 if ( getFaceEdgeNum( node, i * 2 ) ) 03452 { 03453 nface ++ ; 03454 } 03455 } 03456 } 03457 } 03458 03459 /* from http://eigen.tuxfamily.org/bz/show_bug.cgi?id=257 */ 03460 template<typename _Matrix_Type_> 03461 void pseudoInverse(const _Matrix_Type_ &a, 03462 _Matrix_Type_ &result, 03463 double epsilon = std::numeric_limits<typename _Matrix_Type_::Scalar>::epsilon()) 03464 { 03465 Eigen::JacobiSVD< _Matrix_Type_ > svd = a.jacobiSvd(Eigen::ComputeFullU | 03466 Eigen::ComputeFullV); 03467 03468 typename _Matrix_Type_::Scalar tolerance = epsilon * std::max(a.cols(), 03469 a.rows()) * 03470 svd.singularValues().array().abs().maxCoeff(); 03471 03472 result = svd.matrixV() * 03473 _Matrix_Type_((svd.singularValues().array().abs() > 03474 tolerance).select(svd.singularValues(). 03475 array().inverse(), 0)).asDiagonal() * 03476 svd.matrixU().adjoint(); 03477 } 03478 03479 void solve_least_squares(const float halfA[], const float b[], 03480 const float midpoint[], float rvalue[]) 03481 { 03482 /* calculate pseudo-inverse */ 03483 Eigen::MatrixXf A(3, 3), pinv(3, 3); 03484 A << halfA[0], halfA[1], halfA[2], 03485 halfA[1], halfA[3], halfA[4], 03486 halfA[2], halfA[4], halfA[5]; 03487 pseudoInverse(A, pinv); 03488 03489 Eigen::Vector3f b2(b), mp(midpoint), result; 03490 b2 = b2 + A * -mp; 03491 result = pinv * b2 + mp; 03492 03493 for(int i = 0; i < 3; i++) 03494 rvalue[i] = result(i); 03495 } 03496 03497 void minimize(float rvalue[3], float mp[3], const float pts[12][3], 03498 const float norms[12][3], const int parity[12]) 03499 { 03500 float ata[6] = { 0, 0, 0, 0, 0, 0 }; 03501 float atb[3] = { 0, 0, 0 } ; 03502 int ec = 0 ; 03503 03504 for ( int i = 0 ; i < 12 ; i ++ ) 03505 { 03506 // if ( getEdgeParity( leaf, i) ) 03507 if ( parity[ i ] ) 03508 { 03509 const float* norm = norms[i] ; 03510 const float* p = pts[i] ; 03511 03512 // QEF 03513 ata[ 0 ] += (float) ( norm[ 0 ] * norm[ 0 ] ); 03514 ata[ 1 ] += (float) ( norm[ 0 ] * norm[ 1 ] ); 03515 ata[ 2 ] += (float) ( norm[ 0 ] * norm[ 2 ] ); 03516 ata[ 3 ] += (float) ( norm[ 1 ] * norm[ 1 ] ); 03517 ata[ 4 ] += (float) ( norm[ 1 ] * norm[ 2 ] ); 03518 ata[ 5 ] += (float) ( norm[ 2 ] * norm[ 2 ] ); 03519 03520 double pn = p[0] * norm[0] + p[1] * norm[1] + p[2] * norm[2] ; 03521 03522 atb[ 0 ] += (float) ( norm[ 0 ] * pn ) ; 03523 atb[ 1 ] += (float) ( norm[ 1 ] * pn ) ; 03524 atb[ 2 ] += (float) ( norm[ 2 ] * pn ) ; 03525 03526 // Minimizer 03527 mp[0] += p[0] ; 03528 mp[1] += p[1] ; 03529 mp[2] += p[2] ; 03530 03531 ec ++ ; 03532 } 03533 } 03534 03535 if ( ec == 0 ) 03536 { 03537 return ; 03538 } 03539 mp[0] /= ec ; 03540 mp[1] /= ec ; 03541 mp[2] /= ec ; 03542 03543 // Solve least squares 03544 solve_least_squares(ata, atb, mp, rvalue); 03545 } 03546 03547 void Octree::computeMinimizer( UCHAR* leaf, int st[3], int len, float rvalue[3] ) 03548 { 03549 // First, gather all edge intersections 03550 float pts[12][3], norms[12][3] ; 03551 // fillEdgeIntersections( leaf, st, len, pts, norms ) ; 03552 int parity[12] ; 03553 fillEdgeIntersections( leaf, st, len, pts, norms, parity ) ; 03554 03555 // Next, construct QEF and minimizer 03556 float mp[3] = {0, 0, 0}; 03557 minimize(rvalue, mp, pts, norms, parity); 03558 03559 /* Restraining the location of the minimizer */ 03560 float nh1 = hermite_num * len ; 03561 float nh2 = ( 1 + hermite_num ) * len ; 03562 if((mode == DUALCON_MASS_POINT || mode == DUALCON_CENTROID) || 03563 ( rvalue[0] < st[0] - nh1 || rvalue[1] < st[1] - nh1 || rvalue[2] < st[2] - nh1 || 03564 rvalue[0] > st[0] + nh2 || rvalue[1] > st[1] + nh2 || rvalue[2] > st[2] + nh2 )) 03565 { 03566 if(mode == DUALCON_CENTROID) { 03567 // Use centroids 03568 rvalue[0] = (float) st[0] + len / 2 ; 03569 rvalue[1] = (float) st[1] + len / 2 ; 03570 rvalue[2] = (float) st[2] + len / 2 ; 03571 } 03572 else { 03573 // Use mass point instead 03574 rvalue[0] = mp[0] ; 03575 rvalue[1] = mp[1] ; 03576 rvalue[2] = mp[2] ; 03577 } 03578 } 03579 } 03580 03581 void Octree::generateMinimizer( UCHAR* node, int st[3], int len, int height, int& offset ) 03582 { 03583 int i, j ; 03584 03585 if ( height == 0 ) 03586 { 03587 // Leaf cell, generate 03588 03589 // First, find minimizer 03590 float rvalue[3] ; 03591 rvalue[0] = (float) st[0] + len / 2 ; 03592 rvalue[1] = (float) st[1] + len / 2 ; 03593 rvalue[2] = (float) st[2] + len / 2 ; 03594 computeMinimizer( node, st, len, rvalue ) ; 03595 03596 // Update 03597 //float fnst[3] ; 03598 for ( j = 0 ; j < 3 ; j ++ ) 03599 { 03600 rvalue[ j ] = rvalue[ j ] * range / dimen + origin[ j ] ; 03601 //fnst[ j ] = st[ j ] * range / dimen + origin[ j ] ; 03602 } 03603 03604 int mult = 0, smask = getSignMask( node ) ; 03605 03606 if(use_manifold) 03607 { 03608 mult = manifold_table[ smask ].comps ; 03609 } 03610 else 03611 { 03612 if ( smask > 0 && smask < 255 ) 03613 { 03614 mult = 1 ; 03615 } 03616 } 03617 03618 for ( j = 0 ; j < mult ; j ++ ) 03619 { 03620 add_vert(output_mesh, rvalue); 03621 } 03622 03623 // Store the index 03624 setMinimizerIndex( node, offset ) ; 03625 03626 offset += mult ; 03627 } 03628 else 03629 { 03630 // Internal cell, recur 03631 int count = 0 ; 03632 len >>= 1 ; 03633 for ( i = 0 ; i < 8 ; i ++ ) 03634 { 03635 if ( hasChild( node, i ) ) 03636 { 03637 int nst[3] ; 03638 nst[0] = st[0] + vertmap[i][0] * len ; 03639 nst[1] = st[1] + vertmap[i][1] * len ; 03640 nst[2] = st[2] + vertmap[i][2] * len ; 03641 03642 generateMinimizer( getChild( node, count ), nst, len, height - 1, offset ) ; 03643 count ++ ; 03644 } 03645 } 03646 } 03647 } 03648 03649 void Octree::processEdgeWrite( UCHAR* node[4], int depth[4], int maxdep, int dir ) 03650 { 03651 //int color = 0 ; 03652 03653 int i = 3 ; 03654 { 03655 if ( getEdgeParity( node[i], processEdgeMask[dir][i] ) ) 03656 { 03657 int flip = 0 ; 03658 int edgeind = processEdgeMask[dir][i] ; 03659 if ( getSign( node[i], edgemap[ edgeind ][ 1 ] ) > 0 ) 03660 { 03661 flip = 1 ; 03662 } 03663 03664 int num = 0 ; 03665 { 03666 int ind[8]; 03667 if(use_manifold) 03668 { 03669 /* Deprecated 03670 int ind[4] = { 03671 getMinimizerIndex( node[0], processEdgeMask[dir][0] ), 03672 getMinimizerIndex( node[1], processEdgeMask[dir][1] ), 03673 getMinimizerIndex( node[3], processEdgeMask[dir][3] ), 03674 getMinimizerIndex( node[2], processEdgeMask[dir][2] ) 03675 } ; 03676 num = 4 ; 03677 */ 03678 int vind[2] ; 03679 int seq[4] = {0,1,3,2}; 03680 for ( int k = 0 ; k < 4 ; k ++ ) 03681 { 03682 getMinimizerIndices( node[seq[k]], processEdgeMask[dir][seq[k]], vind ) ; 03683 ind[num] = vind[0] ; 03684 num ++ ; 03685 03686 if ( vind[1] != -1 ) 03687 { 03688 ind[num] = vind[1] ; 03689 num ++ ; 03690 if ( flip == 0 ) 03691 { 03692 ind[num-1] = vind[0] ; 03693 ind[num-2] = vind[1] ; 03694 } 03695 } 03696 } 03697 #ifdef TESTMANIFOLD 03698 if ( num != 4 ) 03699 { 03700 dc_printf("Polygon: %d\n", num); 03701 } 03702 for ( k = 0 ; k < num ; k ++ ) 03703 { 03704 fprintf(testfout, "{%d,%d},", ind[k], ind[(k+1)%num] ); 03705 } 03706 #endif 03707 03708 /* we don't use the manifold option, but if it is 03709 ever enabled again note that it can output 03710 non-quads */ 03711 } 03712 else { 03713 if(flip) { 03714 ind[0] = getMinimizerIndex( node[2] ); 03715 ind[1] = getMinimizerIndex( node[3] ); 03716 ind[2] = getMinimizerIndex( node[1] ); 03717 ind[3] = getMinimizerIndex( node[0] ); 03718 } 03719 else { 03720 ind[0] = getMinimizerIndex( node[0] ); 03721 ind[1] = getMinimizerIndex( node[1] ); 03722 ind[2] = getMinimizerIndex( node[3] ); 03723 ind[3] = getMinimizerIndex( node[2] ); 03724 } 03725 03726 add_quad(output_mesh, ind); 03727 } 03728 /* 03729 if ( this->outType == 0 ) 03730 { 03731 // OFF 03732 03733 num = ( color ? -num : num ) ; 03734 03735 fprintf(fout, "%d ", num); 03736 03737 if ( flip ) 03738 { 03739 for ( int k = num - 1 ; k >= 0 ; k -- ) 03740 { 03741 fprintf(fout, "%d ", ind[k] ) ; 03742 } 03743 } 03744 else 03745 { 03746 for ( int k = 0 ; k < num ; k ++ ) 03747 { 03748 fprintf(fout, "%d ", ind[k] ) ; 03749 } 03750 } 03751 03752 fprintf( fout, "\n") ; 03753 03754 actualQuads ++ ; 03755 } 03756 else if ( this->outType == 1 ) 03757 { 03758 // PLY 03759 03760 if ( flip ) 03761 { 03762 int tind[8]; 03763 for ( int k = num - 1 ; k >= 0 ; k -- ) 03764 { 03765 tind[k] = ind[num-1-k] ; 03766 } 03767 // PLYWriter::writeFace( fout, num, tind ) ; 03768 } 03769 else 03770 { 03771 // PLYWriter::writeFace( fout, num, ind ) ; 03772 } 03773 03774 actualQuads ++ ; 03775 }*/ 03776 } 03777 return ; 03778 } 03779 else 03780 { 03781 return ; 03782 } 03783 } 03784 } 03785 03786 03787 void Octree::edgeProcContour( UCHAR* node[4], int leaf[4], int depth[4], int maxdep, int dir ) 03788 { 03789 if ( ! ( node[0] && node[1] && node[2] && node[3] ) ) 03790 { 03791 return ; 03792 } 03793 if ( leaf[0] && leaf[1] && leaf[2] && leaf[3] ) 03794 { 03795 processEdgeWrite( node, depth, maxdep, dir ) ; 03796 } 03797 else 03798 { 03799 int i, j ; 03800 UCHAR* chd[ 4 ][ 8 ] ; 03801 for ( j = 0 ; j < 4 ; j ++ ) 03802 { 03803 for ( i = 0 ; i < 8 ; i ++ ) 03804 { 03805 chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i ) )? getChild( node[j], getChildCount( node[j], i ) ) : NULL ; 03806 } 03807 } 03808 03809 // 2 edge calls 03810 UCHAR* ne[4] ; 03811 int le[4] ; 03812 int de[4] ; 03813 for ( i = 0 ; i < 2 ; i ++ ) 03814 { 03815 int c[ 4 ] = { edgeProcEdgeMask[ dir ][ i ][ 0 ], 03816 edgeProcEdgeMask[ dir ][ i ][ 1 ], 03817 edgeProcEdgeMask[ dir ][ i ][ 2 ], 03818 edgeProcEdgeMask[ dir ][ i ][ 3 ] } ; 03819 03820 for ( int j = 0 ; j < 4 ; j ++ ) 03821 { 03822 if ( leaf[j] ) 03823 { 03824 le[j] = leaf[j] ; 03825 ne[j] = node[j] ; 03826 de[j] = depth[j] ; 03827 } 03828 else 03829 { 03830 le[j] = isLeaf( node[j], c[j] ) ; 03831 ne[j] = chd[ j ][ c[j] ] ; 03832 de[j] = depth[j] - 1 ; 03833 } 03834 } 03835 03836 edgeProcContour( ne, le, de, maxdep - 1, edgeProcEdgeMask[ dir ][ i ][ 4 ] ) ; 03837 } 03838 03839 } 03840 } 03841 03842 void Octree::faceProcContour( UCHAR* node[2], int leaf[2], int depth[2], int maxdep, int dir ) 03843 { 03844 if ( ! ( node[0] && node[1] ) ) 03845 { 03846 return ; 03847 } 03848 03849 if ( ! ( leaf[0] && leaf[1] ) ) 03850 { 03851 int i, j ; 03852 // Fill children nodes 03853 UCHAR* chd[ 2 ][ 8 ] ; 03854 for ( j = 0 ; j < 2 ; j ++ ) 03855 { 03856 for ( i = 0 ; i < 8 ; i ++ ) 03857 { 03858 chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i )) ? getChild( node[j], getChildCount( node[j], i ) ) : NULL ; 03859 } 03860 } 03861 03862 // 4 face calls 03863 UCHAR* nf[2] ; 03864 int df[2] ; 03865 int lf[2] ; 03866 for ( i = 0 ; i < 4 ; i ++ ) 03867 { 03868 int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] }; 03869 for ( int j = 0 ; j < 2 ; j ++ ) 03870 { 03871 if ( leaf[j] ) 03872 { 03873 lf[j] = leaf[j] ; 03874 nf[j] = node[j] ; 03875 df[j] = depth[j] ; 03876 } 03877 else 03878 { 03879 lf[j] = isLeaf( node[j], c[j] ) ; 03880 nf[j] = chd[ j ][ c[j] ] ; 03881 df[j] = depth[j] - 1 ; 03882 } 03883 } 03884 faceProcContour( nf, lf, df, maxdep - 1, faceProcFaceMask[ dir ][ i ][ 2 ] ) ; 03885 } 03886 03887 // 4 edge calls 03888 int orders[2][4] = {{ 0, 0, 1, 1 }, { 0, 1, 0, 1 }} ; 03889 UCHAR* ne[4] ; 03890 int le[4] ; 03891 int de[4] ; 03892 03893 for ( i = 0 ; i < 4 ; i ++ ) 03894 { 03895 int c[4] = { faceProcEdgeMask[ dir ][ i ][ 1 ], faceProcEdgeMask[ dir ][ i ][ 2 ], 03896 faceProcEdgeMask[ dir ][ i ][ 3 ], faceProcEdgeMask[ dir ][ i ][ 4 ] }; 03897 int* order = orders[ faceProcEdgeMask[ dir ][ i ][ 0 ] ] ; 03898 03899 for ( int j = 0 ; j < 4 ; j ++ ) 03900 { 03901 if ( leaf[order[j]] ) 03902 { 03903 le[j] = leaf[order[j]] ; 03904 ne[j] = node[order[j]] ; 03905 de[j] = depth[order[j]] ; 03906 } 03907 else 03908 { 03909 le[j] = isLeaf( node[order[j]], c[j] ) ; 03910 ne[j] = chd[ order[ j ] ][ c[j] ] ; 03911 de[j] = depth[order[j]] - 1 ; 03912 } 03913 } 03914 03915 edgeProcContour( ne, le, de, maxdep - 1, faceProcEdgeMask[ dir ][ i ][ 5 ] ) ; 03916 } 03917 } 03918 } 03919 03920 03921 void Octree::cellProcContour( UCHAR* node, int leaf, int depth ) 03922 { 03923 if ( node == NULL ) 03924 { 03925 return ; 03926 } 03927 03928 if ( ! leaf ) 03929 { 03930 int i ; 03931 03932 // Fill children nodes 03933 UCHAR* chd[ 8 ] ; 03934 for ( i = 0 ; i < 8 ; i ++ ) 03935 { 03936 chd[ i ] = ((!leaf) && hasChild( node, i )) ? getChild( node, getChildCount( node, i ) ) : NULL ; 03937 } 03938 03939 // 8 Cell calls 03940 for ( i = 0 ; i < 8 ; i ++ ) 03941 { 03942 cellProcContour( chd[ i ], isLeaf( node, i ), depth - 1 ) ; 03943 } 03944 03945 // 12 face calls 03946 UCHAR* nf[2] ; 03947 int lf[2] ; 03948 int df[2] = { depth - 1, depth - 1 } ; 03949 for ( i = 0 ; i < 12 ; i ++ ) 03950 { 03951 int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] }; 03952 03953 lf[0] = isLeaf( node, c[0] ) ; 03954 lf[1] = isLeaf( node, c[1] ) ; 03955 03956 nf[0] = chd[ c[0] ] ; 03957 nf[1] = chd[ c[1] ] ; 03958 03959 faceProcContour( nf, lf, df, depth - 1, cellProcFaceMask[ i ][ 2 ] ) ; 03960 } 03961 03962 // 6 edge calls 03963 UCHAR* ne[4] ; 03964 int le[4] ; 03965 int de[4] = { depth - 1, depth - 1, depth - 1, depth - 1 } ; 03966 for ( i = 0 ; i < 6 ; i ++ ) 03967 { 03968 int c[ 4 ] = { cellProcEdgeMask[ i ][ 0 ], cellProcEdgeMask[ i ][ 1 ], cellProcEdgeMask[ i ][ 2 ], cellProcEdgeMask[ i ][ 3 ] }; 03969 03970 for ( int j = 0 ; j < 4 ; j ++ ) 03971 { 03972 le[j] = isLeaf( node, c[j] ) ; 03973 ne[j] = chd[ c[j] ] ; 03974 } 03975 03976 edgeProcContour( ne, le, de, depth - 1, cellProcEdgeMask[ i ][ 4 ] ) ; 03977 } 03978 } 03979 03980 } 03981 03982 #endif 03983 03984 03985 03986 void Octree::processEdgeParity( UCHAR* node[4], int depth[4], int maxdep, int dir ) 03987 { 03988 int con = 0 ; 03989 for ( int i = 0 ; i < 4 ; i ++ ) 03990 { 03991 // Minimal cell 03992 // if ( op == 0 ) 03993 { 03994 if ( getEdgeParity( node[i], processEdgeMask[dir][i] ) ) 03995 { 03996 con = 1 ; 03997 break ; 03998 } 03999 } 04000 } 04001 04002 if ( con == 1 ) 04003 { 04004 for ( int i = 0 ; i < 4 ; i ++ ) 04005 { 04006 setEdge( node[ i ], processEdgeMask[dir][i] ) ; 04007 } 04008 } 04009 04010 } 04011 04012 void Octree::edgeProcParity( UCHAR* node[4], int leaf[4], int depth[4], int maxdep, int dir ) 04013 { 04014 if ( ! ( node[0] && node[1] && node[2] && node[3] ) ) 04015 { 04016 return ; 04017 } 04018 if ( leaf[0] && leaf[1] && leaf[2] && leaf[3] ) 04019 { 04020 processEdgeParity( node, depth, maxdep, dir ) ; 04021 } 04022 else 04023 { 04024 int i, j ; 04025 UCHAR* chd[ 4 ][ 8 ] ; 04026 for ( j = 0 ; j < 4 ; j ++ ) 04027 { 04028 for ( i = 0 ; i < 8 ; i ++ ) 04029 { 04030 chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i ) )? getChild( node[j], getChildCount( node[j], i ) ) : NULL ; 04031 } 04032 } 04033 04034 // 2 edge calls 04035 UCHAR* ne[4] ; 04036 int le[4] ; 04037 int de[4] ; 04038 for ( i = 0 ; i < 2 ; i ++ ) 04039 { 04040 int c[ 4 ] = { edgeProcEdgeMask[ dir ][ i ][ 0 ], 04041 edgeProcEdgeMask[ dir ][ i ][ 1 ], 04042 edgeProcEdgeMask[ dir ][ i ][ 2 ], 04043 edgeProcEdgeMask[ dir ][ i ][ 3 ] } ; 04044 04045 // int allleaf = 1 ; 04046 for ( int j = 0 ; j < 4 ; j ++ ) 04047 { 04048 04049 if ( leaf[j] ) 04050 { 04051 le[j] = leaf[j] ; 04052 ne[j] = node[j] ; 04053 de[j] = depth[j] ; 04054 } 04055 else 04056 { 04057 le[j] = isLeaf( node[j], c[j] ) ; 04058 ne[j] = chd[ j ][ c[j] ] ; 04059 de[j] = depth[j] - 1 ; 04060 04061 } 04062 04063 } 04064 04065 edgeProcParity( ne, le, de, maxdep - 1, edgeProcEdgeMask[ dir ][ i ][ 4 ] ) ; 04066 } 04067 04068 } 04069 } 04070 04071 void Octree::faceProcParity( UCHAR* node[2], int leaf[2], int depth[2], int maxdep, int dir ) 04072 { 04073 if ( ! ( node[0] && node[1] ) ) 04074 { 04075 return ; 04076 } 04077 04078 if ( ! ( leaf[0] && leaf[1] ) ) 04079 { 04080 int i, j ; 04081 // Fill children nodes 04082 UCHAR* chd[ 2 ][ 8 ] ; 04083 for ( j = 0 ; j < 2 ; j ++ ) 04084 { 04085 for ( i = 0 ; i < 8 ; i ++ ) 04086 { 04087 chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i )) ? getChild( node[j], getChildCount( node[j], i ) ) : NULL ; 04088 } 04089 } 04090 04091 // 4 face calls 04092 UCHAR* nf[2] ; 04093 int df[2] ; 04094 int lf[2] ; 04095 for ( i = 0 ; i < 4 ; i ++ ) 04096 { 04097 int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] }; 04098 for ( int j = 0 ; j < 2 ; j ++ ) 04099 { 04100 if ( leaf[j] ) 04101 { 04102 lf[j] = leaf[j] ; 04103 nf[j] = node[j] ; 04104 df[j] = depth[j] ; 04105 } 04106 else 04107 { 04108 lf[j] = isLeaf( node[j], c[j] ) ; 04109 nf[j] = chd[ j ][ c[j] ] ; 04110 df[j] = depth[j] - 1 ; 04111 } 04112 } 04113 faceProcParity( nf, lf, df, maxdep - 1, faceProcFaceMask[ dir ][ i ][ 2 ] ) ; 04114 } 04115 04116 // 4 edge calls 04117 int orders[2][4] = {{ 0, 0, 1, 1 }, { 0, 1, 0, 1 }} ; 04118 UCHAR* ne[4] ; 04119 int le[4] ; 04120 int de[4] ; 04121 04122 for ( i = 0 ; i < 4 ; i ++ ) 04123 { 04124 int c[4] = { faceProcEdgeMask[ dir ][ i ][ 1 ], faceProcEdgeMask[ dir ][ i ][ 2 ], 04125 faceProcEdgeMask[ dir ][ i ][ 3 ], faceProcEdgeMask[ dir ][ i ][ 4 ] }; 04126 int* order = orders[ faceProcEdgeMask[ dir ][ i ][ 0 ] ] ; 04127 04128 for ( int j = 0 ; j < 4 ; j ++ ) 04129 { 04130 if ( leaf[order[j]] ) 04131 { 04132 le[j] = leaf[order[j]] ; 04133 ne[j] = node[order[j]] ; 04134 de[j] = depth[order[j]] ; 04135 } 04136 else 04137 { 04138 le[j] = isLeaf( node[order[j]], c[j] ) ; 04139 ne[j] = chd[ order[ j ] ][ c[j] ] ; 04140 de[j] = depth[order[j]] - 1 ; 04141 } 04142 } 04143 04144 edgeProcParity( ne, le, de, maxdep - 1, faceProcEdgeMask[ dir ][ i ][ 5 ] ) ; 04145 } 04146 } 04147 } 04148 04149 04150 void Octree::cellProcParity( UCHAR* node, int leaf, int depth ) 04151 { 04152 if ( node == NULL ) 04153 { 04154 return ; 04155 } 04156 04157 if ( ! leaf ) 04158 { 04159 int i ; 04160 04161 // Fill children nodes 04162 UCHAR* chd[ 8 ] ; 04163 for ( i = 0 ; i < 8 ; i ++ ) 04164 { 04165 chd[ i ] = ((!leaf) && hasChild( node, i )) ? getChild( node, getChildCount( node, i ) ) : NULL ; 04166 } 04167 04168 // 8 Cell calls 04169 for ( i = 0 ; i < 8 ; i ++ ) 04170 { 04171 cellProcParity( chd[ i ], isLeaf( node, i ), depth - 1 ) ; 04172 } 04173 04174 // 12 face calls 04175 UCHAR* nf[2] ; 04176 int lf[2] ; 04177 int df[2] = { depth - 1, depth - 1 } ; 04178 for ( i = 0 ; i < 12 ; i ++ ) 04179 { 04180 int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] }; 04181 04182 lf[0] = isLeaf( node, c[0] ) ; 04183 lf[1] = isLeaf( node, c[1] ) ; 04184 04185 nf[0] = chd[ c[0] ] ; 04186 nf[1] = chd[ c[1] ] ; 04187 04188 faceProcParity( nf, lf, df, depth - 1, cellProcFaceMask[ i ][ 2 ] ) ; 04189 } 04190 04191 // 6 edge calls 04192 UCHAR* ne[4] ; 04193 int le[4] ; 04194 int de[4] = { depth - 1, depth - 1, depth - 1, depth - 1 } ; 04195 for ( i = 0 ; i < 6 ; i ++ ) 04196 { 04197 int c[ 4 ] = { cellProcEdgeMask[ i ][ 0 ], cellProcEdgeMask[ i ][ 1 ], cellProcEdgeMask[ i ][ 2 ], cellProcEdgeMask[ i ][ 3 ] }; 04198 04199 for ( int j = 0 ; j < 4 ; j ++ ) 04200 { 04201 le[j] = isLeaf( node, c[j] ) ; 04202 ne[j] = chd[ c[j] ] ; 04203 } 04204 04205 edgeProcParity( ne, le, de, depth - 1, cellProcEdgeMask[ i ][ 4 ] ) ; 04206 } 04207 } 04208 04209 } 04210 04211 /* definitions for global arrays */ 04212 const int edgemask[3] = {5, 3, 6}; 04213 04214 const int faceMap[6][4] = { 04215 {4, 8, 5, 9}, 04216 {6, 10, 7, 11}, 04217 {0, 8, 1, 10}, 04218 {2, 9, 3, 11}, 04219 {0, 4, 2, 6}, 04220 {1, 5, 3, 7} 04221 }; 04222 04223 const int cellProcFaceMask[12][3] = { 04224 {0, 4, 0}, 04225 {1, 5, 0}, 04226 {2, 6, 0}, 04227 {3, 7, 0}, 04228 {0, 2, 1}, 04229 {4, 6, 1}, 04230 {1, 3, 1}, 04231 {5, 7, 1}, 04232 {0, 1, 2}, 04233 {2, 3, 2}, 04234 {4, 5, 2}, 04235 {6, 7, 2} 04236 }; 04237 04238 const int cellProcEdgeMask[6][5] = { 04239 {0, 1, 2, 3, 0}, 04240 {4, 5, 6, 7, 0}, 04241 {0, 4, 1, 5, 1}, 04242 {2, 6, 3, 7, 1}, 04243 {0, 2, 4, 6, 2}, 04244 {1, 3, 5, 7, 2} 04245 }; 04246 04247 const int faceProcFaceMask[3][4][3] = { 04248 {{4, 0, 0}, 04249 {5, 1, 0}, 04250 {6, 2, 0}, 04251 {7, 3, 0}}, 04252 {{2, 0, 1}, 04253 {6, 4, 1}, 04254 {3, 1, 1}, 04255 {7, 5, 1}}, 04256 {{1, 0, 2}, 04257 {3, 2, 2}, 04258 {5, 4, 2}, 04259 {7, 6, 2}} 04260 }; 04261 04262 const int faceProcEdgeMask[3][4][6] = { 04263 {{1, 4, 0, 5, 1, 1}, 04264 {1, 6, 2, 7, 3, 1}, 04265 {0, 4, 6, 0, 2, 2}, 04266 {0, 5, 7, 1, 3, 2}}, 04267 {{0, 2, 3, 0, 1, 0}, 04268 {0, 6, 7, 4, 5, 0}, 04269 {1, 2, 0, 6, 4, 2}, 04270 {1, 3, 1, 7, 5, 2}}, 04271 {{1, 1, 0, 3, 2, 0}, 04272 {1, 5, 4, 7, 6, 0}, 04273 {0, 1, 5, 0, 4, 1}, 04274 {0, 3, 7, 2, 6, 1}} 04275 }; 04276 04277 const int edgeProcEdgeMask[3][2][5] = { 04278 {{3, 2, 1, 0, 0}, 04279 {7, 6, 5, 4, 0}}, 04280 {{5, 1, 4, 0, 1}, 04281 {7, 3, 6, 2, 1}}, 04282 {{6, 4, 2, 0, 2}, 04283 {7, 5, 3, 1, 2}}, 04284 }; 04285 04286 const int processEdgeMask[3][4] = { 04287 {3, 2, 1, 0}, 04288 {7, 5, 6, 4}, 04289 {11, 10, 9, 8} 04290 }; 04291 04292 const int dirCell[3][4][3] = { 04293 {{0, -1, -1}, 04294 {0, -1, 0}, 04295 {0, 0, -1}, 04296 {0, 0, 0}}, 04297 {{-1, 0, -1}, 04298 {-1, 0, 0}, 04299 {0, 0, -1}, 04300 {0, 0, 0}}, 04301 {{-1, -1, 0}, 04302 {-1, 0, 0}, 04303 {0, -1, 0}, 04304 {0, 0, 0}} 04305 }; 04306 04307 const int dirEdge[3][4] = { 04308 {3, 2, 1, 0}, 04309 {7, 6, 5, 4}, 04310 {11, 10, 9, 8} 04311 };