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

3D图形编程

开发平台:

Visual C++

  1. //###############################################################
  2. // VertexFilter.cc
  3. // Matt Ginzton, Kari Pulli
  4. // Thu Jul  2 18:29:04 PDT 1998
  5. // 
  6. // Interface for creating a filtered copy of mesh geometry data
  7. //###############################################################
  8. #ifdef WIN32
  9. # include "winGLdecs.h"
  10. #endif
  11. #include <GL/gl.h>
  12. #include <GL/glu.h>
  13. #include "VertexFilter.h"
  14. #include "TbObj.h"
  15. #include "Pnt3.h"
  16. #include "plvGlobals.h"
  17. #include "Trackball.h"
  18. #include "defines.h"
  19. #include "plvClipBoxCmds.h"
  20. #include "Projector.h"
  21. // macros to accept / reject based on inversion status,
  22. // to keep things less confusing
  23. #define ACCEPT   return (!inverted)
  24. #define REJECT   return (inverted)
  25. //#define DEBUG_HIT_RATE
  26. // factory that creates a specific VertexFilter from a Selection
  27. VertexFilter* filterFromSelection (TbObj* ms, const Selection& sel)
  28. {
  29.   VertexFilter* filter = NULL;
  30.   
  31.   if (sel.type == Selection::rect) {
  32.     filter = new ScreenBox (ms,
  33.     sel[0].x, sel[2].x,
  34.     sel[0].y, sel[2].y);
  35.   } else if (sel.type == Selection::shape) {
  36.     filter = new ScreenPolyLine (ms, sel.pts);
  37.   }
  38.   return filter;
  39. }
  40. #ifdef DEBUG_HIT_RATE
  41. static int yes, no;
  42. #endif
  43. // and implementations
  44. VertexFilter::VertexFilter()
  45. {
  46. #ifdef DEBUG_HIT_RATE
  47.   yes = no = 0;
  48. #endif
  49. }
  50. VertexFilter::~VertexFilter()
  51. {
  52. #ifdef DEBUG_HIT_RATE
  53.   cout << "VertexFilter: Yes=" << yes << "; No=" << no << endl;
  54. #endif
  55. }
  56. ScreenBox::ScreenBox (TbObj *ms, int x1, int x2, int y1, int y2)
  57.   : projector (ms ? tbView : NULL, ms)
  58. {
  59.   // for projector constructor above:
  60.   // get modelview matrix -- if ms is specified, use its coordinate system 
  61.   // (apply camera transform and its transform); if ms is NULL, then use
  62.   // current GL state.
  63.   inverted = false;
  64.   xmin = MIN(x1,x2);
  65.   xmax = MAX(x1,x2);
  66.   ymin = MIN(y1,y2);
  67.   ymax = MAX(y1,y2);
  68. }
  69. ScreenBox::ScreenBox (const ScreenBox* source)
  70. {
  71.   *this = *source;
  72. }
  73. VertexFilter* ScreenBox::transformedClone (const Xform<float>& xf) const
  74. {
  75.   ScreenBox* sb = new ScreenBox (this);
  76.   sb->projector.xformBy (xf);
  77.   return sb;
  78. }
  79. bool ScreenBox::accept (const Pnt3& crd) const
  80. {
  81.   Pnt3 screen = projector (crd);
  82.   bool in = (screen[0] <= xmax && screen[0] >= xmin
  83.      && screen[1] <= ymax && screen[1] >= ymin);
  84. #ifdef DEBUG_HIT_RATE
  85.   if (in) ++yes; else ++no;
  86. #endif
  87.   if (in)
  88.     ACCEPT;
  89.   else
  90.     REJECT;
  91. }
  92. //
  93. // ScreenBox::accept (Bbox)
  94. //
  95. // Decide whether or not a bbox intersects the current screen box
  96. // selection.  Based on Ned Greene's gem in Graphics Gems IV.
  97. //
  98. struct _edge {
  99.    int vIndex[2];
  100.    int fIndex[2];
  101.   _edge() {}
  102. };
  103. struct _face {
  104.    int vIndex[4];
  105.    Pnt3 normal;
  106.   _face() {}
  107. };
  108. class IntersectPrecalculations
  109. {
  110. public:
  111.   IntersectPrecalculations()
  112.     {
  113.       // First some fun topology
  114.       bboxEdges = vector<_edge> (12);
  115.       bboxFaces = vector<_face> (6);
  116.       
  117.       // Back face edges
  118.       bboxEdges[0].vIndex[0] = 0;
  119.       bboxEdges[0].vIndex[1] = 3;
  120.       bboxEdges[0].fIndex[0] = 0;
  121.       bboxEdges[0].fIndex[1] = 2;
  122.       
  123.       bboxEdges[1].vIndex[0] = 3;
  124.       bboxEdges[1].vIndex[1] = 2;
  125.       bboxEdges[1].fIndex[0] = 0;
  126.       bboxEdges[1].fIndex[1] = 5;
  127.       
  128.       bboxEdges[2].vIndex[0] = 2;
  129.       bboxEdges[2].vIndex[1] = 1;
  130.       bboxEdges[2].fIndex[0] = 0;
  131.       bboxEdges[2].fIndex[1] = 3;
  132.       
  133.       bboxEdges[3].vIndex[0] = 1;
  134.       bboxEdges[3].vIndex[1] = 0;
  135.       bboxEdges[3].fIndex[0] = 0;
  136.       bboxEdges[3].fIndex[1] = 4;
  137.       
  138.       // Front face edges
  139.       bboxEdges[4].vIndex[0] = 7;
  140.       bboxEdges[4].vIndex[1] = 4;
  141.       bboxEdges[4].fIndex[0] = 1;
  142.       bboxEdges[4].fIndex[1] = 2;
  143.       
  144.       bboxEdges[5].vIndex[0] = 6;
  145.       bboxEdges[5].vIndex[1] = 7;
  146.       bboxEdges[5].fIndex[0] = 1;
  147.       bboxEdges[5].fIndex[1] = 5;
  148.       
  149.       bboxEdges[6].vIndex[0] = 5;
  150.       bboxEdges[6].vIndex[1] = 6;
  151.       bboxEdges[6].fIndex[0] = 1;
  152.       bboxEdges[6].fIndex[1] = 3;
  153.       
  154.       bboxEdges[7].vIndex[0] = 4;
  155.       bboxEdges[7].vIndex[1] = 5;
  156.       bboxEdges[7].fIndex[0] = 1;
  157.       bboxEdges[7].fIndex[1] = 4;
  158.       
  159.       // The rest of the edges
  160.       bboxEdges[8].vIndex[0] = 0;
  161.       bboxEdges[8].vIndex[1] = 4;
  162.       bboxEdges[8].fIndex[0] = 2;
  163.       bboxEdges[8].fIndex[1] = 4;
  164.       
  165.       bboxEdges[9].vIndex[0] = 7;
  166.       bboxEdges[9].vIndex[1] = 3;
  167.       bboxEdges[9].fIndex[0] = 2;
  168.       bboxEdges[9].fIndex[1] = 5;
  169.       
  170.       bboxEdges[10].vIndex[0] = 5;
  171.       bboxEdges[10].vIndex[1] = 1;
  172.       bboxEdges[10].fIndex[0] = 3;
  173.       bboxEdges[10].fIndex[1] = 4;
  174.       
  175.       bboxEdges[11].vIndex[0] = 2;
  176.       bboxEdges[11].vIndex[1] = 6;
  177.       bboxEdges[11].fIndex[0] = 3;
  178.       bboxEdges[11].fIndex[1] = 5;
  179.       
  180.       
  181.       // Back face
  182.       bboxFaces[0].vIndex[0] = 3;
  183.       bboxFaces[0].vIndex[1] = 2;
  184.       bboxFaces[0].vIndex[2] = 1;
  185.       bboxFaces[0].vIndex[3] = 0;
  186.       
  187.       // Front face
  188.       bboxFaces[1].vIndex[0] = 4;
  189.       bboxFaces[1].vIndex[1] = 5;
  190.       bboxFaces[1].vIndex[2] = 6;
  191.       bboxFaces[1].vIndex[3] = 7;
  192.       
  193.       // Left face
  194.       bboxFaces[2].vIndex[0] = 0;
  195.       bboxFaces[2].vIndex[1] = 4;
  196.       bboxFaces[2].vIndex[2] = 7;
  197.       bboxFaces[2].vIndex[3] = 3;
  198.       
  199.       // Right face
  200.       bboxFaces[3].vIndex[0] = 1;
  201.       bboxFaces[3].vIndex[1] = 2;
  202.       bboxFaces[3].vIndex[2] = 6;
  203.       bboxFaces[3].vIndex[3] = 5;
  204.       
  205.       // Bottom face
  206.       bboxFaces[4].vIndex[0] = 0;
  207.       bboxFaces[4].vIndex[1] = 1;
  208.       bboxFaces[4].vIndex[2] = 5;
  209.       bboxFaces[4].vIndex[3] = 4;
  210.       
  211.       // Top face
  212.       bboxFaces[5].vIndex[0] = 3;
  213.       bboxFaces[5].vIndex[1] = 7;
  214.       bboxFaces[5].vIndex[2] = 6;
  215.       bboxFaces[5].vIndex[3] = 2;
  216.     };
  217.   
  218.   vector<_edge> bboxEdges;
  219.   vector<_face> bboxFaces;
  220. };
  221. IntersectPrecalculations ned;
  222. bool ScreenBox::accept (const Bbox &bbox) const
  223. {
  224.    int i;
  225.    Bbox projBbox;
  226.    vector<Pnt3> verts(8);
  227.   vector<_edge> silEdges(12);
  228.   
  229.   // Explicitly define the vertices of the 3D bbox
  230.   // note, the ordering is important here for the code that uses these to
  231.   // work, and the ordering is NOT the same as that returned by
  232.   // bbox.corner().
  233.   verts[0].set(bbox.min()[0], bbox.min()[1], bbox.min()[2]);
  234.   verts[1].set(bbox.max()[0], bbox.min()[1], bbox.min()[2]);
  235.   verts[2].set(bbox.max()[0], bbox.max()[1], bbox.min()[2]);
  236.   verts[3].set(bbox.min()[0], bbox.max()[1], bbox.min()[2]);
  237.   verts[4].set(bbox.min()[0], bbox.min()[1], bbox.max()[2]);
  238.   verts[5].set(bbox.max()[0], bbox.min()[1], bbox.max()[2]);
  239.   verts[6].set(bbox.max()[0], bbox.max()[1], bbox.max()[2]);
  240.   verts[7].set(bbox.min()[0], bbox.max()[1], bbox.max()[2]);
  241.    // Transform and project the 3D bounding box and compute a screen space
  242.    //  bounding box
  243.    for (i = 0; i < 8; i++) {
  244.      verts[i] = projector (verts[i]);
  245.      if (verts[i][2] > 1) {
  246.        //cerr << "flip" << endl;
  247.        verts[i] *= -1;
  248.      }
  249.      
  250.      projBbox.add(verts[i]);
  251.    }
  252. #ifdef VERBOSE
  253.    cout << projBbox << endl;
  254.    cout << "Screen bounds: ("
  255. << xmin << ", " << ymin <<")  ("
  256. << xmax << ", " << ymax << ")" << endl;
  257. #endif
  258.    // If the screen space bounding boxes do not intersect, then report
  259.    //   no intersection
  260.    // if the clip region is inverted, then every region is valid, unless it is 
  261.    // completely within the clipping box. A REJECT is specified, but due to how 
  262.    // this macro works, it actually ends up meaning ACCEPT in the inverted case.
  263.    if (inverted) {
  264.      if (projBbox.min()[0] >= xmin &&
  265.  projBbox.max()[0] <= xmax &&
  266.  projBbox.min()[1] >= ymin &&
  267.  projBbox.max()[1] <= ymax) {
  268.        if (g_verbose) cerr << "Wholly within bounding box, rejecting" << endl;
  269.        ACCEPT;
  270.      }else {
  271.        REJECT;
  272.      }
  273.    }
  274.    if (projBbox.min()[0] >= xmax ||
  275.        projBbox.max()[0] <= xmin ||
  276.        projBbox.min()[1] >= ymax ||
  277.        projBbox.max()[1] <= ymin) {
  278.      REJECT;
  279.    }
  280.    // Compute face normals in the projected coordinates
  281.    for (i = 0; i < 6; i++) {
  282.      _face& face = ned.bboxFaces[i];
  283.      face.normal = normal (verts[face.vIndex[0]],
  284.    verts[face.vIndex[1]],
  285.    verts[face.vIndex[2]]);
  286.    }
  287.    // Silhouette edges will have neighboring faces with opposite
  288.    //   normals in the projection direction.  Identify these edges and
  289.    //   make sure of the ordering of vertices within the edge.
  290.    int numEdges = 0;
  291.    for (i = 0; i < 12; i++) {
  292.       if (ned.bboxFaces[ned.bboxEdges[i].fIndex[0]].normal[2] >= 0 && 
  293.   ned.bboxFaces[ned.bboxEdges[i].fIndex[1]].normal[2] <= 0) {
  294. silEdges[numEdges].vIndex[0] = ned.bboxEdges[i].vIndex[0];
  295. silEdges[numEdges].vIndex[1] = ned.bboxEdges[i].vIndex[1];
  296. numEdges++;
  297.       }
  298.       else if (ned.bboxFaces[ned.bboxEdges[i].fIndex[0]].normal[2] <= 0 && 
  299.        ned.bboxFaces[ned.bboxEdges[i].fIndex[1]].normal[2] >= 0) {
  300. silEdges[numEdges].vIndex[0] = ned.bboxEdges[i].vIndex[1];
  301. silEdges[numEdges].vIndex[1] = ned.bboxEdges[i].vIndex[0];
  302. numEdges++;  
  303.       }
  304.    }
  305. #ifdef VERBOSE
  306.       cout << "Number of edges: " << numEdges << endl;
  307. #endif
  308.    // Treat the projected vertices as homogeneous 2D verts
  309.    for (i = 0; i < 8; i++) {
  310.       verts[i][2] = 1;
  311.    }
  312.    Pnt3 silEdgeEq;
  313.    Pnt3 screenBoxVert0(xmin, ymin, 1);
  314.    Pnt3 screenBoxVert1(xmax, ymin, 1);
  315.    Pnt3 screenBoxVert2(xmin, ymax, 1);
  316.    Pnt3 screenBoxVert3(xmax, ymax, 1);
  317.    // Determine if the clip box is completely outside of the projected
  318.    //   3D bbox in the image plane.
  319.    for (i = 0; i < numEdges; i++) {
  320.       // Compute equation of line
  321.       silEdgeEq = cross(verts[silEdges[i].vIndex[0]], 
  322. verts[silEdges[i].vIndex[1]]);
  323.       // Determine if all points are on the "wrong" side of the line
  324.       if ((dot(silEdgeEq,screenBoxVert0) < 0) &&
  325.   (dot(silEdgeEq,screenBoxVert1) < 0) &&
  326.   (dot(silEdgeEq,screenBoxVert2) < 0) &&
  327.   (dot(silEdgeEq,screenBoxVert3) < 0)) {
  328. REJECT;
  329.       }
  330.    }
  331.    
  332.    ACCEPT;
  333. }
  334. bool ScreenBox::acceptFully (const Bbox &bbox) const
  335. {
  336.   // quick test to see if ALL of a bbox passes the screenbox test.
  337.   // If it does, then things inside it don't need to be tested.
  338.    for (int i = 0; i < 8; i++) {
  339.       if (!accept (bbox.corner (i)))
  340. REJECT;
  341.    }
  342.    ACCEPT;
  343. }
  344. void ScreenBox::invert (void)
  345. {
  346.   inverted = !inverted;
  347. }
  348. //////////////////////////////////////////////////////////////////////
  349. ScreenPolyLine::ScreenPolyLine (TbObj *ms, const vector<ScreenPnt>& pts)
  350.   : ScreenBox (ms, 0, 0, 0, 0)
  351. {
  352.   // fixup minmax x,y bounds
  353.   xmin = xmax = pts[0].x;
  354.   ymin = ymax = pts[0].y;
  355.   for (int i = 1; i < pts.size(); i++) {
  356.     if (pts[i].x < xmin)
  357.       xmin = pts[i].x;
  358.     if (pts[i].x > xmax)
  359.       xmax = pts[i].x;
  360.     if (pts[i].y < ymin)
  361.       ymin = pts[i].y;
  362.     if (pts[i].y > ymax)
  363.       ymax = pts[i].y;
  364.   }
  365.   // then get buffer info
  366.   width = theWidth;
  367.   height = theHeight;
  368.   pixels = filledPolyPixels (width, height, pts);
  369. }
  370. ScreenPolyLine::~ScreenPolyLine()
  371. {
  372.   delete pixels;
  373. }
  374. ScreenPolyLine::ScreenPolyLine (const ScreenPolyLine* source)
  375.   : ScreenBox (source)
  376. {
  377.   *this = *source;
  378.   
  379.   // make a deep copy of the pixel data
  380.   pixels = new unsigned char [width * height];
  381.   memcpy(pixels, source->pixels, 
  382.  width * height * sizeof(unsigned char));
  383. }
  384. VertexFilter* ScreenPolyLine::transformedClone (const Xform<float>& xf) const
  385. {
  386.   ScreenPolyLine* spl = new ScreenPolyLine (this);
  387.   spl->projector.xformBy (xf);
  388.   return spl;
  389. }
  390. bool ScreenPolyLine::accept (const Pnt3& crd) const
  391. {
  392.   Pnt3 screen = projector (crd);
  393.   int x = screen[0];
  394.   int y = screen[1];
  395.   if (x < xmin || x >= xmax || y < ymin || y >= ymax)
  396.     REJECT;
  397.   int ofs = y * width + x;
  398.   bool in = pixels[ofs] != 0;
  399. #ifdef DEBUG_HIT_RATE
  400.   if (in) ++yes; else ++no;
  401. #endif
  402.   if (in)
  403.     ACCEPT;
  404.   else
  405.     REJECT;
  406. }