CSCI441 OpenGL Library 6.0.1.1
CS@Mines CSCI441 Computer Graphics Course Library
Loading...
Searching...
No Matches
objects_impl.hpp
Go to the documentation of this file.
1
15#ifndef CSCI441_OBJECTS_IMPL_HPP
16#define CSCI441_OBJECTS_IMPL_HPP
17
18#include "OpenGLUtils.hpp"
19#include "teapot.hpp"
20
21#ifdef CSCI441_USE_GLEW
22 #include <GL/glew.h>
23#else
24 #include <glad/gl.h>
25#endif
26
27#include <glm/gtc/constants.hpp>
28#include <glm/trigonometric.hpp>
29
30#include <map> // for map
31
34// Internal rendering implementations to stay consistent with solid and wire modes
35//
36// Cone is drawn with a cylinder
37// Disk is drawn with a partial disk
38
43namespace CSCI441_INTERNAL {
47 void deleteObjectVAOs();
51 void deleteObjectVBOs();
52
58 void drawCube( GLfloat sideLength, GLenum renderMode );
64 void drawCubeIndexed( GLfloat sideLength, GLenum renderMode );
70 void drawCubeFlat( GLfloat sideLength, GLenum renderMode );
81 void drawCylinder( GLfloat base, GLfloat top, GLfloat height, GLuint stacks, GLuint slices, GLenum renderMode );
92 void drawPartialDisk(GLfloat innerRadius, GLfloat outerRadius, GLuint slices, GLuint rings, GLfloat startAngle, GLfloat sweepAngle, GLenum renderMode );
100 void drawSphere( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode );
108 void drawHalfSphere( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode );
116 void drawDome( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode );
125 void drawTorus( GLfloat innerRadius, GLfloat outerRadius, GLuint sides, GLuint rings, GLenum renderMode );
130 void drawTeapot( GLenum renderMode );
131
135 inline GLint _positionAttributeLocation = -1;
139 inline GLint _normalAttributeLocation = -1;
143 inline GLint _texCoordAttributeLocation = -1;
147 inline GLint _tangentAttributeLocation = -1;
148
153 void generateCubeVAOFlat( GLfloat sideLength );
154
159 void generateCubeVAOIndexed( GLfloat sideLength );
163 inline std::map< GLfloat, GLuint > _cubeVAO;
167 inline std::map< GLfloat, GLuint > _cubeVBO;
171 inline std::map< GLfloat, GLuint > _cubeVAOIndexed;
175 inline std::map< GLfloat, GLuint > _cubeVBOIndexed;
179 inline std::map< GLfloat, GLuint > _cubeIBOIndexed;
180
182 struct CylinderData {
184 GLfloat radiusBase;
186 GLfloat radiusTop;
188 GLfloat height;
190 GLuint stacks;
192 GLuint slices;
194 [[nodiscard]] GLuint64 numVertices() const { return stacks * (slices + 1) * 2; }
196 bool operator<( const CylinderData rhs ) const {
197 if( radiusBase < rhs.radiusBase ) {
198 return true;
199 } else if( fabs(radiusBase - rhs.radiusBase) <= 0.000001 ) {
200 if( radiusTop < rhs.radiusTop ) {
201 return true;
202 } else if( fabs(radiusTop - rhs.radiusTop) <= 0.000001 ) {
203 if( height < rhs.height ) {
204 return true;
205 } else if( fabs(height - rhs.height) <= 0.000001 ) {
206 if( stacks < rhs.stacks ) {
207 return true;
208 } else if( stacks == rhs.stacks ) {
209 if( slices < rhs.slices ) {
210 return true;
211 }
212 }
213 }
214 }
215 }
216 return false;
217 }
218 };
219 void generateCylinderVAO( const CylinderData& cylData );
220 inline std::map< CylinderData, GLuint > _cylinderVAO;
221 inline std::map< CylinderData, GLuint > _cylinderVBO;
222
223 struct DiskData {
224 GLfloat innerRadius, outerRadius, startAngle, sweepAngle;
225 GLuint slices, rings;
226 [[nodiscard]] GLuint64 numVertices() const { return rings * (slices + 1) * 2; }
227 bool operator<( const DiskData rhs ) const {
228 if( innerRadius < rhs.innerRadius ) {
229 return true;
230 } else if( fabs(innerRadius - rhs.innerRadius) <= 0.000001 ) {
231 if( outerRadius < rhs.outerRadius ) {
232 return true;
233 } else if( fabs(outerRadius - rhs.outerRadius) <= 0.000001 ) {
234 if( startAngle < rhs.startAngle ) {
235 return true;
236 } else if( fabs(startAngle - rhs.startAngle) <= 0.000001 ) {
237 if( sweepAngle < rhs.sweepAngle ) {
238 return true;
239 } else if( fabs(sweepAngle - rhs.sweepAngle) <= 0.000001 ) {
240 if( slices < rhs.slices ) {
241 return true;
242 } else if( slices == rhs.slices ) {
243 if(rings < rhs.rings ) {
244 return true;
245 }
246 }
247 }
248 }
249 }
250 }
251 return false;
252 }
253 };
254 void generateDiskVAO( const DiskData& diskData );
255 inline std::map< DiskData, GLuint > _diskVAO;
256 inline std::map< DiskData, GLuint > _diskVBO;
257
258 struct SphereData {
259 GLfloat radius;
260 GLuint stacks, slices;
261 [[nodiscard]] GLuint64 numVertices() const { return ((slices + 2) * 2) + (((stacks - 2) * (slices+1)) * 2); }
262 bool operator<( const SphereData rhs ) const {
263 if( radius < rhs.radius ) {
264 return true;
265 } else if( fabs(radius - rhs.radius) <= 0.000001 ) {
266 if( stacks < rhs.stacks ) {
267 return true;
268 } else if( stacks == rhs.stacks ) {
269 if( slices < rhs.slices ) {
270 return true;
271 }
272 }
273 }
274 return false;
275 }
276 };
277 void generateSphereVAO( const SphereData& sphereData );
278 inline std::map< SphereData, GLuint > _sphereVAO;
279 inline std::map< SphereData, GLuint > _sphereVBO;
280
281 struct TorusData {
282 GLfloat innerRadius, outerRadius;
283 GLuint sides, rings;
284 [[nodiscard]] GLuint64 numVertices() const { return sides * 4 * rings; }
285 bool operator<( const TorusData rhs ) const {
286 if( innerRadius < rhs.innerRadius ) {
287 return true;
288 } else if( fabs(innerRadius - rhs.innerRadius) <= 0.000001 ) {
289 if( outerRadius < rhs.outerRadius ) {
290 return true;
291 } else if( fabs(outerRadius - rhs.outerRadius) <= 0.000001 ) {
292 if( sides < rhs.sides ) {
293 return true;
294 } else if( sides == rhs.sides ) {
295 if( rings < rhs.rings ) {
296 return true;
297 }
298 }
299 }
300 }
301 return false;
302 }
303 };
304 void generateTorusVAO( const TorusData& torusData );
305 inline std::map< TorusData, GLuint > _torusVAO;
306 inline std::map< TorusData, GLuint > _torusVBO;
307}
308
311// Internal function rendering implementations
312
313inline void CSCI441_INTERNAL::deleteObjectVAOs() {
314 for(auto &[sideLength, vaod] : _cubeVAO) {
315 glDeleteVertexArrays(1, &vaod);
316 }
317 _cubeVAO.clear();
318
319 for(auto &[sideLength, vaod] : _cubeVAOIndexed) {
320 glDeleteVertexArrays(1, &vaod);
321 }
322 _cubeVAOIndexed.clear();
323
324 for(auto &[cylData, vaod] : _cylinderVAO) {
325 glDeleteVertexArrays(1, &vaod);
326 }
327 _cylinderVAO.clear();
328
329 for(auto &[diskData, vaod] : _diskVAO) {
330 glDeleteVertexArrays(1, &vaod);
331 }
332 _diskVAO.clear();
333
334 for(auto &[sphereData, vaod] : _sphereVAO) {
335 glDeleteVertexArrays(1, &vaod);
336 }
337 _sphereVAO.clear();
338
339 for(auto &[torusData, vaod] : _torusVAO) {
340 glDeleteVertexArrays(1, &vaod);
341 }
342 _torusVAO.clear();
343}
344
345inline void CSCI441_INTERNAL::deleteObjectVBOs() {
346 for(auto &[sideLength, vbod] : _cubeVBO) {
347 glDeleteBuffers(1, &vbod);
348 }
349 _cubeVBO.clear();
350
351 for(auto &[sideLength, vbod] : _cubeVBOIndexed) {
352 glDeleteBuffers(1, &vbod);
353 }
354 _cubeVBOIndexed.clear();
355
356 for(auto &[sideLength, vbod] : _cubeIBOIndexed) {
357 glDeleteBuffers(1, &vbod);
358 }
359 _cubeIBOIndexed.clear();
360
361 for(auto &[cylData, vbod] : _cylinderVBO) {
362 glDeleteBuffers(1, &vbod);
363 }
364 _cylinderVBO.clear();
365
366 for(auto &[diskData, vbod] : _diskVBO) {
367 glDeleteBuffers(1, &vbod);
368 }
369 _diskVBO.clear();
370
371 for(auto &[sphereData, vbod] : _sphereVBO) {
372 glDeleteBuffers(1, &vbod);
373 }
374 _sphereVBO.clear();
375
376 for(auto &[torusData, vbod] : _torusVBO) {
377 glDeleteBuffers(1, &vbod);
378 }
379 _torusVBO.clear();
380}
381
382inline void CSCI441_INTERNAL::drawCube( const GLfloat sideLength, const GLenum renderMode ) {
383 drawCubeIndexed(sideLength, renderMode);
384}
385
386inline void CSCI441_INTERNAL::drawCubeFlat( const GLfloat sideLength, const GLenum renderMode ) {
387 if( _cubeVAO.count( sideLength ) == 0 ) {
388 generateCubeVAOFlat( sideLength );
389 }
390
391 constexpr GLuint64 NUM_VERTICES = 36;
392
393 GLint currentPolygonMode[2];
394 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
395
396 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
397 glBindVertexArray( _cubeVAO.find( sideLength )->second );
398 glBindBuffer( GL_ARRAY_BUFFER, _cubeVBO.find( sideLength )->second );
399 if(_positionAttributeLocation != -1) {
400 glEnableVertexAttribArray( _positionAttributeLocation );
401 glVertexAttribPointer( _positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
402 }
403 if(_normalAttributeLocation != -1) {
404 glEnableVertexAttribArray( _normalAttributeLocation );
405 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES) );
406 }
407 if(_texCoordAttributeLocation != -1) {
408 glEnableVertexAttribArray( _texCoordAttributeLocation );
409 glVertexAttribPointer( _texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2) );
410 }
411 if (_tangentAttributeLocation != -1) {
412 glEnableVertexAttribArray( _tangentAttributeLocation );
413 glVertexAttribPointer( _tangentAttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES) );
414 }
415
416 glDrawArrays( GL_TRIANGLES, 0, 36 );
417
418 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
419}
420
421inline void CSCI441_INTERNAL::drawCubeIndexed( const GLfloat sideLength, const GLenum renderMode ) {
422 if( _cubeVAOIndexed.count( sideLength ) == 0 ) {
423 generateCubeVAOIndexed( sideLength );
424 }
425
426 constexpr GLuint64 NUM_VERTICES = 8;
427
428 GLint currentPolygonMode[2];
429 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
430
431 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
432 glBindVertexArray( _cubeVAOIndexed.find( sideLength )->second );
433 glBindBuffer( GL_ARRAY_BUFFER, _cubeVBOIndexed.find( sideLength )->second );
434 if(_positionAttributeLocation != -1) {
435 glEnableVertexAttribArray( _positionAttributeLocation );
436 glVertexAttribPointer( _positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
437 }
438 if(_normalAttributeLocation != -1) {
439 glEnableVertexAttribArray( _normalAttributeLocation );
440 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES) );
441 }
442 if(_texCoordAttributeLocation != -1) {
443 glEnableVertexAttribArray( _texCoordAttributeLocation );
444 glVertexAttribPointer( _texCoordAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2) );
445 }
446 if (_tangentAttributeLocation != -1) {
447 glEnableVertexAttribArray( _tangentAttributeLocation );
448 glVertexAttribPointer( _tangentAttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES) );
449 }
450
451 glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, nullptr);
452
453 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
454}
455
456inline void CSCI441_INTERNAL::drawCylinder( const GLfloat base, const GLfloat top, const GLfloat height, const GLuint stacks, const GLuint slices, const GLenum renderMode ) {
457 const CylinderData cylData = { base, top, height, stacks, slices };
458 if( _cylinderVAO.count( cylData ) == 0 ) {
459 generateCylinderVAO( cylData );
460 }
461
462 const GLuint64 NUM_VERTICES = cylData.numVertices();
463
464 GLint currentPolygonMode[2];
465 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
466
467 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
468 glBindVertexArray( _cylinderVAO.find( cylData )->second );
469 glBindBuffer( GL_ARRAY_BUFFER, _cylinderVBO.find( cylData )->second );
470 if(_positionAttributeLocation != -1) {
471 glEnableVertexAttribArray( _positionAttributeLocation );
472 glVertexAttribPointer( _positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
473 }
474 if(_normalAttributeLocation != -1) {
475 glEnableVertexAttribArray( _normalAttributeLocation );
476 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES) );
477 }
478 if(_texCoordAttributeLocation != -1) {
479 glEnableVertexAttribArray( _texCoordAttributeLocation );
480 glVertexAttribPointer( _texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2) );
481 }
482 if (_tangentAttributeLocation != -1) {
483 glEnableVertexAttribArray( _tangentAttributeLocation );
484 glVertexAttribPointer( _tangentAttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES) );
485 }
486
487 for(GLuint stackNum = 0; stackNum < stacks; stackNum++) {
488 glDrawArrays( GL_TRIANGLE_STRIP, static_cast<GLint>((slices+1)*2*stackNum), static_cast<GLint>((slices+1)*2) );
489 }
490
491 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
492}
493
494inline void CSCI441_INTERNAL::drawPartialDisk(const GLfloat innerRadius, const GLfloat outerRadius, const GLuint slices, const GLuint rings, const GLfloat startAngle, const GLfloat sweepAngle, const GLenum renderMode ) {
495 const DiskData diskData = {innerRadius, outerRadius, startAngle, sweepAngle, slices, rings };
496 if( _diskVAO.count( diskData ) == 0 ) {
497 generateDiskVAO( diskData );
498 }
499
500 const GLuint64 NUM_VERTICES = diskData.numVertices();
501
502 GLint currentPolygonMode[2];
503 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
504
505 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
506 glBindVertexArray( _diskVAO.find( diskData )->second );
507 glBindBuffer( GL_ARRAY_BUFFER, _diskVBO.find( diskData )->second );
508 if(_positionAttributeLocation != -1) {
509 glEnableVertexAttribArray( _positionAttributeLocation );
510 glVertexAttribPointer( _positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
511 }
512 if(_normalAttributeLocation != -1) {
513 glEnableVertexAttribArray( _normalAttributeLocation );
514 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES) );
515 }
516 if(_texCoordAttributeLocation != -1) {
517 glEnableVertexAttribArray( _texCoordAttributeLocation );
518 glVertexAttribPointer( _texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2) );
519 }
520 if (_tangentAttributeLocation != -1) {
521 glEnableVertexAttribArray( _tangentAttributeLocation );
522 glVertexAttribPointer( _tangentAttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES) );
523 }
524
525 for(GLuint ringNum = 0; ringNum < rings; ringNum++) {
526 glDrawArrays( GL_TRIANGLE_STRIP, static_cast<GLint>((slices+1)*2*ringNum), static_cast<GLint>((slices+1)*2) );
527 }
528
529 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
530}
531
532inline void CSCI441_INTERNAL::drawSphere( const GLfloat radius, const GLuint stacks, const GLuint slices, const GLenum renderMode ) {
533 const SphereData sphereData = { radius, stacks, slices };
534 if( _sphereVAO.count( sphereData ) == 0 ) {
535 generateSphereVAO( sphereData );
536 }
537
538 const GLuint64 NUM_VERTICES = sphereData.numVertices();
539
540 GLint currentPolygonMode[2];
541 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
542
543 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
544 glBindVertexArray( _sphereVAO.find( sphereData )->second );
545 glBindBuffer( GL_ARRAY_BUFFER, _sphereVBO.find( sphereData )->second );
546 if(_positionAttributeLocation != -1) {
547 glEnableVertexAttribArray( _positionAttributeLocation );
548 glVertexAttribPointer( _positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
549 }
550 if(_normalAttributeLocation != -1) {
551 glEnableVertexAttribArray( _normalAttributeLocation );
552 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES) );
553 }
554 if(_texCoordAttributeLocation != -1) {
555 glEnableVertexAttribArray( _texCoordAttributeLocation );
556 glVertexAttribPointer( _texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2) );
557 }
558 if (_tangentAttributeLocation != -1) {
559 glEnableVertexAttribArray( _tangentAttributeLocation );
560 glVertexAttribPointer( _tangentAttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES) );
561 }
562
563 glDrawArrays( GL_TRIANGLE_FAN, 0, static_cast<GLint>(slices+2) );
564
565 for(GLuint stackNum = 1; stackNum < stacks-1; stackNum++) {
566 glDrawArrays( GL_TRIANGLE_STRIP, static_cast<GLint>((slices+2) + (stackNum-1)*((slices+1)*2)), static_cast<GLint>((slices+1)*2) );
567 }
568
569 glDrawArrays( GL_TRIANGLE_FAN, static_cast<GLint>((slices+2) + (stacks-2)*(slices+1)*2), static_cast<GLint>(slices+2) );
570
571 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
572}
573
574inline void CSCI441_INTERNAL::drawHalfSphere( const GLfloat radius, const GLuint stacks, const GLuint slices, const GLenum renderMode ) {
575 const SphereData sphereData = { radius, stacks, slices };
576 if( _sphereVAO.count( sphereData ) == 0 ) {
577 generateSphereVAO( sphereData );
578 }
579
580 const GLuint64 NUM_VERTICES = sphereData.numVertices();
581
582 GLint currentPolygonMode[2];
583 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
584
585 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
586 glBindVertexArray( _sphereVAO.find( sphereData )->second );
587 glBindBuffer( GL_ARRAY_BUFFER, _sphereVBO.find( sphereData )->second );
588 if(_positionAttributeLocation != -1) {
589 glEnableVertexAttribArray( _positionAttributeLocation );
590 glVertexAttribPointer( _positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
591 }
592 if(_normalAttributeLocation != -1) {
593 glEnableVertexAttribArray( _normalAttributeLocation );
594 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES) );
595 }
596 if(_texCoordAttributeLocation != -1) {
597 glEnableVertexAttribArray( _texCoordAttributeLocation );
598 glVertexAttribPointer( _texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2) );
599 }
600 if (_tangentAttributeLocation != -1) {
601 glEnableVertexAttribArray( _tangentAttributeLocation );
602 glVertexAttribPointer( _tangentAttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES) );
603 }
604
605 glDrawArrays( GL_TRIANGLE_FAN, static_cast<GLint>((slices+2)/2), static_cast<GLint>((slices+2)/2) );
606
607 for(GLuint stackNum = 1; stackNum < stacks-1; stackNum++) {
608 glDrawArrays( GL_TRIANGLE_STRIP, static_cast<GLint>((slices+2) + (stackNum-1)*((slices+1)*2)), static_cast<GLint>(slices+2) );
609 }
610
611 glDrawArrays( GL_TRIANGLE_FAN, static_cast<GLint>((slices+2) + (stacks-2)*(slices+1)*2), static_cast<GLint>((slices+2)/2) );
612
613 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
614
615 drawPartialDisk(0.0f, radius, slices, stacks, 0.0f, glm::two_pi<GLfloat>(), renderMode);
616}
617
618inline void CSCI441_INTERNAL::drawDome( const GLfloat radius, const GLuint stacks, const GLuint slices, const GLenum renderMode ) {
619 SphereData sphereData = { radius, stacks, slices };
620 if( _sphereVAO.count( sphereData ) == 0 ) {
621 generateSphereVAO( sphereData );
622 }
623
624 const GLuint64 NUM_VERTICES = sphereData.numVertices();
625
626 GLint currentPolygonMode[2];
627 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
628
629 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
630 glBindVertexArray( _sphereVAO.find( sphereData )->second );
631 glBindBuffer( GL_ARRAY_BUFFER, _sphereVBO.find( sphereData )->second );
632 if(_positionAttributeLocation != -1) {
633 glEnableVertexAttribArray( _positionAttributeLocation );
634 glVertexAttribPointer( _positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
635 }
636 if(_normalAttributeLocation != -1) {
637 glEnableVertexAttribArray( _normalAttributeLocation );
638 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES) );
639 }
640 if(_texCoordAttributeLocation != -1) {
641 glEnableVertexAttribArray( _texCoordAttributeLocation );
642 glVertexAttribPointer( _texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2) );
643 }
644 if (_tangentAttributeLocation != -1) {
645 glEnableVertexAttribArray( _tangentAttributeLocation );
646 glVertexAttribPointer( _tangentAttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES) );
647 }
648
649 glDrawArrays( GL_TRIANGLE_FAN, 0, static_cast<GLint>(slices+2) );
650
651 for(GLuint stackNum = (stacks-1)/2; stackNum < stacks-1; stackNum++) {
652 glDrawArrays( GL_TRIANGLE_STRIP, static_cast<GLint>((slices+2) + (stackNum-1)*((slices+1)*2)), static_cast<GLint>((slices+1)*2) );
653 }
654
655 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
656}
657
658inline void CSCI441_INTERNAL::drawTorus( const GLfloat innerRadius, const GLfloat outerRadius, const GLuint sides, const GLuint rings, const GLenum renderMode ) {
659 const TorusData torusData = { innerRadius, outerRadius, sides, rings };
660 if( _torusVAO.count( torusData ) == 0 ) {
661 generateTorusVAO( torusData );
662 }
663
664 const GLuint64 NUM_VERTICES = torusData.numVertices();
665
666 GLint currentPolygonMode[2];
667 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
668
669 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
670 glBindVertexArray( _torusVAO.find( torusData )->second );
671 glBindBuffer( GL_ARRAY_BUFFER, _torusVBO.find( torusData )->second );
672 if(_positionAttributeLocation != -1) {
673 glEnableVertexAttribArray( _positionAttributeLocation );
674 glVertexAttribPointer( _positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
675 }
676 if(_normalAttributeLocation != -1) {
677 glEnableVertexAttribArray( _normalAttributeLocation );
678 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES) );
679 }
680 if(_texCoordAttributeLocation != -1) {
681 glEnableVertexAttribArray( _texCoordAttributeLocation );
682 glVertexAttribPointer( _texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2) );
683 }
684 if (_tangentAttributeLocation != -1) {
685 glEnableVertexAttribArray( _tangentAttributeLocation );
686 glVertexAttribPointer( _tangentAttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES) );
687 }
688
689 for(GLuint ringNum = 0; ringNum < rings; ringNum++) {
690 glDrawArrays( GL_TRIANGLE_STRIP, static_cast<GLint>(ringNum*sides*4), static_cast<GLint>(sides*4) );
691 }
692
693 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
694}
695
696inline void CSCI441_INTERNAL::drawTeapot( const GLenum renderMode ) {
697 GLint currentPolygonMode[2];
698 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
699
700 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
701 teapot();
702 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
703}
704
705inline void CSCI441_INTERNAL::generateCubeVAOFlat( const GLfloat sideLength ) {
706 GLuint vaod;
707 glGenVertexArrays( 1, &vaod );
708 glBindVertexArray( vaod );
709
710 GLuint vbod;
711 glGenBuffers( 1, &vbod );
712 glBindBuffer( GL_ARRAY_BUFFER, vbod );
713
714 const GLfloat CORNER_POINT = sideLength / 2.0f;
715
716 constexpr GLuint64 NUM_VERTICES = 36;
717
718 const glm::vec3 vertices[NUM_VERTICES] = {
719 // Left Face
720 {-CORNER_POINT, -CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, -CORNER_POINT},
721 {-CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, CORNER_POINT},
722 // Right Face
723 {CORNER_POINT, CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, CORNER_POINT, -CORNER_POINT},
724 {CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, -CORNER_POINT},
725 // Top Face
726 {-CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, CORNER_POINT}, {CORNER_POINT, CORNER_POINT, -CORNER_POINT},
727 {CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, CORNER_POINT}, {CORNER_POINT, CORNER_POINT, CORNER_POINT},
728 // Bottom Face
729 {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, -CORNER_POINT},
730 {CORNER_POINT, -CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, -CORNER_POINT},
731 // Back Face
732 {CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, -CORNER_POINT},
733 {-CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, -CORNER_POINT},
734 // Front Face
735 {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, CORNER_POINT},
736 {-CORNER_POINT, CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, CORNER_POINT, CORNER_POINT}
737 };
738 const glm::vec3 normals[NUM_VERTICES] = {
739 // Left Face = -X Axis
740 CSCI441::X_AXIS_NEG, CSCI441::X_AXIS_NEG, CSCI441::X_AXIS_NEG,
741 CSCI441::X_AXIS_NEG, CSCI441::X_AXIS_NEG, CSCI441::X_AXIS_NEG,
742 // Right Face = +X Axis
743 CSCI441::X_AXIS_POS, CSCI441::X_AXIS_POS, CSCI441::X_AXIS_POS,
744 CSCI441::X_AXIS_POS, CSCI441::X_AXIS_POS, CSCI441::X_AXIS_POS,
745 // Top Face = +Y Axis
746 CSCI441::Y_AXIS_POS, CSCI441::Y_AXIS_POS, CSCI441::Y_AXIS_POS,
747 CSCI441::Y_AXIS_POS, CSCI441::Y_AXIS_POS, CSCI441::Y_AXIS_POS,
748 // Bottom Face = -Y Axis
749 CSCI441::Y_AXIS_NEG, CSCI441::Y_AXIS_NEG, CSCI441::Y_AXIS_NEG,
750 CSCI441::Y_AXIS_NEG, CSCI441::Y_AXIS_NEG, CSCI441::Y_AXIS_NEG,
751 // Back Face = -Z Axis
752 CSCI441::Z_AXIS_NEG, CSCI441::Z_AXIS_NEG, CSCI441::Z_AXIS_NEG,
753 CSCI441::Z_AXIS_NEG, CSCI441::Z_AXIS_NEG, CSCI441::Z_AXIS_NEG,
754 // Front Face = +Z Axis
755 CSCI441::Z_AXIS_POS, CSCI441::Z_AXIS_POS, CSCI441::Z_AXIS_POS,
756 CSCI441::Z_AXIS_POS, CSCI441::Z_AXIS_POS, CSCI441::Z_AXIS_POS
757 };
758 constexpr GLfloat handedness = 1.0f;
759 const glm::vec4 tangents[NUM_VERTICES] = {
760 // Left Face = -Y Axis
761 glm::vec4(CSCI441::Y_AXIS_NEG, handedness), glm::vec4(CSCI441::Y_AXIS_NEG, handedness), glm::vec4(CSCI441::Y_AXIS_NEG, handedness),
762 glm::vec4(CSCI441::Y_AXIS_NEG, handedness), glm::vec4(CSCI441::Y_AXIS_NEG, handedness), glm::vec4(CSCI441::Y_AXIS_NEG, handedness),
763 // Right Face = +Y Axis
764 glm::vec4(CSCI441::Y_AXIS_POS, handedness), glm::vec4(CSCI441::Y_AXIS_POS, handedness), glm::vec4(CSCI441::Y_AXIS_POS, handedness),
765 glm::vec4(CSCI441::Y_AXIS_POS, handedness), glm::vec4(CSCI441::Y_AXIS_POS, handedness), glm::vec4(CSCI441::Y_AXIS_POS, handedness),
766 // Top Face = +Z Axis
767 glm::vec4(CSCI441::Z_AXIS_POS, handedness), glm::vec4(CSCI441::Z_AXIS_POS, handedness), glm::vec4(CSCI441::Z_AXIS_POS, handedness),
768 glm::vec4(CSCI441::Z_AXIS_POS, handedness), glm::vec4(CSCI441::Z_AXIS_POS, handedness), glm::vec4(CSCI441::Z_AXIS_POS, handedness),
769 // Bottom Face = -Z Axis
770 glm::vec4(CSCI441::Z_AXIS_NEG, handedness), glm::vec4(CSCI441::Z_AXIS_NEG, handedness), glm::vec4(CSCI441::Z_AXIS_NEG, handedness),
771 glm::vec4(CSCI441::Z_AXIS_NEG, handedness), glm::vec4(CSCI441::Z_AXIS_NEG, handedness), glm::vec4(CSCI441::Z_AXIS_NEG, handedness),
772 // Back Face = -X Axis
773 glm::vec4(CSCI441::X_AXIS_NEG, handedness), glm::vec4(CSCI441::X_AXIS_NEG, handedness), glm::vec4(CSCI441::X_AXIS_NEG, handedness),
774 glm::vec4(CSCI441::X_AXIS_NEG, handedness), glm::vec4(CSCI441::X_AXIS_NEG, handedness), glm::vec4(CSCI441::X_AXIS_NEG, handedness),
775 // Front Face = +X Axis
776 glm::vec4(CSCI441::X_AXIS_POS, handedness), glm::vec4(CSCI441::X_AXIS_POS, handedness), glm::vec4(CSCI441::X_AXIS_POS, handedness),
777 glm::vec4(CSCI441::X_AXIS_POS, handedness), glm::vec4(CSCI441::X_AXIS_POS, handedness), glm::vec4(CSCI441::X_AXIS_POS, handedness)
778 };
779 const glm::vec2 texCoords[NUM_VERTICES] = {
780 // Left Face
781 {0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f},
782 {0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f},
783 // Right Face
784 {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f},
785 {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f},
786 // Top Face
787 {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f},
788 {0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f},
789 // Bottom Face
790 {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f},
791 {0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f},
792 // Back Face
793 {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f},
794 {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f},
795 // Front Face
796 {0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f},
797 {0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}
798 };
799
800 glBufferData(GL_ARRAY_BUFFER, (sizeof(glm::vec3)*2 + sizeof(glm::vec2) + sizeof(glm::vec4)) * NUM_VERTICES, nullptr, GL_STATIC_DRAW );
801 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * NUM_VERTICES, vertices );
802 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES, sizeof(glm::vec3) * NUM_VERTICES, normals );
803 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2, sizeof(glm::vec2) * NUM_VERTICES, texCoords );
804 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES, sizeof(glm::vec4) * NUM_VERTICES, tangents );
805
806 _cubeVAO.insert( std::pair( sideLength, vaod ) );
807 _cubeVBO.insert( std::pair( sideLength, vbod ) );
808}
809
810inline void CSCI441_INTERNAL::generateCubeVAOIndexed( const GLfloat sideLength ) {
811 const GLfloat CORNER_POINT = sideLength / 2.0f;
812
813 constexpr GLuint64 NUM_VERTICES = 8;
814
815 const glm::vec3 vertices[NUM_VERTICES] = {
816 { -CORNER_POINT, -CORNER_POINT, -CORNER_POINT }, // 0 - bln
817 { CORNER_POINT, -CORNER_POINT, -CORNER_POINT }, // 1 - brn
818 { CORNER_POINT, CORNER_POINT, -CORNER_POINT }, // 2 - trn
819 { -CORNER_POINT, CORNER_POINT, -CORNER_POINT }, // 3 - tln
820 { -CORNER_POINT, -CORNER_POINT, CORNER_POINT }, // 4 - blf
821 { CORNER_POINT, -CORNER_POINT, CORNER_POINT }, // 5 - brf
822 { CORNER_POINT, CORNER_POINT, CORNER_POINT }, // 6 - trf
823 { -CORNER_POINT, CORNER_POINT, CORNER_POINT } // 7 - tlf
824 };
825 const glm::vec3 normals[NUM_VERTICES] = {
826 {-1.0f, -1.0f, -1.0f}, // 0 bln
827 { 1.0f, -1.0f, -1.0f}, // 1 brn
828 { 1.0f, 1.0f, -1.0f}, // 2 trn
829 {-1.0f, 1.0f, -1.0f}, // 3 tln
830 {-1.0f, -1.0f, 1.0f}, // 4 blf
831 { 1.0f, -1.0f, 1.0f}, // 5 brf
832 { 1.0f, 1.0f, 1.0f}, // 6 trf
833 {-1.0f, 1.0f, 1.0f} // 7 tlf
834 };
835 constexpr GLfloat handedness = 1.0f;
836 const glm::vec4 tangents[NUM_VERTICES] = {
837 {-1.0f, 0.0f, 1.0f, handedness}, // 0 bln
838 {-1.0f, 0.0f, -1.0f, handedness}, // 1 brn
839 {-1.0f, 0.0f, -1.0f, handedness}, // 2 trn
840 {-1.0f, 0.0f, 1.0f, handedness}, // 3 tln
841 { 1.0f, 0.0f, 1.0f, handedness}, // 4 blf
842 { 1.0f, 0.0f, -1.0f, handedness}, // 5 brf
843 { 1.0f, 0.0f, -1.0f, handedness}, // 6 trf
844 { 1.0f, 0.0f, 1.0f, handedness} // 7 tlf
845 };
846 const glm::vec3 texCoords[NUM_VERTICES] = {
847 {-1.0f, -1.0f, -1.0f}, // 0 bln
848 { 1.0f, -1.0f, -1.0f}, // 1 brn
849 { 1.0f, 1.0f, -1.0f}, // 2 trn
850 {-1.0f, 1.0f, -1.0f}, // 3 tln
851 {-1.0f, -1.0f, 1.0f}, // 4 blf
852 { 1.0f, -1.0f, 1.0f}, // 5 brf
853 { 1.0f, 1.0f, 1.0f}, // 6 trf
854 {-1.0f, 1.0f, 1.0f} // 7 tlf
855 };
856 const GLushort indices[36] = {
857 0, 2, 1, 0, 3, 2, // near
858 1, 2, 5, 5, 2, 6, // right
859 2, 7, 6, 3, 7, 2, // top
860 0, 1, 4, 1, 5, 4, // bottom
861 4, 5, 6, 4, 6, 7, // back
862 0, 4, 3, 4, 7, 3 // left
863 };
864
865 GLuint vaod;
866 glGenVertexArrays( 1, &vaod );
867 glBindVertexArray( vaod );
868
869 GLuint vbods[2];
870 glGenBuffers( 2, vbods );
871
872 glBindBuffer( GL_ARRAY_BUFFER, vbods[0] );
873 glBufferData(GL_ARRAY_BUFFER, (sizeof(glm::vec3)*2 + sizeof(glm::vec2) + sizeof(glm::vec4)) * NUM_VERTICES, nullptr, GL_STATIC_DRAW );
874 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * NUM_VERTICES, vertices );
875 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES, sizeof(glm::vec3) * NUM_VERTICES, normals );
876 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2, sizeof(glm::vec2) * NUM_VERTICES, texCoords );
877 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES, sizeof(glm::vec4) * NUM_VERTICES, tangents );
878
879 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbods[1] );
880 glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW) ;
881
882 _cubeVAOIndexed.insert( std::pair( sideLength, vaod ) );
883 _cubeVBOIndexed.insert( std::pair( sideLength, vbods[0] ) );
884 _cubeIBOIndexed.insert( std::pair( sideLength, vbods[1] ) );
885}
886
887inline void CSCI441_INTERNAL::generateCylinderVAO( const CylinderData& cylData ) {
888 GLuint vaod;
889 glGenVertexArrays( 1, &vaod );
890 glBindVertexArray( vaod );
891
892 GLuint vbod;
893 glGenBuffers( 1, &vbod );
894 glBindBuffer( GL_ARRAY_BUFFER, vbod );
895
896 const GLuint64 NUM_VERTICES = cylData.numVertices();
897 const auto RADIUS_BOTTOM = cylData.radiusBase;
898 const auto RADIUS_TOP = cylData.radiusTop;
899 const auto NUM_STACKS = cylData.stacks;
900 const auto NUM_STACKS_GL_FLOAT = static_cast<GLfloat>(NUM_STACKS);
901 const auto NUM_SLICES = cylData.slices;
902 const auto NUM_SLICES_GL_FLOAT = static_cast<GLfloat>(NUM_SLICES);
903
904 const GLfloat sliceDelta = glm::two_pi<GLfloat>() / NUM_SLICES_GL_FLOAT;
905 const GLfloat stackDelta = cylData.height / NUM_STACKS_GL_FLOAT;
906 constexpr GLfloat quarterPI = glm::quarter_pi<GLfloat>();
907
908 const auto vertices = new glm::vec3[NUM_VERTICES];
909 const auto normals = new glm::vec3[NUM_VERTICES];
910 const auto tangents = new glm::vec4[NUM_VERTICES];
911 const auto texCoords = new glm::vec2[NUM_VERTICES];
912
913 constexpr GLfloat handedness = 1.0f;
914
915 GLuint64 idx = 0;
916
917 for(GLuint stackNum = 0; stackNum < NUM_STACKS; stackNum++ ) {
918 const auto currStackNum = static_cast<GLfloat>(stackNum);
919 const auto nextStackNum = static_cast<GLfloat>(stackNum + 1);
920 const GLfloat currStackBotRadius = RADIUS_BOTTOM * static_cast<GLfloat>(NUM_STACKS - stackNum ) / NUM_STACKS_GL_FLOAT + RADIUS_TOP * currStackNum / NUM_STACKS_GL_FLOAT;
921 const GLfloat currStackTopRadius = RADIUS_BOTTOM * static_cast<GLfloat>(NUM_STACKS - stackNum - 1) / NUM_STACKS_GL_FLOAT + RADIUS_TOP * nextStackNum / NUM_STACKS_GL_FLOAT;
922
923 for(GLuint sliceNum = 0; sliceNum <= NUM_SLICES; sliceNum++ ) {
924 const auto currSliceNum = static_cast<GLfloat>(sliceNum);
925
926 const auto theta = currSliceNum * sliceDelta;
927 const GLfloat cosTheta = glm::cos( theta );
928 const GLfloat sinTheta = glm::sin( theta );
929
930 vertices[ idx ] = glm::vec3(
931 cosTheta * currStackBotRadius,
932 currStackNum * stackDelta,
933 sinTheta * currStackBotRadius
934 );
935 normals[ idx ] = glm::vec3(
936 cosTheta,
937 0.0f,
938 sinTheta
939 );
940 tangents[ idx ] = glm::vec4(
941 glm::vec3(
942 glm::cos( theta + quarterPI ),
943 0.0f,
944 glm::sin( theta + quarterPI )
945 ),
946 handedness
947 );
948 texCoords[ idx ] = glm::vec2(
949 1.0f - currSliceNum / NUM_SLICES_GL_FLOAT,
950 currStackNum / NUM_STACKS_GL_FLOAT
951 );
952
953 idx++;
954
955 vertices[ idx ] = glm::vec3(
956 cosTheta * currStackTopRadius,
957 nextStackNum * stackDelta,
958 sinTheta * currStackTopRadius
959 );
960 normals[ idx ] = glm::vec3(
961 cosTheta,
962 0.0f,
963 sinTheta
964 );
965 tangents[ idx ] = glm::vec4(
966 glm::vec3(
967 glm::cos( theta + quarterPI ),
968 0.0f,
969 glm::sin( theta + quarterPI )
970 ),
971 handedness
972 );
973 texCoords[ idx ] = glm::vec2(
974 1.0f - currSliceNum / NUM_SLICES_GL_FLOAT,
975 nextStackNum / NUM_STACKS_GL_FLOAT
976 );
977
978 idx++;
979 }
980 }
981
982 glBufferData(GL_ARRAY_BUFFER, (sizeof(glm::vec3)*2 + sizeof(glm::vec2) + sizeof(glm::vec4)) * NUM_VERTICES, nullptr, GL_STATIC_DRAW );
983 glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizeiptr>(sizeof(glm::vec3) * NUM_VERTICES), vertices );
984 glBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(sizeof(glm::vec3) * NUM_VERTICES), static_cast<GLsizeiptr>(sizeof(glm::vec3) * NUM_VERTICES), normals );
985 glBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(sizeof(glm::vec3) * NUM_VERTICES * 2), static_cast<GLsizeiptr>(sizeof(glm::vec2) * NUM_VERTICES), texCoords );
986 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES, sizeof(glm::vec4) * NUM_VERTICES, tangents );
987
988 _cylinderVAO.insert( std::pair( cylData, vaod ) );
989 _cylinderVBO.insert( std::pair( cylData, vbod ) );
990
991 delete[] vertices;
992 delete[] normals;
993 delete[] tangents;
994 delete[] texCoords;
995}
996
997inline void CSCI441_INTERNAL::generateDiskVAO( const DiskData& diskData ) {
998 GLuint vaod;
999 glGenVertexArrays( 1, &vaod );
1000 glBindVertexArray( vaod );
1001
1002 GLuint vbod;
1003 glGenBuffers( 1, &vbod );
1004 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1005
1006 const GLuint64 NUM_VERTICES = diskData.numVertices();
1007
1008 const GLfloat sliceDelta = diskData.sweepAngle / static_cast<GLfloat>(diskData.slices);
1009 const GLfloat ringDelta = (diskData.outerRadius - diskData.innerRadius) / static_cast<GLfloat>(diskData.rings);
1010 constexpr GLfloat quarterPI = glm::pi<GLfloat>() / 4.0f;
1011
1012 const auto vertices = new glm::vec3[NUM_VERTICES];
1013 const auto normals = new glm::vec3[NUM_VERTICES];
1014 const auto tangents = new glm::vec4[NUM_VERTICES];
1015 const auto texCoords = new glm::vec2[NUM_VERTICES];
1016
1017 constexpr GLfloat handedness = 1.0f;
1018
1019 GLuint64 idx = 0;
1020
1021 for(GLuint ringNum = 0; ringNum < diskData.rings; ringNum++ ) {
1022 const GLfloat currRadius = diskData.innerRadius + static_cast<GLfloat>(ringNum) * ringDelta;
1023 const GLfloat nextRadius = diskData.innerRadius + static_cast<GLfloat>(ringNum + 1) * ringDelta;
1024
1025 GLfloat theta = diskData.startAngle;
1026
1027 for(GLuint i = 0; i <= diskData.slices; i++ ) {
1028 const GLfloat cosTheta = glm::cos( theta );
1029 const GLfloat sinTheta = glm::sin( theta );
1030
1031 vertices[ idx ] = glm::vec3(
1032 cosTheta * currRadius,
1033 sinTheta * currRadius,
1034 0.0f
1035 );
1036 normals[ idx ] = CSCI441::Z_AXIS_POS;
1037 tangents[ idx ] = glm::vec4(
1038 glm::vec3(
1039 glm::cos(theta + quarterPI),
1040 glm::sin(theta + quarterPI),
1041 0.0f
1042 ),
1043 handedness
1044 );
1045 texCoords[ idx ] = glm::vec2(
1046 cosTheta * (currRadius / diskData.outerRadius),
1047 sinTheta * (currRadius / diskData.outerRadius)
1048 );
1049
1050 idx++;
1051
1052 vertices[ idx ] = glm::vec3(
1053 cosTheta * nextRadius,
1054 sinTheta * nextRadius,
1055 0.0f
1056 );
1057 normals[ idx ] = CSCI441::Z_AXIS_POS;
1058 tangents[ idx ] = glm::vec4(
1059 glm::vec3(
1060 glm::cos(theta + quarterPI),
1061 glm::sin(theta + quarterPI),
1062 0.0f
1063 ),
1064 handedness
1065 );
1066 texCoords[ idx ] = glm::vec2(
1067 cosTheta * (nextRadius / diskData.outerRadius),
1068 sinTheta * (nextRadius / diskData.outerRadius)
1069 );
1070
1071 idx++;
1072 theta += sliceDelta;
1073 }
1074 }
1075
1076 glBufferData(GL_ARRAY_BUFFER, (sizeof(glm::vec3)*2 + sizeof(glm::vec2) + sizeof(glm::vec4)) * NUM_VERTICES, nullptr, GL_STATIC_DRAW );
1077 glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizeiptr>(sizeof(glm::vec3) * NUM_VERTICES), vertices );
1078 glBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(sizeof(glm::vec3) * NUM_VERTICES), static_cast<GLsizeiptr>(sizeof(glm::vec3) * NUM_VERTICES), normals );
1079 glBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(sizeof(glm::vec3) * NUM_VERTICES * 2), static_cast<GLsizeiptr>(sizeof(glm::vec2) * NUM_VERTICES), texCoords );
1080 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES, sizeof(glm::vec4) * NUM_VERTICES, tangents );
1081
1082 _diskVAO.insert( std::pair( diskData, vaod ) );
1083 _diskVBO.insert( std::pair( diskData, vbod ) );
1084
1085 delete[] vertices;
1086 delete[] normals;
1087 delete[] tangents;
1088 delete[] texCoords;
1089}
1090
1091inline void CSCI441_INTERNAL::generateSphereVAO( const SphereData& sphereData ) {
1092 GLuint vaod;
1093 glGenVertexArrays( 1, &vaod );
1094 glBindVertexArray( vaod );
1095
1096 GLuint vbod;
1097 glGenBuffers( 1, &vbod );
1098 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1099
1100 const GLuint64 NUM_VERTICES = sphereData.numVertices();
1101
1102 const auto RADIUS = sphereData.radius;
1103 const auto NUM_SLICES = sphereData.slices;
1104 const auto NUM_SLICES_GL_FLOAT = static_cast<GLfloat>(NUM_SLICES);
1105 const auto NUM_STACKS = sphereData.stacks;
1106 const auto NUM_STACKS_GL_FLOAT = static_cast<GLfloat>(NUM_STACKS);
1107 const auto NUM_STACKS_LESS_ONE = static_cast<GLfloat>(NUM_STACKS - 1);
1108 const auto NUM_STACKS_LESS_TWO = static_cast<GLfloat>(NUM_STACKS - 2);
1109
1110 const GLfloat sliceDelta = glm::two_pi<GLfloat>() / NUM_SLICES_GL_FLOAT;
1111 const GLfloat stackDelta = glm::pi<GLfloat>() / NUM_STACKS_GL_FLOAT;
1112
1113 const auto vertices = new glm::vec3[NUM_VERTICES];
1114 const auto normals = new glm::vec3[NUM_VERTICES];
1115 const auto tangents = new glm::vec4[NUM_VERTICES];
1116 const auto texCoords = new glm::vec2[NUM_VERTICES];
1117
1118 constexpr GLfloat handedness = 1.0f;
1119
1120 GLuint64 idx = 0;
1121
1122 // sphere top
1123 {
1124 constexpr GLfloat phi = glm::pi<GLfloat>();
1125 const GLfloat cosPhi = glm::cos( phi );
1126
1127 const GLfloat phiNext = stackDelta * NUM_STACKS_LESS_ONE;
1128 const GLfloat sinPhiNext = glm::sin( phiNext );
1129 const GLfloat cosPhiNext = glm::cos( phiNext );
1130
1131 vertices[ idx ] = glm::vec3(
1132 0.0f,
1133 -cosPhi * RADIUS,
1134 0.0f
1135 );
1136 normals [ idx ] = CSCI441::Y_AXIS_POS;
1137 tangents[ idx ] = glm::vec4(
1138 CSCI441::Z_AXIS_POS,
1139 handedness
1140 );
1141 texCoords[idx ] = glm::vec2(
1142 0.5f,
1143 1.0f
1144 );
1145
1146 idx++;
1147
1148 for(GLuint sliceNum = 0; sliceNum <= NUM_SLICES; ++sliceNum ) {
1149 const GLfloat theta = sliceDelta * static_cast<GLfloat>(sliceNum);
1150 const GLfloat sinTheta = glm::sin( theta );
1151 const GLfloat cosTheta = glm::cos( theta );
1152
1153 vertices[ idx ] = glm::vec3(
1154 -cosTheta * sinPhiNext * RADIUS,
1155 -cosPhiNext * RADIUS,
1156 sinTheta * sinPhiNext * RADIUS
1157 );
1158 normals[ idx ] = glm::normalize( vertices[idx] );
1159 tangents[ idx ] = glm::vec4(
1160 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1161 handedness
1162 );
1163 texCoords[ idx ] = glm::vec2(
1164 static_cast<GLfloat>(sliceNum) / NUM_SLICES_GL_FLOAT,
1165 1.0f
1166 );
1167
1168 idx++;
1169 }
1170 }
1171
1172 // sphere stacks
1173 for(GLuint stackNum = 1; stackNum < NUM_STACKS - 1; ++stackNum ) {
1174 const GLfloat phi = stackDelta * static_cast<GLfloat>(stackNum);
1175 const GLfloat sinPhi = glm::sin( phi );
1176 const GLfloat cosPhi = glm::cos( phi );
1177
1178 const GLfloat phiNext = stackDelta * static_cast<GLfloat>(stackNum + 1);
1179 const GLfloat sinPhiNext = glm::sin( phiNext );
1180 const GLfloat cosPhiNext = glm::cos( phiNext );
1181
1182 for(GLuint sliceNum = NUM_SLICES; sliceNum > 0; --sliceNum ) {
1183 const GLfloat theta = sliceDelta * static_cast<GLfloat>(sliceNum);
1184 const GLfloat sinTheta = glm::sin( theta );
1185 const GLfloat cosTheta = glm::cos( theta );
1186
1187 vertices[ idx ] = glm::vec3(
1188 -cosTheta * sinPhi * RADIUS,
1189 -cosPhi * RADIUS,
1190 sinTheta * sinPhi * RADIUS
1191 );
1192 normals[ idx ] = glm::normalize( vertices[idx] );
1193 tangents[ idx ] = glm::vec4(
1194 glm::normalize(glm::cross(CSCI441::Y_AXIS, glm::normalize(normals[idx])) ),
1195 handedness
1196 );
1197 texCoords[ idx ] = glm::vec2(
1198 static_cast<GLfloat>(sliceNum) / NUM_SLICES_GL_FLOAT,
1199 static_cast<GLfloat>(stackNum - 1) / NUM_STACKS_LESS_TWO
1200 );
1201
1202 idx++;
1203
1204 vertices[ idx ] = glm::vec3(
1205 -cosTheta * sinPhiNext * RADIUS,
1206 -cosPhiNext * RADIUS,
1207 sinTheta * sinPhiNext * RADIUS
1208 );
1209 normals[ idx ] = glm::normalize( vertices[idx] );
1210 tangents[ idx ] = glm::vec4(
1211 glm::normalize(glm::cross(CSCI441::Y_AXIS, glm::normalize(normals[idx])) ),
1212 handedness
1213 );
1214 texCoords[ idx ] = glm::vec2(
1215 static_cast<GLfloat>(sliceNum) / NUM_SLICES_GL_FLOAT,
1216 static_cast<GLfloat>(stackNum) / NUM_STACKS_LESS_TWO
1217 );
1218
1219 idx++;
1220 }
1221
1222 vertices[ idx ] = glm::vec3(
1223 -sinPhi * RADIUS,
1224 -cosPhi * RADIUS,
1225 0.0f
1226 );
1227 normals[ idx ] = glm::normalize( vertices[idx] );
1228 tangents[ idx ] = glm::vec4(
1229 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1230 handedness
1231 );
1232 texCoords[ idx ] = glm::vec2(
1233 0.0f,
1234 static_cast<GLfloat>(stackNum - 1) / NUM_STACKS_LESS_TWO
1235 );
1236
1237 idx++;
1238
1239 vertices[ idx ] = glm::vec3(
1240 -sinPhiNext * RADIUS,
1241 -cosPhiNext * RADIUS,
1242 0.0f
1243 );
1244 normals[ idx ] = glm::normalize( vertices[idx] );
1245 tangents[ idx ] = glm::vec4(
1246 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1247 handedness
1248 );
1249 texCoords[ idx ] = glm::vec2(
1250 0.0f,
1251 static_cast<GLfloat>(stackNum) / NUM_STACKS_LESS_TWO
1252 );
1253
1254 idx++;
1255 }
1256
1257 // sphere bottom
1258 {
1259 constexpr GLfloat phi = 0.0f;
1260 const GLfloat cosPhi = glm::cos( phi );
1261
1262 const GLfloat phiNext = stackDelta;
1263 const GLfloat sinPhiNext = glm::sin( phiNext );
1264 const GLfloat cosPhiNext = glm::cos( phiNext );
1265
1266 vertices[ idx ] = glm::vec3(
1267 0.0f,
1268 -cosPhi * RADIUS,
1269 0.0f
1270 );
1271 normals[ idx ] = CSCI441::Y_AXIS_NEG;
1272 tangents[ idx ] = glm::vec4( CSCI441::Z_AXIS_NEG, handedness );
1273 texCoords[ idx ] = glm::vec2(
1274 0.5f,
1275 0.0f
1276 );
1277
1278 idx++;
1279
1280 for(GLuint sliceNum = NUM_SLICES; sliceNum > 0; --sliceNum) {
1281 const GLfloat theta = sliceDelta * static_cast<GLfloat>(sliceNum);
1282 const GLfloat sinTheta = glm::sin( theta );
1283 const GLfloat cosTheta = glm::cos( theta );
1284
1285 vertices[ idx ] = glm::vec3(
1286 -cosTheta * sinPhiNext * RADIUS,
1287 -cosPhiNext * RADIUS,
1288 sinTheta * sinPhiNext * RADIUS
1289 );
1290 normals[ idx ] = glm::normalize( vertices[idx] );
1291 tangents[ idx ] = glm::vec4(
1292 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1293 handedness
1294 );
1295 texCoords[ idx ] = glm::vec2(
1296 static_cast<GLfloat>(sliceNum) / NUM_SLICES_GL_FLOAT,
1297 0.0f
1298 );
1299
1300 idx++;
1301 }
1302
1303 vertices[ idx ] = glm::vec3(
1304 -sinPhiNext * RADIUS,
1305 -cosPhiNext * RADIUS,
1306 0.0f
1307 );
1308 normals[ idx ] = glm::normalize( vertices[idx] );
1309 tangents[ idx ] = glm::vec4(
1310 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1311 handedness
1312 );
1313 texCoords[ idx ] = glm::vec2(
1314 0.0f,
1315 0.0f
1316 );
1317 }
1318
1319 glBufferData(GL_ARRAY_BUFFER, (sizeof(glm::vec3)*2 + sizeof(glm::vec2) + sizeof(glm::vec4)) * NUM_VERTICES, nullptr, GL_STATIC_DRAW );
1320 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * NUM_VERTICES, vertices );
1321 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES, sizeof(glm::vec3) * NUM_VERTICES, normals );
1322 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2, sizeof(glm::vec2) * NUM_VERTICES, texCoords );
1323 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES, sizeof(glm::vec4) * NUM_VERTICES, tangents );
1324
1325 _sphereVAO.insert( std::pair( sphereData, vaod ) );
1326 _sphereVBO.insert( std::pair( sphereData, vbod ) );
1327
1328 delete[] vertices;
1329 delete[] texCoords;
1330 delete[] normals;
1331 delete[] tangents;
1332}
1333
1334inline void CSCI441_INTERNAL::generateTorusVAO( const TorusData& torusData ) {
1335 GLuint vaod;
1336 glGenVertexArrays( 1, &vaod );
1337 glBindVertexArray( vaod );
1338
1339 GLuint vbod;
1340 glGenBuffers( 1, &vbod );
1341 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1342
1343 const auto NUM_VERTICES = torusData.numVertices();
1344 const auto OUTER_RADIUS = torusData.outerRadius;
1345 const auto INNER_RADIUS = torusData.innerRadius;
1346 const auto NUM_SIDES = torusData.sides;
1347 const auto NUM_SIDES_GL_FLOAT = static_cast<GLfloat>(NUM_SIDES);
1348 const auto NUM_RINGS = torusData.rings;
1349 const auto NUM_RINGS_GL_FLOAT = static_cast<GLfloat>(NUM_RINGS);
1350
1351 const auto vertices = new glm::vec3[NUM_VERTICES];
1352 const auto normals = new glm::vec3[NUM_VERTICES];
1353 const auto tangents = new glm::vec4[NUM_VERTICES];
1354 const auto texCoords = new glm::vec2[NUM_VERTICES];
1355
1356 constexpr GLfloat handedness = 1.0f;
1357
1358 GLuint64 idx = 0;
1359
1360 const GLfloat sideDelta = glm::two_pi<GLfloat>() / NUM_SIDES_GL_FLOAT;
1361 const GLfloat ringDelta = glm::two_pi<GLfloat>() / NUM_RINGS_GL_FLOAT;
1362
1363 for(GLuint ringNum = 0; ringNum < NUM_RINGS; ++ringNum ) {
1364 const auto currRingNum = static_cast<GLfloat>(ringNum);
1365 const auto nextRingNum = static_cast<GLfloat>(ringNum + 1);
1366
1367 const GLfloat theta = ringDelta * currRingNum;
1368 const GLfloat sinTheta = glm::sin( theta );
1369 const GLfloat cosTheta = glm::cos( theta );
1370
1371 const GLfloat thetaNext = ringDelta * nextRingNum;
1372 const GLfloat sinThetaNext = glm::sin( thetaNext );
1373 const GLfloat cosThetaNext = glm::cos( thetaNext );
1374
1375 for(GLuint sideNum = 0; sideNum < NUM_SIDES; ++sideNum ) {
1376 const auto currSideNum = static_cast<GLfloat>(sideNum);
1377 const auto nextSideNum = static_cast<GLfloat>(sideNum + 1);
1378
1379 const GLfloat phi = sideDelta * currSideNum;
1380 const GLfloat sinPhi = glm::sin( phi );
1381 const GLfloat cosPhi = glm::cos( phi );
1382
1383 const GLfloat phiNext = sideDelta * nextSideNum;
1384 const GLfloat sinPhiNext = glm::sin( phiNext );
1385 const GLfloat cosPhiNext = glm::cos( phiNext );
1386
1387 vertices[ idx ] = glm::vec3(
1388 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * cosTheta,
1389 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * sinTheta,
1390 INNER_RADIUS * sinPhi
1391 );
1392 normals[ idx ] = glm::vec3(
1393 cosPhi * cosTheta,
1394 cosPhi * sinTheta,
1395 sinPhi
1396 );
1397 tangents[ idx ] = glm::vec4(
1398 glm::vec3(
1399 -(OUTER_RADIUS + INNER_RADIUS * cosPhi ) * sinTheta,
1400 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * cosTheta,
1401 0.0f
1402 ),
1403 handedness
1404 );
1405 texCoords[ idx ] = glm::vec2(
1406 currSideNum / NUM_SIDES_GL_FLOAT,
1407 currRingNum / NUM_RINGS_GL_FLOAT
1408 );
1409
1410 idx++;
1411
1412 vertices[ idx ] = glm::vec3(
1413 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * cosThetaNext,
1414 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * sinThetaNext,
1415 INNER_RADIUS * sinPhi
1416 );
1417 normals[ idx ] = glm::vec3(
1418 cosPhi * cosThetaNext,
1419 cosPhi * sinThetaNext,
1420 sinPhi
1421 );
1422 tangents[ idx ] = glm::vec4(
1423 glm::vec3(
1424 -(OUTER_RADIUS + INNER_RADIUS * cosPhi ) * sinThetaNext,
1425 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * cosThetaNext,
1426 0.0f
1427 ),
1428 handedness
1429 );
1430 texCoords[ idx ] = glm::vec2(
1431 currSideNum / NUM_SIDES_GL_FLOAT,
1432 nextRingNum / NUM_RINGS_GL_FLOAT
1433 );
1434
1435 idx++;
1436
1437 vertices[ idx ] = glm::vec3(
1438 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * cosTheta,
1439 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * sinTheta,
1440 INNER_RADIUS * sinPhiNext
1441 );
1442 normals[ idx ] = glm::vec3(
1443 cosPhiNext * cosTheta,
1444 cosPhiNext * sinTheta,
1445 sinPhiNext
1446 );
1447 tangents[ idx ] = glm::vec4(
1448 glm::vec3(
1449 -(OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * cosTheta,
1450 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * sinTheta,
1451 0.0f
1452 ),
1453 handedness
1454 );
1455 texCoords[ idx ] = glm::vec2(
1456 nextSideNum / NUM_SIDES_GL_FLOAT,
1457 currRingNum / NUM_RINGS_GL_FLOAT
1458 );
1459
1460 idx++;
1461
1462 vertices[ idx ] = glm::vec3(
1463 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * cosThetaNext,
1464 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * sinThetaNext,
1465 INNER_RADIUS * sinPhiNext
1466 );
1467 normals[ idx ] = glm::vec3(
1468 cosPhiNext * cosThetaNext,
1469 cosPhiNext * sinThetaNext,
1470 sinPhiNext
1471 );
1472 tangents[ idx ] = glm::vec4(
1473 glm::vec3(
1474 -(OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * sinThetaNext,
1475 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * cosThetaNext,
1476 0.0f
1477 ),
1478 handedness
1479 );
1480 texCoords[ idx ] = glm::vec2(
1481 nextSideNum / NUM_SIDES_GL_FLOAT,
1482 nextRingNum / NUM_RINGS_GL_FLOAT
1483 );
1484
1485 idx++;
1486 }
1487 }
1488
1489 glBufferData(GL_ARRAY_BUFFER, (sizeof(glm::vec3)*2 + sizeof(glm::vec2) + sizeof(glm::vec4)) * NUM_VERTICES, nullptr, GL_STATIC_DRAW );
1490 glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizeiptr>(sizeof(glm::vec3) * NUM_VERTICES), vertices );
1491 glBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(sizeof(glm::vec3) * NUM_VERTICES), static_cast<GLsizeiptr>(sizeof(glm::vec3) * NUM_VERTICES), normals );
1492 glBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(sizeof(glm::vec3) * NUM_VERTICES * 2), static_cast<GLsizeiptr>(sizeof(glm::vec2) * NUM_VERTICES), texCoords );
1493 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * NUM_VERTICES * 2 + sizeof(glm::vec2) * NUM_VERTICES, sizeof(glm::vec4) * NUM_VERTICES, tangents );
1494
1495 _torusVAO.insert( std::pair( torusData, vaod ) );
1496 _torusVBO.insert( std::pair( torusData, vbod ) );
1497
1498 delete[] vertices;
1499 delete[] normals;
1500 delete[] tangents;
1501 delete[] texCoords;
1502}
1503
1504#endif//CSCI441_OBJECTS_IMPL_HPP
Helper functions to work with OpenGL 3.0+.
void deleteObjectVBOs()
deletes the VBOs stored for all object types
Definition: objects.hpp:359
void deleteObjectVAOs()
deletes the VAOs stored for all object types
Definition: objects.hpp:354
Helper functions to draw teapot with OpenGL 3.0+.