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

3D图形编程

开发平台:

Visual C++

  1. #include <iostream.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <limits.h>
  5. #include <vector.h>
  6. #include <hash_map.h>
  7. #include <assert.h>
  8. #include <math.h>
  9. #include "Mesh.h"
  10. #include "ply++.h"
  11. #include "Timer.h"
  12. #include "Random.h"
  13. #include "plvGlobals.h"
  14. #include "TriMeshUtils.h"
  15. #include "Progress.h"
  16. #include "plvScene.h"
  17. #if 0
  18. #  define VERBOSE 1
  19. #else
  20. #  define VERBOSE 0
  21. #endif
  22. Mesh::Mesh()
  23. {
  24.   init();
  25. }
  26. Mesh::Mesh (const vector<Pnt3>& _vtx, const vector<int>& _tris)
  27. {
  28.   init();
  29.   vtx = _vtx;
  30.   tris = _tris;
  31.   
  32.   initNormals(UseAreaWeightedNormals);
  33.   computeBBox();
  34. }
  35. void Mesh::init()
  36. {
  37.   vertMatDiff = NULL;
  38.   vertIntensity = NULL;
  39.   vertConfidence = NULL;
  40.   texture = NULL;
  41.   triMatDiff = NULL;
  42.   hasVertNormals = FALSE;
  43.   bNeedsSave = FALSE;
  44.   numTris = 0;
  45.   hasVoxels = FALSE;
  46. }
  47. Mesh::~Mesh()
  48. {
  49.   if (vertMatDiff != NULL)
  50.     delete [] vertMatDiff;
  51.   
  52.   if (vertIntensity != NULL)
  53.     delete [] vertIntensity;
  54.   
  55.   if (vertConfidence != NULL)
  56.     delete [] vertConfidence;
  57.   
  58.   if (texture != NULL)
  59.     delete [] texture;
  60.   
  61.   if (triMatDiff != NULL)
  62.     delete [] triMatDiff;
  63. }
  64. void
  65. Mesh::initNormals(int useArea)
  66. {
  67.   if (!hasVertNormals) {
  68.     if (tstrips.size())
  69.       getVertexNormals(vtx, tstrips, true, nrm, useArea);
  70.     else
  71.       getVertexNormals(vtx, tris, false, nrm, useArea);
  72.     hasVertNormals = true;
  73.   }
  74. }
  75. void 
  76. Mesh::flipNormals()
  77. {
  78.   if (tris.size())
  79.     flip_tris (tris, false);
  80.   if (tstrips.size())
  81.     flip_tris (tstrips, true);
  82.   int n = nrm.size();
  83.   for (int i = 0; i < n; i++)
  84.     nrm[i] = -nrm[i];
  85.   bNeedsSave = TRUE;
  86. }
  87. void
  88. Mesh::computeBBox()
  89. {
  90.   bbox.clear();
  91.   for (int i = 0; i < vtx.size(); i++) {
  92.     bbox.add(vtx[i]);
  93.   }
  94.   if (vtx.size() == 0) {
  95.     center = Pnt3();
  96.     radius = 0;
  97.   } else {
  98.     center = bbox.center();
  99.     radius = bbox.diag()*.5;
  100.   }
  101. }
  102. void
  103. Mesh::updateScale()
  104.   // this exists because Mesh is only used to read .ply files, and
  105.   // there's a lot of old legacy data that exists in meters instead
  106.   // of millimeters.  Not only will it display at the wrong scale
  107.   // (only a problem if you view it side-by-side with new data),
  108.   // but things that are typical sizes for a scan with the older
  109.   // CyberWare scanners, like the dragon (say 20 cm across), expressed in
  110.   // meters, will have dimensions on the scale of 0.01.  Inter-point
  111.   // spacing will be like .0001, and so cross products at triangle
  112.   // vertices will have norms below float thresholds.  Thus the normals
  113.   // used for lighting will be calculated incorrectly.  Unfortunately the
  114.   // headers of these files don't say whether they're measured in meters
  115.   // or millimeters.  So we'll try to guess from the size of the bbox.
  116. {
  117.   // if the largest dimension is smaller than 10, assume we're dealing
  118.   // with millimeters and scale everything up by 1000.
  119.   // will false-positive on millimeter-scale scans of objects smaller than 
  120.   // 1cm x 1cm x 1cm (and they'll look too big).
  121.   // will false-negative on meter-scale scans of objects bigger than 10m
  122.   // on any side (and they'll stay too small, and render black).
  123.   // will not affect ply conversions of Cyra data, whose dimensions are
  124.   // big enough to be in the bounds of the above test, because the test is 
  125.   // one-way, only growing things -- although if Cyra data were mistakenly 
  126.   // saved as meters, this test would probably not catch it (the false
  127.   // negative described above).
  128.   // But wait!  This hack sucks rocks for pvrip output.  Often
  129.   // you get one or two chunks that are too small, so they scale
  130.   // by 1000, and suddenly the viewing bbox is 1000x too big,
  131.   // and everything else is 1000x too small (in comparison) and
  132.   // so you only see that tiny chunk (or nothing at all) when
  133.   // the viewer pops up.  You have to find and delete the scan
  134.   // that got multiplied before you can rescale the viewer to
  135.   // be able to see the rest of the mesh. UGLY Hack.  Turning
  136.   // it off, legacy crud be damned.  -- Lucas
  137.   computeBBox();
  138. #if 0
  139.   if (bbox.maxDim() < 10) {
  140.     cerr << "Warning: scaling mesh from meters to millimeters" << endl;
  141.     for (Pnt3* vp = vtx.begin(); vp != vtx.end(); vp++) {
  142.       *vp *= 1000;
  143.     }
  144.     computeBBox();
  145.   }
  146. #endif
  147. }
  148. int
  149. Mesh::num_tris (void)
  150. {
  151.   if (tris.size())
  152.     return (numTris = tris.size() / 3);
  153.   if (numTris)
  154.     return numTris;
  155.   // ok, have to count tstrips
  156.   numTris = tstrips.size();
  157.   for (const int* ti = tstrips.begin(); ti < tstrips.end(); ti++) {
  158.     if ((*ti) == -1)
  159.       numTris -= 3;
  160.   }
  161.   return numTris;
  162. }
  163. vector<int>&
  164. Mesh::getTris (void)
  165. {
  166.   if (!tris.size()) {
  167.     strips_to_tris(tstrips, tris, numTris);
  168.     printf ("rehydrated %d trisn", num_tris());
  169.   }
  170.   return tris;
  171. }
  172. vector<int>&
  173. Mesh::getTstrips (void)
  174. {
  175.   if (!tstrips.size()) {
  176. #if VERBOSE
  177.     TIMER(Build_t_strips);
  178. #endif
  179.     tris_to_strips(vtx.size(), tris, tstrips);
  180.   }
  181.   return tstrips;
  182. }
  183. void
  184. Mesh::freeTris (void)
  185. {
  186.   if (tstrips.size() == 0)
  187.     printf ("Cannot free triangles because strips don't existn");
  188.   else {
  189.     tris.clear();
  190.     delete [] triMatDiff;
  191.     triMatDiff = NULL;
  192.   }
  193. }
  194. void
  195. Mesh::freeTStrips (void)
  196. {
  197.   if (tris.size() == 0)
  198.     printf ("Cannot free tstrips because separate triangles don't existn");
  199.   else {
  200.     tstrips.clear();
  201.   }
  202. }
  203. // src and dst are indices to the triangle face (i.e., vertex face / 3).
  204. void
  205. Mesh::copyTriFrom (Mesh *meshSrc, int src, int dst)
  206. {
  207.   if (meshSrc->hasVoxels) this->hasVoxels = true;
  208.   for (int i = 0; i < 3; i++) {
  209.     // make sure triangle is within bounds of vector
  210.     assert(3*dst+i <= this->tris.size());
  211.     if (3*dst+i < this->tris.size()) {
  212.       this->tris[3*dst+i] = meshSrc->tris[3*src+i];
  213.       // copy voxel in - for voxel display feature
  214.       if (meshSrc->hasVoxels) 
  215. this->fromVoxels[3*dst+i] = meshSrc->fromVoxels[3*src+i];
  216.       
  217.     } else {  // adding to the end
  218.       this->tris.push_back (meshSrc->tris[3*src+i]);
  219.       if (meshSrc->hasVoxels) 
  220. this->fromVoxels.push_back(meshSrc->fromVoxels[3*src+i]);
  221.       
  222.     }
  223.   }
  224.     
  225.   if (meshSrc->triMatDiff != NULL) {
  226.     this->triMatDiff[dst][0] = meshSrc->triMatDiff[src][0];
  227.     this->triMatDiff[dst][1] = meshSrc->triMatDiff[src][1];
  228.     this->triMatDiff[dst][2] = meshSrc->triMatDiff[src][2];
  229.   }
  230. }
  231. void
  232. Mesh::copyVertFrom (Mesh *meshSrc, int src, int dst)
  233. {
  234.   assert (dst <= this->vtx.size());
  235.   if (dst < this->vtx.size())
  236.     this->vtx[dst] = meshSrc->vtx[src];
  237.   else
  238.     this->vtx.push_back(meshSrc->vtx[src]);
  239.   if (this->nrm.capacity() && meshSrc->nrm.size()) {
  240.     int nd = 3 * dst;
  241.     int ns = 3 * src;
  242.     if (nd < this->nrm.size()) {
  243.       this->nrm[nd  ] = meshSrc->nrm[ns  ];
  244.       this->nrm[nd+1] = meshSrc->nrm[ns+1];
  245.       this->nrm[nd+2] = meshSrc->nrm[ns+2];
  246.     } else {
  247.       this->nrm.push_back(meshSrc->nrm[ns  ]);
  248.       this->nrm.push_back(meshSrc->nrm[ns+1]);
  249.       this->nrm.push_back(meshSrc->nrm[ns+2]);
  250.     }
  251.   }
  252.   
  253.   if (meshSrc->vertMatDiff != NULL) {
  254.     this->vertMatDiff[dst][0] = meshSrc->vertMatDiff[src][0];
  255.     this->vertMatDiff[dst][1] = meshSrc->vertMatDiff[src][1];
  256.     this->vertMatDiff[dst][2] = meshSrc->vertMatDiff[src][2];
  257.   }
  258.   
  259.   if (meshSrc->vertIntensity != NULL) {
  260.     this->vertIntensity[dst] = meshSrc->vertIntensity[src];
  261.   }
  262.   
  263.   if (meshSrc->vertConfidence != NULL) {
  264.     this->vertConfidence[dst] = meshSrc->vertConfidence[src];
  265.   }
  266.   
  267.   if (meshSrc->texture != NULL) {
  268.     this->texture[dst][0] = meshSrc->texture[src][0];
  269.     this->texture[dst][1] = meshSrc->texture[src][1];
  270.   }
  271. }
  272. void
  273. Mesh::mark_boundary_verts(void)
  274. {
  275.   if (bdry.size()) return;
  276.   // initialize the boundary flags
  277.   //bdry.erase(bdry.begin(), bdry.end());
  278.   bdry.insert(bdry.end(), vtx.size(), 0);
  279.   ::mark_boundary_verts(bdry, getTris());
  280. }
  281. void plycrunch_simplify (const vector<Pnt3>& vtx, const vector<int>& tris,
  282.  vector<Pnt3>& outVtx, vector<int>& outTris,
  283.  int approxDesired);
  284. Mesh *
  285. Mesh::Decimate(int numFaces, int optLevel,
  286.        float errLevel, float boundWeight,
  287.        ResolutionCtrl::Decimator dec)
  288. {
  289.   Mesh  *outMesh = new Mesh();
  290.   switch (dec) {
  291.   case ResolutionCtrl::decQslim:
  292.     quadric_simplify(vtx, getTris(), outMesh->vtx, outMesh->tris,
  293.      numFaces, optLevel, errLevel, boundWeight);
  294.     break;
  295.   case ResolutionCtrl::decPlycrunch:
  296.     plycrunch_simplify (vtx, getTris(), outMesh->vtx, outMesh->tris, numFaces);
  297.     break;
  298.   default:
  299.     cerr << "Mesh::Decimate: unsupported decimator " << dec << endl;
  300.     delete outMesh;
  301.     return NULL;
  302.   }
  303.   outMesh->initNormals(0);
  304.   outMesh->computeBBox();
  305.   return outMesh;
  306. }
  307. struct PlyVertex {
  308.   float x, y, z;
  309.   float nx, ny, nz;
  310.   uchar diff_r, diff_g, diff_b;
  311.   float tex_u, tex_v;
  312.   float intensity;
  313.   float std_dev;
  314.   float confidence;
  315. };
  316. const int MAX_FACE_VERTS = 100;
  317. /* Added field to hold voxel from which the face was derived 
  318.    - for voxel display feature */
  319. struct PlyFace {
  320.   uchar nverts;
  321.   int verts[MAX_FACE_VERTS];
  322.   float fromVoxelX, fromVoxelY, fromVoxelZ;
  323. };
  324. struct CoordConfVert {
  325.    float v[3];
  326.    float conf;
  327. };
  328. struct TriLocal {
  329.    uchar nverts;
  330.    int index[3];
  331. };
  332. static PlyProperty vert_prop_x =  
  333.    {"x", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  334. static PlyProperty vert_prop_y =  
  335.   {"y", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  336. static PlyProperty vert_prop_z =  
  337.   {"z", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  338. static PlyProperty vert_prop_nx =  
  339.    {"nx", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  340. static PlyProperty vert_prop_ny =  
  341.   {"ny", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  342. static PlyProperty vert_prop_nz =  
  343.   {"nz", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  344. static PlyProperty vert_prop_texture_u =  
  345.   {"texture_u", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  346. static PlyProperty vert_prop_texture_v =  
  347.   {"texture_v", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  348. static PlyProperty vert_prop_intens =  
  349.   {"intensity", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  350. static PlyProperty vert_prop_std_dev =  
  351.   {"std_dev", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  352. static PlyProperty vert_prop_confidence =  
  353.   {"confidence", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  354. static PlyProperty vert_prop_diff_r =  
  355.   {"diffuse_red", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  356. static PlyProperty vert_prop_diff_g =  
  357.   {"diffuse_green", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  358. static PlyProperty vert_prop_diff_b =  
  359.   {"diffuse_blue", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  360. /* Added another face_prop that holds data for the voxel from which
  361.    the face was derived - for voxel display feature */
  362. static PlyProperty face_props[] = { 
  363.   {"vertex_indices", PLY_INT, PLY_INT, 0, 1, PLY_UCHAR, PLY_UCHAR, 0},
  364. };
  365. static PlyProperty face_prop_from_voxel_x =
  366.   {"from_voxel_x", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  367. static PlyProperty face_prop_from_voxel_y =
  368.   {"from_voxel_y", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  369. static PlyProperty face_prop_from_voxel_z =
  370.   {"from_voxel_z", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
  371. struct tstrip_info {
  372.   int nverts;
  373.   int* vertData;
  374. };
  375. static PlyProperty tstrips_props[] = {
  376.   {"vertex_indices", PLY_INT, PLY_INT, 4, 1, PLY_INT, PLY_INT, 0},
  377. };
  378. static void
  379. set_offsets(void)
  380. {
  381.   static int first = 1;
  382.   if (first) {
  383.     first = 0;
  384.     vert_prop_x.offset          = offsetof(PlyVertex,x);
  385.     vert_prop_y.offset          = offsetof(PlyVertex,y);
  386.     vert_prop_z.offset          = offsetof(PlyVertex,z);
  387.     vert_prop_nx.offset         = offsetof(PlyVertex,nx);
  388.     vert_prop_ny.offset         = offsetof(PlyVertex,ny);
  389.     vert_prop_nz.offset         = offsetof(PlyVertex,nz);
  390.     vert_prop_intens.offset     = offsetof(PlyVertex, intensity);
  391.     vert_prop_std_dev.offset    = offsetof(PlyVertex, std_dev);
  392.     vert_prop_confidence.offset = offsetof(PlyVertex, confidence);
  393.     vert_prop_diff_r.offset     = offsetof(PlyVertex,diff_r);
  394.     vert_prop_diff_g.offset     = offsetof(PlyVertex,diff_g);
  395.     vert_prop_diff_b.offset     = offsetof(PlyVertex,diff_b);
  396.     vert_prop_texture_u.offset  = offsetof(PlyVertex,tex_u);
  397.     vert_prop_texture_v.offset  = offsetof(PlyVertex,tex_v);
  398.     tstrips_props[0].offset     = offsetof(tstrip_info,vertData);
  399.   }
  400. }
  401. static const int progress_update = 0xfff;
  402. int  
  403. Mesh::readPlyFile(const char *filename)
  404. {
  405.   int i, j;
  406.   int nelems;
  407.   char **elist;
  408.   char **obj_info;
  409.   int num_obj_info;
  410.   char *elem_name;
  411.   int nprops;
  412.   int num_elems;
  413.   int hasConfidence = 0;
  414.   //int hasIntensity = 0;
  415.   //int hasStdDev = 0;
  416.   int hasDiffuseColors = 0;
  417.   int hasTexture = 0;
  418.   int notATriangleMesh = 0;
  419.   int skipTexture = 1;
  420. #if VERBOSE
  421.   TIMER(Read_ply_file);
  422. #endif
  423.   face_props[0].offset = offsetof(PlyFace, verts);
  424.   face_props[0].count_offset = offsetof(PlyFace, nverts);
  425.   // face_prop offsets for voxel display feature
  426.   face_prop_from_voxel_x.offset = offsetof(PlyFace, fromVoxelX);
  427.   face_prop_from_voxel_y.offset = offsetof(PlyFace, fromVoxelY);
  428.   face_prop_from_voxel_z.offset = offsetof(PlyFace, fromVoxelZ);
  429.     
  430.   PlyFile ply;
  431.   if (ply.open_for_reading((char*)filename, &nelems, &elist) == 0)
  432.     return 0;
  433.   // Look for a texture file reference
  434.   char temp[PATH_MAX];
  435.   obj_info = ply.get_obj_info (&num_obj_info);
  436.   for (i = 0; i < num_obj_info; i++) {
  437.     if (strstr(obj_info[i], "texture_file")) {
  438.       sscanf(obj_info[i], "%s%s", temp, texFileName);
  439.       FILE *fp = fopen(texFileName, "r");
  440.       if (fp != NULL) {
  441. fclose(fp);
  442. skipTexture = 0;
  443.       } else {
  444. texFileName[0] = 0;
  445.       }
  446.     }
  447.   }
  448.    
  449.   vector<PlyProperty> vert_props;
  450.   set_offsets();
  451.   PlyVertex plyVert;
  452.   PlyFace plyFace;
  453.   for (i = 0; i < nelems; i++) {
  454.     // get the description of the first element
  455.     elem_name = elist[i];
  456.     ply.get_element_description(elem_name, &num_elems, &nprops);
  457.     // if we're on vertex elements, read them in
  458.     if (equal_strings ("vertex", elem_name)) {
  459.    
  460. #if VERBOSE 
  461.       TIMER(Read_vertices);
  462. #endif
  463.       vtx.reserve(num_elems);
  464.     
  465.       if (ply.is_valid_property("vertex", vert_prop_x.name) &&
  466.   ply.is_valid_property("vertex", vert_prop_y.name) &&
  467.   ply.is_valid_property("vertex", vert_prop_z.name)) {
  468. ply.get_property(elem_name, &vert_prop_x);
  469. ply.get_property(elem_name, &vert_prop_y);
  470. ply.get_property(elem_name, &vert_prop_z);
  471.       }
  472.   
  473.       if (ply.is_valid_property("vertex", vert_prop_nx.name) &&
  474.   ply.is_valid_property("vertex", vert_prop_ny.name) &&
  475.   ply.is_valid_property("vertex", vert_prop_nz.name) ) {
  476. ply.get_property(elem_name, &vert_prop_nx);
  477. ply.get_property(elem_name, &vert_prop_ny);
  478. ply.get_property(elem_name, &vert_prop_nz);
  479. hasVertNormals = 1;
  480. nrm.reserve(num_elems * 3);
  481.       }
  482.   
  483.       if (ply.is_valid_property("vertex", vert_prop_intens.name)) {
  484. ply.get_property(elem_name, &vert_prop_intens);
  485. //hasIntensity = 1;
  486.       }
  487.     
  488.       if (ply.is_valid_property("vertex", vert_prop_std_dev.name)){
  489. ply.get_property(elem_name, &vert_prop_std_dev);
  490. //hasStdDev = 1;
  491.       }
  492.     
  493.       if (ply.is_valid_property("vertex", 
  494. vert_prop_confidence.name)) {
  495. ply.get_property(elem_name, &vert_prop_confidence);
  496. hasConfidence = 1;
  497. vertConfidence = new float[num_elems];
  498.       }
  499.     
  500.       if (ply.is_valid_property("vertex", "diffuse_red") &&
  501.   ply.is_valid_property("vertex", "diffuse_green") &&
  502.   ply.is_valid_property("vertex", "diffuse_blue")) {
  503. ply.get_property(elem_name, &vert_prop_diff_r);
  504. ply.get_property(elem_name, &vert_prop_diff_g);
  505. ply.get_property(elem_name, &vert_prop_diff_b);
  506. hasDiffuseColors = 1;
  507. vertMatDiff = new vec3uc[num_elems];
  508.       }
  509.     
  510.       if (!skipTexture) {
  511. if (ply.is_valid_property("vertex", "texture_u") &&
  512.     ply.is_valid_property("vertex", "texture_v")) {
  513.   ply.get_property(elem_name, &vert_prop_texture_u);
  514.   ply.get_property(elem_name, &vert_prop_texture_v);
  515.   hasTexture = 1;
  516.   texture = new vec2f[num_elems];
  517. }
  518.       }
  519.       Progress progress (num_elems, "%s: read vertices", filename);
  520.       // grab all the vertex elements
  521.       for (j = 0; j < num_elems; j++) {
  522. if ((j & progress_update) == progress_update)
  523.   progress.update (j);
  524. ply.get_element ((void *) &plyVert);
  525. vtx.push_back(Pnt3(plyVert.x, plyVert.y, plyVert.z));
  526. if (hasVertNormals)
  527.   pushNormalAsShorts (nrm, Pnt3(plyVert.nx, plyVert.ny, plyVert.nz));
  528. if (hasDiffuseColors) {
  529.   vertMatDiff[j][0] = plyVert.diff_r;
  530.   vertMatDiff[j][1] = plyVert.diff_g;
  531.   vertMatDiff[j][2] = plyVert.diff_b;
  532. }
  533. if (hasConfidence) {
  534.   vertConfidence[j] = plyVert.confidence;
  535. }
  536. if (hasTexture) {
  537.   texture[j][0] = plyVert.tex_u;
  538.   texture[j][1] = plyVert.tex_v;
  539. }
  540.       }
  541.     }
  542.     if (equal_strings ("face", elem_name)) {
  543. #if VERBOSE
  544.       TIMER(Read_faces);
  545. #endif
  546.       ply.get_property(elem_name, face_props);
  547.       /* check to see if we have voxel information for voxel
  548.          display feature */
  549.       if (ply.is_valid_property("face", "from_voxel_x")
  550.   || ply.is_valid_property("face", "from_voxel_y")
  551.   || ply.is_valid_property("face", "from_voxel_z")) {
  552. printf("Voxel information present...n");
  553. ply.get_property(elem_name, &face_prop_from_voxel_x);
  554. ply.get_property(elem_name, &face_prop_from_voxel_y);
  555. ply.get_property(elem_name, &face_prop_from_voxel_z);
  556. hasVoxels = 1;
  557.       } else printf("No voxel information stored...n");
  558.       
  559.       if (num_elems == 0)
  560. continue;
  561.       assert(tris.size() == 0);
  562.       tris.reserve (num_elems * 3);
  563.       Progress progress (num_elems, "%s: read tris", filename);
  564.       for (j = 0; j < num_elems; j++) {
  565. if ((j & progress_update) == progress_update)
  566.   progress.update (j);
  567. ply.get_element_noalloc((void *) &plyFace);
  568. if (plyFace.nverts != 3)
  569.   notATriangleMesh = 1;
  570. assert(plyFace.nverts <= MAX_FACE_VERTS);
  571. addTri(plyFace.verts[0],
  572.        plyFace.verts[1],
  573.        plyFace.verts[2]);
  574. if (hasVoxels) {
  575.   /* printf("adding voxel %f, %f, %fn",
  576.  plyFace.fromVoxelX, plyFace.fromVoxelY,
  577.  plyFace.fromVoxelZ); */
  578.   /* store voxel here - for voxel display feature */
  579.   
  580.   addVoxelInfo(plyFace.verts[0], plyFace.verts[1],
  581.        plyFace.verts[2],
  582.        plyFace.fromVoxelX, plyFace.fromVoxelY,
  583.        plyFace.fromVoxelZ);
  584. }
  585. //delete[] plyFace.verts;
  586.       }
  587.       if (notATriangleMesh) {
  588. cerr << "readPlyFile: Not a triangle mesh!" << endl;
  589.       }
  590.     }
  591.     if (equal_strings ("tristrips", elem_name)) {
  592.       tstrip_info info;
  593.       if (num_elems != 1)
  594. continue;
  595. #if VERBOSE
  596.       TIMER(Read_stripped_faces);
  597. #endif
  598.       ply.get_property (elem_name, tstrips_props);
  599.       ply.get_element ((void*)&info);
  600.       tstrips.reserve (info.nverts);
  601.       Progress progress (info.nverts, "%s: read t-strips", filename);
  602.       int lastend = 0;
  603.       for (int iv = 0; iv < info.nverts; iv++) {
  604. if ((iv & progress_update) == progress_update)
  605.   progress.update (iv);
  606. int vert = info.vertData[iv];
  607. bool ok = (vert >= 0 && vert < vtx.size())
  608.   || (vert == -1 && lastend >= 3);
  609. if (ok) {
  610.   // middle of strip
  611.   tstrips.push_back (vert);
  612.   if (vert == -1)
  613.     lastend = 0;
  614.   else
  615.     ++lastend;
  616. } else {
  617.   cerr << "nnRed alert: invalid index " << vert
  618.        << " in tstrip (index = " << iv
  619.        << ", valid range=0.." << vtx.size() - 1
  620.        << ")n" << endl;
  621.   // remove last strip
  622.   if (lastend) {
  623.     while (--lastend)
  624.       tstrips.pop_back();
  625.   }
  626. }
  627.       }
  628.     }
  629.   }
  630.   return 1;
  631. }
  632. int
  633. Mesh::writePlyFile (const char *filename, int useColorNotTexture, 
  634.     int writeNormals)
  635. {
  636. #if 1
  637.   vector<int>* pInds = NULL;
  638.   bool bStrips = false;
  639.   vector<uchar> color;
  640.   vector<float> conf;
  641.   if (theScene->meshes_written_stripped()) {
  642.     pInds = &getTstrips();
  643.     bStrips = true;
  644.   } else {
  645.     pInds = &getTris();
  646.     bStrips = false;
  647.   }
  648.   if (vertMatDiff) {
  649.     color.reserve (vtx.size() * 3);
  650.     for (int i = 0; i < vtx.size(); i++) {
  651.       color.push_back (vertMatDiff[i][0]);
  652.       color.push_back (vertMatDiff[i][1]);
  653.       color.push_back (vertMatDiff[i][2]);
  654.     }
  655.   } else if (vertIntensity) {
  656.     color.reserve (vtx.size());
  657.     for (int i = 0; i < vtx.size(); i++)
  658.       color.push_back (vertIntensity[i]);
  659.   }
  660.   if (vertConfidence) {
  661.     conf.reserve (vtx.size());
  662.     for (int i = 0; i < vtx.size(); i++)
  663.       conf.push_back (vertConfidence[i]);
  664.   }
  665.   if (color.size())
  666.     if (conf.size())
  667.       write_ply_file (filename, vtx, *pInds, bStrips, color, conf);
  668.     else
  669.       write_ply_file (filename, vtx, *pInds, bStrips, color);
  670.   else
  671.     if (conf.size())
  672.       write_ply_file (filename, vtx, *pInds, bStrips, conf);
  673.     else
  674.       write_ply_file (filename, vtx, *pInds, bStrips);
  675.   return true;
  676. #else
  677.   int i;
  678.   char *elem_names[] = {"vertex", "face"};
  679.   int hasIntensity  = vertIntensity != NULL;
  680.   int hasColor      = vertMatDiff != NULL;
  681.   int hasConfidence = vertConfidence != NULL;
  682.   int hasTexture    = texture != NULL;
  683.   PlyFile ply;
  684.   if (!ply.open_for_writing((char*)filename, 2, elem_names,PLY_BINARY_BE))
  685.     return 0;
  686.   if (hasTexture && !useColorNotTexture) {
  687.     char obj_info[PATH_MAX];
  688.     sprintf(obj_info, "%s %s", "texture_file", texFileName);
  689.     ply.put_obj_info(obj_info);
  690.   }
  691.   vector<PlyProperty> vert_props;
  692.   set_offsets();
  693.   vert_props.push_back(vert_prop_x);
  694.   vert_props.push_back(vert_prop_y);
  695.   vert_props.push_back(vert_prop_z);
  696.   if (writeNormals) {
  697.     vert_props.push_back(vert_prop_nx);
  698.     vert_props.push_back(vert_prop_ny);
  699.     vert_props.push_back(vert_prop_nz);
  700.   }
  701.   if (hasIntensity) {
  702.     vert_props.push_back(vert_prop_intens);
  703.   }
  704.     
  705.   if (hasConfidence) {
  706.     vert_props.push_back(vert_prop_confidence);
  707.     hasConfidence = 1;
  708.   }
  709.     
  710.   if (hasColor || (hasTexture && useColorNotTexture)) {
  711.     vert_props.push_back(vert_prop_diff_r);
  712.     vert_props.push_back(vert_prop_diff_g);
  713.     vert_props.push_back(vert_prop_diff_b);
  714.   }
  715.     
  716.   if (hasTexture && !useColorNotTexture) {
  717.     vert_props.push_back(vert_prop_texture_u);
  718.     vert_props.push_back(vert_prop_texture_v);
  719.   }
  720.   // count offset
  721.   face_props[0].offset = offsetof(PlyFace, verts);
  722.   face_props[0].count_offset = offsetof(PlyFace, nverts);
  723.   
  724.   ply.describe_element("vertex", vtx.size(), 
  725.        vert_props.size(), &vert_props[0]);
  726.   ply.describe_element("face", tris.size()/3, 1, face_props);
  727.   ply.header_complete();
  728.     
  729.     // set up and write the vertex elements
  730.   PlyVertex plyVert;
  731.   ply.put_element_setup("vertex");
  732.   for (i = 0; i < vtx.size(); i++) {
  733.     plyVert.x = vtx[i][0];
  734.     plyVert.y = vtx[i][1];
  735.     plyVert.z = vtx[i][2];
  736.     if (hasIntensity)
  737.       plyVert.intensity = vertIntensity[i];
  738.     
  739.     if (hasConfidence)
  740.       plyVert.confidence = vertConfidence[i];
  741.     
  742.     if (hasColor) {
  743.       plyVert.diff_r = vertMatDiff[i][0];
  744.       plyVert.diff_g = vertMatDiff[i][1];
  745.       plyVert.diff_b = vertMatDiff[i][2];
  746.     }
  747.     if (writeNormals) {
  748.       plyVert.nx = nrm[i][0];
  749.       plyVert.ny = nrm[i][1];
  750.       plyVert.nz = nrm[i][2];
  751.     }
  752.     /*
  753.     if (hasTexture && !useColorNotTexture) {
  754.       plyVert.tex_u = texture[i][0];
  755.       plyVert.tex_v = texture[i][1];
  756.     } 
  757.     else if (hasTexture && useColorNotTexture) {
  758.       float texU = texture[i][0];
  759.       float texV = texture[i][1];
  760.       int xOff = int(texU*meshSet->texXdim);
  761.       int yOff = int(texV*meshSet->texYdim);
  762.       // shouldn't that be texXdim, not texYdim*yOff ??
  763.       uchar *col = &meshSet->
  764. texture[3*(xOff + meshSet->texYdim*yOff)];
  765.       plyVert.diff_r = col[0];
  766.       plyVert.diff_g = col[1];
  767.       plyVert.diff_b = col[2];
  768.     }
  769.     */
  770.     ply.put_element((void *) &plyVert);
  771.   }
  772.   PlyFace plyFace;
  773.   ply.put_element_setup("face");
  774.   for (i = 0; i < tris.size(); i+=3) {
  775.     plyFace.nverts = 3;
  776.     plyFace.verts[0] = tris[i+0];
  777.     plyFace.verts[1] = tris[i+1];
  778.     plyFace.verts[2] = tris[i+2];
  779.     ply.put_element_static_strg((void *) &plyFace);
  780.   }
  781.   return 1;  
  782. #endif
  783. }
  784. static Random rnd;
  785. void
  786. Mesh::subsample_points(float rate, vector<Pnt3> &pts)
  787. {
  788.   subsample_points(int(rate*vtx.size()), pts);
  789. }
  790. void
  791. Mesh::subsample_points(float rate, vector<Pnt3> &pts,
  792.        vector<Pnt3> &nrms)
  793. {
  794.   subsample_points(int(rate*vtx.size()), pts, nrms);
  795. }
  796. bool
  797. Mesh::subsample_points(int n, vector<Pnt3> &pts)
  798. {
  799.   pts.clear(); pts.reserve(n);
  800.   double nv = vtx.size();
  801.   if (n > nv) return 0;
  802.   double np = n;
  803.   int end = nv;
  804.   for (int i = 0; i<end; i++) {
  805.     if (rnd(nv) <= np) {
  806.       pts.push_back(vtx[i]);   // save point
  807.       np--;
  808.     }
  809.     nv--;
  810.   }
  811.   assert(np == 0);
  812.   return 1;
  813. }
  814. bool
  815. Mesh::subsample_points(int n, vector<Pnt3> &pts, 
  816.        vector<Pnt3> &nrms)
  817. {
  818.   pts.clear(); pts.reserve(n);
  819.   nrms.clear(); nrms.reserve(n);
  820.   double nv = vtx.size();
  821.   if (n > nv) return 0;
  822.   double np = n;
  823.   int end = nv;
  824.   for (int i = 0; i<end; i++) {
  825.     if (rnd(nv) <= np) {
  826.       pts.push_back(vtx[i]);    // save point
  827.       pushNormalAsPnt3 (nrms, nrm.begin(), i);
  828.       np--;
  829.     }
  830.     nv--;
  831.   }
  832.   assert(np == 0);
  833.   return 1;
  834. }
  835. void
  836. Mesh::remove_unused_vtxs(void)
  837. {
  838.   // prepare vertex index map
  839.   vector<int> vtx_ind(vtx.size(), -1);
  840.   
  841.   // march through the triangles
  842.   // and mark the vertices that are actually used
  843.   int n = getTris().size();
  844.   for (int i=0; i<n; i++) {
  845.     assert (tris[i] >= 0 && tris[i] < vtx.size());
  846.     vtx_ind[tris[i]] = tris[i];
  847.   }
  848.   // remove the vertices that were not marked,
  849.   // also keep tab on how the indices change
  850.   int cnt = 0;
  851.   n = vtx.size();
  852.   for (i=0; i<n; i++) {
  853.     if (vtx_ind[i] != -1) {
  854.       vtx_ind[i] = cnt;
  855.       copyVertFrom (this, i, cnt);
  856.       cnt++;
  857.     }
  858.   }
  859.   vtx.erase(&vtx[cnt], vtx.end());
  860.   if (nrm.size()) nrm.erase(&nrm[cnt*3], nrm.end());
  861.   // march through triangles and correct the indices
  862.   n = tris.size();
  863.   for (i=0; i<n; i++) {
  864.     tris[i] = vtx_ind[tris[i]];
  865.     assert (tris[i] >=0 && tris[i] < vtx.size());
  866.   }
  867. }
  868. // find the median edge length
  869. // if a triangle has an edge that's longer than
  870. // factor times the median (or percentile), remove the triangle
  871. void
  872. Mesh::remove_stepedges(int percentile, int factor)
  873. {
  874.   ::remove_stepedges(vtx, getTris(), factor, percentile);
  875.   remove_unused_vtxs();
  876.   freeTStrips();
  877. }
  878. static Pnt3 GetNrm (const vector<short>& nrm, int ivert)
  879. {
  880.   ivert *= 3;
  881.   Pnt3 n (nrm[ivert], nrm[ivert+1], nrm[ivert+2]);
  882.   n /= 32767.0;
  883.   return n;
  884. }
  885. void
  886. Mesh::simulateFaceNormals (vector<short>& facen)
  887. {
  888.   facen.clear();
  889.   facen.reserve (getTris().size());
  890.   // note: Mesh doesn't store per tri normals any more
  891.   for (int i = 0; i < tris.size(); i+=3) {
  892.     Pnt3 n  = GetNrm (nrm, tris[i+0]);
  893.     n += GetNrm (nrm, tris[i+1]);
  894.     n += GetNrm (nrm, tris[i+2]);
  895.     n /= 3.0;
  896.     pushNormalAsShorts (facen, n);
  897.   }
  898. }
  899. // added by wsh for warping violin meshes (test stuff)
  900. // A little dangerous 'cuz we're fudging the verticies as we go
  901. void
  902. Mesh::Warp()
  903. {
  904.   printf("(%f, %f, %f)n", center[0], center[1], center[2]);
  905.   for ( vector<Pnt3>::iterator i = vtx.begin();
  906. i != vtx.end();
  907. i++ ) {
  908.     (*i)[2] += 7 * cos(0.017674205 * (*i)[1]) + 
  909.       5 * cos(0.030921161  * (*i)[0]);
  910.   }
  911. }
  912. /***************************************************************************
  913.                D E Q U A N T I Z A T I O N S M O O T H I N G 
  914. ***************************************************************************/
  915. void Mesh::dequantizationSmoothing(double maxDisplacement)
  916. {
  917.   cout << "Number of verts: " << vtx.size() << endl;
  918.   // Make sure we have the inverse table
  919.   calcTriLists();
  920.   
  921.   // Get a structure for new points of appropriate size
  922.   vector<Pnt3> nvtx;
  923.   nvtx=vtx;
  924.   printf ("size nvtx %ldn",nvtx.size());
  925.   // print info every how many tris? (mod count)
  926.   int mc= 100000;
  927.   
  928.   // Loop over every vtx, blurring
  929.   for (int i=0;i<vtx.size();i++)
  930.     {
  931.       if (i%mc==0) printf("Vertex Number %d tri count %ldn ",
  932.   i,vtxTris[i].size());
  933.       
  934.       Pnt3 pnt(0,0,0);
  935.       double w=0;
  936.       // Loop over all tris touching this vert
  937.       for (TriListI j=vtxTris[i].begin();j!=vtxTris[i].end();j++)
  938. {
  939.   if (i%mc==0) printf("  Tri Number: %dn",(*j));
  940.   
  941.   // Loop over all verts in adjacent tri
  942.   // note that we end up double counting verts
  943.   for (int k=0;k<3;k++)
  944.     {
  945.       w++;
  946.       Pnt3 npnt=vtx[tris[(*j)*3+k]];
  947.       if (i%mc==0) printf ("    Vtx %f  %f  %fn",npnt[0],npnt[1],npnt[2]);
  948.       if (i%mc==0) printf ("      Pnt %f  %f  %fn",pnt[0],pnt[1],pnt[2]);
  949.       pnt= pnt + npnt;
  950.       if (i%mc==0) printf ("      Pnt %f  %f  %fn",pnt[0],pnt[1],pnt[2]);
  951.     }
  952. }
  953.       // Divide the weight ,( number of verts) out
  954.       pnt= pnt / w;
  955.       // Check the distance, so that we constrain.
  956.       
  957.       // Assign the new value
  958.       nvtx[i]=pnt;
  959.     }
  960.   printf ("size nvtx %ldn",nvtx.size());
  961.   
  962.   // Copy new points to main store
  963.   vtx=nvtx;
  964.   puts ("finish");
  965. }
  966. /***************************************************************************
  967.                       R E S T O R E O R I G V E R T S 
  968. ***************************************************************************/
  969. void Mesh::restoreOrigVerts()
  970. {
  971.   // Don't restore if we never saved away the original
  972.   if (orig_vtx.size()==vtx.size())
  973.     {
  974.       vtx=orig_vtx;
  975.     }
  976.   else if (orig_vtx.size()==0)
  977.     {
  978.       saveOrigVerts();
  979.     }
  980. }
  981. /***************************************************************************
  982.                          S A V E O R I G V E R T S 
  983. ***************************************************************************/
  984. void Mesh::saveOrigVerts()
  985. {
  986.   orig_vtx=vtx;
  987. }
  988. /***************************************************************************
  989.                           C A L C T R I L I S T S 
  990. ***************************************************************************/
  991. void Mesh::calcTriLists()
  992. {
  993.   // Don't bother if we already did it
  994.   if (vtxTris.size()==vtx.size()) return;
  995.   
  996.   // Insure that we have the tris structure
  997.   // Size the vtxTris structure correctly
  998.   TriList empty;
  999.   for (int j=0;j<vtx.size();j++)
  1000.     {
  1001.       vtxTris.push_back(empty);
  1002.     }
  1003.   cout << "sizes match?  " << vtxTris.size() << " " << vtx.size() << endl;
  1004.   vector<int>&ltris=getTris();
  1005.   int triSize=ltris.size()/3;
  1006.   int vtxSize=vtx.size();
  1007.   
  1008.   
  1009.   cout << "Number of tris " << triSize << endl;
  1010.   
  1011.   // Fill in the structure
  1012.   for (int i=0;i<triSize*3;i++)
  1013.     {
  1014.       int curtri=i/3;
  1015.       assert(curtri<triSize);
  1016.       
  1017.       int curvert=ltris[i];
  1018.       assert(curvert<vtxSize);
  1019.       //printf ("before %dn",vtxTris[curvert].size());
  1020.       vtxTris[curvert].insert(curtri);
  1021.       //printf ("after %dn",vtxTris[curvert].size());
  1022.     }
  1023. }