home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / include / k3d / k3dsdk / mesh_triangulate_detail.h < prev    next >
C/C++ Source or Header  |  2008-11-07  |  5KB  |  210 lines

  1. #ifndef K3DSDK_MESH_TRIANGULATE_DETAIL_H
  2. #define K3DSDK_MESH_TRIANGULATE_DETAIL_H
  3.  
  4. // K-3D
  5. // Copyright (c) 1995-2006, Timothy M. Shead
  6. //
  7. // Contact: tshead@k-3d.com
  8. //
  9. // This program is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17. // General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public
  20. // License along with this program; if not, write to the Free Software
  21. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22.  
  23. #include "sgi_tesselator.h"
  24.  
  25. namespace detail
  26. {
  27.  
  28. template<typename OutputFaceIterator, typename OutputPointIterator>
  29. class glu_triangulator_t
  30. {
  31. public:
  32.     glu_triangulator_t(OutputFaceIterator OutputFaces, OutputPointIterator OutputPoints) :
  33.         tessellator(sgiNewTess()),
  34.         output_faces(OutputFaces),
  35.         output_points(OutputPoints),
  36.         current_face(0)
  37.     {
  38.         sgiTessCallback(tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast<callback_t>(&raw_begin));
  39.         sgiTessCallback(tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast<callback_t>(&raw_vertex));
  40.         sgiTessCallback(tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast<callback_t>(&raw_combine));
  41.         sgiTessCallback(tessellator, GLU_TESS_END_DATA, reinterpret_cast<callback_t>(&raw_end));
  42.         sgiTessCallback(tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast<callback_t>(&raw_error));
  43.     }
  44.  
  45.     ~glu_triangulator_t()
  46.     {
  47.         sgiDeleteTess(tessellator);
  48.     }
  49.  
  50.     void operator()(face& Face)
  51.     {
  52.         current_face = &Face;
  53.  
  54.         sgiTessBeginPolygon(tessellator, this);
  55.  
  56.         // Handle the main contour for the face ...
  57.         sgiTessBeginContour(tessellator);
  58.         for(split_edge* edge = Face.first_edge; edge && edge->face_clockwise; edge = edge->face_clockwise)
  59.         {
  60.             sgiTessVertex(tessellator, edge->vertex->position.n, edge->vertex);
  61.             if(edge->face_clockwise == Face.first_edge)
  62.                 break;
  63.         }
  64.         sgiTessEndContour(tessellator);
  65.  
  66.         // Handle holes ...
  67.         for(face::holes_t::const_iterator hole = Face.holes.begin(); hole != Face.holes.end(); ++hole)
  68.         {
  69.             sgiTessBeginContour(tessellator);
  70.             for(split_edge* edge = *hole; edge && edge->face_clockwise; edge = edge->face_clockwise)
  71.             {
  72.                 sgiTessVertex(tessellator, edge->vertex->position.n, edge->vertex);
  73.                 if(edge->face_clockwise == *hole)
  74.                     break;
  75.             }
  76.             sgiTessEndContour(tessellator);
  77.         }
  78.  
  79.         sgiTessEndPolygon(tessellator);
  80.     }
  81.  
  82. private:
  83.     void begin(GLenum Mode)
  84.     {
  85.         mode = Mode;
  86.         v0 = v1 = v2 = 0;
  87.         flip_strip = false;
  88.     }
  89.  
  90.     void vertex(void* VertexData)
  91.     {
  92.         if(!v0)
  93.         {
  94.             v0 = v1;
  95.             v1 = v2;
  96.         }
  97.         v2 = reinterpret_cast<point*>(VertexData);
  98.  
  99.         if(!v0)
  100.             return;
  101.  
  102.         std::vector<split_edge*> new_edges;
  103.         switch(mode)
  104.         {
  105.             case GL_TRIANGLE_FAN:
  106.                 new_edges.push_back(new split_edge(v0));
  107.                 new_edges.push_back(new split_edge(v1));
  108.                 new_edges.push_back(new split_edge(v2));
  109.                 break;
  110.             case GL_TRIANGLE_STRIP:
  111.                 new_edges.push_back(new split_edge(v0));
  112.                 new_edges.push_back(new split_edge(v1));
  113.                 new_edges.push_back(new split_edge(v2));
  114.                 if(flip_strip)
  115.                     std::reverse(new_edges.begin(), new_edges.end());
  116.                 break;
  117.             case GL_TRIANGLES:
  118.                 new_edges.push_back(new split_edge(v0));
  119.                 new_edges.push_back(new split_edge(v1));
  120.                 new_edges.push_back(new split_edge(v2));
  121.                 break;
  122.         }
  123.         loop_edges(new_edges.begin(), new_edges.end());
  124.  
  125.         face* const new_face = new face(*current_face);
  126.         new_face->holes.clear();
  127.         new_face->first_edge = new_edges.front();
  128.         *output_faces++ = new_face;
  129.  
  130.         switch(mode)
  131.         {
  132.             case GL_TRIANGLE_FAN:
  133.                 v1 = v2;
  134.                 break;
  135.             case GL_TRIANGLE_STRIP:
  136.                 v0 = v1;
  137.                 v1 = v2;
  138.                 flip_strip = !flip_strip;
  139.                 break;
  140.             case GL_TRIANGLES:
  141.                 v0 = v1 = v2 = 0;
  142.                 break;
  143.         }
  144.     }
  145.  
  146.     void combine(GLdouble Coords[3], void* VertexData[4], GLfloat Weight[4], void** OutputData)
  147.     {
  148.         point* const new_point = new point(point3(Coords[0], Coords[1], Coords[2]));
  149.         *OutputData = new_point;
  150.         *output_points++ = new_point;
  151.     }
  152.  
  153.     void end()
  154.     {
  155.     }
  156.  
  157.     void error(GLenum ErrorNumber)
  158.     {
  159.         log() << k3d::error << k3d_file_reference << " " << gluErrorString(ErrorNumber) << std::endl;
  160.     }
  161.  
  162.     static glu_triangulator_t* instance(void* UserData)
  163.     {
  164.         return reinterpret_cast<glu_triangulator_t*>(UserData);
  165.     }
  166.  
  167.     static void raw_begin(GLenum Mode, void* UserData)
  168.     {
  169.         instance(UserData)->begin(Mode);
  170.     }
  171.  
  172.     static void raw_vertex(void* VertexData, void* UserData)
  173.     {
  174.         instance(UserData)->vertex(VertexData);
  175.     }
  176.  
  177.     static void raw_combine(GLdouble Coords[3], void* VertexData[4], GLfloat Weight[4], void** OutputData, void* UserData)
  178.     {
  179.         instance(UserData)->combine(Coords, VertexData, Weight, OutputData);
  180.     }
  181.  
  182.     static void raw_end(void* UserData)
  183.     {
  184.         instance(UserData)->end();
  185.     }
  186.  
  187.     static void raw_error(GLenum ErrorNumber, void* UserData)
  188.     {
  189.         instance(UserData)->error(ErrorNumber);
  190.     }
  191.  
  192.     SGItesselator* const tessellator;
  193.     OutputFaceIterator output_faces;
  194.     OutputPointIterator output_points;
  195.  
  196.     GLenum mode;
  197.     point* v0;
  198.     point* v1;
  199.     point* v2;
  200.     bool flip_strip;
  201.  
  202.     /// Stores a reference to the "current" face so data can be copied to child triangles
  203.     face* current_face;
  204. };
  205.  
  206. } // namespace detail
  207.  
  208. #endif // !K3DSDK_MESH_TRIANGULATE_DETAIL_H
  209.  
  210.