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 >
Wrap
C/C++ Source or Header
|
2008-11-07
|
5KB
|
210 lines
#ifndef K3DSDK_MESH_TRIANGULATE_DETAIL_H
#define K3DSDK_MESH_TRIANGULATE_DETAIL_H
// K-3D
// Copyright (c) 1995-2006, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "sgi_tesselator.h"
namespace detail
{
template<typename OutputFaceIterator, typename OutputPointIterator>
class glu_triangulator_t
{
public:
glu_triangulator_t(OutputFaceIterator OutputFaces, OutputPointIterator OutputPoints) :
tessellator(sgiNewTess()),
output_faces(OutputFaces),
output_points(OutputPoints),
current_face(0)
{
sgiTessCallback(tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast<callback_t>(&raw_begin));
sgiTessCallback(tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast<callback_t>(&raw_vertex));
sgiTessCallback(tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast<callback_t>(&raw_combine));
sgiTessCallback(tessellator, GLU_TESS_END_DATA, reinterpret_cast<callback_t>(&raw_end));
sgiTessCallback(tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast<callback_t>(&raw_error));
}
~glu_triangulator_t()
{
sgiDeleteTess(tessellator);
}
void operator()(face& Face)
{
current_face = &Face;
sgiTessBeginPolygon(tessellator, this);
// Handle the main contour for the face ...
sgiTessBeginContour(tessellator);
for(split_edge* edge = Face.first_edge; edge && edge->face_clockwise; edge = edge->face_clockwise)
{
sgiTessVertex(tessellator, edge->vertex->position.n, edge->vertex);
if(edge->face_clockwise == Face.first_edge)
break;
}
sgiTessEndContour(tessellator);
// Handle holes ...
for(face::holes_t::const_iterator hole = Face.holes.begin(); hole != Face.holes.end(); ++hole)
{
sgiTessBeginContour(tessellator);
for(split_edge* edge = *hole; edge && edge->face_clockwise; edge = edge->face_clockwise)
{
sgiTessVertex(tessellator, edge->vertex->position.n, edge->vertex);
if(edge->face_clockwise == *hole)
break;
}
sgiTessEndContour(tessellator);
}
sgiTessEndPolygon(tessellator);
}
private:
void begin(GLenum Mode)
{
mode = Mode;
v0 = v1 = v2 = 0;
flip_strip = false;
}
void vertex(void* VertexData)
{
if(!v0)
{
v0 = v1;
v1 = v2;
}
v2 = reinterpret_cast<point*>(VertexData);
if(!v0)
return;
std::vector<split_edge*> new_edges;
switch(mode)
{
case GL_TRIANGLE_FAN:
new_edges.push_back(new split_edge(v0));
new_edges.push_back(new split_edge(v1));
new_edges.push_back(new split_edge(v2));
break;
case GL_TRIANGLE_STRIP:
new_edges.push_back(new split_edge(v0));
new_edges.push_back(new split_edge(v1));
new_edges.push_back(new split_edge(v2));
if(flip_strip)
std::reverse(new_edges.begin(), new_edges.end());
break;
case GL_TRIANGLES:
new_edges.push_back(new split_edge(v0));
new_edges.push_back(new split_edge(v1));
new_edges.push_back(new split_edge(v2));
break;
}
loop_edges(new_edges.begin(), new_edges.end());
face* const new_face = new face(*current_face);
new_face->holes.clear();
new_face->first_edge = new_edges.front();
*output_faces++ = new_face;
switch(mode)
{
case GL_TRIANGLE_FAN:
v1 = v2;
break;
case GL_TRIANGLE_STRIP:
v0 = v1;
v1 = v2;
flip_strip = !flip_strip;
break;
case GL_TRIANGLES:
v0 = v1 = v2 = 0;
break;
}
}
void combine(GLdouble Coords[3], void* VertexData[4], GLfloat Weight[4], void** OutputData)
{
point* const new_point = new point(point3(Coords[0], Coords[1], Coords[2]));
*OutputData = new_point;
*output_points++ = new_point;
}
void end()
{
}
void error(GLenum ErrorNumber)
{
log() << k3d::error << k3d_file_reference << " " << gluErrorString(ErrorNumber) << std::endl;
}
static glu_triangulator_t* instance(void* UserData)
{
return reinterpret_cast<glu_triangulator_t*>(UserData);
}
static void raw_begin(GLenum Mode, void* UserData)
{
instance(UserData)->begin(Mode);
}
static void raw_vertex(void* VertexData, void* UserData)
{
instance(UserData)->vertex(VertexData);
}
static void raw_combine(GLdouble Coords[3], void* VertexData[4], GLfloat Weight[4], void** OutputData, void* UserData)
{
instance(UserData)->combine(Coords, VertexData, Weight, OutputData);
}
static void raw_end(void* UserData)
{
instance(UserData)->end();
}
static void raw_error(GLenum ErrorNumber, void* UserData)
{
instance(UserData)->error(ErrorNumber);
}
SGItesselator* const tessellator;
OutputFaceIterator output_faces;
OutputPointIterator output_points;
GLenum mode;
point* v0;
point* v1;
point* v2;
bool flip_strip;
/// Stores a reference to the "current" face so data can be copied to child triangles
face* current_face;
};
} // namespace detail
#endif // !K3DSDK_MESH_TRIANGULATE_DETAIL_H