[37] | 1 | /* |
---|
| 2 | |
---|
| 3 | Name: slices.cc |
---|
| 4 | |
---|
| 5 | Coded: Paul Ning |
---|
| 6 | |
---|
| 7 | Modified by: Brian Curless |
---|
| 8 | Computer Graphics Laboratory |
---|
| 9 | Stanford University |
---|
| 10 | |
---|
| 11 | Comment: Processes all selected slices. |
---|
| 12 | |
---|
| 13 | Copyright (1997) The Board of Trustees of the Leland Stanford Junior |
---|
| 14 | University. Except for commercial resale, lease, license or other |
---|
| 15 | commercial transactions, permission is hereby given to use, copy, |
---|
| 16 | modify this software for academic purposes only. No part of this |
---|
| 17 | software or any derivatives thereof may be used in the production of |
---|
| 18 | computer models for resale or for use in a commercial |
---|
| 19 | product. STANFORD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND |
---|
| 20 | CONCERNING THIS SOFTWARE. No support is implied or provided. |
---|
| 21 | |
---|
| 22 | */ |
---|
| 23 | |
---|
| 24 | |
---|
| 25 | #include "Linear.h" |
---|
| 26 | #include <signal.h> |
---|
| 27 | #include <stdio.h> |
---|
| 28 | #include <string.h> |
---|
| 29 | #include "mc.h" |
---|
| 30 | #include <unistd.h> |
---|
| 31 | #include "ply.h" |
---|
| 32 | #include "OccGridRLE.h" |
---|
| 33 | #include "SectionRLE.h" |
---|
| 34 | #include "mc_more.h" |
---|
| 35 | #include <assert.h> |
---|
| 36 | |
---|
| 37 | //#define USE_VALUE_WEIGHT_PRODUCT |
---|
| 38 | |
---|
| 39 | #define GET_MORE_CUBE_TRIS |
---|
| 40 | |
---|
| 41 | struct PlyVertex { |
---|
| 42 | float x, y, z; |
---|
| 43 | float nx, ny, nz; |
---|
| 44 | float confidence; |
---|
| 45 | uchar realData; |
---|
| 46 | }; |
---|
| 47 | |
---|
| 48 | struct PlyTri { |
---|
| 49 | unsigned char nverts; |
---|
| 50 | int *verts; |
---|
| 51 | }; |
---|
| 52 | |
---|
| 53 | static char *elem_names[] = { |
---|
| 54 | "vertex", "face", |
---|
| 55 | }; |
---|
| 56 | |
---|
| 57 | static PlyProperty vert_props[] = { |
---|
| 58 | {"x", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0}, |
---|
| 59 | {"y", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0}, |
---|
| 60 | {"z", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0}, |
---|
| 61 | {"confidence", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0}, |
---|
| 62 | {"real_data", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0}, |
---|
| 63 | {"nx", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0}, |
---|
| 64 | {"ny", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0}, |
---|
| 65 | {"nz", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0}, |
---|
| 66 | }; |
---|
| 67 | |
---|
| 68 | static PlyProperty face_props[] = { |
---|
| 69 | {"vertex_indices", PLY_INT, PLY_INT, 0, 1, PLY_UCHAR, PLY_UCHAR, 0}, |
---|
| 70 | }; |
---|
| 71 | |
---|
| 72 | |
---|
| 73 | int loadCube(Cube cube, SectionRLE **section, int index, int xx, int yy); |
---|
| 74 | void computeGradients(SectionRLE **section, int level); |
---|
| 75 | static void UpdateGeometry(int j, int k, SectionRLE **rleSection, |
---|
| 76 | TriangleVertex *vertexList, uchar EdgeTableIndex); |
---|
| 77 | static void writePlyFile(char *filename, float tx, float ty, float tz); |
---|
| 78 | static Vertex *findVertex(TriangleVertex *vert, TriSet *set); |
---|
| 79 | static void loadSection(SectionRLE *rleSection, |
---|
| 80 | OccGridRLE *occGrid, int sliceNum); |
---|
| 81 | static void copyElement(Point *sect, SectionElement *elem); |
---|
| 82 | static Vertex *addVertex(TriangleVertex *inVert, int j, int k, |
---|
| 83 | SectionRLE **rleSection); |
---|
| 84 | int loadCubeAllowPartiallyValid(Cube cube, SectionRLE **section, |
---|
| 85 | int index, int xx, int yy); |
---|
| 86 | |
---|
| 87 | |
---|
| 88 | static int numVerts; |
---|
| 89 | static int numTris; |
---|
| 90 | static ChunkAllocator *triChunker; |
---|
| 91 | static ChunkAllocator *vertChunker; |
---|
| 92 | |
---|
| 93 | |
---|
| 94 | void |
---|
| 95 | DoSlicesOccRLE() |
---|
| 96 | { |
---|
| 97 | SectionRLE *rleSection[5], *temp; |
---|
| 98 | int i,j,k; /* indices within sections - relative to i0,j_0,k0 */ |
---|
| 99 | int slices,rows,cols; /* dimensions of stack of sections */ |
---|
| 100 | int iter; |
---|
| 101 | Cube cube; |
---|
| 102 | unsigned char EdgeTableIndex = 0x00; |
---|
| 103 | int xx, yy, zz, ii; |
---|
| 104 | int runType; |
---|
| 105 | RunLength length; |
---|
| 106 | SectionElement *element; |
---|
| 107 | |
---|
| 108 | numVerts = 0; |
---|
| 109 | numTris = 0; |
---|
| 110 | |
---|
| 111 | triChunker = new ChunkAllocator(CHUNK_SIZE); |
---|
| 112 | vertChunker = new ChunkAllocator(CHUNK_SIZE); |
---|
| 113 | |
---|
| 114 | |
---|
| 115 | |
---|
| 116 | /* |
---|
| 117 | * allocate memory for four sections |
---|
| 118 | */ |
---|
| 119 | slices = i1 - i0 + 3; |
---|
| 120 | rows = j_1 - j_0 + 3; |
---|
| 121 | cols = k1 - k0 + 3; |
---|
| 122 | |
---|
| 123 | if (UseValueWeightProduct) { |
---|
| 124 | signal(SIGFPE, SIG_IGN); |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | for (i=0;i<5;i++) |
---|
| 128 | rleSection[i] = new SectionRLE(rows,cols,CHUNK_SIZE); |
---|
| 129 | |
---|
| 130 | /* |
---|
| 131 | * read initial three slices (into section[1-3]) |
---|
| 132 | */ |
---|
| 133 | for (iter=0;iter<3;iter++) { |
---|
| 134 | /* |
---|
| 135 | * read appropriate regions of slice file |
---|
| 136 | */ |
---|
| 137 | loadSection(rleSection[iter+1], occGrid, FirstSliceFileNumber+i0-1+iter); |
---|
| 138 | } |
---|
| 139 | |
---|
| 140 | |
---|
| 141 | /* |
---|
| 142 | * compute normals in section[2] |
---|
| 143 | */ |
---|
| 144 | |
---|
| 145 | computeGradients(rleSection, 2); |
---|
| 146 | |
---|
| 147 | /* |
---|
| 148 | * Main Loop - Read New Slice |
---|
| 149 | */ |
---|
| 150 | |
---|
| 151 | fflush(stdout); |
---|
| 152 | |
---|
| 153 | for (i=1;i<slices-2;i++) { |
---|
| 154 | |
---|
| 155 | /* rotate section memories to make room for new slice */ |
---|
| 156 | temp = rleSection[0]; |
---|
| 157 | rleSection[0] = rleSection[1]; |
---|
| 158 | rleSection[1] = rleSection[2]; |
---|
| 159 | rleSection[2] = rleSection[3]; |
---|
| 160 | rleSection[3] = temp; |
---|
| 161 | |
---|
| 162 | /* |
---|
| 163 | * read appropriate regions of slice file |
---|
| 164 | */ |
---|
| 165 | |
---|
| 166 | loadSection(rleSection[3], occGrid, FirstSliceFileNumber+i0+i+1); |
---|
| 167 | |
---|
| 168 | computeGradients(rleSection, 2); |
---|
| 169 | |
---|
| 170 | /* Process the cubes in raster order */ |
---|
| 171 | for (yy = 1; yy < rleSection[1]->ydim-2; yy++) { |
---|
| 172 | rleSection[1]->setScanline(yy); |
---|
| 173 | xx = 0; |
---|
| 174 | while (TRUE) { |
---|
| 175 | |
---|
| 176 | length = rleSection[1]->getNextLength(); |
---|
| 177 | runType = rleSection[1]->getRunType(&length); |
---|
| 178 | |
---|
| 179 | if (runType == SectionRLE::END_OF_RUN) |
---|
| 180 | break; |
---|
| 181 | |
---|
| 182 | if (runType == SectionRLE::CONSTANT_DATA) { |
---|
| 183 | xx += length; |
---|
| 184 | } |
---|
| 185 | else { |
---|
| 186 | for (ii=0; ii<length; ii++, xx++) { |
---|
| 187 | if (xx == 0 || xx >= rleSection[2]->xdim-2) |
---|
| 188 | continue; |
---|
| 189 | |
---|
| 190 | #ifdef GET_MORE_CUBE_TRIS |
---|
| 191 | if (!loadCubeAllowPartiallyValid(cube, rleSection, |
---|
| 192 | 1, xx, yy)) |
---|
| 193 | continue; |
---|
| 194 | #else |
---|
| 195 | if (!loadCube(cube, rleSection, 1, xx, yy)) |
---|
| 196 | continue; |
---|
| 197 | #endif |
---|
| 198 | |
---|
| 199 | /* dispatch to DoCube with absolute i,j,k position */ |
---|
| 200 | TriangleVertex *vertexList = |
---|
| 201 | NewDoCube(cube,i0+i,j_0+xx,k0+yy,&EdgeTableIndex); |
---|
| 202 | |
---|
| 203 | if (TheEdgeTable[EdgeTableIndex].Ntriangles > 0) |
---|
| 204 | UpdateGeometry(xx, yy, rleSection, vertexList, |
---|
| 205 | EdgeTableIndex); |
---|
| 206 | } |
---|
| 207 | } |
---|
| 208 | } |
---|
| 209 | } |
---|
| 210 | printf("\rProcess slice %d of %d. Triangle count = %d", |
---|
| 211 | i+3, slices+1, TotalTriangles); |
---|
| 212 | fflush(stdout); |
---|
| 213 | |
---|
| 214 | } /* for (i) */ |
---|
| 215 | |
---|
| 216 | printf("\n\n"); |
---|
| 217 | fflush(stdout); |
---|
| 218 | |
---|
| 219 | |
---|
| 220 | printf("Writing out triangles...\n"); |
---|
| 221 | writePlyFile(outfile, |
---|
| 222 | occGrid->origin[0] - occGrid->resolution, |
---|
| 223 | occGrid->origin[1] - occGrid->resolution, |
---|
| 224 | occGrid->origin[2] - occGrid->resolution); |
---|
| 225 | |
---|
| 226 | printf("Done.\n\n"); |
---|
| 227 | |
---|
| 228 | } /* DoSlices */ |
---|
| 229 | |
---|
| 230 | |
---|
| 231 | static void |
---|
| 232 | UpdateGeometry(int j, int k, SectionRLE **rleSection, |
---|
| 233 | TriangleVertex *vertexList, uchar EdgeTableIndex) |
---|
| 234 | { |
---|
| 235 | int n; |
---|
| 236 | Triple triangle; |
---|
| 237 | Tri *tri; |
---|
| 238 | TriSet *set; |
---|
| 239 | |
---|
| 240 | set = &rleSection[2]->getElement(j,k)->set; |
---|
| 241 | set->ntris = 0; |
---|
| 242 | TriangleVertex *v0, *v1, *v2; |
---|
| 243 | for (n=0;n<TheEdgeTable[EdgeTableIndex].Ntriangles;n++) { |
---|
| 244 | triangle = (TheEdgeTable[EdgeTableIndex].TriangleList)[n]; |
---|
| 245 | |
---|
| 246 | v0 = &vertexList[triangle.A]; |
---|
| 247 | v1 = &vertexList[triangle.B]; |
---|
| 248 | v2 = &vertexList[triangle.C]; |
---|
| 249 | |
---|
| 250 | #ifdef GET_MORE_CUBE_TRIS |
---|
| 251 | if (!v0->valid || !v1->valid || !v2->valid) { |
---|
| 252 | continue; |
---|
| 253 | } |
---|
| 254 | #endif |
---|
| 255 | |
---|
| 256 | // Don't add degenerate triangles |
---|
| 257 | if (((v0->x == v1->x) && (v0->y == v1->y) && (v0->z == v1->z)) || |
---|
| 258 | ((v0->x == v2->x) && (v0->y == v2->y) && (v0->z == v2->z)) || |
---|
| 259 | ((v2->x == v1->x) && (v2->y == v1->y) && (v2->z == v1->z))) { |
---|
| 260 | |
---|
| 261 | continue; |
---|
| 262 | } |
---|
| 263 | |
---|
| 264 | tri = (Tri *)triChunker->alloc(sizeof(Tri)); |
---|
| 265 | tri->verts[0] = addVertex(v0,j,k,rleSection); |
---|
| 266 | tri->verts[1] = addVertex(v1,j,k,rleSection); |
---|
| 267 | tri->verts[2] = addVertex(v2,j,k,rleSection); |
---|
| 268 | numTris++; |
---|
| 269 | |
---|
| 270 | set->tris[set->ntris] = tri; |
---|
| 271 | set->ntris++; |
---|
| 272 | } |
---|
| 273 | } |
---|
| 274 | |
---|
| 275 | |
---|
| 276 | static Vertex * |
---|
| 277 | addVertex(TriangleVertex *inVert, int j, int k, SectionRLE **rleSection) |
---|
| 278 | { |
---|
| 279 | Vertex *outVert, *newVert, *oldVert, temp; |
---|
| 280 | TriSet *set; |
---|
| 281 | SectionElement *elem; |
---|
| 282 | |
---|
| 283 | // We should only need to go to (j,k), not (j+1,k+1), but |
---|
| 284 | // since we're dropping triangles with low confidence, we |
---|
| 285 | // need to account for the possiblity that vertices below and |
---|
| 286 | // behind may be dropped - really should just need to consider |
---|
| 287 | // the (j+1,k+1) in the slice below... |
---|
| 288 | |
---|
| 289 | for (int zz = 1; zz <= 2; zz++) { |
---|
| 290 | for (int yy = k-1; yy <= k+1; yy++) { |
---|
| 291 | for (int xx = j-1; xx <= j+1; xx++) { |
---|
| 292 | elem = rleSection[zz]->getElement(xx,yy); |
---|
| 293 | set = &elem->set; |
---|
| 294 | oldVert = findVertex(inVert, set); |
---|
| 295 | if (oldVert != NULL) |
---|
| 296 | return oldVert; |
---|
| 297 | |
---|
| 298 | } |
---|
| 299 | } |
---|
| 300 | } |
---|
| 301 | |
---|
| 302 | outVert = (Vertex *)vertChunker->alloc(sizeof(Vertex)); |
---|
| 303 | outVert->x = inVert->x; |
---|
| 304 | outVert->y = inVert->y; |
---|
| 305 | outVert->z = inVert->z; |
---|
| 306 | outVert->nx = inVert->nx; |
---|
| 307 | outVert->ny = inVert->ny; |
---|
| 308 | outVert->nz = inVert->nz; |
---|
| 309 | outVert->confidence = inVert->confidence; |
---|
| 310 | outVert->realData = inVert->realData; |
---|
| 311 | outVert->index = numVerts; |
---|
| 312 | |
---|
| 313 | numVerts++; |
---|
| 314 | |
---|
| 315 | return outVert; |
---|
| 316 | } |
---|
| 317 | |
---|
| 318 | |
---|
| 319 | static Vertex* |
---|
| 320 | findVertex(TriangleVertex *vert, TriSet *set) |
---|
| 321 | { |
---|
| 322 | int i, j; |
---|
| 323 | Vertex *oldVert; |
---|
| 324 | |
---|
| 325 | for (i = 0; i < set->ntris; i++) { |
---|
| 326 | for (j = 0; j < 3; j++) { |
---|
| 327 | oldVert = set->tris[i]->verts[j]; |
---|
| 328 | #if 0 |
---|
| 329 | if (fabs(oldVert->x - vert->x) < CULL_TRIANGLE_FACTOR*dx && |
---|
| 330 | fabs(oldVert->y - vert->y) < CULL_TRIANGLE_FACTOR*dy && |
---|
| 331 | fabs(oldVert->z - vert->z) < CULL_TRIANGLE_FACTOR*dz) |
---|
| 332 | return oldVert; |
---|
| 333 | #else |
---|
| 334 | if (oldVert->x == vert->x && |
---|
| 335 | oldVert->y == vert->y && |
---|
| 336 | oldVert->z == vert->z) |
---|
| 337 | return oldVert; |
---|
| 338 | #endif |
---|
| 339 | } |
---|
| 340 | } |
---|
| 341 | |
---|
| 342 | return NULL; |
---|
| 343 | } |
---|
| 344 | |
---|
| 345 | |
---|
| 346 | |
---|
| 347 | |
---|
| 348 | static void |
---|
| 349 | loadSection(SectionRLE *rleSection, OccGridRLE *occGrid, int sliceNum) |
---|
| 350 | { |
---|
| 351 | RunLength length; |
---|
| 352 | int runType, xx; |
---|
| 353 | SectionElement sectElement; |
---|
| 354 | OccElement *occElement; |
---|
| 355 | ushort totalWeight; |
---|
| 356 | |
---|
| 357 | rleSection->reset(); |
---|
| 358 | |
---|
| 359 | for (int yy = 0; yy < occGrid->ydim; yy++) { |
---|
| 360 | occGrid->setScanline(yy, sliceNum); |
---|
| 361 | rleSection->allocNewRun(yy); |
---|
| 362 | xx = 0; |
---|
| 363 | while (TRUE) { |
---|
| 364 | length = occGrid->getNextLength(); |
---|
| 365 | rleSection->putNextLength(length); |
---|
| 366 | runType = rleSection->getRunType(&length); |
---|
| 367 | |
---|
| 368 | if (runType == SectionRLE::END_OF_RUN) { |
---|
| 369 | break; |
---|
| 370 | } |
---|
| 371 | |
---|
| 372 | if (runType == SectionRLE::CONSTANT_DATA) { |
---|
| 373 | occElement = occGrid->getNextElement(); |
---|
| 374 | |
---|
| 375 | // This line was not present, causing compiler |
---|
| 376 | // warnings up until 6/5/06. (Brian Curless) |
---|
| 377 | totalWeight = occElement->totalWeight & |
---|
| 378 | ~OccGridRLE::FALSE_DATA_BIT; |
---|
| 379 | |
---|
| 380 | if (UseValueWeightProduct) { |
---|
| 381 | if (totalWeight > 0) { |
---|
| 382 | sectElement.density = (occElement->value/256.0 - 128)* |
---|
| 383 | occElement->totalWeight + 128; |
---|
| 384 | } else { |
---|
| 385 | sectElement.density = occElement->value/256.0; |
---|
| 386 | } |
---|
| 387 | } |
---|
| 388 | else { |
---|
| 389 | sectElement.density = occElement->value/256.0; |
---|
| 390 | } |
---|
| 391 | |
---|
| 392 | sectElement.confidence = occElement->totalWeight/256.0; |
---|
| 393 | sectElement.valid = FALSE; |
---|
| 394 | sectElement.realData = TRUE; |
---|
| 395 | sectElement.set.ntris = 0; |
---|
| 396 | |
---|
| 397 | rleSection->putNextElement(§Element); |
---|
| 398 | xx += length; |
---|
| 399 | } |
---|
| 400 | else { |
---|
| 401 | for (int i = 0; i < length; i++) { |
---|
| 402 | occElement = occGrid->getNextElement(); |
---|
| 403 | totalWeight = occElement->totalWeight & |
---|
| 404 | ~OccGridRLE::FALSE_DATA_BIT; |
---|
| 405 | if (UseValueWeightProduct) { |
---|
| 406 | if (totalWeight > 0) { |
---|
| 407 | sectElement.density = (occElement->value/256.0 - 128) |
---|
| 408 | *occElement->totalWeight + 128; |
---|
| 409 | } else { |
---|
| 410 | sectElement.density = occElement->value/256.0; |
---|
| 411 | } |
---|
| 412 | } |
---|
| 413 | else { |
---|
| 414 | sectElement.density = occElement->value/256.0; |
---|
| 415 | } |
---|
| 416 | sectElement.confidence = totalWeight/256.0; |
---|
| 417 | sectElement.valid = |
---|
| 418 | totalWeight > OCC_CONF_THRESHOLD; |
---|
| 419 | sectElement.realData = |
---|
| 420 | (occElement->totalWeight & |
---|
| 421 | OccGridRLE::FALSE_DATA_BIT) == 0; |
---|
| 422 | |
---|
| 423 | sectElement.set.ntris = 0; |
---|
| 424 | rleSection->putNextElement(§Element); |
---|
| 425 | xx++; |
---|
| 426 | } |
---|
| 427 | } |
---|
| 428 | } |
---|
| 429 | } |
---|
| 430 | } |
---|
| 431 | |
---|
| 432 | |
---|
| 433 | static void |
---|
| 434 | copyElement(Point *sect, SectionElement *elem) |
---|
| 435 | { |
---|
| 436 | sect->density = elem->density; |
---|
| 437 | sect->nx = elem->nx; |
---|
| 438 | sect->ny = elem->ny; |
---|
| 439 | sect->nz = elem->nz; |
---|
| 440 | sect->valid = elem->valid; |
---|
| 441 | sect->realData = elem->realData; |
---|
| 442 | sect->confidence = elem->confidence; |
---|
| 443 | } |
---|
| 444 | |
---|
| 445 | |
---|
| 446 | void |
---|
| 447 | computeGradients(SectionRLE **section, int level) |
---|
| 448 | { |
---|
| 449 | int yy, xx, i; |
---|
| 450 | int runType; |
---|
| 451 | RunLength length; |
---|
| 452 | SectionElement *element, *elem1, *elem2; |
---|
| 453 | |
---|
| 454 | for (yy = 1; yy < section[level]->ydim-1; yy++) { |
---|
| 455 | section[level]->setScanline(yy); |
---|
| 456 | xx = 0; |
---|
| 457 | while (TRUE) { |
---|
| 458 | |
---|
| 459 | length = section[level]->getNextLength(); |
---|
| 460 | runType = section[level]->getRunType(&length); |
---|
| 461 | |
---|
| 462 | if (runType == SectionRLE::END_OF_RUN) |
---|
| 463 | break; |
---|
| 464 | |
---|
| 465 | if (runType == SectionRLE::CONSTANT_DATA) { |
---|
| 466 | element = section[level]->getNextElement(); |
---|
| 467 | xx += length; |
---|
| 468 | } |
---|
| 469 | else { |
---|
| 470 | for (i=0; i<length; i++, xx++) { |
---|
| 471 | element = section[level]->getNextElement(); |
---|
| 472 | if (xx == 0 || xx == section[level]->xdim-1) |
---|
| 473 | continue; |
---|
| 474 | element->nx = |
---|
| 475 | -(section[level+1]->getElement(xx, yy)->density |
---|
| 476 | - section[level-1]->getElement(xx, yy)->density)/2.0/dx; |
---|
| 477 | element->ny = |
---|
| 478 | (section[level]->getElement(xx, yy+1)->density |
---|
| 479 | - section[level]->getElement(xx, yy-1)->density)/2.0/dy; |
---|
| 480 | element->nz = |
---|
| 481 | (section[level]->getElement(xx-1, yy)->density |
---|
| 482 | - section[level]->getElement(xx+1, yy)->density)/2.0/dz; |
---|
| 483 | } |
---|
| 484 | } |
---|
| 485 | } |
---|
| 486 | } |
---|
| 487 | } |
---|
| 488 | |
---|
| 489 | |
---|
| 490 | int |
---|
| 491 | loadCube(Cube cube, SectionRLE **section, int index, int xx, int yy) |
---|
| 492 | { |
---|
| 493 | copyElement(&cube[0], section[index]->getElement(xx+1,yy)); |
---|
| 494 | if (!cube[0].valid) { |
---|
| 495 | return 0; |
---|
| 496 | } |
---|
| 497 | |
---|
| 498 | copyElement(&cube[1], section[index]->getElement(xx+1,yy+1)); |
---|
| 499 | if (!cube[1].valid) |
---|
| 500 | return 0; |
---|
| 501 | |
---|
| 502 | copyElement(&cube[2], section[index]->getElement(xx,yy+1)); |
---|
| 503 | if (!cube[2].valid) |
---|
| 504 | return 0; |
---|
| 505 | |
---|
| 506 | copyElement(&cube[3], section[index]->getElement(xx,yy)); |
---|
| 507 | if (!cube[3].valid) |
---|
| 508 | return 0; |
---|
| 509 | |
---|
| 510 | copyElement(&cube[4], section[index+1]->getElement(xx+1,yy)); |
---|
| 511 | if (!cube[4].valid) |
---|
| 512 | return 0; |
---|
| 513 | |
---|
| 514 | copyElement(&cube[5], section[index+1]->getElement(xx+1,yy+1)); |
---|
| 515 | if (!cube[5].valid) |
---|
| 516 | return 0; |
---|
| 517 | |
---|
| 518 | copyElement(&cube[6], section[index+1]->getElement(xx,yy+1)); |
---|
| 519 | if (!cube[6].valid) |
---|
| 520 | return 0; |
---|
| 521 | |
---|
| 522 | copyElement(&cube[7], section[index+1]->getElement(xx,yy)); |
---|
| 523 | if (!cube[7].valid) |
---|
| 524 | return 0; |
---|
| 525 | |
---|
| 526 | return 1; |
---|
| 527 | } |
---|
| 528 | |
---|
| 529 | |
---|
| 530 | int |
---|
| 531 | loadCubeAllowPartiallyValid(Cube cube, SectionRLE **section, |
---|
| 532 | int index, int xx, int yy) |
---|
| 533 | { |
---|
| 534 | uchar valid_count = 0; |
---|
| 535 | |
---|
| 536 | copyElement(&cube[0], section[index]->getElement(xx+1,yy)); |
---|
| 537 | valid_count += cube[0].valid; |
---|
| 538 | |
---|
| 539 | copyElement(&cube[1], section[index]->getElement(xx+1,yy+1)); |
---|
| 540 | valid_count += cube[1].valid; |
---|
| 541 | |
---|
| 542 | copyElement(&cube[2], section[index]->getElement(xx,yy+1)); |
---|
| 543 | valid_count += cube[2].valid; |
---|
| 544 | |
---|
| 545 | copyElement(&cube[3], section[index]->getElement(xx,yy)); |
---|
| 546 | valid_count += cube[3].valid; |
---|
| 547 | |
---|
| 548 | copyElement(&cube[4], section[index+1]->getElement(xx+1,yy)); |
---|
| 549 | valid_count += cube[4].valid; |
---|
| 550 | |
---|
| 551 | // First early exit |
---|
| 552 | if (valid_count < 1) |
---|
| 553 | return 0; |
---|
| 554 | |
---|
| 555 | copyElement(&cube[5], section[index+1]->getElement(xx+1,yy+1)); |
---|
| 556 | valid_count += cube[5].valid; |
---|
| 557 | |
---|
| 558 | if (valid_count < 2) |
---|
| 559 | return 0; |
---|
| 560 | |
---|
| 561 | copyElement(&cube[6], section[index+1]->getElement(xx,yy+1)); |
---|
| 562 | valid_count += cube[6].valid; |
---|
| 563 | |
---|
| 564 | if (valid_count < 3) |
---|
| 565 | return 0; |
---|
| 566 | |
---|
| 567 | copyElement(&cube[7], section[index+1]->getElement(xx,yy)); |
---|
| 568 | valid_count += cube[7].valid; |
---|
| 569 | |
---|
| 570 | if (valid_count < 4) |
---|
| 571 | return 0; |
---|
| 572 | else |
---|
| 573 | return 1; |
---|
| 574 | } |
---|
| 575 | |
---|
| 576 | |
---|
| 577 | static void |
---|
| 578 | writePlyFile(char *filename, float tx, float ty, float tz) |
---|
| 579 | { |
---|
| 580 | int i, nvp; |
---|
| 581 | float version; |
---|
| 582 | PlyFile *ply; |
---|
| 583 | PlyVertex aVert; |
---|
| 584 | Vertex *vert; |
---|
| 585 | Tri *currentTri; |
---|
| 586 | PlyTri aTri; |
---|
| 587 | Vec3f norm; |
---|
| 588 | |
---|
| 589 | ply = ply_open_for_writing(filename, 2, elem_names, |
---|
| 590 | PLY_BINARY_BE, &version); |
---|
| 591 | |
---|
| 592 | nvp = 0; |
---|
| 593 | vert_props[nvp].offset = offsetof(PlyVertex, x); nvp++; |
---|
| 594 | vert_props[nvp].offset = offsetof(PlyVertex, y); nvp++; |
---|
| 595 | vert_props[nvp].offset = offsetof(PlyVertex, z); nvp++; |
---|
| 596 | |
---|
| 597 | |
---|
| 598 | vert_props[nvp].offset = offsetof(PlyVertex, confidence); nvp++; |
---|
| 599 | |
---|
| 600 | vert_props[nvp].offset = offsetof(PlyVertex, realData); nvp++; |
---|
| 601 | |
---|
| 602 | if (WriteNormals) { |
---|
| 603 | vert_props[nvp].offset = offsetof(PlyVertex, nx); nvp++; |
---|
| 604 | vert_props[nvp].offset = offsetof(PlyVertex, ny); nvp++; |
---|
| 605 | vert_props[nvp].offset = offsetof(PlyVertex, nz); nvp++; |
---|
| 606 | } |
---|
| 607 | |
---|
| 608 | |
---|
| 609 | face_props[0].offset = offsetof(PlyTri, verts); |
---|
| 610 | face_props[0].count_offset = offsetof(PlyTri, nverts); /* count offset */ |
---|
| 611 | |
---|
| 612 | ply_describe_element (ply, "vertex", numVerts, nvp, vert_props); |
---|
| 613 | |
---|
| 614 | ply_describe_element (ply, "face", numTris, 1, face_props); |
---|
| 615 | |
---|
| 616 | ply_header_complete (ply); |
---|
| 617 | |
---|
| 618 | /* set up and write the vertex elements */ |
---|
| 619 | ply_put_element_setup (ply, "vertex"); |
---|
| 620 | |
---|
| 621 | vertChunker->reset(); |
---|
| 622 | for (i = 0; i < numVerts; i++) { |
---|
| 623 | vert = (Vertex *)vertChunker->nextElem(sizeof(Vertex)); |
---|
| 624 | |
---|
| 625 | aVert.x = -vert->z + tx; |
---|
| 626 | aVert.y = vert->y + ty; |
---|
| 627 | aVert.z = -vert->x + tz; |
---|
| 628 | |
---|
| 629 | if (WriteNormals) { |
---|
| 630 | norm.setValue(vert->nz, -vert->ny, vert->nx); |
---|
| 631 | norm.normalize(); |
---|
| 632 | aVert.nx = norm.x; |
---|
| 633 | aVert.ny = norm.y; |
---|
| 634 | aVert.nz = norm.z; |
---|
| 635 | } |
---|
| 636 | |
---|
| 637 | aVert.confidence = vert->confidence; |
---|
| 638 | aVert.realData = vert->realData; |
---|
| 639 | |
---|
| 640 | ply_put_element (ply, (void *) &aVert); |
---|
| 641 | } |
---|
| 642 | |
---|
| 643 | /* set up and write the face elements */ |
---|
| 644 | ply_put_element_setup (ply, "face"); |
---|
| 645 | |
---|
| 646 | int v[3]; |
---|
| 647 | aTri.nverts = 3; |
---|
| 648 | aTri.verts = (int *)v; |
---|
| 649 | triChunker->reset(); |
---|
| 650 | for (i = 0; i < numTris; i++) { |
---|
| 651 | currentTri = (Tri *)triChunker->nextElem(sizeof(Tri)); |
---|
| 652 | |
---|
| 653 | aTri.verts[0] = currentTri->verts[1]->index; |
---|
| 654 | aTri.verts[1] = currentTri->verts[0]->index; |
---|
| 655 | aTri.verts[2] = currentTri->verts[2]->index; |
---|
| 656 | |
---|
| 657 | ply_put_element (ply, (void *) &aTri); |
---|
| 658 | } |
---|
| 659 | |
---|
| 660 | /* close the PLY file */ |
---|
| 661 | ply_close (ply); |
---|
| 662 | } |
---|