Commit aa6cc3a1 authored by Bastian Krayer's avatar Bastian Krayer

- small fix: vao now gets deleted

- added solution 2
parent 3812070f
......@@ -28,9 +28,9 @@ GLFWwindow* Renderer::initialize(int width, int height) {
mShaderProgram->useProgram();
mColorHandle =
glGetUniformLocation(mShaderProgram->getProgramID(), "color");
GLuint vaoHandle;
glGenVertexArrays(1, &vaoHandle);
glBindVertexArray(vaoHandle);
glGenVertexArrays(1, &mVaoHandle);
glBindVertexArray(mVaoHandle);
glGenBuffers(2, mVbos);
return window;
}
......@@ -65,4 +65,7 @@ void Renderer::render(BSpline& spline) {
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
Renderer::~Renderer() { glDeleteBuffers(2, mVbos); }
Renderer::~Renderer() {
glDeleteBuffers(2, mVbos);
glDeleteVertexArrays(1, &mVaoHandle);
}
......@@ -22,6 +22,7 @@ class Renderer {
private:
GLint mColorHandle = 0;
GLuint mVbos[2]{};
GLuint mVaoHandle = 0;
std::unique_ptr<CVK::ShaderSet> mShaderProgram;
};
......
#include "BSpline.h"
#include <cmath>
BSpline::BSpline(std::vector<glm::vec3> cpoints, int k)
: mControlPoints(std::move(cpoints)), mK(k) {}
BSpline::~BSpline() = default;
glm::vec3 BSpline::evaluate(float t) {
// Aufgabe 5 (c)
// accumulate weighted points
glm::vec3 result(0.0f);
for (int i = 0; i < mControlPoints.size(); i++) {
result += coxDeBoor(t, i, mK) * mControlPoints[i];
}
return result;
}
float BSpline::coxDeBoor(float t, int i, int k) {
// Aufgabe 5 (d)
if (k == 1) {
return mKnotVector[i] <= t && t < mKnotVector[i + 1] ? 1.0f : 0.0f;
}
float denom1 = mKnotVector[i + k - 1] - mKnotVector[i];
float denom2 = mKnotVector[i + k] - mKnotVector[i + 1];
float num1 = (t - mKnotVector[i]) * coxDeBoor(t, i, k - 1);
float num2 = (mKnotVector[i + k] - t) * coxDeBoor(t, i + 1, k - 1);
float s1 = std::abs(denom1) < 1E-7 ? 0 : num1 / denom1;
float s2 = std::abs(denom2) < 1E-7 ? 0 : num2 / denom2;
return s1 + s2;
}
void BSpline::setK(int val) { mK = val; }
int BSpline::getK() const { return mK; }
std::vector<glm::vec3>& BSpline::getVertices() { return mVertices; }
std::vector<glm::vec3>& BSpline::getControlPoints() { return mControlPoints; }
#ifndef BSPLINE_H
#define BSPLINE_H
#include <glm/glm.hpp>
#include <iostream>
#include <list>
#include <vector>
class BSpline {
public:
BSpline(std::vector<glm::vec3> cpoints, int k);
virtual ~BSpline();
virtual bool initialize(int num) = 0;
void setK(int val);
int getK() const;
std::vector<glm::vec3>& getVertices();
std::vector<glm::vec3>& getControlPoints();
protected:
float coxDeBoor(float t, int i, int k);
glm::vec3 evaluate(float t);
std::vector<glm::vec3> mControlPoints;
std::vector<glm::vec3> mVertices;
std::vector<float> mKnotVector;
int mK;
};
#endif
\ No newline at end of file
cmake_minimum_required(VERSION 2.8)
include(${CMAKE_MODULE_PATH}/DefaultExecutable.cmake)
\ No newline at end of file
#include "OpenBSpline.h"
// for std::iota
#include <numeric>
// for std::is_sorted
#include <algorithm>
bool OpenBSpline::initialize(int num) {
auto n = mControlPoints.size();
// check correct size
if (mKnotVector.size() != mK + n) {
return false;
}
// check if values are in increasing order
// alternatively, loop yourself
if (!std::is_sorted(mKnotVector.begin(), mKnotVector.end())) {
return false;
}
// min param
float min_t = mKnotVector[mK - 1];
float max_t = mKnotVector[n];
float d_t = max_t - min_t;
// generate points
mVertices.resize(num);
for (int i = 0; i < num; i++) {
// t value sampled in valid interval
auto t = min_t + d_t * static_cast<float>(i) / static_cast<float>(num);
mVertices[i] = evaluate(t);
}
return true;
}
OpenBSpline::OpenBSpline(std::vector<glm::vec3> cpoints, int k, int num)
: BSpline(std::move(cpoints), k) {
// number of knots in knot vector is n + k
auto n = mControlPoints.size();
auto nk = n + k;
mKnotVector.resize(nk);
// first n values are 0
std::fill(mKnotVector.begin(), mKnotVector.begin() + k, 0);
std::iota(mKnotVector.begin() + k, mKnotVector.begin() + n, 1);
std::fill(mKnotVector.begin() + n, mKnotVector.end(), n - k + 1);
initialize(num);
}
#ifndef OPENBSPLINE_H
#define OPENBSPLINE_H
#include "BSpline.h"
class OpenBSpline : public BSpline {
public:
OpenBSpline(std::vector<glm::vec3> cpoints, int k, int num);
bool initialize(int num) override;
};
#endif // OPENBSPLINE_H
#include "PeriodicBSpline.h"
// for std::iota
#include <numeric>
// for std::is_sorted
#include <algorithm>
PeriodicBSpline::PeriodicBSpline(std::vector<glm::vec3> cpoints, int k, int num)
: BSpline(std::move(cpoints), k) {
// Aufgabe 5 (a)
// number of knots in knot vector is n + k
auto n = mControlPoints.size();
auto nk = n + k;
mKnotVector.resize(nk);
// periodic b-spline has increasing number of values
// std::iota fills vector with increasing values starting at the last
// argument.
// Alternatively loop over size
std::iota(mKnotVector.begin(), mKnotVector.end(), 0);
initialize(num);
}
PeriodicBSpline::~PeriodicBSpline() = default;
bool PeriodicBSpline::initialize(int num) {
// Aufgabe 5 (b)
auto n = mControlPoints.size();
// check correct size
if (mKnotVector.size() != mK + n) {
return false;
}
// check if values are in increasing order
// alternatively, loop yourself
if (!std::is_sorted(mKnotVector.begin(), mKnotVector.end())) {
return false;
}
// min param
float min_t = mKnotVector[mK - 1];
float max_t = mKnotVector[n];
float d_t = max_t - min_t;
// generate points
mVertices.resize(num);
for (int i = 0; i < num; i++) {
// t value sampled in valid interval
auto t = min_t + d_t * static_cast<float>(i) / static_cast<float>(num);
mVertices[i] = evaluate(t);
}
return true;
}
\ No newline at end of file
#ifndef PERIODICBSPLINE_H
#define PERIODICBSPLINE_H
#include "BSpline.h"
class PeriodicBSpline : public BSpline {
public:
PeriodicBSpline(std::vector<glm::vec3> cpoints, int k, int num);
~PeriodicBSpline() override;
bool initialize(int num) override;
};
#endif
#include "Renderer.h"
#include <CVK_2/CVK_Framework.h>
#include <memory>
GLFWwindow* Renderer::initialize(int width, int height) {
glfwInit();
CVK::useOpenGL33CoreProfile();
GLFWwindow* window =
glfwCreateWindow(width, height, "BSpline", nullptr, nullptr);
glfwSetWindowPos(window, 600, 50);
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize OpenGL context" << std::endl;
return nullptr;
}
glClearColor(1, 1, 1, 1);
// compile a shader program
mShaderProgram = std::make_unique<CVK::ShaderSet>(
VERTEX_SHADER_BIT | FRAGMENT_SHADER_BIT,
std::vector<std::string>{CVK::State::getInstance()->getShaderPath() +
"/BSplines/bsplines.vert",
CVK::State::getInstance()->getShaderPath() +
"/BSplines/bsplines.frag"});
// use the shader program
mShaderProgram->useProgram();
mColorHandle =
glGetUniformLocation(mShaderProgram->getProgramID(), "color");
glGenVertexArrays(1, &mVaoHandle);
glBindVertexArray(mVaoHandle);
glGenBuffers(2, mVbos);
return window;
}
void Renderer::render(BSpline& spline) {
glm::vec3 black = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 red = glm::vec3(1.0f, 0.0f, 0.0f);
// draw control points
glPointSize(15.0f);
glUniform3fv(mColorHandle, 1, glm::value_ptr(black));
glBindBuffer(GL_ARRAY_BUFFER, mVbos[0]);
glBufferData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * spline.getControlPoints().size(),
spline.getControlPoints().data(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_POINTS, 0, spline.getControlPoints().size());
// draw curve points
glPointSize(5.0f);
glUniform3fv(mColorHandle, 1, glm::value_ptr(red));
glBindBuffer(GL_ARRAY_BUFFER, mVbos[1]);
glBufferData(GL_ARRAY_BUFFER,
sizeof(glm::vec3) * spline.getVertices().size(),
spline.getVertices().data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_LINE_STRIP, 0, spline.getVertices().size());
// unbind the VBO, we don't need it anymore
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
Renderer::~Renderer() {
glDeleteBuffers(2, mVbos);
glDeleteVertexArrays(1, &mVaoHandle);
}
#ifndef RENDERER_H
#define RENDERER_H
#include "BSpline.h"
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <CVK_2/CVK_ShaderSet.h>
#include <memory>
class Renderer {
public:
Renderer() = default;
virtual ~Renderer();
GLFWwindow* initialize(int width, int height);
void render(BSpline& spline);
private:
GLint mColorHandle = 0;
GLuint mVbos[2]{};
GLuint mVaoHandle = 0;
std::unique_ptr<CVK::ShaderSet> mShaderProgram;
};
#endif
#include "OpenBSpline.h"
#include "PeriodicBSpline.h"
#include "Renderer.h"
std::vector<glm::vec3> cpoints; // controlpoints
int num_samples = 1000; // number of vertices
int k = 5; // order
const int width = 800; // window width
const int height = 800; // window height
int drawType = 0;
void keyfun(GLFWwindow*, int key, int, int action, int) {
if (key == GLFW_KEY_N && action == GLFW_PRESS) {
drawType = (drawType + 1) % 2;
}
}
int main() {
// create control points
cpoints.emplace_back(-0.5, -0.25, 0.0);
cpoints.emplace_back(0.0, 0.5, 0.0);
cpoints.emplace_back(0.5, -0.25, 0.0);
cpoints.emplace_back(0.75, -0.75, 0.0);
cpoints.emplace_back(-0.75, -0.75, 0.0);
PeriodicBSpline p_spline(cpoints, k, num_samples);
OpenBSpline o_spline(cpoints, k, num_samples);
GLFWwindow* window = nullptr;
{
// render stuff
// Renderer lives only in this block and will clean up when it is
// destroyed
Renderer renderer;
window = renderer.initialize(width, height);
glfwSetKeyCallback(window, keyfun);
if (window == nullptr) {
std::cerr << "error initializing opengl" << std::endl;
return -1;
}
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (drawType == 0) {
renderer.render(p_spline);
} else {
renderer.render(o_spline);
}
// show what's been drawn
glfwSwapBuffers(window);
glfwPollEvents();
}
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment