Spline scene

This commit is contained in:
ao 2018-10-08 10:12:21 +02:00
parent 08e3667ffb
commit 89a19a6ab6
7 changed files with 262 additions and 2 deletions

View File

@ -0,0 +1,175 @@
#include "hellospline.h"
#include "bspline.h"
#include <iostream>
//#define deg2rad(x) float(M_PI)*(x)/180.f
// CTOR
SimpleSpline::SimpleSpline(int width, int height, MainWindow* w) : Scene(width, height, w), _activecamera(0), _camera(nullptr)
{
// Initialize last shaders
_lastVertex = _w->vertexShader;
_lastFragment = _w->fragmentShader;
// LOAD B-SPLINE
std::cout << "Vertices count: " << _vertices.size() / 3 << std::endl;
std::cout << "Edges count: " << _indices.size() << std::endl;
std::cout << "Triangles count: " << _indices.size() / 3 << std::endl;
// 1. Generate geometry buffers
glGenBuffers(1, &_vbo) ;
glGenBuffers(1, &_nbo) ;
glGenBuffers(1, &_ebo) ;
glGenVertexArrays(1, &_vao) ;
// 2. Bind Vertex Array Object
glBindVertexArray(_vao);
// 3. Copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, _vertices.size()*sizeof (GLfloat), _vertices.data(), GL_STATIC_DRAW);
// 4. Then set our vertex attributes pointers
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// 5. Copy our normals array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, _nbo);
glBufferData(GL_ARRAY_BUFFER, _normals.size()*sizeof (GLfloat), _normals.data(), GL_STATIC_DRAW);
// 6. Copy our vertices array in a buffer for OpenGL to use
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
// 7. Copy our index array in a element buffer for OpenGL to use
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size()*sizeof (GLfloat), _indices.data(), GL_STATIC_DRAW);
//6. Unbind the VAO
glBindVertexArray(0);
// Camera Initialization
_cameraselector.push_back( []()->Camera*{return new EulerCamera(glm::vec3(0.f, 0.f, 1.f));} );
_cameraselector.push_back( []()->Camera*{return new TrackballCamera(glm::vec3(0.f, 0.f, 1.f),glm::vec3(0.f, 1.f, 0.f),glm::vec3(0.f, 0.f, 0.f));} );
_camera.reset(_cameraselector[_activecamera]());
_camera->setviewport(glm::vec4(0.f, 0.f, _width, _height));
_view = _camera->viewmatrix();
_projection = glm::perspective(_camera->zoom(), float(_width) / _height, 0.1f, 100.0f);
generateProgram();
glUseProgram(_program);
}
SimpleSpline::~SimpleSpline() {}
void SimpleSpline::resize(int width, int height){
Scene::resize(width, height);
_camera->setviewport(glm::vec4(0.f, 0.f, _width, _height));
}
void SimpleSpline::draw() {
// Set OpenGL Render Mode
Scene::draw();
// Recompute program, but using pipeline should be better
if(_lastVertex != _w->vertexShader || _lastFragment != _w->fragmentShader) {
generateProgram();
glUseProgram(_program);
}
/* Uniforms
glUniform3f(glGetUniformLocation(_program, "center"), 0.0f, 0.0f, 0.0f);
glUniform1f(glGetUniformLocation(_program, "radius"), _radius);
glUniform1f(glGetUniformLocation(_program, "errorMax"), _errorMax);
*/
glUniform3f(glGetUniformLocation(_program, "cameraView"), _camera->_front.x, _camera->_front.y, _camera->_front.z);
// Camera
_view = _camera->viewmatrix();
glUniformMatrix4fv( glGetUniformLocation(_program, "model"), 1, GL_FALSE, glm::value_ptr(_model));
glUniformMatrix4fv( glGetUniformLocation(_program, "view"), 1, GL_FALSE, glm::value_ptr(_view));
glUniformMatrix4fv( glGetUniformLocation(_program, "projection"), 1, GL_FALSE, glm::value_ptr(_projection));
// Draw the shape
glBindVertexArray(_vao);
glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
void SimpleSpline::mouseclick(int button, float xpos, float ypos) {
_button = button;
_mousex = xpos;
_mousey = ypos;
_camera->processmouseclick(_button, xpos, ypos);
}
void SimpleSpline::mousemove(float xpos, float ypos) {
_camera->processmousemovement(_button, xpos, ypos, true);
}
void SimpleSpline::keyboardmove(int key, double time) {
_camera->processkeyboard(Camera_Movement(key), time);
}
bool SimpleSpline::keyboard(unsigned char k) {
switch(k) {
case 'p':
_activecamera = (_activecamera+1)%2;
_camera.reset(_cameraselector[_activecamera]());
_camera->setviewport(glm::vec4(0.f, 0.f, _width, _height));
return true;
default:
return false;
}
}
void SimpleSpline::generateProgram() {
// Change last shader variables
_lastVertex = _w->vertexShader;
_lastFragment = _w->fragmentShader;
// Initialize shaders
GLint success;
GLchar infoLog[512]; // warning fixed size ... request for LOG_LENGTH!!!
GLuint vertexshader, fragmentshader;
/* VERTEX SHADER */
// 1. Generate the shader
vertexshader = glCreateShader(GL_VERTEX_SHADER);
// 2. set the source
auto pointerVertex = _w->vertexShaders[_w->vertexShader].c_str();
glShaderSource(vertexshader, 1, &pointerVertex, NULL);
// 3. Compile
glCompileShader(vertexshader);
// 4. test for compile error
glGetShaderiv(vertexshader, GL_COMPILE_STATUS, &success);
if(!success) {
glGetShaderInfoLog(vertexshader, 512, NULL, infoLog);
std::cerr << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
/* FRAGMENT SHADER */
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
auto pointerFragment = _w->fragmentShaders[_w->fragmentShader].c_str();
glShaderSource(fragmentshader, 1, &pointerFragment, NULL);
glCompileShader(fragmentshader);
glGetShaderiv(fragmentshader, GL_COMPILE_STATUS, &success);
if(!success) {
glGetShaderInfoLog(fragmentshader, 512, NULL, infoLog);
std::cerr << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
/* Program Object */
// 1. Generate the program
_program = glCreateProgram();
// 2. Attach the shaders to the program
glAttachShader(_program, vertexshader);
glAttachShader(_program, fragmentshader);
// 3. Link the program
glLinkProgram(_program);
// 4. Test for link errors
glGetProgramiv(_program, GL_LINK_STATUS, &success);
if(!success) {
glGetProgramInfoLog(_program, 512, NULL, infoLog);
std::cerr << "ERROR::SHADER::LINK_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexshader);
glDeleteShader(fragmentshader);
}

View File

@ -0,0 +1,71 @@
#ifndef HELLOSPLINE_H
#define HELLOSPLINE_H
#include "scene.h"
#include "hello_camera/camera.h"
#include "mainwindow.h"
#include <memory>
#include <functional>
/** Simple drawing demonstration
*/
class SimpleSpline : public Scene {
public:
explicit SimpleSpline(int width, int height, MainWindow* w);
~SimpleSpline();
void resize(int width, int height) override;
void draw() override;
void mouseclick(int button, float xpos, float ypos) override;
void mousemove(float xpos, float ypos) override;
void keyboardmove(int key, double time) override;
bool keyboard(unsigned char k) override;
public slots:
void generateProgram();
private:
// A simple geometry
std::vector<GLfloat> _vertices;
std::vector<GLfloat> _normals;
std::vector<GLuint> _indices;
// OpenGL object for geometry
GLuint _vao;
GLuint _vbo;
GLuint _nbo;
GLuint _ebo;
// Shader program for rendering
QString _lastVertex;
QString _lastFragment;
GLuint _program;
// for mouse management
int _button; // 0 --> left. 1 --> right. 2 --> middle. 3 --> other
float _mousex{0};
float _mousey{0};
// Camera
using CameraSelector=std::function<Camera*()>;
std::vector<CameraSelector> _cameraselector;
int _activecamera;
std::unique_ptr<Camera> _camera;
// Matrices
glm::mat4 _model;
glm::mat4 _view;
glm::mat4 _projection;
/* Shape Methods
void drawCube(float size = 0.1f);
void drawUVSphere(int resolution = 5, float radius = 0.5f);
void drawIcoSphere(int resolution = 5, float radius = 0.f);
float _radius = 0.5f;
float _errorMax = 0.0f;
*/
};
#endif // SIMPLESPLINE_H

View File

@ -52,6 +52,10 @@ void MainWindow::on_actionHello_spheres_triggered() {
ui->openglWidget->activatedemo(3);
}
void MainWindow::on_actionHello_spline_triggered() {
ui->openglWidget->activatedemo(4);
}
void MainWindow::on_actionToggle_Back_Face_Culling_triggered(bool checked)
{
culling = checked;

View File

@ -29,6 +29,7 @@ private slots:
void on_actionHello_triangle_triggered();
void on_actionHello_camera_triggered();
void on_actionHello_spheres_triggered();
void on_actionHello_spline_triggered();
void on_actionHello_clear_triggered();
void on_actionToggle_Back_Face_Culling_triggered(bool checked);

View File

@ -27,7 +27,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>25</height>
<height>24</height>
</rect>
</property>
<widget class="QMenu" name="menuInfo">
@ -44,6 +44,7 @@
<addaction name="actionHello_triangle"/>
<addaction name="actionHello_camera"/>
<addaction name="actionHello_spheres"/>
<addaction name="actionHello_spline"/>
</widget>
<widget class="QMenu" name="menuShaders">
<property name="title">
@ -101,6 +102,11 @@
<string>Toggle backface culling</string>
</property>
</action>
<action name="actionHello_spline">
<property name="text">
<string>Hello splines ...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

View File

@ -10,6 +10,7 @@
#include "hello_triangles/hellotriangles.h"
#include "hello_camera/hellocamera.h"
#include "hello_spheres/hellosphere.h"
#include "hello_spline/hellospline.h"
MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) :QOpenGLWidget(parent), QOpenGLFunctions_4_1_Core(), _scene(nullptr), _lastime(0) {
@ -18,6 +19,7 @@ MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) :QOpenGLWidget(parent), QOpenGLF
_democonstructors.push_back( [](int width, int height, MainWindow* w)->Scene*{std::cout << "Hello triangles ..." << std::endl; return new SimpleTriangle(width, height, w);} );
_democonstructors.push_back( [](int width, int height, MainWindow* w)->Scene*{std::cout << "Hello camera ..." << std::endl; return new SimpleCamera(width, height, w);} );
_democonstructors.push_back( [](int width, int height, MainWindow* w)->Scene*{std::cout << "Hello sphere ..." << std::endl; return new SimpleSphere(width, height, w);} );
_democonstructors.push_back( [](int width, int height, MainWindow* w)->Scene*{std::cout << "Hello spline ..." << std::endl; return new SimpleSpline(width, height, w);} );
}
MyOpenGLWidget::~MyOpenGLWidget() {
@ -30,7 +32,7 @@ void MyOpenGLWidget::initializeGL() {
exit(1);
}
// Initialize OpenGL and all OpenGL dependent stuff below
_scene.reset(_democonstructors[3](width(), height(), (MainWindow*) this->parent()));
_scene.reset(_democonstructors[4](width(), height(), (MainWindow*) this->parent()));
}
void MyOpenGLWidget::paintGL() {

View File

@ -5,6 +5,7 @@
Scene::Scene(int width, int height, MainWindow* w) : _width(width), _height(height), _w(w), _drawfill(true) {
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, width, height);
glPointSize(5.0f);
}
Scene::~Scene() {