You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
8.9 KiB
266 lines
8.9 KiB
/**************************************************************************** |
|
* VCGLib o o * |
|
* Visual and Computer Graphics Library o o * |
|
* _ O _ * |
|
* Copyright(C) 2004-2016 \/)\/ * |
|
* Visual Computing Lab /\/| * |
|
* ISTI - Italian National Research Council | * |
|
* \ * |
|
* All rights reserved. * |
|
* * |
|
* 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 (http://www.gnu.org/licenses/gpl.txt) * |
|
* for more details. * |
|
* * |
|
****************************************************************************/ |
|
#ifndef __VCGLIB_GLU_TESSELATOR_H |
|
#define __VCGLIB_GLU_TESSELATOR_H |
|
#include <vcg/space/point2.h> |
|
#include <vector> |
|
|
|
#ifndef GL_VERSION_1_1 |
|
#error "Please include OpenGL before including this file" |
|
#endif |
|
|
|
|
|
// The inclusion of glu should be always safe (if someone has already included gl stuff). |
|
#ifndef GLU_VERSIONS |
|
#ifdef __APPLE__ |
|
#include <OpenGL/glu.h> |
|
#else |
|
#ifdef _WIN32 |
|
#include <windows.h> |
|
#endif |
|
#include <GL/glu.h> |
|
#endif |
|
#endif |
|
|
|
#ifndef CALLBACK |
|
#ifdef _WIN32 |
|
#define CALLBACK __stdcall |
|
#else |
|
#define CALLBACK |
|
#endif |
|
#endif |
|
|
|
namespace vcg |
|
{ |
|
|
|
class glu_tesselator |
|
{ |
|
public: |
|
|
|
typedef glu_tesselator this_type; |
|
|
|
/* |
|
Works with Point2 and Point3; |
|
|
|
sample usage: |
|
|
|
// tesselation input: each outline represents a polygon contour |
|
std::vector< std::vector<point_type> > outlines = ...; |
|
|
|
// tesselation output (triangles indices) |
|
std::vector<int> indices; |
|
|
|
// compute triangles indices |
|
glu_tesselator::tesselate(outlines, indices); |
|
|
|
// unroll input contours points |
|
std::vector<point_type> points; |
|
|
|
for (size_t i=0; i<outlines.size(); ++i) |
|
{ |
|
for (size_t j=0; j<outlines[i].size(); ++j) |
|
{ |
|
points.push_back(outlines[i][j]); |
|
} |
|
} |
|
// or simply call glu_tesselator::unroll(outlines, points); |
|
|
|
// create triangles |
|
for (size_t i=0; i<indices.size(); i+=3) |
|
{ |
|
create_triangle( |
|
points[ indices[i+0] ], |
|
points[ indices[i+1] ], |
|
points[ indices[i+2] ]); |
|
} |
|
*/ |
|
|
|
template <class point_type> |
|
static inline void unroll(const std::vector< std::vector<point_type> > & outlines, std::vector<point_type> & points) |
|
{ |
|
for (size_t i=0; i<outlines.size(); ++i) |
|
{ |
|
for (size_t j=0; j<outlines[i].size(); ++j) |
|
{ |
|
points.push_back(outlines[i][j]); |
|
} |
|
} |
|
} |
|
|
|
template <class point_type> |
|
static inline void tesselate(const std::vector< std::vector<point_type> > & outlines, std::vector<int> & indices) |
|
{ |
|
tess_prim_data_vec t_data; |
|
|
|
this_type::do_tesselation(outlines, t_data); |
|
|
|
//int k = 0; |
|
for (size_t i=0; i<t_data.size(); ++i) |
|
{ |
|
const size_t st = t_data[i].indices.size(); |
|
if (st < 3) continue; |
|
|
|
switch (t_data[i].type) |
|
{ |
|
case GL_TRIANGLES: |
|
for (size_t j=0; j<st; ++j) |
|
{ |
|
indices.push_back(t_data[i].indices[j]); |
|
} |
|
break; |
|
|
|
case GL_TRIANGLE_STRIP: |
|
{ |
|
int i0 = t_data[i].indices[0]; |
|
int i1 = t_data[i].indices[1]; |
|
|
|
bool ccw = true; |
|
|
|
for (size_t j=2; j<st; ++j) |
|
{ |
|
const int i2 = t_data[i].indices[j]; |
|
|
|
indices.push_back(i0); |
|
indices.push_back(i1); |
|
indices.push_back(i2); |
|
|
|
if (ccw) i0 = i2; |
|
else i1 = i2; |
|
|
|
ccw = !ccw; |
|
} } |
|
break; |
|
|
|
case GL_TRIANGLE_FAN: |
|
{ |
|
const int first = t_data[i].indices[0]; |
|
int prev = t_data[i].indices[1]; |
|
|
|
for (size_t j=2; j<st; ++j) |
|
{ |
|
const int curr = t_data[i].indices[j]; |
|
|
|
indices.push_back(first); |
|
indices.push_back(prev); |
|
indices.push_back(curr); |
|
|
|
prev = curr; |
|
} |
|
} |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
} |
|
|
|
protected: |
|
|
|
class tess_prim_data |
|
{ |
|
public: |
|
|
|
typedef tess_prim_data this_type; |
|
|
|
GLenum type; |
|
std::vector<int> indices; |
|
|
|
tess_prim_data(void) { } |
|
tess_prim_data(GLenum t) : type(t) { } |
|
}; |
|
|
|
typedef std::vector<tess_prim_data> tess_prim_data_vec; |
|
|
|
static void CALLBACK begin_cb(GLenum type, void * polygon_data) |
|
{ |
|
tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data; |
|
t_data->push_back(tess_prim_data(type)); |
|
} |
|
|
|
static void CALLBACK end_cb(void * polygon_data) |
|
{ |
|
(void)polygon_data; |
|
} |
|
|
|
static void CALLBACK vertex_cb(void * vertex_data, void * polygon_data) |
|
{ |
|
tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data; |
|
t_data->back().indices.push_back((int)((size_t)vertex_data)); |
|
} |
|
|
|
template <class point_type> |
|
static void do_tesselation(const std::vector< std::vector<point_type> > & outlines, tess_prim_data_vec & t_data) |
|
{ |
|
GLUtesselator * tess = gluNewTess(); |
|
//#ifdef __APPLE__ |
|
// gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)(...))(this_type::begin_cb)); |
|
// gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)(...))(this_type::end_cb)); |
|
// gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)(...))(this_type::vertex_cb)); |
|
//#else |
|
gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)())(this_type::begin_cb)); |
|
gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)())(this_type::end_cb)); |
|
gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)())(this_type::vertex_cb)); |
|
//#endif |
|
void * polygon_data = (void *)(&t_data); |
|
|
|
GLdouble vertex[3]; |
|
|
|
size_t k = 0; |
|
gluTessBeginPolygon(tess, polygon_data); |
|
for (size_t i=0; i<outlines.size(); ++i) |
|
{ |
|
gluTessBeginContour(tess); |
|
for (size_t j=0; j<outlines[i].size(); ++j) |
|
{ |
|
this_type::get_position(outlines[i][j], vertex); |
|
gluTessVertex(tess, vertex, (void *)k); |
|
++k; |
|
} |
|
gluTessEndContour(tess); |
|
} |
|
gluTessEndPolygon(tess); |
|
|
|
gluDeleteTess(tess); |
|
} |
|
|
|
template <class scalar_type> |
|
static inline void get_position(const vcg::Point2<scalar_type> & p, GLdouble * d) |
|
{ |
|
d[0] = (GLdouble)(p[0]); |
|
d[1] = (GLdouble)(p[1]); |
|
d[2] = (GLdouble)(0); |
|
} |
|
|
|
template <class scalar_type> |
|
static inline void get_position(const vcg::Point3<scalar_type> & p, GLdouble * d) |
|
{ |
|
d[0] = (GLdouble)(p[0]); |
|
d[1] = (GLdouble)(p[1]); |
|
d[2] = (GLdouble)(p[2]); |
|
} |
|
}; |
|
|
|
} // end namespace vcg |
|
|
|
#endif // __VCGLIB_GLU_TESSELATOR_H
|
|
|