Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
Tessellator.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
33 
34 using namespace vl;
35 
36 //-----------------------------------------------------------------------------
38 {
39  VL_DEBUG_SET_OBJECT_NAME()
40  mTessNormal = fvec3(0,0,0);
41  mBoundaryOnly = false;
42  mTolerance = 0.0;
45 }
46 //-----------------------------------------------------------------------------
48 {
50 }
51 //-----------------------------------------------------------------------------
52 bool Tessellator::tessellate(bool append_tessellated_tris)
53 {
54  if (!append_tessellated_tris)
55  mTessellatedTris.clear();
56  mFans.clear();
57  mTriStrips.clear();
58  mLineLoops.clear();
59  mPrimitiveType = 0;
61  if (mContours.empty() || mContourVerts.empty())
62  {
63  vl::Log::error("Tessellator::tessellate(): no contours specified.\n");
64  return false;
65  }
66 
67  GLUtesselator* tobj = gluNewTess();
68  // callbacks
69  gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (callback_type)tessBeginData);
70  gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (callback_type)tessVertexData);
71  gluTessCallback(tobj, GLU_TESS_COMBINE_DATA, (callback_type)tessCombineData);
72  gluTessCallback(tobj, GLU_TESS_END, (callback_type)tessEnd);
73  gluTessCallback(tobj, GLU_TESS_ERROR, (callback_type)tessError);
74  // normal
75  gluTessNormal( tobj, tessNormal().x(), tessNormal().y(), tessNormal().z() );
76  // properties
77  gluTessProperty(tobj, GLU_TESS_BOUNDARY_ONLY, boundaryOnly() ? GL_TRUE : GL_FALSE);
78  gluTessProperty(tobj, GLU_TESS_TOLERANCE, tolerance());
79  gluTessProperty(tobj, GLU_TESS_WINDING_RULE, windingRule());
80  // tessellation
82  {
83  gluTessBeginPolygon(tobj, this);
84  for(unsigned cont=0, idx=0; cont<mContours.size(); ++cont)
85  {
86  gluTessBeginContour(tobj);
87  for(int i=0; i<mContours[cont]; ++i, ++idx)
88  gluTessVertex(tobj, mContourVerts[idx].ptr(), mContourVerts[idx].ptr());
89  gluTessEndContour(tobj);
90  }
91  gluTessEndPolygon(tobj);
92  }
93  else
94  {
95  for(unsigned cont=0, idx=0; cont<mContours.size(); ++cont)
96  {
97  gluTessBeginPolygon(tobj, this);
98  gluTessBeginContour(tobj);
99  for(int i=0; i<mContours[cont]; ++i, ++idx)
100  gluTessVertex(tobj, mContourVerts[idx].ptr(), mContourVerts[idx].ptr());
101  gluTessEndContour(tobj);
102  gluTessEndPolygon(tobj);
103  }
104  }
105  gluDeleteTess(tobj);
106 
107  // triangulate fans
108  for(unsigned fan=0; fan<mFans.size(); ++fan)
109  for(unsigned iv =1; iv<mFans[fan].size()-1; ++iv)
110  {
111  mTessellatedTris.push_back(mFans[fan][0]);
112  mTessellatedTris.push_back(mFans[fan][iv]);
113  mTessellatedTris.push_back(mFans[fan][iv+1]);
114  }
115 
116  // triangulate strips
117  for(unsigned strip=0; strip<mTriStrips.size(); ++strip)
118  for(unsigned iv=0; iv<mTriStrips[strip].size()-2; ++iv)
119  {
120  if (iv % 2)
121  {
122  mTessellatedTris.push_back(mTriStrips[strip][iv+0]);
123  mTessellatedTris.push_back(mTriStrips[strip][iv+2]);
124  mTessellatedTris.push_back(mTriStrips[strip][iv+1]);
125  }
126  else
127  {
128  mTessellatedTris.push_back(mTriStrips[strip][iv+0]);
129  mTessellatedTris.push_back(mTriStrips[strip][iv+1]);
130  mTessellatedTris.push_back(mTriStrips[strip][iv+2]);
131  }
132  }
133 
134  mContours.clear();
135  mContourVerts.clear();
136 
137  #if 0
138  if (tessellatedTris().empty())
139  {
140  vl::Log::warning("Tessellator::tessellate(): no triangles generated.\n");
141  return false;
142  }
143  #endif
144 
145  return true;
146 }
147 //-----------------------------------------------------------------------------
149 {
150  for(unsigned i=0; i<mCombinedVertices.size(); ++i)
151  delete mCombinedVertices[i];
152  mCombinedVertices.clear();
153 }
154 //-----------------------------------------------------------------------------
155 ref<Geometry> Tessellator::tessellateGeometry(bool append_tessellated_tris)
156 {
157  tessellate(append_tessellated_tris);
158 
159  if (mTessellatedTris.empty())
160  return NULL;
161 
162  ref<Geometry> geom = new Geometry;
163  ref<ArrayFloat3> vert_array = new ArrayFloat3;
164 
165  vert_array->initFrom(mTessellatedTris);
166 
167  geom->setVertexArray(vert_array.get());
168  geom->drawCalls().push_back( new vl::DrawArrays(PT_TRIANGLES, 0, (int)vert_array->size()) );
169  geom->computeNormals();
170  return geom;
171 }
172 //-----------------------------------------------------------------------------
173 // Tessellation callbacks
174 //-----------------------------------------------------------------------------
175 void CALLBACK Tessellator::tessBeginData( GLenum type, Tessellator* tessellator )
176 {
177  tessellator->mPrimitiveType = type;
178  if(type == GL_TRIANGLES)
179  {
180  // do nothing
181  }
182  else
183  if(type == GL_TRIANGLE_FAN)
184  tessellator->mFans.resize( tessellator->mFans.size() + 1 );
185  else
186  if(type == GL_TRIANGLE_STRIP)
187  tessellator->mTriStrips.resize( tessellator->mTriStrips.size() + 1 );
188  else
189  if(type == GL_LINE_LOOP)
190  tessellator->mLineLoops.resize( tessellator->mLineLoops.size() + 1 );
191  else
192  {
193  Log::error("Tessellator::beginData() unknown primitive.\n");
194  }
195 }
196 //-----------------------------------------------------------------------------
198 {
199  if(tessellator->mPrimitiveType == GL_TRIANGLES)
200  tessellator->mTessellatedTris.push_back( (fvec3)(*vec) );
201  else
202  if(tessellator->mPrimitiveType == GL_TRIANGLE_FAN)
203  tessellator->mFans.back().push_back( (fvec3)(*vec) );
204  else
205  if(tessellator->mPrimitiveType == GL_TRIANGLE_STRIP)
206  tessellator->mTriStrips.back().push_back( (fvec3)(*vec) );
207  else
208  if(tessellator->mPrimitiveType == GL_LINE_LOOP)
209  tessellator->mLineLoops.back().push_back( (fvec3)(*vec) );
210  else
211  {
212  Log::error("Tessellator::vertexData() unknown primitive.\n");
213  }
214 }
215 //-----------------------------------------------------------------------------
216 void CALLBACK Tessellator::tessCombineData( GLdouble coords[3], dvec3*[4], GLfloat[4], dvec3 **dataOut, Tessellator* tessellator )
217 {
218  dvec3 *vec = new dvec3;
219  vec->x() = coords[0];
220  vec->y() = coords[1];
221  vec->z() = coords[2];
222  *dataOut = vec;
223  tessellator->mCombinedVertices.push_back( vec );
224 }
225 //-----------------------------------------------------------------------------
227 {
228 }
229 //-----------------------------------------------------------------------------
230 void CALLBACK Tessellator::tessError( GLenum errno )
231 {
232  const GLubyte* estring = gluErrorString(errno);
233  Log::error( Say("Tessellator error: %s.\n") << estring );
234 }
235 //-----------------------------------------------------------------------------
const std::vector< fvec3 > & tessellatedTris() const
A set of triangles representing the tessellated polygon.
Definition: Tessellator.hpp:76
Tessellates a complex polygon defined by a set of outlines into a set of triangles that can be render...
Definition: Tessellator.hpp:50
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:252
bool boundaryOnly() const
See gluTessProperty documentation (GLU_TESS_BOUNDARY_ONLY)
Definition: Tessellator.hpp:91
static void CALLBACK tessBeginData(GLenum type, Tessellator *tessellator)
const T * get() const
Definition: Object.hpp:128
A simple String formatting class.
Definition: Say.hpp:124
static void warning(const String &message)
Use this function to provide information about situations that might lead to errors or loss of data...
Definition: Log.cpp:155
std::vector< fvec3 > mTessellatedTris
const T_Scalar & z() const
Definition: Vector3.hpp:91
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
void setVertexArray(ArrayAbstract *data)
Conventional vertex array.
Definition: Geometry.cpp:155
static void CALLBACK tessError(GLenum errno)
std::vector< std::vector< fvec3 > > mFans
static void CALLBACK tessEnd(void)
static void CALLBACK tessVertexData(dvec3 *vec, Tessellator *tessellator)
const fvec3 & tessNormal() const
See gluTessNormal documentation.
Definition: Tessellator.hpp:85
bool mTessellateIntoSinglePolygon
std::vector< std::vector< fvec3 > > mTriStrips
double tolerance() const
See gluTessProperty documentation (GLU_TESS_TOLERANCE)
Definition: Tessellator.hpp:94
std::vector< std::vector< fvec3 > > mLineLoops
size_t size() const
Returns the number of elements of an array.
Definition: Array.hpp:235
The Geometry class is a Renderable that implements a polygonal mesh made of polygons, lines and points.
Definition: Geometry.hpp:66
Visualization Library main namespace.
~Tessellator()
Destructor.
Definition: Tessellator.cpp:47
static void CALLBACK tessCombineData(GLdouble coords[3], dvec3 *d[4], GLfloat w[4], dvec3 **dataOut, Tessellator *tessellator)
The Vector3 class is a template class that implements a generic 3 components vector, see also vl::fvec3, vl::dvec3, vl::uvec3, vl::ivec3, vl::svec3, vl::usvec3, vl::bvec3, vl::ubvec3.
Definition: Vector3.hpp:44
void initFrom(const std::vector< T_VectorType > &vector)
Definition: Array.hpp:395
std::vector< int > mContours
void freeCombinedVertices()
Vector3< double > dvec3
A 3 components vector with double precision.
Definition: Vector3.hpp:254
const T_Scalar & y() const
Definition: Vector3.hpp:90
bool tessellateIntoSinglePolygon() const
void computeNormals(bool verbose=false)
Computes the normals in a "smooth" way, i.e.
Definition: Geometry.cpp:269
#define NULL
Definition: OpenGLDefs.hpp:81
Tessellator()
Constructor.
Definition: Tessellator.cpp:37
#define CALLBACK
Definition: Tessellator.hpp:41
ETessellationWinding windingRule() const
See gluTessProperty documentation (GLU_TESS_WINDING_RULE)
ref< Geometry > tessellateGeometry(bool append_tessellated_tris=false)
Utility function that calls tessellate() and creates a Geometry with the tessellated triangles...
std::vector< dvec3 *> mCombinedVertices
const T_Scalar & x() const
Definition: Vector3.hpp:89
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
std::vector< dvec3 > mContourVerts
An array of vl::fvec3.
Definition: Array.hpp:414
Wraps the OpenGL function glDrawArrays().
Definition: DrawArrays.hpp:57
ETessellationWinding mWindingRule
bool tessellate(bool append_tessellated_tris=false)
Definition: Tessellator.cpp:52
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102