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]
Extrusions.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 
34 #include <vlCore/glsl_math.hpp>
35 
36 using namespace vl;
37 
38 ref<Geometry> Extrusions::extrude(bool compatibilityProfile)
39 {
40  if (silhouette().empty() || silhouettes().empty())
41  {
42  Log::error("Extrusion::extrude(): no silhouette defined.\n");
43  return NULL;
44  }
45  if (positionPath().empty())
46  {
47  Log::error("Extrusion::extrude() needs at least a non empty positionPath().\n");
48  return NULL;
49  }
50  if (!scalingPath().empty() && scalingPath().size() != positionPath().size()-2)
51  {
52  Log::error("Extrusion::extrude(): scalingPath() must have the same number of control points as positionPath().\n");
53  return NULL;
54  }
55  if (!rotationPath().empty() && rotationPath().size() != positionPath().size()-2)
56  {
57  Log::error("Extrusion::extrude(): rotationPath() must have the same number of control points as positionPath().\n");
58  return NULL;
59  }
60  if (!colorPath().empty() && colorPath().size() != positionPath().size()-2)
61  {
62  Log::error("Extrusion::extrude(): colorPath() must have the same number of control points as positionPath().\n");
63  return NULL;
64  }
65 
66  ref<Geometry> geom = new Geometry;
67 
68  size_t segments = positionPath().size()-2;
69 
70  std::vector<fvec3> verts;
71  verts.resize( silhouette().size() * segments );
72 
74 
75  // initialize silhouette on the x/z plane
76  std::vector<vl::fvec3> projected_sil;
77  projected_sil.resize(silhouette().size());
78  for(unsigned i=0; i<silhouette().size(); ++i)
79  {
80  projected_sil[i] = m * vl::fvec3(silhouette()[i].x(),0,silhouette()[i].y()) + positionPath()[0];
81  }
82 
83  // initialize plane normals from 1 to n-1 (end points are excluded)
84  std::vector<fvec3> plane_normals;
85  plane_normals.resize(positionPath().size());
86  for(unsigned i=1; i<plane_normals.size()-1; ++i)
87  {
88  fvec3 p0 = positionPath()[i-1] - positionPath()[i];
89  fvec3 p1 = positionPath()[i+1] - positionPath()[i];
90  p0.normalize();
91  p1.normalize();
92  plane_normals[i] = (p1-p0).normalize();
93  }
94 
95  for(unsigned i=1; i<positionPath().size()-1; ++i)
96  {
97  for(int j=0; j<(int)silhouette().size(); ++j)
98  {
99  fvec3 V = (positionPath()[i] - positionPath()[i-1]).normalize();
100  const fvec3& P = projected_sil[j];
101  const fvec3& orig = positionPath()[i];
102  const fvec3& N = plane_normals [i];
103  float d = dot(N,orig);
104  float t = dot(V,N) ? (d-dot(P,N))/dot(V,N) : 0 /*error*/;
105  // project current projected_sil on next plane along p0->p1 vector
106  verts.at(j+silhouette().size()*(i-1)) = projected_sil[j] = P + V*t;
107  }
108  }
109 
110  // rotation
111  if(!rotationPath().empty())
112  {
113  for(unsigned i=1; i<positionPath().size()-1; ++i)
114  {
115  fvec3 r = (positionPath()[i+1] - positionPath()[i]).normalize();
116  fmat4 mat = vl::fmat4::getRotation(rotationPath()[i-1],r);
117  fvec3 c;
118  for(int j=0; j<(int)silhouette().size(); ++j)
119  c += verts.at(j+silhouette().size()*(i-1));
120  c /= (float)silhouette().size();
121  for(int j=0; j<(int)silhouette().size(); ++j)
122  verts.at(j+silhouette().size()*(i-1)) = (mat*(verts.at(j+silhouette().size()*(i-1))-c))+c;
123  }
124  }
125 
126  // scaling
127  if(!scalingPath().empty())
128  {
129  for(unsigned i=1; i<positionPath().size()-1; ++i)
130  {
131  float s = scalingPath()[i-1];
132  fvec3 c;
133  for(int j=0; j<(int)silhouette().size(); ++j)
134  c += verts.at(j+silhouette().size()*(i-1));
135  c /= (float)silhouette().size();
136  for(int j=0; j<(int)silhouette().size(); ++j)
137  verts.at(j+silhouette().size()*(i-1)) = (s*(verts.at(j+silhouette().size()*(i-1))-c))+c;
138  }
139  }
140 
141  for(unsigned int i = 0; i < silhouettes().size(); ++i)
142  {
143  int previousSilhouetteSize = (i == 0) ? 0 : silhouettes().at(i - 1);
144  int prof_count = silhouetteMode() == SilhouetteClosed ? (int)silhouettes().at(i) : (int)silhouettes().at(i) - 1;
146  geom->drawCalls().push_back(de.get());
147  de->indexBuffer()->resize(4 * prof_count * (segments-1));
148  for(size_t iseg=0; iseg<segments-1; ++iseg)
149  {
150  for(int iquad=0; iquad<prof_count; ++iquad)
151  {
152  de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize;
153  de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize; // % is used for loop
154  de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize; // % is used for loop
155  de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize;
156  }
157  }
158  }
159 
160  // bottom/top caps
161 
162  size_t tess_bottom_count = 0;
163  size_t tess_top_count = 0;
164 
165  if(fillBottom())
166  {
167  size_t start = verts.size();
168  Tessellator tessellator;
169  for(unsigned i=0; i < silhouettes().size(); ++i)
170  tessellator.contours().push_back(silhouettes().at(i));
171  for(unsigned i=0; i<silhouette().size(); ++i)
172  tessellator.contourVerts().push_back((dvec3)verts[i]);
174  tessellator.tessellate();
175  for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
176  verts.push_back(tessellator.tessellatedTris()[i]);
177  if (tessellator.tessellatedTris().size())
178  geom->drawCalls().push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
179  tess_bottom_count = tessellator.tessellatedTris().size();
180  }
181  if(fillTop())
182  {
183  size_t start = verts.size();
184  Tessellator tessellator;
185  for(int i=silhouettes().size() - 1; i >= 0; --i)
186  tessellator.contours().push_back(silhouettes().at(i));
187  for(unsigned i=0; i < silhouette().size(); ++i)
188  tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]);
190  tessellator.tessellate();
191  for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
192  verts.push_back(tessellator.tessellatedTris()[i]);
193  if (tessellator.tessellatedTris().size())
194  geom->drawCalls().push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
195  tess_top_count = tessellator.tessellatedTris().size();
196  }
197 
198  ref<ArrayFloat3> vert_array = new ArrayFloat3;
199  if(compatibilityProfile)
200  geom->setVertexArray( vert_array.get() );
201  else
202  geom->setVertexAttribArray(VA_Position, vert_array.get());
203  vert_array->initFrom(verts);
204 
205  if (!colorPath().empty())
206  {
207  ref<ArrayFloat4> col_array = new ArrayFloat4;
208  if(compatibilityProfile)
209  geom->setColorArray(col_array.get());
210  else
211  geom->setVertexAttribArray(VA_Color, col_array.get());
212  col_array->resize(geom->vertexArray()->size());
213  int offs = 0;
214  for(size_t iseg=0; iseg<segments; ++iseg)
215  {
216  for(unsigned j=0; j<silhouette().size(); ++j, ++offs)
217  col_array->at(offs) = colorPath()[iseg];
218  }
219  if (fillBottom())
220  {
221  for(unsigned j=0; j<tess_bottom_count; ++j, ++offs)
222  col_array->at(offs) = colorPath()[0];
223  }
224  if (fillTop())
225  {
226  for(unsigned j=0; j<tess_top_count; ++j, ++offs)
227  col_array->at(offs) = colorPath().back();
228  }
229  }
230 
231  if (!smooth())
233 
234  geom->computeNormals();
235 
236  return geom;
237 }
238 
const std::vector< fvec3 > & tessellatedTris() const
A set of triangles representing the tessellated polygon.
Definition: Tessellator.hpp:76
const std::vector< vl::fvec3 > & positionPath() const
The path along which the silhouette is extruded.
Definition: Extrusions.hpp:107
const std::vector< float > & scalingPath() const
The scaling to be applied along the extrusion.
Definition: Extrusions.hpp:114
Tessellates a complex polygon defined by a set of outlines into a set of triangles that can be render...
Definition: Tessellator.hpp:50
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:227
An array of vl::fvec4.
Definition: Array.hpp:416
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:252
bool fillBottom() const
Whether a set of triangles should be generated to fill the beginning of the extrusion (default is tru...
Definition: Extrusions.hpp:98
const T * get() const
Definition: Object.hpp:128
bool smooth() const
If true the normals of the geometry are smoothed.
Definition: Extrusions.hpp:93
const ArrayAbstract * vertexArray() const
Conventional vertex array.
Definition: Geometry.hpp:248
const std::vector< vl::fvec4 > & colorPath() const
The color to be applied to the extrusion.
Definition: Extrusions.hpp:130
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
void resize(size_t dim)
Definition: Array.hpp:233
void setColorArray(const fvec4 &color)
Fills the color array with the given color.
Definition: Geometry.hpp:108
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.
float dot(float a, float b)
Definition: glsl_math.hpp:1111
const std::vector< dvec3 > & contourVerts() const
The contours that specify the complex polygon to be tessellated.
Definition: Tessellator.hpp:64
const std::vector< vl::fvec2 > & silhouette() const
Returns the silhouette to be extruded.
Definition: Extrusions.hpp:81
void initFrom(const std::vector< T_VectorType > &vector)
Definition: Array.hpp:395
vl::ref< vl::Geometry > extrude(bool compatibilityProfile=true)
Performs the actual extrusion.
Definition: Extrusions.cpp:38
See DrawElements.
ESilhouetteMode silhouetteMode() const
Wether the silhouette is considered closed, i.e. a line-loop, or open.
Definition: Extrusions.hpp:88
Implements the OpenGL Shading Language convenience functions for scalar and vector operations...
const std::vector< int > & contours() const
The contours that specify the complex polygon to be tessellated.
Definition: Tessellator.hpp:70
void convertDrawCallToDrawArrays()
Converts all the DrawCall objects bound to a Geometry into DrawArrays.
Definition: Geometry.cpp:766
void computeNormals(bool verbose=false)
Computes the normals in a "smooth" way, i.e.
Definition: Geometry.cpp:269
#define NULL
Definition: OpenGLDefs.hpp:81
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
const std::vector< unsigned int > & silhouettes() const
Return the number of points in each silhouette.
Definition: Extrusions.hpp:74
static Matrix4 & getRotation(Matrix4 &out, float degrees, float x, float y, float z)
Definition: Matrix4.hpp:904
T_VectorType & at(size_t i)
Definition: Array.hpp:255
virtual size_t size() const =0
Returns the number of elements of an array.
void setWindingRule(ETessellationWinding rule)
See gluTessProperty documentation (GLU_TESS_WINDING_RULE)
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
An array of vl::fvec3.
Definition: Array.hpp:414
bool fillTop() const
Whether a set of triangles should be generated to fill the ending of the extrusion (default is true)...
Definition: Extrusions.hpp:103
Wraps the OpenGL function glDrawArrays().
Definition: DrawArrays.hpp:57
const std::vector< float > & rotationPath() const
The rotation to be applied along the extrusion.
Definition: Extrusions.hpp:122
T normalize(T)
Definition: glsl_math.hpp:1128
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
void setVertexAttribArray(int attrib_location, const ArrayAbstract *info)
Binds a generic vertex attribute.
Definition: Geometry.cpp:415