15#ifndef CSCI441_OBJECTS_IMPL_HPP
16#define CSCI441_OBJECTS_IMPL_HPP
21#ifdef CSCI441_USE_GLEW
27#include <glm/gtc/constants.hpp>
28#include <glm/trigonometric.hpp>
43namespace CSCI441_INTERNAL {
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 );
135 inline GLint _positionAttributeLocation = -1;
139 inline GLint _normalAttributeLocation = -1;
143 inline GLint _texCoordAttributeLocation = -1;
147 inline GLint _tangentAttributeLocation = -1;
153 void generateCubeVAOFlat( GLfloat sideLength );
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;
182 struct CylinderData {
194 [[nodiscard]] GLuint64 numVertices()
const {
return stacks * (slices + 1) * 2; }
196 bool operator<(
const CylinderData rhs )
const {
197 if( radiusBase < rhs.radiusBase ) {
199 }
else if( fabs(radiusBase - rhs.radiusBase) <= 0.000001 ) {
200 if( radiusTop < rhs.radiusTop ) {
202 }
else if( fabs(radiusTop - rhs.radiusTop) <= 0.000001 ) {
203 if( height < rhs.height ) {
205 }
else if( fabs(height - rhs.height) <= 0.000001 ) {
206 if( stacks < rhs.stacks ) {
208 }
else if( stacks == rhs.stacks ) {
209 if( slices < rhs.slices ) {
219 void generateCylinderVAO(
const CylinderData& cylData );
220 inline std::map< CylinderData, GLuint > _cylinderVAO;
221 inline std::map< CylinderData, GLuint > _cylinderVBO;
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 ) {
230 }
else if( fabs(innerRadius - rhs.innerRadius) <= 0.000001 ) {
231 if( outerRadius < rhs.outerRadius ) {
233 }
else if( fabs(outerRadius - rhs.outerRadius) <= 0.000001 ) {
234 if( startAngle < rhs.startAngle ) {
236 }
else if( fabs(startAngle - rhs.startAngle) <= 0.000001 ) {
237 if( sweepAngle < rhs.sweepAngle ) {
239 }
else if( fabs(sweepAngle - rhs.sweepAngle) <= 0.000001 ) {
240 if( slices < rhs.slices ) {
242 }
else if( slices == rhs.slices ) {
243 if(rings < rhs.rings ) {
254 void generateDiskVAO(
const DiskData& diskData );
255 inline std::map< DiskData, GLuint > _diskVAO;
256 inline std::map< DiskData, GLuint > _diskVBO;
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 ) {
265 }
else if( fabs(radius - rhs.radius) <= 0.000001 ) {
266 if( stacks < rhs.stacks ) {
268 }
else if( stacks == rhs.stacks ) {
269 if( slices < rhs.slices ) {
277 void generateSphereVAO(
const SphereData& sphereData );
278 inline std::map< SphereData, GLuint > _sphereVAO;
279 inline std::map< SphereData, GLuint > _sphereVBO;
282 GLfloat innerRadius, outerRadius;
284 [[nodiscard]] GLuint64 numVertices()
const {
return sides * 4 * rings; }
285 bool operator<(
const TorusData rhs )
const {
286 if( innerRadius < rhs.innerRadius ) {
288 }
else if( fabs(innerRadius - rhs.innerRadius) <= 0.000001 ) {
289 if( outerRadius < rhs.outerRadius ) {
291 }
else if( fabs(outerRadius - rhs.outerRadius) <= 0.000001 ) {
292 if( sides < rhs.sides ) {
294 }
else if( sides == rhs.sides ) {
295 if( rings < rhs.rings ) {
304 void generateTorusVAO(
const TorusData& torusData );
305 inline std::map< TorusData, GLuint > _torusVAO;
306 inline std::map< TorusData, GLuint > _torusVBO;
313inline void CSCI441_INTERNAL::deleteObjectVAOs() {
314 for(
auto &[sideLength, vaod] : _cubeVAO) {
315 glDeleteVertexArrays(1, &vaod);
319 for(
auto &[sideLength, vaod] : _cubeVAOIndexed) {
320 glDeleteVertexArrays(1, &vaod);
322 _cubeVAOIndexed.clear();
324 for(
auto &[cylData, vaod] : _cylinderVAO) {
325 glDeleteVertexArrays(1, &vaod);
327 _cylinderVAO.clear();
329 for(
auto &[diskData, vaod] : _diskVAO) {
330 glDeleteVertexArrays(1, &vaod);
334 for(
auto &[sphereData, vaod] : _sphereVAO) {
335 glDeleteVertexArrays(1, &vaod);
339 for(
auto &[torusData, vaod] : _torusVAO) {
340 glDeleteVertexArrays(1, &vaod);
345inline void CSCI441_INTERNAL::deleteObjectVBOs() {
346 for(
auto &[sideLength, vbod] : _cubeVBO) {
347 glDeleteBuffers(1, &vbod);
351 for(
auto &[sideLength, vbod] : _cubeVBOIndexed) {
352 glDeleteBuffers(1, &vbod);
354 _cubeVBOIndexed.clear();
356 for(
auto &[sideLength, vbod] : _cubeIBOIndexed) {
357 glDeleteBuffers(1, &vbod);
359 _cubeIBOIndexed.clear();
361 for(
auto &[cylData, vbod] : _cylinderVBO) {
362 glDeleteBuffers(1, &vbod);
364 _cylinderVBO.clear();
366 for(
auto &[diskData, vbod] : _diskVBO) {
367 glDeleteBuffers(1, &vbod);
371 for(
auto &[sphereData, vbod] : _sphereVBO) {
372 glDeleteBuffers(1, &vbod);
376 for(
auto &[torusData, vbod] : _torusVBO) {
377 glDeleteBuffers(1, &vbod);
382inline void CSCI441_INTERNAL::drawCube(
const GLfloat sideLength,
const GLenum renderMode ) {
383 drawCubeIndexed(sideLength, renderMode);
386inline void CSCI441_INTERNAL::drawCubeFlat(
const GLfloat sideLength,
const GLenum renderMode ) {
387 if( _cubeVAO.count( sideLength ) == 0 ) {
388 generateCubeVAOFlat( sideLength );
391 constexpr GLuint64 NUM_VERTICES = 36;
393 GLint currentPolygonMode[2];
394 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
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 );
403 if(_normalAttributeLocation != -1) {
404 glEnableVertexAttribArray( _normalAttributeLocation );
405 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * NUM_VERTICES) );
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) );
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) );
416 glDrawArrays( GL_TRIANGLES, 0, 36 );
418 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
421inline void CSCI441_INTERNAL::drawCubeIndexed(
const GLfloat sideLength,
const GLenum renderMode ) {
422 if( _cubeVAOIndexed.count( sideLength ) == 0 ) {
423 generateCubeVAOIndexed( sideLength );
426 constexpr GLuint64 NUM_VERTICES = 8;
428 GLint currentPolygonMode[2];
429 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
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 );
438 if(_normalAttributeLocation != -1) {
439 glEnableVertexAttribArray( _normalAttributeLocation );
440 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * NUM_VERTICES) );
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) );
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) );
451 glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT,
nullptr);
453 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
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 );
462 const GLuint64 NUM_VERTICES = cylData.numVertices();
464 GLint currentPolygonMode[2];
465 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
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 );
474 if(_normalAttributeLocation != -1) {
475 glEnableVertexAttribArray( _normalAttributeLocation );
476 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * NUM_VERTICES) );
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) );
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) );
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) );
491 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
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 );
500 const GLuint64 NUM_VERTICES = diskData.numVertices();
502 GLint currentPolygonMode[2];
503 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
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 );
512 if(_normalAttributeLocation != -1) {
513 glEnableVertexAttribArray( _normalAttributeLocation );
514 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * NUM_VERTICES) );
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) );
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) );
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) );
529 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
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 );
538 const GLuint64 NUM_VERTICES = sphereData.numVertices();
540 GLint currentPolygonMode[2];
541 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
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 );
550 if(_normalAttributeLocation != -1) {
551 glEnableVertexAttribArray( _normalAttributeLocation );
552 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * NUM_VERTICES) );
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) );
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) );
563 glDrawArrays( GL_TRIANGLE_FAN, 0,
static_cast<GLint
>(slices+2) );
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) );
569 glDrawArrays( GL_TRIANGLE_FAN,
static_cast<GLint
>((slices+2) + (stacks-2)*(slices+1)*2),
static_cast<GLint
>(slices+2) );
571 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
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 );
580 const GLuint64 NUM_VERTICES = sphereData.numVertices();
582 GLint currentPolygonMode[2];
583 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
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 );
592 if(_normalAttributeLocation != -1) {
593 glEnableVertexAttribArray( _normalAttributeLocation );
594 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * NUM_VERTICES) );
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) );
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) );
605 glDrawArrays( GL_TRIANGLE_FAN,
static_cast<GLint
>((slices+2)/2),
static_cast<GLint
>((slices+2)/2) );
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) );
611 glDrawArrays( GL_TRIANGLE_FAN,
static_cast<GLint
>((slices+2) + (stacks-2)*(slices+1)*2),
static_cast<GLint
>((slices+2)/2) );
613 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
615 drawPartialDisk(0.0f, radius, slices, stacks, 0.0f, glm::two_pi<GLfloat>(), renderMode);
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 );
624 const GLuint64 NUM_VERTICES = sphereData.numVertices();
626 GLint currentPolygonMode[2];
627 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
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 );
636 if(_normalAttributeLocation != -1) {
637 glEnableVertexAttribArray( _normalAttributeLocation );
638 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * NUM_VERTICES) );
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) );
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) );
649 glDrawArrays( GL_TRIANGLE_FAN, 0,
static_cast<GLint
>(slices+2) );
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) );
655 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
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 );
664 const GLuint64 NUM_VERTICES = torusData.numVertices();
666 GLint currentPolygonMode[2];
667 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
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 );
676 if(_normalAttributeLocation != -1) {
677 glEnableVertexAttribArray( _normalAttributeLocation );
678 glVertexAttribPointer( _normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * NUM_VERTICES) );
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) );
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) );
689 for(GLuint ringNum = 0; ringNum < rings; ringNum++) {
690 glDrawArrays( GL_TRIANGLE_STRIP,
static_cast<GLint
>(ringNum*sides*4),
static_cast<GLint
>(sides*4) );
693 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
696inline void CSCI441_INTERNAL::drawTeapot(
const GLenum renderMode ) {
697 GLint currentPolygonMode[2];
698 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
700 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
702 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
705inline void CSCI441_INTERNAL::generateCubeVAOFlat(
const GLfloat sideLength ) {
707 glGenVertexArrays( 1, &vaod );
708 glBindVertexArray( vaod );
711 glGenBuffers( 1, &vbod );
712 glBindBuffer( GL_ARRAY_BUFFER, vbod );
714 const GLfloat CORNER_POINT = sideLength / 2.0f;
716 constexpr GLuint64 NUM_VERTICES = 36;
718 const glm::vec3 vertices[NUM_VERTICES] = {
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},
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},
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},
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},
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},
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}
738 const glm::vec3 normals[NUM_VERTICES] = {
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,
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,
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,
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,
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,
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
758 constexpr GLfloat handedness = 1.0f;
759 const glm::vec4 tangents[NUM_VERTICES] = {
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),
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),
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),
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),
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),
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)
779 const glm::vec2 texCoords[NUM_VERTICES] = {
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},
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},
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},
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},
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},
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}
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 );
806 _cubeVAO.insert( std::pair( sideLength, vaod ) );
807 _cubeVBO.insert( std::pair( sideLength, vbod ) );
810inline void CSCI441_INTERNAL::generateCubeVAOIndexed(
const GLfloat sideLength ) {
811 const GLfloat CORNER_POINT = sideLength / 2.0f;
813 constexpr GLuint64 NUM_VERTICES = 8;
815 const glm::vec3 vertices[NUM_VERTICES] = {
816 { -CORNER_POINT, -CORNER_POINT, -CORNER_POINT },
817 { CORNER_POINT, -CORNER_POINT, -CORNER_POINT },
818 { CORNER_POINT, CORNER_POINT, -CORNER_POINT },
819 { -CORNER_POINT, CORNER_POINT, -CORNER_POINT },
820 { -CORNER_POINT, -CORNER_POINT, CORNER_POINT },
821 { CORNER_POINT, -CORNER_POINT, CORNER_POINT },
822 { CORNER_POINT, CORNER_POINT, CORNER_POINT },
823 { -CORNER_POINT, CORNER_POINT, CORNER_POINT }
825 const glm::vec3 normals[NUM_VERTICES] = {
826 {-1.0f, -1.0f, -1.0f},
827 { 1.0f, -1.0f, -1.0f},
828 { 1.0f, 1.0f, -1.0f},
829 {-1.0f, 1.0f, -1.0f},
830 {-1.0f, -1.0f, 1.0f},
831 { 1.0f, -1.0f, 1.0f},
835 constexpr GLfloat handedness = 1.0f;
836 const glm::vec4 tangents[NUM_VERTICES] = {
837 {-1.0f, 0.0f, 1.0f, handedness},
838 {-1.0f, 0.0f, -1.0f, handedness},
839 {-1.0f, 0.0f, -1.0f, handedness},
840 {-1.0f, 0.0f, 1.0f, handedness},
841 { 1.0f, 0.0f, 1.0f, handedness},
842 { 1.0f, 0.0f, -1.0f, handedness},
843 { 1.0f, 0.0f, -1.0f, handedness},
844 { 1.0f, 0.0f, 1.0f, handedness}
846 const glm::vec3 texCoords[NUM_VERTICES] = {
847 {-1.0f, -1.0f, -1.0f},
848 { 1.0f, -1.0f, -1.0f},
849 { 1.0f, 1.0f, -1.0f},
850 {-1.0f, 1.0f, -1.0f},
851 {-1.0f, -1.0f, 1.0f},
852 { 1.0f, -1.0f, 1.0f},
856 const GLushort indices[36] = {
866 glGenVertexArrays( 1, &vaod );
867 glBindVertexArray( vaod );
870 glGenBuffers( 2, vbods );
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 );
879 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbods[1] );
880 glBufferData( GL_ELEMENT_ARRAY_BUFFER,
sizeof(indices), indices, GL_STATIC_DRAW) ;
882 _cubeVAOIndexed.insert( std::pair( sideLength, vaod ) );
883 _cubeVBOIndexed.insert( std::pair( sideLength, vbods[0] ) );
884 _cubeIBOIndexed.insert( std::pair( sideLength, vbods[1] ) );
887inline void CSCI441_INTERNAL::generateCylinderVAO(
const CylinderData& cylData ) {
889 glGenVertexArrays( 1, &vaod );
890 glBindVertexArray( vaod );
893 glGenBuffers( 1, &vbod );
894 glBindBuffer( GL_ARRAY_BUFFER, vbod );
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);
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>();
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];
913 constexpr GLfloat handedness = 1.0f;
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;
923 for(GLuint sliceNum = 0; sliceNum <= NUM_SLICES; sliceNum++ ) {
924 const auto currSliceNum =
static_cast<GLfloat
>(sliceNum);
926 const auto theta = currSliceNum * sliceDelta;
927 const GLfloat cosTheta = glm::cos( theta );
928 const GLfloat sinTheta = glm::sin( theta );
930 vertices[ idx ] = glm::vec3(
931 cosTheta * currStackBotRadius,
932 currStackNum * stackDelta,
933 sinTheta * currStackBotRadius
935 normals[ idx ] = glm::vec3(
940 tangents[ idx ] = glm::vec4(
942 glm::cos( theta + quarterPI ),
944 glm::sin( theta + quarterPI )
948 texCoords[ idx ] = glm::vec2(
949 1.0f - currSliceNum / NUM_SLICES_GL_FLOAT,
950 currStackNum / NUM_STACKS_GL_FLOAT
955 vertices[ idx ] = glm::vec3(
956 cosTheta * currStackTopRadius,
957 nextStackNum * stackDelta,
958 sinTheta * currStackTopRadius
960 normals[ idx ] = glm::vec3(
965 tangents[ idx ] = glm::vec4(
967 glm::cos( theta + quarterPI ),
969 glm::sin( theta + quarterPI )
973 texCoords[ idx ] = glm::vec2(
974 1.0f - currSliceNum / NUM_SLICES_GL_FLOAT,
975 nextStackNum / NUM_STACKS_GL_FLOAT
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 );
988 _cylinderVAO.insert( std::pair( cylData, vaod ) );
989 _cylinderVBO.insert( std::pair( cylData, vbod ) );
997inline void CSCI441_INTERNAL::generateDiskVAO(
const DiskData& diskData ) {
999 glGenVertexArrays( 1, &vaod );
1000 glBindVertexArray( vaod );
1003 glGenBuffers( 1, &vbod );
1004 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1006 const GLuint64 NUM_VERTICES = diskData.numVertices();
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;
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];
1017 constexpr GLfloat handedness = 1.0f;
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;
1025 GLfloat theta = diskData.startAngle;
1027 for(GLuint i = 0; i <= diskData.slices; i++ ) {
1028 const GLfloat cosTheta = glm::cos( theta );
1029 const GLfloat sinTheta = glm::sin( theta );
1031 vertices[ idx ] = glm::vec3(
1032 cosTheta * currRadius,
1033 sinTheta * currRadius,
1036 normals[ idx ] = CSCI441::Z_AXIS_POS;
1037 tangents[ idx ] = glm::vec4(
1039 glm::cos(theta + quarterPI),
1040 glm::sin(theta + quarterPI),
1045 texCoords[ idx ] = glm::vec2(
1046 cosTheta * (currRadius / diskData.outerRadius),
1047 sinTheta * (currRadius / diskData.outerRadius)
1052 vertices[ idx ] = glm::vec3(
1053 cosTheta * nextRadius,
1054 sinTheta * nextRadius,
1057 normals[ idx ] = CSCI441::Z_AXIS_POS;
1058 tangents[ idx ] = glm::vec4(
1060 glm::cos(theta + quarterPI),
1061 glm::sin(theta + quarterPI),
1066 texCoords[ idx ] = glm::vec2(
1067 cosTheta * (nextRadius / diskData.outerRadius),
1068 sinTheta * (nextRadius / diskData.outerRadius)
1072 theta += sliceDelta;
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 );
1082 _diskVAO.insert( std::pair( diskData, vaod ) );
1083 _diskVBO.insert( std::pair( diskData, vbod ) );
1091inline void CSCI441_INTERNAL::generateSphereVAO(
const SphereData& sphereData ) {
1093 glGenVertexArrays( 1, &vaod );
1094 glBindVertexArray( vaod );
1097 glGenBuffers( 1, &vbod );
1098 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1100 const GLuint64 NUM_VERTICES = sphereData.numVertices();
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);
1110 const GLfloat sliceDelta = glm::two_pi<GLfloat>() / NUM_SLICES_GL_FLOAT;
1111 const GLfloat stackDelta = glm::pi<GLfloat>() / NUM_STACKS_GL_FLOAT;
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];
1118 constexpr GLfloat handedness = 1.0f;
1124 constexpr GLfloat phi = glm::pi<GLfloat>();
1125 const GLfloat cosPhi = glm::cos( phi );
1127 const GLfloat phiNext = stackDelta * NUM_STACKS_LESS_ONE;
1128 const GLfloat sinPhiNext = glm::sin( phiNext );
1129 const GLfloat cosPhiNext = glm::cos( phiNext );
1131 vertices[ idx ] = glm::vec3(
1136 normals [ idx ] = CSCI441::Y_AXIS_POS;
1137 tangents[ idx ] = glm::vec4(
1138 CSCI441::Z_AXIS_POS,
1141 texCoords[idx ] = glm::vec2(
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 );
1153 vertices[ idx ] = glm::vec3(
1154 -cosTheta * sinPhiNext * RADIUS,
1155 -cosPhiNext * RADIUS,
1156 sinTheta * sinPhiNext * RADIUS
1158 normals[ idx ] = glm::normalize( vertices[idx] );
1159 tangents[ idx ] = glm::vec4(
1160 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1163 texCoords[ idx ] = glm::vec2(
1164 static_cast<GLfloat
>(sliceNum) / NUM_SLICES_GL_FLOAT,
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 );
1178 const GLfloat phiNext = stackDelta *
static_cast<GLfloat
>(stackNum + 1);
1179 const GLfloat sinPhiNext = glm::sin( phiNext );
1180 const GLfloat cosPhiNext = glm::cos( phiNext );
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 );
1187 vertices[ idx ] = glm::vec3(
1188 -cosTheta * sinPhi * RADIUS,
1190 sinTheta * sinPhi * RADIUS
1192 normals[ idx ] = glm::normalize( vertices[idx] );
1193 tangents[ idx ] = glm::vec4(
1194 glm::normalize(glm::cross(CSCI441::Y_AXIS, glm::normalize(normals[idx])) ),
1197 texCoords[ idx ] = glm::vec2(
1198 static_cast<GLfloat
>(sliceNum) / NUM_SLICES_GL_FLOAT,
1199 static_cast<GLfloat
>(stackNum - 1) / NUM_STACKS_LESS_TWO
1204 vertices[ idx ] = glm::vec3(
1205 -cosTheta * sinPhiNext * RADIUS,
1206 -cosPhiNext * RADIUS,
1207 sinTheta * sinPhiNext * RADIUS
1209 normals[ idx ] = glm::normalize( vertices[idx] );
1210 tangents[ idx ] = glm::vec4(
1211 glm::normalize(glm::cross(CSCI441::Y_AXIS, glm::normalize(normals[idx])) ),
1214 texCoords[ idx ] = glm::vec2(
1215 static_cast<GLfloat
>(sliceNum) / NUM_SLICES_GL_FLOAT,
1216 static_cast<GLfloat
>(stackNum) / NUM_STACKS_LESS_TWO
1222 vertices[ idx ] = glm::vec3(
1227 normals[ idx ] = glm::normalize( vertices[idx] );
1228 tangents[ idx ] = glm::vec4(
1229 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1232 texCoords[ idx ] = glm::vec2(
1234 static_cast<GLfloat
>(stackNum - 1) / NUM_STACKS_LESS_TWO
1239 vertices[ idx ] = glm::vec3(
1240 -sinPhiNext * RADIUS,
1241 -cosPhiNext * RADIUS,
1244 normals[ idx ] = glm::normalize( vertices[idx] );
1245 tangents[ idx ] = glm::vec4(
1246 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1249 texCoords[ idx ] = glm::vec2(
1251 static_cast<GLfloat
>(stackNum) / NUM_STACKS_LESS_TWO
1259 constexpr GLfloat phi = 0.0f;
1260 const GLfloat cosPhi = glm::cos( phi );
1262 const GLfloat phiNext = stackDelta;
1263 const GLfloat sinPhiNext = glm::sin( phiNext );
1264 const GLfloat cosPhiNext = glm::cos( phiNext );
1266 vertices[ idx ] = glm::vec3(
1271 normals[ idx ] = CSCI441::Y_AXIS_NEG;
1272 tangents[ idx ] = glm::vec4( CSCI441::Z_AXIS_NEG, handedness );
1273 texCoords[ idx ] = glm::vec2(
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 );
1285 vertices[ idx ] = glm::vec3(
1286 -cosTheta * sinPhiNext * RADIUS,
1287 -cosPhiNext * RADIUS,
1288 sinTheta * sinPhiNext * RADIUS
1290 normals[ idx ] = glm::normalize( vertices[idx] );
1291 tangents[ idx ] = glm::vec4(
1292 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1295 texCoords[ idx ] = glm::vec2(
1296 static_cast<GLfloat
>(sliceNum) / NUM_SLICES_GL_FLOAT,
1303 vertices[ idx ] = glm::vec3(
1304 -sinPhiNext * RADIUS,
1305 -cosPhiNext * RADIUS,
1308 normals[ idx ] = glm::normalize( vertices[idx] );
1309 tangents[ idx ] = glm::vec4(
1310 glm::normalize(glm::cross(CSCI441::Y_AXIS, normals[idx]) ),
1313 texCoords[ idx ] = glm::vec2(
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 );
1325 _sphereVAO.insert( std::pair( sphereData, vaod ) );
1326 _sphereVBO.insert( std::pair( sphereData, vbod ) );
1334inline void CSCI441_INTERNAL::generateTorusVAO(
const TorusData& torusData ) {
1336 glGenVertexArrays( 1, &vaod );
1337 glBindVertexArray( vaod );
1340 glGenBuffers( 1, &vbod );
1341 glBindBuffer( GL_ARRAY_BUFFER, vbod );
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);
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];
1356 constexpr GLfloat handedness = 1.0f;
1360 const GLfloat sideDelta = glm::two_pi<GLfloat>() / NUM_SIDES_GL_FLOAT;
1361 const GLfloat ringDelta = glm::two_pi<GLfloat>() / NUM_RINGS_GL_FLOAT;
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);
1367 const GLfloat theta = ringDelta * currRingNum;
1368 const GLfloat sinTheta = glm::sin( theta );
1369 const GLfloat cosTheta = glm::cos( theta );
1371 const GLfloat thetaNext = ringDelta * nextRingNum;
1372 const GLfloat sinThetaNext = glm::sin( thetaNext );
1373 const GLfloat cosThetaNext = glm::cos( thetaNext );
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);
1379 const GLfloat phi = sideDelta * currSideNum;
1380 const GLfloat sinPhi = glm::sin( phi );
1381 const GLfloat cosPhi = glm::cos( phi );
1383 const GLfloat phiNext = sideDelta * nextSideNum;
1384 const GLfloat sinPhiNext = glm::sin( phiNext );
1385 const GLfloat cosPhiNext = glm::cos( phiNext );
1387 vertices[ idx ] = glm::vec3(
1388 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * cosTheta,
1389 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * sinTheta,
1390 INNER_RADIUS * sinPhi
1392 normals[ idx ] = glm::vec3(
1397 tangents[ idx ] = glm::vec4(
1399 -(OUTER_RADIUS + INNER_RADIUS * cosPhi ) * sinTheta,
1400 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * cosTheta,
1405 texCoords[ idx ] = glm::vec2(
1406 currSideNum / NUM_SIDES_GL_FLOAT,
1407 currRingNum / NUM_RINGS_GL_FLOAT
1412 vertices[ idx ] = glm::vec3(
1413 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * cosThetaNext,
1414 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * sinThetaNext,
1415 INNER_RADIUS * sinPhi
1417 normals[ idx ] = glm::vec3(
1418 cosPhi * cosThetaNext,
1419 cosPhi * sinThetaNext,
1422 tangents[ idx ] = glm::vec4(
1424 -(OUTER_RADIUS + INNER_RADIUS * cosPhi ) * sinThetaNext,
1425 (OUTER_RADIUS + INNER_RADIUS * cosPhi ) * cosThetaNext,
1430 texCoords[ idx ] = glm::vec2(
1431 currSideNum / NUM_SIDES_GL_FLOAT,
1432 nextRingNum / NUM_RINGS_GL_FLOAT
1437 vertices[ idx ] = glm::vec3(
1438 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * cosTheta,
1439 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * sinTheta,
1440 INNER_RADIUS * sinPhiNext
1442 normals[ idx ] = glm::vec3(
1443 cosPhiNext * cosTheta,
1444 cosPhiNext * sinTheta,
1447 tangents[ idx ] = glm::vec4(
1449 -(OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * cosTheta,
1450 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * sinTheta,
1455 texCoords[ idx ] = glm::vec2(
1456 nextSideNum / NUM_SIDES_GL_FLOAT,
1457 currRingNum / NUM_RINGS_GL_FLOAT
1462 vertices[ idx ] = glm::vec3(
1463 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * cosThetaNext,
1464 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * sinThetaNext,
1465 INNER_RADIUS * sinPhiNext
1467 normals[ idx ] = glm::vec3(
1468 cosPhiNext * cosThetaNext,
1469 cosPhiNext * sinThetaNext,
1472 tangents[ idx ] = glm::vec4(
1474 -(OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * sinThetaNext,
1475 (OUTER_RADIUS + INNER_RADIUS * cosPhiNext ) * cosThetaNext,
1480 texCoords[ idx ] = glm::vec2(
1481 nextSideNum / NUM_SIDES_GL_FLOAT,
1482 nextRingNum / NUM_RINGS_GL_FLOAT
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 );
1495 _torusVAO.insert( std::pair( torusData, vaod ) );
1496 _torusVBO.insert( std::pair( torusData, vbod ) );
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+.