Visualization Library 2.1.0

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

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
Extrusion.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 
32 #include <vlGraphics/Extrusion.hpp>
34 #include <vlCore/glsl_math.hpp>
35 
36 using namespace vl;
37 
39 {
40  if (silhouette().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  int segments = int(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  int prof_count = silhouetteMode() == SilhouetteClosed ? (int)silhouette().size() : (int)silhouette().size()-1;
143  geom->drawCalls().push_back(de.get());
144  de->indexBuffer()->resize(4 * prof_count * (segments-1));
145  for(int iseg=0; iseg<segments-1; ++iseg)
146  {
147  for(int iquad=0; iquad<prof_count; ++iquad)
148  {
149  de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad;
150  de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
151  de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
152  de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad;
153  }
154  }
155 
156  // bottom/top caps
157 
158  size_t tess_bottom_count = 0;
159  size_t tess_top_count = 0;
160 
161  if(fillBottom())
162  {
163  int start = int(verts.size());
164  Tessellator tessellator;
165  tessellator.contours().push_back((int)silhouette().size());
166  for(unsigned i=0; i<silhouette().size(); ++i)
167  tessellator.contourVerts().push_back((dvec3)verts[i]);
168  tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
169  tessellator.tessellate();
170  for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
171  verts.push_back(tessellator.tessellatedTris()[i]);
172  if (tessellator.tessellatedTris().size())
173  geom->drawCalls().push_back( new DrawArrays(PT_TRIANGLES, start, (int)tessellator.tessellatedTris().size()) );
174  tess_bottom_count = tessellator.tessellatedTris().size();
175  }
176  if(fillTop())
177  {
178  int start = int(verts.size());
179  Tessellator tessellator;
180  tessellator.contours().push_back((int)silhouette().size());
181  for(unsigned i=0; i<silhouette().size(); ++i)
182  tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]);
183  tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
184  tessellator.tessellate();
185  for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
186  verts.push_back(tessellator.tessellatedTris()[i]);
187  if (tessellator.tessellatedTris().size())
188  geom->drawCalls().push_back( new DrawArrays(PT_TRIANGLES, start, (int)tessellator.tessellatedTris().size()) );
189  tess_top_count = tessellator.tessellatedTris().size();
190  }
191 
192  ref<ArrayFloat3> vert_array = new ArrayFloat3;
193  geom->setVertexArray( vert_array.get() );
194  vert_array->initFrom(verts);
195 
196  if (!colorPath().empty())
197  {
198  ref<ArrayFloat4> col_array = new ArrayFloat4;
199  geom->setColorArray(col_array.get());
200  col_array->resize(geom->vertexArray()->size());
201  int offs = 0;
202  for(int iseg=0; iseg<segments; ++iseg)
203  {
204  for(unsigned j=0; j<silhouette().size(); ++j, ++offs)
205  col_array->at(offs) = colorPath()[iseg];
206  }
207  if (fillBottom())
208  {
209  for(unsigned j=0; j<tess_bottom_count; ++j, ++offs)
210  col_array->at(offs) = colorPath()[0];
211  }
212  if (fillTop())
213  {
214  for(unsigned j=0; j<tess_top_count; ++j, ++offs)
215  col_array->at(offs) = colorPath().back();
216  }
217  }
218 
219  if (!smooth())
221 
222  geom->computeNormals();
223 
224  return geom;
225 }
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:228
An array of vl::fvec4.
Definition: Array.hpp:416
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:253
const T * get() const
Definition: Object.hpp:128
const std::vector< vl::fvec4 > & colorPath() const
The color to be applied to the extrusion.
Definition: Extrusion.hpp:123
ESilhouetteMode silhouetteMode() const
Wether the silhouette is considered closed, i.e. a line-loop, or open.
Definition: Extrusion.hpp:81
const ArrayAbstract * vertexArray() const
Conventional vertex array.
Definition: Geometry.hpp:248
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< float > & rotationPath() const
The rotation to be applied along the extrusion.
Definition: Extrusion.hpp:115
bool smooth() const
If true the normals of the geometry are smoothed.
Definition: Extrusion.hpp:86
vl::ref< vl::Geometry > extrude()
Performs the actual extrusion.
Definition: Extrusion.cpp:38
void initFrom(const std::vector< T_VectorType > &vector)
Definition: Array.hpp:395
See DrawElements.
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
bool fillBottom() const
Whether a set of triangles should be generated to fill the beginning of the extrusion (default is tru...
Definition: Extrusion.hpp:91
#define NULL
Definition: OpenGLDefs.hpp:81
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
static Matrix4 & getRotation(Matrix4 &out, float degrees, float x, float y, float z)
Definition: Matrix4.hpp:909
T_VectorType & at(size_t i)
Definition: Array.hpp:255
virtual size_t size() const =0
Returns the number of elements of an array.
bool fillTop() const
Whether a set of triangles should be generated to fill the ending of the extrusion (default is true)...
Definition: Extrusion.hpp:96
const std::vector< vl::fvec2 > & silhouette() const
Returns the silhouette to be extruded.
Definition: Extrusion.hpp:74
const std::vector< vl::fvec3 > & positionPath() const
The path along which the silhouette is extruded.
Definition: Extrusion.hpp:100
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
An array of vl::fvec3.
Definition: Array.hpp:414
const std::vector< float > & scalingPath() const
The scaling to be applied along the extrusion.
Definition: Extrusion.hpp:107
Wraps the OpenGL function glDrawArrays().
Definition: DrawArrays.hpp:57
T normalize(T)
Definition: glsl_math.hpp:1128
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102