15#ifndef CSCI441_OBJECTS_HPP
16#define CSCI441_OBJECTS_HPP
20#ifdef CSCI441_USE_GLEW
26#include <glm/gtc/constants.hpp>
69 [[maybe_unused]]
void drawSolidCone( GLfloat base, GLfloat height, GLint stacks, GLint slices );
82 [[maybe_unused]]
void drawWireCone( GLfloat base, GLfloat height, GLint stacks, GLint slices );
117 [[maybe_unused]]
void drawWireCube( GLfloat sideLength );
125 [[maybe_unused]]
void drawCubeMap( GLfloat sideLength );
140 [[maybe_unused]]
void drawSolidCylinder( GLfloat base, GLfloat top, GLfloat height, GLint stacks, GLint slices );
154 [[maybe_unused]]
void drawWireCylinder( GLfloat base, GLfloat top, GLfloat height, GLint stacks, GLint slices );
169 [[maybe_unused]]
void drawSolidDisk( GLfloat inner, GLfloat outer, GLint slices, GLint rings );
183 [[maybe_unused]]
void drawWireDisk( GLfloat inner, GLfloat outer, GLint slices, GLint rings );
202 [[maybe_unused]]
void drawSolidPartialDisk( GLfloat inner, GLfloat outer, GLint slices, GLint rings, GLfloat start, GLfloat sweep );
220 [[maybe_unused]]
void drawWirePartialDisk( GLfloat inner, GLfloat outer, GLint slices, GLint rings, GLfloat start, GLfloat sweep );
232 [[maybe_unused]]
void drawSolidSphere( GLfloat radius, GLint stacks, GLint slices );
243 [[maybe_unused]]
void drawWireSphere( GLfloat radius, GLint stacks, GLint slices );
266 [[maybe_unused]]
void drawWireHalfSphere( GLfloat radius, GLint stacks, GLint slices );
278 [[maybe_unused]]
void drawSolidDome( GLfloat radius, GLint stacks, GLint slices );
289 [[maybe_unused]]
void drawWireDome( GLfloat radius, GLint stacks, GLint slices );
318 [[maybe_unused]]
void drawSolidTorus( GLfloat innerRadius, GLfloat outerRadius, GLint sides, GLint rings );
331 [[maybe_unused]]
void drawWireTorus( GLfloat innerRadius, GLfloat outerRadius, GLint sides, GLint rings );
345namespace CSCI441_INTERNAL {
360 void drawCube( GLfloat sideLength, GLenum renderMode );
366 void drawCubeIndexed( GLfloat sideLength, GLenum renderMode );
372 void drawCubeFlat( GLfloat sideLength, GLenum renderMode );
383 void drawCylinder( GLfloat base, GLfloat top, GLfloat height, GLuint stacks, GLuint slices, GLenum renderMode );
384 void drawPartialDisk(GLfloat innerRadius, GLfloat outerRadius, GLuint slices, GLuint rings, GLfloat startAngle, GLfloat sweepAngle, GLenum renderMode );
385 void drawSphere( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode );
386 void drawHalfSphere( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode );
387 void drawDome( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode );
388 void drawTorus( GLfloat innerRadius, GLfloat outerRadius, GLuint sides, GLuint rings, GLenum renderMode );
393 void drawTeapot( GLenum renderMode );
398 inline GLint _positionAttributeLocation = -1;
402 inline GLint _normalAttributeLocation = -1;
406 inline GLint _texCoordAttributeLocation = -1;
412 void generateCubeVAOFlat( GLfloat sideLength );
413 void generateCubeVAOIndexed( GLfloat sideLength );
414 inline std::map< GLfloat, GLuint > _cubeVAO;
415 inline std::map< GLfloat, GLuint > _cubeVBO;
416 inline std::map< GLfloat, GLuint > _cubeVAOIndexed;
417 inline std::map< GLfloat, GLuint > _cubeVBOIndexed;
418 inline std::map< GLfloat, GLuint > _cubeIBOIndexed;
421 struct CylinderData {
433 [[nodiscard]] GLuint64 numVertices()
const {
return stacks * (slices + 1) * 2; }
435 bool operator<(
const CylinderData rhs )
const {
436 if( radiusBase < rhs.radiusBase ) {
438 }
else if( fabs(radiusBase - rhs.radiusBase) <= 0.000001 ) {
439 if( top < rhs.top ) {
441 }
else if( fabs(top - rhs.top) <= 0.000001 ) {
442 if( height < rhs.height ) {
444 }
else if( fabs(height - rhs.height) <= 0.000001 ) {
445 if( stacks < rhs.stacks ) {
447 }
else if( stacks == rhs.stacks ) {
448 if( slices < rhs.slices ) {
458 void generateCylinderVAO( CylinderData cylData );
459 inline std::map< CylinderData, GLuint > _cylinderVAO;
460 inline std::map< CylinderData, GLuint > _cylinderVBO;
463 GLfloat innerRadius, outerRadius, startAngle, sweepAngle;
464 GLuint slices, rings;
465 [[nodiscard]] GLuint64 numVertices()
const {
return rings * (slices + 1) * 2; }
466 bool operator<(
const DiskData rhs )
const {
467 if( innerRadius < rhs.innerRadius ) {
469 }
else if( fabs(innerRadius - rhs.innerRadius) <= 0.000001 ) {
470 if( outerRadius < rhs.outerRadius ) {
472 }
else if( fabs(outerRadius - rhs.outerRadius) <= 0.000001 ) {
473 if( startAngle < rhs.startAngle ) {
475 }
else if( fabs(startAngle - rhs.startAngle) <= 0.000001 ) {
476 if( sweepAngle < rhs.sweepAngle ) {
478 }
else if( fabs(sweepAngle - rhs.sweepAngle) <= 0.000001 ) {
479 if( slices < rhs.slices ) {
481 }
else if( slices == rhs.slices ) {
482 if(rings < rhs.rings ) {
493 void generateDiskVAO( DiskData diskData );
494 inline std::map< DiskData, GLuint > _diskVAO;
495 inline std::map< DiskData, GLuint > _diskVBO;
499 GLuint stacks, slices;
500 [[nodiscard]] GLuint64 numVertices()
const {
return ((slices + 2) * 2) + (((stacks - 2) * (slices+1)) * 2); }
501 bool operator<(
const SphereData rhs )
const {
502 if( radius < rhs.radius ) {
504 }
else if( fabs(radius - rhs.radius) <= 0.000001 ) {
505 if( stacks < rhs.stacks ) {
507 }
else if( stacks == rhs.stacks ) {
508 if( slices < rhs.slices ) {
516 void generateSphereVAO( SphereData sphereData );
517 inline std::map< SphereData, GLuint > _sphereVAO;
518 inline std::map< SphereData, GLuint > _sphereVBO;
521 GLfloat innerRadius, outerRadius;
523 [[nodiscard]] GLuint64 numVertices()
const {
return sides * 4 * rings; }
524 bool operator<(
const TorusData rhs )
const {
525 if( innerRadius < rhs.innerRadius ) {
527 }
else if( fabs(innerRadius - rhs.innerRadius) <= 0.000001 ) {
528 if( outerRadius < rhs.outerRadius ) {
530 }
else if( fabs(outerRadius - rhs.outerRadius) <= 0.000001 ) {
531 if( sides < rhs.sides ) {
533 }
else if( sides == rhs.sides ) {
534 if( rings < rhs.rings ) {
543 void generateTorusVAO( TorusData torusData );
544 inline std::map< TorusData, GLuint > _torusVAO;
545 inline std::map< TorusData, GLuint > _torusVBO;
553 CSCI441_INTERNAL::_positionAttributeLocation = positionLocation;
554 CSCI441_INTERNAL::_normalAttributeLocation = normalLocation;
555 CSCI441_INTERNAL::_texCoordAttributeLocation = texCoordLocation;
556 CSCI441_INTERNAL::setTeapotAttributeLocations(positionLocation, normalLocation, texCoordLocation);
561 CSCI441_INTERNAL::deleteObjectVAOs();
566 CSCI441_INTERNAL::deleteObjectVBOs();
571 assert( base > 0.0f );
572 assert( height > 0.0f );
573 assert( stacks > 0 );
574 assert( slices > 2 );
576 CSCI441_INTERNAL::drawCylinder( base, 0.0f, height, stacks, slices, GL_FILL );
581 assert( base > 0.0f );
582 assert( height > 0.0f );
583 assert( stacks > 0 );
584 assert( slices > 2 );
586 CSCI441_INTERNAL::drawCylinder( base, 0.0f, height, stacks, slices, GL_LINE );
600 assert( sideLength > 0.0f );
602 CSCI441_INTERNAL::drawCube( sideLength, GL_FILL );
606 assert( sideLength > 0.0f );
608 CSCI441_INTERNAL::drawCubeFlat( sideLength, GL_FILL );
613 assert( sideLength > 0.0f );
615 CSCI441_INTERNAL::drawCube( sideLength, GL_LINE );
620 assert(sideLength > 0.0f);
622 CSCI441_INTERNAL::drawCube( sideLength, GL_FILL );
627 assert( (base >= 0.0f && top > 0.0f) || (base > 0.0f && top >= 0.0f) );
628 assert( height > 0.0f );
629 assert( stacks > 0 );
630 assert( slices > 2 );
632 CSCI441_INTERNAL::drawCylinder( base, top, height, stacks, slices, GL_FILL );
637 assert( (base >= 0.0f && top > 0.0f) || (base > 0.0f && top >= 0.0f) );
638 assert( height > 0.0f );
639 assert( stacks > 0 );
640 assert( slices > 2 );
642 CSCI441_INTERNAL::drawCylinder( base, top, height, stacks, slices, GL_LINE );
647 assert( inner >= 0.0f );
648 assert( outer > 0.0f );
649 assert( outer > inner );
650 assert( slices > 2 );
653 CSCI441_INTERNAL::drawPartialDisk( inner, outer, slices, rings, 0, glm::two_pi<float>(), GL_FILL );
658 assert( inner >= 0.0f );
659 assert( outer > 0.0f );
660 assert( outer > inner );
661 assert( slices > 2 );
664 CSCI441_INTERNAL::drawPartialDisk( inner, outer, slices, rings, 0, glm::two_pi<float>(), GL_LINE );
669 assert( inner >= 0.0f );
670 assert( outer > 0.0f );
671 assert( outer > inner );
672 assert( slices > 2 );
674 assert( start >= 0.0f && start <= 360.0f );
675 assert( sweep >= 0.0f && sweep <= 360.0f );
677 CSCI441_INTERNAL::drawPartialDisk( inner, outer, slices, rings, start * glm::pi<float>() / 180.0f, sweep * glm::pi<float>() / 180.0f, GL_FILL );
682 assert( inner >= 0.0f );
683 assert( outer > 0.0f );
684 assert( outer > inner );
685 assert( slices > 2 );
687 assert( start >= 0.0f && start <= 360.0f );
688 assert( sweep >= 0.0f && sweep <= 360.0f );
690 CSCI441_INTERNAL::drawPartialDisk( inner, outer, slices, rings, start * glm::pi<float>() / 180.0f, sweep * glm::pi<float>() / 180.0f, GL_LINE );
695 assert( radius > 0.0f );
696 assert( stacks > 1 );
697 assert( slices > 2 );
699 CSCI441_INTERNAL::drawSphere( radius, stacks, slices, GL_FILL );
704 assert( radius > 0.0f );
706 assert( slices > 2 );
708 CSCI441_INTERNAL::drawSphere( radius, stacks, slices, GL_LINE );
713 assert( radius > 0.0f );
714 assert( stacks > 1 );
715 assert( slices > 2 );
717 CSCI441_INTERNAL::drawHalfSphere( radius, stacks, slices, GL_FILL );
722 assert( radius > 0.0f );
724 assert( slices > 2 );
726 CSCI441_INTERNAL::drawHalfSphere( radius, stacks, slices, GL_LINE );
731 assert( radius > 0.0f );
732 assert( stacks > 1 );
733 assert( slices > 2 );
735 CSCI441_INTERNAL::drawDome( radius, stacks, slices, GL_FILL );
740 assert( radius > 0.0f );
742 assert( slices > 2 );
744 CSCI441_INTERNAL::drawDome( radius, stacks, slices, GL_LINE );
749 CSCI441_INTERNAL::drawTeapot(GL_FILL);
754 CSCI441_INTERNAL::drawTeapot(GL_LINE);
759 assert( innerRadius > 0.0f );
760 assert( outerRadius > 0.0f );
764 CSCI441_INTERNAL::drawTorus( innerRadius, outerRadius, sides, rings, GL_FILL );
769 assert( innerRadius > 0.0f );
770 assert( outerRadius > 0.0f );
774 CSCI441_INTERNAL::drawTorus( innerRadius, outerRadius, sides, rings, GL_LINE );
781inline void CSCI441_INTERNAL::deleteObjectVAOs() {
782 for(
auto & iter : _cubeVAO) {
783 glDeleteVertexArrays(1, &(iter.second));
785 for(
auto & iter : _cubeVAOIndexed) {
786 glDeleteVertexArrays(1, &(iter.second));
788 for(
auto & iter : _cylinderVAO) {
789 glDeleteVertexArrays(1, &(iter.second));
791 for(
auto & iter : _diskVAO) {
792 glDeleteVertexArrays(1, &(iter.second));
794 for(
auto & iter : _sphereVAO) {
795 glDeleteVertexArrays(1, &(iter.second));
797 for(
auto & iter : _torusVAO) {
798 glDeleteVertexArrays(1, &(iter.second));
802inline void CSCI441_INTERNAL::deleteObjectVBOs() {
803 for(
auto & iter : _cubeVBO) {
804 glDeleteBuffers(1, &(iter.second));
806 for(
auto & iter : _cubeVBOIndexed) {
807 glDeleteBuffers(1, &(iter.second));
809 for(
auto & iter : _cubeIBOIndexed) {
810 glDeleteBuffers(1, &(iter.second));
812 for(
auto & iter : _cylinderVBO) {
813 glDeleteBuffers(1, &(iter.second));
815 for(
auto & iter : _diskVBO) {
816 glDeleteBuffers(1, &(iter.second));
818 for(
auto & iter : _sphereVBO) {
819 glDeleteBuffers(1, &(iter.second));
821 for(
auto & iter : _torusVBO) {
822 glDeleteBuffers(1, &(iter.second));
826inline void CSCI441_INTERNAL::drawCube( GLfloat sideLength, GLenum renderMode ) {
827 drawCubeIndexed(sideLength, renderMode);
830inline void CSCI441_INTERNAL::drawCubeFlat( GLfloat sideLength, GLenum renderMode ) {
831 if( CSCI441_INTERNAL::_cubeVAO.count( sideLength ) == 0 ) {
832 CSCI441_INTERNAL::generateCubeVAOFlat( sideLength );
835 const GLuint64 NUM_VERTICES = 36;
837 GLint currentPolygonMode[2];
838 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
840 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
841 glBindVertexArray( CSCI441_INTERNAL::_cubeVAO.find( sideLength )->second );
842 glBindBuffer( GL_ARRAY_BUFFER, CSCI441_INTERNAL::_cubeVBO.find( sideLength )->second );
843 if(CSCI441_INTERNAL::_positionAttributeLocation != -1) {
844 glEnableVertexAttribArray( CSCI441_INTERNAL::_positionAttributeLocation );
845 glVertexAttribPointer( CSCI441_INTERNAL::_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)
nullptr );
847 if(CSCI441_INTERNAL::_normalAttributeLocation != -1) {
848 glEnableVertexAttribArray( CSCI441_INTERNAL::_normalAttributeLocation );
849 glVertexAttribPointer( CSCI441_INTERNAL::_normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES) );
851 if(CSCI441_INTERNAL::_texCoordAttributeLocation != -1) {
852 glEnableVertexAttribArray( CSCI441_INTERNAL::_texCoordAttributeLocation );
853 glVertexAttribPointer( CSCI441_INTERNAL::_texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES * 2) );
856 glDrawArrays( GL_TRIANGLES, 0, 36 );
858 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
861inline void CSCI441_INTERNAL::drawCubeIndexed( GLfloat sideLength, GLenum renderMode ) {
862 if( CSCI441_INTERNAL::_cubeVAOIndexed.count( sideLength ) == 0 ) {
863 CSCI441_INTERNAL::generateCubeVAOIndexed( sideLength );
866 const GLuint64 NUM_VERTICES = 8;
868 GLint currentPolygonMode[2];
869 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
871 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
872 glBindVertexArray( CSCI441_INTERNAL::_cubeVAOIndexed.find( sideLength )->second );
873 glBindBuffer( GL_ARRAY_BUFFER, CSCI441_INTERNAL::_cubeVBOIndexed.find( sideLength )->second );
874 if(CSCI441_INTERNAL::_positionAttributeLocation != -1) {
875 glEnableVertexAttribArray( CSCI441_INTERNAL::_positionAttributeLocation );
876 glVertexAttribPointer( CSCI441_INTERNAL::_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)
nullptr );
878 if(CSCI441_INTERNAL::_normalAttributeLocation != -1) {
879 glEnableVertexAttribArray( CSCI441_INTERNAL::_normalAttributeLocation );
880 glVertexAttribPointer( CSCI441_INTERNAL::_normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES) );
882 if(CSCI441_INTERNAL::_texCoordAttributeLocation != -1) {
883 glEnableVertexAttribArray( CSCI441_INTERNAL::_texCoordAttributeLocation );
884 glVertexAttribPointer( CSCI441_INTERNAL::_texCoordAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES * 2) );
887 glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (
void*)
nullptr);
889 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
892inline void CSCI441_INTERNAL::drawCylinder( GLfloat base, GLfloat top, GLfloat height, GLuint stacks, GLuint slices, GLenum renderMode ) {
893 CylinderData cylData = { base, top, height, stacks, slices };
894 if( CSCI441_INTERNAL::_cylinderVAO.count( cylData ) == 0 ) {
895 CSCI441_INTERNAL::generateCylinderVAO( cylData );
898 const GLuint64 NUM_VERTICES = cylData.numVertices();
900 GLint currentPolygonMode[2];
901 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
903 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
904 glBindVertexArray( CSCI441_INTERNAL::_cylinderVAO.find( cylData )->second );
905 glBindBuffer( GL_ARRAY_BUFFER, CSCI441_INTERNAL::_cylinderVBO.find( cylData )->second );
906 if(CSCI441_INTERNAL::_positionAttributeLocation != -1) {
907 glEnableVertexAttribArray( CSCI441_INTERNAL::_positionAttributeLocation );
908 glVertexAttribPointer( CSCI441_INTERNAL::_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)
nullptr );
910 if(CSCI441_INTERNAL::_normalAttributeLocation != -1) {
911 glEnableVertexAttribArray( CSCI441_INTERNAL::_normalAttributeLocation );
912 glVertexAttribPointer( CSCI441_INTERNAL::_normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES) );
914 if(CSCI441_INTERNAL::_texCoordAttributeLocation != -1) {
915 glEnableVertexAttribArray( CSCI441_INTERNAL::_texCoordAttributeLocation );
916 glVertexAttribPointer( CSCI441_INTERNAL::_texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES * 2) );
919 for(GLuint stackNum = 0; stackNum < stacks; stackNum++) {
920 glDrawArrays( GL_TRIANGLE_STRIP,
static_cast<GLint
>((slices+1)*2*stackNum),
static_cast<GLint
>((slices+1)*2) );
923 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
926inline void CSCI441_INTERNAL::drawPartialDisk(GLfloat innerRadius, GLfloat outerRadius, GLuint slices, GLuint rings, GLfloat startAngle, GLfloat sweepAngle, GLenum renderMode ) {
927 DiskData diskData = {innerRadius, outerRadius, startAngle, sweepAngle, slices, rings };
928 if( CSCI441_INTERNAL::_diskVAO.count( diskData ) == 0 ) {
929 CSCI441_INTERNAL::generateDiskVAO( diskData );
932 const GLuint64 NUM_VERTICES = diskData.numVertices();
934 GLint currentPolygonMode[2];
935 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
937 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
938 glBindVertexArray( CSCI441_INTERNAL::_diskVAO.find( diskData )->second );
939 glBindBuffer( GL_ARRAY_BUFFER, CSCI441_INTERNAL::_diskVBO.find( diskData )->second );
940 if(CSCI441_INTERNAL::_positionAttributeLocation != -1) {
941 glEnableVertexAttribArray( CSCI441_INTERNAL::_positionAttributeLocation );
942 glVertexAttribPointer( CSCI441_INTERNAL::_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)
nullptr );
944 if(CSCI441_INTERNAL::_normalAttributeLocation != -1) {
945 glEnableVertexAttribArray( CSCI441_INTERNAL::_normalAttributeLocation );
946 glVertexAttribPointer( CSCI441_INTERNAL::_normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES) );
948 if(CSCI441_INTERNAL::_texCoordAttributeLocation != -1) {
949 glEnableVertexAttribArray( CSCI441_INTERNAL::_texCoordAttributeLocation );
950 glVertexAttribPointer( CSCI441_INTERNAL::_texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES * 2) );
953 for(GLuint ringNum = 0; ringNum < rings; ringNum++) {
954 glDrawArrays( GL_TRIANGLE_STRIP,
static_cast<GLint
>((slices+1)*2*ringNum),
static_cast<GLint
>((slices+1)*2) );
957 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
960inline void CSCI441_INTERNAL::drawSphere( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode ) {
961 SphereData sphereData = { radius, stacks, slices };
962 if( CSCI441_INTERNAL::_sphereVAO.count( sphereData ) == 0 ) {
963 CSCI441_INTERNAL::generateSphereVAO( sphereData );
966 const GLuint64 NUM_VERTICES = sphereData.numVertices();
968 GLint currentPolygonMode[2];
969 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
971 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
972 glBindVertexArray( CSCI441_INTERNAL::_sphereVAO.find( sphereData )->second );
973 glBindBuffer( GL_ARRAY_BUFFER, CSCI441_INTERNAL::_sphereVBO.find( sphereData )->second );
974 if(CSCI441_INTERNAL::_positionAttributeLocation != -1) {
975 glEnableVertexAttribArray( CSCI441_INTERNAL::_positionAttributeLocation );
976 glVertexAttribPointer( CSCI441_INTERNAL::_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)
nullptr );
978 if(CSCI441_INTERNAL::_normalAttributeLocation != -1) {
979 glEnableVertexAttribArray( CSCI441_INTERNAL::_normalAttributeLocation );
980 glVertexAttribPointer( CSCI441_INTERNAL::_normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES) );
982 if(CSCI441_INTERNAL::_texCoordAttributeLocation != -1) {
983 glEnableVertexAttribArray( CSCI441_INTERNAL::_texCoordAttributeLocation );
984 glVertexAttribPointer( CSCI441_INTERNAL::_texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES * 2) );
987 glDrawArrays( GL_TRIANGLE_FAN, 0,
static_cast<GLint
>(slices+2) );
989 for(GLuint stackNum = 1; stackNum < stacks-1; stackNum++) {
990 glDrawArrays( GL_TRIANGLE_STRIP,
static_cast<GLint
>((slices+2) + (stackNum-1)*((slices+1)*2)),
static_cast<GLint
>((slices+1)*2) );
993 glDrawArrays( GL_TRIANGLE_FAN,
static_cast<GLint
>((slices+2) + (stacks-2)*(slices+1)*2),
static_cast<GLint
>(slices+2) );
995 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
998inline void CSCI441_INTERNAL::drawHalfSphere( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode ) {
999 SphereData sphereData = { radius, stacks, slices };
1000 if( CSCI441_INTERNAL::_sphereVAO.count( sphereData ) == 0 ) {
1001 CSCI441_INTERNAL::generateSphereVAO( sphereData );
1004 const GLuint64 NUM_VERTICES = sphereData.numVertices();
1006 GLint currentPolygonMode[2];
1007 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
1009 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
1010 glBindVertexArray( CSCI441_INTERNAL::_sphereVAO.find( sphereData )->second );
1011 glBindBuffer( GL_ARRAY_BUFFER, CSCI441_INTERNAL::_sphereVBO.find( sphereData )->second );
1012 if(CSCI441_INTERNAL::_positionAttributeLocation != -1) {
1013 glEnableVertexAttribArray( CSCI441_INTERNAL::_positionAttributeLocation );
1014 glVertexAttribPointer( CSCI441_INTERNAL::_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)
nullptr );
1016 if(CSCI441_INTERNAL::_normalAttributeLocation != -1) {
1017 glEnableVertexAttribArray( CSCI441_INTERNAL::_normalAttributeLocation );
1018 glVertexAttribPointer( CSCI441_INTERNAL::_normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES) );
1020 if(CSCI441_INTERNAL::_texCoordAttributeLocation != -1) {
1021 glEnableVertexAttribArray( CSCI441_INTERNAL::_texCoordAttributeLocation );
1022 glVertexAttribPointer( CSCI441_INTERNAL::_texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES * 2) );
1025 glDrawArrays( GL_TRIANGLE_FAN,
static_cast<GLint
>((slices+2)/2),
static_cast<GLint
>((slices+2)/2) );
1027 for(GLuint stackNum = 1; stackNum < stacks-1; stackNum++) {
1028 glDrawArrays( GL_TRIANGLE_STRIP,
static_cast<GLint
>((slices+2) + (stackNum-1)*((slices+1)*2)),
static_cast<GLint
>(slices+2) );
1031 glDrawArrays( GL_TRIANGLE_FAN,
static_cast<GLint
>((slices+2) + (stacks-2)*(slices+1)*2),
static_cast<GLint
>((slices+2)/2) );
1033 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
1035 drawPartialDisk(0.0f, radius, slices, stacks, 0.0f, glm::two_pi<float>(), renderMode);
1038inline void CSCI441_INTERNAL::drawDome( GLfloat radius, GLuint stacks, GLuint slices, GLenum renderMode ) {
1039 SphereData sphereData = { radius, stacks, slices };
1040 if( CSCI441_INTERNAL::_sphereVAO.count( sphereData ) == 0 ) {
1041 CSCI441_INTERNAL::generateSphereVAO( sphereData );
1044 const GLuint64 NUM_VERTICES = sphereData.numVertices();
1046 GLint currentPolygonMode[2];
1047 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
1049 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
1050 glBindVertexArray( CSCI441_INTERNAL::_sphereVAO.find( sphereData )->second );
1051 glBindBuffer( GL_ARRAY_BUFFER, CSCI441_INTERNAL::_sphereVBO.find( sphereData )->second );
1052 if(CSCI441_INTERNAL::_positionAttributeLocation != -1) {
1053 glEnableVertexAttribArray( CSCI441_INTERNAL::_positionAttributeLocation );
1054 glVertexAttribPointer( CSCI441_INTERNAL::_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)
nullptr );
1056 if(CSCI441_INTERNAL::_normalAttributeLocation != -1) {
1057 glEnableVertexAttribArray( CSCI441_INTERNAL::_normalAttributeLocation );
1058 glVertexAttribPointer( CSCI441_INTERNAL::_normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES) );
1060 if(CSCI441_INTERNAL::_texCoordAttributeLocation != -1) {
1061 glEnableVertexAttribArray( CSCI441_INTERNAL::_texCoordAttributeLocation );
1062 glVertexAttribPointer( CSCI441_INTERNAL::_texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES * 2) );
1065 glDrawArrays( GL_TRIANGLE_FAN, 0,
static_cast<GLint
>(slices+2) );
1067 for(GLuint stackNum = (stacks-1)/2; stackNum < stacks-1; stackNum++) {
1068 glDrawArrays( GL_TRIANGLE_STRIP,
static_cast<GLint
>((slices+2) + (stackNum-1)*((slices+1)*2)),
static_cast<GLint
>((slices+1)*2) );
1071 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
1074inline void CSCI441_INTERNAL::drawTorus( GLfloat innerRadius, GLfloat outerRadius, GLuint sides, GLuint rings, GLenum renderMode ) {
1075 TorusData torusData = { innerRadius, outerRadius, sides, rings };
1076 if( CSCI441_INTERNAL::_torusVAO.count( torusData ) == 0 ) {
1077 CSCI441_INTERNAL::generateTorusVAO( torusData );
1080 const GLuint64 NUM_VERTICES = torusData.numVertices();
1082 GLint currentPolygonMode[2];
1083 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
1085 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
1086 glBindVertexArray( CSCI441_INTERNAL::_torusVAO.find( torusData )->second );
1087 glBindBuffer( GL_ARRAY_BUFFER, CSCI441_INTERNAL::_torusVBO.find( torusData )->second );
1088 if(CSCI441_INTERNAL::_positionAttributeLocation != -1) {
1089 glEnableVertexAttribArray( CSCI441_INTERNAL::_positionAttributeLocation );
1090 glVertexAttribPointer( CSCI441_INTERNAL::_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)
nullptr );
1092 if(CSCI441_INTERNAL::_normalAttributeLocation != -1) {
1093 glEnableVertexAttribArray( CSCI441_INTERNAL::_normalAttributeLocation );
1094 glVertexAttribPointer( CSCI441_INTERNAL::_normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES) );
1096 if(CSCI441_INTERNAL::_texCoordAttributeLocation != -1) {
1097 glEnableVertexAttribArray( CSCI441_INTERNAL::_texCoordAttributeLocation );
1098 glVertexAttribPointer( CSCI441_INTERNAL::_texCoordAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, (
void*)(
sizeof(glm::vec3) * NUM_VERTICES * 2) );
1101 for(GLuint ringNum = 0; ringNum < rings; ringNum++) {
1102 glDrawArrays( GL_TRIANGLE_STRIP,
static_cast<GLint
>(ringNum*sides*4),
static_cast<GLint
>(sides*4) );
1105 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
1108inline void CSCI441_INTERNAL::drawTeapot( GLenum renderMode ) {
1109 GLint currentPolygonMode[2];
1110 glGetIntegerv(GL_POLYGON_MODE, currentPolygonMode);
1112 glPolygonMode( GL_FRONT_AND_BACK, renderMode );
1113 CSCI441_INTERNAL::teapot();
1114 glPolygonMode( GL_FRONT_AND_BACK, currentPolygonMode[0] );
1117inline void CSCI441_INTERNAL::generateCubeVAOFlat( GLfloat sideLength ) {
1119 glGenVertexArrays( 1, &vaod );
1120 glBindVertexArray( vaod );
1123 glGenBuffers( 1, &vbod );
1124 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1126 const GLfloat CORNER_POINT = sideLength / 2.0f;
1128 const GLuint64 NUM_VERTICES = 36;
1130 glm::vec3 vertices[NUM_VERTICES] = {
1132 {-CORNER_POINT, -CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, -CORNER_POINT},
1133 {-CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, CORNER_POINT},
1135 {CORNER_POINT, CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, CORNER_POINT, -CORNER_POINT},
1136 {CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, -CORNER_POINT},
1138 {-CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, CORNER_POINT}, {CORNER_POINT, CORNER_POINT, -CORNER_POINT},
1139 {CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, CORNER_POINT}, {CORNER_POINT, CORNER_POINT, CORNER_POINT},
1141 {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, -CORNER_POINT},
1142 {CORNER_POINT, -CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, -CORNER_POINT},
1144 {CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, -CORNER_POINT},
1145 {-CORNER_POINT, CORNER_POINT, -CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, -CORNER_POINT}, {-CORNER_POINT, -CORNER_POINT, -CORNER_POINT},
1147 {-CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {-CORNER_POINT, CORNER_POINT, CORNER_POINT},
1148 {-CORNER_POINT, CORNER_POINT, CORNER_POINT}, {CORNER_POINT, -CORNER_POINT, CORNER_POINT}, {CORNER_POINT, CORNER_POINT, CORNER_POINT}
1150 glm::vec3 normals[NUM_VERTICES] = {
1152 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
1153 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
1155 {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f},
1156 {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f},
1158 {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f},
1159 {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f},
1161 {0.0f, -1.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {0.0f, -1.0f, 0.0f},
1162 {0.0f, -1.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {0.0f, -1.0f, 0.0f},
1164 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
1165 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
1167 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
1168 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}
1170 glm::vec2 texCoords[NUM_VERTICES] = {
1172 {0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f},
1173 {0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f},
1175 {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f},
1176 {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f},
1178 {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f},
1179 {0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f},
1181 {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f},
1182 {0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f},
1184 {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f},
1185 {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f},
1187 {0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f},
1188 {0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}
1191 glBufferData(GL_ARRAY_BUFFER, (
sizeof(glm::vec3)*2 +
sizeof(glm::vec2)) * NUM_VERTICES,
nullptr, GL_STATIC_DRAW );
1192 glBufferSubData(GL_ARRAY_BUFFER, 0,
sizeof(glm::vec3) * NUM_VERTICES, vertices );
1193 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES,
sizeof(glm::vec3) * NUM_VERTICES, normals );
1194 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES * 2,
sizeof(glm::vec2) * NUM_VERTICES, texCoords );
1196 CSCI441_INTERNAL::_cubeVAO.insert( std::pair<GLfloat, GLuint>( sideLength, vaod ) );
1197 CSCI441_INTERNAL::_cubeVBO.insert( std::pair<GLfloat, GLuint>( sideLength, vbod ) );
1200inline void CSCI441_INTERNAL::generateCubeVAOIndexed( GLfloat sideLength ) {
1201 const GLfloat CORNER_POINT = sideLength / 2.0f;
1203 const GLuint64 NUM_VERTICES = 8;
1205 glm::vec3 vertices[NUM_VERTICES] = {
1206 { -CORNER_POINT, -CORNER_POINT, -CORNER_POINT },
1207 { CORNER_POINT, -CORNER_POINT, -CORNER_POINT },
1208 { CORNER_POINT, CORNER_POINT, -CORNER_POINT },
1209 { -CORNER_POINT, CORNER_POINT, -CORNER_POINT },
1210 { -CORNER_POINT, -CORNER_POINT, CORNER_POINT },
1211 { CORNER_POINT, -CORNER_POINT, CORNER_POINT },
1212 { CORNER_POINT, CORNER_POINT, CORNER_POINT },
1213 { -CORNER_POINT, CORNER_POINT, CORNER_POINT }
1215 glm::vec3 normals[NUM_VERTICES] = {
1216 {-1.0f, -1.0f, -1.0f},
1217 { 1.0f, -1.0f, -1.0f},
1218 { 1.0f, 1.0f, -1.0f},
1219 {-1.0f, 1.0f, -1.0f},
1220 {-1.0f, -1.0f, 1.0f},
1221 { 1.0f, -1.0f, 1.0f},
1222 { 1.0f, 1.0f, 1.0f},
1225 glm::vec3 texCoords[NUM_VERTICES] = {
1226 {-1.0f, -1.0f, -1.0f},
1227 { 1.0f, -1.0f, -1.0f},
1228 { 1.0f, 1.0f, -1.0f},
1229 {-1.0f, 1.0f, -1.0f},
1230 {-1.0f, -1.0f, 1.0f},
1231 { 1.0f, -1.0f, 1.0f},
1232 { 1.0f, 1.0f, 1.0f},
1235 GLushort indices[36] = {
1245 glGenVertexArrays( 1, &vaod );
1246 glBindVertexArray( vaod );
1249 glGenBuffers( 2, vbods );
1251 glBindBuffer( GL_ARRAY_BUFFER, vbods[0] );
1252 glBufferData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES * 3,
nullptr, GL_STATIC_DRAW );
1253 glBufferSubData(GL_ARRAY_BUFFER, 0,
sizeof(glm::vec3) * NUM_VERTICES, vertices );
1254 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES,
sizeof(glm::vec3) * NUM_VERTICES, normals );
1255 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES * 2,
sizeof(glm::vec3) * NUM_VERTICES, texCoords );
1257 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbods[1] );
1258 glBufferData( GL_ELEMENT_ARRAY_BUFFER,
sizeof(indices), indices, GL_STATIC_DRAW) ;
1260 CSCI441_INTERNAL::_cubeVAOIndexed.insert( std::pair<GLfloat, GLuint>( sideLength, vaod ) );
1261 CSCI441_INTERNAL::_cubeVBOIndexed.insert( std::pair<GLfloat, GLuint>( sideLength, vbods[0] ) );
1262 CSCI441_INTERNAL::_cubeIBOIndexed.insert( std::pair<GLfloat, GLuint>( sideLength, vbods[1] ) );
1265inline void CSCI441_INTERNAL::generateCylinderVAO( CylinderData cylData ) {
1267 glGenVertexArrays( 1, &vaod );
1268 glBindVertexArray( vaod );
1271 glGenBuffers( 1, &vbod );
1272 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1274 const GLuint64 NUM_VERTICES = cylData.numVertices();
1276 GLfloat sliceStep = glm::two_pi<float>() / (GLfloat)cylData.slices;
1277 GLfloat stackStep = cylData.height / (GLfloat)cylData.stacks;
1279 auto vertices =
new glm::vec3[NUM_VERTICES];
1280 auto normals =
new glm::vec3[NUM_VERTICES];
1281 auto texCoords =
new glm::vec2[NUM_VERTICES];
1285 for(GLuint stackNum = 0; stackNum < cylData.stacks; stackNum++ ) {
1286 GLfloat botRadius = cylData.radiusBase * (GLfloat)(cylData.stacks - stackNum) / (GLfloat)cylData.stacks + cylData.top * (GLfloat)stackNum / (GLfloat)cylData.stacks;
1287 GLfloat topRadius = cylData.radiusBase * (GLfloat)(cylData.stacks - stackNum - 1) / (GLfloat)cylData.stacks + cylData.top * (GLfloat)(stackNum + 1) / (GLfloat)cylData.stacks;
1289 for(GLuint sliceNum = 0; sliceNum <= cylData.slices; sliceNum++ ) {
1290 vertices[ idx ].x = glm::cos( sliceNum * sliceStep )*botRadius;
1291 vertices[ idx ].y = (GLfloat)stackNum * stackStep;
1292 vertices[ idx ].z = glm::sin( sliceNum * sliceStep )*botRadius;
1294 normals[ idx ].x = glm::cos( sliceNum * sliceStep );
1295 normals[ idx ].y = 0.0f;
1296 normals[ idx ].z = glm::sin( sliceNum * sliceStep );
1298 texCoords[ idx ].s = (GLfloat)sliceNum / (GLfloat)cylData.slices;
1299 texCoords[ idx ].t = (GLfloat)stackNum / (GLfloat)cylData.stacks;
1303 vertices[ idx ].x = glm::cos( sliceNum * sliceStep )*topRadius;
1304 vertices[ idx ].y = (GLfloat)(stackNum+1) * stackStep;
1305 vertices[ idx ].z = glm::sin( sliceNum * sliceStep )*topRadius;
1307 normals[ idx ].x = glm::cos( sliceNum * sliceStep );
1308 normals[ idx ].y = 0.0f;
1309 normals[ idx ].z = glm::sin( sliceNum * sliceStep );
1311 texCoords[ idx ].s = (GLfloat)sliceNum / (GLfloat)cylData.slices;
1312 texCoords[ idx ].t = (GLfloat)(stackNum+1) / (GLfloat)cylData.stacks;
1318 glBufferData(GL_ARRAY_BUFFER, (
sizeof(glm::vec3)*2 +
sizeof(glm::vec2)) * NUM_VERTICES,
nullptr, GL_STATIC_DRAW );
1319 glBufferSubData(GL_ARRAY_BUFFER, 0,
static_cast<GLsizeiptr
>(
sizeof(glm::vec3) * NUM_VERTICES), vertices );
1320 glBufferSubData(GL_ARRAY_BUFFER,
static_cast<GLintptr
>(
sizeof(glm::vec3) * NUM_VERTICES),
static_cast<GLsizeiptr
>(
sizeof(glm::vec3) * NUM_VERTICES), normals );
1321 glBufferSubData(GL_ARRAY_BUFFER,
static_cast<GLintptr
>(
sizeof(glm::vec3) * NUM_VERTICES * 2),
static_cast<GLsizeiptr
>(
sizeof(glm::vec2) * NUM_VERTICES), texCoords );
1323 CSCI441_INTERNAL::_cylinderVAO.insert( std::pair<CylinderData, GLuint>( cylData, vaod ) );
1324 CSCI441_INTERNAL::_cylinderVBO.insert( std::pair<CylinderData, GLuint>( cylData, vbod ) );
1331inline void CSCI441_INTERNAL::generateDiskVAO( DiskData diskData ) {
1333 glGenVertexArrays( 1, &vaod );
1334 glBindVertexArray( vaod );
1337 glGenBuffers( 1, &vbod );
1338 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1340 const GLuint64 NUM_VERTICES = diskData.numVertices();
1342 GLfloat sliceStep = diskData.sweepAngle / (GLfloat)diskData.slices;
1343 GLfloat ringStep = (diskData.outerRadius - diskData.innerRadius) / (GLfloat)diskData.rings;
1345 auto vertices =
new glm::vec3[NUM_VERTICES];
1346 auto normals =
new glm::vec3[NUM_VERTICES];
1347 auto texCoords =
new glm::vec2[NUM_VERTICES];
1351 for(GLuint ringNum = 0; ringNum < diskData.rings; ringNum++ ) {
1352 GLfloat currRadius = diskData.innerRadius + (GLfloat)ringNum * ringStep;
1353 GLfloat nextRadius = diskData.innerRadius + (GLfloat)(ringNum + 1) * ringStep;
1355 GLfloat theta = diskData.startAngle;
1356 for(GLuint i = 0; i <= diskData.slices; i++ ) {
1357 vertices[ idx ].x = glm::cos(theta)*currRadius;
1358 vertices[ idx ].y = glm::sin(theta)*currRadius;
1359 vertices[ idx ].z = 0.0f;
1361 normals[ idx ].x = 0.0f;
1362 normals[ idx ].y = 0.0f;
1363 normals[ idx ].z = 1.0f;
1365 texCoords[ idx ].s = glm::cos(theta)*(currRadius/diskData.outerRadius);
1366 texCoords[ idx ].t = glm::sin(theta)*(currRadius/diskData.outerRadius);
1370 vertices[ idx ].x = glm::cos(theta)*nextRadius;
1371 vertices[ idx ].y = glm::sin(theta)*nextRadius;
1372 vertices[ idx ].z = 0.0f;
1374 normals[ idx ].x = 0.0f;
1375 normals[ idx ].y = 0.0f;
1376 normals[ idx ].z = 1.0f;
1378 texCoords[ idx ].s = glm::cos(theta)*(nextRadius/diskData.outerRadius);
1379 texCoords[ idx ].t = glm::sin(theta)*(nextRadius/diskData.outerRadius);
1386 glBufferData(GL_ARRAY_BUFFER, (
sizeof(glm::vec3)*2 +
sizeof(glm::vec2)) * NUM_VERTICES,
nullptr, GL_STATIC_DRAW );
1387 glBufferSubData(GL_ARRAY_BUFFER, 0,
sizeof(glm::vec3) * NUM_VERTICES, vertices );
1388 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES,
sizeof(glm::vec3) * NUM_VERTICES, normals );
1389 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES * 2,
sizeof(glm::vec2) * NUM_VERTICES, texCoords );
1391 CSCI441_INTERNAL::_diskVAO.insert( std::pair<DiskData, GLuint>( diskData, vaod ) );
1392 CSCI441_INTERNAL::_diskVBO.insert( std::pair<DiskData, GLuint>( diskData, vbod ) );
1399inline void CSCI441_INTERNAL::generateSphereVAO( SphereData sphereData ) {
1401 glGenVertexArrays( 1, &vaod );
1402 glBindVertexArray( vaod );
1405 glGenBuffers( 1, &vbod );
1406 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1408 const GLuint64 NUM_VERTICES = sphereData.numVertices();
1410 GLfloat sliceStep = glm::two_pi<float>() / (GLfloat)sphereData.slices;
1411 GLfloat stackStep = glm::pi<float>() / (GLfloat)sphereData.stacks;
1413 auto vertices =
new glm::vec3[NUM_VERTICES];
1414 auto normals =
new glm::vec3[NUM_VERTICES];
1415 auto texCoords =
new glm::vec2[NUM_VERTICES];
1420 GLfloat phi = stackStep * (GLfloat)sphereData.stacks;
1421 GLfloat phiNext = stackStep * (GLfloat)(sphereData.stacks - 1);
1423 vertices[ idx ].x = 0.0f;
1424 vertices[ idx ].y = -glm::cos( phi )*sphereData.radius;
1425 vertices[ idx ].z = 0.0f;
1427 normals[ idx ].x = 0.0f;
1428 normals[ idx ].y = 1.0f;
1429 normals[ idx ].z = 0.0f;
1431 texCoords[ idx ].s = 0.5f;
1432 texCoords[ idx ].t = 1.0f;
1436 for(GLuint sliceNum = 0; sliceNum <= sphereData.slices; sliceNum++ ) {
1437 GLfloat theta = sliceStep * (GLfloat)sliceNum;
1439 vertices[ idx ].x = -glm::cos( theta )*glm::sin( phiNext )*sphereData.radius;
1440 vertices[ idx ].y = -glm::cos( phiNext )*sphereData.radius;
1441 vertices[ idx ].z = glm::sin( theta )*glm::sin( phiNext )*sphereData.radius;
1443 normals[ idx ].x = -glm::cos( theta )*glm::sin( phiNext );
1444 normals[ idx ].y = -glm::cos( phiNext );
1445 normals[ idx ].z = glm::sin( theta )*glm::sin( phiNext );
1447 texCoords[ idx ].s = (GLfloat)sliceNum / (GLfloat)sphereData.slices;
1448 texCoords[ idx ].t = 1.0f;
1454 for(GLuint stackNum = 1; stackNum < sphereData.stacks - 1; stackNum++ ) {
1455 phi = stackStep * (GLfloat)stackNum;
1456 phiNext = stackStep * (GLfloat)(stackNum + 1);
1458 for(GLuint sliceNum = sphereData.slices; sliceNum > 0; sliceNum-- ) {
1459 GLfloat theta = sliceStep * (GLfloat)sliceNum;
1461 vertices[ idx ].x = -glm::cos( theta )*glm::sin( phi )*sphereData.radius;
1462 vertices[ idx ].y = -glm::cos( phi )*sphereData.radius;
1463 vertices[ idx ].z = glm::sin( theta )*glm::sin( phi )*sphereData.radius;
1465 normals[ idx ].x = -glm::cos( theta )*glm::sin( phi );
1466 normals[ idx ].y = -glm::cos( phi );
1467 normals[ idx ].z = glm::sin( theta )*glm::sin( phi );
1469 texCoords[ idx ].s = (GLfloat)sliceNum / (GLfloat)sphereData.slices;
1470 texCoords[ idx ].t = (GLfloat)(stackNum-1) / (GLfloat)(sphereData.stacks - 2);
1474 vertices[ idx ].x = -glm::cos( theta )*glm::sin( phiNext )*sphereData.radius;
1475 vertices[ idx ].y = -glm::cos( phiNext )*sphereData.radius;
1476 vertices[ idx ].z = glm::sin( theta )*glm::sin( phiNext )*sphereData.radius;
1478 normals[ idx ].x = -glm::cos( theta )*glm::sin( phiNext );
1479 normals[ idx ].y = -glm::cos( phiNext );
1480 normals[ idx ].z = glm::sin( theta )*glm::sin( phiNext );
1482 texCoords[ idx ].s = (GLfloat)sliceNum / (GLfloat)sphereData.slices;
1483 texCoords[ idx ].t = (GLfloat)(stackNum) / (GLfloat)(sphereData.stacks - 2);
1488 vertices[ idx ].x = -glm::sin( phi )*sphereData.radius;
1489 vertices[ idx ].y = -glm::cos( phi )*sphereData.radius;
1490 vertices[ idx ].z = 0.0f;
1492 normals[ idx ].x = -glm::sin( phi );
1493 normals[ idx ].y = -glm::cos( phi );
1494 normals[ idx ].z = 0.0f;
1496 texCoords[ idx ].s = 0.0f;
1497 texCoords[ idx ].t = (GLfloat)(stackNum-1) / (GLfloat)(sphereData.stacks - 2);
1501 vertices[ idx ].x = -glm::sin( phiNext )*sphereData.radius;
1502 vertices[ idx ].y = -glm::cos( phiNext )*sphereData.radius;
1503 vertices[ idx ].z = 0.0f;
1505 normals[ idx ].x = -glm::sin( phiNext );
1506 normals[ idx ].y = -glm::cos( phiNext );
1507 normals[ idx ].z = 0.0f;
1509 texCoords[ idx ].s = 0.0f;
1510 texCoords[ idx ].t = (GLfloat)(stackNum) / (GLfloat)(sphereData.stacks - 2);
1517 phiNext = stackStep;
1519 vertices[ idx ].x = 0.0f;
1520 vertices[ idx ].y = -glm::cos( phi )*sphereData.radius;
1521 vertices[ idx ].z = 0.0f;
1523 normals[ idx ].x = 0.0f;
1524 normals[ idx ].y = -1.0f;
1525 normals[ idx ].z = 0.0f;
1527 texCoords[ idx ].s = 0.5f;
1528 texCoords[ idx ].t = 0.0f;
1532 for(GLuint sliceNum = sphereData.slices; sliceNum > 0; sliceNum--) {
1533 GLfloat theta = sliceStep * (GLfloat)sliceNum;
1535 vertices[ idx ].x = -glm::cos( theta )*glm::sin( phiNext )*sphereData.radius;
1536 vertices[ idx ].y = -glm::cos( phiNext )*sphereData.radius;
1537 vertices[ idx ].z = glm::sin( theta )*glm::sin( phiNext )*sphereData.radius;
1539 normals[ idx ].x = -glm::cos( theta )*glm::sin( phiNext );
1540 normals[ idx ].y = -glm::cos( phiNext );
1541 normals[ idx ].z = glm::sin( theta )*glm::sin( phiNext );
1543 texCoords[ idx ].s = (GLfloat)sliceNum / (GLfloat)sphereData.slices;
1544 texCoords[ idx ].t = 0.0f;
1549 vertices[ idx ].x = -glm::sin( phiNext )*sphereData.radius;
1550 vertices[ idx ].y = -glm::cos( phiNext )*sphereData.radius;
1551 vertices[ idx ].z = 0.0f;
1553 normals[ idx ].x = -glm::sin( phiNext );
1554 normals[ idx ].y = -glm::cos( phiNext );
1555 normals[ idx ].z = 0.0f;
1557 texCoords[ idx ].s = 0.0f;
1558 texCoords[ idx ].t = 0.0f;
1560 glBufferData(GL_ARRAY_BUFFER, (
sizeof(glm::vec3)*2 +
sizeof(glm::vec2)) * NUM_VERTICES,
nullptr, GL_STATIC_DRAW );
1561 glBufferSubData(GL_ARRAY_BUFFER, 0,
sizeof(glm::vec3) * NUM_VERTICES, vertices );
1562 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES,
sizeof(glm::vec3) * NUM_VERTICES, normals );
1563 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES * 2,
sizeof(glm::vec2) * NUM_VERTICES, texCoords );
1565 CSCI441_INTERNAL::_sphereVAO.insert( std::pair<SphereData, GLuint>( sphereData, vaod ) );
1566 CSCI441_INTERNAL::_sphereVBO.insert( std::pair<SphereData, GLuint>( sphereData, vbod ) );
1573inline void CSCI441_INTERNAL::generateTorusVAO( TorusData torusData ) {
1575 glGenVertexArrays( 1, &vaod );
1576 glBindVertexArray( vaod );
1579 glGenBuffers( 1, &vbod );
1580 glBindBuffer( GL_ARRAY_BUFFER, vbod );
1582 const GLuint64 NUM_VERTICES = torusData.numVertices();
1584 auto vertices =
new glm::vec3[NUM_VERTICES];
1585 auto normals =
new glm::vec3[NUM_VERTICES];
1586 auto texCoords =
new glm::vec2[NUM_VERTICES];
1590 GLfloat sideStep = glm::two_pi<float>() / (GLfloat)torusData.sides;
1591 GLfloat ringStep = glm::two_pi<float>() / (GLfloat)torusData.rings;
1593 for(GLuint ringNum = 0; ringNum < torusData.rings; ringNum++ ) {
1594 GLfloat currTheta = ringStep * (GLfloat)ringNum;
1595 GLfloat nextTheta = ringStep * (GLfloat)(ringNum+1);
1597 for(GLuint sideNum = 0; sideNum < torusData.sides; sideNum++ ) {
1598 GLfloat currPhi = sideStep * (GLfloat)sideNum;
1599 GLfloat nextPhi = sideStep * (GLfloat)(sideNum+1);
1601 vertices[ idx ].x = (torusData.outerRadius + torusData.innerRadius * glm::cos(currPhi ) ) * glm::cos(currTheta );
1602 vertices[ idx ].y = (torusData.outerRadius + torusData.innerRadius * glm::cos(currPhi ) ) * glm::sin(currTheta );
1603 vertices[ idx ].z = torusData.innerRadius * glm::sin(currPhi );
1605 normals[ idx ].x = glm::cos( currPhi ) * glm::cos( currTheta );
1606 normals[ idx ].y = glm::cos( currPhi ) * glm::sin( currTheta );
1607 normals[ idx ].z = glm::sin( currPhi );
1609 texCoords[ idx ].s = (GLfloat)sideNum / (GLfloat)torusData.sides;
1610 texCoords[ idx ].t = (GLfloat)ringNum / (GLfloat)torusData.rings;
1614 vertices[ idx ].x = (torusData.outerRadius + torusData.innerRadius * glm::cos(currPhi ) ) * glm::cos(nextTheta );
1615 vertices[ idx ].y = (torusData.outerRadius + torusData.innerRadius * glm::cos(currPhi ) ) * glm::sin(nextTheta );
1616 vertices[ idx ].z = torusData.innerRadius * glm::sin(currPhi );
1618 normals[ idx ].x = glm::cos( currPhi ) * glm::cos( nextTheta );
1619 normals[ idx ].y = glm::cos( currPhi ) * glm::sin( nextTheta );
1620 normals[ idx ].z = glm::sin( currPhi );
1622 texCoords[ idx ].s = (GLfloat)sideNum / (GLfloat)torusData.sides;
1623 texCoords[ idx ].t = (GLfloat)(ringNum+1) / (GLfloat)torusData.rings;
1627 vertices[ idx ].x = (torusData.outerRadius + torusData.innerRadius * glm::cos(nextPhi ) ) * glm::cos(currTheta );
1628 vertices[ idx ].y = (torusData.outerRadius + torusData.innerRadius * glm::cos(nextPhi ) ) * glm::sin(currTheta );
1629 vertices[ idx ].z = torusData.innerRadius * glm::sin(nextPhi );
1631 normals[ idx ].x = glm::cos( nextPhi ) * glm::cos( currTheta );
1632 normals[ idx ].y = glm::cos( nextPhi ) * glm::sin( currTheta );
1633 normals[ idx ].z = glm::sin( nextPhi );
1635 texCoords[ idx ].s = (GLfloat)(sideNum+1) / (GLfloat)torusData.sides;
1636 texCoords[ idx ].t = (GLfloat)ringNum / (GLfloat)torusData.rings;
1640 vertices[ idx ].x = (torusData.outerRadius + torusData.innerRadius * glm::cos(nextPhi ) ) * glm::cos(nextTheta );
1641 vertices[ idx ].y = (torusData.outerRadius + torusData.innerRadius * glm::cos(nextPhi ) ) * glm::sin(nextTheta );
1642 vertices[ idx ].z = torusData.innerRadius * glm::sin(nextPhi );
1644 normals[ idx ].x = glm::cos( nextPhi ) * glm::cos( nextTheta );
1645 normals[ idx ].y = glm::cos( nextPhi ) * glm::sin( nextTheta );
1646 normals[ idx ].z = glm::sin( nextPhi );
1648 texCoords[ idx ].s = (GLfloat)(sideNum+1) / (GLfloat)torusData.sides;
1649 texCoords[ idx ].t = (GLfloat)(ringNum+1) / (GLfloat)torusData.rings;
1655 glBufferData(GL_ARRAY_BUFFER, (
sizeof(glm::vec3)*2 +
sizeof(glm::vec2)) * NUM_VERTICES,
nullptr, GL_STATIC_DRAW );
1656 glBufferSubData(GL_ARRAY_BUFFER, 0,
sizeof(glm::vec3) * NUM_VERTICES, vertices );
1657 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES,
sizeof(glm::vec3) * NUM_VERTICES, normals );
1658 glBufferSubData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * NUM_VERTICES * 2,
sizeof(glm::vec2) * NUM_VERTICES, texCoords );
1660 CSCI441_INTERNAL::_torusVAO.insert( std::pair<TorusData, GLuint>( torusData, vaod ) );
1661 CSCI441_INTERNAL::_torusVBO.insert( std::pair<TorusData, GLuint>( torusData, vbod ) );
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17
void drawSolidTeapot(GLfloat unused=1.0f)
Draws a solid teapot.
Definition: objects.hpp:748
void drawWireTeapot(GLfloat unused=1.0f)
Draws a wireframe teapot.
Definition: objects.hpp:753
void drawSolidCube(GLfloat sideLength)
Calls through to drawSolidCubeIndexed()
Definition: objects.hpp:590
void drawSolidCylinder(GLfloat base, GLfloat top, GLfloat height, GLint stacks, GLint slices)
Draws a solid open ended cylinder.
Definition: objects.hpp:626
void drawWireCube(GLfloat sideLength)
Draws a wireframe cube.
Definition: objects.hpp:612
void drawSolidPartialDisk(GLfloat inner, GLfloat outer, GLint slices, GLint rings, GLfloat start, GLfloat sweep)
Draws part of a solid disk.
Definition: objects.hpp:668
void drawSolidDome(GLfloat radius, GLint stacks, GLint slices)
Draws a solid dome.
Definition: objects.hpp:730
void deleteObjectVBOs()
deletes the VBOs stored for all object types
Definition: objects.hpp:565
void deleteObjectVAOs()
deletes the VAOs stored for all object types
Definition: objects.hpp:560
void setVertexAttributeLocations(GLint positionLocation, GLint normalLocation=-1, GLint texCoordLocation=-1)
Sets the attribute locations for vertex positions, normals, and texture coordinates.
Definition: objects.hpp:552
void drawWireTorus(GLfloat innerRadius, GLfloat outerRadius, GLint sides, GLint rings)
Draws a wireframe torus.
Definition: objects.hpp:768
void drawWireDome(GLfloat radius, GLint stacks, GLint slices)
Draws a wireframe dome.
Definition: objects.hpp:739
void drawSolidCone(GLfloat base, GLfloat height, GLint stacks, GLint slices)
Draws a solid cone.
Definition: objects.hpp:570
void drawWireHalfSphere(GLfloat radius, GLint stacks, GLint slices)
Draws a wireframe half sphere with a bottom.
Definition: objects.hpp:721
void drawSolidCubeTextured(GLfloat sideLength)
Draws a solid textured cube. Calls through to drawSolidCubeFlat()
Definition: objects.hpp:595
void drawSolidTorus(GLfloat innerRadius, GLfloat outerRadius, GLint sides, GLint rings)
Draws a solid torus.
Definition: objects.hpp:758
void drawSolidHalfSphere(GLfloat radius, GLint stacks, GLint slices)
Draws a solid half sphere with a bottom.
Definition: objects.hpp:712
void drawSolidCubeFlat(GLfloat sideLength)
Draws a solid cube with normals aligned with cube face.
Definition: objects.hpp:605
void drawWireSphere(GLfloat radius, GLint stacks, GLint slices)
Draws a wireframe sphere.
Definition: objects.hpp:703
void drawSolidSphere(GLfloat radius, GLint stacks, GLint slices)
Draws a solid sphere.
Definition: objects.hpp:694
void drawWireCone(GLfloat base, GLfloat height, GLint stacks, GLint slices)
Draws a wireframe cone.
Definition: objects.hpp:580
void drawSolidDisk(GLfloat inner, GLfloat outer, GLint slices, GLint rings)
Draws a solid disk.
Definition: objects.hpp:646
void drawSolidCubeIndexed(GLfloat sideLength)
Draws a solid cube.
Definition: objects.hpp:599
void drawCubeMap(GLfloat sideLength)
Draws a cube with 3D Texture Coordinates to map a cube map texture to it.
Definition: objects.hpp:619
void drawWireDisk(GLfloat inner, GLfloat outer, GLint slices, GLint rings)
Draws a wireframe disk.
Definition: objects.hpp:657
void drawWirePartialDisk(GLfloat inner, GLfloat outer, GLint slices, GLint rings, GLfloat start, GLfloat sweep)
Draws part of a wireframe disk.
Definition: objects.hpp:681
void drawWireCylinder(GLfloat base, GLfloat top, GLfloat height, GLint stacks, GLint slices)
Draws a wireframe open ended cylinder.
Definition: objects.hpp:636
Helper functions to draw teapot with OpenGL 3.0+.