├── CMakeLists.txt ├── GeoCommon.hpp ├── HashMap.hpp ├── ModelReader.hpp ├── PLYReader.hpp ├── PLYWriter.hpp ├── dc.cpp ├── eigen.cpp ├── eigen.hpp ├── intersection.hpp ├── mechanic.dcf ├── octree.cpp ├── octree.hpp └── readme.txt /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | Project(dc) 4 | 5 | # command-line parsing using the boost program-options library 6 | find_package(Boost COMPONENTS program_options REQUIRED) 7 | 8 | 9 | set(DC_SRC_FILES 10 | dc.cpp 11 | eigen.cpp 12 | octree.cpp 13 | # SOGReader.cpp 14 | ) 15 | 16 | set(DC_INCLUDE_FILES 17 | eigen.hpp 18 | GeoCommon.hpp 19 | HashMap.hpp 20 | intersection.hpp 21 | ModelReader.hpp 22 | octree.hpp 23 | PLYReader.hpp 24 | PLYWriter.hpp 25 | # SOGReader.hpp 26 | ) 27 | 28 | set(CMAKE_CXX_FLAGS "-fpermissive") 29 | 30 | ADD_EXECUTABLE(dualcontour ${DC_SRC_FILES}) 31 | 32 | if(Boost_FOUND) 33 | include_directories(${Boost_INCLUDE_DIRS}) 34 | target_link_libraries(dualcontour ${Boost_LIBRARIES}) 35 | endif() 36 | 37 | -------------------------------------------------------------------------------- /GeoCommon.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Structure definitions for points and triangles. 3 | 4 | Copyright (C) 2011 Tao Ju 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public License 8 | (LGPL) as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #ifndef GEOCOMMON_H 22 | #define GEOCOMMON_H 23 | 24 | // #define UCHAR unsigned char 25 | // #define USHORT unsigned short 26 | 27 | #define USE_MINIMIZER 28 | 29 | // 3d point with integer coordinates 30 | typedef struct { 31 | int x, y, z; 32 | } Point3i; 33 | 34 | typedef struct { 35 | Point3i begin; 36 | Point3i end; 37 | } BoundingBox; 38 | 39 | // triangle that points to three vertices 40 | typedef struct { 41 | float vt[3][3] ; 42 | } Triangle; 43 | 44 | struct TriangleList { 45 | float vt[3][3] ; 46 | TriangleList* next ; 47 | }; 48 | 49 | struct VertexList { 50 | float vt[3] ; 51 | VertexList* next ; 52 | }; 53 | 54 | struct IndexedTriangleList { 55 | int vt[3] ; 56 | IndexedTriangleList* next ; 57 | }; 58 | 59 | // 3d point with float coordinates 60 | typedef struct { 61 | float x, y, z; 62 | } Point3f; 63 | 64 | typedef struct { 65 | Point3f begin; 66 | Point3f end; 67 | } BoundingBoxf; 68 | 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /HashMap.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | A hash table hashed by two/four integers. 4 | 5 | Copyright (C) 2011 Tao Ju 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public License 9 | (LGPL) as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | 23 | #ifndef HASHMAP_H 24 | #define HASHMAP_H 25 | 26 | #include 27 | #include 28 | 29 | #define HASH_LENGTH 20 30 | #define MAX_HASH (1<n1 == k1) && (p->n2 == k2)) 98 | { 99 | index = p->index ; 100 | location = p->location ; 101 | return 1 ; 102 | } 103 | p = p->next; 104 | } 105 | 106 | return 0 ; 107 | }; 108 | 109 | 110 | /// Insertion method 111 | void InsertKey ( int k1, int k2, int index, int location ) 112 | { 113 | /// Create hash key 114 | int ind = CreateKey ( k1, k2 ); 115 | 116 | /// Create hash entry 117 | ElementList *node = new ElementList; 118 | 119 | node->index = index ; 120 | node->location = location ; 121 | node->n1 = k1 ; 122 | node->n2 = k2 ; 123 | node->next = table[ ind ] ; 124 | table[ ind ] = node ; 125 | }; 126 | 127 | // Destruction method 128 | ~HashMap() 129 | { 130 | ElementList *p, *pp; 131 | 132 | for ( int i = 0; i < MAX_HASH; i ++) 133 | { 134 | p = table[i]; 135 | 136 | while (p) 137 | { 138 | pp = p->next; 139 | delete p; 140 | p = pp; 141 | } 142 | 143 | } 144 | 145 | }; 146 | 147 | }; 148 | 149 | class HashMap2 150 | { 151 | /// Hash table 152 | ElementList2 *table[MAX_HASH]; 153 | 154 | /// Create hash key 155 | int CreateKey( int k1, int k2 ) 156 | { 157 | int ind = ( (( k1 & ( (1<n1 == k1) && (p->n2 == k2)) 186 | { 187 | coord[0] = p->v[0] ; 188 | coord[1] = p->v[1] ; 189 | coord[2] = p->v[2] ; 190 | return 1 ; 191 | } 192 | p = p->next; 193 | } 194 | 195 | return 0 ; 196 | }; 197 | 198 | 199 | /// Insertion method 200 | void InsertKey ( int k1, int k2, float coord[3] ) 201 | { 202 | /// Create hash key 203 | int ind = CreateKey ( k1, k2 ); 204 | 205 | /// Create hash entry 206 | ElementList2 *node = new ElementList2; 207 | 208 | node->v[0] = coord[0] ; 209 | node->v[1] = coord[1] ; 210 | node->v[2] = coord[2] ; 211 | node->n1 = k1 ; 212 | node->n2 = k2 ; 213 | node->next = table[ ind ] ; 214 | table[ ind ] = node ; 215 | }; 216 | 217 | // Destruction method 218 | ~HashMap2() 219 | { 220 | ElementList2 *p, *pp; 221 | 222 | for ( int i = 0; i < MAX_HASH; i ++) 223 | { 224 | p = table[i]; 225 | 226 | while (p) 227 | { 228 | pp = p->next; 229 | delete p; 230 | p = pp; 231 | } 232 | 233 | } 234 | 235 | }; 236 | 237 | }; 238 | 239 | class HashMap4 240 | { 241 | /// Hash table 242 | ElementList4 *table[MAX_HASH]; 243 | 244 | /// Create hash key 245 | int CreateKey( int k1, int k2, int k3, int k4 ) 246 | { 247 | int ind = ( (( k1 & ( (1<n1 == k1) && (p->n2 == k2) && (p->n3 == k3) && (p->n4 == k4)) 278 | { 279 | return p->index ; 280 | } 281 | p = p->next; 282 | } 283 | 284 | return -1 ; 285 | }; 286 | 287 | 288 | /// Insertion method 289 | void InsertKey ( int k1, int k2, int k3, int k4, int index ) 290 | { 291 | /// Create hash key 292 | int ind = CreateKey ( k1, k2, k3, k4 ); 293 | 294 | /// Create hash entry 295 | ElementList4 *node = new ElementList4; 296 | 297 | node->index = index ; 298 | node->n1 = k1 ; 299 | node->n2 = k2 ; 300 | node->n3 = k3 ; 301 | node->n4 = k4 ; 302 | node->next = table[ ind ] ; 303 | table[ ind ] = node ; 304 | }; 305 | 306 | // Destruction method 307 | ~HashMap4() 308 | { 309 | ElementList4 *p, *pp; 310 | 311 | for ( int i = 0; i < MAX_HASH; i ++) 312 | { 313 | p = table[i]; 314 | 315 | while (p) 316 | { 317 | pp = p->next; 318 | delete p; 319 | p = pp; 320 | } 321 | 322 | } 323 | 324 | }; 325 | 326 | }; 327 | 328 | #endif -------------------------------------------------------------------------------- /ModelReader.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Virtual class for input file readers 4 | 5 | Copyright (C) 2011 Tao Ju 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public License 9 | (LGPL) as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | 23 | 24 | #ifndef MODELREADER_H 25 | #define MODELREADER_H 26 | 27 | #include "GeoCommon.hpp" 28 | 29 | class ModelReader 30 | { 31 | public: 32 | /// Constructor 33 | ModelReader(){} ; 34 | /// Get next triangle 35 | virtual Triangle* getNextTriangle( ) = 0 ; 36 | virtual int getNextTriangle( int t[3] ) = 0 ; 37 | /// Get bounding box 38 | virtual float getBoundingBox ( float origin[3] ) = 0 ; 39 | /// Get number of triangles 40 | virtual int getNumTriangles ( ) = 0 ; 41 | /// Get storage size 42 | virtual int getMemory ( ) = 0 ; 43 | /// Reset file reading location 44 | virtual void reset( ) = 0 ; 45 | /// For explicit vertex models 46 | virtual int getNumVertices( ) = 0 ; 47 | virtual void getNextVertex( float v[3] ) = 0 ; 48 | virtual void printInfo ( ) = 0 ; 49 | }; 50 | 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /PLYReader.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Class for reading PLY (asc or binary) files 4 | * for PLY specification, see http://www.ics.uci.edu/~graphics/teaching/ply.html 5 | 6 | Copyright (C) 2011 Tao Ju 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public License 10 | (LGPL) as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifndef PLYREADER_H 24 | #define PLYREADER_H 25 | 26 | #include "GeoCommon.hpp" 27 | #include "ModelReader.hpp" 28 | #include 29 | #include 30 | #include 31 | 32 | const char typeName[11][10] = {"char","uchar","short","ushort","int","uint","float","double", "uint8", "float32", "int32"} ; 33 | const int typeSize[11] = {1,1,2,2,4,4,4,8,1,4,4} ; 34 | const int totalTypes = 11 ; 35 | 36 | class PLYReader : public ModelReader 37 | { 38 | public: 39 | // File handle 40 | FILE* fin ; 41 | 42 | // Number of triangles 43 | int numTrians, curtrian ; 44 | 45 | // Number of vertices 46 | int numVerts, curvert ; 47 | 48 | // Vertex array 49 | float* vertarray ; 50 | 51 | // Bounding box 52 | float min[3], max[3] ; 53 | float rawmin[3], rawmax[3] ; 54 | 55 | // Size of box 56 | float maxsize ; 57 | 58 | // Types and info 59 | int extraVertex ; 60 | 61 | // Temporary array for non-triangle faces 62 | int temparray[64] ; 63 | int tottri, curtri ; 64 | 65 | // Mode 66 | int mode ; // 0 for asc, 1 for little-endian, 2 for big endian 67 | 68 | // Mode 69 | int vmode ; 70 | 71 | // Offset for reading faces 72 | long offset ; 73 | 74 | public: 75 | /// Constructor 76 | PLYReader( char* fname, float scl ) 77 | { 78 | if ( ! ( fin = fopen( fname, "rb" ) ) ) 79 | { 80 | printf("Unable to open file %s\n", fname) ; 81 | }; 82 | 83 | // Scan to get info 84 | // printf("Scanning file for bounding box...\n"); 85 | 86 | // Parse header 87 | int vmode = 0, lines = 0 ; 88 | this->numTrians = this->numVerts = this->extraVertex = 0 ; 89 | char seps[] = " ,\t\n\r "; 90 | seps[5] = 10 ; 91 | while ( 1 ) 92 | { 93 | char header[1024] ; 94 | fgets( header, 1024, fin ) ; 95 | // printf("%s\n", header) ; 96 | 97 | char* token = strtok( header, seps ) ; 98 | // token[ strlen(token) - 1 ] = '\0' ; 99 | // int comp = strcmp ( token, "end_header" ) ; 100 | // printf("%s %d\n", token, comp ) ; 101 | // char c = getchar() ; 102 | 103 | 104 | 105 | if ( ! strcmp ( token, "end_header" ) ) 106 | { 107 | // Header finished 108 | // printf("End encountered!") ; 109 | break ; 110 | } else if ( ! strcmp( token, "format" ) ) 111 | { 112 | // Format specification 113 | token = strtok ( NULL, seps ) ; 114 | if ( !strcmp ( token, "ascii" ) ) 115 | { 116 | this->mode = 0 ; 117 | } 118 | else if ( ! strcmp ( token, "binary_big_endian") ) 119 | { 120 | this->mode = 2 ; 121 | } 122 | else 123 | { 124 | this->mode = 1 ; 125 | } 126 | 127 | } else if ( ! strcmp( token, "element") ) 128 | { 129 | vmode = 0 ; 130 | lines = 0 ; 131 | token = strtok( NULL, seps ) ; 132 | if ( !strcmp( token, "vertex" ) ) 133 | { 134 | // Vertex count 135 | token = strtok( NULL, seps ) ; 136 | sscanf( token, "%d", &(this->numVerts) ) ; 137 | 138 | // Enter vertex mode 139 | vmode = 1 ; 140 | } else if ( !strcmp( token, "face" ) ) 141 | { 142 | // Face count 143 | token = strtok( NULL, seps ) ; 144 | sscanf( token, "%d", &(this->numTrians) ) ; 145 | 146 | // Enter face mode 147 | vmode = 2 ; 148 | } 149 | } else if ( ! strcmp( token, "property" ) ) 150 | { 151 | switch ( vmode ) 152 | { 153 | case 1: // Vertex mode 154 | if ( lines >= 3 ) 155 | { 156 | // Extra storage for each vertex 157 | token = strtok( NULL, seps ) ; 158 | 159 | for ( int i = 0 ; i < totalTypes ; i ++ ) 160 | { 161 | if ( ! strcmp( token, typeName[i] ) ) 162 | { 163 | this->extraVertex += typeSize[i] ; 164 | break ; 165 | } 166 | } 167 | } 168 | 169 | lines ++ ; 170 | break ; 171 | 172 | case 2: // Face mode 173 | 174 | break ; 175 | } 176 | } 177 | } 178 | //printf("Header info: %d vertices, %d faces, %d extra bytes per vertex. At %d\n", this->numVerts, this->numTrians, this->extraVertex, ftell( fin ) ); 179 | this->vertarray = new float [ 3 * this->numVerts ] ; 180 | // char c = getchar() ; 181 | 182 | /* 183 | float *ok= new float[ numVerts * 3 ] ; 184 | char c = getchar() ; 185 | return ; 186 | 187 | this->vertarray = new float* [this->numVerts ] ; 188 | 189 | 190 | int i ; 191 | 192 | for ( i = 0 ; i < this->numVerts ; i ++ ) 193 | { 194 | vertarray[i] = new float[4] ; 195 | } 196 | printf("Done"); 197 | */ 198 | 199 | 200 | // Start reading vertices 201 | int i ; 202 | char temp[1024] ; 203 | if ( mode > 0 ) 204 | { 205 | for ( i = 0 ; i < this->numVerts ; i ++ ) 206 | { 207 | int haveread = 0 ; 208 | if ( ( haveread = fread( &(vertarray[ 3 * i ]), sizeof( float ), 3, fin ) ) != 3 ) 209 | { 210 | 211 | if( feof( fin ) ) 212 | { 213 | printf( "Read error %ld ", ftell( fin ) ); 214 | } 215 | 216 | printf("%d\n", haveread ) ; 217 | exit(0) ; 218 | } 219 | if ( mode == 2 ) 220 | { 221 | // Flip bits 222 | for ( int j = 0 ; j < 3 ; j ++ ) 223 | { 224 | flipBits32( & (vertarray[3*i + j]) ) ; 225 | } 226 | } 227 | /* 228 | printf("%f %f %f\n", vertarray[i][0], vertarray[i][1], vertarray[i][2] ) ; 229 | if ( i == 10 ) 230 | { 231 | exit(0) ; 232 | } 233 | */ 234 | 235 | // Read extra data 236 | fread( temp, 1, this->extraVertex, fin ) ; 237 | if ( i == 0 ) 238 | { 239 | for ( int j = 0 ; j < 3 ; j ++ ) 240 | { 241 | rawmin[j] = rawmax[j] = vertarray[3 * i + j] ; 242 | } 243 | } 244 | else 245 | { 246 | for ( int k = 0 ; k < 3 ; k ++ ) 247 | { 248 | if ( rawmin[k] > vertarray[3 * i + k] ) 249 | { 250 | rawmin[k] = vertarray[3 * i + k] ; 251 | } 252 | if ( rawmax[k] < vertarray[3 * i + k] ) 253 | { 254 | rawmax[k] = vertarray[3 * i + k] ; 255 | } 256 | } 257 | } 258 | 259 | } 260 | } 261 | else 262 | { 263 | // ASCII mode 264 | 265 | 266 | for ( i = 0 ; i < this->numVerts ; i ++ ) 267 | { 268 | fgets ( temp, 1024, fin ) ; 269 | 270 | char seps[] = " ,\t\n"; 271 | char* token = strtok( temp, seps ) ; 272 | 273 | sscanf( token, "%f", &(vertarray[ 3 * i ] ) ) ; 274 | token = strtok( NULL, seps ) ; 275 | sscanf( token, "%f", &(vertarray[ 3 * i + 1 ] ) ) ; 276 | token = strtok( NULL, seps ) ; 277 | sscanf( token, "%f", &(vertarray[ 3 * i + 2 ] ) ) ; 278 | 279 | if ( i == 0 ) 280 | { 281 | for ( int j = 0 ; j < 3 ; j ++ ) 282 | { 283 | rawmin[j] = rawmax[j] = vertarray[3 * i + j] ; 284 | } 285 | } 286 | else 287 | { 288 | for ( int k = 0 ; k < 3 ; k ++ ) 289 | { 290 | if ( rawmin[k] > vertarray[3 * i + k] ) 291 | { 292 | rawmin[k] = vertarray[3 * i + k] ; 293 | } 294 | if ( rawmax[k] < vertarray[3 * i + k] ) 295 | { 296 | rawmax[k] = vertarray[3 * i + k] ; 297 | } 298 | } 299 | } 300 | 301 | } 302 | } 303 | 304 | 305 | maxsize = rawmax[0] - rawmin[0] ; 306 | if ( rawmax[1] - rawmin[1] > maxsize ) 307 | { 308 | maxsize = rawmax[1] - rawmin[1] ; 309 | } 310 | if ( rawmax[2] - rawmin[2] > maxsize ) 311 | { 312 | maxsize = rawmax[2] - rawmin[2] ; 313 | } 314 | 315 | for ( i = 0 ; i < 3 ; i ++ ) 316 | { 317 | min[i] = ( rawmax[i] + rawmin[i] ) / 2 - maxsize / 2 ; 318 | max[i] = ( rawmax[i] + rawmin[i] ) / 2 + maxsize / 2 ; 319 | } 320 | 321 | // printf( "Low corner: %f %f %f High corner %f %f %f \n", min[0], min[1], min[2], max[0], max[1], max[2] ); 322 | // printf( "Maxdif: %f \n", maxsize ); 323 | 324 | // Scale 325 | for ( i = 0 ; i < 3 ; i ++ ) 326 | { 327 | min[i] -= maxsize * ( 1 / scl - 1 ) / 2 ; 328 | } 329 | maxsize *= ( 1 / scl ) ; 330 | 331 | // Reset 332 | this->offset = ftell( fin ) ; 333 | curtrian = 0 ; 334 | 335 | }; 336 | 337 | void reset( ) 338 | { 339 | curtrian = 0 ; 340 | curvert = 0 ; 341 | 342 | curtri = 0 ; 343 | tottri = 0 ; 344 | 345 | fseek( fin, offset, SEEK_SET ) ; 346 | } 347 | 348 | /// Get next triangle 349 | Triangle* getNextTriangle( ) 350 | { 351 | if ( curtrian == numTrians ) 352 | { 353 | return NULL ; 354 | } 355 | 356 | if ( curtri == tottri ) 357 | { 358 | // Read next face 359 | unsigned char num ; 360 | 361 | 362 | if ( mode > 0 ) 363 | { 364 | // Read number of vertices in the face 365 | fread( &num, sizeof( unsigned char ), 1, fin ) ; 366 | fread( temparray, sizeof( int ), num, fin ) ; 367 | if ( mode == 2 ) 368 | { 369 | for ( int i = 0 ; i < num ; i ++ ) 370 | { 371 | flipBits32( &(temparray[i]) ) ; 372 | } 373 | } 374 | // printf("%d\n", tottri) ; 375 | // printf("\n") ; 376 | 377 | // if ( curtrian == 10 ) exit(1) ; 378 | } 379 | else 380 | { 381 | char temp[1024] ; 382 | fgets( temp, 1024, fin ) ; 383 | 384 | char seps[] = " ,\t\n"; 385 | char* token = strtok( temp, seps ) ; 386 | 387 | sscanf( token, "%d", (int*)&num ) ; 388 | 389 | for ( int i = 0 ; i < num ; i ++ ) 390 | { 391 | token = strtok( NULL, seps ) ; 392 | sscanf( token, "%d", &(temparray[i]) ) ; 393 | } 394 | } 395 | 396 | 397 | tottri = num - 2 ; 398 | curtri = 0 ; 399 | curtrian ++ ; 400 | } 401 | 402 | Triangle* t = new Triangle() ; 403 | for ( int i = 0 ; i < 3 ; i ++ ) 404 | { 405 | t->vt[0][i] = vertarray[ 3 * temparray[0] + i ] ; 406 | t->vt[1][i] = vertarray[ 3 * temparray[curtri + 1] + i ] ; 407 | t->vt[2][i] = vertarray[ 3 * temparray[curtri + 2] + i ] ; 408 | } 409 | 410 | curtri ++ ; 411 | 412 | // printf("%d %d %d\n", temparray[0], temparray[curtri + 1], temparray[curtri + 2]); 413 | 414 | return t ; 415 | }; 416 | 417 | /// Get next triangle 418 | int getNextTriangle( int ind[3] ) 419 | { 420 | if ( curtrian == numTrians ) 421 | { 422 | return 0 ; 423 | } 424 | 425 | if ( curtri == tottri ) 426 | { 427 | // Read next face 428 | unsigned char num ; 429 | 430 | if ( mode > 0 ) 431 | { 432 | // Read number of vertices in the face 433 | fread( &num, sizeof( unsigned char ), 1, fin ) ; 434 | 435 | // Read array of indices 436 | fread( temparray, sizeof( int ), num, fin ) ; 437 | if ( mode == 2 ) 438 | { 439 | for ( int i = 0 ; i < num ; i ++ ) 440 | { 441 | flipBits32( &(temparray[i]) ) ; 442 | // printf("%d ", temparray[i]) ; 443 | } 444 | } 445 | // printf("\n") ; 446 | 447 | // if ( curtrian == 10 ) exit(1) ; 448 | } 449 | else 450 | { 451 | char temp[1024] ; 452 | fgets( temp, 1024, fin ) ; 453 | 454 | char seps[] = " ,\t\n"; 455 | char* token = strtok( temp, seps ) ; 456 | 457 | sscanf( token, "%d", (int*)&num ) ; 458 | 459 | for ( int i = 0 ; i < num ; i ++ ) 460 | { 461 | token = strtok( NULL, seps ) ; 462 | sscanf( token, "%d", &(temparray[i]) ) ; 463 | } 464 | } 465 | 466 | tottri = num - 2 ; 467 | curtri = 0 ; 468 | curtrian ++ ; 469 | } 470 | 471 | ind[0] = temparray[0] ; 472 | ind[1] = temparray[curtri + 1] ; 473 | ind[2] = temparray[curtri + 2] ; 474 | 475 | curtri ++ ; 476 | return 1 ; 477 | }; 478 | 479 | void printInfo ( ) 480 | { 481 | printf("Vertices: %d Polygons: %d\n",this->numVerts, this->numTrians) ; 482 | } 483 | 484 | 485 | /// Get bounding box 486 | float getBoundingBox ( float origin[3] ) 487 | { 488 | for ( int i = 0 ; i < 3 ; i ++ ) 489 | { 490 | origin[i] = min[i] ; 491 | } 492 | 493 | return maxsize ; 494 | }; 495 | 496 | void getRawBoundingBox ( float low[3], float high[3] ) 497 | { 498 | for ( int i = 0 ; i < 3 ; i ++ ) 499 | { 500 | low[i] = rawmin[i] ; 501 | high[i] = rawmax[i] ; 502 | } 503 | } 504 | 505 | /// Get storage size 506 | int getMemory ( ) 507 | { 508 | return sizeof ( class PLYReader ) + this->numVerts * sizeof( float ) * 3 ; 509 | }; 510 | 511 | // Flip bits 512 | 513 | void flipBits32 ( void *x ) 514 | { 515 | unsigned char *temp = (unsigned char *)x; 516 | unsigned char swap; 517 | 518 | swap = temp [ 0 ]; 519 | temp [ 0 ] = temp [ 3 ]; 520 | temp [ 3 ] = swap; 521 | 522 | swap = temp [ 1 ]; 523 | temp [ 1 ] = temp [ 2 ]; 524 | temp [ 2 ] = swap; 525 | } 526 | 527 | void printBits32 ( void *x ) 528 | { 529 | unsigned char *temp = (unsigned char *)x; 530 | 531 | printf("%2x %2x %2x %2x\n", temp[0], temp[1], temp[2], temp[3]) ; 532 | } 533 | 534 | int getNumTriangles() 535 | { 536 | return this->numTrians ; 537 | } 538 | 539 | int getNumVertices() 540 | { 541 | return this->numVerts ; 542 | } 543 | 544 | float* getVertex( int ind ) 545 | { 546 | return &(this->vertarray[ 3 * ind ]) ; 547 | } 548 | 549 | void getNextVertex( float v[3] ) 550 | { 551 | v[0] = vertarray[ 3 * curvert ] ; 552 | v[1] = vertarray[ 3 * curvert + 1 ] ; 553 | v[2] = vertarray[ 3 * curvert + 2 ] ; 554 | 555 | curvert ++ ; 556 | } 557 | 558 | int getMode( ) 559 | { 560 | return this->mode ; 561 | } 562 | 563 | void close() 564 | { 565 | fclose( this->fin ) ; 566 | } 567 | 568 | }; 569 | 570 | 571 | #endif 572 | -------------------------------------------------------------------------------- /PLYWriter.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Static class for writing PLY files. 4 | 5 | Copyright (C) 2011 Tao Ju 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public License 9 | (LGPL) as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef PLYWRITER_H 23 | #define PLYWRITER_H 24 | 25 | class PLYWriter { 26 | public: 27 | /// Constructor 28 | PLYWriter( ) { }; 29 | 30 | /// Write ply header 31 | static void writeHeader ( FILE* fout, int numVert, int numFace ) { 32 | // Ply 33 | fprintf( fout, "ply\n" ) ; 34 | 35 | // Always big endian 36 | fprintf( fout, "format binary_big_endian 1.0\n" ) ; 37 | 38 | // vertex properties 39 | fprintf( fout, "element vertex %d\n", numVert ) ; 40 | fprintf( fout, "property float x\n" ) ; 41 | fprintf( fout, "property float y\n" ) ; 42 | fprintf( fout, "property float z\n" ) ; 43 | 44 | // face properties 45 | fprintf( fout, "element face %d\n", numFace ) ; 46 | fprintf( fout, "property list uchar int vertex_indices\n" ) ; 47 | 48 | // End 49 | fprintf( fout, "end_header\n" ) ; 50 | }; 51 | // data written below is not ascii, but binary! 52 | 53 | /// Write vertex 54 | static void writeVertex ( FILE* fout, float vt[3] ) 55 | { 56 | float nvt[3] ; 57 | for ( int i = 0 ; i < 3 ; i ++ ) 58 | { 59 | nvt[i] = vt[i] ; 60 | flipBits32( &(nvt[i]) ) ; 61 | } 62 | fwrite( nvt, sizeof ( float ), 3, fout ) ; 63 | }; 64 | 65 | /// Write face 66 | static void writeFace ( FILE* fout, int num, int fc[] ) 67 | { 68 | unsigned char cnum = num ; 69 | fwrite( &cnum, sizeof( unsigned char ), 1, fout ) ; 70 | for ( int i = 0 ; i < num ; i ++ ) 71 | { 72 | flipBits32( &(fc[i]) ) ; 73 | } 74 | fwrite( fc, sizeof ( int ), num, fout ) ; 75 | }; 76 | 77 | static void flipBits32 ( void *x ) 78 | { 79 | unsigned char *temp = (unsigned char *)x; 80 | unsigned char swap; 81 | 82 | swap = temp [ 0 ]; 83 | temp [ 0 ] = temp [ 3 ]; 84 | temp [ 3 ] = swap; 85 | 86 | swap = temp [ 1 ]; 87 | temp [ 1 ] = temp [ 2 ]; 88 | temp [ 2 ] = swap; 89 | }; 90 | 91 | }; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /dc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 Tao Ju 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public License 6 | (LGPL) as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | #include "octree.hpp" 19 | #include "PLYReader.hpp" 20 | #include "PLYWriter.hpp" 21 | #include "intersection.hpp" 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | namespace po = boost::program_options; 28 | 29 | //#define ALLOW_INTERSECTION 30 | 31 | /* Parameters 32 | * argv[1]: name of input file (.dcf format) 33 | * argv[2]: name of output file (.ply format) 34 | * argv[3]: (OPTIONAL) name of secondary output file (.ply format) 35 | * when using dual contouring, storing self-intersecting triangles. 36 | */ 37 | 38 | int main( int args, char* argv[] ) 39 | { 40 | // Declare the supported options. 41 | po::options_description desc("Allowed options"); 42 | desc.add_options() 43 | ("help", "produce help message") 44 | ("simplify", po::value(), "set simplify threshold (float)") 45 | ("nointer", "use intersection-free algorithm") 46 | ("test", "run intersection test") 47 | ; 48 | 49 | po::variables_map vm; 50 | po::store(po::parse_command_line(args, argv, desc), vm); 51 | po::notify(vm); 52 | 53 | if (vm.count("help")) { 54 | std::cout << desc << "\n"; 55 | return 1; 56 | } 57 | float simplify_threshold = -1; 58 | if (vm.count("simplify")) { 59 | simplify_threshold = vm["simplify"].as(); 60 | std::cout << "Simplify threshold set: " << simplify_threshold << "\n"; 61 | } else { 62 | std::cout << "Simplify not set.\n"; 63 | } 64 | 65 | // Read input file 66 | std::cout << " input file: " << argv[1] << "\n"; 67 | Octree* mytree = new Octree( argv[1], simplify_threshold ) ; 68 | 69 | if (vm.count("nointer")) { 70 | std::cout << "Intersection-free algorithm! [Ju et al. 2006] \n"; 71 | mytree->genContourNoInter2( argv[2] ) ; 72 | } else { 73 | std::cout << "Original algorithm! [Ju et al. 2002] \n"; 74 | mytree->genContour( argv[2] ) ; 75 | } 76 | 77 | if (vm.count("test")) { 78 | printf("Running intersection test... \n") ; 79 | int num = Intersection::testIntersection( argv[2], argv[3] ); // Pairwise intersection test - may take a while 80 | printf("%d intersections found!\n", num) ; 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /eigen.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Numerical functions for computing minimizers of a least-squares system 4 | of equations. 5 | 6 | Copyright (C) 2011 Scott Schaefer 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public License 10 | (LGPL) as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | 24 | #include "eigen.hpp" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);a[k][l]=h+s*(g-h*tau); 31 | 32 | // used to select solving method in calcPoint() 33 | int method = 3; 34 | 35 | // for reducing two upper triangular systems of equations into 1 36 | void qr ( float *mat1, float *mat2, float *rvalue ) 37 | { 38 | int i, j; 39 | float temp1 [ 8 ] [ 4 ]; 40 | 41 | for ( i = 0; i < 4; i++ ) 42 | { 43 | for ( j = 0; j < i; j++ ) 44 | { 45 | temp1 [ i ] [ j ] = 0; 46 | temp1 [ i + 4 ] [ j ] = 0; 47 | } 48 | for ( j = i; j < 4; j++ ) 49 | { 50 | temp1 [ i ] [ j ] = mat1 [ ( 7 * i - i * i ) / 2 + j ]; 51 | temp1 [ i + 4 ] [ j ] = mat2 [ ( 7 * i - i * i ) / 2 + j ]; 52 | } 53 | } 54 | 55 | qr ( temp1, 8, rvalue ); 56 | } 57 | 58 | // WARNING: destroys eqs in the process 59 | void qr ( float eqs[][4], int num, float *rvalue ) 60 | { 61 | int i, j, k; 62 | 63 | qr ( eqs, num, 0.000001f ); 64 | for ( i = 0; i < 10; i++ ) 65 | { 66 | rvalue [ i ] = 0; 67 | } 68 | 69 | k = 0; 70 | for ( i = 0; i < num && i < 4; i++ ) 71 | { 72 | for ( j = i; j < 4; j++ ) 73 | { 74 | rvalue [ k++ ] = eqs [ i ] [ j ]; 75 | } 76 | } 77 | } 78 | 79 | void qr ( float eqs[][4], int num, float tol ) 80 | { 81 | int i, j, k; 82 | float a, b, mag, temp; 83 | 84 | for ( i = 0; i < 4 && i < num; i++ ) 85 | { 86 | for ( j = i + 1; j < num; j++ ) 87 | { 88 | a = eqs [ i ] [ i ]; 89 | b = eqs [ j ] [ i ]; 90 | 91 | if ( fabs ( a ) > 0.000001f || fabs ( b ) > 0.000001f ) 92 | { 93 | mag = (float)sqrt ( a * a + b * b ); 94 | a /= mag; 95 | b /= mag; 96 | 97 | for ( k = 0; k < 4; k++ ) 98 | { 99 | temp = a * eqs [ i ] [ k ] + b * eqs [ j ] [ k ]; 100 | eqs [ j ] [ k ] = b * eqs [ i ] [ k ] - a * eqs [ j ] [ k ]; 101 | eqs [ i ] [ k ] = temp; 102 | } 103 | } 104 | } 105 | for ( j = i - 1; j >= 0; j-- ) 106 | { 107 | if ( eqs [ j ] [ j ] < 0.000001f && eqs [ j ] [ j ] > -0.000001f ) 108 | { 109 | a = eqs [ i ] [ i ]; 110 | b = eqs [ j ] [ i ]; 111 | 112 | if ( fabs ( a ) > 0.000001f || fabs ( b ) > 0.000001f ) 113 | { 114 | mag = (float)sqrt ( a * a + b * b ); 115 | a /= mag; 116 | b /= mag; 117 | 118 | for ( k = 0; k < 4; k++ ) 119 | { 120 | temp = a * eqs [ i ] [ k ] + b * eqs [ j ] [ k ]; 121 | eqs [ j ] [ k ] = b * eqs [ i ] [ k ] - a * eqs [ j ] [ k ]; 122 | eqs [ i ] [ k ] = temp; 123 | } 124 | } 125 | } 126 | } 127 | } 128 | 129 | } 130 | 131 | void jacobi ( float u[][3], float d[], float v[][3] ) 132 | { 133 | int j, iq, ip, i; 134 | float tresh, theta, tau, t, sm, s, h, g, c, b [ 3 ], z [ 3 ]; 135 | float a [ 3 ] [ 3 ]; 136 | 137 | a [ 0 ] [ 0 ] = u [ 0 ] [ 0 ]; 138 | a [ 0 ] [ 1 ] = u [ 0 ] [ 1 ]; 139 | a [ 0 ] [ 2 ] = u [ 0 ] [ 2 ]; 140 | a [ 1 ] [ 0 ] = u [ 1 ] [ 0 ]; 141 | a [ 1 ] [ 1 ] = u [ 1 ] [ 1 ]; 142 | a [ 1 ] [ 2 ] = u [ 1 ] [ 2 ]; 143 | a [ 2 ] [ 0 ] = u [ 2 ] [ 0 ]; 144 | a [ 2 ] [ 1 ] = u [ 2 ] [ 1 ]; 145 | a [ 2 ] [ 2 ] = u [ 2 ] [ 2 ]; 146 | 147 | for ( ip = 0; ip < 3; ip++ ) 148 | { 149 | for ( iq = 0; iq < 3; iq++ ) 150 | { 151 | v [ ip ] [ iq ] = 0.0f; 152 | } 153 | v [ ip ] [ ip ] = 1.0f; 154 | } 155 | 156 | for ( ip = 0; ip < 3; ip++ ) 157 | { 158 | b [ ip ] = a [ ip ] [ ip ]; 159 | d [ ip ] = b [ ip ]; 160 | z [ ip ] = 0.0f; 161 | } 162 | 163 | for ( i = 1; i <= 50; i++ ) 164 | { 165 | sm = 0.0f; 166 | for ( ip = 0; ip < 2; ip++ ) 167 | { 168 | for ( iq = ip + 1; iq < 3; iq++ ) 169 | { 170 | sm += (float)fabs ( a [ ip ] [ iq ] ); 171 | } 172 | } 173 | 174 | if ( sm == 0.0f ) 175 | { 176 | // sort the stupid things and transpose 177 | a [ 0 ] [ 0 ] = v [ 0 ] [ 0 ]; 178 | a [ 0 ] [ 1 ] = v [ 1 ] [ 0 ]; 179 | a [ 0 ] [ 2 ] = v [ 2 ] [ 0 ]; 180 | a [ 1 ] [ 0 ] = v [ 0 ] [ 1 ]; 181 | a [ 1 ] [ 1 ] = v [ 1 ] [ 1 ]; 182 | a [ 1 ] [ 2 ] = v [ 2 ] [ 1 ]; 183 | a [ 2 ] [ 0 ] = v [ 0 ] [ 2 ]; 184 | a [ 2 ] [ 1 ] = v [ 1 ] [ 2 ]; 185 | a [ 2 ] [ 2 ] = v [ 2 ] [ 2 ]; 186 | 187 | if ( fabs ( d [ 0 ] ) < fabs ( d [ 1 ] ) ) 188 | { 189 | sm = d [ 0 ]; 190 | d [ 0 ] = d [ 1 ]; 191 | d [ 1 ] = sm; 192 | 193 | sm = a [ 0 ] [ 0 ]; 194 | a [ 0 ] [ 0 ] = a [ 1 ] [ 0 ]; 195 | a [ 1 ] [ 0 ] = sm; 196 | sm = a [ 0 ] [ 1 ]; 197 | a [ 0 ] [ 1 ] = a [ 1 ] [ 1 ]; 198 | a [ 1 ] [ 1 ] = sm; 199 | sm = a [ 0 ] [ 2 ]; 200 | a [ 0 ] [ 2 ] = a [ 1 ] [ 2 ]; 201 | a [ 1 ] [ 2 ] = sm; 202 | } 203 | if ( fabs ( d [ 1 ] ) < fabs ( d [ 2 ] ) ) 204 | { 205 | sm = d [ 1 ]; 206 | d [ 1 ] = d [ 2 ]; 207 | d [ 2 ] = sm; 208 | 209 | sm = a [ 1 ] [ 0 ]; 210 | a [ 1] [ 0 ] = a [ 2 ] [ 0 ]; 211 | a [ 2 ] [ 0 ] = sm; 212 | sm = a [ 1 ] [ 1 ]; 213 | a [ 1 ] [ 1 ] = a [ 2 ] [ 1 ]; 214 | a [ 2 ] [ 1 ] = sm; 215 | sm = a [ 1 ] [ 2 ]; 216 | a [ 1 ] [ 2 ] = a [ 2 ] [ 2 ]; 217 | a [ 2 ] [ 2 ] = sm; 218 | } 219 | if ( fabs ( d [ 0 ] ) < fabs ( d [ 1 ] ) ) 220 | { 221 | sm = d [ 0 ]; 222 | d [ 0 ] = d [ 1 ]; 223 | d [ 1 ] = sm; 224 | 225 | sm = a [ 0 ] [ 0 ]; 226 | a [ 0 ] [ 0 ] = a [ 1 ] [ 0 ]; 227 | a [ 1 ] [ 0 ] = sm; 228 | sm = a [ 0 ] [ 1 ]; 229 | a [ 0 ] [ 1 ] = a [ 1 ] [ 1 ]; 230 | a [ 1 ] [ 1 ] = sm; 231 | sm = a [ 0 ] [ 2 ]; 232 | a [ 0 ] [ 2 ] = a [ 1 ] [ 2 ]; 233 | a [ 1 ] [ 2 ] = sm; 234 | } 235 | 236 | v [ 0 ] [ 0 ] = a [ 0 ] [ 0 ]; 237 | v [ 0 ] [ 1 ] = a [ 0 ] [ 1 ]; 238 | v [ 0 ] [ 2 ] = a [ 0 ] [ 2 ]; 239 | v [ 1 ] [ 0 ] = a [ 1 ] [ 0 ]; 240 | v [ 1 ] [ 1 ] = a [ 1 ] [ 1 ]; 241 | v [ 1 ] [ 2 ] = a [ 1 ] [ 2 ]; 242 | v [ 2 ] [ 0 ] = a [ 2 ] [ 0 ]; 243 | v [ 2 ] [ 1 ] = a [ 2 ] [ 1 ]; 244 | v [ 2 ] [ 2 ] = a [ 2 ] [ 2 ]; 245 | 246 | return; 247 | } 248 | 249 | if ( i < 4 ) 250 | { 251 | tresh = 0.2f * sm / 9; 252 | } 253 | else 254 | { 255 | tresh = 0.0f; 256 | } 257 | 258 | for ( ip = 0; ip < 2; ip++ ) 259 | { 260 | for ( iq = ip + 1; iq < 3; iq++ ) 261 | { 262 | g = 100.0f * (float)fabs ( a [ ip ] [ iq ] ); 263 | if ( i > 4 && (float)( fabs ( d [ ip ] ) + g ) == (float)fabs ( d [ ip ] ) 264 | && (float)( fabs ( d [ iq ] ) + g ) == (float)fabs ( d [ iq ] ) ) 265 | { 266 | a [ ip ] [ iq ] = 0.0f; 267 | } 268 | else 269 | { 270 | if ( fabs ( a [ ip ] [ iq ] ) > tresh ) 271 | { 272 | h = d [ iq ] - d [ ip ]; 273 | if ( (float)( fabs ( h ) + g ) == (float)fabs ( h ) ) 274 | { 275 | t = ( a [ ip ] [ iq ] ) / h; 276 | } 277 | else 278 | { 279 | theta = 0.5f * h / ( a [ ip ] [ iq ] ); 280 | t = 1.0f / ( (float)fabs ( theta ) + (float)sqrt ( 1.0f + theta * theta ) ); 281 | if ( theta < 0.0f ) 282 | { 283 | t = -1.0f * t; 284 | } 285 | } 286 | 287 | c = 1.0f / (float)sqrt ( 1 + t * t ); 288 | s = t * c; 289 | tau = s / ( 1.0f + c ); 290 | h = t * a [ ip ] [ iq ]; 291 | z [ ip ] -= h; 292 | z [ iq ] += h; 293 | d [ ip ] -= h; 294 | d [ iq ] += h; 295 | a [ ip ] [ iq ] = 0.0f; 296 | for ( j = 0; j <= ip - 1; j++ ) 297 | { 298 | ROTATE ( a, j, ip, j, iq ) 299 | } 300 | for ( j = ip + 1; j <= iq - 1; j++ ) 301 | { 302 | ROTATE ( a, ip, j, j, iq ) 303 | } 304 | for ( j = iq + 1; j < 3; j++ ) 305 | { 306 | ROTATE ( a, ip, j, iq, j ) 307 | } 308 | for ( j = 0; j < 3; j++ ) 309 | { 310 | ROTATE ( v, j, ip, j, iq ) 311 | } 312 | } 313 | } 314 | } 315 | } 316 | 317 | for ( ip = 0; ip < 3; ip++ ) 318 | { 319 | b [ ip ] += z [ ip ]; 320 | d [ ip ] = b [ ip ]; 321 | z [ ip ] = 0.0f; 322 | } 323 | } 324 | printf ( "too many iterations in jacobi\n" ); 325 | exit ( 1 ); 326 | } 327 | 328 | int estimateRank ( float *a ) 329 | { 330 | float w [ 3 ]; 331 | float u [ 3 ] [ 3 ]; 332 | float mat [ 3 ] [ 3 ]; 333 | int i; 334 | 335 | mat [ 0 ] [ 0 ] = a [ 0 ]; 336 | mat [ 0 ] [ 1 ] = a [ 1 ]; 337 | mat [ 0 ] [ 2 ] = a [ 2 ]; 338 | mat [ 1 ] [ 1 ] = a [ 3 ]; 339 | mat [ 1 ] [ 2 ] = a [ 4 ]; 340 | mat [ 2 ] [ 2 ] = a [ 5 ]; 341 | mat [ 1 ] [ 0 ] = a [ 1 ]; 342 | mat [ 2 ] [ 0 ] = a [ 2 ]; 343 | mat [ 2 ] [ 1 ] = a [ 4 ]; 344 | 345 | jacobi ( mat, w, u ); 346 | 347 | if ( w [ 0 ] == 0.0f ) 348 | { 349 | return 0; 350 | } 351 | else 352 | { 353 | for ( i = 1; i < 3; i++ ) 354 | { 355 | if ( w [ i ] < 0.1f ) 356 | { 357 | return i; 358 | } 359 | } 360 | 361 | return 3; 362 | } 363 | 364 | } 365 | 366 | void matInverse ( float mat[][3], float midpoint[], float rvalue[][3], float w[], float u[][3] ) 367 | { 368 | // there is an implicit assumption that mat is symmetric and real 369 | // U and V in the SVD will then be the same matrix whose rows are the eigenvectors of mat 370 | // W will just be the eigenvalues of mat 371 | // float w [ 3 ]; 372 | // float u [ 3 ] [ 3 ]; 373 | int i; 374 | 375 | jacobi ( mat, w, u ); 376 | 377 | if ( w [ 0 ] == 0.0f ) 378 | { 379 | // printf ( "error: largest eigenvalue is 0!\n" ); 380 | } 381 | else 382 | { 383 | for ( i = 1; i < 3; i++ ) 384 | { 385 | if ( w [ i ] < 0.001f ) // / w [ 0 ] < TOLERANCE ) 386 | { 387 | w [ i ] = 0; 388 | } 389 | else 390 | { 391 | w [ i ] = 1.0f / w [ i ]; 392 | } 393 | } 394 | w [ 0 ] = 1.0f / w [ 0 ]; 395 | } 396 | 397 | rvalue [ 0 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 0 ] + 398 | w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 0 ] + 399 | w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 0 ]; 400 | rvalue [ 0 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 1 ] + 401 | w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 1 ] + 402 | w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 1 ]; 403 | rvalue [ 0 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 2 ] + 404 | w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 2 ] + 405 | w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 2 ]; 406 | rvalue [ 1 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 0 ] + 407 | w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 0 ] + 408 | w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 0 ]; 409 | rvalue [ 1 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 1 ] + 410 | w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 1 ] + 411 | w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 1 ]; 412 | rvalue [ 1 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 2 ] + 413 | w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 2 ] + 414 | w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 2 ]; 415 | rvalue [ 2 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 0 ] + 416 | w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 0 ] + 417 | w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 0 ]; 418 | rvalue [ 2 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 1 ] + 419 | w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 1 ] + 420 | w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 1 ]; 421 | rvalue [ 2 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 2 ] + 422 | w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 2 ] + 423 | w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 2 ]; 424 | } 425 | 426 | float calcError ( float a[][3], float b[], float btb, float point[] ) 427 | { 428 | float rvalue = btb; 429 | 430 | rvalue += -2.0f * ( point [ 0 ] * b [ 0 ] + point [ 1 ] * b [ 1 ] + point [ 2 ] * b [ 2 ] ); 431 | rvalue += point [ 0 ] * ( a [ 0 ] [ 0 ] * point [ 0 ] + a [ 0 ] [ 1 ] * point [ 1 ] + a [ 0 ] [ 2 ] * point [ 2 ] ); 432 | rvalue += point [ 1 ] * ( a [ 1 ] [ 0 ] * point [ 0 ] + a [ 1 ] [ 1 ] * point [ 1 ] + a [ 1 ] [ 2 ] * point [ 2 ] ); 433 | rvalue += point [ 2 ] * ( a [ 2 ] [ 0 ] * point [ 0 ] + a [ 2 ] [ 1 ] * point [ 1 ] + a [ 2 ] [ 2 ] * point [ 2 ] ); 434 | 435 | return rvalue; 436 | } 437 | 438 | float *calcNormal ( float halfA[], float norm[], float expectedNorm[] ) 439 | { 440 | /* 441 | float a [ 3 ] [ 3 ]; 442 | float w [ 3 ]; 443 | float u [ 3 ] [ 3 ]; 444 | 445 | a [ 0 ] [ 0 ] = halfA [ 0 ]; 446 | a [ 0 ] [ 1 ] = halfA [ 1 ]; 447 | a [ 0 ] [ 2 ] = halfA [ 2 ]; 448 | a [ 1 ] [ 1 ] = halfA [ 3 ]; 449 | a [ 1 ] [ 2 ] = halfA [ 4 ]; 450 | a [ 1 ] [ 0 ] = halfA [ 1 ]; 451 | a [ 2 ] [ 0 ] = halfA [ 2 ]; 452 | a [ 2 ] [ 1 ] = halfA [ 4 ]; 453 | a [ 2 ] [ 2 ] = halfA [ 5 ]; 454 | 455 | jacobi ( a, w, u ); 456 | 457 | if ( u [ 1 ] != 0 ) 458 | { 459 | if ( w [ 1 ] / w [ 0 ] > 0.2f ) 460 | { 461 | // two dominant eigen values, just return the expectedNorm 462 | norm [ 0 ] = expectedNorm [ 0 ]; 463 | norm [ 1 ] = expectedNorm [ 1 ]; 464 | norm [ 2 ] = expectedNorm [ 2 ]; 465 | return; 466 | } 467 | } 468 | 469 | norm [ 0 ] = u [ 0 ] [ 0 ]; 470 | norm [ 1 ] = u [ 0 ] [ 1 ]; 471 | norm [ 2 ] = u [ 0 ] [ 2 ]; 472 | */ 473 | float dot = norm [ 0 ] * expectedNorm [ 0 ] + norm [ 1 ] * expectedNorm [ 1 ] + 474 | norm [ 2 ] * expectedNorm [ 2 ]; 475 | 476 | if ( dot < 0 ) 477 | { 478 | norm [ 0 ] *= -1.0f; 479 | norm [ 1 ] *= -1.0f; 480 | norm [ 2 ] *= -1.0f; 481 | 482 | dot *= -1.0f; 483 | } 484 | 485 | if ( dot < 0.707f ) 486 | { 487 | return expectedNorm; 488 | } 489 | else 490 | { 491 | return norm; 492 | } 493 | } 494 | 495 | void descent ( float A[][3], float B[], float guess[], BoundingBoxf *box ) 496 | { 497 | int i; 498 | float r [ 3 ]; 499 | float delta, delta0; 500 | int n = 10; 501 | float alpha, div; 502 | float newPoint [ 3 ]; 503 | float c; 504 | float store [ 3 ]; 505 | 506 | store [ 0 ] = guess [ 0 ]; 507 | store [ 1 ] = guess [ 1 ]; 508 | store [ 2 ] = guess [ 2 ]; 509 | 510 | if ( method == 2 || method == 0 ) { 511 | 512 | i = 0; 513 | r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] ); 514 | r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] ); 515 | r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] ); 516 | 517 | delta = r [ 0 ] * r [ 0 ] + r [ 1 ] * r [ 1 ] + r [ 2 ] * r [ 2 ]; 518 | delta0 = delta * TOLERANCE * TOLERANCE; 519 | 520 | while ( i < n && delta > delta0 ) { 521 | div = r [ 0 ] * ( A [ 0 ] [ 0 ] * r [ 0 ] + A [ 0 ] [ 1 ] * r [ 1 ] + A [ 0 ] [ 2 ] * r [ 2 ] ); 522 | div += r [ 1 ] * ( A [ 1 ] [ 0 ] * r [ 0 ] + A [ 1 ] [ 1 ] * r [ 1 ] + A [ 1 ] [ 2 ] * r [ 2 ] ); 523 | div += r [ 2 ] * ( A [ 2 ] [ 0 ] * r [ 0 ] + A [ 2 ] [ 1 ] * r [ 1 ] + A [ 2 ] [ 2 ] * r [ 2 ] ); 524 | 525 | if ( fabs ( div ) < 0.0000001f ) 526 | break; 527 | 528 | alpha = delta / div; 529 | 530 | newPoint [ 0 ] = guess [ 0 ] + alpha * r [ 0 ]; 531 | newPoint [ 1 ] = guess [ 1 ] + alpha * r [ 1 ]; 532 | newPoint [ 2 ] = guess [ 2 ] + alpha * r [ 2 ]; 533 | 534 | guess [ 0 ] = newPoint [ 0 ]; 535 | guess [ 1 ] = newPoint [ 1 ]; 536 | guess [ 2 ] = newPoint [ 2 ]; 537 | 538 | r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] ); 539 | r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] ); 540 | r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] ); 541 | 542 | delta = r [ 0 ] * r [ 0 ] + r [ 1 ] * r [ 1 ] + r [ 2 ] * r [ 2 ]; 543 | 544 | i++; 545 | } 546 | 547 | if ( guess [ 0 ] >= box->begin.x && guess [ 0 ] <= box->end.x && 548 | guess [ 1 ] >= box->begin.y && guess [ 1 ] <= box->end.y && 549 | guess [ 2 ] >= box->begin.z && guess [ 2 ] <= box->end.z ) 550 | { 551 | return; 552 | } 553 | } // method 2 or 0 554 | 555 | if ( method == 0 || method == 1 ) { 556 | c = A [ 0 ] [ 0 ] + A [ 1 ] [ 1 ] + A [ 2 ] [ 2 ]; 557 | if ( c == 0 ) 558 | return; 559 | 560 | c = ( 0.75f / c ); 561 | 562 | guess [ 0 ] = store [ 0 ]; 563 | guess [ 1 ] = store [ 1 ]; 564 | guess [ 2 ] = store [ 2 ]; 565 | 566 | r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] ); 567 | r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] ); 568 | r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] ); 569 | 570 | for ( i = 0; i < n; i++ ) { 571 | guess [ 0 ] = guess [ 0 ] + c * r [ 0 ]; 572 | guess [ 1 ] = guess [ 1 ] + c * r [ 1 ]; 573 | guess [ 2 ] = guess [ 2 ] + c * r [ 2 ]; 574 | 575 | r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] ); 576 | r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] ); 577 | r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] ); 578 | } 579 | } 580 | /* 581 | if ( guess [ 0 ] > store [ 0 ] + 1 || guess [ 0 ] < store [ 0 ] - 1 || 582 | guess [ 1 ] > store [ 1 ] + 1 || guess [ 1 ] < store [ 1 ] - 1 || 583 | guess [ 2 ] > store [ 2 ] + 1 || guess [ 2 ] < store [ 2 ] - 1 ) 584 | { 585 | printf ( "water let point go from %f,%f,%f to %f,%f,%f\n", 586 | store [ 0 ], store [ 1 ], store [ 2 ], guess [ 0 ], guess [ 1 ], guess [ 2 ] ); 587 | printf ( "A is %f,%f,%f %f,%f,%f %f,%f,%f\n", A [ 0 ] [ 0 ], A [ 0 ] [ 1 ], A [ 0 ] [ 2 ], 588 | A [ 1 ] [ 0 ] , A [ 1 ] [ 1 ], A [ 1 ] [ 2 ], A [ 2 ] [ 0 ], A [ 2 ] [ 1 ], A [ 2 ] [ 2 ] ); 589 | printf ( "B is %f,%f,%f\n", B [ 0 ], B [ 1 ], B [ 2 ] ); 590 | printf ( "bounding box is %f,%f,%f to %f,%f,%f\n", 591 | box->begin.x, box->begin.y, box->begin.z, box->end.x, box->end.y, box->end.z ); 592 | } 593 | */ 594 | } 595 | 596 | float calcPoint ( float halfA[], float b[], float btb, float midpoint[], float rvalue[], BoundingBoxf *box, float *mat ) 597 | { 598 | float newB [ 3 ]; 599 | float a [ 3 ] [ 3 ]; 600 | float inv [ 3 ] [ 3 ]; 601 | float w [ 3 ]; 602 | float u [ 3 ] [ 3 ]; 603 | 604 | a [ 0 ] [ 0 ] = halfA [ 0 ]; 605 | a [ 0 ] [ 1 ] = halfA [ 1 ]; 606 | a [ 0 ] [ 2 ] = halfA [ 2 ]; 607 | a [ 1 ] [ 1 ] = halfA [ 3 ]; 608 | a [ 1 ] [ 2 ] = halfA [ 4 ]; 609 | a [ 1 ] [ 0 ] = halfA [ 1 ]; 610 | a [ 2 ] [ 0 ] = halfA [ 2 ]; 611 | a [ 2 ] [ 1 ] = halfA [ 4 ]; 612 | a [ 2 ] [ 2 ] = halfA [ 5 ]; 613 | 614 | switch ( method ) // by default method = 3 615 | { 616 | case 0: 617 | case 1: 618 | case 2: 619 | rvalue [ 0 ] = midpoint [ 0 ]; 620 | rvalue [ 1 ] = midpoint [ 1 ]; 621 | rvalue [ 2 ] = midpoint [ 2 ]; 622 | 623 | descent ( a, b, rvalue, box ); 624 | return calcError ( a, b, btb, rvalue ); 625 | break; 626 | case 3: 627 | matInverse( a, midpoint, inv, w, u ); 628 | newB [ 0 ] = b [ 0 ] - a [ 0 ] [ 0 ] * midpoint [ 0 ] - a [ 0 ] [ 1 ] * midpoint [ 1 ] - a [ 0 ] [ 2 ] * midpoint [ 2 ]; 629 | newB [ 1 ] = b [ 1 ] - a [ 1 ] [ 0 ] * midpoint [ 0 ] - a [ 1 ] [ 1 ] * midpoint [ 1 ] - a [ 1 ] [ 2 ] * midpoint [ 2 ]; 630 | newB [ 2 ] = b [ 2 ] - a [ 2 ] [ 0 ] * midpoint [ 0 ] - a [ 2 ] [ 1 ] * midpoint [ 1 ] - a [ 2 ] [ 2 ] * midpoint [ 2 ]; 631 | rvalue [ 0 ] = inv [ 0 ] [ 0 ] * newB [ 0 ] + inv [ 1 ] [ 0 ] * newB [ 1 ] + inv [ 2 ] [ 0 ] * newB [ 2 ] + midpoint [ 0 ]; 632 | rvalue [ 1 ] = inv [ 0 ] [ 1 ] * newB [ 0 ] + inv [ 1 ] [ 1 ] * newB [ 1 ] + inv [ 2 ] [ 1 ] * newB [ 2 ] + midpoint [ 1 ]; 633 | rvalue [ 2 ] = inv [ 0 ] [ 2 ] * newB [ 0 ] + inv [ 1 ] [ 2 ] * newB [ 1 ] + inv [ 2 ] [ 2 ] * newB [ 2 ] + midpoint [ 2 ]; 634 | return calcError ( a, b, btb, rvalue ); 635 | break; 636 | case 4: 637 | method = 3; 638 | calcPoint ( halfA, b, btb, midpoint, rvalue, box, mat ); 639 | method = 4; 640 | /* 641 | int rank; 642 | float eqs [ 4 ] [ 4 ]; 643 | 644 | // form the square matrix 645 | eqs [ 0 ] [ 0 ] = mat [ 0 ]; 646 | eqs [ 0 ] [ 1 ] = mat [ 1 ]; 647 | eqs [ 0 ] [ 2 ] = mat [ 2 ]; 648 | eqs [ 0 ] [ 3 ] = mat [ 3 ]; 649 | eqs [ 1 ] [ 1 ] = mat [ 4 ]; 650 | eqs [ 1 ] [ 2 ] = mat [ 5 ]; 651 | eqs [ 1 ] [ 3 ] = mat [ 6 ]; 652 | eqs [ 2 ] [ 2 ] = mat [ 7 ]; 653 | eqs [ 2 ] [ 3 ] = mat [ 8 ]; 654 | eqs [ 3 ] [ 3 ] = mat [ 9 ]; 655 | eqs [ 1 ] [ 0 ] = eqs [ 2 ] [ 0 ] = eqs [ 2 ] [ 1 ] = eqs [ 3 ] [ 0 ] = eqs [ 3 ] [ 1 ] = eqs [ 3 ] [ 2 ] = 0; 656 | 657 | // compute the new QR decomposition and rank 658 | rank = qr ( eqs ); 659 | 660 | method = 2; 661 | calcPoint ( halfA, b, btb, midpoint, rvalue, box, mat ); 662 | method = 4; 663 | /* 664 | if ( rank == 0 ) 665 | { 666 | // it's zero, no equations 667 | rvalue [ 0 ] = midpoint [ 0 ]; 668 | rvalue [ 1 ] = midpoint [ 1 ]; 669 | rvalue [ 2 ] = midpoint [ 2 ]; 670 | } 671 | else 672 | { 673 | if ( rank == 1 ) 674 | { 675 | // one equation, it's a plane 676 | float temp = ( eqs [ 0 ] [ 0 ] * midpoint [ 0 ] + eqs [ 0 ] [ 1 ] * midpoint [ 1 ] + eqs [ 0 ] [ 2 ] * midpoint [ 2 ] - eqs [ 0 ] [ 3 ] ) / 677 | ( eqs [ 0 ] [ 0 ] * eqs [ 0 ] [ 0 ] + eqs [ 0 ] [ 1 ] * eqs [ 0 ] [ 1 ] + eqs [ 0 ] [ 2 ] * eqs [ 0 ] [ 2 ] ); 678 | 679 | rvalue [ 0 ] = midpoint [ 0 ] - temp * eqs [ 0 ] [ 0 ]; 680 | rvalue [ 1 ] = midpoint [ 1 ] - temp * eqs [ 0 ] [ 1 ]; 681 | rvalue [ 2 ] = midpoint [ 2 ] - temp * eqs [ 0 ] [ 2 ]; 682 | } 683 | else 684 | { 685 | if ( rank == 2 ) 686 | { 687 | // two equations, it's a line 688 | float a, b, c, d, e, f, g; 689 | 690 | // reduce back to upper triangular 691 | qr ( eqs, 2, 0.000001f ); 692 | 693 | a = eqs [ 0 ] [ 0 ]; 694 | b = eqs [ 0 ] [ 1 ]; 695 | c = eqs [ 0 ] [ 2 ]; 696 | d = eqs [ 0 ] [ 3 ]; 697 | e = eqs [ 1 ] [ 1 ]; 698 | f = eqs [ 1 ] [ 2 ]; 699 | g = eqs [ 1 ] [ 3 ]; 700 | 701 | // solved using the equations 702 | // ax + by + cz = d 703 | // ey + fz = g 704 | // minimize (x-px)^2 + (y-py)^2 + (z-pz)^2 705 | if ( a > 0.000001f || a < -0.000001f ) 706 | { 707 | if ( e > 0.00000f || e < -0.000001f ) 708 | { 709 | rvalue [ 2 ] = ( -1 * b * d * e * f + ( a * a + b * b ) * g * f + c * e * ( d * e - b * g ) + 710 | a * e * ( ( b * f - c * e ) * midpoint [ 0 ] - a * f * midpoint [ 1 ] + a * e * midpoint [ 2 ] ) ) / 711 | ( a * a * ( e * e + f * f ) + ( c * e - b * f ) * ( c * e - b * f ) ); 712 | rvalue [ 1 ] = ( g - f * rvalue [ 2 ] ) / e; 713 | rvalue [ 0 ] = ( d - b * rvalue [ 1 ] - c * rvalue [ 2 ] ) / a; 714 | } 715 | else 716 | { 717 | // slightly degenerate case where e==0 718 | rvalue [ 2 ] = g / f; 719 | rvalue [ 1 ] = ( b * d * f - b * c * g - a * b * f * midpoint [ 0 ] + a * a * f * midpoint [ 1 ] ) / 720 | ( a * a * f + b * b * f ); 721 | rvalue [ 0 ] = ( d - b * rvalue [ 1 ] - c * rvalue [ 2 ] ) / a; 722 | } 723 | } 724 | else 725 | { 726 | // degenerate case where a==0 so e == 0 (upper triangular) 727 | 728 | rvalue [ 2 ] = g / f; 729 | rvalue [ 1 ] = ( d - c * rvalue [ 2 ] ) / b; 730 | rvalue [ 0 ] = midpoint [ 0 ]; 731 | } 732 | 733 | } 734 | else 735 | { 736 | // must be three equations or more now... solve using back-substitution 737 | rvalue [ 2 ] = mat [ 8 ] / mat [ 7 ]; 738 | rvalue [ 1 ] = ( mat [ 6 ] - mat [ 5 ] * rvalue [ 2 ] ) / mat [ 4 ]; 739 | rvalue [ 0 ] = ( mat [ 3 ] - mat [ 2 ] * rvalue [ 2 ] - mat [ 1 ] * rvalue [ 1 ] ) / mat [ 0 ]; 740 | } 741 | } 742 | } 743 | */ 744 | 745 | float ret; 746 | float tmp; 747 | 748 | ret = mat [ 9 ] * mat [ 9 ]; 749 | 750 | tmp = mat [ 0 ] * rvalue [ 0 ] + mat [ 1 ] * rvalue [ 1 ] + mat [ 2 ] * rvalue [ 2 ] - mat [ 3 ]; 751 | ret += tmp * tmp; 752 | 753 | tmp = mat [ 4 ] * rvalue [ 1 ] + mat [ 5 ] * rvalue [ 2 ] - mat [ 6 ]; 754 | ret += tmp * tmp; 755 | 756 | tmp = mat [ 7 ] * rvalue [ 2 ] - mat [ 8 ]; 757 | ret += tmp * tmp; 758 | 759 | return ret; 760 | 761 | break; 762 | case 5: // do nothing, return midpoint 763 | rvalue [ 0 ] = midpoint [ 0 ]; 764 | rvalue [ 1 ] = midpoint [ 1 ]; 765 | rvalue [ 2 ] = midpoint [ 2 ]; 766 | 767 | return calcError ( a, b, btb, rvalue ); 768 | } 769 | 770 | return 0 ; 771 | } 772 | -------------------------------------------------------------------------------- /eigen.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Numerical functions for computing minimizers of a least-squares system 4 | of equations. 5 | 6 | Copyright (C) 2011 Scott Schaefer 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public License 10 | (LGPL) as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | 24 | #ifndef EIGEN_H 25 | #define EIGEN_H 26 | 27 | #define TOLERANCE 0.0001f 28 | 29 | #include "GeoCommon.hpp" 30 | 31 | 32 | 33 | /** 34 | * Uses a jacobi method to return the eigenvectors and eigenvalues 35 | * of a 3x3 symmetric matrix. Note: "a" will be destroyed in this 36 | * process. "d" will contain the eigenvalues sorted in order of 37 | * decreasing modulus and v will contain the corresponding eigenvectors. 38 | * 39 | * @param a the 3x3 symmetric matrix to calculate the eigensystem for 40 | * @param d the variable to hold the eigenvalues 41 | * @param v the variables to hold the eigenvectors 42 | */ 43 | void jacobi ( float a[][3], float d[], float v[][3] ); 44 | 45 | /** 46 | * Inverts a 3x3 symmetric matrix by computing the pseudo-inverse. 47 | * 48 | * @param mat the matrix to invert 49 | * @param midpoint the point to minimize towards 50 | * @param rvalue the variable to store the pseudo-inverse in 51 | * @param w the place to store the inverse of the eigenvalues 52 | * @param u the place to store the eigenvectors 53 | */ 54 | void matInverse ( float mat[][3], float midpoint[], float rvalue[][3], float w[], float u[][3] ); 55 | 56 | /** 57 | * Calculates the L2 norm of the residual (the error) 58 | * (Transpose[A].A).x = Transpose[A].B 59 | * 60 | * @param a the matrix Transpose[A].A 61 | * @param b the matrix Transpose[A].B 62 | * @param btb the value Transpose[B].B 63 | * @param point the minimizer found 64 | * 65 | * @return the error of the minimizer 66 | */ 67 | float calcError ( float a[][3], float b[], float btb, float point[] ); 68 | 69 | /** 70 | * Calculates the normal. This function is not called and doesn't do 71 | * anything right now. It was originally meant to orient the normals 72 | * correctly that came from the principle eigenvector, but we're flat 73 | * shading now. 74 | */ 75 | float *calcNormal ( float halfA[], float norm[], float expectedNorm[] ); 76 | 77 | /** 78 | * Calculates the minimizer of the given system and returns its error. 79 | * 80 | * @param halfA the compressed form of the symmetric matrix Transpose[A].A 81 | * @param b the matrix Transpose[A].B 82 | * @param btb the value Transpose[B].B 83 | * @param midpoint the point to minimize towards 84 | * @param rvalue the place to store the minimizer 85 | * @param box the volume bounding the voxel this QEF is for 86 | * 87 | * @return the error of the minimizer 88 | */ 89 | float calcPoint ( float halfA[], float b[], float btb, float midpoint[], float rvalue[], BoundingBoxf *box, float *mat ); 90 | 91 | 92 | void qr ( float eqs[][4], int num, float *rvalue ); 93 | void qr ( float *mat1, float *mat2, float *rvalue ); 94 | void qr ( float eqs[][4], int num = 4, float tol = 0.000001f ); 95 | 96 | int estimateRank ( float *a ); 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /intersection.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (C) 2011 Tao Ju 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public License 7 | (LGPL) as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef INTERSECTION_H 21 | #define INTERSECTION_H 22 | 23 | #include "GeoCommon.hpp" 24 | #include "PLYReader.hpp" 25 | #include "PLYWriter.hpp" 26 | #include 27 | #include 28 | #include 29 | 30 | class Intersection 31 | { 32 | public: 33 | Intersection(){} ; 34 | // c = a x b 35 | static void cross( float a[3], float b[3], float c[3] ) 36 | { 37 | c[0] = a[1] * b[2] - a[2] * b[1] ; 38 | c[1] = a[2] * b[0] - a[0] * b[2] ; 39 | c[2] = a[0] * b[1] - a[1] * b[0] ; 40 | } 41 | // a dot b 42 | static float dot( float a[3], float b[3] ) 43 | { 44 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ; 45 | } 46 | 47 | 48 | static int separating( float axes[3], Triangle* t1, Triangle* t2 ) 49 | { 50 | //float mag1 = sqrt(dot( axes, axes )) ; 51 | //axes[0] /= mag1 ; 52 | //axes[1] /= mag1 ; 53 | //axes[2] /= mag1 ; 54 | 55 | float min1 = dot( axes, t1->vt[0] ), max1; 56 | max1 = min1 ; 57 | float min2 = dot( axes, t2->vt[0] ), max2; 58 | max2 = min2 ; 59 | 60 | float temp ; 61 | for ( int i = 1 ; i < 3 ; i ++ ) 62 | { 63 | temp = dot( axes, t1->vt[i] ) ; 64 | if ( temp < min1 ) 65 | { 66 | min1 = temp ; 67 | } 68 | else if ( temp > max1 ) 69 | { 70 | max1 = temp ; 71 | } 72 | 73 | temp = dot( axes, t2->vt[i] ) ; 74 | if ( temp < min2 ) 75 | { 76 | min2 = temp ; 77 | } 78 | else if ( temp > max2 ) 79 | { 80 | max2 = temp ; 81 | } 82 | } 83 | 84 | if ( min1 >= max2 || min2 >= max1 ) 85 | { 86 | return 1 ; 87 | } 88 | else 89 | { 90 | return 0 ; 91 | } 92 | } 93 | 94 | static int separating( float axes[3], Triangle* t1, Triangle* t2, int printout ) 95 | { 96 | //float mag1 = sqrt(dot( axes, axes )) ; 97 | //axes[0] /= mag1 ; 98 | //axes[1] /= mag1 ; 99 | //axes[2] /= mag1 ; 100 | 101 | float min1 = dot( axes, t1->vt[0] ), max1; 102 | max1 = min1 ; 103 | float min2 = dot( axes, t2->vt[0] ), max2; 104 | max2 = min2 ; 105 | 106 | float temp ; 107 | for ( int i = 1 ; i < 3 ; i ++ ) 108 | { 109 | temp = dot( axes, t1->vt[i] ) ; 110 | if ( temp < min1 ) 111 | { 112 | min1 = temp ; 113 | } 114 | else if ( temp > max1 ) 115 | { 116 | max1 = temp ; 117 | } 118 | 119 | temp = dot( axes, t2->vt[i] ) ; 120 | if ( temp < min2 ) 121 | { 122 | min2 = temp ; 123 | } 124 | else if ( temp > max2 ) 125 | { 126 | max2 = temp ; 127 | } 128 | } 129 | 130 | if ( printout ) 131 | { 132 | for ( int k = 0 ; k < 3 ; k ++ ) 133 | { 134 | printf("(%f %f %f),", t1->vt[k][0], t1->vt[k][1],t1->vt[k][2]); 135 | } 136 | printf("\n"); 137 | for ( int k = 0 ; k < 3 ; k ++ ) 138 | { 139 | printf("(%f %f %f),", t2->vt[k][0], t2->vt[k][1],t2->vt[k][2]); 140 | } 141 | 142 | printf("\n(%f, %f), (%f, %f)\n", min1, max1, min2, max2) ; 143 | } 144 | 145 | if ( min1 >= max2 || min2 >= max1 ) 146 | { 147 | return 1 ; 148 | } 149 | else 150 | { 151 | return 0 ; 152 | } 153 | } 154 | 155 | static int separating( float axes[3], Triangle* t1, float v1[3], float v2[3] ) 156 | { 157 | float mag1 = sqrt(dot( axes, axes )) ; 158 | axes[0] /= mag1 ; 159 | axes[1] /= mag1 ; 160 | axes[2] /= mag1 ; 161 | 162 | float min1 = dot( axes, t1->vt[0] ), max1 = min1 ; 163 | float temp ; 164 | for ( int i = 1 ; i < 3 ; i ++ ) 165 | { 166 | temp = dot( axes, t1->vt[i] ) ; 167 | if ( temp < min1 ) 168 | { 169 | min1 = temp ; 170 | } 171 | else if ( temp > max1 ) 172 | { 173 | max1 = temp ; 174 | } 175 | } 176 | 177 | float min2 = dot( axes, v1 ) ; 178 | float max2 = dot( axes, v2 ) ; 179 | if ( min2 > max2 ) 180 | { 181 | temp = min2 ; 182 | min2 = max2 ; 183 | max2 = temp ; 184 | } 185 | 186 | 187 | if ( min1 > max2 + 0.00001f || min2 > max1 + 0.00001f ) 188 | { 189 | return 1 ; 190 | } 191 | else 192 | { 193 | return 0 ; 194 | } 195 | } 196 | 197 | static int testIntersection( Triangle* t1, Triangle* t2 ) 198 | { 199 | // Two face normals 200 | float v1[3][3] = {{ t1->vt[1][0] - t1->vt[0][0], t1->vt[1][1] - t1->vt[0][1], t1->vt[1][2] - t1->vt[0][2] }, 201 | { t1->vt[2][0] - t1->vt[1][0], t1->vt[2][1] - t1->vt[1][1], t1->vt[2][2] - t1->vt[1][2] }, 202 | { t1->vt[0][0] - t1->vt[2][0], t1->vt[0][1] - t1->vt[2][1], t1->vt[0][2] - t1->vt[2][2] }}; 203 | float v2[3][3] = {{ t2->vt[1][0] - t2->vt[0][0], t2->vt[1][1] - t2->vt[0][1], t2->vt[1][2] - t2->vt[0][2] }, 204 | { t2->vt[2][0] - t2->vt[1][0], t2->vt[2][1] - t2->vt[1][1], t2->vt[2][2] - t2->vt[1][2] }, 205 | { t2->vt[0][0] - t2->vt[2][0], t2->vt[0][1] - t2->vt[2][1], t2->vt[0][2] - t2->vt[2][2] } }; 206 | float n1[3], n2[3] ; 207 | cross( v1[0], v1[1], n1 ) ; 208 | cross( v2[0], v2[1], n2 ) ; 209 | 210 | float n[3] ; 211 | cross( n1, n2, n ) ; 212 | int i, j ; 213 | if ( n[0] == 0 && n[1] == 0 && n[2] == 0 ) 214 | { 215 | // Co-planar 216 | 217 | if ( dot( n1, t1->vt[0] ) != dot( n1, t2->vt[0] ) ) 218 | { 219 | return 0 ; 220 | } 221 | 222 | float axes[3] ; 223 | for ( i = 0 ; i < 3 ; i ++ ) 224 | { 225 | cross( n1, v1[i], axes ) ; 226 | if ( separating( axes, t1, t2 ) ) 227 | { 228 | return 0 ; 229 | } 230 | } 231 | for ( i = 0 ; i < 3 ; i ++ ) 232 | { 233 | cross( n2, v2[i], axes ) ; 234 | if ( separating( axes, t1, t2 ) ) 235 | { 236 | return 0 ; 237 | } 238 | } 239 | } 240 | else 241 | { 242 | // Non co-planar 243 | if ( separating( n1, t1, t2 ) || separating( n2, t1, t2 ) ) 244 | { 245 | return 0 ; 246 | } 247 | 248 | float axes[3] ; 249 | for ( i = 0 ; i < 3 ; i ++ ) 250 | for ( j = 0 ; j < 3 ; j ++ ) 251 | { 252 | cross( v1[i], v2[j], axes ) ; 253 | if ( separating( axes, t1, t2 ) ) 254 | { 255 | return 0 ; 256 | } 257 | } 258 | } 259 | 260 | return 1 ; 261 | } 262 | 263 | static int testIntersection( Triangle* t1, BoundingBox b1, Triangle* t2, BoundingBox b2, int printout ) 264 | { 265 | // Bounding box 266 | if ( b1.begin.x > b2.end.x || b1.begin.y > b2.end.y || b1.begin.z > b2.end.z || 267 | b2.begin.x > b1.end.x || b2.begin.y > b1.end.y || b2.begin.z > b1.end.z ) 268 | { 269 | return 0 ; 270 | } 271 | 272 | // Two face normals 273 | float v1[3][3] = {{ t1->vt[1][0] - t1->vt[0][0], t1->vt[1][1] - t1->vt[0][1], t1->vt[1][2] - t1->vt[0][2] }, 274 | { t1->vt[2][0] - t1->vt[1][0], t1->vt[2][1] - t1->vt[1][1], t1->vt[2][2] - t1->vt[1][2] }, 275 | { t1->vt[0][0] - t1->vt[2][0], t1->vt[0][1] - t1->vt[2][1], t1->vt[0][2] - t1->vt[2][2] }}; 276 | float v2[3][3] = {{ t2->vt[1][0] - t2->vt[0][0], t2->vt[1][1] - t2->vt[0][1], t2->vt[1][2] - t2->vt[0][2] }, 277 | { t2->vt[2][0] - t2->vt[1][0], t2->vt[2][1] - t2->vt[1][1], t2->vt[2][2] - t2->vt[1][2] }, 278 | { t2->vt[0][0] - t2->vt[2][0], t2->vt[0][1] - t2->vt[2][1], t2->vt[0][2] - t2->vt[2][2] } }; 279 | float n1[3], n2[3] ; 280 | cross( v1[0], v1[1], n1 ) ; 281 | cross( v2[0], v2[1], n2 ) ; 282 | 283 | float n[3] ; 284 | cross( n1, n2, n ) ; 285 | int i, j ; 286 | if ( n[0] == 0 && n[1] == 0 && n[2] == 0 ) 287 | { 288 | // Co-planar, regard it as not intersecting -- Hack! 289 | return 0 ; 290 | 291 | if ( printout ) 292 | { 293 | printf("Co-planar!\n") ; 294 | } 295 | if ( dot( n1, t1->vt[0] ) != dot( n1, t2->vt[0] ) ) 296 | { 297 | return 0 ; 298 | } 299 | 300 | float axes[3] ; 301 | for ( i = 0 ; i < 3 ; i ++ ) 302 | { 303 | cross( n1, v1[i], axes ) ; 304 | if ( separating( axes, t1, t2, printout ) ) 305 | { 306 | return 0 ; 307 | } 308 | } 309 | for ( i = 0 ; i < 3 ; i ++ ) 310 | { 311 | cross( n2, v2[i], axes ) ; 312 | if ( separating( axes, t1, t2, printout ) ) 313 | { 314 | return 0 ; 315 | } 316 | } 317 | } 318 | else 319 | { 320 | // Non co-planar 321 | if ( separating( n1, t1, t2, printout ) || separating( n2, t1, t2, printout ) ) 322 | { 323 | return 0 ; 324 | } 325 | 326 | float axes[3] ; 327 | for ( i = 0 ; i < 3 ; i ++ ) 328 | for ( j = 0 ; j < 3 ; j ++ ) 329 | { 330 | cross( v1[i], v2[j], axes ) ; 331 | if ( separating( axes, t1, t2, printout ) ) 332 | { 333 | return 0 ; 334 | } 335 | } 336 | } 337 | 338 | return 1 ; 339 | } 340 | 341 | static int testIntersection( char* fname, char* outname ) 342 | { 343 | Triangle *intertris[100000]; 344 | 345 | // Read triangles 346 | PLYReader* myreader = new PLYReader( fname, 1 ) ; 347 | int numpoly = myreader->getNumTriangles() ; 348 | int num = 0 ; 349 | Triangle** tris = new Triangle *[ numpoly ] ; 350 | Triangle* tri = NULL ; 351 | myreader->reset() ; 352 | while( (tri = myreader->getNextTriangle()) != NULL ) 353 | { 354 | tris[ num ] = tri ; 355 | num ++ ; 356 | } 357 | myreader->close() ; 358 | printf("Reading %d polygons, %d triangles.\n", numpoly, num ) ; 359 | 360 | // Build bounding boxes 361 | printf("Building bounding boxes...\n") ; 362 | int i ; 363 | BoundingBox* boxes = new BoundingBox[ num ] ; 364 | for ( i = 0 ; i < num ; i ++ ) 365 | { 366 | Triangle* t = tris[ i ] ; 367 | 368 | boxes[i].begin.x = 100000 ; 369 | boxes[i].begin.y = 100000 ; 370 | boxes[i].begin.z = 100000 ; 371 | boxes[i].end.x = -100000 ; 372 | boxes[i].end.y = -100000 ; 373 | boxes[i].end.z = -100000 ; 374 | 375 | for ( int j = 0 ; j < 3 ; j ++ ) 376 | { 377 | if ( t->vt[j][0] < boxes[i].begin.x ) 378 | { 379 | boxes[i].begin.x = t->vt[j][0] ; 380 | } 381 | if ( t->vt[j][0] > boxes[i].end.x ) 382 | { 383 | boxes[i].end.x = t->vt[j][0] ; 384 | } 385 | 386 | if ( t->vt[j][1] < boxes[i].begin.y ) 387 | { 388 | boxes[i].begin.y = t->vt[j][1] ; 389 | } 390 | if ( t->vt[j][1] > boxes[i].end.y ) 391 | { 392 | boxes[i].end.y = t->vt[j][1] ; 393 | } 394 | 395 | if ( t->vt[j][2] < boxes[i].begin.z ) 396 | { 397 | boxes[i].begin.z = t->vt[j][2] ; 398 | } 399 | if ( t->vt[j][2] > boxes[i].end.z ) 400 | { 401 | boxes[i].end.z = t->vt[j][2] ; 402 | } 403 | } 404 | 405 | } 406 | 407 | // Test intersections 408 | printf("Pairwise searching...\n") ; 409 | int numinters = 0 ; 410 | for ( i = 0 ; i < num ; i ++ ) 411 | { 412 | for ( int j = 0 ; j < i ; j ++ ) 413 | { 414 | if ( testIntersection( tris[i], boxes[i], tris[j], boxes[j], 0 ) ) 415 | { 416 | intertris[ 2 * numinters ] = tris[i] ; 417 | intertris[ 2 * numinters + 1 ] = tris[j] ; 418 | numinters ++ ; 419 | 420 | /* 421 | printf("First tri: "); 422 | for ( int k = 0 ; k < 3 ; k ++ ) 423 | { 424 | printf("(%f %f %f),", tris[i]->vt[k][0], tris[i]->vt[k][1],tris[i]->vt[k][2]); 425 | } 426 | printf("\nSecond tri: "); 427 | for ( k = 0 ; k < 3 ; k ++ ) 428 | { 429 | printf("(%f %f %f),", tris[j]->vt[k][0], tris[j]->vt[k][1],tris[j]->vt[k][2]); 430 | } 431 | // printf("\n") ; 432 | */ 433 | } 434 | } 435 | } 436 | 437 | // Write out 438 | printf("Write out...\n") ; 439 | if ( numinters > 0 ) 440 | { 441 | FILE* intout = fopen( outname, "wb" ) ; 442 | PLYWriter::writeHeader( intout, 6 * numinters, 2 * numinters ) ; 443 | Triangle* t ; 444 | 445 | // Write vertices 446 | for ( int i = 0 ; i < numinters ; i ++ ) 447 | { 448 | t = intertris[ 2 * i ] ; 449 | for ( int j = 0 ; j < 3 ; j ++ ) 450 | { 451 | PLYWriter::writeVertex( intout, t->vt[j] ) ; 452 | } 453 | t = intertris[ 2 * i + 1 ] ; 454 | for ( int j = 0 ; j < 3 ; j ++ ) 455 | { 456 | PLYWriter::writeVertex( intout, t->vt[j] ) ; 457 | } 458 | } 459 | 460 | // Write triangles 461 | for ( int i = 0 ; i < numinters ; i ++ ) 462 | { 463 | int tind1[] = { 6 * i, 6 * i + 1, 6 * i + 2 } ; 464 | PLYWriter::writeFace( intout, 3, tind1 ) ; 465 | int tind2[] = { 6 * i + 3, 6 * i + 4, 6 * i + 5 } ; 466 | PLYWriter::writeFace( intout, 3, tind2 ) ; 467 | } 468 | 469 | fclose( intout ) ; 470 | } 471 | 472 | return numinters ; 473 | } 474 | 475 | }; 476 | 477 | 478 | #endif 479 | -------------------------------------------------------------------------------- /mechanic.dcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aewallin/dualcontouring/6ad20d36caa10302e4cd296c553bbe7a7b2d57ed/mechanic.dcf -------------------------------------------------------------------------------- /octree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Implementations of Octree member functions. 4 | 5 | Copyright (C) 2011 Tao Ju 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public License 9 | (LGPL) as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | #include "octree.hpp" 32 | #include "PLYWriter.hpp" 33 | 34 | 35 | #if _WIN64 || __x86_64__ || __ppc64__ 36 | #define ENVIRONMENT64 37 | #else 38 | #define ENVIRONMENT32 39 | #endif 40 | 41 | 42 | #ifdef ENVIRONMENT64 43 | typedef long int ptr_type; 44 | #else 45 | typedef int ptr_type; 46 | #endif 47 | 48 | Octree::Octree( char* fname, double threshold ) 49 | { 50 | simplify_threshold = threshold; 51 | // Recognize file format 52 | /* 53 | if ( strstr( fname, ".sog" ) != NULL || strstr( fname, ".SOG" ) != NULL ) { 54 | printf("Reading SOG file format.\n") ; 55 | this->hasQEF = 0 ; 56 | readSOG( fname ) ; 57 | }*/ 58 | if ( strstr( fname, ".dcf" ) != NULL || strstr( fname, ".DCF" ) != NULL ) { 59 | printf("Reading DCF file format.\n") ; 60 | this->hasQEF = 1 ; 61 | readDCF( fname ) ; 62 | } 63 | else { 64 | printf("Wrong input format. Must be SOG/DCF.\n"); 65 | exit(0) ; 66 | } 67 | 68 | } 69 | 70 | void Octree::simplify( float thresh ) { 71 | if ( this->hasQEF ) { 72 | int st[3] = {0,0,0} ; 73 | this->root = simplify( this->root, st, this->dimen, thresh ) ; 74 | } 75 | } 76 | 77 | // simplify by collapsing nodes where the parent node QEF solution is good enough 78 | OctreeNode* Octree::simplify( OctreeNode* node, int st[3], int len, float thresh ) { 79 | if ( node == NULL ) 80 | return NULL ; 81 | 82 | //NodeType type = ; 83 | 84 | if ( node->getType() == INTERNAL ) { 85 | InternalNode* inode = (InternalNode*)node ; 86 | int simple = 1; 87 | 88 | // QEF data 89 | float ata[6] = { 0, 0, 0, 0, 0, 0 }; 90 | float atb[3] = { 0, 0, 0 } ; 91 | float pt[3] = { 0, 0, 0 } ; 92 | //float mp[3] = { 0, 0, 0 } ; 93 | float btb = 0 ; 94 | int signs[8] = {-1,-1,-1,-1,-1,-1,-1,-1} ; 95 | int midsign = -1 ; 96 | 97 | // child data 98 | int nlen = len / 2 ; 99 | int nst[3] ; 100 | int ec = 0 ; 101 | int ht ; 102 | 103 | for ( int i = 0 ; i < 8 ; i ++ ) { // recurse into tree 104 | nst[0] = st[0] + vertMap[i][0] * nlen ; 105 | nst[1] = st[1] + vertMap[i][1] * nlen ; 106 | nst[2] = st[2] + vertMap[i][2] * nlen ; 107 | 108 | inode->child[i] = simplify( inode->child[i], nst, nlen, thresh ) ; 109 | 110 | if ( inode->child[i] != NULL ) { 111 | if ( inode->child[i]->getType() == INTERNAL ) { 112 | simple = 0 ; 113 | } 114 | else if ( inode->child[i]->getType() == LEAF ) { // sum child leaf QEFs 115 | LeafNode* lnode = (LeafNode *) inode->child[i] ; 116 | ht = lnode->height ; 117 | 118 | for ( int j = 0 ; j < 6 ; j ++ ) 119 | ata[j] += lnode->ata[j] ; 120 | 121 | for ( int j = 0 ; j < 3 ; j ++ ) { 122 | atb[j] += lnode->atb[j] ; 123 | pt[j] += lnode->mp[j] ; 124 | } 125 | if ( lnode->mp[0] == 0 ) 126 | printf("%f %f %f, Height: %d\n", lnode->mp[0], lnode->mp[1], lnode->mp[2], ht) ; 127 | 128 | btb += lnode->btb ; 129 | ec++ ; // QEF count (?) 130 | 131 | midsign = lnode->getSign( 7 - i ) ; 132 | signs[i] = lnode->getSign( i ) ; 133 | } 134 | else { // pseudoleaf 135 | assert( inode->child[i]->getType() == PSEUDOLEAF ); 136 | PseudoLeafNode* pnode = (PseudoLeafNode *) inode->child[i]; 137 | ht = pnode->height ; 138 | 139 | for ( int j = 0 ; j < 6 ; j ++ ) 140 | ata[j] += pnode->ata[j] ; 141 | 142 | for ( int j = 0 ; j < 3 ; j ++ ) { 143 | atb[j] += pnode->atb[j] ; 144 | pt[j] += pnode->mp[j] ; 145 | } 146 | btb += pnode->btb ; 147 | ec ++ ; 148 | 149 | midsign = pnode->getSign( 7 - i ) ; 150 | signs[i] = pnode->getSign( i ) ; 151 | } 152 | } 153 | } // all QEFs summed 154 | 155 | if ( simple ) { // one or more child INTERNAL (?) 156 | if ( ec == 0 ) { // no QEFs found/summed above ( all childs INTERNAL ?) 157 | //printf("deleting INTERNAL node because all children INTERNAL\n"); 158 | delete node; 159 | return NULL; 160 | } 161 | else { 162 | pt[0] = pt[0] / ec; // average of summed points 163 | pt[1] = pt[1] / ec; 164 | pt[2] = pt[2] / ec; 165 | //if ( pt[0] < st[0] || pt[1] < st[1] || pt[2] < st[2] || 166 | // pt[0] > st[0] + len || pt[1] > st[1] + len || pt[2] > st[2] + len ) 167 | //{ // pt outside node cube 168 | //printf("Out! %f %f %f, Box: (%d %d %d) Len: %d ec: %d\n", pt[0], pt[1], pt[2], st[0],st[1],st[2],len,ec) ; 169 | //} 170 | 171 | unsigned char sg = 0 ; 172 | for ( int i = 0 ; i < 8 ; i ++ ) { 173 | if ( signs[i] == 1 ) 174 | sg |= ( 1 << i ) ; 175 | else if ( signs[i] == -1 ) { // Undetermined, use center sign instead 176 | if ( midsign == 1 ) 177 | sg |= ( 1 << i ) ; 178 | else if ( midsign == -1 ) 179 | printf("Wrong!"); 180 | } 181 | } 182 | 183 | // Solve QEF for parent node 184 | float mat[10]; 185 | BoundingBoxf* box = new BoundingBoxf(); 186 | box->begin.x = (float) st[0] ; 187 | box->begin.y = (float) st[1] ; 188 | box->begin.z = (float) st[2] ; 189 | box->end.x = (float) st[0] + len ; 190 | box->end.y = (float) st[1] + len ; 191 | box->end.z = (float) st[2] + len ; 192 | // pt is the average of child-nodes 193 | // mp is the new solution point 194 | float mp[3] = { 0, 0, 0 } ; 195 | float error = calcPoint( ata, atb, btb, pt, mp, box, mat ) ; 196 | #ifdef CLAMP 197 | if ( mp[0] < st[0] || mp[1] < st[1] || mp[2] < st[2] || // mp is outside boudning-box 198 | mp[0] > st[0] + len || mp[1] > st[1] + len || mp[2] > st[2] + len ) { 199 | mp[0] = pt[0] ; 200 | mp[1] = pt[1] ; 201 | mp[2] = pt[2] ; 202 | } 203 | #endif 204 | if ( error <= thresh ) { // if parent QEF solution is good enough 205 | PseudoLeafNode* pnode = new PseudoLeafNode( ht+1, sg, ata, atb, btb, mp ) ; 206 | delete inode ; 207 | return pnode ; 208 | } 209 | else { // QEF solution not good enough 210 | return node ; 211 | } 212 | } 213 | 214 | } else { // simple == 0 215 | return node ; 216 | } 217 | } else { // type != INTERNAL 218 | return node ; 219 | } 220 | } 221 | 222 | 223 | 224 | void Octree::readDCF( char* fname ) { 225 | FILE* fin = fopen( fname, "rb" ) ; 226 | if ( fin == NULL ) 227 | printf("Can not open file %s.\n", fname) ; 228 | 229 | // Process header 230 | char version[10] ; 231 | fread( version, sizeof( char ), 10, fin ) ; 232 | if ( strcmp( version, "multisign" ) != 0 ) { 233 | printf("Wrong DCF version.\n") ; 234 | exit(0) ; 235 | } 236 | 237 | fread( &(this->dimen), sizeof( int ), 1, fin ) ; 238 | fread( &(this->dimen), sizeof( int ), 1, fin ) ; 239 | fread( &(this->dimen), sizeof( int ), 1, fin ) ; 240 | this->maxDepth = 0 ; 241 | int temp = 1 ; 242 | while ( temp < this->dimen ) { 243 | maxDepth ++ ; 244 | temp <<= 1 ; 245 | } 246 | printf(" dimen: %d maxDepth: %d\n", this->dimen, maxDepth ) ; 247 | 248 | // Recursive reader 249 | int st[3] = {0, 0, 0} ; 250 | this->root = readDCF( fin, st, dimen, maxDepth ) ; 251 | int nodecount[3]; 252 | countNodes( nodecount ); 253 | std::cout << " Read nodes from file: Internal " << nodecount[0] << "\tPseudo " << nodecount[1] << "\tLeaf " << nodecount[2] << "\n"; 254 | 255 | // optional octree simplification 256 | if (simplify_threshold > 0 ) { 257 | std::cout << "Simplifying with threshold " << simplify_threshold << "\n"; 258 | int nodecount1[3],nodecount2[3]; 259 | countNodes( nodecount1 ); 260 | std::cout << " Before simplify: Internal " << nodecount1[0] << "\tPseudo " << nodecount1[1] << "\tLeaf " << nodecount1[2] << "\n"; 261 | simplify( simplify_threshold ); 262 | countNodes( nodecount2 ); 263 | std::cout << " After simplify: Internal " << nodecount2[0] << "\tPseudo " << nodecount2[1] << "\tLeaf " << nodecount2[2] << "\n"; 264 | std::cout << " Nodecount I+P+L reduced from " << nodecount1[0]+nodecount1[1]+nodecount1[2] << " to " << nodecount2[0]+nodecount2[1]+nodecount2[2] << "\n"; 265 | } 266 | printf("Done reading.\n") ; 267 | fclose( fin ) ; 268 | } 269 | 270 | // only InternalNode and LeafNode returned by this function 271 | // st cube corner (x,y,z) 272 | // len cube side length 273 | // ht node depth (root has 0, leaf has maxDepth) 274 | // 275 | // recursive reader 276 | OctreeNode* Octree::readDCF( FILE* fin, int st[3], int len, int height ) { 277 | OctreeNode* rvalue = NULL ; 278 | 279 | int type ; 280 | fread( &type, sizeof( int ), 1, fin ) ; // Get type 281 | //printf("%d %d (%02d, %02d, %02d) NodeType: %d\n", height, len, st[0], st[1], st[2], type); 282 | 283 | if ( type == 0 ) { // Internal node 284 | rvalue = new InternalNode() ; 285 | int child_len = len / 2 ; // len of child node is half that of parent 286 | int child_st[3] ; 287 | 288 | for ( int i = 0 ; i < 8 ; i ++ ) { // create eight child nodes 289 | child_st[0] = st[0] + vertMap[i][0] * child_len; // child st position 290 | child_st[1] = st[1] + vertMap[i][1] * child_len; 291 | child_st[2] = st[2] + vertMap[i][2] * child_len; 292 | ((InternalNode *)rvalue)->child[i] = readDCF( fin, child_st, child_len, height - 1 ) ; // height is one less than parent 293 | } 294 | return rvalue ; 295 | } 296 | 297 | else if ( type == 1 ) { // Empty node, 298 | short sg ; 299 | fread( &sg, sizeof( short ), 1, fin ) ; // signs not used?? 300 | assert( rvalue == NULL ); 301 | return rvalue ; 302 | } 303 | 304 | else if ( type == 2 ) { // Leaf node 305 | short rsg[8] ; 306 | fread( rsg, sizeof( short ), 8, fin ) ; 307 | unsigned char sg = 0 ; 308 | for ( int i = 0 ; i < 8 ; i ++ ) { // set signs 309 | if ( rsg[i] != 0 ) 310 | sg |= ( 1 << i ) ; 311 | } 312 | 313 | // intersections and normals 314 | float inters[12][3], norms[12][3] ; 315 | int numinters = 0; 316 | for ( int i = 0 ; i < 12 ; i ++ ) { // potentially there are 12 intersections, one for each edge of the cube 317 | int num = 0; 318 | fread( &num, sizeof( int ), 1, fin ) ; 319 | //if ( num > 0 ) { 320 | for ( int j = 0 ; j < num ; j ++ ) { 321 | float off ; 322 | fread( &off, sizeof( float ), 1, fin ) ; 323 | fread( norms[numinters], sizeof( float ), 3, fin ) ; // normals 324 | 325 | int dir = i / 4 ; 326 | int base = edgevmap[ i ][ 0 ] ; 327 | inters[numinters][0] = st[0] + vertMap[base][0] * len ; 328 | inters[numinters][1] = st[1] + vertMap[base][1] * len ; 329 | inters[numinters][2] = st[2] + vertMap[base][2] * len ; 330 | inters[numinters][dir] += off ; 331 | numinters ++ ; 332 | } 333 | //} 334 | } 335 | 336 | if ( numinters > 0 ) 337 | rvalue = new LeafNode( height, sg, st, len, numinters, inters, norms ) ; 338 | else 339 | rvalue = NULL ; 340 | 341 | return rvalue ; 342 | } 343 | else { 344 | printf("Wrong! Node Type: %d\n", type); 345 | exit(-1); 346 | } 347 | } 348 | 349 | // no-intersections algorithm 350 | // fname is the PLY output file 351 | void Octree::genContourNoInter2( char* fname ) { 352 | int numTris = 0 ; 353 | int numVertices = 0 ; 354 | IndexedTriangleList* tlist = new IndexedTriangleList(); 355 | VertexList* vlist = new VertexList(); 356 | tlist->next = NULL ; 357 | vlist->next = NULL ; 358 | 359 | founds = 0 ; 360 | news = 0 ; 361 | 362 | // generate triangles 363 | faceVerts = 0 ; 364 | edgeVerts = 0 ; 365 | HashMap* hash = new HashMap(); 366 | int st[3] = {0,0,0}; 367 | printf("Processing contour...\n") ; 368 | 369 | clock_t start = clock( ) ; 370 | // one cellProc call to root processes entire tree 371 | cellProcContourNoInter2( root, st, dimen, hash, tlist, numTris, vlist, numVertices ) ; 372 | clock_t finish = clock( ) ; 373 | printf("Time used: %f seconds.\n", (float) (finish - start) / (float) CLOCKS_PER_SEC ) ; 374 | 375 | printf("Face vertices: %d Edge vertices: %d\n", faceVerts, edgeVerts ) ; 376 | printf("New hash entries: %d. Found times: %d\n", news, founds) ; 377 | 378 | // Finally, turn into PLY 379 | FILE* fout = fopen ( fname, "wb" ) ; 380 | printf("Vertices counted: %d Triangles counted: %d \n", numVertices, numTris ) ; 381 | PLYWriter::writeHeader( fout, numVertices, numTris ) ; 382 | 383 | VertexList* v = vlist->next ; 384 | while ( v != NULL ) { 385 | PLYWriter::writeVertex( fout, v->vt ) ; 386 | v = v->next ; 387 | } 388 | 389 | IndexedTriangleList* t = tlist->next ; 390 | for ( int i = 0 ; i < numTris ; i ++ ) { 391 | int inds[] = {numVertices - 1 - t->vt[0], numVertices - 1 - t->vt[1], numVertices - 1 - t->vt[2]} ; 392 | PLYWriter::writeFace( fout, 3, inds ) ; 393 | t = t->next ; 394 | } 395 | 396 | fclose( fout ) ; 397 | 398 | // Clear up 399 | delete hash ; 400 | v = vlist ; 401 | while ( v != NULL ) { 402 | vlist = v->next ; 403 | delete v ; 404 | v = vlist ; 405 | } 406 | t = tlist ; 407 | while ( t != NULL ) { 408 | tlist = t->next ; 409 | delete t ; 410 | t = tlist ; 411 | } 412 | } 413 | 414 | 415 | // original algorithm 416 | // may produce intersecting polygons? 417 | void Octree::genContour( char* fname ) { 418 | int numTris = 0 ; 419 | int numVertices = 0 ; 420 | 421 | FILE* fout = fopen ( fname, "wb" ) ; 422 | cellProcCount ( root, numVertices, numTris ) ; 423 | printf("numVertices: %d numTriangles: %d \n", numVertices, numTris ) ; 424 | PLYWriter::writeHeader( fout, numVertices, numTris ) ; 425 | int offset = 0; // start of vertex index 426 | 427 | clock_t start = clock(); 428 | generateVertexIndex( root, offset, fout ); // write vertices to file, populate node->index 429 | printf("Wrote %d vertices to file\n", offset ) ; 430 | 431 | actualTris = 0 ; 432 | cellProcContour( this->root, fout ) ; // a single call to root runs algorithm on entire tree 433 | clock_t finish = clock(); 434 | printf("Time used: %f seconds.\n", (float) (finish - start) / (float) CLOCKS_PER_SEC ) ; 435 | printf("Actual triangles written: %d\n", actualTris ) ; 436 | fclose( fout ) ; 437 | } 438 | 439 | // this writes out octree vertices to the PLY file 440 | // each vertex gets an index, which is stored in node->index 441 | void Octree::generateVertexIndex( OctreeNode* node, int& offset, FILE* fout ) { 442 | NodeType type = node->getType() ; 443 | 444 | if ( type == INTERNAL ) { // Internal node, recurse into tree 445 | InternalNode* inode = ( (InternalNode* ) node ) ; 446 | for ( int i = 0 ; i < 8 ; i ++ ) { 447 | if ( inode->child[i] != NULL ) 448 | generateVertexIndex( inode->child[i], offset, fout ) ; 449 | } 450 | } 451 | else if ( type == LEAF ) { // Leaf node 452 | LeafNode* lnode = ((LeafNode *) node) ; 453 | PLYWriter::writeVertex( fout, lnode->mp ) ; // write out mp 454 | lnode->index = offset; 455 | offset++; 456 | } 457 | else if ( type == PSEUDOLEAF ) { // Pseudo leaf node 458 | PseudoLeafNode* pnode = ((PseudoLeafNode *) node) ; 459 | PLYWriter::writeVertex( fout, pnode->mp ) ; // write out mp 460 | pnode->index = offset; 461 | offset++; 462 | } 463 | } 464 | 465 | // cellProcContour( this->root ) is the entry-point to the entire algorithm 466 | void Octree::cellProcContour( OctreeNode* node, FILE* fout ) { 467 | if ( node == NULL ) 468 | return ; 469 | 470 | int type = node->getType() ; 471 | 472 | if ( type == INTERNAL ) { // internal node 473 | InternalNode* inode = (( InternalNode * ) node ); 474 | for ( int i = 0 ; i < 8 ; i ++ ) // 8 Cell calls on children 475 | cellProcContour( inode->child[ i ], fout ); 476 | 477 | for ( int i = 0 ; i < 12 ; i ++ ) { // 12 face calls, faces between each child node 478 | int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] }; 479 | OctreeNode* fcd[2]; 480 | fcd[0] = inode->child[ c[0] ] ; 481 | fcd[1] = inode->child[ c[1] ] ; 482 | faceProcContour( fcd, cellProcFaceMask[ i ][ 2 ], fout ) ; 483 | } 484 | 485 | for ( int i = 0 ; i < 6 ; i ++ ) { // 6 edge calls 486 | int c[ 4 ] = { cellProcEdgeMask[ i ][ 0 ], cellProcEdgeMask[ i ][ 1 ], cellProcEdgeMask[ i ][ 2 ], cellProcEdgeMask[ i ][ 3 ] }; 487 | OctreeNode* ecd[4] ; 488 | for ( int j = 0 ; j < 4 ; j ++ ) 489 | ecd[j] = inode->child[ c[j] ] ; 490 | 491 | edgeProcContour( ecd, cellProcEdgeMask[ i ][ 4 ], fout ) ; 492 | } 493 | } 494 | }; 495 | 496 | // node[2] are the two nodes that share a face 497 | // dir comes from cellProcFaceMask[i][2] where i=0..11 498 | void Octree::faceProcContour ( OctreeNode* node[2], int dir, FILE* fout ) { 499 | // printf("I am at a face! %d\n", dir ) ; 500 | if ( ! ( node[0] && node[1] ) ) { 501 | // printf("I am none.\n") ; 502 | return ; 503 | } 504 | 505 | NodeType type[2] = { node[0]->getType(), node[1]->getType() } ; 506 | 507 | if ( type[0] == INTERNAL || type[1] == INTERNAL ) { // both nodes internal 508 | // 4 face calls 509 | OctreeNode* fcd[2] ; 510 | for ( int i = 0 ; i < 4 ; i ++ ) { 511 | int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] }; 512 | for ( int j = 0 ; j < 2 ; j ++ ) { 513 | if ( type[j] > 0 ) 514 | fcd[j] = node[j]; 515 | else 516 | fcd[j] = ((InternalNode *) node[ j ] )->child[ c[j] ]; 517 | } 518 | faceProcContour( fcd, faceProcFaceMask[ dir ][ i ][ 2 ], fout ) ; 519 | } 520 | 521 | // 4 edge calls 522 | int orders[2][4] = {{ 0, 0, 1, 1 }, { 0, 1, 0, 1 }} ; 523 | OctreeNode* ecd[4] ; 524 | 525 | for ( int i = 0 ; i < 4 ; i ++ ) { 526 | int c[4] = { faceProcEdgeMask[ dir ][ i ][ 1 ], faceProcEdgeMask[ dir ][ i ][ 2 ], 527 | faceProcEdgeMask[ dir ][ i ][ 3 ], faceProcEdgeMask[ dir ][ i ][ 4 ] }; 528 | int* order = orders[ faceProcEdgeMask[ dir ][ i ][ 0 ] ] ; 529 | 530 | for ( int j = 0 ; j < 4 ; j ++ ) { 531 | if ( type[order[j]] > 0 ) 532 | ecd[j] = node[order[j]] ; 533 | else 534 | ecd[j] = ( (InternalNode *) node[ order[ j ] ] )->child[ c[j] ] ; 535 | } 536 | edgeProcContour( ecd, faceProcEdgeMask[ dir ][ i ][ 5 ], fout ) ; 537 | } 538 | // printf("I am done.\n") ; 539 | } 540 | else { 541 | // printf("I don't have any children.\n") ; 542 | } 543 | }; 544 | 545 | // a common edge between four nodes in node[4] 546 | // "dir" comes from cellProcEdgeMask 547 | void Octree::edgeProcContour ( OctreeNode* node[4], int dir, FILE* fout ) { 548 | if ( ! ( node[0] && node[1] && node[2] && node[3] ) ) 549 | return; 550 | 551 | NodeType type[4] = { node[0]->getType(), node[1]->getType(), node[2]->getType(), node[3]->getType() } ; 552 | 553 | if ( type[0] != INTERNAL && type[1] != INTERNAL && type[2] != INTERNAL && type[3] != INTERNAL ) { 554 | processEdgeWrite( node, dir, fout ) ; // a face (quad?) is output 555 | } else { 556 | // 2 edge calls 557 | OctreeNode* ecd[4] ; 558 | for ( int i = 0 ; i < 2 ; i ++ ) { 559 | int c[ 4 ] = { edgeProcEdgeMask[ dir ][ i ][ 0 ], 560 | edgeProcEdgeMask[ dir ][ i ][ 1 ], 561 | edgeProcEdgeMask[ dir ][ i ][ 2 ], 562 | edgeProcEdgeMask[ dir ][ i ][ 3 ] } ; 563 | 564 | for ( int j = 0 ; j < 4 ; j ++ ) { 565 | if ( type[j] > 0 ) 566 | ecd[j] = node[j] ; 567 | else 568 | ecd[j] = ((InternalNode *) node[j])->child[ c[j] ] ; 569 | } 570 | 571 | edgeProcContour( ecd, edgeProcEdgeMask[ dir ][ i ][ 4 ], fout ) ; 572 | } 573 | 574 | } 575 | }; 576 | 577 | // this writes out a face to the PLY file 578 | // vertices already exist in the file 579 | // so here we write out topology only, i.e. sets of indices that form a face 580 | void Octree::processEdgeWrite ( OctreeNode* node[4], int dir, FILE* fout ) { 581 | // Get minimal cell 582 | int type, ht, minht = this->maxDepth+1, mini = -1 ; 583 | int ind[4], sc[4], flip[4] = {0,0,0,0} ; 584 | int flip2; 585 | for ( int i = 0 ; i < 4 ; i ++ ) { 586 | if ( node[i]->getType() == LEAF ) { 587 | LeafNode* lnode = ((LeafNode *) node[i]) ; 588 | int ed = processEdgeMask[dir][i] ; 589 | int c1 = edgevmap[ed][0] ; 590 | int c2 = edgevmap[ed][1] ; 591 | 592 | if ( lnode->height < minht ) { 593 | minht = lnode->height ; 594 | mini = i ; 595 | if ( lnode->getSign(c1) > 0 ) 596 | flip2 = 1 ; 597 | else 598 | flip2 = 0 ; 599 | } 600 | ind[i] = lnode->index ; 601 | 602 | if ( lnode->getSign( c1 ) == lnode->getSign( c2 ) ) 603 | sc[ i ] = 0 ; 604 | else 605 | sc[ i ] = 1 ; 606 | 607 | // if ( lnode->getSign(c1) > 0 ) 608 | // { 609 | // flip[ i ] = 1 ; 610 | // } 611 | // } 612 | } else { 613 | assert( node[i]->getType() == PSEUDOLEAF ); 614 | PseudoLeafNode* pnode = ((PseudoLeafNode *) node[i]) ; 615 | 616 | int ed = processEdgeMask[dir][i] ; 617 | int c1 = edgevmap[ed][0] ; 618 | int c2 = edgevmap[ed][1] ; 619 | 620 | if ( pnode->height < minht ) { 621 | minht = pnode->height; 622 | mini = i; 623 | if ( pnode->getSign(c1) > 0 ) 624 | flip2 = 1 ; 625 | else 626 | flip2 = 0 ; 627 | } 628 | ind[i] = pnode->index ; 629 | 630 | if ( pnode->getSign( c1 ) == pnode->getSign( c2 ) ) 631 | sc[ i ] = 0 ; 632 | else 633 | sc[ i ] = 1 ; 634 | 635 | // if ( pnode->getSign(c1) > 0 ) 636 | // { 637 | // flip[ i ] = 1 ; 638 | // flip2 = 1 ; 639 | // } 640 | // } 641 | } 642 | 643 | } 644 | 645 | if ( sc[ mini ] == 1 ) { // condition for any triangle output? 646 | if ( flip2 == 0 ) { 647 | actualTris ++ ; 648 | if ( ind[0] == ind[1] ) { // two indices same, so output triangle 649 | int tind[] = { ind[0], ind[3], ind[2] } ; 650 | PLYWriter::writeFace( fout, 3, tind ) ; 651 | } else if ( ind[1] == ind[3] ) { 652 | int tind[] = { ind[0], ind[1], ind[2] } ; 653 | PLYWriter::writeFace( fout, 3, tind ) ; 654 | } else if ( ind[3] == ind[2] ) { 655 | int tind[] = { ind[0], ind[1], ind[3] } ; 656 | PLYWriter::writeFace( fout, 3, tind ) ; 657 | } else if ( ind[2] == ind[0] ) { 658 | int tind[] = { ind[1], ind[3], ind[2] } ; 659 | PLYWriter::writeFace( fout, 3, tind ) ; 660 | } else { // all indices unique, so output a quad by outputting two triangles 661 | int tind1[] = { ind[0], ind[1], ind[3] } ; 662 | PLYWriter::writeFace( fout, 3, tind1 ) ; 663 | int tind2[] = { ind[0], ind[3], ind[2] } ; 664 | PLYWriter::writeFace( fout, 3, tind2 ) ; 665 | actualTris ++ ; // two triangles, so add one here also 666 | } 667 | } else { 668 | actualTris ++ ; 669 | if ( ind[0] == ind[1] ) { 670 | int tind[] = { ind[0], ind[2], ind[3] } ; 671 | PLYWriter::writeFace( fout, 3, tind ) ; 672 | } else if ( ind[1] == ind[3] ) { 673 | int tind[] = { ind[0], ind[2], ind[1] } ; 674 | PLYWriter::writeFace( fout, 3, tind ) ; 675 | } else if ( ind[3] == ind[2] ) { 676 | int tind[] = { ind[0], ind[3], ind[1] } ; 677 | PLYWriter::writeFace( fout, 3, tind ) ; 678 | } else if ( ind[2] == ind[0] ) { 679 | int tind[] = { ind[1], ind[2], ind[3] } ; 680 | PLYWriter::writeFace( fout, 3, tind ) ; 681 | } else { 682 | int tind1[] = { ind[0], ind[3], ind[1] } ; 683 | PLYWriter::writeFace( fout, 3, tind1 ) ; 684 | int tind2[] = { ind[0], ind[2], ind[3] } ; 685 | PLYWriter::writeFace( fout, 3, tind2 ) ; 686 | actualTris++; // two triangles, so add one here also 687 | } 688 | } 689 | } 690 | }; 691 | 692 | 693 | // used initially for counting number of vertices 694 | // genContour calls cellProcCount(root) and this is a recursive function 695 | void Octree::cellProcCount( OctreeNode* node, int& nverts, int& nfaces ) { 696 | if ( node == NULL ) 697 | return ; 698 | 699 | int type = node->getType() ; 700 | 701 | if (type != INTERNAL) 702 | nverts ++ ; // !internal, so leaf or pseudoleaf node produces a vertex 703 | else { 704 | // recurse into tree 705 | InternalNode* inode = (( InternalNode * ) node ) ; 706 | 707 | for ( int i = 0 ; i < 8 ; i ++ ) // 8 recursive calls to child nodes 708 | cellProcCount( inode->child[ i ], nverts, nfaces ) ; 709 | 710 | OctreeNode* fcd[2]; 711 | for ( int i = 0 ; i < 12 ; i ++ ) { // 12 face calls. among the 8 child-nodes there are 12 common faces 712 | int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] }; 713 | fcd[0] = inode->child[ c[0] ] ; 714 | fcd[1] = inode->child[ c[1] ] ; 715 | faceProcCount( fcd, cellProcFaceMask[ i ][ 2 ], nverts, nfaces ); // 2nd argument is "dir" 716 | } 717 | 718 | OctreeNode* ecd[4] ; 719 | for ( int i = 0 ; i < 6 ; i ++ ) { // 6 edge calls 720 | int c[ 4 ] = { cellProcEdgeMask[ i ][ 0 ], cellProcEdgeMask[ i ][ 1 ], cellProcEdgeMask[ i ][ 2 ], cellProcEdgeMask[ i ][ 3 ] }; 721 | for ( int j = 0 ; j < 4 ; j ++ ) 722 | ecd[j] = inode->child[ c[j] ] ; 723 | edgeProcCount( ecd, cellProcEdgeMask[ i ][ 4 ], nverts, nfaces ) ; 724 | } 725 | } 726 | }; 727 | 728 | void Octree::faceProcCount ( OctreeNode* node[2], int dir, int& nverts, int& nfaces ) { 729 | if ( ! ( node[0] && node[1] ) ) 730 | return ; 731 | 732 | int type[2] = { node[0]->getType(), node[1]->getType() } ; 733 | 734 | if ( type[0] == INTERNAL || type[1] == INTERNAL ) { 735 | OctreeNode* fcd[2] ; 736 | for ( int i = 0 ; i < 4 ; i ++ ) { // 4 face calls, recursive! 737 | int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] }; 738 | for ( int j = 0 ; j < 2 ; j ++ ) { 739 | if ( type[j] != INTERNAL ) 740 | fcd[j] = node[j] ; 741 | else 742 | fcd[j] = ((InternalNode *) node[ j ] )->child[ c[j] ] ; 743 | } 744 | faceProcCount( fcd, faceProcFaceMask[ dir ][ i ][ 2 ], nverts, nfaces ) ; 745 | } 746 | 747 | int orders[2][4] = {{ 0, 0, 1, 1 }, { 0, 1, 0, 1 }} ; 748 | OctreeNode* ecd[4] ; 749 | 750 | for ( int i = 0 ; i < 4 ; i ++ ) { // 4 edge calls 751 | int c[4] = { faceProcEdgeMask[ dir ][ i ][ 1 ], faceProcEdgeMask[ dir ][ i ][ 2 ], 752 | faceProcEdgeMask[ dir ][ i ][ 3 ], faceProcEdgeMask[ dir ][ i ][ 4 ] }; 753 | int* order = orders[ faceProcEdgeMask[ dir ][ i ][ 0 ] ] ; 754 | 755 | for ( int j = 0 ; j < 4 ; j ++ ) { 756 | if ( type[order[j]] != INTERNAL ) 757 | ecd[j] = node[order[j]] ; 758 | else 759 | ecd[j] = ( (InternalNode *) node[ order[ j ] ] )->child[ c[j] ] ; 760 | } 761 | 762 | edgeProcCount( ecd, faceProcEdgeMask[ dir ][ i ][ 5 ], nverts, nfaces ) ; 763 | } 764 | } 765 | }; 766 | 767 | void Octree::edgeProcCount ( OctreeNode* node[4], int dir, int& nverts, int& nfaces ) { 768 | if ( ! ( node[0] && node[1] && node[2] && node[3] ) ) 769 | return ; 770 | 771 | int type[4] = { node[0]->getType(), node[1]->getType(), node[2]->getType(), node[3]->getType() } ; 772 | if ( type[0] != INTERNAL && type[1] != INTERNAL && type[2] != INTERNAL && type[3] != INTERNAL ) 773 | processEdgeCount( node, dir, nverts, nfaces ) ; 774 | else { 775 | // 2 edge calls 776 | OctreeNode* ecd[4] ; 777 | for ( int i = 0 ; i < 2 ; i ++ ) { 778 | int c[ 4 ] = { edgeProcEdgeMask[ dir ][ i ][ 0 ], 779 | edgeProcEdgeMask[ dir ][ i ][ 1 ], 780 | edgeProcEdgeMask[ dir ][ i ][ 2 ], 781 | edgeProcEdgeMask[ dir ][ i ][ 3 ] } ; 782 | 783 | for ( int j = 0 ; j < 4 ; j ++ ) { 784 | if ( type[j] != INTERNAL ) 785 | ecd[j] = node[j] ; 786 | else 787 | ecd[j] = ((InternalNode *) node[j])->child[ c[j] ] ; 788 | } 789 | edgeProcCount( ecd, edgeProcEdgeMask[ dir ][ i ][ 4 ], nverts, nfaces ) ; 790 | } 791 | } 792 | }; 793 | 794 | void Octree::processEdgeCount ( OctreeNode* node[4], int dir, int& nverts, int& nfaces ) { 795 | // Get minimal cell 796 | int i, type, ht, minht = maxDepth+1, mini = -1 ; 797 | int ind[4], sc[4], flip[4] = {0,0,0,0} ; 798 | for ( i = 0 ; i < 4 ; i ++ ) { 799 | if ( node[i]->getType() == 1 ) { 800 | LeafNode* lnode = ((LeafNode *) node[i]) ; 801 | 802 | if ( lnode->height < minht ) { 803 | minht = lnode->height ; 804 | mini = i ; 805 | } 806 | ind[i] = lnode->index ; 807 | 808 | int ed = processEdgeMask[dir][i] ; 809 | int c1 = edgevmap[ed][0] ; 810 | int c2 = edgevmap[ed][1] ; 811 | 812 | if ( lnode->getSign( c1 ) == lnode->getSign( c2 ) ) { 813 | sc[ i ] = 0 ; 814 | } 815 | else { 816 | sc[ i ] = 1 ; 817 | if ( lnode->getSign(c1) > 0 ) 818 | flip[ i ] = 1 ; 819 | } 820 | } 821 | else { 822 | PseudoLeafNode* pnode = ((PseudoLeafNode *) node[i]) ; 823 | if ( pnode->height < minht ) { 824 | minht = pnode->height ; 825 | mini = i ; 826 | } 827 | ind[i] = pnode->index ; 828 | 829 | int ed = processEdgeMask[dir][i] ; 830 | int c1 = edgevmap[ed][0] ; 831 | int c2 = edgevmap[ed][1] ; 832 | 833 | if ( pnode->getSign( c1 ) == pnode->getSign( c2 ) ) { 834 | sc[ i ] = 0 ; 835 | } 836 | else { 837 | sc[ i ] = 1 ; 838 | if ( pnode->getSign(c1) > 0 ) 839 | flip[ i ] = 1 ; 840 | } 841 | } 842 | } 843 | 844 | if ( sc[ mini ] == 1 ) { 845 | nfaces ++ ; // triangle 846 | if ( node[0] != node[1] && node[1] != node[3] && node[3] != node[2] && node[2] != node[0] ) 847 | nfaces ++ ; // quad, so two triangles 848 | } 849 | 850 | }; 851 | 852 | /************************************************************************/ 853 | /* Start intersection free algorithm */ 854 | /************************************************************************/ 855 | 856 | 857 | 858 | int Octree::testFace( int st[3], int len, int dir, float v1[3], float v2[3] ) 859 | { 860 | #ifdef TESS_UNIFORM 861 | return 0 ; 862 | #endif 863 | 864 | #ifdef TESS_NONE 865 | return 1 ; 866 | #endif 867 | float vec[3] = { v2[0]-v1[0], v2[1]-v1[1], v2[2]-v1[2] } ; 868 | float ax1[3], ax2[3] ; 869 | float ed1[3]={0,0,0}, ed2[3] = {0,0,0}; 870 | ed1[(dir+1)%3]=1; 871 | ed2[(dir+2)%3]=1; 872 | 873 | Intersection::cross( ed1, vec, ax1 ) ; 874 | Intersection::cross( ed2, vec, ax2 ) ; 875 | 876 | Triangle* t1 = new Triangle ; 877 | Triangle* t2 = new Triangle ; 878 | 879 | for ( int i = 0 ; i < 3 ; i ++ ) 880 | { 881 | t1->vt[0][i] = v1[i] ; 882 | t1->vt[1][i] = v2[i] ; 883 | t1->vt[2][i] = v2[i] ; 884 | 885 | t2->vt[0][i] = st[i] ; 886 | t2->vt[1][i] = st[i] ; 887 | t2->vt[2][i] = st[i] ; 888 | } 889 | t2->vt[1][(dir+1)%3] += len ; 890 | t2->vt[2][(dir+2)%3] += len ; 891 | 892 | if ( Intersection::separating( ax1, t1, t2 ) || Intersection::separating( ax2, t1, t2 ) ) 893 | { 894 | faceVerts ++ ; 895 | /* 896 | printf("\n{{{%d, %d, %d},%d,%d},{{%f, %f, %f},{%f, %f, %f}}}\n", 897 | st[0],st[1], st[2], 898 | len, dir+1, 899 | v1[0], v1[1], v1[2], 900 | v2[0], v2[1], v2[2]) ; 901 | */ 902 | return 0 ; 903 | } 904 | else 905 | { 906 | return 1 ; 907 | } 908 | }; 909 | 910 | int Octree::testEdge( int st[3], int len, int dir, OctreeNode* node[4], float v[4][3] ) 911 | { 912 | #ifdef TESS_UNIFORM 913 | return 0 ; 914 | #endif 915 | 916 | #ifdef TESS_NONE 917 | return 1 ; 918 | #endif 919 | 920 | if ( node[0] == node[1] || node[1] == node[3] || node[3] == node[2] || node[2] == node[0] ) 921 | { 922 | // return 1 ; 923 | } 924 | 925 | float p1[3] ={st[0], st[1], st[2]}; 926 | float p2[3] ={st[0], st[1], st[2]}; 927 | p2[dir] += len ; 928 | 929 | int nbr[]={0,1,3,2,0} ; 930 | int nbr2[]={3,2,0,1,3} ; 931 | float nm[3], vec1[4][3], vec2[4][3] ; 932 | float d1, d2 ; 933 | 934 | for ( int i = 0 ; i < 4 ; i ++ ) 935 | { 936 | for ( int j = 0 ; j < 3 ; j ++ ) 937 | { 938 | vec1[i][j] = v[i][j] - p1[j] ; 939 | vec2[i][j] = v[i][j] - p2[j] ; 940 | } 941 | } 942 | 943 | #ifdef EDGE_TEST_CONVEXITY 944 | for ( i = 0 ; i < 4 ; i ++ ) 945 | { 946 | int a = nbr[i] ; 947 | int b = nbr[i+1] ; 948 | int c = nbr2[i] ; 949 | int d = nbr2[i+1] ; 950 | 951 | if ( node[a] == node[b] ) 952 | { 953 | continue ; 954 | } 955 | 956 | Intersection::cross( vec1[a], vec1[b], nm ) ; 957 | d1 = Intersection::dot( vec1[c], nm ) ; 958 | d2 = Intersection::dot( vec1[d], nm ) ; 959 | 960 | if ( d1 * d2 < 0 ) 961 | { 962 | /* 963 | printf("1\n{{{%f, %f, %f},{%f, %f, %f}},{{%f, %f, %f},{%f, %f, %f},{%f, %f, %f},{%f, %f, %f}}}\n", 964 | p1[0], p1[1], p1[2], 965 | p2[0], p2[1], p2[2], 966 | v[0][0], v[0][1], v[0][2], 967 | v[1][0], v[1][1], v[1][2], 968 | v[2][0], v[2][1], v[2][2], 969 | v[3][0], v[3][1], v[3][2]) ; 970 | */ 971 | return 0 ; 972 | } 973 | 974 | Intersection::cross( vec2[a], vec2[b], nm ) ; 975 | d1 = Intersection::dot( vec2[c], nm ) ; 976 | d2 = Intersection::dot( vec2[d], nm ) ; 977 | 978 | if ( d1 * d2 < 0 ) 979 | { 980 | /* 981 | printf("2\n{{{%f, %f, %f},{%f, %f, %f}},{{%f, %f, %f},{%f, %f, %f},{%f, %f, %f},{%f, %f, %f}}}\n", 982 | p1[0], p1[1], p1[2], 983 | p2[0], p2[1], p2[2], 984 | v[0][0], v[0][1], v[0][2], 985 | v[1][0], v[1][1], v[1][2], 986 | v[2][0], v[2][1], v[2][2], 987 | v[3][0], v[3][1], v[3][2]) ; 988 | */ 989 | return 0 ; 990 | } 991 | } 992 | #else 993 | #ifdef EDGE_TEST_FLIPDIAGONAL 994 | Triangle* t1 = new Triangle ; 995 | Triangle* t2 = new Triangle ; 996 | int tri[2][2][4] = {{{0,1,3,2},{3,2,0,1}},{{2,0,1,3},{1,3,2,0}}} ; 997 | for ( i = 0 ; i < 2 ; i ++ ) 998 | { 999 | int good = 1 ; 1000 | for ( int j = 0 ; j < 2 ; j ++ ) 1001 | { 1002 | // Top 1003 | for ( int k = 0 ; k < 3 ; k ++ ) 1004 | { 1005 | t1->vt[0][k] = v[tri[i][j][0]][k] ; 1006 | t1->vt[1][k] = v[tri[i][j][1]][k] ; 1007 | t1->vt[2][k] = v[tri[i][j][2]][k] ; 1008 | 1009 | t2->vt[0][k] = p1[k] ; 1010 | t2->vt[1][k] = v[tri[i][j][2]][k] ; 1011 | t2->vt[2][k] = v[tri[i][j][3]][k] ; 1012 | } 1013 | 1014 | if ( Intersection::testIntersection( t1, t2 ) ) 1015 | { 1016 | good = 0 ; 1017 | break ; 1018 | } 1019 | 1020 | // Bottom 1021 | for ( k = 0 ; k < 3 ; k ++ ) 1022 | { 1023 | t2->vt[0][k] = p2[k] ; 1024 | t2->vt[1][k] = v[tri[i][j][2]][k] ; 1025 | t2->vt[2][k] = v[tri[i][j][3]][k] ; 1026 | } 1027 | 1028 | if ( Intersection::testIntersection( t1, t2 ) ) 1029 | { 1030 | good = 0 ; 1031 | break ; 1032 | } 1033 | } 1034 | 1035 | if ( good ) 1036 | { 1037 | return (i+1) ; 1038 | } 1039 | } 1040 | return 0 ; 1041 | 1042 | #else 1043 | #ifdef EDGE_TEST_NEW 1044 | Triangle* t1 = new Triangle ; 1045 | int tri[2][2][4] = {{{0,1,3,2},{3,2,0,1}},{{2,0,1,3},{1,3,2,0}}} ; 1046 | for ( int i = 0 ; i < 2 ; i ++ ) 1047 | { 1048 | // For each triangulation 1049 | for ( int j = 0 ; j < 2 ; j ++ ) 1050 | { 1051 | // Starting with each triangle 1052 | int k ; 1053 | 1054 | // Check triangle and dual edge 1055 | float vec1[3], vec2[3], vec3[3], vec[3] ; 1056 | for ( k = 0 ; k < 3 ; k ++ ) 1057 | { 1058 | t1->vt[0][k] = v[tri[i][j][0]][k] ; 1059 | t1->vt[1][k] = v[tri[i][j][1]][k] ; 1060 | t1->vt[2][k] = v[tri[i][j][2]][k] ; 1061 | 1062 | vec1[k] = t1->vt[1][k] - t1->vt[0][k] ; 1063 | vec2[k] = t1->vt[2][k] - t1->vt[1][k] ; 1064 | } 1065 | 1066 | float axes[3] ; 1067 | Intersection::cross( vec1, vec2, axes ) ; 1068 | 1069 | if ( Intersection::separating( axes, t1, p1, p2 ) ) 1070 | { 1071 | continue ; 1072 | } 1073 | 1074 | // Check diagonal and the other triangle 1075 | for ( k = 0 ; k < 3 ; k ++ ) 1076 | { 1077 | t1->vt[0][k] = p1[k] ; 1078 | t1->vt[1][k] = p2[k] ; 1079 | t1->vt[2][k] = v[tri[i][j][3]][k] ; 1080 | 1081 | vec1[k] = t1->vt[1][k] - t1->vt[0][k] ; 1082 | vec2[k] = t1->vt[2][k] - t1->vt[1][k] ; 1083 | vec3[k] = t1->vt[0][k] - t1->vt[2][k] ; 1084 | 1085 | vec[k] = v[tri[i][j][2]][k] - v[tri[i][j][0]][k] ; 1086 | } 1087 | 1088 | float axes1[3], axes2[3], axes3[3] ; 1089 | Intersection::cross( vec1, vec, axes1 ) ; 1090 | Intersection::cross( vec2, vec, axes2 ) ; 1091 | Intersection::cross( vec3, vec, axes3 ) ; 1092 | 1093 | if ( Intersection::separating( axes1, t1, v[tri[i][j][0]], v[tri[i][j][2]] ) || 1094 | Intersection::separating( axes2, t1, v[tri[i][j][0]], v[tri[i][j][2]] ) || 1095 | Intersection::separating( axes3, t1, v[tri[i][j][0]], v[tri[i][j][2]] ) ) 1096 | { 1097 | continue ; 1098 | } 1099 | 1100 | return (i+1) ; 1101 | } 1102 | } 1103 | return 0 ; 1104 | 1105 | 1106 | #endif 1107 | 1108 | #endif 1109 | #endif 1110 | 1111 | return 1 ; 1112 | }; 1113 | 1114 | 1115 | void Octree::makeEdgeVertex( int st[3], int len, int dir, OctreeNode* node[4], float mp[4][3], float v[3] ) 1116 | { 1117 | int nlen = len / 2 ; 1118 | v[0] = st[0] ; 1119 | v[1] = st[1] ; 1120 | v[2] = st[2] ; 1121 | v[dir] += nlen ; 1122 | 1123 | //return ; 1124 | 1125 | // if ( this->hasQEF == 0 ) 1126 | // { 1127 | // return ; 1128 | // } 1129 | 1130 | 1131 | /* QEF based method 1132 | 1133 | int i, j ; 1134 | float ata[6] = { 0, 0, 0, 0, 0, 0 }; 1135 | float atb[3] = { 0, 0, 0 } ; 1136 | float btb = 0 ; 1137 | 1138 | // Gather QEF 1139 | for ( j = 0 ; j < 4 ; j ++ ) 1140 | { 1141 | if ( node[j]->getType() == 1 ) 1142 | { 1143 | LeafNode* lnode = ((LeafNode *) node[j]) ; 1144 | for ( i = 0 ; i < 6 ; i ++ ) 1145 | { 1146 | ata[i] += lnode->ata[i] ; 1147 | } 1148 | for ( i = 0 ; i < 3 ; i ++ ) 1149 | { 1150 | atb[i] += lnode->atb[i] ; 1151 | } 1152 | btb += lnode->btb ; 1153 | } 1154 | else 1155 | { 1156 | PseudoLeafNode* lnode = ((PseudoLeafNode *) node[j]) ; 1157 | for ( i = 0 ; i < 6 ; i ++ ) 1158 | { 1159 | ata[i] += lnode->ata[i] ; 1160 | } 1161 | for ( i = 0 ; i < 3 ; i ++ ) 1162 | { 1163 | atb[i] += lnode->atb[i] ; 1164 | } 1165 | btb += lnode->btb ; 1166 | } 1167 | } 1168 | 1169 | // Find coefficient A and b 1170 | float A, b ; 1171 | switch ( dir ) 1172 | { 1173 | case 0 : 1174 | A = ata[ 0 ] ; 1175 | b = atb[ 0 ] - ata[ 1 ] * st[ 1 ] - ata[ 2 ] * st[ 2 ] ; 1176 | break ; 1177 | case 1 : 1178 | A = ata[ 3 ] ; 1179 | b = atb[ 1 ] - ata[ 1 ] * st[ 0 ] - ata[ 4 ] * st[ 2 ] ; 1180 | break ; 1181 | case 2 : 1182 | A = ata[ 5 ] ; 1183 | b = atb[ 2 ] - ata[ 2 ] * st[ 0 ] - ata[ 4 ] * st[ 1 ] ; 1184 | break ; 1185 | } 1186 | 1187 | if ( A == 0 ) 1188 | { 1189 | printf("A is zero!\n") ; 1190 | return ; 1191 | } 1192 | else 1193 | { 1194 | v[ dir ] = b / A ; 1195 | if ( v[ dir ] < st[ dir ] ) 1196 | { 1197 | v[ dir ] = st[ dir ] ; 1198 | } 1199 | else if ( v[ dir ] > st[ dir ] + len) 1200 | { 1201 | v[ dir ] = st[ dir ] + len ; 1202 | } 1203 | } 1204 | */ 1205 | 1206 | 1207 | /* Barycentric approach */ 1208 | float pt[4][2], pv[4], x[2] ; 1209 | int dir2 = ( dir + 1 ) % 3 ; 1210 | int dir3 = ( dir2 + 1 ) % 3 ; 1211 | int seq[] = {0,1,3,2} ; 1212 | float epsilon = 0.000001f; 1213 | 1214 | for ( int i = 0 ; i < 4 ; i ++ ) 1215 | { 1216 | pt[ i ][ 0 ] = mp[ seq[i] ][ dir2 ] ; 1217 | pt[ i ][ 1 ] = mp[ seq[i] ][ dir3 ] ; 1218 | pv[ i ] = mp[ seq[i] ][ dir ] ; 1219 | } 1220 | x[ 0 ] = st[ dir2 ] ; 1221 | x[ 1 ] = st[ dir3 ] ; 1222 | 1223 | // Compute mean-value interpolation 1224 | 1225 | float vec[4][2], d[4] ; 1226 | for ( int i = 0 ; i < 4 ; i ++ ) 1227 | { 1228 | vec[i][0] = pt[i][0] - x[0] ; 1229 | vec[i][1] = pt[i][1] - x[1] ; 1230 | 1231 | d[i] = sqrt( vec[i][0] * vec[i][0] + vec[i][1] * vec[i][1] ); 1232 | 1233 | if ( d[i] < epsilon ) 1234 | { 1235 | 1236 | v[ dir ] = pv[ i ] ; 1237 | if ( v[dir] < st[dir] ) 1238 | { 1239 | v[dir] = st[dir] ; 1240 | } 1241 | else if ( v[dir] > st[dir] + len ) 1242 | { 1243 | v[dir] = st[dir] + len ; 1244 | } 1245 | 1246 | return ; 1247 | } 1248 | } 1249 | 1250 | float w[4]={0,0,0,0}, totw = 0 ; 1251 | for ( int i = 0 ; i < 4 ; i ++ ) 1252 | { 1253 | int i2 = ( i + 1 ) % 4 ; 1254 | float sine = ( vec[i][0] * vec[i2][1] - vec[i][1] * vec[i2][0] ) / ( d[i] * d[i2] ) ; 1255 | float cosine = ( vec[i][0] * vec[i2][0] + vec[i][1] * vec[i2][1] ) / ( d[i] * d[i2] ) ; 1256 | 1257 | if ( fabs(cosine + 1) < epsilon ) 1258 | { 1259 | v[ dir ] = ( pv[ i ] * d[i2] + pv[ i2 ] * d[i] ) / (d[i] + d[i2]); 1260 | 1261 | if ( v[dir] < st[dir] ) 1262 | { 1263 | v[dir] = st[dir] ; 1264 | } 1265 | else if ( v[dir] > st[dir] + len ) 1266 | { 1267 | v[dir] = st[dir] + len ; 1268 | } 1269 | 1270 | return ; 1271 | } 1272 | 1273 | float tan2 = sine / ( 1 + cosine ) ; 1274 | 1275 | w[i] += ( tan2 / d[i] ) ; 1276 | w[i2] += ( tan2 / d[i2] ) ; 1277 | 1278 | totw += ( tan2 / d[i] ) ; 1279 | totw += ( tan2 / d[i2] ) ; 1280 | } 1281 | 1282 | v[dir] = 0 ; 1283 | for ( int i = 0 ; i < 4 ; i ++ ) 1284 | { 1285 | v[dir] += ( w[i] * pv[ i ] / totw ); 1286 | } 1287 | /**/ 1288 | if ( v[dir] < st[dir] ) 1289 | { 1290 | v[dir] = st[dir] ; 1291 | } 1292 | else if ( v[dir] > st[dir] + len ) 1293 | { 1294 | v[dir] = st[dir] + len ; 1295 | } 1296 | 1297 | }; 1298 | 1299 | 1300 | void Octree::cellProcContourNoInter2( OctreeNode* node, int st[3], int len, 1301 | HashMap* hash, IndexedTriangleList* tlist, int& numTris, VertexList* vlist, int& numVerts ) 1302 | { 1303 | // printf("I am at a cell! %d %d %d, %d \n", st[0], st[1], st[2], len ) ; 1304 | if ( node == NULL ) 1305 | { 1306 | // printf("Empty cell.\n") ; 1307 | return ; 1308 | } 1309 | 1310 | int type = node->getType() ; 1311 | 1312 | if ( type == 0 ) 1313 | { 1314 | InternalNode* inode = (( InternalNode * ) node ) ; 1315 | 1316 | // 8 Cell calls 1317 | // printf("Process cell calls!\n") ; 1318 | int nlen = len / 2 ; 1319 | int nst[3] ; 1320 | 1321 | for ( int i = 0 ; i < 8 ; i ++ ) 1322 | { 1323 | // printf("Cell %d..\n", i) ; 1324 | nst[0] = st[0] + vertMap[i][0] * nlen ; 1325 | nst[1] = st[1] + vertMap[i][1] * nlen ; 1326 | nst[2] = st[2] + vertMap[i][2] * nlen ; 1327 | cellProcContourNoInter2( inode->child[ i ], nst, nlen, hash, tlist, numTris, vlist, numVerts ) ; 1328 | // printf("Return from %d %d %d, %d \n", nst[0], nst[1], nst[2], nlen ) ; 1329 | } 1330 | // printf("I am done with cells!\n") ; 1331 | 1332 | // 12 face calls 1333 | // printf("Process face calls!\n") ; 1334 | OctreeNode* fcd[2] ; 1335 | int dirCell2[3][4][3] = { 1336 | {{0,-1,-1},{0,-1,0},{0,0,-1},{0,0,0}}, 1337 | {{-1,0,-1},{0,0,-1},{-1,0,0},{0,0,0}}, 1338 | {{-1,-1,0},{-1,0,0},{0,-1,0},{0,0,0}}}; 1339 | for ( int i = 0 ; i < 3 ; i ++ ) 1340 | for ( int j = 0 ; j < 4 ; j ++ ) 1341 | { 1342 | nst[0] = st[0] + nlen + dirCell2[i][j][0] * nlen ; 1343 | nst[1] = st[1] + nlen + dirCell2[i][j][1] * nlen ; 1344 | nst[2] = st[2] + nlen + dirCell2[i][j][2] * nlen ; 1345 | 1346 | int ed = i * 4 + j ; 1347 | int c[ 2 ] = { cellProcFaceMask[ ed ][ 0 ], cellProcFaceMask[ ed ][ 1 ] }; 1348 | 1349 | fcd[0] = inode->child[ c[0] ] ; 1350 | fcd[1] = inode->child[ c[1] ] ; 1351 | 1352 | faceProcContourNoInter2( fcd, nst, nlen, cellProcFaceMask[ ed ][ 2 ], hash, tlist, numTris, vlist, numVerts ) ; 1353 | } 1354 | // printf("I am done with faces!\n") ; 1355 | 1356 | // 6 edge calls 1357 | // printf("Process edge calls!\n") ; 1358 | OctreeNode* ecd[4] ; 1359 | for ( int i = 0 ; i < 6 ; i ++ ) 1360 | { 1361 | int c[ 4 ] = { cellProcEdgeMask[ i ][ 0 ], cellProcEdgeMask[ i ][ 1 ], cellProcEdgeMask[ i ][ 2 ], cellProcEdgeMask[ i ][ 3 ] }; 1362 | 1363 | for ( int j = 0 ; j < 4 ; j ++ ) 1364 | { 1365 | ecd[j] = inode->child[ c[j] ] ; 1366 | } 1367 | 1368 | int dir = cellProcEdgeMask[ i ][ 4 ] ; 1369 | nst[0] = st[0] + nlen ; 1370 | nst[1] = st[1] + nlen ; 1371 | nst[2] = st[2] + nlen ; 1372 | if ( i % 2 == 0 ) 1373 | { 1374 | nst[ dir ] -= nlen ; 1375 | } 1376 | 1377 | edgeProcContourNoInter2( ecd, nst, nlen, dir, hash, tlist, numTris, vlist, numVerts ) ; 1378 | } 1379 | // printf("I am done with edges!\n") ; 1380 | 1381 | } 1382 | // printf("I am done with cell %d %d %d, %d \n", st[0], st[1], st[2], len ) ; 1383 | }; 1384 | 1385 | void Octree::faceProcContourNoInter2( OctreeNode* node[2], int st[3], int len, int dir, HashMap* hash, IndexedTriangleList* tlist, int& numTris, VertexList* vlist, int& numVerts ) 1386 | { 1387 | // printf("I am at a face! %d %d %d, %d, %d\n", st[0], st[1], st[2], len, dir ) ; 1388 | if ( ! ( node[0] && node[1] ) ) 1389 | { 1390 | // printf("I am none.\n") ; 1391 | return ; 1392 | } 1393 | 1394 | int type[2] = { node[0]->getType(), node[1]->getType() } ; 1395 | 1396 | if ( type[0] == 0 || type[1] == 0 ) 1397 | { 1398 | int i, j ; 1399 | int nlen = len / 2 ; 1400 | int nst[3] ; 1401 | 1402 | // 4 face calls 1403 | OctreeNode* fcd[2] ; 1404 | int iface = faceProcFaceMask[ dir ][ 0 ][ 0 ] ; 1405 | for ( i = 0 ; i < 4 ; i ++ ) 1406 | { 1407 | int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] }; 1408 | for ( int j = 0 ; j < 2 ; j ++ ) 1409 | { 1410 | if ( type[j] > 0 ) 1411 | { 1412 | fcd[j] = node[j] ; 1413 | } 1414 | else 1415 | { 1416 | fcd[j] = ((InternalNode *) node[ j ] )->child[ c[j] ] ; 1417 | } 1418 | } 1419 | 1420 | nst[0] = st[0] + nlen * ( vertMap[ c[ 0 ] ][ 0 ] - vertMap[ iface ][ 0 ] ); 1421 | nst[1] = st[1] + nlen * ( vertMap[ c[ 0 ] ][ 1 ] - vertMap[ iface ][ 1 ] ); 1422 | nst[2] = st[2] + nlen * ( vertMap[ c[ 0 ] ][ 2 ] - vertMap[ iface ][ 2 ] ); 1423 | 1424 | faceProcContourNoInter2( fcd, nst, nlen, faceProcFaceMask[ dir ][ i ][ 2 ], hash, tlist, numTris, vlist, numVerts ) ; 1425 | } 1426 | 1427 | 1428 | // 4 edge calls 1429 | int orders[2][4] = {{ 0, 0, 1, 1 }, { 0, 1, 0, 1 }} ; 1430 | OctreeNode* ecd[4] ; 1431 | 1432 | for ( i = 0 ; i < 4 ; i ++ ) 1433 | { 1434 | int c[4] = { faceProcEdgeMask[ dir ][ i ][ 1 ], faceProcEdgeMask[ dir ][ i ][ 2 ], 1435 | faceProcEdgeMask[ dir ][ i ][ 3 ], faceProcEdgeMask[ dir ][ i ][ 4 ] }; 1436 | int* order = orders[ faceProcEdgeMask[ dir ][ i ][ 0 ] ] ; 1437 | 1438 | for ( int j = 0 ; j < 4 ; j ++ ) 1439 | { 1440 | if ( type[order[j]] > 0 ) 1441 | { 1442 | ecd[j] = node[order[j]] ; 1443 | } 1444 | else 1445 | { 1446 | ecd[j] = ( (InternalNode *) node[ order[ j ] ] )->child[ c[j] ] ; 1447 | } 1448 | } 1449 | 1450 | int ndir = faceProcEdgeMask[ dir ][ i ][ 5 ] ; 1451 | nst[0] = st[0] + nlen ; 1452 | nst[1] = st[1] + nlen ; 1453 | nst[2] = st[2] + nlen ; 1454 | nst[dir] -= nlen ; 1455 | if ( i % 2 == 0 ) 1456 | { 1457 | nst[ ndir ] -= nlen ; 1458 | } 1459 | 1460 | edgeProcContourNoInter2( ecd, nst, nlen, ndir, hash, tlist, numTris, vlist, numVerts ) ; 1461 | } 1462 | // printf("I am done.\n") ; 1463 | } 1464 | else 1465 | { 1466 | // printf("i don't have children.\n"); 1467 | } 1468 | }; 1469 | 1470 | void Octree::edgeProcContourNoInter2( OctreeNode* node[4], int st[3], int len, int dir, HashMap* hash, IndexedTriangleList* tlist, int& numTris, VertexList* vlist, int& numVerts ) 1471 | { 1472 | // printf("I am at an edge! %d %d %d \n", st[0], st[1], st[2] ) ; 1473 | if ( ! ( node[0] && node[1] && node[2] && node[3] ) ) 1474 | { 1475 | // printf("I am done!\n") ; 1476 | return ; 1477 | } 1478 | 1479 | int type[4] = { node[0]->getType(), node[1]->getType(), node[2]->getType(), node[3]->getType() } ; 1480 | 1481 | if ( type[0] > 0 && type[1] > 0 && type[2] > 0 && type[3] > 0 ) 1482 | { 1483 | this->processEdgeNoInter2( node, st, len, dir, hash, tlist, numTris, vlist, numVerts ) ; 1484 | } 1485 | else 1486 | { 1487 | int i, j ; 1488 | int nlen = len / 2 ; 1489 | int nst[3] ; 1490 | 1491 | // 2 edge calls 1492 | OctreeNode* ecd[4] ; 1493 | for ( i = 0 ; i < 2 ; i ++ ) 1494 | { 1495 | int c[ 4 ] = { edgeProcEdgeMask[ dir ][ i ][ 0 ], 1496 | edgeProcEdgeMask[ dir ][ i ][ 1 ], 1497 | edgeProcEdgeMask[ dir ][ i ][ 2 ], 1498 | edgeProcEdgeMask[ dir ][ i ][ 3 ] } ; 1499 | 1500 | for ( int j = 0 ; j < 4 ; j ++ ) 1501 | { 1502 | if ( type[j] > 0 ) 1503 | { 1504 | ecd[j] = node[j] ; 1505 | } 1506 | else 1507 | { 1508 | ecd[j] = ((InternalNode *) node[j])->child[ c[j] ] ; 1509 | } 1510 | } 1511 | 1512 | nst[0] = st[0] ; 1513 | nst[1] = st[1] ; 1514 | nst[2] = st[2] ; 1515 | nst[dir] += nlen * i ; 1516 | 1517 | edgeProcContourNoInter2( ecd, nst, nlen, edgeProcEdgeMask[ dir ][ i ][ 4 ], hash, tlist, numTris, vlist, numVerts ) ; 1518 | } 1519 | 1520 | } 1521 | // printf("I am done!\n") ; 1522 | }; 1523 | 1524 | 1525 | void Octree::processEdgeNoInter2( OctreeNode* node[4], int st[3], int len, int dir, HashMap* hash, IndexedTriangleList* tlist, int& numTris, VertexList* vlist, int& numVerts ) 1526 | { 1527 | // printf("I am at a leaf edge! %d %d %d\n", st[0], st[1], st[2] ) ; 1528 | // Get minimal cell 1529 | int i, type, minht = maxDepth+1, mini = -1 ; 1530 | int ind[4], sc[4], ht[4], flip=0; 1531 | float mp[4][3] ; 1532 | for ( i = 0 ; i < 4 ; i ++ ) { 1533 | if ( node[i]->getType() == LEAF ) { 1534 | LeafNode* lnode = ((LeafNode *) node[i]) ; 1535 | ht[i] = lnode->height ; 1536 | mp[i][0] = lnode->mp[0] ; 1537 | mp[i][1] = lnode->mp[1] ; 1538 | mp[i][2] = lnode->mp[2] ; 1539 | 1540 | 1541 | int ed = processEdgeMask[dir][i] ; 1542 | int c1 = edgevmap[ed][0] ; 1543 | int c2 = edgevmap[ed][1] ; 1544 | 1545 | if ( lnode->height < minht ) { 1546 | minht = lnode->height ; 1547 | mini = i ; 1548 | if ( lnode->getSign(c1) > 0 ) 1549 | flip = 1 ; 1550 | else 1551 | flip = 0 ; 1552 | } 1553 | ind[i] = lnode->index ; 1554 | if ( ind[i] < 0 ) 1555 | { 1556 | // Create new index 1557 | VertexList* nv = new VertexList ; 1558 | nv->vt[0] = lnode->mp[0] ; 1559 | nv->vt[1] = lnode->mp[1] ; 1560 | nv->vt[2] = lnode->mp[2] ; 1561 | nv->next = vlist->next ; 1562 | vlist->next = nv ; 1563 | ind[i] = numVerts ; 1564 | lnode->index = numVerts ; 1565 | numVerts ++ ; 1566 | } 1567 | 1568 | if ( lnode->getSign( c1 ) == lnode->getSign( c2 ) ) 1569 | sc[ i ] = 0 ; 1570 | else 1571 | sc[ i ] = 1 ; 1572 | } 1573 | else if ( node[i]->getType() == PSEUDOLEAF ) { 1574 | PseudoLeafNode* pnode = ((PseudoLeafNode *) node[i]) ; 1575 | ht[i] = pnode->height ; 1576 | mp[i][0] = pnode->mp[0] ; 1577 | mp[i][1] = pnode->mp[1] ; 1578 | mp[i][2] = pnode->mp[2] ; 1579 | 1580 | int ed = processEdgeMask[dir][i] ; 1581 | int c1 = edgevmap[ed][0] ; 1582 | int c2 = edgevmap[ed][1] ; 1583 | 1584 | if ( pnode->height < minht ) 1585 | { 1586 | minht = pnode->height ; 1587 | mini = i ; 1588 | if ( pnode->getSign(c1) > 0 ) 1589 | flip = 1 ; 1590 | else 1591 | flip = 0 ; 1592 | 1593 | } 1594 | ind[i] = pnode->index ; 1595 | if ( ind[i] < 0 ) { 1596 | // Create new index 1597 | VertexList* nv = new VertexList ; 1598 | nv->vt[0] = pnode->mp[0] ; 1599 | nv->vt[1] = pnode->mp[1] ; 1600 | nv->vt[2] = pnode->mp[2] ; 1601 | nv->next = vlist->next ; 1602 | vlist->next = nv ; 1603 | ind[i] = numVerts ; 1604 | pnode->index = numVerts ; 1605 | numVerts ++ ; 1606 | } 1607 | 1608 | if ( pnode->getSign( c1 ) == pnode->getSign( c2 ) ) 1609 | sc[ i ] = 0 ; 1610 | else 1611 | sc[ i ] = 1 ; 1612 | } 1613 | else { 1614 | printf("Wrong!\n"); 1615 | } 1616 | 1617 | } 1618 | 1619 | if ( sc[ mini ] == 0 ) 1620 | { 1621 | // printf("I am done!\n" ) ; 1622 | return ; 1623 | } 1624 | 1625 | /************************************************************************/ 1626 | /* Performing test */ 1627 | /************************************************************************/ 1628 | 1629 | int fverts[4] ; 1630 | int hasFverts[4] = { 0, 0, 0, 0 } ; 1631 | int evert ; 1632 | int needTess = 0 ; 1633 | int location[4] ; 1634 | int nvert[4] ={0,0,0,0}; 1635 | 1636 | 1637 | 1638 | // First, face test 1639 | int nbr[4][2] = { {0,1},{1,3},{2,3},{0,2} }; 1640 | int fdir[3][4] = { 1641 | {2,1,2,1}, 1642 | {0,2,0,2}, 1643 | {1,0,1,0}}; 1644 | int dir3[3][4][2] = { 1645 | {{1, -1},{2, 0},{1, 0},{2, -1}}, 1646 | {{2, -1},{0, 0},{2, 0},{0, -1}}, 1647 | {{0, -1},{1, 0},{0, 0},{1, -1}} }; 1648 | 1649 | for ( i = 0 ; i < 4 ; i ++ ) 1650 | { 1651 | int a = nbr[i][0]; 1652 | int b = nbr[i][1] ; 1653 | 1654 | #ifndef TESS_UNIFORM 1655 | if ( ht[a] != ht[b] ) 1656 | #endif 1657 | { 1658 | // Different level, check if the dual edge passes through the face 1659 | if ( hash->FindKey( (ptr_type) (node[a]), (ptr_type)(node[b]), fverts[i], location[i] ) ) 1660 | { 1661 | // The vertex was found previously 1662 | founds++ ; 1663 | hasFverts[i] = 1 ; 1664 | nvert[i] = 0 ; 1665 | needTess = 1 ; 1666 | } 1667 | else 1668 | { 1669 | // Otherwise, we test it here 1670 | int sht = ( ht[a] > ht[b] ? ht[b] : ht[a] ) ; 1671 | int flen = ( 1 << sht ) ; 1672 | int fst[3] ; 1673 | 1674 | fst[ fdir[dir][i] ] = st[ fdir[dir][i] ] ; 1675 | fst[ dir3[dir][i][0] ] = st[ dir3[dir][i][0] ] + flen * dir3[dir][i][1] ; 1676 | fst[ dir ] = st[ dir ] - ( st[ dir ] & (( 1 << sht ) - 1 ) ) ; 1677 | 1678 | if ( testFace( fst, flen, fdir[dir][i], mp[a], mp[b] ) == 0 ) 1679 | { 1680 | // Dual edge does not pass face, let's make a new vertex 1681 | VertexList* nv = new VertexList ; 1682 | nv->vt[0] = 0 ; 1683 | nv->vt[1] = 0 ; 1684 | nv->vt[2] = 0 ; 1685 | nv->next = vlist->next ; 1686 | vlist->next = nv ; 1687 | fverts[i] = numVerts ; 1688 | location[i] = ((ptr_type) nv) ; 1689 | nvert[i] = 1 ; 1690 | numVerts ++ ; 1691 | 1692 | hash->InsertKey( (ptr_type)(node[a]), (ptr_type)(node[b]), fverts[i], location[i] ) ; 1693 | 1694 | 1695 | hasFverts[ i ] = 1 ; 1696 | needTess = 1 ; 1697 | news ++ ; 1698 | } 1699 | } 1700 | } 1701 | } 1702 | 1703 | // Next, edge test 1704 | int diag = 1 ; 1705 | if ( needTess == 0 ) 1706 | { 1707 | // Even if all dual edges pass through faces, the dual complex of an edge may not be convex 1708 | //int st2[3] = { st[0], st[1], st[2] } ; 1709 | //st2[ dir ] += len ; 1710 | 1711 | diag = testEdge( st, len, dir, node, mp ) ; 1712 | if ( diag == 0 ) 1713 | { 1714 | // When this happens, we need to create an extra vertex on the primal edge 1715 | needTess = 1 ; 1716 | } 1717 | } 1718 | 1719 | float cent[3] ; 1720 | if ( needTess ) 1721 | { 1722 | edgeVerts ++ ; 1723 | makeEdgeVertex( st, len, dir, node, mp, cent ) ; 1724 | 1725 | /* Just take centroid 1726 | int num = 0 ; 1727 | evert[0] = st[0] ; 1728 | evert[1] = st[1] ; 1729 | evert[2] = st[2] ; 1730 | evert[dir] = 0 ; 1731 | for ( i = 0 ; i < 4 ; i ++ ) 1732 | { 1733 | evert[dir] += mp[i][dir] ; 1734 | num ++ ; 1735 | 1736 | if ( hasFverts[ i ] ) 1737 | { 1738 | evert[dir] += fverts[i][dir] ; 1739 | num ++ ; 1740 | } 1741 | } 1742 | evert[dir] /= num ; 1743 | */ 1744 | 1745 | /* 1746 | if ( evert[dir] < st[dir] ) 1747 | { 1748 | evert[dir] = st[dir] ; 1749 | } 1750 | else if ( evert[dir] > st[dir] + len ) 1751 | { 1752 | evert[dir] = st[dir] + len ; 1753 | } 1754 | */ 1755 | 1756 | VertexList* nv = new VertexList ; 1757 | nv->vt[0] = cent[0] ; 1758 | nv->vt[1] = cent[1] ; 1759 | nv->vt[2] = cent[2] ; 1760 | nv->next = vlist->next ; 1761 | vlist->next = nv ; 1762 | evert = numVerts ; 1763 | numVerts ++ ; 1764 | 1765 | } 1766 | 1767 | int flipped[3]; 1768 | if ( flip == 0 ) 1769 | { 1770 | for (i = 0 ;i < 3 ; i ++) 1771 | { 1772 | flipped[i] = i ; 1773 | } 1774 | } 1775 | else 1776 | { 1777 | for (i = 0 ;i < 3 ; i ++) 1778 | { 1779 | flipped[i] = 2 - i ; 1780 | } 1781 | } 1782 | 1783 | 1784 | 1785 | // Finally, let's output triangle 1786 | if ( needTess == 0 ) 1787 | { 1788 | // Normal splitting of quad 1789 | if ( diag == 1 ) 1790 | { 1791 | if ( node[0] != node[1] && node[1] != node[3] ) 1792 | { 1793 | int tind1[]={0,1,3} ; 1794 | 1795 | numTris ++ ; 1796 | IndexedTriangleList* t1 = new IndexedTriangleList ; 1797 | t1->next = tlist->next; 1798 | tlist->next = t1 ; 1799 | for ( int j = 0 ; j < 3 ; j ++ ) 1800 | { 1801 | t1->vt[flipped[j]] = ind[ tind1[j] ] ; 1802 | } 1803 | } 1804 | 1805 | if ( node[3] != node[2] && node[2] != node[0] ) 1806 | { 1807 | int tind2[]={3,2,0} ; 1808 | 1809 | numTris ++ ; 1810 | IndexedTriangleList* t2 = new IndexedTriangleList ; 1811 | t2->next = tlist->next; 1812 | tlist->next = t2 ; 1813 | for ( int j = 0 ; j < 3 ; j ++ ) 1814 | { 1815 | t2->vt[flipped[j]] = ind[ tind2[j] ] ; 1816 | } 1817 | } 1818 | } 1819 | else 1820 | { 1821 | if ( node[0] != node[1] && node[1] != node[2] ) 1822 | { 1823 | int tind1[]={0,1,2} ; 1824 | 1825 | 1826 | numTris ++ ; 1827 | IndexedTriangleList* t1 = new IndexedTriangleList ; 1828 | t1->next = tlist->next; 1829 | tlist->next = t1 ; 1830 | for ( int j = 0 ; j < 3 ; j ++ ) 1831 | { 1832 | t1->vt[flipped[j]] = ind[ tind1[j] ] ; 1833 | } 1834 | } 1835 | 1836 | if ( node[1] != node[3] && node[3] != node[2] ) 1837 | { 1838 | int tind2[]={1,3,2} ; 1839 | 1840 | numTris ++ ; 1841 | IndexedTriangleList* t2 = new IndexedTriangleList ; 1842 | t2->next = tlist->next; 1843 | tlist->next = t2 ; 1844 | for ( int j = 0 ; j < 3 ; j ++ ) 1845 | { 1846 | t2->vt[flipped[j]] = ind[ tind2[j] ] ; 1847 | } 1848 | } 1849 | } 1850 | 1851 | } 1852 | 1853 | else 1854 | {/* 1855 | if ( flip == 1 ) 1856 | { 1857 | int tempind[4]={ind[0], ind[2], ind[1], ind[3]}; 1858 | OctreeNode* tempnode[4] = {node[0], node[2], node[1], node[3]}; 1859 | int tempfverts[4]={fverts[3], fverts[2], fverts[1], fverts[0]}; 1860 | int temphasFverts[4]={hasFverts[3], hasFverts[2], hasFverts[1], hasFverts[0]}; 1861 | int templocation[4]={location[3], location[2], location[1], location[0]}; 1862 | int tempnvert[4]={nvert[3], nvert[2], nvert[1], nvert[0]}; 1863 | 1864 | for ( i = 0 ; i < 4 ; i ++ ) 1865 | { 1866 | ind[i] = tempind[i] ; 1867 | node[i] = tempnode[i] ; 1868 | fverts[i] = tempfverts[i] ; 1869 | hasFverts[i] = temphasFverts[i] ; 1870 | location[i] = templocation[i] ; 1871 | nvert[i] = tempnvert[i] ; 1872 | } 1873 | } 1874 | */ 1875 | int nnbr[4][2] = { {0,1},{1,3},{3,2},{2,0} }; 1876 | 1877 | // Center-splitting 1878 | for ( i = 0 ; i < 4 ; i ++ ) 1879 | { 1880 | int a = nnbr[i][0]; 1881 | int b = nnbr[i][1] ; 1882 | 1883 | if ( hasFverts[ i ] ) 1884 | { 1885 | // Further split each triangle into two 1886 | numTris += 2 ; 1887 | 1888 | IndexedTriangleList* t = new IndexedTriangleList ; 1889 | t->next = tlist->next; 1890 | tlist->next = t ; 1891 | t->vt[flipped[0]] = ind[ a ] ; 1892 | t->vt[flipped[1]] = fverts[ i ] ; 1893 | t->vt[flipped[2]] = evert ; 1894 | 1895 | t = new IndexedTriangleList ; 1896 | t->next = tlist->next; 1897 | tlist->next = t ; 1898 | t->vt[flipped[0]] = evert ; 1899 | t->vt[flipped[1]] = fverts[ i ] ; 1900 | t->vt[flipped[2]] = ind[ b ] ; 1901 | 1902 | // Update geometric location of the face vertex 1903 | VertexList* nv = ((VertexList *) location[i]) ; 1904 | if ( nvert[i] ) 1905 | { 1906 | nv->vt[0] = cent[0] ; 1907 | nv->vt[1] = cent[1] ; 1908 | nv->vt[2] = cent[2] ; 1909 | } 1910 | else 1911 | { 1912 | nv->vt[0] = ( nv->vt[0] + cent[0] ) / 2 ; 1913 | nv->vt[1] = ( nv->vt[1] + cent[1] ) / 2 ; 1914 | nv->vt[2] = ( nv->vt[2] + cent[2] ) / 2 ; 1915 | } 1916 | } 1917 | else 1918 | { 1919 | // For one triangle with center vertex 1920 | if ( node[a] != node[b] ) 1921 | { 1922 | numTris ++ ; 1923 | IndexedTriangleList* t = new IndexedTriangleList ; 1924 | t->next = tlist->next; 1925 | tlist->next = t ; 1926 | t->vt[flipped[0]] = ind[ a ] ; 1927 | t->vt[flipped[1]] = ind[ b ] ; 1928 | t->vt[flipped[2]] = evert ; 1929 | } 1930 | } 1931 | } 1932 | } 1933 | // printf("I am done!\n" ) ; 1934 | 1935 | }; 1936 | -------------------------------------------------------------------------------- /octree.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Main class and structures for DC 4 | 5 | Copyright (C) 2011 Tao Ju 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public License 9 | (LGPL) as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef OCTREE_H 23 | #define OCTREE_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "GeoCommon.hpp" 31 | #include "eigen.hpp" 32 | #include "HashMap.hpp" 33 | #include "intersection.hpp" 34 | 35 | // Clamp all minimizers to be inside the cell 36 | //#define CLAMP 37 | 38 | // If SOG vertices are relative to each cell 39 | //#define SOG_RELATIVE 40 | 41 | //#define EDGE_TEST_CONVEXITY 42 | //#define EDGE_TEST_FLIPDIAGONAL 43 | #define EDGE_TEST_NEW 44 | 45 | //#define TESS_UNIFORM 46 | //#define TESS_NONE 47 | 48 | // old definiton was: 0== InternalNode, 1== LeafNode, 2==PseudoLeafNode 49 | enum NodeType { INTERNAL, LEAF, PSEUDOLEAF }; 50 | 51 | /* Tree nodes */ 52 | class OctreeNode { 53 | public: 54 | OctreeNode(){}; 55 | virtual NodeType getType() = 0; // 0== InternalNode, 1== LeafNode, 2==PseudoLeafNode 56 | }; 57 | 58 | class InternalNode : public OctreeNode { 59 | public: // no signs, height, len, or QEF stored for internal node 60 | OctreeNode * child[8] ; 61 | InternalNode () { 62 | for ( int i = 0 ; i < 8 ; i ++ ) 63 | child[i] = NULL ; 64 | }; 65 | ~InternalNode() { 66 | for ( int i = 0 ; i < 8 ; i ++ ) { 67 | if (child[i] != NULL) { 68 | delete child[i]; 69 | } 70 | } 71 | } 72 | NodeType getType ( ) { return INTERNAL; }; 73 | }; 74 | 75 | class QEFMixin { 76 | protected: 77 | unsigned char signs; 78 | public: 79 | char height; // depth 80 | float mp[3]; // this is the minimizer point of the QEF 81 | int index; // vertex index in PLY file 82 | float ata[6], atb[3], btb; // QEF data 83 | 84 | void clearQEF() { 85 | for ( int i = 0 ; i < 6 ; i ++ ) 86 | ata[i] = 0 ; 87 | 88 | for ( int i = 0 ; i < 3 ; i ++ ) { 89 | mp[i] = 0; 90 | atb[i] = 0 ; 91 | } 92 | 93 | btb = 0 ; 94 | } 95 | void setQEF(float ata1[6], float atb1[3], float btb1, float mp1[3] ) { 96 | for ( int i = 0 ; i < 6 ; i ++ ) 97 | ata[i] = ata1[i] ; 98 | 99 | for ( int i = 0 ; i < 3 ; i ++ ) { 100 | mp[i] = mp1[i] ; 101 | atb[i] = atb1[i] ; 102 | } 103 | btb = btb1 ; 104 | } 105 | int getSign ( int index ) { return (( signs >> index ) & 1 ); }; 106 | }; 107 | 108 | class LeafNode : public OctreeNode, public QEFMixin { 109 | 110 | public: 111 | ~LeafNode() {}; 112 | 113 | // Construction 114 | LeafNode( int ht, unsigned char sg, float coord[3] ) { 115 | height = ht ; 116 | signs = sg ; 117 | clearQEF(); 118 | index = -1 ; 119 | }; 120 | 121 | // Construction by QEF 122 | // each edge of the cube can have an intersection point 123 | // so we can give up to 12 intersection points with 12 normal-vectors 124 | // specify number of intersections in numint 125 | // 126 | // st is the minimum bounding-box point 127 | // st + (1,1,1)*len is the maximum bounding-box point 128 | LeafNode( int ht, unsigned char sg, int st[3], int len, int numint, float inters[12][3], float norms[12][3] ) { 129 | height = ht; 130 | signs = sg; 131 | index = -1; 132 | clearQEF(); 133 | 134 | float pt[3] ={0,0,0} ; 135 | if ( numint > 0 ) { 136 | for ( int i = 0 ; i < numint ; i ++ ) { 137 | float* norm = norms[i] ; 138 | float* p = inters[i] ; 139 | // printf("Norm: %f, %f, %f Pts: %f, %f, %f\n", norm[0], norm[1], norm[2], p[0], p[1], p[2] ) ; 140 | 141 | // QEF 142 | ata[ 0 ] += (float) ( norm[ 0 ] * norm[ 0 ] ); 143 | ata[ 1 ] += (float) ( norm[ 0 ] * norm[ 1 ] ); 144 | ata[ 2 ] += (float) ( norm[ 0 ] * norm[ 2 ] ); 145 | ata[ 3 ] += (float) ( norm[ 1 ] * norm[ 1 ] ); 146 | ata[ 4 ] += (float) ( norm[ 1 ] * norm[ 2 ] ); 147 | ata[ 5 ] += (float) ( norm[ 2 ] * norm[ 2 ] ); 148 | double pn = p[0] * norm[0] + p[1] * norm[1] + p[2] * norm[2] ; 149 | atb[ 0 ] += (float) ( norm[ 0 ] * pn ) ; 150 | atb[ 1 ] += (float) ( norm[ 1 ] * pn ) ; 151 | atb[ 2 ] += (float) ( norm[ 2 ] * pn ) ; 152 | btb += (float) pn * (float) pn ; 153 | // Minimizer 154 | pt[0] += p[0] ; 155 | pt[1] += p[1] ; 156 | pt[2] += p[2] ; 157 | } 158 | // we minimize towards the average of all intersection points 159 | pt[0] /= numint ; 160 | pt[1] /= numint ; 161 | pt[2] /= numint ; 162 | // Solve 163 | float mat[10] ; 164 | BoundingBoxf * box = new BoundingBoxf(); 165 | box->begin.x = (float) st[0] ; 166 | box->begin.y = (float) st[1] ; 167 | box->begin.z = (float) st[2] ; 168 | box->end.x = (float) st[0] + len ; 169 | box->end.y = (float) st[1] + len ; 170 | box->end.z = (float) st[2] + len ; 171 | 172 | // eigen.hpp 173 | // calculate minimizer point, and return error 174 | // QEF: ata, atb, btb 175 | // pt is the average of the intersection points 176 | // mp is the result 177 | // box is a bounding-box for this node 178 | // mat is storage for calcPoint() ? 179 | float error = calcPoint( ata, atb, btb, pt, mp, box, mat ) ; 180 | 181 | #ifdef CLAMP // Clamp all minimizers to be inside the cell 182 | if ( mp[0] < st[0] || mp[1] < st[1] || mp[2] < st[2] || // mp is outside bounding-box min-pt 183 | mp[0] > st[0] + len || mp[1] > st[1] + len || mp[2] > st[2] + len ) // mp is outside bounding-box max-pt 184 | { 185 | mp[0] = pt[0] ; // reject mp by calcPoint, instead clamp solution to the mass-center 186 | mp[1] = pt[1] ; 187 | mp[2] = pt[2] ; 188 | } 189 | #endif 190 | } 191 | else { 192 | printf("Number of edge intersections in this leaf cell is zero!\n") ; 193 | mp[0] = st[0] + len / 2; 194 | mp[1] = st[1] + len / 2; 195 | mp[2] = st[2] + len / 2; 196 | } 197 | }; 198 | 199 | NodeType getType ( ) { return LEAF ; }; 200 | }; 201 | 202 | // leaf, but not at max depth 203 | // created by merging child-nodes 204 | class PseudoLeafNode : public OctreeNode, public QEFMixin { 205 | public: 206 | OctreeNode * child[8] ; // Children 207 | 208 | ~PseudoLeafNode() { 209 | for ( int i = 0 ; i < 8 ; i ++ ) { 210 | if (child[i] != NULL) 211 | delete child[i]; 212 | } 213 | } 214 | 215 | // Construction, without QEF 216 | PseudoLeafNode ( int ht, unsigned char sg, float coord[3] ) { 217 | height = ht; 218 | signs = sg; 219 | clearQEF(); 220 | for ( int i = 0 ; i < 3 ; i ++ ) 221 | mp[i] = coord[i] ; 222 | 223 | for ( int i = 0 ; i < 8 ; i ++ ) 224 | child[i] = NULL ; 225 | 226 | index = -1 ; 227 | }; 228 | 229 | // construction with QEF 230 | PseudoLeafNode ( int ht, unsigned char sg, float ata1[6], float atb1[3], float btb1, float mp1[3] ) { 231 | height = ht ; 232 | signs = sg ; 233 | setQEF(ata1, atb1, btb1, mp1); 234 | for ( int i = 0 ; i < 8 ; i ++ ) 235 | child[i] = NULL ; 236 | 237 | index = -1 ; 238 | }; 239 | NodeType getType ( ) { return PSEUDOLEAF ; }; 240 | }; 241 | 242 | 243 | /* Global variables */ 244 | 245 | // map from the 12 edges of the cube to the 8 vertices. 246 | // example: edge 0 connects vertices 0,4 247 | const int edgevmap[12][2] = {{0,4},{1,5},{2,6},{3,7},{0,2},{1,3},{4,6},{5,7},{0,1},{2,3},{4,5},{6,7}}; 248 | const int edgemask[3] = { 5, 3, 6 } ; 249 | 250 | // direction from parent st to each of the eight child st 251 | // st is the corner of the cube with minimum (x,y,z) coordinates 252 | const int vertMap[8][3] = {{0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}} ; 253 | 254 | // map from the 6 faces of the cube to the 4 vertices that bound the face 255 | const int faceMap[6][4] = {{4, 8, 5, 9}, {6, 10, 7, 11},{0, 8, 1, 10},{2, 9, 3, 11},{0, 4, 2, 6},{1, 5, 3, 7}} ; 256 | 257 | // first used by cellProcCount() 258 | // used in cellProcContour(). 259 | // between 8 child-nodes there are 12 faces. 260 | // first two numbers are child-pairs, to be processed by faceProcContour() 261 | // the last number is "dir" ? 262 | const int cellProcFaceMask[12][3] = {{0,4,0},{1,5,0},{2,6,0},{3,7,0},{0,2,1},{4,6,1},{1,3,1},{5,7,1},{0,1,2},{2,3,2},{4,5,2},{6,7,2}} ; 263 | 264 | 265 | // then used in cellProcContour() when calling edgeProc() 266 | // between 8 children there are 6 common edges 267 | // table lists the 4 children that share the edge 268 | // the last number is "dir" ? 269 | const int cellProcEdgeMask[6][5] = {{0,1,2,3,0},{4,5,6,7,0},{0,4,1,5,1},{2,6,3,7,1},{0,2,4,6,2},{1,3,5,7,2}} ; 270 | 271 | // usde by faceProcCount() 272 | const int faceProcFaceMask[3][4][3] = { 273 | {{4,0,0},{5,1,0},{6,2,0},{7,3,0}}, 274 | {{2,0,1},{6,4,1},{3,1,1},{7,5,1}}, 275 | {{1,0,2},{3,2,2},{5,4,2},{7,6,2}} 276 | } ; 277 | const int faceProcEdgeMask[3][4][6] = { 278 | {{1,4,0,5,1,1},{1,6,2,7,3,1},{0,4,6,0,2,2},{0,5,7,1,3,2}}, 279 | {{0,2,3,0,1,0},{0,6,7,4,5,0},{1,2,0,6,4,2},{1,3,1,7,5,2}}, 280 | {{1,1,0,3,2,0},{1,5,4,7,6,0},{0,1,5,0,4,1},{0,3,7,2,6,1}} 281 | }; 282 | const int edgeProcEdgeMask[3][2][5] = { 283 | {{3,2,1,0,0},{7,6,5,4,0}}, 284 | {{5,1,4,0,1},{7,3,6,2,1}}, 285 | {{6,4,2,0,2},{7,5,3,1,2}}, 286 | }; 287 | const int processEdgeMask[3][4] = {{3,2,1,0},{7,5,6,4},{11,10,9,8}} ; 288 | 289 | const int dirCell[3][4][3] = { 290 | {{0,-1,-1},{0,-1,0},{0,0,-1},{0,0,0}}, 291 | {{-1,0,-1},{-1,0,0},{0,0,-1},{0,0,0}}, 292 | {{-1,-1,0},{-1,0,0},{0,-1,0},{0,0,0}} 293 | }; 294 | const int dirEdge[3][4] = { 295 | {3,2,1,0}, 296 | {7,6,5,4}, 297 | {11,10,9,8} 298 | }; 299 | 300 | 301 | /** 302 | * Class for building and processing an octree 303 | */ 304 | class Octree { 305 | public: 306 | OctreeNode* root ; 307 | int dimen; // Length of grid 308 | int maxDepth; 309 | int hasQEF; // used in simplify() 310 | int faceVerts, edgeVerts; 311 | int actualTris ; // number of triangles produced by cellProcContour() 312 | int founds, news ; 313 | public: 314 | Octree ( char* fname , double threshold) ; 315 | ~Octree ( ) ; 316 | void simplify ( float thresh ) ; 317 | void genContour ( char* fname ) ; 318 | //void genContourNoInter ( char* fname ) ; // not called from main() ? 319 | void genContourNoInter2 ( char* fname ) ; 320 | 321 | void countNodes(int result[3]) { 322 | for (int i=0;i<3;i++) 323 | result[i]=0; 324 | countNodes(this->root, result); 325 | } 326 | 327 | void countNodes( OctreeNode* node, int result[3] ) { 328 | switch( node->getType() ) { 329 | case INTERNAL: 330 | result[0]++; 331 | InternalNode* inode; 332 | inode = (InternalNode*)node; 333 | for (int i=0;i<8;i++) { 334 | if (inode->child[i]!=NULL) 335 | countNodes( inode->child[i], result); 336 | } 337 | break; 338 | case PSEUDOLEAF: 339 | result[1]++; 340 | PseudoLeafNode* pnode; 341 | pnode = (PseudoLeafNode*)node; 342 | for (int i=0;i<8;i++) { 343 | if (pnode->child[i]!=NULL) 344 | countNodes( pnode->child[i], result); 345 | } 346 | break; 347 | case LEAF: 348 | result[2]++; 349 | break; 350 | } 351 | } 352 | private: 353 | float simplify_threshold; 354 | OctreeNode* simplify( OctreeNode* node, int st[3], int len, float thresh ) ; 355 | 356 | //void readSOG ( char* fname ) ; // read SOG file 357 | //OctreeNode* readSOG ( FILE* fin, int st[3], int len, int ht, float origin[3], float range ) ; 358 | void readDCF ( char* fname ) ; // read DCF file 359 | OctreeNode* readDCF ( FILE* fin, int st[3], int len, int ht ) ; 360 | 361 | // Contouring 362 | void generateVertexIndex( OctreeNode* node, int& offset, FILE* fout ) ; // not used by NoInter2-functions? 363 | 364 | void cellProcContour ( OctreeNode* node, FILE* fout ) ; 365 | void faceProcContour ( OctreeNode* node[2], int dir, FILE* fout ) ; 366 | void edgeProcContour ( OctreeNode* node[4], int dir, FILE* fout ) ; 367 | void processEdgeWrite ( OctreeNode* node[4], int dir, FILE* fout ) ; 368 | void cellProcCount ( OctreeNode* node, int& nverts, int& nfaces ) ; 369 | void faceProcCount ( OctreeNode* node[2], int dir, int& nverts, int& nfaces ) ; 370 | void edgeProcCount ( OctreeNode* node[4], int dir, int& nverts, int& nfaces ) ; 371 | void processEdgeCount ( OctreeNode* node[4], int dir, int& nverts, int& nfaces ) ; 372 | 373 | /* not used !? 374 | void cellProcContourNoInter( OctreeNode* node, int st[3], int len, HashMap2* hash, TriangleList* list, int& numTris ) ; 375 | void faceProcContourNoInter( OctreeNode* node[2], int st[3], int len, int dir, HashMap2* hash, TriangleList* list, int& numTris ) ; 376 | void edgeProcContourNoInter( OctreeNode* node[4], int st[3], int len, int dir, HashMap2* hash, TriangleList* list, int& numTris ) ; 377 | void processEdgeNoInter( OctreeNode* node[4], int st[3], int len, int dir, HashMap2* hash, TriangleList* list, int& numTris ) ; 378 | */ 379 | 380 | void cellProcContourNoInter2( OctreeNode* node, int st[3], int len, HashMap* hash, IndexedTriangleList* tlist, int& numTris, VertexList* vlist, int& numVerts ) ; 381 | void faceProcContourNoInter2( OctreeNode* node[2], int st[3], int len, int dir, HashMap* hash, IndexedTriangleList* tlist, int& numTris, VertexList* vlist, int& numVerts ) ; 382 | void edgeProcContourNoInter2( OctreeNode* node[4], int st[3], int len, int dir, HashMap* hash, IndexedTriangleList* tlist, int& numTris, VertexList* vlist, int& numVerts ) ; 383 | void processEdgeNoInter2( OctreeNode* node[4], int st[3], int len, int dir, HashMap* hash, IndexedTriangleList* tlist, int& numTris, VertexList* vlist, int& numVerts ) ; 384 | 385 | /** 386 | * Non-intersecting test and tesselation 387 | */ 388 | int testFace( int st[3], int len, int dir, float v1[3], float v2[3] ) ; 389 | int testEdge( int st[3], int len, int dir, OctreeNode* node[4], float v[4][3] ) ; 390 | // not called? 391 | // void makeFaceVertex( int st[3], int len, int dir, OctreeNode* node1, OctreeNode* node2, float v[3] ) ; 392 | void makeEdgeVertex( int st[3], int len, int dir, OctreeNode* node[4], float mp[4][3], float v[3] ) ; 393 | }; 394 | 395 | 396 | #endif 397 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | ------------------------------------ 2 | Anders github fork readme 3 | https://github.com/aewallin/dualcontouring 4 | ------------------------------------ 5 | 6 | To test: 7 | $ mkdir bld 8 | $ cd bld 9 | $ cmake .. 10 | $ make 11 | $ ./dualcontour ../mechanic.dcf test.ply 12 | 13 | Options: 14 | --simplify 0.01 (octree simplification) 15 | --nointer (intersection-free algorithm) 16 | --test (run intersection tests after contouring) 17 | 18 | This produces a test.ply file that can be viewed with meshlab. 19 | $ meshlab test.ply 20 | 21 | When running with --nointer the --test should obviously(?) return zero 22 | intersections. 23 | 24 | ------------------------------------- 25 | Original readme: 26 | http://www1.cse.wustl.edu/~taoju/ 27 | http://sourceforge.net/projects/dualcontouring/ 28 | ------------------------------------- 29 | Dual Contouring Implementation in C++ 30 | 31 | Author: Tao Ju (with QEF code written by Scott Schaefer) 32 | Updated: February 2011 33 | 34 | 35 | I. What's included 36 | 37 | /code Source code and Microsoft Visualt Studio 6.0 project/workspace files 38 | /data A test file (mechanical part), in both .dcf and .ply formats 39 | 40 | 41 | II. How to run 42 | 43 | The dc.exe in the /code/release can be run by calling: 44 | 45 | >dc.exe mechanic.dcf out.ply 46 | 47 | where out.ply stores the polygonal output. 48 | 49 | 50 | III. File formats 51 | 52 | The code can take in two kinds of input: .dcf (Dual Contouring Format) and 53 | .sog (Signed Octree with Geometry). Both formats store an octree grid with 54 | inside/outside signs. DCF contains intersection points and normals on 55 | grid edges, whereas SOG contains a single point location within each 56 | non-empty grid cell. Both formats can be produced from a polygonal 57 | model, via scan-conversion, using the Polymender software on my website: 58 | 59 | http://www1.cse.wustl.edu/~taoju/code/polymender.htm 60 | 61 | The detail formats are documented in the readme file of Polymender. 62 | 63 | 64 | IV. Other notes. 65 | 66 | Two algorithms are implemented in this code: the original dual contouring 67 | algorithm [Ju et al., Siggraph 2002] and the intersection-free 68 | extension [Ju et al., Pacific Graphics 2006]. You can switch between 69 | them in the main() function in dc.cpp. In addition, octree 70 | simplification (guided by QEF errors) is also implemented, and can be 71 | turned on in the main() function. 72 | 73 | The use of all code is limited to non-profit research purposes only. 74 | --------------------------------------------------------------------------------