first step in the rendering process, we can display a sphere

This commit is contained in:
Anselme 2015-06-29 08:40:11 +02:00
parent 61c6f97da3
commit b6c9377268
10 changed files with 184 additions and 21 deletions

View File

@ -26,8 +26,8 @@ void Camera::computeProjectionMatrix()
void Camera::computeViewMatrix()
{
m_viewMatrix = glm::rotate(glm::mat4(), m_rotation.y, glm::vec3(0, 1, 0));
m_viewMatrix = glm::rotate(m_viewMatrix, m_rotation.x, glm::vec3(1, 0, 0));
m_viewMatrix = glm::rotate(glm::mat4(), m_rotation.y, glm::vec3(1, 0, 0));
m_viewMatrix = glm::rotate(m_viewMatrix, m_rotation.x, glm::vec3(0, 1, 0));
m_viewMatrix = glm::translate(m_viewMatrix, -m_position);
m_viewHasChanged = false;
}
@ -85,8 +85,7 @@ void Camera::lookAt(glm::vec3 position)
glm::vec3 delta = position - m_position;
glm::normalize(delta);
m_rotation.y = std::asin(delta.y);
m_rotation.x = std::acos(delta.z/std::acos(delta.y));
if(delta.z < 0) m_rotation.x += M_PI;
m_rotation.x = std::atan2(delta.z, delta.x);
}
void Camera::lookAt(glm::vec2 rotation)

View File

@ -8,7 +8,7 @@ Mesh::~Mesh()
destroyGL();
}
void Mesh::addVertex(Vertex& v)
void Mesh::addVertex(const Vertex& v)
{
if(!locked)
vertices.push_back(v);

4
mesh.h
View File

@ -16,14 +16,14 @@ public:
} Vertex;
~Mesh();
void addVertex(Vertex& v);
void addVertex(const Vertex& v);
void addFace(int i1, int i2, int i3);
void initGL();
void destroyGL();
void draw();
bool isLocked(){return locked;}
private:
protected:
enum {VERTEX_BUFFER, INDICES_BUFFER, NB_BUFFERS};
std::vector<Vertex> vertices;

View File

