1 /*************************************************************************
2 * *
3 * Vega FEM Simulation Library Version 3.1 *
4 * *
5 * "objMesh" library , Copyright (C) 2007 CMU, 2009 MIT, 2016 USC *
6 * All rights reserved. *
7 * *
8 * Code authors: Jernej Barbic, Christopher Twigg, Daniel Schroeder *
9 * http://www.jernejbarbic.com/code *
10 * *
11 * Research: Jernej Barbic, Fun Shing Sin, Daniel Schroeder, *
12 * Doug L. James, Jovan Popovic *
13 * *
14 * Funding: National Science Foundation, Link Foundation, *
15 * Singapore-MIT GAMBIT Game Lab, *
16 * Zumberge Research and Innovation Fund at USC *
17 * *
18 * This library is free software; you can redistribute it and/or *
19 * modify it under the terms of the BSD-style license that is *
20 * included with this library in the file LICENSE.txt *
21 * *
22 * This library is distributed in the hope that it will be useful, *
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file *
25 * LICENSE.TXT for more details. *
26 * *
27 *************************************************************************/
28
29 /*
30 Author: Jernej Barbic, 2003
31 Generates a voxel representation of an offset surface
32 */
33
34 #if defined(_WIN32) || defined(WIN32)
35 #pragma warning(disable : 4996)
36 #pragma warning(disable : 4267)
37 #pragma warning(disable : 4244)
38 #endif
39 #include "objMeshOffsetVoxels.h"
40 #include "matrixIO.h"
41 #include "matrixMacros.h"
42 #include <fstream>
43 #include <iomanip>
44 #include <string.h>
45 using namespace std;
46
ObjMeshOffsetVoxels(ObjMesh * objMesh_,int resolution_[3],int depth_,Vec3d bmin_,Vec3d bmax_)47 ObjMeshOffsetVoxels::ObjMeshOffsetVoxels( ObjMesh * objMesh_, int resolution_[3], int depth_, Vec3d bmin_, Vec3d bmax_ )
48 {
49 objMesh = new ObjMesh(*objMesh_);
50 init(resolution_, depth_, bmin_, bmax_);
51 }
52
ObjMeshOffsetVoxels(ObjMesh * objMesh_,int resolution_[3],int depth_,double expansionFactor)53 ObjMeshOffsetVoxels::ObjMeshOffsetVoxels( ObjMesh * objMesh_, int resolution_[3], int depth_, double expansionFactor )
54 {
55 objMesh = new ObjMesh(*objMesh_);
56
57 // build mesh bounding box
58 Vec3d bmin_, bmax_;
59 objMesh->getCubicBoundingBox(expansionFactor, &bmin_, &bmax_);
60
61 init(resolution_, depth_, bmin_, bmax_);
62 }
63
init(int resolution_[3],int depth_,Vec3d bmin_,Vec3d bmax_)64 void ObjMeshOffsetVoxels::init(int resolution_[3], int depth_, Vec3d bmin_, Vec3d bmax_)
65 {
66 resolution[0] = resolution_[0];
67 resolution[1] = resolution_[1];
68 resolution[2] = resolution_[2];
69 depth = depth_;
70 bmin = bmin_;
71 bmax = bmax_;
72
73 //cout << "Entering obj mesh voxelization routine..." << endl;
74 //cout << "Resolution is " << resolution[0] << " x " << resolution[1] << " x " << resolution[2] << " ..." << endl;
75
76 //cout << "Checking if mesh is triangular... ";
77 if (!(objMesh->isTriangularMesh()))
78 {
79 //cout << "mesh was not triangular: triangulating... ";
80 objMesh->triangulate();
81 //cout << "done" << endl;
82 }
83 else
84 {
85 //cout << "yes" << endl;
86 }
87
88 side = bmax - bmin;
89 inc[0] = side[0] / resolution[0];
90 inc[1] = side[1] / resolution[1];
91 inc[2] = side[2] / resolution[2];
92
93 //cout << "Scene bounding box is: " << bmin << " " << bmax << endl;
94 //cout << "Computing voxels intersecting the model..." << endl;
95
96 // iterate over all triangles
97 // for every triangle, find the voxel containing its center of mass
98 // then, grow the voxels until they don't intersect the triangle any more
99
100 voxels.clear(); // will contain voxels intersecting the triangles
101
102 // local search helpers:
103 set<voxel> checkedVoxels; // used to mark what voxels have already been visited
104 vector<voxel> scheduledVoxels; // contains voxels still to be processed
105 for (unsigned int i=0; i<objMesh->getNumGroups(); i++)
106 {
107 const ObjMesh::Group * getGroupHandle = objMesh->getGroupHandle(i);
108
109 for (unsigned int j=0; j<getGroupHandle->getNumFaces(); j++)
110 {
111 Vec3d p0 = objMesh->getPosition(getGroupHandle->getFace(j).getVertex(0).getPositionIndex());
112 Vec3d p1 = objMesh->getPosition(getGroupHandle->getFace(j).getVertex(1).getPositionIndex());
113 Vec3d p2 = objMesh->getPosition(getGroupHandle->getFace(j).getVertex(2).getPositionIndex());
114 TriangleBasic triangle(p0,p1,p2);
115
116 Vec3d center = 1.0 / 3 * (p0 + p1 + p2);
117 Vec3d relCenter = center-bmin;
118
119 // find voxel containing center
120 int vi,vj,vk;
121 vi = (int)(relCenter[0] / inc[0]);
122 vj = (int)(relCenter[1] / inc[1]);
123 vk = (int)(relCenter[2] / inc[2]);
124
125 checkedVoxels.clear();
126 checkedVoxels.insert(voxel(vi,vj,vk));
127
128 scheduledVoxels.clear();
129 scheduledVoxels.push_back(voxel(vi,vj,vk));
130
131 // while there are still some scheduled voxels:
132 // take one
133 // check if intersecting the triangle
134 // if yes
135 // add voxel to voxels
136 // queue all neighbors that haven't been visited yet
137
138 while (!scheduledVoxels.empty())
139 {
140 voxel v = scheduledVoxels.back();
141 scheduledVoxels.pop_back();
142
143 // make bounding box for voxel
144 Vec3d bbmin = bmin + Vec3d(v.first * inc[0], v.second * inc[1], v.third * inc[2]);
145 BoundingBox bbox(bbmin, bbmin + inc);
146
147 if (triangle.doesIntersectBox(bbox)) // intersection test
148 {
149 // add the voxel to the final list of hits
150 voxels.insert(v);
151 // queue all neighbors of v, and also put them into checkedVoxels
152 // (but don't do anything if they have already been queued)
153 voxel neighbor;
154 #define PROCESS(ii,jj,kk)\
155 neighbor = voxel(v.first+(ii),v.second+(jj),v.third+(kk));\
156 if ((neighbor.first >= 0) && (neighbor.first <= resolution[0]) &&\
157 (neighbor.second >= 0) && (neighbor.second <= resolution[1]) &&\
158 (neighbor.third >= 0) && (neighbor.third <= resolution[2])) \
159 {\
160 if (checkedVoxels.find(neighbor) == checkedVoxels.end())\
161 {\
162 checkedVoxels.insert(neighbor);\
163 scheduledVoxels.push_back(neighbor);\
164 }\
165 }
166 for (int iii=-1; iii<=1; iii++)
167 for (int jjj=-1; jjj<=1; jjj++)
168 for (int kkk=-1; kkk<=1; kkk++)
169 {
170 if ((iii == 0) && (jjj ==0) && (kkk==0))
171 continue;
172 PROCESS(iii,jjj,kkk)
173 }
174 }
175 }
176
177 // now, voxels contains all voxels that intersect the given triangle (plus everything from previous triangles)
178 }
179 }
180
181 // now, voxels contains all voxels intersecting any triangle
182
183 //cout << "Growing " << depth << " layers of voxels out of the original (squashing cubes) layer." << endl;
184
185 // grow voxels several layers
186 set<voxel> voxeli; // temporary buffer
187 for (int i=0; i<depth; i++)
188 {
189 // expand all voxels in all directions
190 // take everything out of voxels, expand one layer, and insert into voxeli
191 voxeli.clear();
192
193 voxel neighbor;
194
195 #define PROCESSI(ii,jj,kk)\
196 neighbor = voxel(vox->first+(ii),vox->second+(jj),vox->third+(kk));\
197 if ((neighbor.first >= 0) && (neighbor.first <= resolution[0]) &&\
198 (neighbor.second >= 0) && (neighbor.second <= resolution[1]) &&\
199 (neighbor.third >= 0) && (neighbor.third <= resolution[2])) \
200 {\
201 voxeli.insert(neighbor);\
202 }
203
204 set<voxel>::iterator vox;
205
206 for (vox = voxels.begin(); vox != voxels.end(); ++vox) // over all members of voxels
207 {
208 for (int iii=-1; iii<=1; iii++)
209 for (int jjj=-1; jjj<=1; jjj++)
210 for (int kkk=-1; kkk<=1; kkk++)
211 {
212 PROCESSI(iii,jjj,kkk)
213 }
214 }
215 voxels = voxeli;
216 }
217
218 //cout << "Building unique list of faces..." << endl;
219 // build unique list of faces
220
221 buildUniqueListOfFaces();
222 }
223
emptyComponents(vector<Vec3d> & componentSeeds,vector<int> & componentSize,bool interiorOnly)224 void ObjMeshOffsetVoxels::emptyComponents(vector<Vec3d> & componentSeeds, vector<int> & componentSize, bool interiorOnly)
225 {
226 componentSeeds.clear();
227 componentSize.clear();
228
229 set<voxel> voxelSet = voxels;
230
231 for(int i=0; i<resolution[0]; i++)
232 for(int j=0; j<resolution[1]; j++)
233 for(int k=0; k<resolution[2]; k++)
234 {
235 if (voxelSet.find(voxel(i,j,k)) == voxelSet.end())
236 {
237 // new component detected
238 size_t sizePrev = voxelSet.size();
239 Vec3d seed(bmin[0] + inc[0] * ( i + 0.5 ),
240 bmin[1] + inc[1] * ( j + 0.5 ),
241 bmin[2] + inc[2] * ( k + 0.5 ));
242 bool touchesBoundingBox = floodFillFromSet(seed, voxelSet);
243 if (!(interiorOnly && touchesBoundingBox))
244 {
245 componentSize.push_back(voxelSet.size() - sizePrev);
246 componentSeeds.push_back(seed);
247 }
248 }
249 }
250 }
251
floodFill(Vec3d seed)252 void ObjMeshOffsetVoxels::floodFill(Vec3d seed)
253 {
254 //cout << "Flood-filling from seed: " << seed << endl;
255 floodFillFromSet(seed, voxels);
256 buildUniqueListOfFaces();
257 }
258
floodFill(vector<Vec3d> & seeds)259 void ObjMeshOffsetVoxels::floodFill(vector<Vec3d> & seeds)
260 {
261 for(unsigned int i=0; i<seeds.size(); i++)
262 {
263 //cout << "Flood-filling from seed: " << seeds[i] << endl;
264 floodFillFromSet(seeds[i], voxels);
265 }
266
267 buildUniqueListOfFaces();
268 }
269
floodFillFromSet(Vec3d seed,set<voxel> & voxelSet)270 bool ObjMeshOffsetVoxels::floodFillFromSet(Vec3d seed, set<voxel> & voxelSet)
271 {
272 bool touchesBoundingBox = false;
273
274 // find voxel containing seed
275 int vi,vj,vk;
276 Vec3d relSeed = seed-bmin;
277 vi = (int)(relSeed[0] / inc[0]);
278 vj = (int)(relSeed[1] / inc[1]);
279 vk = (int)(relSeed[2] / inc[2]);
280
281 if ((vi < 0) || (vi >= resolution[0]) ||
282 (vj < 0) || (vj >= resolution[1]) ||
283 (vk < 0) || (vk >= resolution[2]))
284 {
285 printf("Warning: flood-filling seed is outside the bounding box. Performing no flood-fill.\n");
286 return false;
287 }
288
289
290 voxel seedVoxel(vi,vj,vk);
291
292 set<voxel> queue;
293 queue.insert(seedVoxel);
294 voxelSet.insert(seedVoxel);
295
296 while (!queue.empty())
297 {
298 //cout << "." << flush;
299
300 voxel vox = *(queue.begin());
301 queue.erase(vox);
302
303 voxel neighbor;
304
305 //printf("vox: %d %d %d\n",vox.first,vox.second,vox.third);
306
307 // process all 8 neighbors
308 #define PROCESSNGH(ii,jj,kk)\
309 neighbor = voxel(vox.first+(ii),vox.second+(jj),vox.third+(kk));\
310 if ((neighbor.first >= 0) && (neighbor.first < resolution[0]) &&\
311 (neighbor.second >= 0) && (neighbor.second < resolution[1]) &&\
312 (neighbor.third >= 0) && (neighbor.third < resolution[2])) \
313 {\
314 if (voxelSet.find(neighbor) == voxelSet.end())\
315 {\
316 queue.insert(neighbor);\
317 voxelSet.insert(neighbor);\
318 if (!touchesBoundingBox)\
319 if ((neighbor.first == 0) || (neighbor.first == resolution[0] - 1) ||\
320 (neighbor.second == 0) || (neighbor.second == resolution[1] - 1) ||\
321 (neighbor.third == 0) || (neighbor.third == resolution[2] - 1))\
322 touchesBoundingBox = true;\
323 }\
324 }
325
326 PROCESSNGH(1,0,0);
327 PROCESSNGH(-1,0,0);
328 PROCESSNGH(0,1,0);
329 PROCESSNGH(0,-1,0);
330 PROCESSNGH(0,0,1);
331 PROCESSNGH(0,0,-1);
332 }
333
334 return touchesBoundingBox;
335 }
336
buildUniqueListOfFaces()337 void ObjMeshOffsetVoxels::buildUniqueListOfFaces()
338 {
339 surfaceFaces.clear();
340 interiorFaces.clear();
341
342 set<voxel>::iterator vox;
343 for (vox = voxels.begin(); vox != voxels.end(); ++vox) // over all members of voxels
344 {
345 // for each face of vox:
346 // if already on the list of surface faces, erase it from there, and add it among interior faces
347 // else add it among surface faces
348
349 //cout << "Voxel: " << vox->first << " " << vox->second << " " << vox->third << endl;
350
351 gridPoint pmin(vox->first,vox->second,vox->third);
352 gridPoint pmax(vox->first+1,vox->second+1,vox->third+1);
353
354 gridPoint p0(pmin.first,pmin.second,pmin.third);
355 gridPoint p1(pmax.first,pmin.second,pmin.third);
356 gridPoint p2(pmax.first,pmax.second,pmin.third);
357 gridPoint p3(pmin.first,pmax.second,pmin.third);
358
359 gridPoint p4(pmin.first,pmin.second,pmax.third);
360 gridPoint p5(pmax.first,pmin.second,pmax.third);
361 gridPoint p6(pmax.first,pmax.second,pmax.third);
362 gridPoint p7(pmin.first,pmax.second,pmax.third);
363
364 TopologicalFace * face;
365
366 #define PROCESS_FACE(q0,q1,q2,q3)\
367 face = new TopologicalFace((q0),(q1),(q2),(q3));\
368 if (surfaceFaces.find(*face) != surfaceFaces.end())\
369 {\
370 surfaceFaces.erase(*face);\
371 interiorFaces.insert(*face);\
372 }\
373 else\
374 {\
375 surfaceFaces.insert(*face);\
376 }\
377 delete(face);
378
379 PROCESS_FACE(p0,p3,p2,p1)
380 PROCESS_FACE(p4,p5,p6,p7)
381 PROCESS_FACE(p0,p1,p5,p4)
382 PROCESS_FACE(p3,p7,p6,p2)
383 PROCESS_FACE(p1,p2,p6,p5)
384 PROCESS_FACE(p0,p4,p7,p3)
385 }
386 }
387
render()388 void ObjMeshOffsetVoxels::render()
389 {
390 set<voxel>::iterator vox;
391 for (vox = voxels.begin(); vox != voxels.end(); ++vox) // over all members of voxels
392 renderVoxel(*vox);
393 }
394
renderSurfaceFaces()395 void ObjMeshOffsetVoxels::renderSurfaceFaces()
396 {
397 set<TopologicalFace,FaceOrder>::iterator face;
398
399 for (face = surfaceFaces.begin(); face != surfaceFaces.end(); ++face) // over all surface faces
400 renderTopologicalFace(*face);
401 }
402
403
404
renderVoxel(voxel vox)405 void ObjMeshOffsetVoxels::renderVoxel(voxel vox)
406 {
407 // make bounding box for voxel
408 Vec3d bbmin = bmin + Vec3d(vox.first*inc[0],vox.second*inc[1],vox.third*inc[2]);
409 BoundingBox bbox(bbmin,bbmin+inc);
410 bbox.render();
411 }
412
renderTopologicalFace(const TopologicalFace & face) const413 void ObjMeshOffsetVoxels::renderTopologicalFace(const TopologicalFace & face) const
414 {
415 // make flat bounding box
416 Vec3d bbmin = Vec3d(face.vertex(0).first*inc[0],face.vertex(0).second*inc[1],face.vertex(0).third*inc[2]);
417 bbmin += bmin;
418 Vec3d bbmax = Vec3d(face.vertex(2).first*inc[0],face.vertex(2).second*inc[1],face.vertex(2).third*inc[2]);
419 bbmax += bmin;
420 BoundingBox bbox(bbmin,bbmax);
421 bbox.render();
422 }
423
surfaceOffsetMesh()424 ObjMesh * ObjMeshOffsetVoxels::surfaceOffsetMesh()
425 {
426 ObjMesh * objMesh = new ObjMesh();
427
428 // create a list of vertices
429 set<gridPoint> vertices;
430
431 set<TopologicalFace,FaceOrder>::iterator face; // insert all vertices
432 for (face = surfaceFaces.begin(); face != surfaceFaces.end(); ++face) // over all surface faces
433 {
434 vertices.insert(face->vertex(0));
435 vertices.insert(face->vertex(1));
436 vertices.insert(face->vertex(2));
437 vertices.insert(face->vertex(3));
438 }
439
440 // now, vertices contains all vertices with no duplications
441
442 // create default group
443 objMesh->addGroup("Default");
444
445 // add all vertices into a map, together with their corresponding position
446 // also, add vertices to objMesh
447 map<gridPoint,int> vertices2;
448 set<gridPoint>:: iterator v;
449 int position=0;
450 for (v = vertices.begin(); v != vertices.end(); ++v)
451 {
452 vertices2.insert(pair<gridPoint,int>(*v,position));
453 Vec3d pos = bmin + Vec3d(v->first*inc[0], v->second*inc[1], v->third*inc[2]);
454 objMesh->addVertexPosition( pos );
455 //cout << "Position " << position << ": " << pos << endl;
456 position++;
457 }
458
459 // add all faces
460 unsigned int index;
461 for (face = surfaceFaces.begin(); face != surfaceFaces.end(); ++face) // over all surface faces
462 {
463 ObjMesh::Face newFace;
464 for (int i=0; i<4; i++)
465 {
466 index = (vertices2.find(face->vertex(i)))->second;
467
468 std::pair< bool, unsigned int > texPos(false,0); // no textures or normals assigned
469 std::pair< bool, unsigned int > normal(false,0);
470
471 newFace.addVertex( ObjMesh::Vertex( index, texPos, normal ) );
472
473 }
474 objMesh->addFaceToGroup(newFace,0);
475 }
476
477 return objMesh;
478 }
479
operator ()(const TopologicalFace & x,const TopologicalFace & y) const480 bool ObjMeshOffsetVoxels::FaceOrder::operator()(const TopologicalFace & x, const TopologicalFace & y) const
481 {
482
483 // first, sort the vertices on each face (order of vertices is irrelevant when comparing if two faces are equal)
484 TopologicalFace xSorted = x; xSorted.sortVertices();
485 TopologicalFace ySorted = y; ySorted.sortVertices();
486
487 for (int i=0; i<4; i++)
488 {
489 gridPoint x1 = xSorted.vertex(i);
490 gridPoint y1 = ySorted.vertex(i);
491
492 if (x1 < y1)
493 return true;
494 if (y1 < x1)
495 return false;
496 }
497
498 return false;
499 }
500
TopologicalFace(gridPoint p1,gridPoint p2,gridPoint p3,gridPoint p4)501 ObjMeshOffsetVoxels::TopologicalFace::TopologicalFace(gridPoint p1, gridPoint p2, gridPoint p3, gridPoint p4)
502 {
503 vertices_.push_back(p1); vertices_.push_back(p2); vertices_.push_back(p3); vertices_.push_back(p4);
504
505 assert(vertices_.size() == 4);
506 }
507
sortVertices()508 void ObjMeshOffsetVoxels::TopologicalFace::sortVertices()
509 {
510 sort(vertices_.begin(),vertices_.end());
511
512 // sanity check
513 unique(vertices_.begin(),vertices_.end());
514 assert(vertices_.size() == 4);
515 }
516
generateCubicMesh(const string & filenameVeg,const string & filenameInterp,const string & filenameObj)517 void ObjMeshOffsetVoxels::generateCubicMesh(const string & filenameVeg, const string & filenameInterp, const string & filenameObj)
518 {
519 cout << "Generating cubic mesh..." << endl;
520 cout << "Writing mesh to " << filenameVeg << " ." << endl;
521
522 // open file
523 ofstream fout(filenameVeg.c_str());
524
525 if (!fout)
526 {
527 cout << "Error: could not write to file " << filenameVeg << endl;
528 return;
529 }
530
531 // create a list of vertices in all voxels
532 set<gridPoint> vertices;
533 // insert all voxel vertices
534 set<voxel>::iterator aVoxel;
535 for (aVoxel = voxels.begin(); aVoxel != voxels.end(); ++aVoxel) // over all voxels
536 {
537 unsigned int i1,j1,k1;
538 i1 = aVoxel->first;
539 j1 = aVoxel->second;
540 k1 = aVoxel->third;
541
542 vertices.insert(gridPoint(i1,j1,k1));
543 vertices.insert(gridPoint(i1+1,j1,k1));
544 vertices.insert(gridPoint(i1+1,j1+1,k1));
545 vertices.insert(gridPoint(i1,j1+1,k1));
546
547 vertices.insert(gridPoint(i1,j1,k1+1));
548 vertices.insert(gridPoint(i1+1,j1,k1+1));
549 vertices.insert(gridPoint(i1+1,j1+1,k1+1));
550 vertices.insert(gridPoint(i1,j1+1,k1+1));
551 }
552
553 // now, vertices contains all voxel vertices with no duplications
554
555 cout << "Num voxels: " << voxels.size() << " Num voxel vertices: " << vertices.size() << endl;
556
557 // open up the objMesh for the output surface mesh
558 ObjMesh * objMesh = new ObjMesh();
559
560 // create default group
561 objMesh->addGroup("Default");
562
563 // add all voxel vertices into a map, together with their corresponding index (i.e. serial number of a voxel vertex in the set order)
564 map<gridPoint,int> vertices2;
565 set<gridPoint>:: iterator v; // will run over all voxel vertices
566 int position=0;
567
568 fout << "*VERTICES" << endl;
569 fout << (int)vertices.size() << " 3 0 0" << endl;
570
571 for (v = vertices.begin(); v != vertices.end(); ++v)
572 {
573 vertices2.insert(pair<gridPoint,int>(*v,position));
574 Vec3d pos = bmin + Vec3d(v->first*inc[0], v->second*inc[1], v->third*inc[2]);
575 objMesh->addVertexPosition(pos);
576
577 //cout << "Position " << position << ": " << pos << endl;
578 position++;
579
580 // write vertex to file
581 fout << setprecision (16) << position << " " << pos[0] << " " << pos[1] << " " << pos[2] << endl;
582 }
583
584 fout << endl;
585 fout << "*ELEMENTS" << endl;
586 fout << "CUBIC" << endl;
587 fout << (int)voxels.size() << " 4 0" << endl;
588
589 // print out all voxels
590 unsigned int index;
591 position = 0;
592 for (aVoxel = voxels.begin(); aVoxel != voxels.end(); ++aVoxel) // over all voxels
593 {
594 fout << position+1;
595 unsigned int i1,j1,k1;
596 i1 = aVoxel->first;
597 j1 = aVoxel->second;
598 k1 = aVoxel->third;
599
600 #define PROCESS_CORNER(di,dj,dk)\
601 index = 1+(vertices2.find(gridPoint(i1+(di),j1+(dj),k1+(dk))))->second;\
602 fout << " " << index;
603
604 PROCESS_CORNER(0,0,0);
605 PROCESS_CORNER(1,0,0);
606 PROCESS_CORNER(1,1,0);
607 PROCESS_CORNER(0,1,0);
608 PROCESS_CORNER(0,0,1);
609 PROCESS_CORNER(1,0,1);
610 PROCESS_CORNER(1,1,1);
611 PROCESS_CORNER(0,1,1);
612
613 fout << endl;
614
615 position++;
616 }
617
618 fout.close();
619
620 // generate the barycentric masks
621
622 cout << "Writing interpolation info to file " << filenameInterp << " ." << endl;
623
624 // open file
625 fout.open(filenameInterp.c_str());
626
627 if (!fout)
628 {
629 cout << "Error: could not write to file " << filenameInterp << endl;
630 return;
631 }
632
633 // for every vertex of the mesh, find what voxel it is in
634 // then find indices of the vertices of that voxel
635 // and compute the barycentric coordinates
636
637 for (unsigned int i=0; i < objMesh->getNumVertices(); i++) // over all vertices of the mesh
638 {
639 Vec3d pos = objMesh->getPosition(i);
640 unsigned int i1,j1,k1;
641
642 Vec3d relPos = pos-bmin;
643
644 // find voxel containing 'pos'
645 i1 = (unsigned int)(relPos[0] / inc[0]);
646 j1 = (unsigned int)(relPos[1] / inc[1]);
647 k1 = (unsigned int)(relPos[2] / inc[2]);
648
649 // compute barycentric coordinates
650 Vec3d w = pos - (bmin + Vec3d(i1 * inc[0], j1 * inc[1], k1 * inc[2]));
651 double alpha = w[0] / inc[0];
652 double beta = w[1] / inc[1];
653 double gamma = w[2] / inc[2];
654
655 unsigned int c000 = vertices2.find(gridPoint(i1+0,j1+0,k1+0))->second;
656 unsigned int c100 = vertices2.find(gridPoint(i1+1,j1+0,k1+0))->second;
657 unsigned int c110 = vertices2.find(gridPoint(i1+1,j1+1,k1+0))->second;
658 unsigned int c010 = vertices2.find(gridPoint(i1+0,j1+1,k1+0))->second;
659
660 unsigned int c001 = vertices2.find(gridPoint(i1+0,j1+0,k1+1))->second;
661 unsigned int c101 = vertices2.find(gridPoint(i1+1,j1+0,k1+1))->second;
662 unsigned int c111 = vertices2.find(gridPoint(i1+1,j1+1,k1+1))->second;
663 unsigned int c011 = vertices2.find(gridPoint(i1+0,j1+1,k1+1))->second;
664
665 double f000 = (1-alpha)*(1-beta)*(1-gamma);
666 double f100 = (alpha)*(1-beta)*(1-gamma);
667 double f110 = (alpha)*(beta)*(1-gamma);
668 double f010 = (1-alpha)*(beta)*(1-gamma);
669
670 double f001 = (1-alpha)*(1-beta)*(gamma);
671 double f101 = (alpha)*(1-beta)*(gamma);
672 double f111 = (alpha)*(beta)*(gamma);
673 double f011 = (1-alpha)*(beta)*(gamma);
674
675 fout << i << " ";
676
677 fout << c000 << " " << f000 << " ";
678 fout << c100 << " " << f100 << " ";
679 fout << c110 << " " << f110 << " ";
680 fout << c010 << " " << f010 << " ";
681
682 fout << c001 << " " << f001 << " ";
683 fout << c101 << " " << f101 << " ";
684 fout << c111 << " " << f111 << " ";
685 fout << c011 << " " << f011 << endl;
686 }
687
688 fout.close();
689
690 // by now, surfaceFaces contains a unique list of all surface faces
691 // add all faces to the surface obj mesh of the voxel mesh
692 set<TopologicalFace,FaceOrder>::iterator face;
693 for (face = surfaceFaces.begin(); face != surfaceFaces.end(); ++face) // all surface faces
694 {
695 int index[4];
696 for (int i=0; i<4; i++)
697 index[i] = (vertices2.find(face->vertex(i)))->second;
698
699 std::pair< bool, unsigned int > texPos(false,0); // no textures
700 std::pair< bool, unsigned int > normal(false,0); // no normals
701
702 /*
703 // triangulate the face into two triangles
704
705 Face newFace1;
706 newFace1.addVertex( Vertex( index[0], texPos, normal ) );
707 newFace1.addVertex( Vertex( index[1], texPos, normal ) );
708 newFace1.addVertex( Vertex( index[2], texPos, normal ) );
709
710 Face newFace2;
711 newFace2.addVertex( Vertex( index[2], texPos, normal ) );
712 newFace2.addVertex( Vertex( index[3], texPos, normal ) );
713 newFace2.addVertex( Vertex( index[0], texPos, normal ) );
714
715 objMesh->addFaceToGroup(newFace1,0);
716 objMesh->addFaceToGroup(newFace2,0);
717 */
718
719 // make one quad face
720
721 ObjMesh::Face newFace;
722 newFace.addVertex( ObjMesh::Vertex( index[0], texPos, normal ) );
723 newFace.addVertex( ObjMesh::Vertex( index[1], texPos, normal ) );
724 newFace.addVertex( ObjMesh::Vertex( index[2], texPos, normal ) );
725 newFace.addVertex( ObjMesh::Vertex( index[3], texPos, normal ) );
726
727 objMesh->addFaceToGroup(newFace,0);
728 }
729
730 // search if there already is "default" material; if there is not, add it
731 objMesh->addDefaultMaterial();
732 objMesh->computeBoundingBox();
733
734 objMesh->save(filenameObj);
735
736 delete(objMesh);
737 }
738
generateCubicMesh(int * numCubeVertices,double ** cubeVertices,int * numCubes,int ** cubes,int ** interpolationVertices,double ** interpolationWeights,ObjMesh ** surfaceMesh)739 void ObjMeshOffsetVoxels::generateCubicMesh(int * numCubeVertices, double ** cubeVertices, int * numCubes, int ** cubes, int ** interpolationVertices, double ** interpolationWeights, ObjMesh ** surfaceMesh)
740 {
741 //cout << "Generating cubic mesh..." << endl;
742
743 // create a list of vertices in all voxels
744 set<gridPoint> vertices;
745 // insert all voxel vertices
746 set<voxel>::iterator aVoxel;
747 for (aVoxel = voxels.begin(); aVoxel != voxels.end(); ++aVoxel) // over all voxels
748 {
749 unsigned int i1,j1,k1;
750 i1 = aVoxel->first;
751 j1 = aVoxel->second;
752 k1 = aVoxel->third;
753
754 vertices.insert(gridPoint(i1,j1,k1));
755 vertices.insert(gridPoint(i1+1,j1,k1));
756 vertices.insert(gridPoint(i1+1,j1+1,k1));
757 vertices.insert(gridPoint(i1,j1+1,k1));
758
759 vertices.insert(gridPoint(i1,j1,k1+1));
760 vertices.insert(gridPoint(i1+1,j1,k1+1));
761 vertices.insert(gridPoint(i1+1,j1+1,k1+1));
762 vertices.insert(gridPoint(i1,j1+1,k1+1));
763 }
764
765 // now, "vertices" contains all voxel vertices with no duplications
766 //cout << "Num voxels: " << voxels.size() << " Num voxel vertices: " << vertices.size() << endl;
767
768 // creates an empty objMesh (for the output surface mesh)
769 *surfaceMesh = new ObjMesh();
770
771 // create default group
772 (*surfaceMesh)->addGroup("Default");
773
774 // add all voxel vertices into a map, together with their corresponding index (i.e. serial number of a voxel vertex in the set order)
775 map<gridPoint,int> vertices2;
776 set<gridPoint>:: iterator v; // will run over all voxel vertices
777
778 int position=0;
779 *numCubeVertices = vertices.size();
780 *cubeVertices = (double*) malloc (sizeof(double) * 3 * vertices.size());
781 for (v = vertices.begin(); v != vertices.end(); ++v)
782 {
783 vertices2.insert(pair<gridPoint,int>(*v,position));
784 Vec3d pos = bmin + Vec3d(v->first*inc[0], v->second*inc[1], v->third*inc[2]);
785 (*surfaceMesh)->addVertexPosition(pos);
786
787 (*cubeVertices)[3*position+0] = pos[0];
788 (*cubeVertices)[3*position+1] = pos[1];
789 (*cubeVertices)[3*position+2] = pos[2];
790
791 //cout << "Position " << position << ": " << pos << endl;
792 position++;
793 }
794
795 unsigned int index;
796 position = 0;
797 *numCubes = voxels.size();
798 *cubes = (int*) malloc (sizeof(int) * voxels.size() * 8);
799 for (aVoxel = voxels.begin(); aVoxel != voxels.end(); ++aVoxel) // over all voxels
800 {
801 unsigned int i1,j1,k1;
802 i1 = aVoxel->first;
803 j1 = aVoxel->second;
804 k1 = aVoxel->third;
805
806 #define PROCESS_CORNER_SHORT(di,dj,dk)\
807 index = (vertices2.find(gridPoint(i1+(di),j1+(dj),k1+(dk))))->second;
808
809 PROCESS_CORNER_SHORT(0,0,0); (*cubes)[8*position+0] = index;
810 PROCESS_CORNER_SHORT(1,0,0); (*cubes)[8*position+1] = index;
811 PROCESS_CORNER_SHORT(1,1,0); (*cubes)[8*position+2] = index;
812 PROCESS_CORNER_SHORT(0,1,0); (*cubes)[8*position+3] = index;
813 PROCESS_CORNER_SHORT(0,0,1); (*cubes)[8*position+4] = index;
814 PROCESS_CORNER_SHORT(1,0,1); (*cubes)[8*position+5] = index;
815 PROCESS_CORNER_SHORT(1,1,1); (*cubes)[8*position+6] = index;
816 PROCESS_CORNER_SHORT(0,1,1); (*cubes)[8*position+7] = index;
817
818 position++;
819 }
820
821 // generate the barycentric masks
822
823 // for every vertex of the mesh, find what voxel it is in
824 // then, find indices of the vertices of that voxel
825 // and compute the barycentric coordinates
826
827 *interpolationVertices = (int*) malloc (sizeof(int) * 8 * objMesh->getNumVertices());
828 *interpolationWeights = (double*) malloc (sizeof(double) * 8 * objMesh->getNumVertices());
829
830 for (unsigned int i=0; i < objMesh->getNumVertices(); i++) // over all vertices of the mesh
831 {
832 Vec3d pos = objMesh->getPosition(i);
833 unsigned int i1,j1,k1;
834
835 Vec3d relPos = pos-bmin;
836
837 // find voxel containing 'pos'
838 i1 = (unsigned int)(relPos[0] / inc[0]);
839 j1 = (unsigned int)(relPos[1] / inc[1]);
840 k1 = (unsigned int)(relPos[2] / inc[2]);
841
842 // compute barycentric coordinates
843 Vec3d w = pos - (bmin + Vec3d(i1 * inc[0], j1 * inc[1], k1 * inc[2]));
844 double alpha = w[0] / inc[0];
845 double beta = w[1] / inc[1];
846 double gamma = w[2] / inc[2];
847
848 unsigned int c000, c100, c110, c010, c001, c101, c111, c011;
849 unsigned int * cArray[8] = { &c000, &c100, &c110, &c010, &c001, &c101, &c111, &c011 };
850 int offset[8][3] = { {0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 1, 1} };
851 for(int j=0; j<8; j++)
852 {
853 map<gridPoint,int> :: iterator iter = vertices2.find(gridPoint(i1 + offset[j][0], j1 + offset[j][1], k1 + offset[j][2]));
854 if (iter != vertices2.end())
855 *(cArray[j]) = iter->second;
856 else
857 *(cArray[j]) = 0; // handle case where vertex is at the boundary of a voxel and round-off may move it to a non-existing voxel (barycentric coordinate is zero in this case)
858 }
859
860 //unsigned int c000 = vertices2.find(gridPoint(i1+0,j1+0,k1+0))->second;
861 //unsigned int c100 = vertices2.find(gridPoint(i1+1,j1+0,k1+0))->second;
862 //unsigned int c110 = vertices2.find(gridPoint(i1+1,j1+1,k1+0))->second;
863 //unsigned int c010 = vertices2.find(gridPoint(i1+0,j1+1,k1+0))->second;
864
865 //unsigned int c001 = vertices2.find(gridPoint(i1+0,j1+0,k1+1))->second;
866 //unsigned int c101 = vertices2.find(gridPoint(i1+1,j1+0,k1+1))->second;
867 //unsigned int c111 = vertices2.find(gridPoint(i1+1,j1+1,k1+1))->second;
868 //unsigned int c011 = vertices2.find(gridPoint(i1+0,j1+1,k1+1))->second;
869
870 double f000 = (1-alpha)*(1-beta)*(1-gamma);
871 double f100 = (alpha)*(1-beta)*(1-gamma);
872 double f110 = (alpha)*(beta)*(1-gamma);
873 double f010 = (1-alpha)*(beta)*(1-gamma);
874
875 double f001 = (1-alpha)*(1-beta)*(gamma);
876 double f101 = (alpha)*(1-beta)*(gamma);
877 double f111 = (alpha)*(beta)*(gamma);
878 double f011 = (1-alpha)*(beta)*(gamma);
879
880 (*interpolationVertices)[8*i+0] = c000;
881 (*interpolationVertices)[8*i+1] = c100;
882 (*interpolationVertices)[8*i+2] = c110;
883 (*interpolationVertices)[8*i+3] = c010;
884 (*interpolationVertices)[8*i+4] = c001;
885 (*interpolationVertices)[8*i+5] = c101;
886 (*interpolationVertices)[8*i+6] = c111;
887 (*interpolationVertices)[8*i+7] = c011;
888
889 (*interpolationWeights)[8*i+0] = f000;
890 (*interpolationWeights)[8*i+1] = f100;
891 (*interpolationWeights)[8*i+2] = f110;
892 (*interpolationWeights)[8*i+3] = f010;
893 (*interpolationWeights)[8*i+4] = f001;
894 (*interpolationWeights)[8*i+5] = f101;
895 (*interpolationWeights)[8*i+6] = f111;
896 (*interpolationWeights)[8*i+7] = f011;
897 }
898
899 // by now, surfaceFaces contains a unique list of all surface faces
900 // add all faces to the surface obj mesh of the voxel mesh
901 set<TopologicalFace,FaceOrder>::iterator face;
902 for (face = surfaceFaces.begin(); face != surfaceFaces.end(); ++face) // all surface faces
903 {
904 int index[4];
905 for (int i=0; i<4; i++)
906 index[i] = (vertices2.find(face->vertex(i)))->second;
907
908 std::pair< bool, unsigned int > texPos(false,0); // no textures
909 std::pair< bool, unsigned int > normal(false,0); // no normals
910
911 /*
912 // triangulate the face into two triangles
913
914 Face newFace1;
915 newFace1.addVertex( Vertex( index[0], texPos, normal ) );
916 newFace1.addVertex( Vertex( index[1], texPos, normal ) );
917 newFace1.addVertex( Vertex( index[2], texPos, normal ) );
918
919 Face newFace2;
920 newFace2.addVertex( Vertex( index[2], texPos, normal ) );
921 newFace2.addVertex( Vertex( index[3], texPos, normal ) );
922 newFace2.addVertex( Vertex( index[0], texPos, normal ) );
923
924 objMesh->addFaceToGroup(newFace1,0);
925 objMesh->addFaceToGroup(newFace2,0);
926 */
927
928 // make one quad face
929
930 ObjMesh::Face newFace;
931 newFace.addVertex( ObjMesh::Vertex( index[0], texPos, normal ) );
932 newFace.addVertex( ObjMesh::Vertex( index[1], texPos, normal ) );
933 newFace.addVertex( ObjMesh::Vertex( index[2], texPos, normal ) );
934 newFace.addVertex( ObjMesh::Vertex( index[3], texPos, normal ) );
935
936 (*surfaceMesh)->addFaceToGroup(newFace,0);
937 }
938
939 // search if there already is "default" material; if there is not, add it
940 (*surfaceMesh)->addDefaultMaterial();
941
942 (*surfaceMesh)->computeBoundingBox();
943 }
944
generateInterpolationMasks(const string & filenameInterp,const string & inputObjMesh)945 void ObjMeshOffsetVoxels::generateInterpolationMasks(const string & filenameInterp, const string & inputObjMesh)
946 {
947 cout << "Generating interpolation masks for the external file " << inputObjMesh << endl;
948
949 // create a list of vertices in all voxels
950 set<gridPoint> vertices;
951
952 // insert all voxel vertices
953 set<voxel>::iterator aVoxel;
954 for (aVoxel = voxels.begin(); aVoxel != voxels.end(); ++aVoxel) // over all voxels
955 {
956 unsigned int i1,j1,k1;
957 i1 = aVoxel->first;
958 j1 = aVoxel->second;
959 k1 = aVoxel->third;
960
961 vertices.insert(gridPoint(i1,j1,k1));
962 vertices.insert(gridPoint(i1+1,j1,k1));
963 vertices.insert(gridPoint(i1+1,j1+1,k1));
964 vertices.insert(gridPoint(i1,j1+1,k1));
965
966 vertices.insert(gridPoint(i1,j1,k1+1));
967 vertices.insert(gridPoint(i1+1,j1,k1+1));
968 vertices.insert(gridPoint(i1+1,j1+1,k1+1));
969 vertices.insert(gridPoint(i1,j1+1,k1+1));
970 }
971
972 // now, vertices contains all voxel vertices with no duplications
973
974 // add all voxel vertices into a map, together with their corresponding index (i.e. serial number of a voxel vertex in the set order)
975 map<gridPoint,int> vertices2;
976 set<gridPoint>:: iterator v; // will run over all voxel vertices
977 int position=0;
978 for (v = vertices.begin(); v != vertices.end(); ++v)
979 {
980 vertices2.insert(pair<gridPoint,int>(*v,position));
981 //Vec3d pos = bmin + Vec3d(v->first*inc[0], v->second*inc[1], v->third*inc[2]);
982 //cout << "Position " << position << ": " << pos << endl;
983 position++;
984 }
985
986 // generate the barycentric masks
987
988 cout << "Writing interpolation info to file " << filenameInterp << " ." << endl;
989
990 // open file
991 ofstream fout(filenameInterp.c_str());
992
993 if (!fout)
994 {
995 cout << "Error: could not write to file " << filenameInterp << endl;
996 return;
997 }
998
999 // for every vertex of the mesh, find what voxel it is in
1000 // then find indices of the vertices of that voxel
1001 // and compute the barycentric coordinates
1002
1003 ObjMesh inputMesh(inputObjMesh);
1004
1005 // will contain all voxels that contain at least one vertex of the external mesh
1006 set<voxel> visitedVoxels;
1007
1008 cout << "Processing vertices of the external mesh file..." << endl;
1009 for (unsigned int i=0; i < inputMesh.getNumVertices(); i++) // over all vertices of the mesh
1010 {
1011 if (i % 100 == 0)
1012 cout << i << " " << flush;
1013
1014 Vec3d pos = inputMesh.getPosition(i);
1015 unsigned int i1,j1,k1;
1016
1017 Vec3d relPos = pos-bmin;
1018
1019 // find voxel containing 'pos'
1020 i1 = (unsigned int)(relPos[0] / inc[0]);
1021 j1 = (unsigned int)(relPos[1] / inc[1]);
1022 k1 = (unsigned int)(relPos[2] / inc[2]);
1023
1024 // store voxel so that we can later print out a list of visited voxels
1025 visitedVoxels.insert(voxel(i1,j1,k1));
1026
1027 // compute barycentric coordinates
1028 Vec3d w = pos - (bmin + Vec3d(i1 * inc[0], j1 * inc[1], k1 * inc[2]));
1029 double alpha = w[0] / inc[0];
1030 double beta = w[1] / inc[1];
1031 double gamma = w[2] / inc[2];
1032
1033 map<gridPoint,int> :: iterator voxelVertexEntry;
1034
1035 voxelVertexEntry = vertices2.find(gridPoint(i1+0,j1+0,k1+0));
1036 if (voxelVertexEntry == vertices2.end())
1037 {
1038 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 000" << endl;
1039 return;
1040 }
1041 unsigned int c000 = voxelVertexEntry->second;
1042
1043 voxelVertexEntry = vertices2.find(gridPoint(i1+1,j1+0,k1+0));
1044 if (voxelVertexEntry == vertices2.end())
1045 {
1046 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 100" << endl;
1047 return;
1048 }
1049 unsigned int c100 = voxelVertexEntry->second;
1050
1051 voxelVertexEntry = vertices2.find(gridPoint(i1+1,j1+1,k1+0));
1052 if (voxelVertexEntry == vertices2.end())
1053 {
1054 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 110" << endl;
1055 return;
1056 }
1057 unsigned int c110 = voxelVertexEntry->second;
1058
1059 voxelVertexEntry = vertices2.find(gridPoint(i1+0,j1+1,k1+0));
1060 if (voxelVertexEntry == vertices2.end())
1061 {
1062 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 010" << endl;
1063 return;
1064 }
1065 unsigned int c010 = voxelVertexEntry->second;
1066
1067 voxelVertexEntry = vertices2.find(gridPoint(i1+0,j1+0,k1+1));
1068 if (voxelVertexEntry == vertices2.end())
1069 {
1070 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 001" << endl;
1071 return;
1072 }
1073 unsigned int c001 = voxelVertexEntry->second;
1074
1075 voxelVertexEntry = vertices2.find(gridPoint(i1+1,j1+0,k1+1));
1076 if (voxelVertexEntry == vertices2.end())
1077 {
1078 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 101" << endl;
1079 return;
1080 }
1081 unsigned int c101 = voxelVertexEntry->second;
1082
1083 voxelVertexEntry = vertices2.find(gridPoint(i1+1,j1+1,k1+1));
1084 if (voxelVertexEntry == vertices2.end())
1085 {
1086 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 111" << endl;
1087 return;
1088 }
1089 unsigned int c111 = voxelVertexEntry->second;
1090
1091 voxelVertexEntry = vertices2.find(gridPoint(i1+0,j1+1,k1+1));
1092 if (voxelVertexEntry == vertices2.end())
1093 {
1094 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 011" << endl;
1095 return;
1096 }
1097 unsigned int c011 = voxelVertexEntry->second;
1098
1099 /*
1100 unsigned int c000 = vertices2.find(gridPoint(i1+0,j1+0,k1+0))->second;
1101 unsigned int c100 = vertices2.find(gridPoint(i1+1,j1+0,k1+0))->second;
1102 unsigned int c110 = vertices2.find(gridPoint(i1+1,j1+1,k1+0))->second;
1103 unsigned int c010 = vertices2.find(gridPoint(i1+0,j1+1,k1+0))->second;
1104
1105 unsigned int c001 = vertices2.find(gridPoint(i1+0,j1+0,k1+1))->second;
1106 unsigned int c101 = vertices2.find(gridPoint(i1+1,j1+0,k1+1))->second;
1107 unsigned int c111 = vertices2.find(gridPoint(i1+1,j1+1,k1+1))->second;
1108 unsigned int c011 = vertices2.find(gridPoint(i1+0,j1+1,k1+1))->second;
1109 */
1110 double f000 = (1-alpha)*(1-beta)*(1-gamma);
1111 double f100 = (alpha)*(1-beta)*(1-gamma);
1112 double f110 = (alpha)*(beta)*(1-gamma);
1113 double f010 = (1-alpha)*(beta)*(1-gamma);
1114
1115 double f001 = (1-alpha)*(1-beta)*(gamma);
1116 double f101 = (alpha)*(1-beta)*(gamma);
1117 double f111 = (alpha)*(beta)*(gamma);
1118 double f011 = (1-alpha)*(beta)*(gamma);
1119
1120 fout << i << " ";
1121
1122 fout << c000 << " " << f000 << " ";
1123 fout << c100 << " " << f100 << " ";
1124 fout << c110 << " " << f110 << " ";
1125 fout << c010 << " " << f010 << " ";
1126
1127 fout << c001 << " " << f001 << " ";
1128 fout << c101 << " " << f101 << " ";
1129 fout << c111 << " " << f111 << " ";
1130 fout << c011 << " " << f011 << endl;
1131 }
1132
1133 fout.close();
1134
1135 // print out indices of all voxels that contain vertices of the external mesh
1136 int index=1;
1137 int lineCounter = 0;
1138 printf("\nVoxels that contain vertices of the given external mesh:\n");
1139 for (aVoxel = voxels.begin(); aVoxel != voxels.end(); ++aVoxel) // over all voxels
1140 {
1141 unsigned int i1,j1,k1;
1142 i1 = aVoxel->first;
1143 j1 = aVoxel->second;
1144 k1 = aVoxel->third;
1145
1146 // seek for (i1,j1,k1) in the list of all voxels
1147 if (visitedVoxels.find(voxel(i1,j1,k1)) != visitedVoxels.end())
1148 {
1149 printf("%d,",index);
1150 lineCounter++;
1151 }
1152
1153 if (lineCounter >= 8)
1154 {
1155 lineCounter = 0;
1156 printf("\n");
1157 }
1158
1159 index++;
1160 }
1161 printf("\n");
1162
1163 index=1;
1164 lineCounter = 0;
1165 printf("\nVoxels that DO NOT contain vertices of the given external mesh:\n");
1166 for (aVoxel = voxels.begin(); aVoxel != voxels.end(); ++aVoxel) // over all voxels
1167 {
1168 unsigned int i1,j1,k1;
1169 i1 = aVoxel->first;
1170 j1 = aVoxel->second;
1171 k1 = aVoxel->third;
1172
1173 // seek for (i1,j1,k1) in the list of all voxels
1174 if (visitedVoxels.find(voxel(i1,j1,k1)) == visitedVoxels.end())
1175 {
1176 printf("%d,",index);
1177 lineCounter++;
1178 }
1179
1180 if (lineCounter >= 8)
1181 {
1182 lineCounter = 0;
1183 printf("\n");
1184 }
1185
1186 index++;
1187 }
1188 printf("\n");
1189
1190 cout << endl << "Total voxels: " << voxels.size() << " Successful termination." << endl;
1191 }
1192
1193 // generates the normal correction matrix for the vertices from the external file 'inputObjMesh'
generateNormalCorrectionMatrix(const string filenameCorrectionMatrix,const string inputObjMesh,const string filenameVoxelModalMatrix,const string filenameNormals)1194 void ObjMeshOffsetVoxels::generateNormalCorrectionMatrix(const string filenameCorrectionMatrix, const string inputObjMesh, const string filenameVoxelModalMatrix, const string filenameNormals)
1195 {
1196 cout << "Generating normal correction matrix for the external file " << inputObjMesh << endl;
1197
1198 // create a list of vertices in all voxels
1199 set<gridPoint> vertices;
1200
1201 // insert all voxel vertices
1202 set<voxel>::iterator aVoxel;
1203 for (aVoxel = voxels.begin(); aVoxel != voxels.end(); ++aVoxel) // over all voxels
1204 {
1205 unsigned int i1,j1,k1;
1206 i1 = aVoxel->first;
1207 j1 = aVoxel->second;
1208 k1 = aVoxel->third;
1209
1210 vertices.insert(gridPoint(i1,j1,k1));
1211 vertices.insert(gridPoint(i1+1,j1,k1));
1212 vertices.insert(gridPoint(i1+1,j1+1,k1));
1213 vertices.insert(gridPoint(i1,j1+1,k1));
1214
1215 vertices.insert(gridPoint(i1,j1,k1+1));
1216 vertices.insert(gridPoint(i1+1,j1,k1+1));
1217 vertices.insert(gridPoint(i1+1,j1+1,k1+1));
1218 vertices.insert(gridPoint(i1,j1+1,k1+1));
1219 }
1220
1221 // now, vertices contains all voxel vertices with no duplications
1222
1223 // add all voxel vertices into a map, together with their corresponding index (i.e. serial number of a voxel vertex in the set order)
1224 map<gridPoint,int> vertices2;
1225 set<gridPoint>:: iterator v; // will run over all voxel vertices
1226 int position=0;
1227 for (v = vertices.begin(); v != vertices.end(); ++v)
1228 {
1229 vertices2.insert(pair<gridPoint,int>(*v,position));
1230 //Vec3d pos = bmin + Vec3d(v->first*inc[0], v->second*inc[1], v->third*inc[2]);
1231 //cout << "Position " << position << ": " << pos << endl;
1232 position++;
1233 }
1234
1235 // === load the voxel modal matrix
1236 cout << "Loading the voxel modal matrix " << filenameVoxelModalMatrix << " ." << endl;
1237
1238 int nVoxel,r;
1239 double * voxelModalMatrix;
1240 ReadMatrixFromDisk_((char*)filenameVoxelModalMatrix.c_str(), &nVoxel, &r, &voxelModalMatrix);
1241 nVoxel /= 3;
1242 Assert_(nVoxel,vertices.size(),1);
1243
1244 // === load normals
1245
1246 FILE * fin;
1247 OpenFile_((char*)filenameNormals.c_str(),&fin,"r");
1248
1249 int numNormals;
1250 if (fscanf(fin,"%d\n",&numNormals) < 1)
1251 printf("Warning: bad input file syntax. Unable to read the number of normals.\n");
1252
1253 vector<Vec3d> normals;
1254 for(int i=0; i<numNormals; i++)
1255 {
1256 double nx,ny,nz;
1257 if (fscanf(fin,"%lf %lf %lf\n",&nx,&ny,&nz) < 3)
1258 printf("Warning: bad input file syntax. Unable to read normals.\n");
1259 normals.push_back(Vec3d(nx,ny,nz));
1260 }
1261
1262 fclose(fin);
1263
1264 // === generate the normal correction matrix
1265
1266 cout << "Loading the external file " << inputObjMesh << " ." << endl;
1267
1268 ObjMesh inputMesh(inputObjMesh);
1269
1270 cout << "Generating the normal correction matrix..." << endl;
1271
1272 int n = inputMesh.getNumVertices();
1273
1274 Assert_(n, numNormals, 2);
1275
1276 double * outputMatrix = (double*) malloc (sizeof(double) * 3 * n * r);
1277
1278 // for every vertex of the mesh, find what voxel it is in
1279 // then find indices of the vertices of that voxel
1280 // and compute the barycentric coordinates
1281 // the assemble the normal matrix correction
1282
1283 cout << "Processing vertices of the external mesh file..." << endl;
1284 for (unsigned int i=0; i < inputMesh.getNumVertices(); i++) // over all vertices of the mesh
1285 {
1286 if (i % 100 == 0)
1287 cout << i << " " << flush;
1288
1289 Vec3d pos = inputMesh.getPosition(i);
1290 unsigned int i1,j1,k1;
1291
1292 Vec3d relPos = pos-bmin;
1293
1294 // find voxel containing 'pos'
1295 i1 = (unsigned int)(relPos[0] / inc[0]);
1296 j1 = (unsigned int)(relPos[1] / inc[1]);
1297 k1 = (unsigned int)(relPos[2] / inc[2]);
1298
1299 // compute barycentric coordinates
1300 Vec3d w = pos - (bmin + Vec3d(i1 * inc[0], j1 * inc[1], k1 * inc[2]));
1301 double alpha = w[0] / inc[0];
1302 double beta = w[1] / inc[1];
1303 double gamma = w[2] / inc[2];
1304
1305 // locate voxel vertices
1306 map<gridPoint,int> :: iterator voxelVertexEntry;
1307
1308 voxelVertexEntry = vertices2.find(gridPoint(i1+0,j1+0,k1+0));
1309 if (voxelVertexEntry == vertices2.end())
1310 {
1311 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 000" << endl;
1312 return;
1313 }
1314 unsigned int c000 = voxelVertexEntry->second;
1315
1316 voxelVertexEntry = vertices2.find(gridPoint(i1+1,j1+0,k1+0));
1317 if (voxelVertexEntry == vertices2.end())
1318 {
1319 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 100" << endl;
1320 return;
1321 }
1322 unsigned int c100 = voxelVertexEntry->second;
1323
1324 voxelVertexEntry = vertices2.find(gridPoint(i1+1,j1+1,k1+0));
1325 if (voxelVertexEntry == vertices2.end())
1326 {
1327 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 110" << endl;
1328 return;
1329 }
1330 unsigned int c110 = voxelVertexEntry->second;
1331
1332 voxelVertexEntry = vertices2.find(gridPoint(i1+0,j1+1,k1+0));
1333 if (voxelVertexEntry == vertices2.end())
1334 {
1335 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 010" << endl;
1336 return;
1337 }
1338 unsigned int c010 = voxelVertexEntry->second;
1339
1340 voxelVertexEntry = vertices2.find(gridPoint(i1+0,j1+0,k1+1));
1341 if (voxelVertexEntry == vertices2.end())
1342 {
1343 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 001" << endl;
1344 return;
1345 }
1346 unsigned int c001 = voxelVertexEntry->second;
1347
1348 voxelVertexEntry = vertices2.find(gridPoint(i1+1,j1+0,k1+1));
1349 if (voxelVertexEntry == vertices2.end())
1350 {
1351 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 101" << endl;
1352 return;
1353 }
1354 unsigned int c101 = voxelVertexEntry->second;
1355
1356 voxelVertexEntry = vertices2.find(gridPoint(i1+1,j1+1,k1+1));
1357 if (voxelVertexEntry == vertices2.end())
1358 {
1359 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 111" << endl;
1360 return;
1361 }
1362 unsigned int c111 = voxelVertexEntry->second;
1363
1364 voxelVertexEntry = vertices2.find(gridPoint(i1+0,j1+1,k1+1));
1365 if (voxelVertexEntry == vertices2.end())
1366 {
1367 cout << "Error: vertex " << i+1 << " at location " << pos << " doesn't have corner neighbor 011" << endl;
1368 return;
1369 }
1370 unsigned int c011 = voxelVertexEntry->second;
1371
1372 /*
1373 unsigned int c000 = vertices2.find(gridPoint(i1+0,j1+0,k1+0))->second;
1374 unsigned int c100 = vertices2.find(gridPoint(i1+1,j1+0,k1+0))->second;
1375 unsigned int c110 = vertices2.find(gridPoint(i1+1,j1+1,k1+0))->second;
1376 unsigned int c010 = vertices2.find(gridPoint(i1+0,j1+1,k1+0))->second;
1377
1378 unsigned int c001 = vertices2.find(gridPoint(i1+0,j1+0,k1+1))->second;
1379 unsigned int c101 = vertices2.find(gridPoint(i1+1,j1+0,k1+1))->second;
1380 unsigned int c111 = vertices2.find(gridPoint(i1+1,j1+1,k1+1))->second;
1381 unsigned int c011 = vertices2.find(gridPoint(i1+0,j1+1,k1+1))->second;
1382 */
1383 /*
1384 double f000 = (1-alpha)*(1-beta)*(1-gamma);
1385 double f100 = (alpha)*(1-beta)*(1-gamma);
1386 double f110 = (alpha)*(beta)*(1-gamma);
1387 double f010 = (1-alpha)*(beta)*(1-gamma);
1388
1389 double f001 = (1-alpha)*(1-beta)*(gamma);
1390 double f101 = (alpha)*(1-beta)*(gamma);
1391 double f111 = (alpha)*(beta)*(gamma);
1392 double f011 = (1-alpha)*(beta)*(gamma);
1393 */
1394 Vec3d gradf000(1.0 / inc[0] * -(1-beta)*(1-gamma), 1.0 / inc[1] * -(1-alpha)*(1-gamma), 1.0 / inc[2] * -(1-alpha)*(1-beta));
1395 Vec3d gradf100(1.0 / inc[0] * (1-beta)*(1-gamma), 1.0 / inc[1] * -alpha*(1-gamma), 1.0 / inc[2] * -alpha*(1-beta));
1396 Vec3d gradf110(1.0 / inc[0] * beta*(1-gamma), 1.0 / inc[1] * alpha*(1-gamma), 1.0 / inc[2] * -alpha*beta);
1397 Vec3d gradf010(1.0 / inc[0] * -beta*(1-gamma), 1.0 / inc[1] * (1-alpha)*(1-gamma), 1.0 / inc[2] * (1-alpha)*-beta);
1398
1399 Vec3d gradf001(1.0 / inc[0] * -(1-beta)*gamma, 1.0 / inc[1] * -(1-alpha)*gamma, 1.0 / inc[2] * (1-alpha)*(1-beta));
1400 Vec3d gradf101(1.0 / inc[0] * (1-beta)*gamma, 1.0 / inc[1] * -alpha*gamma, 1.0 / inc[2] * alpha*(1-beta));
1401 Vec3d gradf111(1.0 / inc[0] * beta*gamma, 1.0 / inc[1] * alpha*gamma, 1.0 / inc[2] * alpha*beta);
1402 Vec3d gradf011(1.0 / inc[0] * -beta*gamma, 1.0 / inc[1] * (1-alpha)*gamma, 1.0 / inc[2] * (1-alpha)*beta);
1403
1404 Vec3d normal = normals[i];
1405
1406 for(int j=0; j<r; j++)
1407 {
1408 Vec3d u000(voxelModalMatrix[ELT(3*nVoxel,3*c000+0,j)],voxelModalMatrix[ELT(3*nVoxel,3*c000+1,j)],voxelModalMatrix[ELT(3*nVoxel,3*c000+2,j)]);
1409 Vec3d u100(voxelModalMatrix[ELT(3*nVoxel,3*c100+0,j)],voxelModalMatrix[ELT(3*nVoxel,3*c100+1,j)],voxelModalMatrix[ELT(3*nVoxel,3*c100+2,j)]);
1410 Vec3d u110(voxelModalMatrix[ELT(3*nVoxel,3*c110+0,j)],voxelModalMatrix[ELT(3*nVoxel,3*c110+1,j)],voxelModalMatrix[ELT(3*nVoxel,3*c110+2,j)]);
1411 Vec3d u010(voxelModalMatrix[ELT(3*nVoxel,3*c010+0,j)],voxelModalMatrix[ELT(3*nVoxel,3*c010+1,j)],voxelModalMatrix[ELT(3*nVoxel,3*c010+2,j)]);
1412 Vec3d u001(voxelModalMatrix[ELT(3*nVoxel,3*c001+0,j)],voxelModalMatrix[ELT(3*nVoxel,3*c001+1,j)],voxelModalMatrix[ELT(3*nVoxel,3*c001+2,j)]);
1413 Vec3d u101(voxelModalMatrix[ELT(3*nVoxel,3*c101+0,j)],voxelModalMatrix[ELT(3*nVoxel,3*c101+1,j)],voxelModalMatrix[ELT(3*nVoxel,3*c101+2,j)]);
1414 Vec3d u111(voxelModalMatrix[ELT(3*nVoxel,3*c111+0,j)],voxelModalMatrix[ELT(3*nVoxel,3*c111+1,j)],voxelModalMatrix[ELT(3*nVoxel,3*c111+2,j)]);
1415 Vec3d u011(voxelModalMatrix[ELT(3*nVoxel,3*c011+0,j)],voxelModalMatrix[ELT(3*nVoxel,3*c011+1,j)],voxelModalMatrix[ELT(3*nVoxel,3*c011+2,j)]);
1416
1417 Vec3d coef(0,0,0);
1418 coef += dot(gradf000,normal) * u000;
1419 coef += dot(gradf100,normal) * u100;
1420 coef += dot(gradf110,normal) * u110;
1421 coef += dot(gradf010,normal) * u010;
1422 coef += dot(gradf001,normal) * u001;
1423 coef += dot(gradf101,normal) * u101;
1424 coef += dot(gradf111,normal) * u111;
1425 coef += dot(gradf011,normal) * u011;
1426
1427 outputMatrix[ELT(3*n, 3*i+0, j)] = coef[0];
1428 outputMatrix[ELT(3*n, 3*i+1, j)] = coef[1];
1429 outputMatrix[ELT(3*n, 3*i+2, j)] = coef[2];
1430 }
1431
1432 }
1433
1434 cout << endl;
1435
1436 WriteMatrixToDisk_((char*)filenameCorrectionMatrix.c_str(), 3*n, r, outputMatrix);
1437
1438 free(outputMatrix);
1439 free(voxelModalMatrix);
1440 }
1441