NGL  6.5
The NCCA Graphics Library
VAOPrimitives.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 Jon Macey
3 
4  This program is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include <fstream>
18 #include <cmath>
19 #include <cstdlib>
20 #include "VAOPrimitives.h"
21 #include "Util.h"
22 #include <iostream>
23 #include "VAOFactory.h"
24 #include "SimpleVAO.h"
25 //----------------------------------------------------------------------------------------------------------------------
28 //----------------------------------------------------------------------------------------------------------------------
29 namespace ngl
30 {
31 
32 
33 //----------------------------------------------------------------------------------------------------------------------
35 {
37 }
38 
39 
40 //----------------------------------------------------------------------------------------------------------------------
41 
42 void VAOPrimitives::draw( const std::string &_name ) noexcept
43 {
44  // get an iterator to the VertexArrayObjects
45  auto VAO=m_createdVAOs.find(_name);
46  // make sure we have a valid shader
47  if(VAO!=m_createdVAOs.end())
48  {
49  // grab the pointer to the shader and call compile
50  VAO->second->bind();
51  VAO->second->draw();
52  VAO->second->unbind();
53  }
54  else {std::cerr<<"Warning VAO not know in Primitive list "<<_name.c_str()<<"\n";}
55 
56 }
57 
58 void VAOPrimitives::draw( const std::string &_name, GLenum _mode ) noexcept
59 {
60  // get an iterator to the VertexArrayObjects
61  auto vao=m_createdVAOs.find(_name);
62  // make sure we have a valid shader
63  if(vao!=m_createdVAOs.end())
64  {
65  // grab the pointer to the shader and call compile
66  vao->second->bind();
67  vao->second->setMode(_mode);
68  vao->second->draw();
69  vao->second->unbind();
70  }
71  else {std::cerr<<"Warning VAO not know in Primitive list "<<_name.c_str()<<"\n";}
72 
73 }
74 
75 void VAOPrimitives::createVAOFromHeader(const std::string &_name, const Real *_data, unsigned int _size ) noexcept
76 {
78 ;
79  // next we bind it so it's active for setting data
80  vao->bind();
81  // now we have our data add it to the VAO, we need to tell the VAO the following
82  // how much (in bytes) data we are copying
83  // a pointer to the first element of data (in this case the address of the first element of the
84  // std::vector
85  vao->setData( SimpleVAO::VertexData(_size*sizeof(Real),_data[0]));
86  // in this case we have packed our data in interleaved format as follows
87  // u,v,nx,ny,nz,x,y,z
88  // If you look at the shader we have the following attributes being used
89  // attribute vec3 inVert; attribute 0
90  // attribute vec2 inUV; attribute 1
91  // attribute vec3 inNormal; attribute 2
92  // so we need to set the vertexAttributePointer so the correct size and type as follows
93  // vertex is attribute 0 with x,y,z(3) parts of type GL_FLOAT, our complete packed data is
94  // sizeof(vertData) and the offset into the data structure for the first x component is 5 (u,v,nx,ny,nz)..x
95  vao->setVertexAttributePointer(0,3,GL_FLOAT,sizeof(vertData),5);
96  // uv same as above but starts at 0 and is attrib 1 and only u,v so 2
97  vao->setVertexAttributePointer(1,2,GL_FLOAT,sizeof(vertData),0);
98  // normal same as vertex only starts at position 2 (u,v)-> nx
99  vao->setVertexAttributePointer(2,3,GL_FLOAT,sizeof(vertData),2);
100  // now we have set the vertex attributes we tell the VAO class how many indices to draw when
101  // glDrawArrays is called, in this case we use buffSize (but if we wished less of the sphere to be drawn we could
102  // specify less (in steps of 3))
103  // In this case each Generic Vertex attribute is 8 elements so we use _size / 8
104  vao->setNumIndices(_size/8);
105  // finally we have finished for now so time to unbind the VAO
106  vao->unbind();
107  m_createdVAOs[_name]=vao;
108  // std::cout<<_name<<" Num Triangles "<<data.size()/3<<"\n";
109 
110 }
111 
112 void VAOPrimitives::createLineGrid( const std::string &_name, Real _width, Real _depth, int _steps ) noexcept
113 {
114  // a std::vector to store our verts, remember vector packs contiguously so we can use it
115  std::vector <vertData> data;
116  vertData vert;
117  // claculate the step size for each grid value
118  Real wstep=_width/static_cast<Real>(_steps);
119  // pre-calc the offset for speed
120  Real ws2=_width/2.0f;
121  // assign v as our value to change each vertex pair
122  Real v1=-ws2;
123 
124  // claculate the step size for each grid value
125  Real dstep=_depth/static_cast<Real>(_steps);
126  // pre-calc the offset for speed
127  Real ds2=_depth/2.0f;
128  // assign v as our value to change each vertex pair
129  Real v2=-ds2;
130 
131  for(int i=0; i<=_steps; ++i)
132  {
133  // vertex 1 x,y,z
134  vert.x=-ws2; // x
135  vert.z=v1; // y
136  vert.y=0.0; // z
137  data.push_back(vert);
138  // vertex 2 x,y,z
139  vert.x=ws2; // x
140  vert.z=v1; // y
141  data.push_back(vert);
142 
143 
144  // vertex 1 x,y,z
145  vert.x=v2; // x
146  vert.z=ds2; // y
147  data.push_back(vert);
148  // vertex 2 x,y,z
149  vert.x=v2; // x
150  vert.z=-ds2; // y
151  data.push_back(vert);
152 
153 
154 
155  // now change our step value
156  v1+=wstep;
157  v2+=dstep;
158  }
159 
160  createVAO(_name,data,GL_LINES);
161 
162 }
163 
164 void VAOPrimitives::createSphere( const std::string &_name, Real _radius, int _precision ) noexcept
165 {
166  // Sphere code based on a function Written by Paul Bourke.
167  // http://astronomy.swin.edu.au/~pbourke/opengl/sphere/
168  // the next part of the code calculates the P,N,UV of the sphere for tri_strips
169 
170  Real theta1 = 0.0f;
171  Real theta2 = 0.0f;
172  Real theta3 = 0.0f;
173 
174  // a std::vector to store our verts, remember vector packs contiguously so we can use it
175  std::vector <vertData> data;
176  // Disallow a negative number for radius.
177 
178  if( _radius < 0.0f )
179  {
180  _radius = -_radius;
181  }
182  // Disallow a negative number for _precision.
183  if( _precision < 4 )
184  {
185  _precision = 4;
186  }
187  // now fill in a vertData structure and add to the data list for our sphere
188  vertData d;
189  for( int i = 0; i < _precision/2; ++i )
190  {
191  theta1 = i * TWO_PI / _precision - PI2;
192  theta2 = (i + 1) * TWO_PI / _precision - PI2;
193 
194  for( int j = 0; j <= _precision; ++j )
195  {
196  theta3 = j * TWO_PI / _precision;
197 
198  d.nx = cosf(theta2) * cosf(theta3);
199  d.ny = sinf(theta2);
200  d.nz = cosf(theta2) * sinf(theta3);
201  d.x = _radius * d.nx;
202  d.y = _radius * d.ny;
203  d.z = _radius * d.nz;
204 
205  d.u = (j/static_cast<Real>(_precision));
206  d.v = 2*(i+1)/static_cast<Real>(_precision);
207 
208  data.push_back(d);
209 
210  d.nx = cosf(theta1) * cosf(theta3);
211  d.ny = sinf(theta1);
212  d.nz = cosf(theta1) * sinf(theta3);
213  d.x = _radius * d.nx;
214  d.y = _radius * d.ny;
215  d.z = _radius * d.nz;
216 
217  d.u = (j/static_cast<Real>(_precision));
218  d.v = 2*i/static_cast<Real>(_precision);
219  data.push_back(d);
220  } // end inner loop
221  }// end outer loop
222 
223  createVAO(_name,data,GL_TRIANGLE_STRIP);
224 
225 }
226 
227 
228 void VAOPrimitives::createCapsule( const std::string &_name, const Real _radius, const Real _height, const int _precision ) noexcept
229 
230 {
231  // based on code from here
232  // https://code.google.com/p/rgine/source/browse/trunk/RGine/opengl/src/RGLShapes.cpp
234  std::vector <vertData> data;
235  vertData d;
236  Real h = _height / 2;
237  Real s, c, s1, c1, o;
238  Real sb, cb, sb1, cb1;
239  Real ang = (1.0f / _precision) * static_cast<Real>(M_PI);
240  for (int i = 0; i < 2 * _precision; ++i)
241  {
242 
243  c = _radius * cosf(ang * i);
244  c1= _radius * cosf(ang * (i + 1));
245  s = _radius * sinf(ang * i);
246  s1 =_radius * sinf(ang * (i + 1));
247  //side top
248  d.x = c1;
249  d.y = h;
250  d.z = s1;
251 
252  d.nx=c1;
253  d.ny= 0.0;
254  d.nz=s1;
255  data.push_back(d);
256  d.x = c;
257  d.z = s;
258  d.nx=c;
259  d.nz=s;
260  data.push_back(d);
261  d.y = -h;
262  data.push_back(d);
263 
264  //side bot
265  data.push_back(d);
266  d.x = c1;
267  d.z = s1;
268  d.nx= c1;
269  d.nz=s1;
270  data.push_back(d);
271  d.x = c1;
272  d.y = h;
273  d.z = s1;
274  d.nx=c1;
275  d.nz=s1;
276  data.push_back(d);
277 
278  for (int j = 0; j <=_precision; ++j)
279  {
280  if (j < _precision / 2)
281  {
282  o = h;
283  }
284  else
285  {
286  o = -h;
287  }
288  //longitude
289  s = -sinf(ang * i);
290  s1 = -sinf(ang * (i + 1));
291  c = cosf(ang * i);
292  c1 = cosf(ang * (i + 1));
293  //latitude
294  sb = _radius * sinf(ang * j);
295  sb1 = _radius * sinf(ang * (j + 1));
296  cb = _radius * cosf(ang * j);
297  cb1 = _radius * cosf(ang * (j + 1));
298  if (j != _precision - 1)
299  {
300  d.nx=d.x = sb * c;
301  d.ny=d.y = cb + o;
302  d.nz=d.z = sb * s;
303  data.push_back(d);
304  d.nx=d.x = sb1 * c;
305  d.ny=d.y = cb1 + o;
306  d.nz=d.z = sb1 * s;
307  data.push_back(d);
308  d.nx=d.x = sb1 * c1;
309  d.ny=d.y = cb1 + o;
310  d.nz=d.z = sb1 * s1;
311  data.push_back(d);
312  }
313  if (j != 0)
314  {
315  d.nx=d.x = sb * c;
316  d.ny=d.y = cb + o;
317  d.nz=d.z = sb * s;
318  data.push_back(d);
319  d.nx=d.x = sb1 * c1;
320  d.ny=d.y = cb1 + o;
321  d.nz=d.z = sb1 * s1;
322  data.push_back(d);
323  d.nx=d.x = sb * c1;
324  d.ny=d.y = cb + o;
325  d.nz=d.z = sb * s1;
326  data.push_back(d);
327  }
328  }
329  }
330  createVAO(_name,data,GL_TRIANGLES);
331 // end citation
332 
333 }
334 
335 void VAOPrimitives::createVAO(const std::string &_name,const std::vector<vertData> &_data, const GLenum _mode) noexcept
336 {
337 
338  AbstractVAO *vao = VAOFactory::createVAO("simpleVAO",_mode);
339  // next we bind it so it's active for setting data
340  vao->bind();
341 
342  // now we have our data add it to the VAO, we need to tell the VAO the following
343  // how much (in bytes) data we are copying
344  // a pointer to the first element of data (in this case the address of the first element of the
345  // std::vector
346  vao->setData(SimpleVAO::VertexData(_data.size()*sizeof(vertData),_data[0].u));
347  // in this case we have packed our data in interleaved format as follows
348  // u,v,nx,ny,nz,x,y,z
349  // If you look at the shader we have the following attributes being used
350  // attribute vec3 inVert; attribute 0
351  // attribute vec2 inUV; attribute 1
352  // attribute vec3 inNormal; attribure 2
353  // so we need to set the vertexAttributePointer so the correct size and type as follows
354  // vertex is attribute 0 with x,y,z(3) parts of type GL_FLOAT, our complete packed data is
355  // sizeof(vertData) and the offset into the data structure for the first x component is 5 (u,v,nx,ny,nz)..x
356  vao->setVertexAttributePointer(0,3,GL_FLOAT,sizeof(vertData),5);
357  // uv same as above but starts at 0 and is attrib 1 and only u,v so 2
358  vao->setVertexAttributePointer(1,2,GL_FLOAT,sizeof(vertData),0);
359  // normal same as vertex only starts at position 2 (u,v)-> nx
360  vao->setVertexAttributePointer(2,3,GL_FLOAT,sizeof(vertData),2);
361  // now we have set the vertex attributes we tell the VAO class how many indices to draw when
362  // glDrawArrays is called, in this case we use buffSize (but if we wished less of the sphere to be drawn we could
363  // specify less (in steps of 3))
364  vao->setNumIndices(_data.size());
365  // finally we have finished for now so time to unbind the VAO
366  vao->unbind();
367  m_createdVAOs[_name]=vao;
368  // std::cout<<_name<<" Num Triangles "<<_data.size()/3<<"\n";
369 
370 }
371 
372 /*----------------------------------------------------------------------------------------------------------------------
373  * Compute lookup table of cos and sin values forming a cirle
374  * borrowed from free glut implimentation of primitive drawing
375  *
376  * Notes:
377  * It is the responsibility of the caller to free these tables
378  * The size of the table is (n+1) to form a connected loop
379  * The last entry is exactly the same as the first
380  * The sign of n can be flipped to get the reverse loop
381  */
382 //----------------------------------------------------------------------------------------------------------------------
383 
384 
385 void VAOPrimitives::fghCircleTable(std::unique_ptr<Real []> &io_sint, std::unique_ptr<Real []> &io_cost, int _n ) noexcept
386 {
387  unsigned int i;
388  /* Determine the angle between samples */
389  const Real angle = 2*PI/( ( _n == 0 ) ? 1 : _n );
390  /* Table size, the sign of n flips the circle direction */
391  int size = abs(_n);
392 
393  /* Allocate memory for n samples, plus duplicate of first entry at the end */
394  io_sint.reset( new Real[size+1]);
395  io_cost.reset( new Real[size+1]);
396  /* Compute cos and sin around the circle */
397  io_sint[0] = 0.0;
398  io_cost[0] = 1.0;
399 
400  for (i=1; i<static_cast<unsigned int>(size); ++i)
401  {
402  io_sint[i] = sinf(angle*i);
403  io_cost[i] = cosf(angle*i);
404  }
405  /* Last sample is duplicate of the first */
406  io_sint[static_cast<unsigned int>(size)] = io_sint[0];
407  io_cost[static_cast<unsigned int>(size)] = io_cost[0];
408 }
409 
410 //----------------------------------------------------------------------------------------------------------------------
411 void VAOPrimitives::createCylinder(const std::string &_name, Real _radius,const Real _height,unsigned int _slices,unsigned int _stacks ) noexcept
412 {
413  /* Step in z and radius as stacks are drawn. */
414 
415  Real z0,z1;
416  const Real zStep = _height / ( ( _stacks > 0 ) ? _stacks : 1 );
417 
418  /* Pre-computed circle */
419  std::unique_ptr<Real []> sint;
420  std::unique_ptr<Real []> cost;
421 
422 
423  fghCircleTable(sint,cost,static_cast<int>(-_slices));
424 
425  /* Do the stacks */
426  // a std::vector to store our verts, remember vector packs contiguously so we can use it
427  std::vector <vertData> data;
428  vertData d;
429  z0 = 0.0;
430  z1 = zStep;
431  // texture co-ords start at 0,0
432  // texture steps
433  Real du=1.0f/_stacks;
434  Real dv=1.0f/_slices;
435  /* Cover each stack with a quad strip, except the top stack */
436  Real u=0.0;
437  Real v=0.0;
438 
439  for(unsigned int i=1; i<=_stacks+1; ++i )
440  {
441  if(i==_stacks)
442  {
443  z1 = _height;
444  }
445  for(unsigned int j=0; j<=_slices-1; ++j)
446  {
447  // vert 1;
448  d.u=u;
449  d.v=v;
450  d.nx=sint[j];
451  d.ny=cost[j];
452  d.nz=0;
453  d.x=sint[j]*_radius;
454  d.y=cost[j]*_radius;
455  d.z=-z0/2.0f;
456  data.push_back(d);
457  // vert 2
458  d.u=u;
459  d.v=v+dv;
460  d.z=-z1/2.0f;
461  data.push_back(d);
462  // vert 3
463  d.u=u+du;
464  d.v=v;
465  d.nx=sint[j+1];
466  d.ny=cost[j+1];
467  d.x=sint[j+1]*_radius;
468  d.y=cost[j+1]*_radius;
469  d.z=-z0/2.0f;
470  data.push_back(d);
471 
472 
473  // vert 1;
474  d.u=u+du;
475  d.v=v;
476  d.nx=sint[j+1];
477  d.ny=cost[j+1];
478  d.nz=0;
479  d.x=sint[j+1]*_radius;
480  d.y=cost[j+1]*_radius;
481  d.z=-z0/2.0f;
482  data.push_back(d);
483 
484  // vert 1;
485  d.u=u;
486  d.v=v+dv;
487  d.nx=sint[j];
488  d.ny=cost[j];
489  d.nz=0;
490  d.x=sint[j]*_radius;
491  d.y=cost[j]*_radius;
492  d.z=-z1/2.0f;
493  data.push_back(d);
494 
495  // vert 1;
496  d.u=u+du;
497  d.v=v+dv;
498  d.nx=sint[j+1];
499  d.ny=cost[j+1];
500  d.nz=0;
501  d.x=sint[j+1]*_radius;
502  d.y=cost[j+1]*_radius;
503  d.z=-z1/2.0f;
504  data.push_back(d);
505 
506  u+=du;
507  }
508  v+=dv;
509  u=0.0f;
510  z0 = z1; z1 += zStep;
511  }
512  // create VAO
513  createVAO(_name,data,GL_TRIANGLES);
514 
515 }
516 
517 //----------------------------------------------------------------------------------------------------------------------
518 void VAOPrimitives::createCone(const std::string &_name, Real _base, Real _height, unsigned int _slices,unsigned int _stacks ) noexcept
519 {
520  /* Step in z and radius as stacks are drawn. */
521  Real z0,z1;
522  Real r0,r1;
523 
524  const Real zStep = _height / ( ( _stacks > 0 ) ? _stacks : 1 );
525  const Real rStep = _base / ( ( _stacks > 0 ) ? _stacks : 1 );
526 
527  /* Scaling factors for vertex normals */
528 
529  const Real cosn = ( _height / sqrtf ( _height * _height + _base * _base ));
530  const Real sinn = ( _base / sqrtf ( _height * _height + _base * _base ));
531 
532  /* Pre-computed circle */
533  std::unique_ptr<Real []> sint;
534  std::unique_ptr<Real []> cost;
535  fghCircleTable(sint,cost,static_cast<int>(-_slices));
536 
537  z0 = 0.0f;
538  z1 = zStep;
539 
540  r0 = _base;
541  r1 = r0 - rStep;
542  // texture co-ords start at 0,0
543  // texture steps
544  Real du=1.0f/_stacks;
545  Real dv=1.0f/_slices;
546  /* Cover each stack with a quad strip, except the top stack */
547  Real u=1.0f;
548  Real v=1.0f;
549  // a std::vector to store our verts, remember vector packs contiguously so we can use it
550  std::vector <vertData> data;
551  vertData d;
552  for(unsigned int i=0; i<_stacks; i++ )
553  {
554  for(unsigned int j=0; j<=_slices; j++)
555  {
556  d.u=u;
557  d.v=v;
558  d.nx = cost[j]*cosn; //ctheta;
559  d.ny = sint[j] * sinn ;//-stheta;
560  d.nz = sinn;// sphi;
561 
562  d.x=cost[j]*r0;
563  d.y=sint[j]*r0;
564  d.z=z0;
565  data.push_back(d);
566  // now for the next verts
567  d.u=u;
568  d.v=v-dv;
569 
570  d.x=cost[j]*r1;
571  d.y=sint[j]*r1;
572  d.z=z1;
573  data.push_back(d);
574  u-=du;
575  }
576  v-=dv;
577  u=1.0;
578  z0 = z1; z1 += zStep;
579  r0 = r1; r1 -= rStep;
580 
581  }
582  // create VAO
583  createVAO(_name,data,GL_TRIANGLE_STRIP);
584 }
585 
586 //----------------------------------------------------------------------------------------------------------------------
587 void VAOPrimitives::createDisk(const std::string &_name, const Real _radius, unsigned int _slices ) noexcept
588 {
589  /* Pre-computed circle */
590  std::unique_ptr<Real []> sint;
591  std::unique_ptr<Real []> cost;
592  fghCircleTable(sint,cost,static_cast<int>(-_slices));
593  // as were using a triangle fan its vert at the centere then
594  //
595 
596  // texture co-ords start at 0,0
597  // texture steps
598  Real du=1.0f/_slices;
599 
600  Real u=0.0f;
601  Real v=0.0f;
602  // a std::vector to store our verts, remember vector packs contiguously so we can use it
603  std::vector <vertData> data;
604  vertData d;
605  // as we are doing a tri fan this is the center
606  d.u=u;
607  d.v=v;
608  d.nx=0.0f;
609  d.ny=0.0f;
610  d.nz=-1.0f;
611  d.x=0;
612  d.y=0;
613  d.z=0;
614  data.push_back(d);
615  v=1.0;
616 
617  for (unsigned int j=0; j<=_slices; ++j)
618  {
619  d.u=u;
620  d.v=v;
621  // normals set above
622  d.x=cost[j]*_radius;
623  d.y=sint[j]*_radius;
624  // z set above
625  data.push_back(d);
626  u+=du;
627  }
628  // create VBO
629  createVAO(_name,data,GL_TRIANGLE_FAN);
630 }
631 
632 
633 //----------------------------------------------------------------------------------------------------------------------
634 void VAOPrimitives::createTorus(const std::string &_name, Real _minorRadius, Real _majorRadius,unsigned int _nSides, unsigned int _nRings, bool _flipTX ) noexcept
635 {
636  Real iradius = _minorRadius, oradius = _majorRadius, phi, psi, dpsi, dphi;
637 
638  Real spsi, cpsi, sphi, cphi ;
639 
640  if ( _nSides < 1 ) { _nSides = 1; }
641  if ( _nRings < 1 ) { _nRings = 1; }
642 
643  /* Increment the number of sides and rings to allow for one more point than surface */
644  _nSides ++ ;
645  _nRings ++ ;
646  // should use vec3 / 2 for these at some stage
647  std::unique_ptr<Real []>vertex( new Real[3 * _nSides * _nRings]);
648  std::unique_ptr<Real []>normal( new Real[3 * _nSides * _nRings]);
649  std::unique_ptr<Real []>uv( new Real[2*_nSides*_nRings*2]);
650 
651  dpsi = 2.0f * static_cast<Real>(M_PI) / (_nRings - 1) ;
652  dphi = -2.0f * static_cast<Real>(M_PI) / (_nSides - 1) ;
653  psi = 0.0f;
654  Real uStep=1.0f/_nRings;
655  Real vStep=1.0f/_nSides;
656  Real tu=0.0f;
657  Real tv=0.0f;
658  // pre compute the values for the torus
659  for(unsigned int j=0; j<_nRings; ++j )
660  {
661  cpsi = cosf ( psi ) ;
662  spsi = sinf ( psi ) ;
663  phi = 0.0;
664  for(unsigned int i=0; i<_nSides; ++i )
665  {
666  unsigned int offset = 3 * ( j * _nSides + i ) ;
667  cphi = cosf( phi ) ;
668  sphi = sinf( phi ) ;
669  vertex[offset] = cpsi * ( oradius + cphi * iradius ) ;
670  vertex[offset+1] = spsi * ( oradius + cphi * iradius ) ;
671  vertex[offset+2] = sphi * iradius ;
672  normal[offset] = cpsi * cphi ;
673  normal[offset+1] = spsi * cphi ;
674  normal[offset+2] = sphi ;
675  if (_flipTX)
676  {
677  uv[offset]=tv;
678  uv[offset+1]=tu;
679  }
680  else
681  {
682  uv[offset]=tu;
683  uv[offset+1]=tv;
684  }
685  tu+=uStep;
686  phi += dphi;
687  } // end of _nSides loop
688  tu=0.0f;
689  tv+=vStep;
690  psi += dpsi;
691  } // end of _nRings loop
692 
693  // a std::vector to store our verts, remember vector packs contiguously so we can use it
694  std::vector <vertData> data;
695  vertData d;
696  for(unsigned int i=0; i<_nSides-1; ++i )
697  {
698  for(unsigned int j=0; j<_nRings-1; ++j )
699  {
700  unsigned int offset = 3 * ( j * _nSides + i ) ;
701  // n=normal[offset];
702  // v=vertex[offset];
703  // t=uv[offset];
704  d.u=uv[offset];
705  d.v=uv[offset+1];
706  d.nx=normal[offset];
707  d.ny=normal[offset+1];
708  d.nz=normal[offset+2];
709  d.x=vertex[offset];
710  d.y=vertex[offset+1];
711  d.z=vertex[offset+2];
712  //V1
713  data.push_back(d);
714  // vert
715  //n=normal+offset+3;
716  //v=vertex+offset+3;
717  //t=uv+offset+3;
718  d.u=uv[offset+3];
719  d.v=uv[offset+4];
720  d.nx=normal[offset+3];
721  d.ny=normal[offset+4];
722  d.nz=normal[offset+5];
723  d.x=vertex[offset+3];
724  d.y=vertex[offset+4];
725  d.z=vertex[offset+5];
726  //V2
727  data.push_back(d);
728 
729  //n=normal + offset + 3 * _nSides + 3;
730  //v=vertex + offset + 3 * _nSides + 3;
731  //t=uv+ offset+3*_nSides+3;
732  // next vert
733  d.u=uv[(offset+3*_nSides+3)];
734  d.v=uv[(offset+3*_nSides+3)+1];
735  d.nx=normal[(offset + 3 * _nSides + 3)];
736  d.ny=normal[(offset + 3 * _nSides + 3)+1];
737  d.nz=normal[(offset + 3 * _nSides + 3)+2];
738  d.x=vertex[(offset + 3 * _nSides + 3)];
739  d.y=vertex[(offset + 3 * _nSides + 3)+1];
740  d.z=vertex[(offset + 3 * _nSides + 3)+2];
741  //V3
742  data.push_back(d);
743 
744 
745 // n=normal+offset;
746 // v=vertex+offset;
747 // t=uv+offset;
748  d.u=uv[offset];
749  d.v=uv[offset+1];
750  d.nx=normal[offset];
751  d.ny=normal[offset+1];
752  d.nz=normal[offset+2];
753  d.x=vertex[offset];
754  d.y=vertex[offset+1];
755  d.z=vertex[offset+2];
756  //V1
757  data.push_back(d);
758 
759 
760  //n=normal[(offset + 3 * _nSides + 3)];
761  //v=vertex[(offset + 3 * _nSides + 3)];
762  //t=uv[(offset+3*_nSides+3)];
763  // next vert
764  d.u=uv[(offset+3*_nSides+3)];
765  d.v=uv[(offset+3*_nSides+3)+1];
766  d.nx=normal[(offset + 3 * _nSides + 3)];
767  d.ny=normal[(offset + 3 * _nSides + 3)+1];
768  d.nz=normal[(offset + 3 * _nSides + 3)+2];
769  d.x=vertex[(offset + 3 * _nSides + 3)];
770  d.y=vertex[(offset + 3 * _nSides + 3)+1];
771  d.z=vertex[(offset + 3 * _nSides + 3)+2];
772  //V3
773  data.push_back(d);
774 
775  // n=normal[ (offset + 3 * _nSides)];
776  // v= vertex[(offset + 3 * _nSides)];
777  // t= uv[(offset+3*_nSides)];
778  // next vert
779  d.u=uv[(offset+3*_nSides)];
780  d.v=uv[(offset+3*_nSides)+1];
781  d.nx=normal[ (offset + 3 * _nSides)];
782  d.ny=normal[ (offset + 3 * _nSides)+1];
783  d.nz=normal[ (offset + 3 * _nSides)+2];
784  d.x=vertex[(offset + 3 * _nSides)];
785  d.y=vertex[(offset + 3 * _nSides)+1];
786  d.z=vertex[(offset + 3 * _nSides)+2];
787  data.push_back(d);
788 
789  } // end _nRings
790  } // end _nSides
791 
792  // now create the VBO
793 
794  createVAO(_name,data,GL_TRIANGLES);
795 }
796 
797 //----------------------------------------------------------------------------------------------------------------------
798 void VAOPrimitives::createTrianglePlane(const std::string &_name,const Real _width,const Real _depth,const int _wP,const int _dP,const Vec3 &_vN) noexcept
799 {
800  // calculate the VBO size basically we have 2 tris per quad based on the width and depth
801  // _precision.
802 
803  // as our plane is centered on 0.0 we range from Width/2.0 and Depth/2.0
804  Real w2=_width/2.0f;
805  Real d2=_depth/2.0f;
806  // calculate the steps for each quad / tri
807  Real wStep=_width/_wP;
808  Real dStep=_depth/_dP;
809  // texture co-ords start at 0,0
810  // texture steps
811  Real du=0.9f/_wP;
812  Real dv=0.9f/_dP;
813 
814  Real u=0.0f;
815  Real v=0.0f;
816 
817  // a std::vector to store our verts, remember vector packs contiguously so we can use it
818  std::vector <vertData> data;
819  vertData vert;
820 
821  for(Real d=-d2; d<d2; d+=dStep)
822  {
823  for(Real w=-w2; w<w2; w+=wStep)
824  {
825  /* tri 1
826  // counter clock wise
827  3
828  | \
829  | \
830  | \
831  1____2
832  */
833  // the normals are always the same so set them for d first
834  vert.nx=_vN.m_x;
835  vert.ny=_vN.m_y;
836  vert.nz=_vN.m_z;
837  // y is always 0 as in a plane
838  vert.y=0.0f;
839  // now for the per vert stuff
840  vert.u=u; vert.v=v+dv; vert.x=w; vert.z=d+dStep;
841  data.push_back(vert);
842  // 2
843  vert.u=u+du; vert.v=v+dv; vert.x=w+wStep; vert.z=d+dStep;
844  data.push_back(vert);
845  // 3
846  vert.u=u; vert.v=v; vert.x=w; vert.z=d;
847  data.push_back(vert);
848 
849 
850  /* tri 2 w,0,d
851  // counter clock wise
852  3_____2
853  \ |
854  \ |
855  \ |
856  \|
857  1
858 
859  */
860  vert.u=u+du; vert.v=v+dv; vert.x=w+wStep; vert.z=d+dStep;
861  data.push_back(vert);
862  // 2
863  vert.u=u+du; vert.v=v; vert.x=w+wStep; vert.z=d;
864  data.push_back(vert);
865  // 3
866  vert.u=u; vert.v=v; vert.x=w; vert.z=d;
867  data.push_back(vert);
868  u+=du;
869  } // end w loop
870  u=0.0f;
871  v+=du;
872  } // end d loop
873  // now create the VBO
874  createVAO(_name,data,GL_TRIANGLES);
875 }
876 
877 
878 //----------------------------------------------------------------------------------------------------------------------
879 void VAOPrimitives::clear() noexcept
880 {
881 
882  std::cerr<<"clearing VAOs\n";
883 
884  // loop through the map and delete the VBO's allocated
885  // note glDeleteBuffers needs a const GLUint * so we need to de-reference the map object
886  for(auto &v : m_createdVAOs)
887  {
888  //GLuint address=v.second->getID();
889  //glDeleteVertexArrays(1,&address);
890  v.second->removeVAO();
891  }
892 
893  m_createdVAOs.erase(m_createdVAOs.begin(),m_createdVAOs.end());
894 }
895 
897 {
898  // get an iterator to the VertexArrayObjects
899  auto VAO=m_createdVAOs.find(_name);
900  // make sure we have a valid shader
901  if(VAO!=m_createdVAOs.end())
902  {
903  return VAO->second;
904  }
905  else return nullptr;
906 }
907 
908 } // end ngl namespace
void draw(const std::string &_name) noexcept
Draw one of the VBO&#39;s created via a name lookup.
some useful definitions and functions
void createVAO(const std::string &_name, const std::vector< vertData > &_data, const GLenum _mode) noexcept
the method to actually create the VAO from the various other methods Note this is used in conjunction...
void createDisk(const std::string &_name, Real _radius, unsigned int _slices) noexcept
create a trinagle fan disk (use as end caps for Cylinder etc)
AbstractVAO * getVAOFromName(const std::string &_name)
get the raw VAO so we can map it etc
void clear() noexcept
clear the VAO elements created (is also called by dtor) This is usefull if you don&#39;t want the default...
static AbstractVAO * createVAO(const std::string &_type, GLenum _mode=GL_TRIANGLES)
Definition: VAOFactory.cpp:19
constexpr Real PI
pre-compute the value for value for PI based on system M_PI
Definition: Util.h:44
void createLineGrid(const std::string &_name, Real _width, Real _depth, int _steps) noexcept
create a line based grid (like the maya ground plane)
const GLfloat * c
Definition: glew.h:16629
constexpr Real PI2
pre-compute the value for value for PI/2.0
Definition: Util.h:48
GLfloat GLfloat v1
Definition: glew.h:1855
#define GL_TRIANGLES
Definition: glew.h:330
void createTorus(const std::string &_name, Real _minorRadius, Real _majorRadius, unsigned int _nSides, unsigned int _nRings, bool _flipTX=false) noexcept
create a VBO based torus from rings of quads.
GLfloat GLfloat GLfloat v2
Definition: glew.h:1859
void createCylinder(const std::string &_name, const Real _radius, Real _height, unsigned int _slices, unsigned int _stacks) noexcept
create a Quad Cylinder as a vbo with auto generated texture cords
void createDefaultVAOs() noexcept
create the default VAO&#39;s this is done by the ctor anyway but can be called if the clear method is cal...
void fghCircleTable(std::unique_ptr< Real[]> &io_sint, std::unique_ptr< Real[]> &io_cost, int _n) noexcept
create the elements of a circle this is borrowed from freeglut
ngl::Real y
Definition: VAOPrimitives.h:50
GLint GLenum GLsizei GLint GLsizei const void * data
Definition: glew.h:1382
void createCone(const std::string &_name, Real _base, Real _height, unsigned int _slices, unsigned int _stacks) noexcept
create a Quad Cone as a vao with auto generated texture cords
simple Vec3 encapsulates a 3 float object like glsl vec3 but not maths use the Vec3 class for maths a...
Definition: Vec3.h:51
unsigned int GLenum
Definition: glew.h:278
std::unordered_map< std::string, AbstractVAO * > m_createdVAOs
a map to store the VAO by name
implementation files for RibExport class
Definition: AABB.cpp:22
void setVertexAttributePointer(GLuint _id, GLint _size, GLenum _type, GLsizei _stride, unsigned int _dataOffset, bool _normalise=false)
set the generic vertex attribute pointer data usually this method will do however the user may occasi...
Definition: AbstractVAO.cpp:36
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition: glew.h:12898
PRECISION Real
create a variable called Real which is the main data type we use (GLfloat for most cases) ...
Definition: Types.h:127
GLintptr offset
Definition: glew.h:1685
base class for all VAO from the VAOFactory this defines the base class type with simple draw / bind b...
Definition: AbstractVAO.h:34
constexpr Real TWO_PI
pre-compute the value for value for 2*PI convert to float to suppress windows warning as well ...
Definition: Util.h:40
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1893
const GLdouble * v
Definition: glew.h:1394
void setNumIndices(size_t _s)
the number of indices to draw in the array. It may be that the draw routine can overide this at anoth...
Definition: AbstractVAO.h:91
void createTrianglePlane(const std::string &_name, const Real _width, const Real _depth, const int _wP, const int _dP, const Vec3 &_vN) noexcept
create a triangulated plane as a vbo with auto generated texture cords
ngl::Real nx
Definition: VAOPrimitives.h:46
ngl::Real nz
Definition: VAOPrimitives.h:48
void unbind()
unbind the VAO by binding default 0
Definition: AbstractVAO.cpp:29
ngl::Real v
Definition: VAOPrimitives.h:45
void bind()
bind the VAO so it can be used.
Definition: AbstractVAO.cpp:23
virtual void setData(const VertexData &_data)=0
this method is used to set the data in the VAO, we have a base data type of VertexData above...
ngl::Real ny
Definition: VAOPrimitives.h:47
ngl::Real u
Definition: VAOPrimitives.h:44
void createVAOFromHeader(const std::string &_name, Real const *_data, unsigned int _Size) noexcept
create a VAO from a static header file of data in the TNV format this will usually be created from th...
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:8039
void createSphere(const std::string &_name, Real _radius, int _precision) noexcept
create a triangulated Sphere as a vbo with auto generated texture cords
GLsizeiptr size
Definition: glew.h:1684
#define GL_TRIANGLE_FAN
Definition: glew.h:332
#define GL_FLOAT
Definition: glew.h:642
ngl::Real x
Definition: VAOPrimitives.h:49
GLdouble angle
Definition: glew.h:9175
#define GL_LINES
Definition: glew.h:324
ngl::Real z
Definition: VAOPrimitives.h:51
VAOPrimitives() noexcept
default constructor
GLdouble s
Definition: glew.h:1393
void createCapsule(const std::string &_name, const Real _radius=1.0f, const Real _height=2.0f, const int _precision=20) noexcept
create a triangulated capsule (Cylinder with spherical ends)
GLsizei const GLchar *const * string
Definition: glew.h:1847
#define GL_TRIANGLE_STRIP
Definition: glew.h:331
GLclampf f
Definition: glew.h:3511