From 9e895bbcfd13d828e3b17aad3367e531cddf796d Mon Sep 17 00:00:00 2001 From: Hugo Willaume Date: Wed, 28 Nov 2018 10:23:34 +0900 Subject: [PATCH] Scene with 3 illuminated models : cube sphere teapot --- BaseGLProject/ADrawable.h | 2 +- BaseGLProject/BaseGLProject.vcxproj | 8 +- BaseGLProject/BaseGLProject.vcxproj.filters | 18 ++ BaseGLProject/CheckeredFloor.cpp | 4 +- BaseGLProject/CheckeredFloor.h | 2 +- BaseGLProject/ColorCube.cpp | 81 +++-- BaseGLProject/ColorCube.h | 4 +- BaseGLProject/IDrawable.h | 8 +- BaseGLProject/LineSegment.cpp | 4 +- BaseGLProject/LineSegment.h | 2 +- BaseGLProject/MyGLWindow.cpp | 107 +++---- BaseGLProject/MyGLWindow.h | 9 +- BaseGLProject/Source.cpp | 21 +- BaseGLProject/Sphere.cpp | 191 ++++++++++++ BaseGLProject/Sphere.h | 45 +++ BaseGLProject/WireCube.cpp | 4 +- BaseGLProject/WireCube.h | 2 +- BaseGLProject/imgui.ini | 2 +- BaseGLProject/light.vert | 42 +++ BaseGLProject/simple.vert | 2 +- BaseGLProject/teapotdata.h | 206 +++++++++++++ BaseGLProject/vboteapot.cpp | 326 ++++++++++++++++++++ BaseGLProject/vboteapot.h | 52 ++++ 23 files changed, 1012 insertions(+), 130 deletions(-) create mode 100644 BaseGLProject/Sphere.cpp create mode 100644 BaseGLProject/Sphere.h create mode 100644 BaseGLProject/light.vert create mode 100644 BaseGLProject/teapotdata.h create mode 100644 BaseGLProject/vboteapot.cpp create mode 100644 BaseGLProject/vboteapot.h diff --git a/BaseGLProject/ADrawable.h b/BaseGLProject/ADrawable.h index a2038d6..5680d7e 100644 --- a/BaseGLProject/ADrawable.h +++ b/BaseGLProject/ADrawable.h @@ -36,7 +36,7 @@ protected: public: - virtual void draw(ShaderProgram *shader, glm::mat4x4 pv) = 0; + virtual void draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) = 0; virtual DrawableType getType() = 0; void addRotation(glm::vec4 vec) override diff --git a/BaseGLProject/BaseGLProject.vcxproj b/BaseGLProject/BaseGLProject.vcxproj index a5dbd77..4e88a62 100644 --- a/BaseGLProject/BaseGLProject.vcxproj +++ b/BaseGLProject/BaseGLProject.vcxproj @@ -157,6 +157,8 @@ + + @@ -177,11 +179,14 @@ + + + - + Geometry 4.0 Geometry @@ -192,6 +197,7 @@ 4.0 Document + diff --git a/BaseGLProject/BaseGLProject.vcxproj.filters b/BaseGLProject/BaseGLProject.vcxproj.filters index cefa8ea..c1fdb2a 100644 --- a/BaseGLProject/BaseGLProject.vcxproj.filters +++ b/BaseGLProject/BaseGLProject.vcxproj.filters @@ -60,6 +60,12 @@ Source Files + + Source Files + + + Source Files + @@ -116,11 +122,23 @@ Header Files + + Header Files + + + Header Files + + + Header Files + Shaders + + Shaders + Shaders diff --git a/BaseGLProject/CheckeredFloor.cpp b/BaseGLProject/CheckeredFloor.cpp index 2a06fdf..98d2bd9 100644 --- a/BaseGLProject/CheckeredFloor.cpp +++ b/BaseGLProject/CheckeredFloor.cpp @@ -80,12 +80,12 @@ CheckeredFloor::~CheckeredFloor() { } -void CheckeredFloor::draw(ShaderProgram * shader, glm::mat4x4 pv) +void CheckeredFloor::draw(ShaderProgram * shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) { _model.glPushMatrix(); effectTransformations(); glBindVertexArray(_vaoHandle); - glm::mat4 mvpMatrix = pv * _model.getMatrix(); + glm::mat4 mvpMatrix = proj_matrix * view_matrix * _model.getMatrix(); glUniformMatrix4fv(shader->uniform("mvp"), 1, GL_FALSE, glm::value_ptr(mvpMatrix)); glDrawArrays(GL_TRIANGLES, 0, _squares * _squares * 6); _model.glPopMatrix(); diff --git a/BaseGLProject/CheckeredFloor.h b/BaseGLProject/CheckeredFloor.h index 4371474..7bd843b 100644 --- a/BaseGLProject/CheckeredFloor.h +++ b/BaseGLProject/CheckeredFloor.h @@ -25,7 +25,7 @@ private : public : CheckeredFloor(int size, int squares); ~CheckeredFloor(); - void draw(ShaderProgram *shader, glm::mat4x4 pv) override; + void draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) override; DrawableType getType() override; }; \ No newline at end of file diff --git a/BaseGLProject/ColorCube.cpp b/BaseGLProject/ColorCube.cpp index bdf6063..1e0d997 100644 --- a/BaseGLProject/ColorCube.cpp +++ b/BaseGLProject/ColorCube.cpp @@ -1,5 +1,13 @@ #include "ColorCube.h" +glm::vec3 computeNormal(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3) +{ + glm::vec3 v1 = p2 - p1; + glm::vec3 v2 = p3 - p1; + + return glm::normalize(glm::cross(v1, v2)); +} + void ColorCube::iboSetup() { std::vector cube_vertices = @@ -49,7 +57,6 @@ void ColorCube::iboSetup() (void*)0); glEnableVertexAttribArray(0); //attr number = 0 - glGenBuffers(1, &_vbo_colors); glBindBuffer(GL_ARRAY_BUFFER, _vbo_colors); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 24, cube_colors, GL_STATIC_DRAW); @@ -86,14 +93,7 @@ void ColorCube::vaoSetup() { -1.0, 1.0, 1.0}, { 1.0, 1.0, 1.0}, { 1.0, 1.0, -1.0}, { 1.0, 1.0, -1.0}, { -1.0, 1.0, -1.0}, { -1.0, 1.0, 1.0} }; - GLushort cube_elements[] = { - 0, 1, 2, 2, 3, 0, 1, 5, 6, - 6, 2, 1, 7, 6, 5, 5, 4, 7, - 4, 0, 3, 3, 7, 4, 4, 5, 1, - 1, 0, 4, 3, 2, 6, 6, 7, 3, - }; - - GLfloat cube_colors[] = { + std::vector cube_colors = { 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, @@ -107,18 +107,17 @@ void ColorCube::vaoSetup() 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; - - GLfloat cube_colorss[] = { - 1.0, 0.0, 0.0, // 0 - 0.0, 1.0, 0.0, // 1 - 0.0, 0.0, 1.0, // 2 - 1.0, 1.0, 1.0, // 3 - 1.0, 0.0, 0.0, // 4 - 0.0, 1.0, 0.0, // 5 - 0.0, 0.0, 1.0, // 6 - 1.0, 1.0, 1.0, // 7 - }; + std::vector cube_normals; + + for (int i = 0; i < cube_vertices.size() - 2; i += 3) + { + glm::vec3 norm = computeNormal( + cube_vertices[i], cube_vertices[i + 1], cube_vertices[i + 2]); + cube_normals.push_back(norm); cube_normals.push_back(norm); cube_normals.push_back(norm); + } + + glGenVertexArrays(1, &_vaoHandle); glBindVertexArray(_vaoHandle); @@ -135,10 +134,9 @@ void ColorCube::vaoSetup() (void*)0); glEnableVertexAttribArray(0); //attr number = 0 - - glGenBuffers(1, &_vbo_colors); - glBindBuffer(GL_ARRAY_BUFFER, _vbo_colors); - glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * cube_vertices.size() * 3, cube_colors, GL_STATIC_DRAW); + glGenBuffers(1, &_vbo_normals); + glBindBuffer(GL_ARRAY_BUFFER, _vbo_normals); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * cube_normals.size() * 3, cube_normals.data(), GL_STATIC_DRAW); glVertexAttribPointer( 1, @@ -149,6 +147,19 @@ void ColorCube::vaoSetup() (void*)0); glEnableVertexAttribArray(1); + glGenBuffers(1, &_vbo_colors); + glBindBuffer(GL_ARRAY_BUFFER, _vbo_colors); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * cube_colors.size(), cube_colors.data(), GL_STATIC_DRAW); + + glVertexAttribPointer( + 2, + 3, + GL_FLOAT, + GL_FALSE, + 0, + (void*)0); + glEnableVertexAttribArray(2); + glBindVertexArray(0); } @@ -162,21 +173,31 @@ ColorCube::ColorCube(bool usingIBO) } -void ColorCube::draw(ShaderProgram *shader, glm::mat4x4 pv) +void ColorCube::draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) { _model.glPushMatrix(); effectTransformations(); - glBindVertexArray(_vaoHandle); - int size; - glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); - glm::mat4 mvpMatrix = pv * _model.getMatrix(); + glBindVertexArray(_vaoHandle); + glm::mat4 mvpMatrix = proj_matrix * view_matrix * _model.getMatrix(); glUniformMatrix4fv(shader->uniform("mvp"), 1, GL_FALSE, glm::value_ptr(mvpMatrix)); + glm::mat4 modelview = view_matrix * _model.getMatrix(); + _model.glPopMatrix(); + glUniform4fv(shader->uniform("LightLocation"), 1, glm::value_ptr(view_matrix * glm::vec4(50, 50, 50, 1))); + glUniformMatrix4fv(shader->uniform("ModelViewMatrix"), 1, GL_FALSE, glm::value_ptr(modelview)); + glm::mat4 inverseModelView = glm::inverse(modelview); + glm::mat3 normalMatrix = glm::mat3(glm::transpose(inverseModelView)); + glUniformMatrix3fv(shader->uniform("NormalMatrix"), 1, GL_FALSE, glm::value_ptr(normalMatrix)); + if (ibo_used) + { + int size; + glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); glDrawElements(GL_TRIANGLES, size / sizeof(GLushort), GL_UNSIGNED_SHORT, 0); + } else glDrawArrays(GL_TRIANGLES, 0, 36); - _model.glPopMatrix(); + } diff --git a/BaseGLProject/ColorCube.h b/BaseGLProject/ColorCube.h index dedb46e..43fbea2 100644 --- a/BaseGLProject/ColorCube.h +++ b/BaseGLProject/ColorCube.h @@ -10,7 +10,7 @@ class ColorCube : public ADrawable private: GLuint _vaoHandle; GLuint _iboHandle; - GLuint _vbo_vertices, _vbo_colors; + GLuint _vbo_vertices, _vbo_colors, _vbo_normals; bool ibo_used; @@ -20,7 +20,7 @@ private: public: ColorCube(bool usingIBO); - void draw(ShaderProgram *shader, glm::mat4x4 pv) override; + void draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) override; DrawableType getType() override; ~ColorCube(); }; diff --git a/BaseGLProject/IDrawable.h b/BaseGLProject/IDrawable.h index 254f661..2b20bc6 100644 --- a/BaseGLProject/IDrawable.h +++ b/BaseGLProject/IDrawable.h @@ -10,7 +10,9 @@ enum DrawableType COLOR_CUBE, CHECKERED_FLOOR, WIRE_CUBE, - LINE_SEGMENT + LINE_SEGMENT, + SPHERE, + TEAPOT }; class IDrawable { @@ -25,6 +27,6 @@ public: virtual glm::vec3 getPosition() = 0; virtual glm::vec4 translateToPivot(glm::vec3) = 0; - virtual void draw(ShaderProgram *shader, glm::mat4x4 pv) = 0; - virtual DrawableType getType() = 0; + virtual void draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) = 0; + virtual DrawableType getType() = 0; }; \ No newline at end of file diff --git a/BaseGLProject/LineSegment.cpp b/BaseGLProject/LineSegment.cpp index 2b1989f..4c6dcfe 100644 --- a/BaseGLProject/LineSegment.cpp +++ b/BaseGLProject/LineSegment.cpp @@ -47,11 +47,11 @@ LineSegment::LineSegment() setup(); } -void LineSegment::draw(ShaderProgram *shader, glm::mat4x4 pv) +void LineSegment::draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) { _model.glPushMatrix(); effectTransformations(); - glm::mat4 mvpMatrix = pv * _model.getMatrix(); + glm::mat4 mvpMatrix = proj_matrix * view_matrix * _model.getMatrix(); glUniformMatrix4fv(shader->uniform("mvp"), 1, GL_FALSE, glm::value_ptr(mvpMatrix)); glLineWidth(4); glBindVertexArray(_vaoHandle); diff --git a/BaseGLProject/LineSegment.h b/BaseGLProject/LineSegment.h index 5b61d26..7be567c 100644 --- a/BaseGLProject/LineSegment.h +++ b/BaseGLProject/LineSegment.h @@ -25,7 +25,7 @@ public: LineSegment(); - void draw(ShaderProgram *shader, glm::mat4x4 pv) override; + void draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) override; DrawableType getType() override; ~LineSegment(); diff --git a/BaseGLProject/MyGLWindow.cpp b/BaseGLProject/MyGLWindow.cpp index 1dba369..0c1cd40 100644 --- a/BaseGLProject/MyGLWindow.cpp +++ b/BaseGLProject/MyGLWindow.cpp @@ -1,6 +1,6 @@ #include #include "MyGlWindow.h" - +//Getting the projection matrix glm::mat4x4 perspective(float fovy, float aspect, float near, float far) { float fovy2 = glm::tan(fovy / 2); @@ -57,31 +57,19 @@ void MyGlWindow::setBgColor(float bgColor[3]) void MyGlWindow::setup() { - _shaderProgram = new ShaderProgram(); - _shaderProgram->initFromFiles("simple.vert", "simple.frag"); + _staticShader = new ShaderProgram(); + _staticShader->initFromFiles("simple.vert", "simple.frag"); + _lightShader = new ShaderProgram(); + _lightShader->initFromFiles("light.vert", "simple.frag"); - _static_drawables.emplace_back(new CheckeredFloor(50, 16)); - _static_drawables.push_back(new ColorCube(true)); - _static_drawables.back()->addTranslation(glm::vec4(-2, 1.1f, 0, 0)); - _static_drawables.push_back(new ColorCube(false)); - _static_drawables.back()->addTranslation(glm::vec4(2, 1.1f, 0, 0)); -} - -void MyGlWindow::setViewFromBox(glm::vec3 &eye, glm::vec3 &look, glm::vec3 &up) -{ - glm::vec4 cube_base_position = { 8, 7.01, 0 , 1.0f}; - Model model; - - cube_base_position.x = 7 - (floatValues["box_horizontal"] * 6); - cube_base_position.y = 7 - (floatValues["box_vertical"] * 6); - - model.glPushMatrix(); - model.glTranslate(-8, 2, 0); - model.glRotate(floatValues["boom_rotation"], 0, -1, 0); - model.glTranslate(8, -2, 0); - - - eye = cube_base_position * model.getMatrix(); + _static_drawables.emplace_back(new CheckeredFloor(50, 16)); + _light_drawables.push_back(new ColorCube(false)); + _light_drawables.back()->addTranslation(glm::vec4(2, 1.1f, 0, 0)); + _light_drawables.push_back(new Sphere(1, 100, 100)); + _light_drawables.back()->addTranslation(glm::vec4(-2, 1.1f, 0, 0)); + _light_drawables.push_back(new VBOTeapot(64, glm::identity())); + _light_drawables.back()->addTranslation(glm::vec4(2, 3, -7, 0)); + _light_drawables.back()->addRotation(glm::vec4(1, 0, 0, -90)); } void MyGlWindow::draw() @@ -91,47 +79,48 @@ void MyGlWindow::draw() glViewport(0, 0, m_width, m_height); glEnable(GL_DEPTH_TEST); - _shaderProgram->use(); - glm::vec3 eye(viewer.getViewPoint().x, viewer.getViewPoint().y, viewer.getViewPoint().z); glm::vec3 look(viewer.getViewCenter().x, viewer.getViewCenter().y, viewer.getViewCenter().z); - glm::vec3 up(viewer.getUpVector().x, viewer.getUpVector().y, viewer.getUpVector().z); + glm::vec3 up(viewer.getUpVector().x, viewer.getUpVector().y, viewer.getUpVector().z); glm::mat4 view = lookAt(eye, look, up); //Calculate view matrix from paramters of m_viewer glm::mat4 projection = perspective(45.0f, m_width / m_height, 0.1f, 500.0f); - _shaderProgram->addUniform("mvp"); + _staticShader->use(); - for (ADrawable *drawable : _static_drawables) - drawable->draw(_shaderProgram, projection * view); - - for (ADrawable *drawable : _crane_boom) - { - glm::vec4 t = drawable->translateToPivot(glm::vec3(0, 9.01, 0)); - drawable->addRotation(glm::vec4(0, 1, 0, floatValues["boom_rotation"])); - drawable->addTranslation(t); - - if (drawable->getType() == COLOR_CUBE) - drawable->addTranslation(glm::vec4(floatValues["box_horizontal"] * -6.01, - floatValues["box_vertical"] * -6.01, 0 ,0)); - if (drawable->getType() == LINE_SEGMENT) - { - drawable->addTranslation(glm::vec4(floatValues["box_horizontal"] * -6.01 , floatValues["box_vertical"] * -4.01, 0, 0)); - drawable->addScaling(glm::vec4(0, floatValues["box_vertical"] * 4.01, 0, 0)); - } - - if (!view_from_box || (drawable->getType() != COLOR_CUBE && drawable->getType() != LINE_SEGMENT)) - drawable->draw(_shaderProgram, projection * view); - - if (drawable->getType() == COLOR_CUBE) - drawable->removeLastTransformations(1); - else if (drawable->getType() == LINE_SEGMENT) - drawable->removeLastTransformations(2); - - drawable->removeLastTransformations(3); - - } + _staticShader->addUniform("mvp"); - _shaderProgram->disable(); + for (ADrawable *drawable : _static_drawables) + drawable->draw(_staticShader, projection, view); + + _staticShader->disable(); + + _lightShader->use(); + + _lightShader->addUniform("mvp"); + _lightShader->addUniform("LightLocation"); //Light Position to camera coordinates : vec4 + + _lightShader->addUniform("Kd"); //Diffuse Object Color :vec3 + glUniform3fv(_lightShader->uniform("Kd"), 1, glm::value_ptr(glm::vec3(1, 1, 0))); + _lightShader->addUniform("Ld"); //Diffuse Light Color : vec3 + glUniform3fv(_lightShader->uniform("Ld"), 1, glm::value_ptr(glm::vec3(1, 1, 1))); + + _lightShader->addUniform("Ka"); //Diffuse Object Color :vec3 + glUniform3fv(_lightShader->uniform("Ka"), 1, glm::value_ptr(glm::vec3(0.2, 0.2, 0))); + _lightShader->addUniform("La"); //Diffuse Light Color : vec3 + glUniform3fv(_lightShader->uniform("La"), 1, glm::value_ptr(glm::vec3(1, 1, 1))); + + _lightShader->addUniform("Ks"); //Diffuse Object Color :vec3 + glUniform3fv(_lightShader->uniform("Ks"), 1, glm::value_ptr(glm::vec3(0.3, 0.3, 0))); + _lightShader->addUniform("Ls"); //Diffuse Light Color : vec3 + glUniform3fv(_lightShader->uniform("Ls"), 1, glm::value_ptr(glm::vec3(1, 1, 1))); + + _lightShader->addUniform("NormalMatrix"); //Refer next slide : mat3 + _lightShader->addUniform("ModelViewMatrix"); //View*Model : mat4 + + for (ADrawable *drawable : _light_drawables) + drawable->draw(_lightShader, projection, view); + + _lightShader->disable(); } void MyGlWindow::AddDrawable(ADrawable *d) diff --git a/BaseGLProject/MyGLWindow.h b/BaseGLProject/MyGLWindow.h index 972014d..7962781 100644 --- a/BaseGLProject/MyGLWindow.h +++ b/BaseGLProject/MyGLWindow.h @@ -12,6 +12,8 @@ #include "CheckeredFloor.h" #include "WireCube.h" #include "LineSegment.h" +#include "Sphere.h" +#include "vboteapot.h" struct vertexAttr { GLfloat posX, posY, posZ; @@ -28,13 +30,13 @@ public: void setBgColor(float bgColor[3]); std::map floatValues; - bool view_from_box = false; void AddDrawable(ADrawable *); void resize(int w, int h); Viewer viewer; private: - ShaderProgram *_shaderProgram; + ShaderProgram *_staticShader; + ShaderProgram *_lightShader; int m_width; int m_height; @@ -44,8 +46,7 @@ private: GLuint _iboHandle; std::vector _static_drawables; - - std::vector _crane_boom; + std::vector _light_drawables; void setup(); void setViewFromBox(glm::vec3 &eye, glm::vec3 &look, glm::vec3 &up); diff --git a/BaseGLProject/Source.cpp b/BaseGLProject/Source.cpp index 4f8c3ac..c96f62c 100644 --- a/BaseGLProject/Source.cpp +++ b/BaseGLProject/Source.cpp @@ -173,31 +173,14 @@ int loop(GLFWwindow *window) if (ImGui::Begin("First Window")) { - ImGui::SetWindowPos(ImVec2(20, 20)); - - static float box_horizontal = .0f; - ImGui::SliderFloat("Box Horizontal", &box_horizontal, 0, 1); - glWin.floatValues["box_horizontal"] = box_horizontal; - - static float box_vertical = .0f; - ImGui::SliderFloat("Box Vertical", &box_vertical, 0, 1); - glWin.floatValues["box_vertical"] = box_vertical; - - static float boom_rotation = .0f; - ImGui::SliderFloat("Boom rotation", &boom_rotation, -180, 180); - glWin.floatValues["boom_rotation"] = boom_rotation; - - static int box_view; - ImGui::RadioButton("Default", &box_view, 0); ImGui::SameLine(); - ImGui::RadioButton("Box", &box_view, 1); - glWin.view_from_box = box_view; + ImGui::SetWindowPos(ImVec2(20, 20)); static float bgColor[3] = { .3f, .3f, .3f }; ImGui::ColorEdit3("Background", bgColor, 0); glWin.setBgColor(bgColor); ImGui::End(); - } + } glfwSwapBuffers(window); glWin.draw(); diff --git a/BaseGLProject/Sphere.cpp b/BaseGLProject/Sphere.cpp new file mode 100644 index 0000000..33ca388 --- /dev/null +++ b/BaseGLProject/Sphere.cpp @@ -0,0 +1,191 @@ +#include "Sphere.h" + +#include +#include +#include +#include + +#include +#include +Sphere::Sphere() +{ + +} + + +Sphere::~Sphere() +{ +} + + + +Sphere::Sphere(float rad, GLuint sl, GLuint st) : +radius(rad), slices(sl), stacks(st) +{ + + nVerts = (slices + 1) * (stacks + 1); + elements = (slices * 2 * (stacks - 1)) * 3; + + // Verts + float * v = new float[3 * nVerts]; + // Normals + float * n = new float[3 * nVerts]; + // Tex coords + float * tex = new float[2 * nVerts]; //we don't use it now + // Index + unsigned int * el = new unsigned int[elements]; //index + + // Generate the vertex data + generateVerts(v, n, tex, el); + + + + //create vao, vbo and ibo here... (We didn't use std::vector here...) + + glGenVertexArrays(1, &VAO); + glBindVertexArray(VAO); + + glGenBuffers(1, &VBO_position); + glBindBuffer(GL_ARRAY_BUFFER, VBO_position); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * nVerts, v, GL_STATIC_DRAW); + + glVertexAttribPointer( + 0, //attr number = 0 + 3, + GL_FLOAT, + GL_FALSE, + 0, + (void*)0); + glEnableVertexAttribArray(0); //attr number = 0 + + glGenBuffers(1, &VBO_normal); + glBindBuffer(GL_ARRAY_BUFFER, VBO_normal); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * nVerts, n, GL_STATIC_DRAW); + + glVertexAttribPointer( + 1, + 3, + GL_FLOAT, + GL_FALSE, + 0, + (void*)0); + glEnableVertexAttribArray(1); + + glGenBuffers(1, &VBO_tex); + glBindBuffer(GL_ARRAY_BUFFER, VBO_tex); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 2 * nVerts, tex, GL_STATIC_DRAW); + + glVertexAttribPointer( + 2, + 3, + GL_FLOAT, + GL_FALSE, + 0, + (void*)0); + glEnableVertexAttribArray(2); + + + glGenBuffers(1, &IBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, elements * sizeof(GLuint), el, GL_STATIC_DRAW); + + glBindVertexArray(0); + + delete[] v; + delete[] n; + delete[] el; + delete[] tex; + +} + +void Sphere::draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) +{ + _model.glPushMatrix(); + effectTransformations(); + glBindVertexArray(VAO); + glm::mat4 mvpMatrix = proj_matrix * view_matrix * _model.getMatrix(); + glUniformMatrix4fv(shader->uniform("mvp"), 1, GL_FALSE, glm::value_ptr(mvpMatrix)); + glm::mat4 modelview = view_matrix * _model.getMatrix(); + glUniform4fv(shader->uniform("LightLocation"), 1, glm::value_ptr(view_matrix * glm::vec4(50, 50, 50, 1))); + glUniformMatrix4fv(shader->uniform("ModelViewMatrix"), 1, GL_FALSE, glm::value_ptr(modelview)); + glm::mat4 inverseModelView = glm::inverse(modelview); + glm::mat3 normalMatrix = glm::mat3(glm::transpose(inverseModelView)); + glUniformMatrix3fv(shader->uniform("NormalMatrix"), 1, GL_FALSE, glm::value_ptr(normalMatrix)); + + int size; + glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); + glDrawElements(GL_TRIANGLES, size / sizeof(GLuint), GL_UNSIGNED_INT, 0); + + _model.glPopMatrix(); + +} + +void Sphere::generateVerts(float * verts, float * norms, float * tex, + unsigned int * el) +{ + // Generate positions and normals + GLfloat theta, phi; + GLfloat thetaFac = glm::two_pi() / slices; + GLfloat phiFac = glm::pi() / stacks; + GLfloat nx, ny, nz, s, t; + GLuint idx = 0, tIdx = 0; + for (GLuint i = 0; i <= slices; i++) { + theta = i * thetaFac; + s = (GLfloat)i / slices; + for (GLuint j = 0; j <= stacks; j++) { + phi = j * phiFac; + t = (GLfloat)j / stacks; + nx = sinf(phi) * cosf(theta); + ny = sinf(phi) * sinf(theta); + nz = cosf(phi); + verts[idx] = radius * nx; verts[idx + 1] = radius * ny; verts[idx + 2] = radius * nz; + norms[idx] = nx; norms[idx + 1] = ny; norms[idx + 2] = nz; + idx += 3; + + tex[tIdx] = s; + tex[tIdx + 1] = t; + tIdx += 2; + } + } + + // Generate the element list + idx = 0; + for (GLuint i = 0; i < slices; i++) { + GLuint stackStart = i * (stacks + 1); + GLuint nextStackStart = (i + 1) * (stacks + 1); + for (GLuint j = 0; j < stacks; j++) { + if (j == 0) { + el[idx] = stackStart; + el[idx + 1] = stackStart + 1; + el[idx + 2] = nextStackStart + 1; + idx += 3; + } + else if (j == stacks - 1) { + el[idx] = stackStart + j; + el[idx + 1] = stackStart + j + 1; + el[idx + 2] = nextStackStart + j; + idx += 3; + } + else { + el[idx] = stackStart + j; + el[idx + 1] = stackStart + j + 1; + el[idx + 2] = nextStackStart + j + 1; + el[idx + 3] = nextStackStart + j; + el[idx + 4] = stackStart + j; + el[idx + 5] = nextStackStart + j + 1; + idx += 6; + } + } + } +} + +DrawableType Sphere::getType() +{ + return DrawableType::SPHERE; +} + +int Sphere::getVertexArrayHandle() +{ + return this->VAO; +} + diff --git a/BaseGLProject/Sphere.h b/BaseGLProject/Sphere.h new file mode 100644 index 0000000..051c4bb --- /dev/null +++ b/BaseGLProject/Sphere.h @@ -0,0 +1,45 @@ +#ifndef ___SPHERE_H +#define ___SPHERE_H + +#include "GL/glew.h" +#include +#include + +#include + +#include "ADrawable.h" + +#include "Loader.h" + + + +class Sphere : public ADrawable +{ +public: + Sphere(); + Sphere(float rad, GLuint sl, GLuint st); + ~Sphere(); + + void draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix); + int getVertexArrayHandle(); + + GLuint VAO, VBO_position, VBO_normal, VBO_tex, IBO; + + + +private: + GLuint nVerts, elements; + float radius; + GLuint slices, stacks; + + void generateVerts(float *, float *, float *, unsigned int *); + + + + // Inherited via ADrawable + virtual DrawableType getType() override; + +}; + + +#endif diff --git a/BaseGLProject/WireCube.cpp b/BaseGLProject/WireCube.cpp index 0d65646..184ac58 100644 --- a/BaseGLProject/WireCube.cpp +++ b/BaseGLProject/WireCube.cpp @@ -43,11 +43,11 @@ WireCube::WireCube() setup(); } -void WireCube::draw(ShaderProgram * shader, glm::mat4x4 pv) +void WireCube::draw(ShaderProgram * shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) { _model.glPushMatrix(); effectTransformations(); - glm::mat4 mvpMatrix = pv * _model.getMatrix(); + glm::mat4 mvpMatrix = proj_matrix * view_matrix * _model.getMatrix(); glUniformMatrix4fv(shader->uniform("mvp"), 1, GL_FALSE, glm::value_ptr(mvpMatrix)); glLineWidth(2); diff --git a/BaseGLProject/WireCube.h b/BaseGLProject/WireCube.h index f02955c..e65e13c 100644 --- a/BaseGLProject/WireCube.h +++ b/BaseGLProject/WireCube.h @@ -19,7 +19,7 @@ private: public: WireCube(); - void draw(ShaderProgram *shader, glm::mat4x4 pv) override; + void draw(ShaderProgram *shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) override; DrawableType getType() override; ~WireCube(); diff --git a/BaseGLProject/imgui.ini b/BaseGLProject/imgui.ini index 20b6a0c..7a9553e 100644 --- a/BaseGLProject/imgui.ini +++ b/BaseGLProject/imgui.ini @@ -45,6 +45,6 @@ Collapsed=0 [Window][First Window] Pos=20,20 -Size=350,150 +Size=322,75 Collapsed=0 diff --git a/BaseGLProject/light.vert b/BaseGLProject/light.vert new file mode 100644 index 0000000..2bbdae2 --- /dev/null +++ b/BaseGLProject/light.vert @@ -0,0 +1,42 @@ +#version 430 + +layout(location=0) in vec3 coord3d; +layout(location=1) in vec3 v_normal; +layout(location=2) in vec3 v_color; + +out vec3 f_color; + +uniform mat4 mvp; +uniform vec4 LightLocation; + +uniform vec3 Kd; +uniform vec3 Ld; + +uniform vec3 Ka; +uniform vec3 La; + +uniform vec3 Ks; +uniform vec3 Ls; + + +uniform mat3 NormalMatrix; +uniform mat4 ModelViewMatrix; + + +void main(void) +{ + vec3 fNormal = normalize(NormalMatrix * v_normal); + vec4 pos = ModelViewMatrix * vec4(coord3d, 1.0); + + vec3 L = normalize(LightLocation.xyz - pos.xyz); + vec3 N = fNormal; + vec3 V = normalize(-pos.xyz); + vec3 R = reflect(-L, N); + + vec3 diffuse = Kd * Ld * max(dot(L, N), 0.0); + vec3 ambient = Ka * La; + vec3 specular = Ks * Ls * pow(max(dot(L, N), 0.0), 50.0); + + f_color = diffuse + ambient + specular; + gl_Position = mvp * vec4(coord3d, 1.0f); +} diff --git a/BaseGLProject/simple.vert b/BaseGLProject/simple.vert index 365c54b..a377d01 100644 --- a/BaseGLProject/simple.vert +++ b/BaseGLProject/simple.vert @@ -11,4 +11,4 @@ void main(void) { f_color = v_color; gl_Position = mvp * vec4(coord3d, 1.0f); -} +} \ No newline at end of file diff --git a/BaseGLProject/teapotdata.h b/BaseGLProject/teapotdata.h new file mode 100644 index 0000000..606c7b4 --- /dev/null +++ b/BaseGLProject/teapotdata.h @@ -0,0 +1,206 @@ +#ifndef TEAPOTDATA_H +#define TEAPOTDATA_H + +/* Copyright (c) Mark J. Kilgard, 1994. */ + +/** +(c) Copyright 1993, Silicon Graphics, Inc. + +ALL RIGHTS RESERVED + +Permission to use, copy, modify, and distribute this software +for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that +both the copyright notice and this permission notice appear in +supporting documentation, and that the name of Silicon +Graphics, Inc. not be used in advertising or publicity +pertaining to distribution of the software without specific, +written prior permission. + +THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU +"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR +OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO +EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE +ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, +INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, +SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR +NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY +OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR +PERFORMANCE OF THIS SOFTWARE. + +US Government Users Restricted Rights + +Use, duplication, or disclosure by the Government is subject to +restrictions set forth in FAR 52.227.19(c)(2) or subparagraph +(c)(1)(ii) of the Rights in Technical Data and Computer +Software clause at DFARS 252.227-7013 and/or in similar or +successor clauses in the FAR or the DOD or NASA FAR +Supplement. Unpublished-- rights reserved under the copyright +laws of the United States. Contractor/manufacturer is Silicon +Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA +94039-7311. + +OpenGL(TM) is a trademark of Silicon Graphics, Inc. +*/ + +/* Rim, body, lid, and bottom data must be reflected in x and + y; handle and spout data across the y axis only. */ + +namespace Teapot { +static int patchdata[][16] = +{ + /* rim */ + {102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + /* body */ + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}, + {24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, + /* lid */ + {96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3,}, + {0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117}, + /* bottom */ + {118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37}, + /* handle */ + {41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56}, + {53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67}, + /* spout */ + {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83}, + {80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95} +}; + +static float cpdata[][3] = +{ + {0.2f, 0.f, 2.7f}, + {0.2f, -0.112f, 2.7f}, + {0.112f, -0.2f, 2.7f}, + {0.f, -0.2f, 2.7f}, + {1.3375f, 0.f, 2.53125f}, + {1.3375f, -0.749f, 2.53125f}, + {0.749f, -1.3375f, 2.53125f}, + {0.f, -1.3375f, 2.53125f}, + {1.4375f, 0.f, 2.53125f}, + {1.4375f, -0.805f, 2.53125f}, + {0.805f, -1.4375f, 2.53125f}, + {0.f, -1.4375f, 2.53125f}, + {1.5f, 0.f, 2.4f}, + {1.5f, -0.84f, 2.4f}, + {0.84f, -1.5f, 2.4f}, + {0.f, -1.5f, 2.4f}, + {1.75f, 0.f, 1.875f}, + {1.75f, -0.98f, 1.875f}, + {0.98f, -1.75f, 1.875f}, + {0.f, -1.75f, 1.875f}, + {2.f, 0.f, 1.35f}, + {2.f, -1.12f, 1.35f}, + {1.12f, -2.f, 1.35f}, + {0.f, -2.f, 1.35f}, + {2.f, 0.f, 0.9f}, + {2.f, -1.12f, 0.9f}, + {1.12f, -2.f, 0.9f}, + {0.f, -2.f, 0.9f}, + {-2.f, 0.f, 0.9f}, + {2.f, 0.f, 0.45f}, + {2.f, -1.12f, 0.45f}, + {1.12f, -2.f, 0.45f}, + {0.f, -2.f, 0.45f}, + {1.5f, 0.f, 0.225f}, + {1.5f, -0.84f, 0.225f}, + {0.84f, -1.5f, 0.225f}, + {0.f, -1.5f, 0.225f}, + {1.5f, 0.f, 0.15f}, + {1.5f, -0.84f, 0.15f}, + {0.84f, -1.5f, 0.15f}, + {0.f, -1.5f, 0.15f}, + {-1.6f, 0.f, 2.025f}, + {-1.6f, -0.3f, 2.025f}, + {-1.5f, -0.3f, 2.25f}, + {-1.5f, 0.f, 2.25f}, + {-2.3f, 0.f, 2.025f}, + {-2.3f, -0.3f, 2.025f}, + {-2.5f, -0.3f, 2.25f}, + {-2.5f, 0.f, 2.25f}, + {-2.7f, 0.f, 2.025f}, + {-2.7f, -0.3f, 2.025f}, + {-3.f, -0.3f, 2.25f}, + {-3.f, 0.f, 2.25f}, + {-2.7f, 0.f, 1.8f}, + {-2.7f, -0.3f, 1.8f}, + {-3.f, -0.3f, 1.8f}, + {-3.f, 0.f, 1.8f}, + {-2.7f, 0.f, 1.575f}, + {-2.7f, -0.3f, 1.575f}, + {-3.f, -0.3f, 1.35f}, + {-3.f, 0.f, 1.35f}, + {-2.5f, 0.f, 1.125f}, + {-2.5f, -0.3f, 1.125f}, + {-2.65f, -0.3f, 0.9375f}, + {-2.65f, 0.f, 0.9375f}, + {-2.f, -0.3f, 0.9f}, + {-1.9f, -0.3f, 0.6f}, + {-1.9f, 0.f, 0.6f}, + {1.7f, 0.f, 1.425f}, + {1.7f, -0.66f, 1.425f}, + {1.7f, -0.66f, 0.6f}, + {1.7f, 0.f, 0.6f}, + {2.6f, 0.f, 1.425f}, + {2.6f, -0.66f, 1.425f}, + {3.1f, -0.66f, 0.825f}, + {3.1f, 0.f, 0.825f}, + {2.3f, 0.f, 2.1f}, + {2.3f, -0.25f, 2.1f}, + {2.4f, -0.25f, 2.025f}, + {2.4f, 0.f, 2.025f}, + {2.7f, 0.f, 2.4f}, + {2.7f, -0.25f, 2.4f}, + {3.3f, -0.25f, 2.4f}, + {3.3f, 0.f, 2.4f}, + {2.8f, 0.f, 2.475f}, + {2.8f, -0.25f, 2.475f}, + {3.525f, -0.25f, 2.49375f}, + {3.525f, 0.f, 2.49375f}, + {2.9f, 0.f, 2.475f}, + {2.9f, -0.15f, 2.475f}, + {3.45f, -0.15f, 2.5125f}, + {3.45f, 0.f, 2.5125f}, + {2.8f, 0.f, 2.4f}, + {2.8f, -0.15f, 2.4f}, + {3.2f, -0.15f, 2.4f}, + {3.2f, 0.f, 2.4f}, + {0.f, 0.f, 3.15f}, + {0.8f, 0.f, 3.15f}, + {0.8f, -0.45f, 3.15f}, + {0.45f, -0.8f, 3.15f}, + {0.f, -0.8f, 3.15f}, + {0.f, 0.f, 2.85f}, + {1.4f, 0.f, 2.4f}, + {1.4f, -0.784f, 2.4f}, + {0.784f, -1.4f, 2.4f}, + {0.f, -1.4f, 2.4f}, + {0.4f, 0.f, 2.55f}, + {0.4f, -0.224f, 2.55f}, + {0.224f, -0.4f, 2.55f}, + {0.f, -0.4f, 2.55f}, + {1.3f, 0.f, 2.55f}, + {1.3f, -0.728f, 2.55f}, + {0.728f, -1.3f, 2.55f}, + {0.f, -1.3f, 2.55f}, + {1.3f, 0.f, 2.4f}, + {1.3f, -0.728f, 2.4f}, + {0.728f, -1.3f, 2.4f}, + {0.f, -1.3f, 2.4f}, + {0.f, 0.f, 0.f}, + {1.425f, -0.798f, 0.f}, + {1.5f, 0.f, 0.075f}, + {1.425f, 0.f, 0.f}, + {0.798f, -1.425f, 0.f}, + {0.f, -1.5f, 0.075f}, + {0.f, -1.425f, 0.f}, + {1.5f, -0.84f, 0.075f}, + {0.84f, -1.5f, 0.075f} +}; + +} + +#endif // TEAPOTDATA_H diff --git a/BaseGLProject/vboteapot.cpp b/BaseGLProject/vboteapot.cpp new file mode 100644 index 0000000..06a55d5 --- /dev/null +++ b/BaseGLProject/vboteapot.cpp @@ -0,0 +1,326 @@ +#include "vboteapot.h" +#include "teapotdata.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + + + +//set grid = 64, lidTransform = 4x4 identity matrix +VBOTeapot::VBOTeapot(int grid, mat4 lidTransform) +{ + int verts = 32 * (grid + 1) * (grid + 1); + faces = grid * grid * 32; + + + float * v = new float[ verts * 3 ]; //vertex positions : vec3 + float * n = new float[ verts * 3 ]; //vertex normals : vec3 + float * tc = new float[ verts * 2 ]; //texture coordinates : vec2 (we don't use it at this point) + unsigned int * el = new unsigned int[faces * 6]; //indices for IBO + + generatePatches(v, n, tc, el, grid); + + + + + glGenVertexArrays(1, &VAO); + glBindVertexArray(VAO); + + glGenBuffers(1, &VBO_position); + glBindBuffer(GL_ARRAY_BUFFER, VBO_position); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * verts, v, GL_STATIC_DRAW); + + glVertexAttribPointer( + 0, //attr number = 0 + 3, + GL_FLOAT, + GL_FALSE, + 0, + (void*)0); + glEnableVertexAttribArray(0); //attr number = 0 + + glGenBuffers(1, &VBO_normal); + glBindBuffer(GL_ARRAY_BUFFER, VBO_normal); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * verts, n, GL_STATIC_DRAW); + + glVertexAttribPointer( + 1, + 3, + GL_FLOAT, + GL_FALSE, + 0, + (void*)0); + glEnableVertexAttribArray(1); + + glGenBuffers(1, &VBO_tex); + glBindBuffer(GL_ARRAY_BUFFER, VBO_tex); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 2 * verts, tc, GL_STATIC_DRAW); + + glVertexAttribPointer( + 2, + 3, + GL_FLOAT, + GL_FALSE, + 0, + (void*)0); + glEnableVertexAttribArray(2); + + + glGenBuffers(1, &IBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, faces * 6 * sizeof(GLuint), el, GL_STATIC_DRAW); + + glBindVertexArray(0); + + + delete [] v; + delete [] n; + delete [] el; + delete [] tc; + + +} + +void VBOTeapot::draw(ShaderProgram * shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) +{ + _model.glPushMatrix(); + effectTransformations(); + glBindVertexArray(VAO); + glm::mat4 mvpMatrix = proj_matrix * view_matrix * _model.getMatrix(); + glUniformMatrix4fv(shader->uniform("mvp"), 1, GL_FALSE, glm::value_ptr(mvpMatrix)); + glm::mat4 modelview = view_matrix * _model.getMatrix(); + glUniform4fv(shader->uniform("LightLocation"), 1, glm::value_ptr(view_matrix * glm::vec4(50, 50, 50, 1))); + glUniformMatrix4fv(shader->uniform("ModelViewMatrix"), 1, GL_FALSE, glm::value_ptr(modelview)); + glm::mat4 inverseModelView = glm::inverse(modelview); + glm::mat3 normalMatrix = glm::mat3(glm::transpose(inverseModelView)); + glUniformMatrix3fv(shader->uniform("NormalMatrix"), 1, GL_FALSE, glm::value_ptr(normalMatrix)); + + int size; + glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); + glDrawElements(GL_TRIANGLES, size / sizeof(GLuint), GL_UNSIGNED_INT, 0); + + _model.glPopMatrix(); + +} + +DrawableType VBOTeapot::getType() +{ + return DrawableType::TEAPOT; +} + +void VBOTeapot::generatePatches(float * v, float * n, float * tc, unsigned int* el, int grid) { + float * B = new float[4*(grid+1)]; // Pre-computed Bernstein basis functions + float * dB = new float[4*(grid+1)]; // Pre-computed derivitives of basis functions + + int idx = 0, elIndex = 0, tcIndex = 0; + + // Pre-compute the basis functions (Bernstein polynomials) + // and their derivatives + computeBasisFunctions(B, dB, grid); + + // Build each patch + // The rim + buildPatchReflect(0, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, true, true); + // The body + buildPatchReflect(1, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, true, true); + buildPatchReflect(2, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, true, true); + // The lid + buildPatchReflect(3, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, true, true); + buildPatchReflect(4, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, true, true); + // The bottom + buildPatchReflect(5, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, true, true); + // The handle + buildPatchReflect(6, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, false, true); + buildPatchReflect(7, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, false, true); + // The spout + buildPatchReflect(8, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, false, true); + buildPatchReflect(9, B, dB, v, n, tc, el, idx, elIndex, tcIndex, grid, false, true); + + delete [] B; + delete [] dB; +} + +void VBOTeapot::moveLid(int grid, float *v, mat4 lidTransform) { + + int start = 3 * 12 * (grid+1) * (grid+1); + int end = 3 * 20 * (grid+1) * (grid+1); + + for( int i = start; i < end; i+=3 ) + { + vec4 vert = vec4(v[i], v[i+1], v[i+2], 1.0f ); + vert = lidTransform * vert; + v[i] = vert.x; + v[i+1] = vert.y; + v[i+2] = vert.z; + } +} + +void VBOTeapot::buildPatchReflect(int patchNum, + float *B, float *dB, + float *v, float *n, + float *tc, unsigned int *el, + int &index, int &elIndex, int &tcIndex, int grid, + bool reflectX, bool reflectY) +{ + vec3 patch[4][4]; + vec3 patchRevV[4][4]; + getPatch(patchNum, patch, false); + getPatch(patchNum, patchRevV, true); + + // Patch without modification + buildPatch(patch, B, dB, v, n, tc, el, + index, elIndex, tcIndex, grid, mat3(1.0f), true); + + // Patch reflected in x + if( reflectX ) { + buildPatch(patchRevV, B, dB, v, n, tc, el, + index, elIndex, tcIndex, grid, mat3(vec3(-1.0f, 0.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 0.0f, 1.0f) ), false ); + } + + // Patch reflected in y + if( reflectY ) { + buildPatch(patchRevV, B, dB, v, n, tc, el, + index, elIndex, tcIndex, grid, mat3(vec3(1.0f, 0.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, 0.0f, 1.0f) ), false ); + } + + // Patch reflected in x and y + if( reflectX && reflectY ) { + buildPatch(patch, B, dB, v, n, tc, el, + index, elIndex, tcIndex, grid, mat3(vec3(-1.0f, 0.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, 0.0f, 1.0f) ), true ); + } +} + +void VBOTeapot::buildPatch(vec3 patch[][4], + float *B, float *dB, + float *v, float *n, float *tc, + unsigned int *el, + int &index, int &elIndex, int &tcIndex, int grid, mat3 reflect, + bool invertNormal) +{ + int startIndex = index / 3; + float tcFactor = 1.0f / grid; + + for( int i = 0; i <= grid; i++ ) + { + for( int j = 0 ; j <= grid; j++) + { + vec3 pt = reflect * evaluate(i,j,B,patch); + vec3 norm = reflect * evaluateNormal(i,j,B,dB,patch); + if( invertNormal ) + norm = -norm; + + v[index] = pt.x; + v[index+1] = pt.y; + v[index+2] = pt.z; + + n[index] = norm.x; + n[index+1] = norm.y; + n[index+2] = norm.z; + + tc[tcIndex] = i * tcFactor; + tc[tcIndex+1] = j * tcFactor; + + index += 3; + tcIndex += 2; + } + } + + for( int i = 0; i < grid; i++ ) + { + int iStart = i * (grid+1) + startIndex; + int nextiStart = (i+1) * (grid+1) + startIndex; + for( int j = 0; j < grid; j++) + { + el[elIndex] = iStart + j; + el[elIndex+1] = nextiStart + j + 1; + el[elIndex+2] = nextiStart + j; + + el[elIndex+3] = iStart + j; + el[elIndex+4] = iStart + j + 1; + el[elIndex+5] = nextiStart + j + 1; + + elIndex += 6; + } + } +} + +void VBOTeapot::getPatch( int patchNum, vec3 patch[][4], bool reverseV ) +{ + for( int u = 0; u < 4; u++) { // Loop in u direction + for( int v = 0; v < 4; v++ ) { // Loop in v direction + if( reverseV ) { + patch[u][v] = vec3( + Teapot::cpdata[Teapot::patchdata[patchNum][u*4+(3-v)]][0], + Teapot::cpdata[Teapot::patchdata[patchNum][u*4+(3-v)]][1], + Teapot::cpdata[Teapot::patchdata[patchNum][u*4+(3-v)]][2] + ); + } else { + patch[u][v] = vec3( + Teapot::cpdata[Teapot::patchdata[patchNum][u*4+v]][0], + Teapot::cpdata[Teapot::patchdata[patchNum][u*4+v]][1], + Teapot::cpdata[Teapot::patchdata[patchNum][u*4+v]][2] + ); + } + } + } +} + +void VBOTeapot::computeBasisFunctions( float * B, float * dB, int grid ) { + float inc = 1.0f / grid; + for( int i = 0; i <= grid; i++ ) + { + float t = i * inc; + float tSqr = t * t; + float oneMinusT = (1.0f - t); + float oneMinusT2 = oneMinusT * oneMinusT; + + B[i*4 + 0] = oneMinusT * oneMinusT2; + B[i*4 + 1] = 3.0f * oneMinusT2 * t; + B[i*4 + 2] = 3.0f * oneMinusT * tSqr; + B[i*4 + 3] = t * tSqr; + + dB[i*4 + 0] = -3.0f * oneMinusT2; + dB[i*4 + 1] = -6.0f * t * oneMinusT + 3.0f * oneMinusT2; + dB[i*4 + 2] = -3.0f * tSqr + 6.0f * t * oneMinusT; + dB[i*4 + 3] = 3.0f * tSqr; + } +} + + +vec3 VBOTeapot::evaluate( int gridU, int gridV, float *B, vec3 patch[][4] ) +{ + vec3 p(0.0f,0.0f,0.0f); + for( int i = 0; i < 4; i++) { + for( int j = 0; j < 4; j++) { + p += patch[i][j] * B[gridU*4+i] * B[gridV*4+j]; + } + } + return p; +} + +vec3 VBOTeapot::evaluateNormal( int gridU, int gridV, float *B, float *dB, vec3 patch[][4] ) +{ + vec3 du(0.0f,0.0f,0.0f); + vec3 dv(0.0f,0.0f,0.0f); + + for( int i = 0; i < 4; i++) { + for( int j = 0; j < 4; j++) { + du += patch[i][j] * dB[gridU*4+i] * B[gridV*4+j]; + dv += patch[i][j] * B[gridU*4+i] * dB[gridV*4+j]; + } + } + return glm::normalize( glm::cross( du, dv ) ); +} diff --git a/BaseGLProject/vboteapot.h b/BaseGLProject/vboteapot.h new file mode 100644 index 0000000..ab57a82 --- /dev/null +++ b/BaseGLProject/vboteapot.h @@ -0,0 +1,52 @@ +#ifndef VBOTEAPOT_H +#define VBOTEAPOT_H + + + + +#include +#include +#include +#include "ADrawable.h" +#include "Loader.h" + +using glm::vec4; +using glm::vec3; +using glm::mat3; +using glm::mat4; + +class VBOTeapot : public ADrawable +{ +private: + GLuint VAO, VBO_position, VBO_normal, VBO_tex, IBO; + unsigned int faces; + + void generatePatches(float * v, float * n, float *tc, unsigned int* el, int grid); + void buildPatchReflect(int patchNum, + float *B, float *dB, + float *v, float *n, float *, unsigned int *el, + int &index, int &elIndex, int &, int grid, + bool reflectX, bool reflectY); + void buildPatch(vec3 patch[][4], + float *B, float *dB, + float *v, float *n,float *, unsigned int *el, + int &index, int &elIndex, int &, int grid, mat3 reflect, bool invertNormal); + void getPatch( int patchNum, vec3 patch[][4], bool reverseV ); + + void computeBasisFunctions( float * B, float * dB, int grid ); + vec3 evaluate( int gridU, int gridV, float *B, vec3 patch[][4] ); + vec3 evaluateNormal( int gridU, int gridV, float *B, float *dB, vec3 patch[][4] ); + void moveLid(int,float *,mat4); + +public: + VBOTeapot(int grid, mat4 lidTransform); + + + // Inherited via ADrawable + virtual void draw(ShaderProgram * shader, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) override; + + virtual DrawableType getType() override; + +}; + +#endif // VBOTEAPOT_H