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]
BezierSurface.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 //-----------------------------------------------------------------------------
70 void BezierPatch::resize(int x, int y)
71 {
72  if ( ((x-1)/3)*3+1 != x || ((y-1)/3)*3+1 != y )
73  {
74  vl::Log::error("BezierPatch::resize(): illegal patch dimensions.\n");
75  mControlPoints.clear();
76  // in debug mode stop here
77  VL_CHECK( ((x-1)/3)*3+1 == x )
78  VL_CHECK( ((y-1)/3)*3+1 == y )
79  return;
80  }
81 
82  mX = x;
83  mY = y;
84  mControlPoints.resize(mX*mY);
85 }
86 //-----------------------------------------------------------------------------
87 void BezierSurface::updateBezierSurface(bool gen_tex_coords)
88 {
89  int patch_count = 0;
90  for(unsigned ipatch=0; ipatch<patches().size(); ++ipatch)
91  patch_count += ((patches()[ipatch]->x()-1)/3)*((patches()[ipatch]->y()-1)/3);
92 
93  ref<ArrayFloat3> vert_array = cast<ArrayFloat3>(vertexArray());
94  if (!vert_array)
95  {
96  vert_array = new ArrayFloat3;
97  setVertexArray(vert_array.get());
98  }
99  vert_array->resize(detail()*detail()*patch_count);
100  vert_array->setBufferObjectDirty();
101 
102  ref<ArrayFloat2> texc_array = cast<ArrayFloat2>(texCoordArray(0));
103  if ( gen_tex_coords )
104  {
105  if (!texc_array)
106  {
107  texc_array = new ArrayFloat2;
108  setTexCoordArray(0,texc_array.get());
109  }
110  texc_array->resize(detail()*detail()*patch_count);
111  texc_array->setBufferObjectDirty();
112  }
113 
114  ref<DrawElementsUInt> de = drawCalls().size() == 1 ? cast<DrawElementsUInt>(drawCalls().at(0)) : NULL;
115  if (!de)
116  {
117  drawCalls().clear();
118  de = new DrawElementsUInt(PT_QUADS);
119  drawCalls().push_back(de.get());
120  }
121  de->indexBuffer()->resize((detail()-1)*(detail()-1)*4*patch_count);
123 
124  int ivert = 0;
125  int iquad = 0;
126  for(unsigned ipatch=0, patch_num=0; ipatch<patches().size(); ++ipatch)
127  {
128  const BezierPatch* p = patches()[ipatch].get();
129  for(int ix=0; ix<p->x()-3; ix+=3)
130  for(int iy=0; iy<p->y()-3; iy+=3)
131  {
132  for(unsigned y=0; y<detail(); ++y)
133  {
134  // A B C D
135  // ^ ^ ^ ^
136  // +---+---+---+
137  // | | | |
138  // +---+---+---+
139  // | | | |
140  // +---+---+---+
141  // | | | |
142  // +---+---+---+
143  real v = (real)y/(detail()-1);
144  real ty = 1.0f - v;
145  real ty1 = 1.0f - ty;
146  real k0 = ty*ty*ty;
147  real k1 = 3*ty*ty*ty1;
148  real k2 = 3*ty*ty1*ty1;
149  real k3 = ty1*ty1*ty1;
150  vec3 A = p->at(ix+0,iy+0)*k0 + p->at(ix+0,iy+1)*k1 + p->at(ix+0,iy+2)*k2 + p->at(ix+0,iy+3)*k3;
151  vec3 B = p->at(ix+1,iy+0)*k0 + p->at(ix+1,iy+1)*k1 + p->at(ix+1,iy+2)*k2 + p->at(ix+1,iy+3)*k3;
152  vec3 C = p->at(ix+2,iy+0)*k0 + p->at(ix+2,iy+1)*k1 + p->at(ix+2,iy+2)*k2 + p->at(ix+2,iy+3)*k3;
153  vec3 D = p->at(ix+3,iy+0)*k0 + p->at(ix+3,iy+1)*k1 + p->at(ix+3,iy+2)*k2 + p->at(ix+3,iy+3)*k3;
154  for(unsigned x=0; x<detail(); ++x, ++ivert)
155  {
156  real u = (real)x/(detail()-1);
157  real tx = 1.0f - u;
158  real tx1 = 1.0f - tx;
159  vert_array->at(ivert) = (fvec3)(A*tx*tx*tx + B*3*tx*tx*tx1 + C*3*tx*tx1*tx1 + D*tx1*tx1*tx1);
160  if(gen_tex_coords)
161  {
162  texc_array->at(ivert).x() = (float)u;
163  texc_array->at(ivert).y() = (float)v;
164  }
165  }
166  }
167 
168  int istart = detail()*detail()*patch_num;
169  for(unsigned y=0; y<detail()-1; ++y)
170  {
171  for(unsigned x=0; x<detail()-1; ++x)
172  {
173  de->indexBuffer()->at(iquad++) = istart + y *detail() + x;
174  de->indexBuffer()->at(iquad++) = istart + y *detail() + x+1;
175  de->indexBuffer()->at(iquad++) = istart + (y+1)*detail() + x+1;
176  de->indexBuffer()->at(iquad++) = istart + (y+1)*detail() + x;
177  }
178  }
179  ++patch_num;
180  }
181  }
182 
183 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
184  this->makeGLESFriendly();
185 #endif
186 }
187 //-----------------------------------------------------------------------------
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:252
const T * get() const
Definition: Object.hpp:128
int x() const
Returns the x dimension of the patch as specified by resize().
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
vec3 & at(int i, int j)
Returns the i/j control point.
void resize(size_t dim)
Definition: Array.hpp:233
Visualization Library main namespace.
int y() const
Returns the y dimension of the patch as specified by resize().
void setBufferObjectDirty(bool dirty=true)
Wether the BufferObject should be updated or not using the local storage.
Definition: Array.hpp:152
Defines one or more concatenated bicubic Bézier patches to be used with the BezierSurface class...
See DrawElements.
void resize(int x, int y)
Defines the x and y dimensions of the control point grid defining the patch.
#define NULL
Definition: OpenGLDefs.hpp:81
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
void updateBezierSurface(bool gen_tex_coords=true)
Generates the Bézier surface geometry based on the current patches and detail.
T_VectorType & at(size_t i)
Definition: Array.hpp:255
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
const T_Scalar & x() const
Definition: Vector2.hpp:132
An array of vl::fvec3.
Definition: Array.hpp:414
const T_Scalar & y() const
Definition: Vector2.hpp:133
An array of vl::fvec2.
Definition: Array.hpp:412
#define VL_CHECK(expr)
Definition: checks.hpp:73