@ -3,7 +3,7 @@
#include "scene.h"
#include "glassert.h"
#include "camera.h"
#include "gridmesh.h"
#include "sphere.h"
#include "phongmaterial.h"
#include <iostream>
#include <glm/glm.hpp>
@ -55,8 +55,11 @@ void MyGLWidget::initializeGL()
void MyGLWidget::buildScene()
{
scene = new Scene();
scene->setCamera(new Camera(width(), height()));
Mesh* myGrid = new GridMesh(2, 2, false);
Camera* cam = new Camera(width(), height());
cam->moveTo(glm::vec3(-1, 0, 0));
cam->lookAt(glm::vec3(0, 0, 0));
scene->setCamera(cam);
Mesh* myGrid = new Sphere(2);
myGrid->initGL();
Shader* shader = new Shader(QString("../phong.vert"), QString("../phong.frag"));
Material* mat = new PhongMaterial(shader);
@ -79,28 +82,30 @@ void MyGLWidget::paintGL()
void MyGLWidget::mouseMoveEvent(QMouseEvent *e)
{
static QPoint* last = NULL;
if(last == NULL)
last = new QPoint(e->pos().x(), e->pos().y());
else
controller.mouseMove(e->pos().x() - last->x(), e->pos().y() - last->y());
*last = e->pos();
controller.mouseMove(e->pos().x() - last.x(), e->pos().y() - last.y());
last = e->pos();
updateGL();
}
void MyGLWidget::mousePressEvent(QMouseEvent* e)
{
controller.mouseEvent(e->button(), true);
last = e->pos();
updateGL();
}
void MyGLWidget::mouseReleaseEvent(QMouseEvent* e)
{
controller.mouseEvent(e->button(), false);
updateGL();
}
void MyGLWidget::keyPressEvent(QKeyEvent *e)
{
controller.mouseEvent(e->key(), true);
updateGL();
}
void MyGLWidget::keyReleaseEvent(QKeyEvent *e)
{
controller.mouseEvent(e->key(), false);
updateGL();
}

View File

@ -16,6 +16,7 @@ class MyGLWidget : public QGLWidget
Scene* scene;
SceneController controller;
QPoint last;
public:
explicit MyGLWidget(QWidget *parent = 0);

View File

@ -10,12 +10,32 @@ void SceneController::setScene(Scene* myScene)
void SceneController::mouseMove(int dx, int dy)
{
switch(grabbed)
{
case 1:
camera->rotate(glm::vec2(dx*3.14f/180, dy*3.14f/180));
break;
case 2:
camera->translate(glm::vec3(dx*0.01f, dy*0.01f, 0));
camera->lookAt(glm::vec3(0, 0, 0));
break;
default:
break;
}
}
void SceneController::mouseEvent(int button, bool state)
{
switch (button) {
case Qt::LeftButton:
grabbed += state ? 1 : -1;
break;
case Qt::RightButton:
grabbed += state ? 2 : -2;
break;
default:
break;
}
}
void SceneController::keyEvent(int key, bool state)

View File

@ -1,7 +1,7 @@
#ifndef SCENECONTROLLER_H
#define SCENECONTROLLER_H
#include <QObject>
#include <cstddef>
class Scene;
class Camera;
@ -10,7 +10,10 @@ class SceneController
{
Camera* camera;
Scene* scene;
int grabbed;
public:
SceneController() : camera(NULL), scene(NULL), grabbed(0) {}
void setScene(Scene* myScene);
void mouseMove(int dx, int dy);
void mouseEvent(int button, bool state);

View File

@ -29,7 +29,8 @@ SOURCES += main.cpp\
gridmesh.cpp \
texture.cpp \
phongmaterial.cpp \
scenecontroller.cpp
scenecontroller.cpp \
sphere.cpp
HEADERS += mainwindow.h \
myglwidget.h \
@ -42,7 +43,8 @@ HEADERS += mainwindow.h \
gridmesh.h \
texture.h \
phongmaterial.h \
scenecontroller.h
scenecontroller.h \
sphere.h
FORMS += mainwindow.ui

108
sphere.cpp Normal file
View File

@ -0,0 +1,108 @@
#include "sphere.h"
#define M_PI 3.14159265358979323846
#define MAGIC_RATIO 0.37139f
Sphere::Sphere(int n)
{
// icosahedron :
// top cap
createVertex(0, 1);
for(int i=0; i<5; i++)
createVertex(i/5.f, 1-MAGIC_RATIO);
// bottom cap
createVertex(0, 0);
for(int i=0; i<5; i++)
createVertex((i+0.5f)/5.f, MAGIC_RATIO);
// Compute faces
for(int i=0; i<5; i++){
int top = 1;
int bottom = 7;
int offset = (i+1)%5;
// top cap
addFace(0, top+i, top+offset);
// bottom cap
addFace(6, bottom+i, bottom+offset);
// middle ribbon
addFace(bottom+i, top+offset, top+i);
addFace(top+offset, bottom+offset, bottom+i);
}
// geodesic subdivisions :
for(int i=0; i<n; i++){
edges = new Edge[vertices.size()-1];
int nb_triangles = indices.size()/3;
for(int j=0; j<nb_triangles; j++)
{
int vid[3];
for(int k=0; k<3; k++)
{
int idA = indices[j*3 + k];
int idB = indices[j*3 + (k+1)%3];
int a = idA < idB ? idA : idB;
int b = idA > idB ? idA : idB;
vid[k] = getEdge(a, b);
}
for(int k=0; k<3; k++)
addFace(indices[j*3 + k], vid[k], vid[(k+2)%3]);
addFace(vid[0], vid[1], vid[2]);
}
delete[](edges);
indices.erase(indices.begin(), indices.begin()+nb_triangles*3);
}
}
int Sphere::getEdge(int a, int b)
{
Edge* current = edges+a;
int vid = -1;
while(vid == -1)
{
if(current->b == b)
vid = current->vertex;
else if(current->next == NULL)
{
// creating subdivision vertex
Vertex v;
Vertex v0 = vertices[a];
Vertex v1 = vertices[b];
v.position = glm::normalize((v0.position + v1.position)/2.f);
v.normal = v.position;
// u/v sphériques, cohérents sur toute la sphère sauf des artefacts au niveau des u==0
float newU = (v.position.x < 0 ? 1.5f : 1.f) + atan(v.position.z/v.position.x)/(2*M_PI);
float newV = acos(v.position.y)/M_PI;
v.texCoord = glm::vec2(newU - floor(newU), newV);
// alternative, u/v moyennés :
//v.texcoord_ = (v0.texcoord_ + v1.texcoord_)/2.f;
vid = vertices.size();
addVertex(v);
// inserting the new vertex in the edge collection
if(current->b == -1)
{
current->vertex = vid;
current->b = b;
}
else
current->next = new Edge(b, vid);
}
else
current = current->next;
}
return vid;
}
void Sphere::createVertex(float u, float v)
{
Vertex vert;
vert.position = glm::vec3(cos(u*2*M_PI)*sin(v*M_PI),
cos(v*M_PI),
sin(u*2*M_PI)*sin(v*M_PI));
vert.normal = vert.position;
vert.texCoord = glm::vec2(u, v);
addVertex(vert);
}

25
sphere.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef SPHERE_H
#define SPHERE_H
#include "mesh.h"
class Sphere : public Mesh
{
private:
class Edge{
public:
int b;
int vertex;
Edge* next;
Edge(int myB = -1, int myVertex = -1):b(myB),vertex(myVertex),next(NULL){}
~Edge(){ if(next != NULL) delete(next); }
};
Edge* edges;
int getEdge(int a, int b);
void createVertex(float u, float v);
public:
Sphere(int n = 0);
};
#endif // SPHERE_H