mpri-graphics-project/render/GlutRender.cpp

200 lines
5.8 KiB
C++
Raw Normal View History

#include "GlutRender.hpp"
2018-02-12 18:40:05 +01:00
#include "../MarchingCubes.hpp"
#include <GL/gl.h>
#include <GL/glut.h>
#include <cstring>
#include <random>
#include <ctime>
GlutRender& GlutRender::get_instance() {
static GlutRender instance;
return instance;
}
2018-02-12 18:40:05 +01:00
GlutRender::GlutRender() {
std::default_random_engine rand_engine(time(NULL));
std::uniform_real_distribution<double> distribution;
rand_color = std::bind(distribution, rand_engine);
}
void GlutRender::init(int* argc, char** argv,
int wid, int hei, const char* win_name)
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(wid, hei);
glutCreateWindow(win_name);
// ==== Callbacks ====
glutDisplayFunc(display_handle);
glutReshapeFunc(reshape_handle);
2018-02-06 19:10:08 +01:00
// ==== Lighting ====
GLfloat light0_pos[] = {2., 10., 2.};
GLfloat light0_ambient[] = {0., 0., 0., 1.};
GLfloat light0_diffuse[] = {1., 1., 1., 1.};
GLfloat light0_specular[] = {1., 1., 1., 1.};
glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
2018-02-06 19:10:08 +01:00
GLfloat light_ambient[] = {.2, .2, .2, 1.};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH); // Enable smooth shading
GLfloat material_specular[] = {1., 1., 1., 1.};
GLfloat material_emission[] = {0., 0., 0., 1.};
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material_emission);
glEnable(GL_COLOR_MATERIAL);
// ==== Misc ====
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Background color
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void GlutRender::cleanup() {
}
2018-02-06 21:05:45 +01:00
void GlutRender::add_mesh(Mesh* mesh) {
meshes.insert(mesh);
}
2018-02-06 21:05:45 +01:00
void GlutRender::remove_mesh(Mesh* mesh) {
meshes.erase(mesh);
}
2018-02-12 18:40:05 +01:00
void GlutRender::add_surface(ImplicitSurface* surf, const Cuboid& box) {
surfaces.insert(SurfaceDetails(surf, box));
}
void GlutRender::remove_surface(ImplicitSurface* surf) {
surfaces.erase(SurfaceDetails(surf, Cuboid::empty()));
}
void GlutRender::run() {
2018-02-06 19:10:08 +01:00
glutMainLoop();
}
2018-02-12 18:40:05 +01:00
void GlutRender::set_idle_func(void (*func)(void)) {
glutIdleFunc(func);
}
void GlutRender::reshape(int wid, int hei) {
2018-02-06 22:15:35 +01:00
if (hei == 0)
2018-02-06 19:10:08 +01:00
hei = 1;
2018-02-06 22:15:35 +01:00
GLfloat aspect = (GLfloat)wid / (GLfloat)hei;
2018-02-06 19:10:08 +01:00
2018-02-06 22:15:35 +01:00
glViewport(0, 0, wid, hei);
2018-02-06 19:10:08 +01:00
2018-02-06 22:15:35 +01:00
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Enable perspective projection with fovy, aspect, zNear and zFar
gluPerspective(45.0f, aspect, 0.1f, 100.0f);
}
2018-02-13 14:25:08 +01:00
void GlutRender::display_mesh(Mesh& mesh) const {
2018-02-12 18:40:05 +01:00
const Point& mesh_center = mesh.get_center();
const std::vector<Point>& points = mesh.get_vertices();
2018-02-13 14:47:34 +01:00
#ifdef DEBUG_DISPLAY_NORMAL
glBegin(GL_LINES);
for(size_t vert_id=0; vert_id < points.size(); ++vert_id) {
const Point& pt = points[vert_id];
Point normal = mesh.get_normal(vert_id);
Point locVert = pt + mesh.get_center();
Point outwards = locVert + normal;
Point inwards = locVert + ((-0.2) * normal);
glColor3f(1., 0., 0.);
glVertex3f(locVert[0], locVert[1], locVert[2]);
glVertex3f(outwards[0], outwards[1], outwards[2]);
glColor3f(0., 0., 1.);
glVertex3f(locVert[0], locVert[1], locVert[2]);
glVertex3f(inwards[0], inwards[1], inwards[2]);
}
glEnd();
#endif // DEBUG_DISPLAY_NORMAL
#ifdef DEBUG_DISPLAY_WIREFRAME
glBegin(GL_LINES);
for(const Face& face: mesh.get_faces()) {
Point n0 = mesh.get_normal(face[0]),
n1 = mesh.get_normal(face[1]),
n2 = mesh.get_normal(face[2]);
Point p0 = face.pt(0, points) + mesh_center + 0.01 * n0,
p1 = face.pt(1, points) + mesh_center + 0.01 * n1,
p2 = face.pt(2, points) + mesh_center + 0.01 * n2;
glColor3f(0., 1., 0.);
glVertex3f(p0[0], p0[1], p0[2]);
glVertex3f(p1[0], p1[1], p1[2]);
glVertex3f(p1[0], p1[1], p1[2]);
glVertex3f(p2[0], p2[1], p2[2]);
glVertex3f(p2[0], p2[1], p2[2]);
glVertex3f(p0[0], p0[1], p0[2]);
}
glEnd();
#endif // DEBUG_DISPLAY_WIREFRAME
2018-02-13 14:47:34 +01:00
2018-02-12 18:40:05 +01:00
glBegin(GL_TRIANGLES);
glColor3f(1., 1., 1.);
2018-02-12 18:40:05 +01:00
for(const Face& face: mesh.get_faces()) {
Point p0 = face.pt(0, points) + mesh_center,
p1 = face.pt(1, points) + mesh_center,
p2 = face.pt(2, points) + mesh_center;
2018-02-13 14:25:08 +01:00
Point n0 = mesh.get_normal(face[0]),
n1 = mesh.get_normal(face[1]),
n2 = mesh.get_normal(face[2]);
2018-02-12 18:40:05 +01:00
glColor3f(rand_color(), rand_color(), rand_color());
2018-02-13 14:25:08 +01:00
glNormal3f(n0[0], n0[1], n0[2]); glVertex3f(p0[0], p0[1], p0[2]);
glNormal3f(n1[0], n1[1], n1[2]); glVertex3f(p1[0], p1[1], p1[2]);
glNormal3f(n2[0], n2[1], n2[2]); glVertex3f(p2[0], p2[1], p2[2]);
2018-02-12 18:40:05 +01:00
}
glEnd();
}
void GlutRender::display() {
2018-02-06 22:15:35 +01:00
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
2018-02-06 19:10:08 +01:00
2018-02-06 21:05:45 +01:00
// Camera position and orientation
glLoadIdentity();
2018-02-12 18:40:05 +01:00
//glTranslatef(1., 2., -10.);
gluLookAt(0, 5, -20,
0, 5, 0,
2018-02-12 18:40:05 +01:00
0, 1, 0);
2018-02-06 21:05:45 +01:00
for(Mesh* mesh: meshes) {
2018-02-12 18:40:05 +01:00
display_mesh(*mesh);
}
for(const SurfaceDetails& surface: surfaces) {
Mesh mesh = MarchingCubes(*surface.surface, surface.box)();
display_mesh(mesh);
}
2018-02-06 19:10:08 +01:00
2018-02-06 22:15:35 +01:00
glutSwapBuffers();
}
void GlutRender::reshape_handle(int wid, int hei) {
get_instance().reshape(wid, hei);
}
void GlutRender::display_handle() {
get_instance().display();
}