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

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. // 
  3. // GenericScan.cc
  4. //
  5. // Kari Pulli
  6. // Mon Jun 29 11:51:05 PDT 1998
  7. //
  8. // Store range scan information from a generic range scanner
  9. // that gives range maps.
  10. // Not much if anything is known of the scanner properties,
  11. // so orthographics scan geometry is assumed.
  12. //
  13. //############################################################
  14. #include <fstream.h>
  15. #include <sys/stat.h>
  16. #include "GenericScan.h"
  17. #include "defines.h"
  18. #include "Mesh.h"
  19. #include "RangeGrid.h"
  20. #include "plvGlobals.h"
  21. #include "plvScene.h"
  22. #include "plvDraw.h"
  23. #include "KDindtree.h"
  24. #include "ColorUtils.h"
  25. #include "TriMeshUtils.h"
  26. #include "FileNameUtils.h"
  27. #include "MeshTransport.h"
  28. #include "VertexFilter.h"
  29. GenericScan::GenericScan ()
  30. {
  31.   _Init();
  32. }
  33. void
  34. GenericScan::_Init()
  35. {
  36.   bDirty = true;
  37.   bNameSet = false;
  38.   pushcount = 0;
  39.   myRangeGrid = NULL;
  40. }
  41. GenericScan::GenericScan (Mesh* mesh, const crope& name)
  42. {
  43.   _Init();
  44.   insertMesh (mesh, name);
  45.   computeBBox();
  46.   set_name (name);
  47. }
  48. GenericScan::~GenericScan ()
  49. {
  50.   while (meshes.size()) {
  51.     delete meshes.back();
  52.     meshes.pop_back();
  53.   }
  54.   
  55.   while (kdtree.size()) {
  56.     delete kdtree.back();
  57.     kdtree.pop_back();
  58.   }
  59.   delete myRangeGrid;
  60. }
  61. MeshTransport*
  62. GenericScan::mesh(bool perVertex, bool stripped,
  63.   ColorSource color, int colorSize)
  64. {
  65.   if (stripped && !perVertex) {
  66.     cerr << "No t-strips without per-vertex properties";
  67.     return NULL;
  68.   }
  69.   Mesh* mesh = currentMesh();
  70.   MeshTransport* mt = new MeshTransport;
  71.   mt->setVtx (&mesh->vtx, MeshTransport::share);
  72.   if (perVertex)
  73.     mt->setNrm (&mesh->nrm, MeshTransport::share);
  74.   else {
  75.     vector<short>* faceNrm = new vector<short>;
  76.     mesh->simulateFaceNormals (*faceNrm);
  77.     mt->setNrm (faceNrm, MeshTransport::steal);
  78.   }
  79.   if (stripped)
  80.     mt->setTris (&mesh->getTstrips(), MeshTransport::share);
  81.   else
  82.     mt->setTris (&mesh->getTris(), MeshTransport::share);
  83.   if (color != colorNone)
  84.     setMTColor (mesh, mt, perVertex, color, colorSize);
  85.   return mt;
  86. }
  87. void
  88. GenericScan::setMTColor (Mesh* mesh, MeshTransport* mt,
  89.  bool perVertex, ColorSource source,
  90.  int colorsize)
  91. {
  92.   if (source == colorBoundary) {
  93.       mesh->mark_boundary_verts();
  94.   } else if (source == colorConf) {
  95.     if (!mesh->vertConfidence)
  96.       return;  // confidence data requested but does not exist
  97.   } else {
  98.     if (!mesh->vertMatDiff && !mesh->vertIntensity &&
  99. (perVertex || !mesh->triMatDiff))
  100.       return;  // no color data at all, or only per-face but per-vert requested
  101.   }
  102.   // we know color data can at the least be synthesized... do it!
  103.   vector<uchar>* colors = new vector<uchar>;
  104.   mt->setColor (colors, MeshTransport::steal);
  105.   if (source == colorConf) {
  106.     if (perVertex) {
  107.       // per-vertex confidence
  108.       colors->reserve (colorsize * mesh->vtx.size());
  109.       for (int i = 0; i < mesh->vtx.size(); i++)
  110. pushConf (*colors, colorsize, mesh->vertConfidence[i]);
  111.     } else {
  112.       // per-face confidence
  113.       colors->reserve (colorsize * mesh->getTris().size()/3);
  114.       for (int i = 0; i < mesh->tris.size(); i+=3) {
  115. pushConf (*colors, colorsize,
  116.   (mesh->vertConfidence[mesh->tris[i+0]]
  117.    + mesh->vertConfidence[mesh->tris[i+1]]
  118.    + mesh->vertConfidence[mesh->tris[i+2]]) / 3);
  119.       }
  120.     }
  121.   } else if (source == colorBoundary) {
  122.       colors->reserve (colorsize * mesh->bdry.size());
  123.       char* end = mesh->bdry.end();
  124.       for (char* c = mesh->bdry.begin(); c < end; c++)
  125. pushConf (*colors, colorsize, (uchar)(*c ? 0 : 255));
  126.   } else { // real diffuse color, not confidence
  127.     if (perVertex) {
  128.       // per-vertex truecolor or intensity
  129.       colors->reserve (colorsize * mesh->vtx.size());
  130.       for (int i = 0; i < mesh->vtx.size(); i++) {
  131. if (source == colorTrue) { // prefer rgb over intensity
  132.   if (mesh->vertMatDiff)
  133.     pushColor (*colors, colorsize, mesh->vertMatDiff[i]);
  134.   else
  135.     pushColor (*colors, colorsize, mesh->vertIntensity[i]);
  136. } else { // prefer intensity over rgb
  137.   if (mesh->vertIntensity)
  138.     pushColor (*colors, colorsize, mesh->vertIntensity[i]);
  139.   else
  140.     pushColor (*colors, colorsize,
  141.        intensityFromRGB (mesh->vertMatDiff[i]));
  142. }
  143.       }
  144.     } else {
  145.       // per-face truecolor or intensity
  146.       colors->reserve (colorsize * mesh->getTris().size()/3);
  147.       for (int i = 0; i < mesh->tris.size(); i+=3) {
  148. if (source == colorTrue) { // prefer rgb from faces,
  149.   // then rgb from verts, then intensity
  150.   if (mesh->triMatDiff)
  151.     pushColor (*colors, colorsize, mesh->triMatDiff[i/3]);
  152.   else if (mesh->vertMatDiff)
  153.     pushColor (*colors, colorsize,
  154.        mesh->vertMatDiff[mesh->tris[i+0]],
  155.        mesh->vertMatDiff[mesh->tris[i+1]],
  156.        mesh->vertMatDiff[mesh->tris[i+2]]);
  157.   else
  158.     pushColor (*colors, colorsize,
  159.        mesh->vertIntensity[mesh->tris[i+0]],
  160.        mesh->vertIntensity[mesh->tris[i+1]],
  161.        mesh->vertIntensity[mesh->tris[i+2]]);
  162. } else { // prefer intensity, then rgb from faces, then rgb from verts
  163.   if (mesh->vertIntensity)
  164.     pushColor (*colors, colorsize,
  165.        mesh->vertIntensity[mesh->getTris()[i+0]],
  166.        mesh->vertIntensity[mesh->tris[i+1]],
  167.        mesh->vertIntensity[mesh->tris[i+2]]);
  168.   else if (mesh->triMatDiff)
  169.     pushColor (*colors, colorsize, mesh->triMatDiff[i/3]);
  170.   else
  171.     pushColor (*colors, colorsize,
  172.        uchar (((int)intensityFromRGB (mesh->vertMatDiff[mesh->getTris()[i+0]])
  173. + intensityFromRGB (mesh->vertMatDiff[mesh->tris[i+1]])
  174. + intensityFromRGB (mesh->vertMatDiff[mesh->tris[i+2]]))/3));
  175. }
  176.       }
  177.     }
  178.   }
  179. }
  180. void
  181. GenericScan::computeBBox()
  182. {
  183.   bool nonEmpty;
  184.   
  185.   bbox.clear();
  186.   for (int i = 0; i < meshes.size(); i++) {
  187.     if (meshes[i]->num_verts() != 0) {
  188.       bbox.add(meshes[i]->bbox);
  189.       nonEmpty = 1;
  190.     }
  191.   }
  192.   
  193.   if (nonEmpty) {
  194.     rot_ctr = bbox.center();
  195.   } else {
  196.     rot_ctr = Pnt3();
  197.   }
  198. }
  199. int
  200. GenericScan::num_vertices(void)
  201. {
  202.   return currentMesh()->num_verts();
  203. }
  204. void 
  205. GenericScan::subsample_points(float rate, vector<Pnt3> &p,
  206.       vector<Pnt3> &n)
  207.   currentMesh()->subsample_points(rate, p, n);
  208. }
  209. bool
  210. GenericScan::read (const crope &fname)
  211. {
  212.   bool success = FALSE;
  213.   // initialize name and remove trailing slash, if it's a directory
  214.   set_name (fname);
  215.   // check if it's a .set file -- or a directory containing a .set
  216.   if ( has_ending(".set") ) {
  217.     success = readSet (fname);
  218.   } else {
  219.     // treat filename as directory name, and look for .set file
  220.     crope fn(get_name());
  221.     fn += crope("/") + get_name() + ".set";
  222.     if (0 == access (fn.c_str(), R_OK)) {
  223.       success = readSet (fn);
  224.       if (success)
  225. set_name(fn);
  226.     }
  227.   }
  228.   // if none of the directory/set forms exist, look for single
  229.   // fully-specified file
  230.   if (!success)
  231.     success = readSingleFile (get_name());
  232.   if (success) {
  233.     // try reading transformation
  234.     pushd();
  235.     TbObj::readXform(get_basename());
  236.     popd();
  237.     bDirty = false;
  238.     bNameSet = true;
  239.   }
  240.   return success;
  241. }
  242. void
  243. GenericScan::setd (const crope& dir, bool bCreate)
  244. {
  245.   char setDir [PATH_MAX];
  246.   strcpy (setDir, dir.c_str());
  247.   char* psep = strrchr (setDir, '/');
  248.   if (psep != NULL) {
  249.     // terminate before filename part
  250.     *psep = 0;
  251.     setdir = setDir;
  252.   } else {
  253.     // default to current directory
  254.     getcwd (setDir, PATH_MAX);
  255.   }
  256.   cout << "Set directory is " << setDir << "/" << endl;
  257.   if (bCreate)
  258.     portable_mkdir (setDir, 00775);
  259. }
  260. void
  261. GenericScan::pushd (void)
  262. {
  263.   //cout << "push: count is " << pushcount << endl;
  264.   if (pushcount++ == 0) {
  265.     assert (pusheddir.empty());
  266.     char szCwd [PATH_MAX];
  267.     getcwd (szCwd, PATH_MAX);
  268.     pusheddir = szCwd;
  269.     chdir (setdir.c_str());
  270.   }
  271. }
  272. void
  273. GenericScan::popd (void)
  274. {
  275.   if (--pushcount == 0) {
  276.     assert (!pusheddir.empty());
  277.     chdir (pusheddir.c_str());
  278.     pusheddir = crope();
  279.   }
  280.   //cout << "pop: count is " << pushcount << endl;
  281. }
  282. bool
  283. GenericScan::readSet (const crope& fn)
  284. {
  285.   //read .set file
  286.   ifstream in (fn.c_str());
  287.   if (in.fail()) {
  288.     cout << "FAILED: " << fn << " does not exist." << endl;
  289.     return false;
  290.   }
  291.   int nMeshes;
  292.   int nDefaultRes;
  293.   in.ignore (20, '=');
  294.   in >> nMeshes;
  295.   in.ignore (20, '=');
  296.   in >> nDefaultRes;
  297.   cout << "Set has " << nMeshes << " meshesn";
  298.   cout << "Default res is " << nDefaultRes << endl;
  299.   // semantics of filenames in set files: relative pathnames are relative
  300.   // to directory containing set file
  301.   setd (fn);
  302.   pushd();
  303.   //read meshes mentioned in .set file
  304.   meshes.clear();
  305.   for (int i = 0; i < nMeshes; i++) {
  306.     char load[20];
  307.     int nRes;
  308.     char path[PATH_MAX];
  309.     in >> load >> nRes >> path;
  310.     bool bPreload = !strcmp (load, "preload");
  311.     if (nRes == nDefaultRes)   //always load the default resolution
  312.       bPreload = true;
  313.     if (bPreload) {  // otherwise leave blank
  314.       Mesh* mesh = readMeshFile (path);
  315.       if (mesh)
  316. insertMesh (mesh, path, true, true, nRes);
  317.       //else
  318.       //cerr << "Mesh " << path 
  319.       //     << " named in .set file does not exist" << endl;
  320.     } else {         // insert dummy mesh
  321.       insertMesh (new Mesh, path, false, false, nRes);
  322.     }
  323.   }
  324.   popd();
  325.   //set default mesh according to .set file
  326.   if (!select_by_count (nDefaultRes))  // didn't find default
  327.     select_coarsest();                 // so set to lowest res
  328.   computeBBox();
  329.   return true;
  330. }
  331. bool 
  332. GenericScan::readSingleFile (const crope& fn)
  333. {
  334.   const char* filename = fn.c_str();
  335.   if (is_range_grid_file(filename)) {
  336.     RangeGrid* rangeGrid = new RangeGrid();
  337.     if (rangeGrid->readRangeGrid(filename) == 0) {
  338.   delete rangeGrid;
  339.   return false;
  340.     }
  341.     int subSamp = 1;
  342.     int nAutoGenRes = 4;
  343.     int iPolys = rangeGrid->numSamples * 2;
  344.     for (int i = 0; i < nAutoGenRes; i++) {
  345.       char name[PATH_MAX];
  346.       strcpy (name, filename);
  347.       char* ext = strrchr (name, '.');
  348.       if (ext == NULL)
  349. ext = name + strlen (name);
  350.       sprintf (ext, "_samp%d.ply", subSamp);
  351.       insertMesh (new Mesh, name, false, false, iPolys / subSamp);
  352.       subSamp *= (SubSampleBase * SubSampleBase);
  353.     }
  354.     myRangeGrid = rangeGrid;
  355.   } else {
  356.     
  357.     Mesh* mesh = readMeshFile (filename);
  358.     if (!mesh)
  359.       return false;
  360.     insertMesh (mesh, filename);
  361.   }
  362.   // set current directory here
  363.   set_name (filename);
  364.   setd();
  365.   select_coarsest();
  366.   computeBBox();
  367.   return true;
  368. }
  369. Mesh*
  370. GenericScan::readMeshFile (const char* name)
  371. {
  372.   Mesh* mesh = new Mesh;
  373.   cout << "Reading mesh " << name << "... " << flush;
  374.   if (!mesh->readPlyFile (name)) {
  375.     cout << "failed!" << endl;
  376.     delete mesh;
  377.     return NULL;
  378.   }
  379.   cout << "calculating normals... " << flush;
  380.   mesh->updateScale();
  381.   mesh->initNormals(UseAreaWeightedNormals);
  382.   cout << "done." << endl;
  383.   return mesh;
  384. }
  385. int
  386. GenericScan::create_resolution_absolute(int budget, Decimator dec)
  387. {
  388.   Mesh *origMesh = highestRes();
  389.   if (origMesh->num_tris() == 0) {
  390.     cerr <<  "No triangles in the original mesh" << endl;
  391.     return 0;
  392.   }
  393.   cerr << "targetSize = " << budget << endl;
  394.   cerr << "num meshes = " << num_resolutions() << endl;
  395.   Mesh *newMesh = origMesh->Decimate(budget, PLACE_OPTIMAL,
  396.      0, 1000, dec);
  397.   char numberEnding[20];
  398.   sprintf(numberEnding, ".%d.ply", newMesh->num_tris());
  399.   cerr << "output vertSize = " << newMesh->num_verts() << endl;
  400.   cerr << "output triSize = " << newMesh->num_tris() << endl;
  401.   newMesh->bNeedsSave = TRUE;   //mark that this is worth keeping
  402.   insertMesh(newMesh, basename + numberEnding);
  403.   computeBBox();
  404.   cerr << "new num meshes = " << num_resolutions() << endl;
  405.   theScene->invalidateDisplayCaches();
  406. #if 0
  407.   for (int i=0; i<meshes.size(); i++) {
  408.     cout << i << endl;
  409.     cout << meshes[i]->num_tris() << endl;
  410.     cout << meshes[i]->num_verts() << endl;
  411.     cout << meshes[i]->vtx[100] << endl;
  412.     cout << meshes[i]->nrm[100] << endl;
  413.     cout << meshes[i]->tris[100] << endl;
  414.   }
  415. #endif
  416.   bDirty = true;
  417.   return newMesh->num_tris();
  418. }
  419. bool
  420. GenericScan::delete_resolution (int nPolys)
  421. {
  422.   int iRes = findLevelForRes (nPolys);
  423.   if (iRes < 0) {
  424.     cerr << "FAILED: Attempt to delete resolution " << nPolys << endl;
  425.     return false;
  426.   }
  427.   delete meshes[iRes];
  428.   meshes.erase (&meshes[iRes]);
  429.   resolutions.erase (&resolutions[iRes]);
  430.   select_coarser();
  431.   return true;
  432. }
  433. void
  434. GenericScan::flipNormals (void)
  435. {
  436.   for (int i = 0; i < meshes.size(); i++)
  437.     meshes[i]->flipNormals();
  438.   bDirty = true;
  439. }
  440. void
  441. GenericScan::insertMesh(Mesh *m, const crope& filename,
  442.     bool bLoaded, bool bAlwaysLoad,
  443.     int nRes)
  444. {
  445.   // insert into resolution vector (sorted by vertex count)
  446.   if (nRes == 0)                  // allow override of
  447.     nRes = m->num_tris();         // temporary resolution
  448.   insert_resolution (nRes, filename, bLoaded, bAlwaysLoad);
  449.   // now add to mesh vector, sorted parallel to resolution vector
  450.   int iPos = findLevelForRes (nRes);
  451.   meshes.insert (&meshes[iPos], m);
  452.   kdtree.insert (&kdtree[iPos], NULL);
  453. }
  454. Mesh*
  455. GenericScan::currentMesh (void)
  456. {
  457.   int i = current_resolution_index();
  458.   if (!resolutions[i].in_memory) {
  459.     load_resolution (i);
  460.   }
  461.   return meshes[i];
  462. }
  463. bool
  464. GenericScan::load_resolution (int i)
  465. {
  466.   if (resolutions[i].in_memory)
  467.     return true;
  468.   Mesh* loaded = NULL;
  469.   if (myRangeGrid) {
  470.     // build mesh from range grid
  471.     int subSamp = 1;
  472.     for (int j = 0; j < i; j++) {
  473.       subSamp *= SubSampleBase;
  474.     }
  475.     loaded = myRangeGrid->toMesh(subSamp, false);
  476.     loaded->updateScale();
  477.     loaded->initNormals(UseAreaWeightedNormals);
  478.     loaded->bNeedsSave = true;
  479.   } else {
  480.     // mesh should be plyfile on disk
  481.     
  482.     pushd();
  483.     loaded = readMeshFile (resolutions[i].filename.c_str());
  484.     if (!loaded) {
  485.       popd();
  486.       return false;
  487.     }
  488.     popd();
  489.   }
  490.   delete meshes[i];
  491.   meshes[i] = loaded;
  492.   resolutions[i].in_memory = true;
  493.   resolutions[i].abs_resolution = loaded->num_tris();
  494.   computeBBox();
  495.   return true;
  496. }
  497. bool
  498. GenericScan::release_resolution (int nPolys)
  499. {
  500.   int iRes = findLevelForRes (nPolys);
  501.   if (iRes < 0) {
  502.     cerr << "FAILD: Attempt to release resolution " << nPolys << endl;
  503.     return false;
  504.   }
  505.   if (!resolutions[iRes].in_memory)
  506.     return true;
  507.   delete meshes[iRes];
  508.   meshes[iRes] = new Mesh;
  509.   resolutions[iRes].in_memory = false;
  510.   return true;
  511. }
  512. bool 
  513. GenericScan::getXformFilename (const char* meshName, char* xfName)
  514. {
  515.   const char* meshFile = meshName;
  516.   const char* dir = setdir.c_str();
  517.   int dirLen = strlen(dir);
  518.   if (dirLen && !strncmp (meshName, dir, dirLen))
  519.     meshFile += dirLen + 1;
  520.   return get_filename_new_ending (meshFile, ".xf", xfName);
  521. }
  522. KDindtree*
  523. GenericScan::get_current_kdtree()
  524. {
  525.   int iTree = current_resolution_index();
  526.   assert (iTree < kdtree.size());
  527.   if (kdtree[iTree] != NULL)
  528.     return kdtree[iTree];
  529.   Mesh* mesh = currentMesh();
  530.   kdtree[iTree] = CreateKDindtree(mesh->vtx.begin(), 
  531.   mesh->nrm.begin(),
  532.   mesh->vtx.size());
  533.   return kdtree[iTree];
  534. }
  535. bool
  536. GenericScan::closest_point(const Pnt3 &p, const Pnt3 &n, 
  537.    Pnt3 &cp, Pnt3 &cn,
  538.    float thr, bool bdry_ok)
  539. {
  540.   KDindtree* tree = get_current_kdtree();
  541.   if (!tree)
  542.     return false;
  543.   int ind, ans;
  544.   Mesh* mesh = currentMesh();
  545.   ans = tree->search(mesh->vtx.begin(), mesh->nrm.begin(), p, n, ind, thr);
  546.   if (ans) {
  547.     if (bdry_ok == 0) {
  548.       // disallow closest points that are on the mesh boundary
  549.       mesh->mark_boundary_verts();
  550.       if (mesh->bdry[ind]) return 0;
  551.     }
  552.     cp = mesh->vtx[ind];
  553.     short *sp = &mesh->nrm[ind*3];
  554.     cn.set(sp[0]/32767.0, 
  555.    sp[1]/32767.0, 
  556.    sp[2]/32767.0);
  557.   }
  558.   return ans;
  559. }
  560. crope
  561. GenericScan::getInfo (void)
  562. {
  563.   char info[512];
  564.   sprintf(info, "Polygon file: %ld resolutionsn"
  565.   "verts %d tris %ld strips %ldnn",
  566.   resolutions.size(),
  567.   currentMesh()->num_verts(), 
  568.   currentMesh()->tris.size() / 3,
  569.   currentMesh()->tstrips.size());
  570.   return crope(info) + RigidScan::getInfo();
  571. }
  572. Mesh*
  573. GenericScan::getMesh (int level)
  574. {
  575.   if (level >= meshes.size())
  576.     level = meshes.size() - 1;
  577.   if (level < 0) level = 0;
  578.   if (!resolutions[level].in_memory)
  579.     load_resolution (level);
  580.   return meshes[level];
  581. }
  582. inline Mesh*
  583. GenericScan::highestRes (void)
  584. {
  585.   return getMesh (0);
  586. }
  587. /* For each triangle in the ply file, this function
  588.    prints out the coordinates of the voxel from which
  589.    it came.  This function is called from plvClipBoxCmds.cc
  590.    which has already called filtered_copy to generate a list
  591.    of the trianlges enclosed by a user-specified box.
  592.    N.B.'s:
  593.    1. This feature should only be called on a *small* set of
  594.    polygons since information is printed out for every polygon
  595.    chosen.
  596.    2. This feature uses the same mechanism as clipping to decide
  597.    which polygons are inside the box.  So, just as clipping returns
  598.    polygons which are inside and facing the box as well as inside
  599.    and facing away from the box, this feature prints information
  600.    for all polygons regardless of whether they are forwards or
  601.    backwards facing.
  602.    - leslie 2001
  603. */
  604. void GenericScan::PrintVoxelInfo()
  605. {
  606.  printf("Printing voxel information...n"); 
  607.  
  608.  Mesh *mesh = currentMesh();
  609.  if (!mesh->hasVoxels) {
  610.    printf("There is no voxel information storedn"); return;
  611.  }
  612.  int triSize = mesh->getTris().size();
  613.  if (triSize != mesh->fromVoxels.size()) {
  614.    printf("Voxel information error: %d tris, %d voxelsn", triSize,
  615.   mesh->fromVoxels.size());
  616.    return;
  617.  }
  618.  for (int i = 0; i < triSize; i += 3) {
  619.    printf("Triangle with vertices atn");
  620.    printf("(%f, %f, %f), (%f, %f, %f), (%f, %f, %f)n",
  621.   mesh->vtx[mesh->tris[i]][0], mesh->vtx[mesh->tris[i]][1],
  622.   mesh->vtx[mesh->tris[i]][2],
  623.   mesh->vtx[mesh->tris[i+1]][0], mesh->vtx[mesh->tris[i+1]][1],
  624.   mesh->vtx[mesh->tris[i+1]][2],
  625.   mesh->vtx[mesh->tris[i+2]][0], mesh->vtx[mesh->tris[i+2]][1],
  626.   mesh->vtx[mesh->tris[i+2]][2]);
  627.    printf("came from voxel atn");
  628.    printf("(%f, %f, %f)n", mesh->fromVoxels[i], 
  629.   mesh->fromVoxels[i+1], mesh->fromVoxels[i+2]);
  630.  }
  631. }
  632. // copy the part of the mesh that is in the clip box
  633. // into the newMeshSet (clipmesh)
  634. RigidScan*
  635. GenericScan::filtered_copy(const VertexFilter& filter)
  636. {
  637.   int i, j;
  638.   GenericScan* newMeshSet = new GenericScan;
  639.   assert(newMeshSet != NULL);
  640.   Mesh *newMesh, *oldMesh;
  641.   newMeshSet->setXform(getXform());
  642.   for (j = 0; j < meshes.size(); j++) {
  643.     vector<int> newIndices;
  644.     newMesh = new Mesh;
  645.     oldMesh = getMesh(j);
  646.     // figure out which vertices remain
  647.     int vertCount = 0;
  648.     for (i = 0; i < oldMesh->num_verts(); i++) {
  649.       if (filter.accept (oldMesh->vtx[i])) {
  650. newIndices.push_back(1);
  651. vertCount++;
  652.       } else {
  653. newIndices.push_back(-1);
  654.       }
  655.     }
  656.     // and then which faces remain
  657.     int triCount = 0;
  658.     for (i = 0; i < oldMesh->getTris().size(); i += 3) {
  659.       if (newIndices[oldMesh->tris[i  ]] >= 0 &&
  660.   newIndices[oldMesh->tris[i+1]] >= 0 &&
  661.   newIndices[oldMesh->tris[i+2]] >= 0) {
  662. triCount++;
  663.       }
  664.     }
  665.     // copy other mesh properties
  666.     newMesh->hasVertNormals = oldMesh->hasVertNormals;
  667.     if (oldMesh->vertMatDiff != NULL)
  668.       newMesh->vertMatDiff = new vec3uc[vertCount];
  669.     if (oldMesh->vertIntensity != NULL)
  670.       newMesh->vertIntensity = new float[vertCount];
  671.     if (oldMesh->vertConfidence != NULL)
  672.       newMesh->vertConfidence = new float[vertCount];
  673.     if (oldMesh->texture != NULL)
  674.       newMesh->texture = new vec2f[vertCount];
  675.     if (oldMesh->triMatDiff != NULL)
  676.       newMesh->triMatDiff = new vec3uc[triCount];
  677.     // copy the surviving vertices
  678.     int count = 0;
  679.     newMesh->vtx.reserve (vertCount);
  680.     if (oldMesh->nrm.size())
  681.       newMesh->nrm.reserve (vertCount);
  682.     for (i = 0; i < oldMesh->num_verts(); i++) {
  683.       if (newIndices[i] > 0) {
  684. newIndices[i] = count;
  685. newMesh->copyVertFrom (oldMesh, i, count);
  686. count++;
  687.       }
  688.     }
  689.     // copy and reindex the surviving faces
  690.     count = 0;
  691.     newMesh->tris.reserve (triCount * 3);
  692.     for (i = 0; i < oldMesh->tris.size(); i += 3) {
  693.       if (newIndices[oldMesh->tris[i  ]] >= 0 &&
  694.   newIndices[oldMesh->tris[i+1]] >= 0 &&
  695.   newIndices[oldMesh->tris[i+2]] >= 0) {
  696. newMesh->copyTriFrom (oldMesh, i/3, count/3);
  697. newMesh->tris[count  ] = newIndices[oldMesh->tris[i  ]];
  698. newMesh->tris[count+1] = newIndices[oldMesh->tris[i+1]];
  699. newMesh->tris[count+2] = newIndices[oldMesh->tris[i+2]];
  700. // copy fromVoxels info - for voxel display feature
  701. if (oldMesh->hasVoxels) {
  702.   newMesh->fromVoxels[count] = oldMesh->fromVoxels[i];
  703.   newMesh->fromVoxels[count+1] = oldMesh->fromVoxels[i+1];
  704.   newMesh->fromVoxels[count+2] = oldMesh->fromVoxels[i+2];
  705. }
  706. count += 3;
  707.       }
  708.     }
  709.     // and finalize this resolution
  710.     newMesh->bNeedsSave = true;
  711.     newMesh->computeBBox();
  712.     // and insert it into new GenericScan
  713.     crope clipName(get_basename());
  714.     char info[20];
  715.     sprintf (info, "Clip.%d.ply", triCount);
  716.     clipName += info;
  717.     newMeshSet->insertMesh (newMesh, clipName);
  718.   }
  719.   // done!
  720.   newMeshSet->computeBBox();
  721.   newMeshSet->curr_res = curr_res;
  722.   return newMeshSet;
  723. }
  724. bool
  725. GenericScan::filter_inplace(const VertexFilter &filter)
  726. {
  727.   for (int iRes = 0; iRes < resolutions.size(); iRes++) {
  728.     vector<int> newIndices;
  729.     Mesh* newMesh = new Mesh;
  730.     Mesh* oldMesh = getMesh(iRes);
  731.     // figure out which vertices remain
  732.     int vertCount = 0;
  733.     for (int i = 0; i < oldMesh->num_verts(); i++) {
  734.       if (filter.accept (oldMesh->vtx[i])) {
  735. newIndices.push_back(1);
  736. vertCount++;
  737.       } else {
  738. newIndices.push_back(-1);
  739.       }
  740.     }
  741.     // and then which faces remain
  742.     int triCount = 0;
  743.     for (i = 0; i < oldMesh->getTris().size(); i += 3) {
  744.       if (newIndices[oldMesh->tris[i  ]] >= 0 &&
  745.   newIndices[oldMesh->tris[i+1]] >= 0 &&
  746.   newIndices[oldMesh->tris[i+2]] >= 0) {
  747. triCount++;
  748.       }
  749.     }
  750.     // copy other mesh properties
  751.     newMesh->hasVertNormals = oldMesh->hasVertNormals;
  752.     if (oldMesh->vertMatDiff != NULL)
  753.       newMesh->vertMatDiff = new vec3uc[vertCount];
  754.     if (oldMesh->vertIntensity != NULL)
  755.       newMesh->vertIntensity = new float[vertCount];
  756.     if (oldMesh->vertConfidence != NULL)
  757.       newMesh->vertConfidence = new float[vertCount];
  758.     if (oldMesh->texture != NULL)
  759.       newMesh->texture = new vec2f[vertCount];
  760.     if (oldMesh->triMatDiff != NULL)
  761.       newMesh->triMatDiff = new vec3uc[triCount];
  762.     // copy the surviving vertices
  763.     int count = 0;
  764.     newMesh->vtx.reserve (vertCount);
  765.     if (oldMesh->nrm.size())
  766.       newMesh->nrm.reserve (vertCount);
  767.     for (i = 0; i < oldMesh->num_verts(); i++) {
  768.       if (newIndices[i] > 0) {
  769. newIndices[i] = count;
  770. newMesh->copyVertFrom (oldMesh, i, count);
  771. count++;
  772.       }
  773.     }
  774.     // copy and reindex the surviving faces
  775.     count = 0;
  776.     newMesh->tris.reserve (triCount * 3);
  777.     for (i = 0; i < oldMesh->tris.size(); i += 3) {
  778.       if (newIndices[oldMesh->tris[i  ]] >= 0 &&
  779.   newIndices[oldMesh->tris[i+1]] >= 0 &&
  780.   newIndices[oldMesh->tris[i+2]] >= 0) {
  781. // newIndices holds renumbered vertices
  782. newMesh->copyTriFrom (oldMesh, i/3, count/3);
  783. newMesh->tris[count  ] = newIndices[oldMesh->tris[i  ]];
  784. newMesh->tris[count+1] = newIndices[oldMesh->tris[i+1]];
  785. newMesh->tris[count+2] = newIndices[oldMesh->tris[i+2]];
  786. // copy from voxel info if we're supporting clipping later
  787. // for voxel display feature
  788. //if (oldMesh->hasVoxels) {
  789. //newMesh->fromVoxels[count] = oldMesh->fromVoxels[i];
  790. //newMesh->fromVoxels[count+1] = oldMesh->fromVoxels[i+1];
  791. //newMesh->fromVoxels[count+2] = oldMesh->fromVoxels[i+2];
  792. //}
  793. count += 3;
  794.       }
  795.     }
  796.     // and finalize this resolution
  797.     newMesh->bNeedsSave = true;
  798.     newMesh->computeBBox();
  799.     // and insert it in place of original
  800.     delete oldMesh;
  801.     meshes[iRes] = newMesh;
  802.     resolutions[iRes].abs_resolution = newMesh->num_tris();
  803.     // nuke any kdtree for this resolution
  804.     delete kdtree[iRes];
  805.     kdtree[iRes] = NULL;
  806.   }
  807.   // done!
  808.   computeBBox();
  809.   bDirty = true;
  810.   return true;
  811. }
  812. bool
  813. GenericScan::filter_vertices (const VertexFilter& filter, vector<Pnt3>& p)
  814. {
  815.   Mesh* mesh = currentMesh();
  816.   Pnt3* vtxend = mesh->vtx.end();
  817.   for (Pnt3* pnt = mesh->vtx.begin(); pnt < vtxend; pnt++) {
  818.     if (filter.accept (*pnt))
  819.       p.push_back (*pnt);
  820.   }
  821.   return true;
  822. }
  823. bool
  824. GenericScan::is_modified (void)
  825. {
  826.   return bDirty;
  827. }
  828. bool
  829. GenericScan::write_metadata (MetaData data)
  830. {
  831.   bool success = false;
  832.   pushd();   // don't return without matching popd!
  833.   switch (data) {
  834.   case md_xform: {
  835.     success = TbObj::writeXform(get_basename());
  836.     break;
  837.   }
  838.   }
  839.   popd();
  840.   return success;
  841. }
  842. bool 
  843. GenericScan::write(const crope &fname)
  844. {
  845.   if (fname.empty()) {  // no filename given...
  846.     if (!bNameSet)      // and we don't already have one
  847.       return false;     // so bail
  848.   } else if (name != fname) {
  849.     cout << "Scan " << name << " being saved as " << fname << endl;
  850.     
  851.     // need to force all meshes to load before changing name
  852.     for (int i = 0; i < resolutions.size(); i++) {
  853.       load_resolution (i);
  854.       meshes[i]->bNeedsSave = true;
  855.     }
  856.     set_name (fname);
  857.     bNameSet = false;    // mark that we need to regenerate child names
  858.   }
  859.   if (ending == crope("set")) {
  860.   } else {
  861.     //need to generate .set name from current name
  862.     const char* dirName = strrchr (name.c_str(), '/');
  863.     if (dirName == NULL) {
  864.       dirName = name.c_str();
  865.     } else {
  866.       dirName++; // skip past the /
  867.     }
  868.     name += crope("/") + crope(dirName);
  869.     set_name (name + ".set");
  870.     cout << "Creating new set file " << name << endl;
  871.     setd (name, true);
  872.   }
  873.   cout << "Writing whole scan to " << name << endl;
  874.   ofstream out (name.c_str());
  875.   out << "NumMeshes = " << meshes.size() << endl;
  876.   out << "DefaultRes = " << meshes[current_resolution_index()]->num_tris()
  877.       << endl;
  878.   pushd();
  879.   for (int i = 0; i < meshes.size(); i++) {
  880.     if (!bNameSet) {
  881.       char stupidbuf[10];
  882.       sprintf (stupidbuf, "%d", meshes[i]->num_tris());
  883.       resolutions[i].filename = basename
  884. + "." + stupidbuf + ".ply";
  885.       // need to rename associated meshes
  886.     }
  887.     out << (resolutions[i].desired_in_mem ? "preload" : "noload") << " ";
  888.     out << resolutions[i].abs_resolution << " ";
  889.     out << resolutions[i].filename << endl;
  890.     if (resolutions[i].in_memory && meshes[i]->bNeedsSave) {
  891.       cout << "Writing mesh " << resolutions[i].filename << endl;
  892.       meshes[i]->writePlyFile(resolutions[i].filename.c_str(), true, false);
  893.     }
  894.   }
  895.   popd();
  896.   cout << "Done." << endl;
  897.   // save transform
  898.   write_metadata (md_xform);
  899.   bDirty = false;
  900.   bNameSet = true;
  901.   return true;
  902. }
  903. bool
  904. GenericScan::write_resolution_mesh (int nPolys, const crope& fname,
  905.     Xform<float> xfBy)
  906. {
  907.   if (!xfBy.isIdentity()) {
  908.     // can't handle this any better than default implementation
  909.     return RigidScan::write_resolution_mesh (nPolys, fname, xfBy);
  910.   }
  911.   int iRes = findLevelForRes (nPolys);
  912.   if (iRes < 0 || iRes >= resolutions.size())
  913.     return false;
  914.   crope& meshName = resolutions[iRes].filename;
  915.   if (!fname.empty())
  916.     meshName = fname;
  917.   if (meshName.empty())
  918.     return false;
  919.   cout << "Writing plyfile " << meshName << "... "<< flush;
  920.   bool ok = getMesh(iRes)->writePlyFile (meshName.c_str(), false, false);
  921.   if (ok)
  922.     cout << "done." << endl;
  923.   else
  924.     cout << "failed!" << endl;
  925.   return ok;
  926. }
  927. int 
  928. PlvWritePlyForVripCmd(ClientData clientData, 
  929.       Tcl_Interp *interp,
  930.       int argc, char* argv[])
  931. {
  932.   if (argc < 3) {
  933.       interp->result = 
  934. "Usage: PlvWritePlyForVripCmd <res level, 0=max> <dir> ";
  935.       return TCL_ERROR;
  936.   }
  937.   int iRes = atoi (argv[1]);
  938.   char* dir = argv[2];
  939.   portable_mkdir (dir, 00775);
  940.   char name[PATH_MAX];
  941.   crope result;
  942.   bool success = true;
  943.   // vrip can't read tstrips
  944.   char* oldStripVal = Tcl_GetVar (interp, "meshWriteStrips", 
  945.   TCL_GLOBAL_ONLY);
  946.   Tcl_SetVar (interp, "meshWriteStrips", "never", 
  947.       TCL_GLOBAL_ONLY);
  948.   char confFN[PATH_MAX];
  949.   sprintf (confFN, "%s/vrip.conf", dir);
  950.   ofstream conffile (confFN, ios::app);
  951.   DisplayableMesh** dm = theScene->meshSets.begin();
  952.   for (; dm < theScene->meshSets.end(); dm++) {
  953.     if (!(*dm)->getVisible())
  954.       continue;
  955.     RigidScan* sd = (*dm)->getMeshData();
  956.     GenericScan* gs = dynamic_cast<GenericScan*> (sd);
  957.     if (!gs)
  958.       continue;
  959.     vector<ResolutionCtrl::res_info> ri;
  960.     int thisIRes;
  961.     const char* filename = sd->get_basename().c_str();
  962.     const char* slash;
  963.     if (NULL != (slash = strrchr (filename, '/')))
  964.       filename = slash + 1;
  965.     else if (NULL != (slash = strrchr (filename, '\')))
  966.       filename = slash + 1;
  967.     sprintf(name, "%s/%s-v.ply", dir, filename);
  968.     if (access (name, R_OK)) {
  969.   cout << "Writing " << name << " ... " << flush;
  970.     } else {
  971.   cout << "Skipping " << name << " (already exists) ... " << endl;
  972.   continue;
  973.     }
  974.     sd->existing_resolutions (ri);
  975.     thisIRes = MIN (iRes, ri.size() - 1);
  976.     gs->load_resolution (thisIRes);
  977.     sd->existing_resolutions (ri);
  978.     int res = ri[thisIRes].abs_resolution;
  979.     if (res) {
  980.   
  981.   // write plyfile
  982.   if (!gs->write_resolution_mesh (res, name, Xform<float>())) {
  983.     cerr << "Scan " << sd->get_name() 
  984.  << " failed to write self!"  << endl;
  985.     return TCL_ERROR;
  986.   }
  987.   
  988.   cout << "done." << endl;
  989.   
  990.   // write config string:
  991.   // bmesh filename x y z i j k r
  992.   char bmesh[PATH_MAX + 200];
  993.   float t[3];
  994.   float q[4];
  995.   Xform<float> xf = sd->getXform();
  996.   xf.toQuaternion (q);
  997.   xf.getTranslation (t);
  998.   sprintf (bmesh, "bmesh %s %g %g %g %g %g %g %g", 
  999.    1+strrchr(name,'/'),
  1000.    t[0], t[1], t[2], -q[1], -q[2], -q[3], q[0]);
  1001.   
  1002.   // write xf
  1003.   strcpy (name + strlen(name) - 3, "xf");
  1004.   cout << "Writing " << name << " ... " << flush;
  1005.   ofstream xffile (name);
  1006.   xffile << xf;
  1007.   if (xffile.fail()) {
  1008.     cerr << "Scan " << sd->get_name() 
  1009.  << " failed to write xform!" << endl;
  1010.     success = false;
  1011.     break;
  1012.   }
  1013.   cout << "done." << endl;
  1014.   conffile << bmesh << endl;
  1015.     }
  1016.   }
  1017.   
  1018.   // cleanup
  1019.   Tcl_SetVar (interp, "meshWriteStrips", oldStripVal, 
  1020.       TCL_GLOBAL_ONLY);
  1021.   if (!success)
  1022.     return TCL_ERROR;
  1023.   return TCL_OK;
  1024. }
  1025. void GenericScan::dequantizationSmoothing(int iterations, double maxDisplacement)
  1026. {
  1027.   Mesh *mesh=currentMesh();
  1028.   // Get the original verts into both lists
  1029.   mesh->restoreOrigVerts();
  1030.   for (int i=0;i<iterations;i++)
  1031.     mesh->dequantizationSmoothing(maxDisplacement);
  1032. }
  1033. void GenericScan::commitSmoothingChanges()
  1034. {
  1035.   Mesh *mesh=currentMesh();
  1036.   // Copy the vtx -> orig_vtx, so the real orig is gone
  1037.   mesh->saveOrigVerts();
  1038. }