TriMeshUtils.cc
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:43k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. // 
  3. // TriMeshUtils.cc
  4. //
  5. // Utility functions for triangle meshes that are represented
  6. // as list of vertices and list of indices that define the
  7. // mesh connectivity.
  8. //
  9. //############################################################
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <iostream.h>
  13. #include <vector.h>
  14. #include <hash_map.h>
  15. #include <hash_set.h>
  16. #include "TriMeshUtils.h"
  17. #include "Median.h"
  18. #include "ply++.h"
  19. #include "plvGlobals.h"
  20. #include "Progress.h"
  21. #include "Timer.h"
  22. // calculate vertex normals by averaging from triangle
  23. // normals (obtained from cross products)
  24. // possibly weighted with triangle areas
  25. void
  26. getVertexNormals(const vector<Pnt3> &vtx,
  27.  const vector<int>  &tri,
  28.  bool                strips,
  29.  vector<short>      &nrm_s,
  30.  int useArea)
  31. {
  32.   vector<Pnt3> nrm (vtx.size(), Pnt3());
  33.   int ntris = tri.size();
  34.   if (!useArea) {
  35.     if (strips) {
  36.       bool flip = false;
  37.       vector<int>::const_iterator i;
  38.       for (i = tri.begin(); i < tri.end(); i++) {
  39. if (*(i+2) == -1) {
  40.   // end of strip
  41.   i += 2;
  42.   flip = false;
  43.   continue;
  44. }
  45. int b, c;
  46. if (flip) {
  47.   b = *(i+2); c = *(i+1); flip = false;
  48. } else {
  49.   b = *(i+1); c = *(i+2); flip = true;
  50. }
  51. Pnt3 norm = normal(vtx[*i], vtx[b], vtx[c]);
  52. nrm[*i] += norm;
  53. nrm[b]  += norm;
  54. nrm[c]  += norm;
  55.       }
  56.     } else {
  57.       for (int i = 0; i < ntris; i += 3) {
  58. Pnt3 norm = normal(vtx[tri[i+0]], 
  59.    vtx[tri[i+1]], 
  60.    vtx[tri[i+2]]);
  61. nrm[tri[i+0]] += norm;
  62. nrm[tri[i+1]] += norm;
  63. nrm[tri[i+2]] += norm;
  64.       }
  65.     }
  66.   } else { // do use area norm
  67.     if (strips) {
  68.       bool flip = false;
  69.       for (int i = 0; i < ntris; i++) {
  70. if (tri[i+2] == -1) {
  71.   // end of strip
  72.   i += 2;
  73.   flip = false;
  74.   continue;
  75. }
  76. int a, b, c;
  77. if (flip) {
  78.   a = tri[i]; b = tri[i+2]; c = tri[i+1]; flip = false;
  79. } else {
  80.   a = tri[i]; b = tri[i+1]; c = tri[i+2]; flip = true;
  81. }
  82. //float area = .5 * cross(vtx[a], vtx[b], vtx[c]).norm();
  83. //Pnt3 areaNorm = normal(vtx[a], vtx[b], vtx[c]);
  84. //areaNorm *= area;
  85. Pnt3 areaNorm = cross(vtx[a], vtx[b], vtx[c]);
  86. nrm[a] += areaNorm;
  87. nrm[b] += areaNorm;
  88. nrm[c] += areaNorm;
  89.       }
  90.     } else {
  91.       for (int i = 0; i < ntris; i += 3) {
  92. /*
  93. float area = .5 * cross(vtx[tri[i+0]], vtx[tri[i+1]],
  94. vtx[tri[i+2]]).norm();
  95. Pnt3 areaNorm = normal(vtx[tri[i+0]], 
  96.        vtx[tri[i+1]], 
  97.        vtx[tri[i+2]]);
  98. areaNorm *= area;
  99. */
  100. Pnt3 areaNorm = cross(vtx[tri[i+0]], 
  101.       vtx[tri[i+1]], 
  102.       vtx[tri[i+2]]);
  103. nrm[tri[i+0]] += areaNorm;
  104. nrm[tri[i+1]] += areaNorm;
  105. nrm[tri[i+2]] += areaNorm;
  106.       }
  107.     }
  108.   }
  109.   nrm_s.clear();
  110.   nrm_s.reserve (3 * vtx.size());
  111.   for (Pnt3* n = nrm.begin(); n != nrm.end(); n++) {
  112.     n->set_norm(32767.0);
  113.     nrm_s.push_back (short(n->operator[](0)));
  114.     nrm_s.push_back (short(n->operator[](1)));
  115.     nrm_s.push_back (short(n->operator[](2)));
  116.   }
  117. }
  118. float
  119. median_edge_length(vector<Pnt3> &vtx,
  120.    vector<int>  &tri,
  121.    bool          strips,
  122.    int           percentile)
  123. {
  124.   int n = tri.size();
  125.   if (n < 3) return 0.0;
  126.   Median<float> med(percentile, n);
  127.     
  128.   if (strips) {
  129.     int *end = &tri[n];
  130.     // reuse the "inner edge" length in the strip
  131.     float inner_edge = dist2(vtx[0], vtx[1]);
  132.     for (int *i=&tri[2]; i<end; i++) {
  133.       if (*i == -1) {
  134. // skip over the start part of the next strip
  135. int cnt = 0;
  136. while (cnt < 3) {
  137.   i++;
  138.   if (i >= end) goto done;
  139.   if (*i == -1) cnt = 0;
  140.   else          cnt++;
  141. }
  142. inner_edge = dist2(vtx[*(i-1)], vtx[*(i-2)]);
  143.       }
  144.       med += inner_edge;
  145.       inner_edge = dist2(vtx[*(i-1)], vtx[*i]);
  146.       med += inner_edge;
  147.       med += dist2(vtx[*(i-2)], vtx[*i]);
  148.     }
  149.   } else {
  150.     // edge lengths
  151.     for (int i=0; i<n; i+=3) {
  152.       med += dist2(vtx[tri[i+0]], vtx[tri[i+1]]);
  153.       med += dist2(vtx[tri[i+2]], vtx[tri[i+1]]);
  154.       med += dist2(vtx[tri[i+0]], vtx[tri[i+2]]);
  155.     } 
  156.   }
  157.  done:
  158.   return sqrtf(med.find());
  159. }
  160. // find the median edge length
  161. // if a triangle has an edge that's longer than
  162. // factor times the median (or percentile), remove the triangle
  163. void 
  164. remove_stepedges(vector<Pnt3> &vtx,
  165.  vector<int>  &tri,
  166.  int           factor, 
  167.  int           percentile,
  168.  bool          strips)
  169. {
  170.   // calculate the threshold
  171.   float thr = median_edge_length(vtx, tri, strips, percentile);
  172.   thr *= thr * float(factor * factor);
  173.   int n = tri.size();
  174.   if (strips) {
  175.     vector<int> ntri;
  176.     ntri.reserve(n);
  177.     bool strip_on = false;
  178.     int cnt  = 0;
  179.     for (int i=0; i<n; i++) {
  180.       if (strip_on) {
  181. // strip is on
  182. bool end_found = (tri[i] == -1);
  183. bool end_here  = false;
  184. if (!end_found) {
  185.   // check for too long edges
  186.   if (cnt == 1) 
  187.     end_here = (dist2(vtx[tri[i]], vtx[tri[i-1]]) > thr);
  188.   else
  189.     end_here = (dist2(vtx[tri[i]], vtx[tri[i-1]]) > thr ||
  190. dist2(vtx[tri[i]], vtx[tri[i-2]]) > thr);
  191. }
  192. if (end_found || end_here) {
  193.   // found an end, clean up
  194.   if (cnt < 3) {
  195.     ntri.pop_back();
  196.     if (cnt == 2) ntri.pop_back();
  197.     if (ntri.size()) assert(ntri.back() == -1);
  198.   } else {
  199.     ntri.push_back(-1);
  200.   }
  201.   strip_on = false;
  202. }
  203. if (end_here) {
  204.   if (cnt % 2) {
  205.     // cnt odd, check if can add a single triangle
  206.     if (i > n-4) break; // almost done, break...
  207.     if (tri[i+1] != -1 &&
  208. tri[i+2] != -1 &&
  209. dist2(vtx[tri[i  ]], vtx[tri[i+1]]) < thr &&
  210. dist2(vtx[tri[i  ]], vtx[tri[i+2]]) < thr &&
  211. dist2(vtx[tri[i+1]], vtx[tri[i+2]]) < thr) {
  212.       ntri.push_back(tri[i]);
  213.       ntri.push_back(tri[i+1]);
  214.       ntri.push_back(tri[i+2]);
  215.       ntri.push_back(-1);
  216.     }
  217.   } else {
  218.     // cnt even, restart a strip
  219.     strip_on = true;
  220.     cnt = 1;
  221.     ntri.push_back(tri[i]);
  222.   }
  223. }
  224. if (!end_found && !end_here) {
  225.   // continue this strip
  226.   ntri.push_back(tri[i]);
  227.   cnt++;
  228. }
  229.       } else {
  230. // strip is not on
  231. if (tri[i] != -1) {
  232.   ntri.push_back(tri[i]);
  233.   strip_on = true;
  234.   cnt = 1;
  235. }
  236.       }
  237.       if (!strip_on) cnt = 0;
  238.     }
  239.     tri = ntri;
  240.   } else {
  241.     // could make faster by not recalculating edges!
  242.     for (int i=n-3; i>=0; i-=3) {
  243.       if (dist2(vtx[tri[i+0]], vtx[tri[i+1]]) > thr ||
  244.   dist2(vtx[tri[i+2]], vtx[tri[i+1]]) > thr ||
  245.   dist2(vtx[tri[i+0]], vtx[tri[i+2]]) > thr) {
  246. // remove the triangle
  247. tri[i+2] = tri.back(); tri.pop_back();
  248. tri[i+1] = tri.back(); tri.pop_back();
  249. tri[i+0] = tri.back(); tri.pop_back();
  250.       }
  251.     }
  252.   }
  253. }
  254. // check whether some vertices in vtx are not being used in tri
  255. // if so, remove them and also adjust the tri indices
  256. void
  257. remove_unused_vtxs(vector<Pnt3> &vtx,
  258.    vector<int>  &tri)
  259. {
  260.   // prepare vertex index map
  261.   vector<int> vtx_ind(vtx.size(), -1);
  262.   
  263.   // march through the triangles
  264.   // and mark the vertices that are actually used
  265.   int n = tri.size();
  266.   for (int i=0; i<n; i+=3) {
  267.     vtx_ind[tri[i+0]] = tri[i+0];
  268.     vtx_ind[tri[i+1]] = tri[i+1];
  269.     vtx_ind[tri[i+2]] = tri[i+2];
  270.   }
  271.   // remove the vertices that were not marked,
  272.   // also keep tab on how the indices change
  273.   int cnt = 0;
  274.   n = vtx.size();
  275.   for (i=0; i<n; i++) {
  276.     if (vtx_ind[i] != -1) {
  277.       vtx_ind[i] = cnt;
  278.       vtx[cnt] = vtx[i];
  279.       cnt++;
  280.     }
  281.   }
  282.   vtx.erase(&vtx[cnt], vtx.end());
  283.   // march through triangles and correct the indices
  284.   n = tri.size();
  285.   for (i=0; i<n; i+=3) {
  286.     tri[i+0] = vtx_ind[tri[i+0]];
  287.     tri[i+1] = vtx_ind[tri[i+1]];
  288.     tri[i+2] = vtx_ind[tri[i+2]];
  289.     assert(tri[i+0] >=0 && tri[i+0] < vtx.size());
  290.     assert(tri[i+1] >=0 && tri[i+1] < vtx.size());
  291.     assert(tri[i+2] >=0 && tri[i+2] < vtx.size());
  292.   }
  293. }
  294. // count the number of triangles in a tstrip
  295. int
  296. count_tris(const vector<int> &strips)
  297. {
  298.   int cnt = 0;
  299.   int i = 0;
  300.   while (i < strips.size()) {
  301.     // skip over the 2 first inds
  302.     i+=2;
  303.     while (strips[i++] != -1) {
  304.       cnt++;
  305.     }
  306.   }
  307.   return cnt;
  308. }
  309. struct _edge {
  310.   int a,b;
  311.   _edge(void) : a(0),b(0) {}
  312.   _edge(int _a, int _b)
  313.     {
  314.       if (_a < _b) { a=_a; b=_b; }
  315.       else         { b=_a; a=_b; }
  316.     }
  317.   void set(int _a, int _b)
  318.     {
  319.       if (_a < _b) { a=_a; b=_b; }
  320.       else         { b=_a; a=_b; }
  321.     }
  322.   bool operator==(const _edge &e) const
  323.     {
  324.       return a == e.a && b == e.b;
  325.     }
  326. };
  327. struct equal_edge
  328. {
  329.   bool operator()(const _edge &e1, const _edge &e2) const
  330.     {
  331.       return e1.a == e2.a && e1.b == e2.b;
  332.     }
  333. };
  334. struct hash_edge
  335. {
  336.   size_t operator()(const _edge &e) const
  337.     {
  338.       return e.a * 1000000 + e.b;
  339.     }
  340. };
  341. static void
  342. remove_this_triangle(vector<int> &ts, int i)
  343. {
  344.   for (int j=0; j<3; j++) {
  345.     int curr = ts[i+j]; // current neighbor
  346.     if (curr >= 0) {
  347.       if      (ts[curr]   == -2) continue; // nbor has been removed
  348.       // mark the correct edge of the neighbor to 
  349.       // not have a neighbor any more
  350.       if      (ts[curr]   == i) ts[curr]   = -1;
  351.       else if (ts[curr+1] == i) ts[curr+1] = -1;
  352.       else if (ts[curr+2] == i) ts[curr+2] = -1;
  353.     }
  354.     ts[i+j] = -2; // remove
  355.   }
  356. }
  357. static int Verbose = 1;
  358. static int Warnings = 1;
  359. static void
  360. old_tris_to_strips(const vector<int> &tris, 
  361.    vector<int>& tstripinds,
  362.    const char* name)
  363. {
  364.   int nTris = tris.size();
  365.   tstripinds.clear();
  366.   tstripinds.reserve(1.1*nTris/3);
  367.   // build a multimap: map edges to incident triangles
  368.   typedef hash_multimap<_edge,int,hash_edge,equal_edge> hmm;
  369.   hmm edges;
  370.   hmm::iterator edge_it;
  371.   int i,j;
  372.   _edge e;
  373.   cout << "Creating triangle strips from raw triangle data..." 
  374.        << endl;
  375.   if (Verbose)
  376.     printf ("input: %d vertices (%d triangles)n", nTris, nTris/3);
  377.   // show progress graphically
  378.   Progress progress (nTris * 3, "Create %s T-Strips", name);
  379.   for (i = 0; i < nTris; i+=3) {  // for all tris
  380.     if (i%300 == 0)
  381.       progress.update (i);
  382.     for (j = 0; j < 3; j++) {      // for all edges
  383.       // create an edge
  384.       e.set(tris[i+j], tris[i+(j+1)%3]);
  385.       // store the edge and starting vertex of the triangle
  386.       edges.insert(pair<const _edge,int>(e,i));
  387.     }
  388.   }
  389.   
  390.   // march through triangles
  391.   // store for each edge the neighboring triangle 
  392.   //  -1 if neighbor doesn't exist, 
  393.   //  later -2 if the triangle is removed/processed
  394.   vector<int> tri_nbors(nTris);
  395.   for (i = 0; i < nTris; i+=3) {
  396.     if (i%300 == 0)
  397.       progress.update (i + nTris);
  398.     for (j = 0; j < 3; j++) {
  399.       // find all instances of current edge
  400.       e.set(tris[i+j], tris[i+(j+1)%3]);
  401.       pair<hmm::iterator, hmm::iterator> p = edges.equal_range(e);
  402.       edge_it = p.first;
  403.       // shouldn't have more than two triangles sharing this edge:
  404.       p.first++;
  405.       if (p.first != p.second) {
  406. p.first++;
  407. if (p.first != p.second) {
  408.   if (Warnings) {
  409.     fprintf(stderr, "More than two pointers to same "
  410.     "edge (%d,%d)n", e.a, e.b);
  411.     while (Verbose && edge_it != p.second) {
  412.       int tri = (*edge_it).second;
  413.       fprintf(stderr, 
  414.       "t: offending tri: #%d (%d,%d,%d)n",
  415.       tri, tris[tri+0],
  416.       tris[tri+1], tris[tri+2]);
  417.       edge_it++;
  418.     }
  419.   }
  420.   // non-manifold edge, no neighbors across this
  421.   tri_nbors[i+j] = -1;
  422.   continue;
  423. }
  424.       }
  425.       // there's only 1 or 2 triangles for this edge
  426.       if ((*edge_it).second != i) { 
  427. // if the first match is not this triangle,
  428. // the neighbor across this edge is the current triangle
  429. tri_nbors[i+j] = (*edge_it).second;
  430.       } else {
  431. // the first of range is the current one
  432. edge_it++;
  433. if (edge_it == p.second) {
  434.   // that was the only edge, so this edge is not shared.
  435.   tri_nbors[i+j] = -1;
  436. } else {
  437.   // found another edge
  438.   // so the neighbor across this edge is now in .second
  439.   assert((*edge_it).first == e);
  440.   assert((*edge_it).second != i);
  441.   tri_nbors[i+j] = (*edge_it).second;
  442. }
  443.       }
  444.     }
  445.   }
  446.   
  447.   int nStrips = 0; //for stat-keeping
  448.   // start removing triangles from the tri_nbors
  449.   // and build the t-strips
  450.   int nNbors = tri_nbors.size();
  451.   for (i = 0; i < nNbors; i += 3) {
  452.     if (i%300 == 0)
  453.       progress.update (2* nTris + i);
  454.       
  455.     if (tri_nbors[i] == -2) continue; // has been removed
  456.     // try finding a neighbor
  457.     int nbor = -1;
  458.     for (j = 0; j < 3; j++) {
  459.       if (tri_nbors[i+j] >= 0) {
  460. nbor = j;
  461. break;
  462.       }
  463.     }
  464.     if (nbor == -1) {
  465.       // single triangle
  466.       tstripinds.push_back(tris[i+0]);
  467.       tstripinds.push_back(tris[i+1]);
  468.       tstripinds.push_back(tris[i+2]);
  469.     } else {
  470.       // initialize the tstrip
  471.       tstripinds.push_back(tris[i+(nbor+2)%3]);
  472.       tstripinds.push_back(tris[i+(nbor  )  ]);
  473.       tstripinds.push_back(tris[i+(nbor+4)%3]);
  474.       
  475.       int prev = i;
  476.       int dir = 1;
  477.       int curr = tri_nbors[prev+nbor];
  478.       while (curr != -1) {
  479. // find from which nbor we came to curr
  480. if      (tri_nbors[curr]   == prev) nbor = 0;
  481. else if (tri_nbors[curr+1] == prev) nbor = 1;
  482. else if (tri_nbors[curr+2] == prev) nbor = 2;
  483. else printf ("Warning: really lost!n");
  484. remove_this_triangle(tri_nbors, prev);
  485. tstripinds.push_back(tris[curr+(nbor+2)%3]);
  486. // find next nbor
  487. nbor = (nbor+1+dir)%3;
  488. dir ^= 1;
  489. prev = curr;
  490. curr = tri_nbors[prev+nbor];
  491.       }
  492.       remove_this_triangle(tri_nbors, prev);
  493.     }
  494.     ++nStrips;   //just for stat-keeping
  495.     tstripinds.push_back(-1);
  496.   }
  497.   if (Verbose)
  498.     printf ("output: %ld vertices (%d strips); avg. length %.1fn",
  499.   tstripinds.size()-nStrips, nStrips,
  500.   ((float)tstripinds.size()/nStrips) - 3);
  501.   printf ("Done.n");
  502. }
  503. typedef unsigned* adjacentfacelist;
  504. adjacentfacelist*
  505. TriMesh_FindAdjacentFaces (int numvertices,
  506.    const vector<int>& faces,
  507.    int*& numadjacentfaces)
  508. {
  509.   cout << "  Computing vtx->face mappings..." << flush;
  510.   int numfaces = faces.size();
  511.   assert (numvertices != 0);
  512.   assert (numfaces != 0);
  513.   // Step I - compute numadjacentfaces
  514.   numadjacentfaces = new int[numvertices];
  515.   memset(numadjacentfaces, 0, numvertices*sizeof(int));
  516.   for (int i = 0; i < numfaces; i++) {
  517.     numadjacentfaces[faces[i]]++;
  518.   }
  519.   // allocate one chunk of memory for all adjacent face lists
  520.   // total number of adjacent faces is numfaces
  521.   unsigned* adjacentfacedata = new unsigned [numfaces];
  522.   // this pointer will be incremented as needed but adjacentfaces[0]
  523.   // will always point to the beginning so it can later be freed
  524.   
  525.   // Step II - compute the actual vertex->tri lists...
  526.   adjacentfacelist* adjacentfaces = new adjacentfacelist[numvertices];
  527.   for (i = 0; i < numvertices; i++) {
  528.     adjacentfaces[i] = adjacentfacedata;
  529.     adjacentfacedata += numadjacentfaces[i];
  530.     //for (int j=0; j<numadjacentfaces[i]; j++)
  531.     //  adjacentfaces[i][j] = numfaces;
  532.   }
  533.   assert (adjacentfacedata == adjacentfaces[0] + numfaces);
  534.   for (unsigned* afdp = adjacentfaces[0]; afdp < adjacentfacedata; afdp++)
  535.     *afdp = numfaces;
  536.   
  537.   for (i = 0; i < numfaces; i++) {
  538.     unsigned *p = adjacentfaces[faces[i]];
  539.     while (*p != numfaces)
  540.       p++;
  541.     // snap to nearest multiple of 3, the start of tri data for that face
  542.     *p = (i/3) * 3;
  543.   }
  544.   return adjacentfaces;
  545. }
  546. #define FOR_EACH_VERTEX_OF_FACE(i,j) 
  547.   for (int jtmp = 0, j = faces[i]; 
  548.        jtmp < 3; 
  549.        jtmp++, j = faces[i + jtmp])
  550. #define FOR_EACH_ADJACENT_FACE(i,j) 
  551.   for (int jtmp=0, j = adjacentfaces[i][0]; 
  552.        jtmp < numadjacentfaces[i]; 
  553.        jtmp++, j = adjacentfaces[i][jtmp])
  554. static bool* done = NULL;
  555. static unsigned* stripsp = NULL;
  556. static int* numadjacentfaces = NULL;
  557. static adjacentfacelist* adjacentfaces = NULL;
  558. static const int* faces = NULL;
  559. static int nstrips = 0;
  560. static int nEvilTriangles;
  561. // Figure out the next triangle we're headed for...
  562. static inline int
  563. Tstrip_Next_Tri(unsigned tri, unsigned v1, unsigned v2)
  564. {
  565.   FOR_EACH_ADJACENT_FACE(v1, f1) {
  566.     if ((f1 == tri) || done[f1/3])
  567.       continue;
  568.     FOR_EACH_ADJACENT_FACE(v2, f2) {
  569.       if ((f2 == tri) || done[f2/3])
  570. continue;
  571.       if (f1 == f2)
  572. return f1;
  573.     }
  574.   }
  575.   
  576.   return -1;
  577. }
  578. // Build a whole strip of triangles, as long as possible...
  579. static void Tstrip_Crawl(unsigned v1, unsigned v2, unsigned v3,
  580.  unsigned next)
  581. {
  582.   // Insert the first tri...
  583.   *stripsp++ = v1;
  584.   *stripsp++ = v2;
  585.   *stripsp++ = v3;
  586.   
  587.   unsigned vlast1 = v3;
  588.   unsigned vlast2 = v2;
  589.   bool shouldbeflipped = true;
  590.   // Main loop...
  591.   do {
  592.     // Find the next vertex
  593.     int vnext;
  594.     FOR_EACH_VERTEX_OF_FACE(next,vnext_tmp) {
  595.       if ((vnext_tmp == vlast1) || (vnext_tmp == vlast2))
  596. continue;
  597.       vnext = vnext_tmp;
  598.       break;
  599.     }
  600.     bool thisflipped = true;
  601.     if ((faces[next+0] == vlast2) &&
  602. (faces[next+1] == vlast1) &&
  603. (faces[next+2] == vnext))
  604.       thisflipped = false;
  605.     if ((faces[next+2] == vlast2) &&
  606. (faces[next+0] == vlast1) &&
  607. (faces[next+1] == vnext))
  608.       thisflipped = false;
  609.     if ((faces[next+1] == vlast2) &&
  610. (faces[next+2] == vlast1) &&
  611. (faces[next+0] == vnext))
  612.       thisflipped = false;
  613.     
  614.     if (thisflipped != shouldbeflipped) {
  615.       if (nEvilTriangles-- > 0) {
  616. cerr << "Tstrip generation: inconsistent triangle orientation, "
  617.      << "tri " << next << endl;
  618.       }
  619.       goto bail;
  620.     }
  621.     
  622.     
  623.     // Record it
  624.     *stripsp++ = vnext;
  625.     vlast2 = vlast1;
  626.     vlast1 = vnext;
  627.     done[next/3] = true;
  628.     shouldbeflipped = !shouldbeflipped;
  629.     
  630.     // Try to find the next tri
  631.   } while ((next = Tstrip_Next_Tri(next, vlast1, vlast2)) != -1);
  632.   
  633.  bail:
  634.   // OK, done.  Mark end of strip
  635.   *stripsp++ = -1;
  636.   ++nstrips;
  637. }
  638. // Begin a tstrip, starting with triangle tri
  639. // tri is ordinal, not index (counts by 1)
  640. static void Tstrip_Bootstrap(unsigned tri)
  641. {
  642.   done[tri] = true;
  643.   
  644.   // Find two vertices with which to start.
  645.   // We do only a bit of lookahead, starting with vertices that will
  646.   // let us form a strip of length at least 2...
  647.   
  648.   tri *= 3;
  649.   unsigned vert1 = faces[tri];
  650.   unsigned vert2 = faces[tri+1];
  651.   unsigned vert3 = faces[tri+2];
  652.   
  653.   // Try vertices 1 and 2...
  654.   int nextface = Tstrip_Next_Tri(tri, vert1, vert2);
  655.   if (nextface != -1) {
  656.     Tstrip_Crawl(vert3, vert1, vert2, nextface);
  657.     return;
  658.   }
  659.   
  660.   // Try vertices 2 and 3...
  661.   nextface = Tstrip_Next_Tri(tri, vert2, vert3);
  662.   if (nextface != -1) {
  663.     Tstrip_Crawl(vert1, vert2, vert3, nextface);
  664.     return;
  665.   }
  666.   
  667.   // Try vertices 3 and 1...
  668.   nextface = Tstrip_Next_Tri(tri, vert3, vert1);
  669.   if (nextface != -1) {
  670.     Tstrip_Crawl(vert2, vert3, vert1, nextface);
  671.     return;
  672.   }
  673.   
  674.   // OK, nothing we can do. Do a single-triangle-long tstrip.
  675.   *stripsp++ = vert1;
  676.   *stripsp++ = vert2;
  677.   *stripsp++ = vert3;
  678.   *stripsp++ = -1;
  679.   ++nstrips;
  680. }
  681. static unsigned *Build_Tstrips(int numvertices,
  682.        const vector<int>& tris,
  683.        unsigned*& endstrips,
  684.        int& outNstrips)
  685. {
  686.   adjacentfaces = TriMesh_FindAdjacentFaces
  687.     (numvertices, tris, numadjacentfaces);
  688.   cout << " stripping... " << flush;
  689.   int numfaces = tris.size() / 3;
  690.   
  691.   // Allocate more than enough memory
  692.   unsigned* strips = new unsigned[4*numfaces+1];
  693.   stripsp = strips;
  694.   nEvilTriangles = 3;
  695.   
  696.   // Allocate array to record what triangles we've already done
  697.   done = new bool[numfaces];
  698.   memset(done, 0, numfaces*sizeof(bool));
  699.   faces = &tris[0];
  700.   nstrips = 0;
  701.   
  702.   // Build the tstrips
  703.   for (int i = 0; i < numfaces; i++) {
  704.     if (!done[i])
  705.       Tstrip_Bootstrap (i);
  706.   }
  707.   endstrips = stripsp;
  708.   outNstrips = nstrips;
  709.   if (nEvilTriangles < 0) {
  710.     cerr << "And there were " << -nEvilTriangles
  711.  << " more evil triangles for which no warnings were printed."
  712.  << endl << endl;
  713.   }
  714.   
  715.   // cleanup global arrays
  716.   delete [] done; done = NULL;
  717.   delete [] numadjacentfaces; numadjacentfaces = NULL;
  718.   delete [] adjacentfaces[0]; // ptr to one chunk of data for all
  719.   delete [] adjacentfaces; adjacentfaces = NULL;
  720.   stripsp = NULL;
  721.   faces = NULL;
  722.   cout << " done." << endl;
  723.   return strips;
  724. }
  725. void
  726. tris_to_strips(int numvertices,
  727.        const vector<int>& tris,
  728.        vector<int>& tstripinds,
  729.        const char* name)
  730. {
  731. #if 0
  732.   old_tris_to_strips (tris, tstripinds, name);
  733. #else
  734.   cout << "Tstripping " << tris.size()/3 << " triangles ("
  735.        << tris.size() << " vertices)..." << endl;
  736.   tstripinds.clear();
  737.   unsigned *strips, *end;
  738.   int nStrips = 0;
  739.   if (tris.size()) {
  740.     strips = Build_Tstrips (numvertices, tris, end, nStrips);
  741.     // this is a hair faster...
  742.     //tstripinds.reserve (end-strips);
  743.     //memcpy (&tstripinds[0], strips, 4*(end-strips));
  744.     
  745.     // but this is legal :)
  746.     //#ifdef __STL_MEMBER_TEMPLATES
  747. #if 0
  748.     tstripinds.assign (strips, end);
  749. #else
  750.     // as long as your compiler supports member templates :(
  751.     tstripinds.reserve (end - strips);
  752.     while (strips < end)
  753.       tstripinds.push_back (*strips++);
  754. #endif
  755.   }
  756.   cout << "Tstrip results: " << nstrips << " strips ("
  757.        << tstripinds.size() - nStrips << " vertices, avg. length "
  758.        << ((float)tstripinds.size()/nStrips) - 3 << ")." << endl;
  759. #endif
  760. }
  761. void 
  762. strips_to_tris(const vector<int> &tstrips, 
  763.        vector<int>& tris, int nTris)
  764. {
  765.   if (!tstrips.size())
  766.      return;
  767.   assert(tstrips.back() == -1);
  768.   tris.clear();
  769.   if (!nTris)
  770.     nTris = tstrips.size() * 3;  // estimate
  771.   tris.reserve (nTris);
  772.   vector<int>::const_iterator vert;
  773.   for (vert = tstrips.begin(); vert != tstrips.end(); vert++) {
  774.     while (*vert == -1) { // handle 0-length strips
  775.       ++vert;
  776.       if (vert == tstrips.end()) break;
  777.     }
  778.     if (vert == tstrips.end()) break;
  779.     vert += 2;   //we'll look backwards at these
  780.     int dir = 0;
  781.     while (*vert != -1)  {
  782.       tris.push_back(vert[-2 + dir]);
  783.       tris.push_back(vert[-1 - dir]);
  784.       tris.push_back(vert[0]);
  785.       vert++;
  786.       dir ^= 1;
  787.     }
  788.   }
  789. }
  790. void
  791. flip_tris(vector<int> &inds, bool stripped)
  792. {
  793.   int n = inds.size();
  794.   
  795.   if (stripped) {
  796.     int i=0;
  797.     while (i<n) {
  798.       i++; // skip the first one
  799.       // after that, swap all complete pairs until -1
  800.       while (1) {
  801. int tmp = inds[i++];
  802. // after break, inds[i-1] == -1
  803. if (tmp == -1) break;
  804. if (inds[i] == -1) { i++; break; }
  805. inds[i-1] = inds[i];
  806. inds[i++] = tmp;
  807.       }
  808.     }
  809.   } else {
  810.     for (int i = 0; i < n; i += 3)
  811.       swap(inds[i], inds[i+1]);
  812.   }
  813. }
  814. #define BEFORE(mod, var) 
  815.   ((mod == 0) ? tris[var + 2] : tris[var - 1])
  816. #define AFTER(mod, var) 
  817.   ((mod == 2) ? tris[var - 2] : tris[var + 1])
  818. // sort a ring of neighbors
  819. static void
  820. sort_nbors(int *nbors, int n, const  vector<int> &tris)
  821. {
  822.   for (int i=0; i<n; i++) {
  823.     int vb = BEFORE(nbors[i]%3, nbors[i]);
  824.     for (int j=i+2; j<n; j++) {
  825.       if (AFTER(nbors[j]%3, nbors[j]) == vb) {
  826. // swap
  827. int tmp    = nbors[i+1];
  828. nbors[i+1] = nbors[j];
  829. nbors[j]   = tmp;
  830. break;
  831.       }
  832.     }
  833.   }
  834. }
  835. static void
  836. nbors_tris(int    n_vtx,
  837.    const  vector<int> &tris,
  838.    int*  &n_nbors, // number of neighbors for vtx i
  839.    int** &nbors,   // the actual neighbors
  840.    bool   sorted = false)
  841. {
  842.   // Step I - compute numadjacentfaces
  843.   n_nbors = new int[n_vtx];
  844.   memset(n_nbors, 0, n_vtx*sizeof(int));
  845.   int n_tri_inds = tris.size();
  846.   for (int i=0; i<n_tri_inds; i++) {
  847.     n_nbors[tris[i]]++;
  848.   }
  849.   // allocate one chunk of memory for all neighbor triangle lists
  850.   // total number of neighboring triangles is n_tri_inds
  851.   int *data = new int[n_tri_inds];
  852.   // this pointer will be incremented as needed but nbors[0]
  853.   // will always point to the beginning so it can later be freed
  854.   
  855.   // Step II - compute the actual vertex->tri lists...
  856.   nbors = new int*[n_vtx];
  857.   for (i=0; i<n_vtx; i++) {
  858.     nbors[i] = data;
  859.     data += n_nbors[i];
  860.   }
  861.   assert (data == nbors[0] + n_tri_inds);
  862.   // mark as empty
  863.   int *p;
  864.   for (p = nbors[0]; p<data; p++) {
  865.     *p = -1;
  866.   }
  867.   for (i=0; i<n_tri_inds; i++) {
  868.     int *p = nbors[tris[i]];
  869.     while (*p != -1) p++;
  870.     *p = i;
  871.   }
  872.   if (sorted) {
  873.     for (i=0; i<n_vtx; i++) {
  874.       sort_nbors(nbors[i], n_nbors[i], tris);
  875.     }
  876.   }
  877. }
  878. // assume bdry has the right size and has been initialized with
  879. // zeroes
  880. void
  881. mark_boundary_verts(vector<char> &bdry,
  882.     const vector<int> &tris)
  883. {
  884.   cout << "Marking boundary vertices ... " << flush;
  885.   int nv = bdry.size();
  886.   int *n_nbors, **nbors;
  887.   nbors_tris(nv, tris, n_nbors, nbors, true);
  888.   // for each vertex, try to find a full loop 
  889.   // around it, if can't its boundary
  890.   int va, vb; // vertex after, vertex before
  891.   for (int i=0; i<nv; i++) {
  892.     if (n_nbors[i] <= 1) {
  893.       bdry[i] = 1;
  894.       continue;
  895.     }
  896.     int jend = n_nbors[i] - 1;
  897.     for (int j=0; j<jend; j++) {
  898.       // which vtx comes before this (corner j)?
  899.       int k = nbors[i][j];
  900.       vb = BEFORE(k % 3, k);
  901.       // which vtx comes after this (corner j+1)?
  902.       k = nbors[i][j+1];
  903.       va = AFTER(k % 3, k);
  904.       if (va != vb) {
  905. // not a continuous neighbor chain
  906. bdry[i] = 1;
  907. break;
  908.       }
  909.     }
  910.     if (bdry[i] == 0) {
  911.       // check the last possible link (from end to start)
  912.       // which vtx comes before this (corner jend)?
  913.       int k = nbors[i][jend];
  914.       vb = BEFORE(k % 3, k);
  915.       // which vtx comes after this (corner jstart)?
  916.       k = nbors[i][0];
  917.       va = AFTER(k % 3, k);
  918.       if (va != vb) {
  919. // not a continuous neighbor chain
  920. bdry[i] = 1;
  921.       }
  922.     }      
  923.   }
  924.   // cleanup
  925.   delete[] n_nbors;
  926.   delete[] nbors[0]; // ptr to one chunk of data for all
  927.   delete[] nbors;
  928.   cout << "done" << endl;
  929. }
  930. typedef vector< vector<int> > vecvec;
  931. typedef vector<int>::const_iterator vicit;
  932. static void
  933. build_nbor_map(vecvec &nlist, const vector<int> &tris)
  934. {
  935.   // build an edge set
  936.   typedef hash_set<_edge,hash_edge,equal_edge> hs;
  937.   hs edges;
  938.   int n = tris.size();
  939.   for (int i=0; i<n; i+=3) {
  940.     edges.insert(_edge(tris[i+0], tris[i+1]));
  941.     edges.insert(_edge(tris[i+1], tris[i+2]));
  942.     edges.insert(_edge(tris[i+2], tris[i+0]));
  943.   }
  944.   // for every edge, create an entry to neighborhood map
  945.   hs::const_iterator edge_it;
  946.   for (edge_it = edges.begin(); edge_it != edges.end(); edge_it++) {
  947.     nlist[(*edge_it).a].push_back((*edge_it).b);
  948.     nlist[(*edge_it).b].push_back((*edge_it).a);
  949.   }
  950. }
  951. #if 0
  952. // assume bdry has the right size and has been initialized with
  953. // zeroes
  954. void
  955. distance_from_boundary(vector<float> &distances,
  956.        const vector<Pnt3> &pnts,
  957.        const vector<int> &tris)
  958. {
  959.   TIMER(dist);
  960.   int n = pnts.size();
  961.   // find boundary verts
  962.   vector<char> bdry(n, 0);
  963.   mark_boundary_verts(bdry, tris);
  964.   // initialize distance vector
  965.   distances.clear();
  966.   distances.insert(distances.begin(), n, 1e33);
  967.   int nbdry = 0;
  968.   for (int i=0; i<n; i++) {
  969.     if (bdry[i]) { distances[i] = 0.0; nbdry++; }
  970.   }
  971.   // build neighborhood map
  972.   vecvec nmap(n);
  973.   build_nbor_map(nmap, tris);
  974.   // find the neighbors of bdry vertices
  975.   hash_set<int,hash<int>,equal_to<int> > prevset, workset, nextset;
  976.   hash_set<int,hash<int>,equal_to<int> >::const_iterator hcit;
  977.   for (i=0; i<n; i++) {
  978.     if (bdry[i]) {
  979.       vicit end = nmap[i].end();
  980.       for (vicit it = nmap[i].begin(); it != end; it++) {
  981. if (!bdry[*it]) {
  982.   workset.insert(*it);
  983. }
  984.       }
  985.       prevset.insert(i);
  986.     }
  987.   }
  988.   // first round: just go through the mesh in the
  989.   // topological order in increasing distance from the
  990.   // mesh boundary
  991.   int cnt = nbdry;
  992.   cout << pnts.size() << "..." << flush;
  993.   while (!workset.empty()) {
  994.     
  995.     cout << pnts.size() - cnt << "..." << flush;
  996.     cnt += workset.size();
  997.     for (hcit = workset.begin(); hcit != workset.end(); hcit++) {
  998.       i = *hcit;
  999.       vicit end = nmap[i].end();
  1000.       for (vicit it = nmap[i].begin(); it != end; it++) {
  1001. // calculate new distance
  1002. float dij = dist(pnts[i], pnts[*it]);
  1003. float d   = dij + distances[*it];
  1004. if (d < distances[i]) distances[i] = d;
  1005. // should neighbor go to the nextset?
  1006. if (workset.find(*it) != workset.end()) continue;
  1007. if (prevset.find(*it) != prevset.end()) continue;
  1008. nextset.insert(*it);
  1009. d = dij + distances[i];
  1010. if (d < distances[*it]) distances[*it] = d;
  1011.       }
  1012.     }
  1013.     prevset = workset;
  1014.     workset = nextset;
  1015.     nextset.clear();
  1016.   }
  1017.   cout << endl << "Restart" << endl;
  1018.   // second round: put all the nonboundary vertices into
  1019.   // the workset, all the 
  1020.   workset.clear();
  1021.   for (i=0; i<n; i++) {
  1022.     if (!bdry[i]) {
  1023.       workset.insert(i);
  1024.     }
  1025.   }
  1026.   while (!workset.empty()) {
  1027.     
  1028.     cout << workset.size() << "..." << flush;
  1029.     nextset.clear();
  1030.     // calculate distances
  1031.     for (hcit = workset.begin(); hcit != workset.end(); hcit++) {
  1032.       i = *hcit;
  1033.       vicit end = nmap[i].end();
  1034.       for (vicit it = nmap[i].begin(); it != end; it++) {
  1035. float d = dist(pnts[i], pnts[*it]) + distances[*it];
  1036. if (d < distances[i]) distances[i] = d;
  1037.       }
  1038.     }
  1039.     // see if neighbors should be in set
  1040.     for (hcit = workset.begin(); hcit != workset.end(); hcit++) {
  1041.       i = *hcit;
  1042.       vicit end = nmap[i].end();
  1043.       for (vicit it = nmap[i].begin(); it != end; it++) {
  1044. float d = dist(pnts[i], pnts[*it]) + distances[i];
  1045. if (d < distances[*it]) {
  1046.   distances[*it] = d;
  1047.   nextset.insert(*it);
  1048. }
  1049.       }
  1050.     }
  1051.     workset = nextset;
  1052.   }
  1053.   cout << endl;
  1054. }
  1055. #else
  1056. // assume bdry has the right size and has been initialized with
  1057. // zeroes
  1058. void
  1059. distance_from_boundary(vector<float> &distances,
  1060.        const vector<Pnt3> &pnts,
  1061.        const vector<int> &tris)
  1062. {
  1063.   TIMER(dist);
  1064.   int n = pnts.size();
  1065.   // find boundary verts
  1066.   vector<char> bdry(n, (char)0);
  1067.   int *n_nbors, **nbors;
  1068.   nbors_tris(n, tris, n_nbors, nbors, true);
  1069.   // for each vertex, try to find a full loop 
  1070.   // around it, if can't its boundary
  1071.   int va, vb; // vertex after, vertex before
  1072.   for (int i=0; i<n; i++) {
  1073.     if (n_nbors[i] <= 1) {
  1074.       bdry[i] = 1;
  1075.       continue;
  1076.     }
  1077.     int jend = n_nbors[i] - 1;
  1078.     for (int j=0; j<jend; j++) {
  1079.       // which vtx comes before this (corner j)?
  1080.       int k = nbors[i][j];
  1081.       vb = BEFORE(k % 3, k);
  1082.       // which vtx comes after this (corner j+1)?
  1083.       k = nbors[i][j+1];
  1084.       va = AFTER(k % 3, k);
  1085.       if (va != vb) {
  1086. // not a continuous neighbor chain
  1087. bdry[i] = 1;
  1088. break;
  1089.       }
  1090.     }
  1091.     if (bdry[i] == 0) {
  1092.       // check the last possible link (from end to start)
  1093.       // which vtx comes before this (corner jend)?
  1094.       int k = nbors[i][jend];
  1095.       vb = BEFORE(k % 3, k);
  1096.       // which vtx comes after this (corner jstart)?
  1097.       k = nbors[i][0];
  1098.       va = AFTER(k % 3, k);
  1099.       if (va != vb) {
  1100. // not a continuous neighbor chain
  1101. bdry[i] = 1;
  1102.       }
  1103.     }      
  1104.   }
  1105.   cout << "done boundary" << endl;
  1106.   // initialize distance vector
  1107.   distances.clear();
  1108.   distances.insert(distances.begin(), n, 1e33);
  1109.   int nbdry = 0;
  1110.   for (i=0; i<n; i++) {
  1111.     if (bdry[i]) { distances[i] = 0.0; nbdry++; }
  1112.   }
  1113.   // find the neighbors of bdry vertices
  1114.   hash_set<int,hash<int>,equal_to<int> > prevset, workset, nextset;
  1115.   hash_set<int,hash<int>,equal_to<int> >::const_iterator hcit;
  1116.   for (i=0; i<n; i++) {
  1117.     if (bdry[i]) {
  1118.       for (int j=0; j<n_nbors[i]; j++) {
  1119. int k = AFTER(nbors[i][j]%3, nbors[i][j]);
  1120. if (!bdry[k]) workset.insert(k);
  1121. k = BEFORE(nbors[i][j]%3, nbors[i][j]);
  1122. if (!bdry[k]) workset.insert(k);
  1123.       }
  1124.       prevset.insert(i);
  1125.     }
  1126.   }
  1127.   // first round: just go through the mesh in the
  1128.   // topological order in increasing distance from the
  1129.   // mesh boundary
  1130.   int cnt = nbdry;
  1131.   cout << pnts.size() << "..." << flush;
  1132.   while (!workset.empty()) {
  1133.     
  1134.     cout << pnts.size() - cnt << "..." << flush;
  1135.     cnt += workset.size();
  1136.     for (hcit = workset.begin(); hcit != workset.end(); hcit++) {
  1137.       i = *hcit;
  1138.       for (int j=0; j<n_nbors[i]; j++) {
  1139. int k = AFTER(nbors[i][j]%3, nbors[i][j]);
  1140. // calculate new distance
  1141. float dij = dist(pnts[i], pnts[k]);
  1142. float d   = dij + distances[k];
  1143. if (d < distances[i]) distances[i] = d;
  1144. // should neighbor go to the nextset?
  1145. if (workset.find(k) != workset.end()) continue;
  1146. if (prevset.find(k) != prevset.end()) continue;
  1147. nextset.insert(k);
  1148. d = dij + distances[i];
  1149. if (d < distances[k]) distances[k] = d;
  1150.       }
  1151.     }
  1152.     prevset = workset;
  1153.     workset = nextset;
  1154.     nextset.clear();
  1155.   }
  1156.   cout << endl << "Restart" << endl;
  1157.   // second round: put all the nonboundary vertices into
  1158.   // the workset, all the 
  1159.   workset.clear();
  1160.   for (i=0; i<n; i++) {
  1161.     if (!bdry[i]) {
  1162.       workset.insert(i);
  1163.     }
  1164.   }
  1165.   while (!workset.empty()) {
  1166.     
  1167.     cout << workset.size() << "..." << flush;
  1168.     nextset.clear();
  1169.     // calculate distances
  1170.     for (hcit = workset.begin(); hcit != workset.end(); hcit++) {
  1171.       i = *hcit;
  1172.       for (int j=0; j<n_nbors[i]; j++) {
  1173. int k = AFTER(nbors[i][j]%3, nbors[i][j]);
  1174. float d = dist(pnts[i], pnts[k]) + distances[k];
  1175. if (d < distances[i]) distances[i] = d;
  1176.       }
  1177.     }
  1178.     // see if neighbors should be in set
  1179.     for (hcit = workset.begin(); hcit != workset.end(); hcit++) {
  1180.       i = *hcit;
  1181.       for (int j=0; j<n_nbors[i]; j++) {
  1182. int k = AFTER(nbors[i][j]%3, nbors[i][j]);
  1183. float d = dist(pnts[i], pnts[k]) + distances[i];
  1184. if (d < distances[k]) {
  1185.   distances[k] = d;
  1186.   nextset.insert(k);
  1187. }
  1188.       }
  1189.     }
  1190.     workset = nextset;
  1191.   }
  1192.   cout << endl;
  1193.   // cleanup
  1194.   delete[] n_nbors;
  1195.   delete[] nbors[0]; // ptr to one chunk of data for all
  1196.   delete[] nbors;
  1197. }
  1198. #endif
  1199. void
  1200. quadric_simplify(const vector<Pnt3> &vtx_in,
  1201.  const vector<int>  &tri_in,
  1202.  vector<Pnt3> &vtx_out,
  1203.  vector<int>  &tri_out,
  1204.  int           goal,
  1205.  int           optLevel,
  1206.  float         errLevel,
  1207.  float         boundWeight)
  1208. {
  1209.    char inName[L_tmpnam], outName[L_tmpnam];
  1210.    FILE *f;
  1211.    int i;
  1212.    char ins[200];
  1213.    vtx_out.clear();
  1214.    tri_out.clear();
  1215.    // Write out the original mesh data to a temporary input file
  1216.    if (!tmpnam(inName))  {
  1217.       cerr << "ERROR: Unable to get temporary filename for QSlim input" << endl;
  1218.       return;
  1219.    }
  1220.    if (!(f = fopen(inName, "w")))  {
  1221.       cerr << "ERROR: Unable to open file " << inName << " for QSlim input"
  1222.            << endl;
  1223.       return;
  1224.    }
  1225.    for (i=0; i<vtx_in.size(); ++i) 
  1226.       fprintf(f, "v %f %f %fn", vtx_in[i][0], vtx_in[i][1], vtx_in[i][2]);
  1227.    for (i=0; i<tri_in.size(); i+=3) 
  1228.       fprintf(f, "f %d %d %dn", tri_in[i]+1, tri_in[i+1]+1, tri_in[i+2]+1);
  1229.    fclose(f);
  1230.    // Get a filename for the temporary output file
  1231.    
  1232.    if (!tmpnam(outName))  {
  1233.       cerr << "ERROR: Unable to get temporary filename for QSlim output"
  1234.            << endl;
  1235.       remove(inName);
  1236.       return;
  1237.    }
  1238.    // Run QSlim as an external program to simplify the mesh
  1239.    char qslimCmd[200];
  1240.    sprintf(qslimCmd, "qslim -t %d -B %f -o %s %s", goal, boundWeight,
  1241.                                                    outName, inName);
  1242.    if (system(qslimCmd))  {
  1243.       cerr << "nERROR: Unable to execute call to external QSlim program:n"
  1244.            << qslimCmd << "nPlease verify that qslim is properly installed"
  1245.            << " and accessible on your system." << endl;
  1246.       remove(inName);
  1247.       remove(outName);
  1248.       return;
  1249.    }
  1250.    // Read in the simplified mesh from the resulting output file
  1251.    float v1, v2, v3;
  1252.    int f1, f2, f3;
  1253.    if (!(f = fopen(outName, "r"))) {
  1254.       cerr << "ERROR: Unable to open file " << outName << " from QSlim"
  1255.            << endl;
  1256.       remove(inName);
  1257.       return;
  1258.    }
  1259.    while (fscanf(f, "%s", ins) == 1)  {
  1260.       if (!strcmp(ins, "v")) {
  1261.          fscanf(f, "%f %f %f", &v1, &v2, &v3);
  1262.          vtx_out.push_back(Pnt3(v1, v2, v3));
  1263.       }
  1264.       else if (!strcmp(ins, "f")) {
  1265.          fscanf(f, "%d %d %d", &f1, &f2, &f3);
  1266.          tri_out.push_back(f1-1);
  1267.          tri_out.push_back(f2-1);
  1268.          tri_out.push_back(f3-1);
  1269.       }
  1270.    }
  1271.    fclose(f);
  1272.    remove(inName);
  1273.    remove(outName);
  1274. }
  1275. /////////////////////////////////////
  1276. // BEGIN write_ply_file() HELPER CODE
  1277. struct PlyVertex {
  1278.   float x, y, z;
  1279.   float nx, ny, nz;
  1280.   uchar diff_r, diff_g, diff_b;
  1281.   float tex_u, tex_v;
  1282.   float intensity;
  1283.   float std_dev;
  1284.   float confidence;
  1285. };
  1286. const int MAX_FACE_VERTS = 100;
  1287. struct PlyFace {
  1288.   uchar nverts;
  1289.   int verts[MAX_FACE_VERTS];
  1290. };
  1291. struct CoordConfVert {
  1292.    float v[3];
  1293.    float conf;
  1294. };
  1295. struct TriLocal {
  1296.    uchar nverts;
  1297.    int index[3];
  1298. };
  1299. static PlyProperty vert_prop_x =  
  1300.    {"x", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1301. static PlyProperty vert_prop_y =  
  1302.   {"y", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1303. static PlyProperty vert_prop_z =  
  1304.   {"z", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1305. static PlyProperty vert_prop_nx =  
  1306.    {"nx", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1307. static PlyProperty vert_prop_ny =  
  1308.   {"ny", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1309. static PlyProperty vert_prop_nz =  
  1310.   {"nz", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1311. static PlyProperty vert_prop_intens =  
  1312.   {"intensity", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1313. static PlyProperty vert_prop_conf =
  1314.   {"confidence", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE,
  1315.    PLY_START_TYPE, 0};
  1316. static PlyProperty vert_prop_diff_r =  
  1317.   {"diffuse_red", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1318. static PlyProperty vert_prop_diff_g =  
  1319.   {"diffuse_green", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1320. static PlyProperty vert_prop_diff_b =  
  1321.   {"diffuse_blue", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  1322. static PlyProperty face_props[] = { 
  1323.   {"vertex_indices", PLY_INT, PLY_INT, 0, true, PLY_UCHAR, PLY_UCHAR, 0},
  1324. };
  1325. struct tstrip_info {
  1326.   int nverts;
  1327.   const int* vertData;
  1328. };
  1329. static PlyProperty tstrips_props[] = {
  1330.   {"vertex_indices", PLY_INT, PLY_INT, 4, true, PLY_INT, PLY_INT, 0},
  1331. };
  1332. static void
  1333. set_offsets(void)
  1334. {
  1335.   static int first = 1;
  1336.   if (first) {
  1337.     first = 0;
  1338.     vert_prop_x.offset          = offsetof(PlyVertex,x);
  1339.     vert_prop_y.offset          = offsetof(PlyVertex,y);
  1340.     vert_prop_z.offset          = offsetof(PlyVertex,z);
  1341.     vert_prop_nx.offset         = offsetof(PlyVertex,nx);
  1342.     vert_prop_ny.offset         = offsetof(PlyVertex,ny);
  1343.     vert_prop_nz.offset         = offsetof(PlyVertex,nz);
  1344.     vert_prop_intens.offset     = offsetof(PlyVertex,intensity);
  1345.     vert_prop_conf.offset       = offsetof(PlyVertex,confidence);
  1346.     vert_prop_diff_r.offset     = offsetof(PlyVertex,diff_r);
  1347.     vert_prop_diff_g.offset     = offsetof(PlyVertex,diff_g);
  1348.     vert_prop_diff_b.offset     = offsetof(PlyVertex,diff_b);
  1349.     tstrips_props[0].offset     = offsetof(tstrip_info,vertData);
  1350.   }
  1351. }
  1352. ////////////////////////////
  1353. // write_ply_file() : called by all exported wrappers to handle the different
  1354. // variants of ply files.
  1355. static void
  1356. write_ply_file(const char *fname,
  1357.        const vector<Pnt3> &vtx,
  1358.        const vector<int> &tris, bool strips,
  1359.        const vector<Pnt3> &nrm,
  1360.        const vector<uchar> &intensity,
  1361.        const vector<float> &confidence,
  1362.        bool hasNrm, bool hasIntensity, bool hasConfidence)
  1363. {
  1364.   int i;
  1365.   char *elem_names[] = {"vertex", strips ? "tristrips" : "face"};
  1366.   bool hasColor = false;
  1367.   bool hasAlpha = false;
  1368.   if (hasIntensity) {
  1369.     if (intensity.size() == 3 * vtx.size()) {
  1370.       hasColor = true;
  1371.       hasIntensity = false;
  1372.     } else if (intensity.size() == 4 * vtx.size()) {
  1373.       hasColor = true;
  1374.       hasAlpha = true;
  1375.       hasIntensity = false;
  1376.     }
  1377.   }
  1378.   PlyFile ply;
  1379.   if (!ply.open_for_writing(fname, 2, elem_names,PLY_BINARY_BE))
  1380.     return;
  1381.   vector<PlyProperty> vert_props;
  1382.   set_offsets();
  1383.   vert_props.push_back(vert_prop_x);
  1384.   vert_props.push_back(vert_prop_y);
  1385.   vert_props.push_back(vert_prop_z);
  1386.   if (hasNrm) {
  1387.     vert_props.push_back(vert_prop_nx);
  1388.     vert_props.push_back(vert_prop_ny);
  1389.     vert_props.push_back(vert_prop_nz);
  1390.   }
  1391.   if (hasIntensity) {
  1392.     vert_props.push_back(vert_prop_intens);
  1393.   }
  1394.     
  1395.   if (hasConfidence) {
  1396.     vert_props.push_back(vert_prop_conf);
  1397.   }
  1398.   if (hasColor) {
  1399.     vert_props.push_back(vert_prop_diff_r);
  1400.     vert_props.push_back(vert_prop_diff_g);
  1401.     vert_props.push_back(vert_prop_diff_b);
  1402.   }
  1403.     
  1404.   // count offset
  1405.   face_props[0].offset = offsetof(PlyFace, verts);
  1406.   face_props[0].count_offset = offsetof(PlyFace, nverts);  
  1407.     
  1408.   ply.describe_element ("vertex", vtx.size(), 
  1409. vert_props.size(), &vert_props[0]);
  1410.   if (strips)
  1411.     ply.describe_element ("tristrips", 1, 1, tstrips_props);
  1412.   else
  1413.     ply.describe_element ("face", tris.size()/3, 1, face_props);
  1414.   ply.header_complete();
  1415.     
  1416.     // set up and write the vertex elements
  1417.   PlyVertex plyVert;
  1418.   ply.put_element_setup ("vertex");
  1419.   for (i = 0; i < vtx.size(); i++) {
  1420.     plyVert.x = vtx[i][0];
  1421.     plyVert.y = vtx[i][1];
  1422.     plyVert.z = vtx[i][2];
  1423.     if (hasIntensity)
  1424.       plyVert.intensity = intensity[i] / 255.0;
  1425.     if (hasColor) {
  1426.       int ci = (hasAlpha ? 4 : 3) * i;
  1427.       plyVert.diff_r = intensity[ci  ];
  1428.       plyVert.diff_g = intensity[ci+1];
  1429.       plyVert.diff_b = intensity[ci+2];
  1430.     }
  1431.     if (hasNrm) {
  1432.       plyVert.nx = nrm[i][0];
  1433.       plyVert.ny = nrm[i][1];
  1434.       plyVert.nz = nrm[i][2];
  1435.     }
  1436.     if (hasConfidence) {
  1437.       plyVert.confidence = confidence[i];
  1438.     }
  1439.     ply.put_element((void *) &plyVert);
  1440.   }
  1441.   if (strips) {
  1442.     ply.put_element_setup ("tristrips");
  1443.     tstrip_info ts_info = { tris.size(), tris.begin() };
  1444.     ply.put_element (&ts_info);
  1445.   } else {
  1446.     ply.put_element_setup ("face");
  1447.     
  1448.     PlyFace plyFace;
  1449.     for (i = 0; i < tris.size(); i+=3) {
  1450.       plyFace.nverts = 3;
  1451.       plyFace.verts[0] = tris[i+0];
  1452.       plyFace.verts[1] = tris[i+1];
  1453.       plyFace.verts[2] = tris[i+2];
  1454.       
  1455.       ply.put_element_static_strg((void *) &plyFace);
  1456.     }
  1457.   }
  1458. }
  1459. // exported wrappers for write_ply_file
  1460. void
  1461. write_ply_file(const char *fname,
  1462.        const vector<Pnt3> &vtx,
  1463.        const vector<int> &tris, bool strips,
  1464.        const vector<Pnt3> &nrm,
  1465.        const vector<uchar> &intensity,
  1466.        const vector<float> &confidence)
  1467. {
  1468.   write_ply_file(fname, vtx, tris, strips, nrm, intensity, confidence, 
  1469.  true, true, true);
  1470. }
  1471. void
  1472. write_ply_file(const char *fname,
  1473.        const vector<Pnt3> &vtx,
  1474.        const vector<int> &tris, bool strips,
  1475.        const vector<Pnt3> &nrm,
  1476.        const vector<uchar> &intensity)
  1477. {
  1478.   vector<float> confidence;
  1479.   write_ply_file(fname, vtx, tris, strips, nrm, intensity, confidence, 
  1480.  true, true, false);
  1481. }
  1482. void
  1483. write_ply_file(const char *fname,
  1484.        const vector<Pnt3> &vtx,
  1485.        const vector<int> &tris, bool strips,
  1486.        const vector<Pnt3> &nrm)
  1487. {
  1488.   vector<uchar> intensity;
  1489.   vector<float> confidence;
  1490.   write_ply_file(fname, vtx, tris, strips, nrm, intensity, confidence, 
  1491.  true, false, false);
  1492. }
  1493. void
  1494. write_ply_file(const char *fname,
  1495.        const vector<Pnt3> &vtx,
  1496.        const vector<int> &tris, bool strips)
  1497. {
  1498.   vector<Pnt3> nrm;
  1499.   vector<uchar> intensity;
  1500.   vector<float> confidence;
  1501.   write_ply_file(fname, vtx, tris, strips, nrm, intensity, confidence,
  1502.  false, false, false);
  1503. }
  1504. void
  1505. write_ply_file(const char *fname,
  1506.        const vector<Pnt3> &vtx,
  1507.        const vector<int> &tris, bool strips,
  1508.        const vector<uchar> &intensity)
  1509. {
  1510.   vector<Pnt3> nrm;
  1511.   vector<float> confidence;
  1512.   write_ply_file(fname, vtx, tris, strips, nrm, intensity, confidence,
  1513.  false, true, false);
  1514. }
  1515. void
  1516. write_ply_file(const char *fname,
  1517.        const vector<Pnt3> &vtx,
  1518.        const vector<int> &tris, bool strips,
  1519.        const vector<float> &confidence)
  1520. {
  1521.   vector<Pnt3> nrm;
  1522.   vector<uchar> intensity;
  1523.   write_ply_file(fname, vtx, tris, strips, nrm, intensity, confidence,
  1524.  false, false, true);
  1525. }
  1526. void
  1527. write_ply_file(const char *fname,
  1528.        const vector<Pnt3> &vtx,
  1529.        const vector<int> &tris, bool strips,
  1530.        const vector<uchar> &intensity,
  1531.        const vector<float> &confidence)
  1532. {
  1533.   vector<Pnt3> nrm;
  1534.   write_ply_file(fname, vtx, tris, strips, nrm, intensity, confidence,
  1535.  false, true, true);
  1536. }
  1537. void
  1538. write_ply_file(const char *fname,
  1539.        const vector<Pnt3> &vtx,
  1540.        const vector<int> &tris, bool strips,
  1541.        const vector<Pnt3> &nrm,
  1542.        const vector<float> &confidence)
  1543. {
  1544.   vector<uchar> intensity;
  1545.   write_ply_file(fname, vtx, tris, strips, nrm, intensity, confidence, 
  1546.  true, false, true);
  1547. }
  1548. void
  1549. pushNormalAsShorts (vector<short>& nrms, Pnt3 n)
  1550. {
  1551.   n *= 32767;
  1552.   nrms.push_back (n[0]);
  1553.   nrms.push_back (n[1]);
  1554.   nrms.push_back (n[2]);
  1555. }
  1556. void
  1557. pushNormalAsPnt3 (vector<Pnt3>& nrms, short* n, int i)
  1558. {
  1559.   i *= 3;
  1560.   Pnt3 nrm (n[i]/32767.0, n[i+1]/32767.0, n[i+2]/32767.0);
  1561.   nrms.push_back (nrm);
  1562. }