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

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. // 
  3. // CyraSubsample.cc
  4. //     (Extra functions for CyraScan.cc)
  5. //   
  6. // Lucas Pereira
  7. // Thu Jul 16 15:20:47 1998
  8. //
  9. // Compute subsampling on Cyra scans, allowing different
  10. // filters, while still passing along confidence values.
  11. //
  12. //############################################################
  13. #include "CyraScan.h"
  14. #include "defines.h"
  15. #include "TriMeshUtils.h"
  16. #include "KDindtree.h"
  17. #include "ColorUtils.h"
  18. #include <stdio.h>
  19. #include <iostream.h>
  20. #include <fstream.h>
  21. #include <stack.h>
  22. // This function, given an original mesh, does mxn subsampling,
  23. // using the given filter
  24. bool
  25. CyraResLevel::Subsample(CyraResLevel &original, int m, int n, 
  26. CyraFilter filter)
  27. {
  28.   // Make width, height the ceilings of dividing by mxn
  29.   width = (original.width + m-1) / m;
  30.   height = (original.height +n-1) / n;
  31.   if (width < 2 || height < 2) {
  32.     // there will be no triangles
  33.     return false;
  34.   }
  35.   numpoints = 0;
  36.   numtris = 0;
  37.   points.clear();
  38.   tris.clear();
  39.   origin = original.origin;
  40.   cerr << "Subsample:  " << width << " x " << height <<endl;
  41.   //////////// Subsample the points ////////////
  42.   switch (filter) {
  43.   case cfPOINT:
  44.     // Point filter:  Just pick vertex at llc.
  45.    if (!PointFilter(original, m, n)) {
  46.       return false;
  47.     }
  48.     break;
  49.     //  case cfBOX:
  50.     //    break;
  51.     //  case cfMEDIAN:
  52.     //    break;
  53.   case cfMEAN50:
  54.     // The mean of the middle 50%.
  55.    if (!Mean50Filter(original, m, n)) {
  56.       return false;
  57.     }
  58.     break;
  59.   default:
  60.     cerr << "CyraSubsample: Filter not implemented." << endl;
  61.     return false;
  62.   }
  63.   //////////// Recompute the triangulation ////////////
  64.   // BUGBUG:  For now, this returns only TESS14 or TESS0
  65.   CyraTess tess = TESS14;
  66.   for (int xx=0; xx < width-1; xx++) {
  67.     for (int yy=0; yy < height-1; yy++) {
  68.       tess = TESS14;
  69.       for (int mm=0; mm < m; mm++) {
  70. for (int nn=0; nn < n; nn++) {
  71.   int xind = MIN(xx*m+mm, original.width-2);
  72.   int yind = MIN(yy*n+nn, original.height-2);
  73.   if (original.tri(xind, yind) != TESS14) {
  74.     tess = TESS0;
  75.     break;
  76.   }
  77. }
  78.       }
  79.       tris.push_back(tess);
  80.       if (tess == TESS14) numtris += 2;
  81.     }
  82.   }
  83.   // Recompute the vertex normals
  84.   CalcNormals();
  85.   return true;
  86. }
  87. // This function does point sampling -- picks the vertex at the
  88. // lower left corner.  Assumes setup and triangulation are handled
  89. // by Subsample.
  90. bool
  91. CyraResLevel::PointFilter(CyraResLevel &original, int m, int n)
  92. {
  93.   CyraSample samp;
  94.   for (int xx=0; xx < width; xx++) {
  95.     for (int yy=0; yy < height; yy++) {
  96.       // Grab the right sample from the original
  97.       samp = original.point(xx*m, yy*n);
  98.       // and stick it into this guy
  99.       points.push_back(samp);
  100.       if (samp.confidence) numpoints++;
  101.     }
  102.   }
  103.   return true;
  104. }
  105. // This function first selects the median 50%, and then does a mean
  106. // filter on those samples. 
  107. //
  108. // Note:  For now, it will only take into account the first 64 samples.
  109. // if max is larger than that, samples will be ignored...
  110. #define MAX_VALID_SAMPS 64
  111. #define OUTLIER_THRESH 50 // mm
  112. bool
  113. CyraResLevel::Mean50Filter(CyraResLevel &original, int m, int n)
  114. {
  115.   CyraSample samp;
  116.   // pointer array to first 64 valid samples...
  117.   CyraSample *validSamp[MAX_VALID_SAMPS];  
  118.   
  119.   cerr << "Running Mean50 filter, " << m << " x " << n << endl;
  120.   for (int xx=0; xx < width; xx++) {
  121.     for (int yy=0; yy < height; yy++) {
  122.       int origxx = xx * m;
  123.       int origyy = yy * m;
  124.       int origxend = MIN(origxx + m, original.width);
  125.       int origyend = MIN(origyy + n, original.height);
  126.       // First count the number of valid samples....
  127.       int ox, oy;
  128.       int nvalid=0;
  129.       for (ox = origxx; ox < origxend; ox++) {
  130. for (oy = origyy; oy < origyend && nvalid < MAX_VALID_SAMPS; oy++) {
  131.   // if sample is valid, add it to the list of valid samps...
  132.   if (original.point(ox,oy).vtx[2] > 0) {
  133.     validSamp[nvalid++] = &(original.point(ox,oy));
  134.   }
  135. }
  136.       }
  137.       // Special case 0, 1, 2, 3, 4 valid samples....
  138.       // Set samp, and then we'll push it on the list later...
  139.       switch (nvalid) {
  140.       case 0:
  141. // If no valid samples, set to empty. E.g., just copy
  142. // the first point, since it's empty, too...
  143. samp = original.point(origxx, origyy);
  144. break;
  145.       case 1:
  146. // Just grab the first sample...
  147. samp = *(validSamp[0]);
  148. break;
  149.       case 2:
  150. // Average the two samples together...
  151. samp.interp(*(validSamp[0]), *(validSamp[1]));
  152. break;
  153.       case 3: 
  154. { // open scope for local vars...
  155.   // Compute the range of depth values in valid samples...
  156.   CyraSample *bigz = validSamp[0];
  157.   CyraSample *litz = validSamp[0];
  158.   for (int i = 1; i < 3; i++) {
  159.     if (validSamp[i]->vtx[2] > bigz->vtx[2]) {
  160.       bigz = validSamp[i];
  161.     } else if (validSamp[i]->vtx[2] < litz->vtx[2]) {
  162.       litz = validSamp[i];
  163.     }
  164.   }
  165.   // Set midz to be the middle sample...
  166.   CyraSample *midz = validSamp[0];
  167.   for (i=1; i < 3; i++) {
  168.     if (validSamp[i] != bigz && validSamp[i] != litz) {
  169.       midz = validSamp[i];
  170.     }
  171.   }
  172.   // If they differ by a lot, then just grab the
  173.   // middle one.  Otherwise, average them together...
  174.   if (bigz - litz > OUTLIER_THRESH) {
  175.     samp = *(midz);
  176.   } else {
  177.     samp.interp(*litz, *midz, *bigz);
  178.   }
  179. } // close localvar scope...
  180. break;
  181.       case -2:
  182. { // open scope for local vars...
  183.   // For four samples, take two middles...
  184.   // Compute the range of depth values in valid samples...
  185.   CyraSample *bigz = validSamp[0];
  186.   CyraSample *litz = validSamp[0];
  187.   int bign = 0;
  188.   int litn = 0;
  189.   for (int i = 1; i < 4; i++) {
  190.     if (validSamp[i]->vtx[2] > bigz->vtx[2]) {
  191.       bigz = validSamp[i];
  192.       bign = i;
  193.     } else if (validSamp[i]->vtx[2] < litz->vtx[2]) {
  194.       litz = validSamp[i];
  195.       litn = i;
  196.     }
  197.   }
  198.   // now find the other two...  Basically, since switch is
  199.   // fast, this computes, based on the values of the big/little 
  200.   // z values, which two other samples to interpolate...
  201.   switch (bign*4 + litn) {
  202.   case 1:
  203.     // 4x 0 + 1 = 1
  204.     samp.interp(*(validSamp[2]), *(validSamp[3]));
  205.     break;
  206.   case 2:
  207.     // 4x 0 + 2 = 2
  208.     samp.interp(*(validSamp[1]), *(validSamp[3]));
  209.     break;
  210.   case 3:
  211.     // 4x 0 + 3 = 3
  212.     samp.interp(*(validSamp[1]), *(validSamp[2]));
  213.     break;
  214.   case 4:
  215.     // 4x 1 + 0 = 4
  216.     samp.interp(*(validSamp[2]), *(validSamp[3]));
  217.     break;
  218.   case 6:
  219.     // 4x 1 + 2 = 6
  220.     samp.interp(*(validSamp[0]), *(validSamp[3]));
  221.     break;
  222.   case 7:
  223.     // 4x 1 + 3 = 7
  224.     samp.interp(*(validSamp[0]), *(validSamp[2]));
  225.     break;
  226.   case 8:
  227.     // 4x 2 + 0 = 8
  228.     samp.interp(*(validSamp[1]), *(validSamp[3]));
  229.     break;
  230.   case 9:
  231.     // 4x 2 + 1 = 9
  232.     samp.interp(*(validSamp[0]), *(validSamp[3]));
  233.     break;
  234.   case 11:
  235.     // 4x 2 + 3 = 11
  236.     samp.interp(*(validSamp[1]), *(validSamp[2]));
  237.     break;
  238.   case 12:
  239.     // 4x 3 + 0 = 12
  240.     samp.interp(*(validSamp[1]), *(validSamp[2]));
  241.     break;
  242.   case 13:
  243.     // 4x 3 + 1 = 13
  244.     samp.interp(*(validSamp[0]), *(validSamp[2]));
  245.     break;
  246.   case 14:
  247.     // 4x 3 + 2 = 14
  248.     samp.interp(*(validSamp[0]), *(validSamp[1]));
  249.     break;
  250.   default:
  251.     // ok, weird, they weren't different...?
  252.     assert(bign==litn);
  253.     samp.interp(*(validSamp[0]), *(validSamp[1]));
  254.     break;
  255.   }
  256.   // now we've set samp, so break
  257. } // close localvar scope...
  258. break;
  259.       default:
  260. { // open scope for local vars...
  261.   // more than 3 samples.... 
  262.   // throw out biggest/smallest pairs until we're down to halfway
  263.   assert(nvalid > 3);
  264.   int nvalidleft = nvalid;
  265.   while ( nvalidleft > (nvalid+1) / 2) {
  266.     // Find biggest/smallest z elements...
  267.     int bign=0;
  268.     int litn=0;
  269.     CyraSample *bigz=validSamp[0];
  270.     CyraSample *litz=validSamp[0];
  271.     for (int i = 1; i < nvalidleft; i++) {
  272.       if (validSamp[i]->vtx[2] > bigz->vtx[2]) {
  273. bigz = validSamp[i];
  274. bign = i;
  275.       } else if (validSamp[i]->vtx[2] < litz->vtx[2]) {
  276. litz = validSamp[i];
  277. litn = i;
  278.       }
  279.     }
  280.     // swap them off the end of the list
  281.     // [only a pointer redirect]
  282.     validSamp[bign] = validSamp[nvalidleft-1];
  283.     validSamp[litn] = validSamp[nvalidleft-2];
  284.     nvalidleft -= 2;
  285.   }
  286.   // ok, at this point, the first nvalidleft elements of validSamp
  287.   // are the ones to interp...
  288.   samp.interp(nvalidleft, validSamp);
  289. } // close localvar scope...
  290. break;
  291.       }
  292.       // Add it to the list...
  293.       points.push_back(samp);
  294.       if (samp.confidence) numpoints++;
  295.     }
  296.   }
  297.   return true;
  298. }