#include "GlutRender.hpp" #include "../MarchingCubes.hpp" #include #include #include #include #include GlutRender& GlutRender::get_instance() { static GlutRender instance; return instance; } GlutRender::GlutRender() : followed_implicit(nullptr), camera_position(0., 2.5, -10.), camera_sight(0, 2.5, 0) { std::default_random_engine rand_engine(time(NULL)); std::uniform_real_distribution 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); glutKeyboardFunc(kb_evt_handle); glutKeyboardUpFunc(kb_evt_up_handle); // ==== Lighting ==== GLfloat light0_pos[] = {30., 35., 20., 0.}; GLfloat light0_ambient[] = {0., 0., 0., 1.}; GLfloat light0_diffuse[] = {1., 1., .85, 1.}; GLfloat light0_specular[] = {5., 5., .43, 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); 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 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); GLfloat material_specular[] = {1., 1., 1., 1.}; GLfloat material_emission[] = {0., 0., 0., 1.}; 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 glClearColor(0.15f, 0.08f, 0.5f, 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() { } void GlutRender::add_mesh(Mesh* mesh) { meshes.insert(mesh); } void GlutRender::remove_mesh(Mesh* mesh) { meshes.erase(mesh); } void GlutRender::add_surface(ImplicitSurface* surf, const Cuboid& box, double resolution) { surfaces.insert(SurfaceDetails(surf, box, resolution)); } void GlutRender::remove_surface(ImplicitSurface* surf) { surfaces.erase(SurfaceDetails(surf, Cuboid::empty(), 0.1)); } void GlutRender::run() { glutMainLoop(); } void GlutRender::set_idle_func(void (*func)(void)) { glutIdleFunc(func); } void GlutRender::add_kb_handler(GlutRender::kb_handler_t handler) { kb_handlers.push_back(handler); } void GlutRender::add_kb_up_handler(GlutRender::kb_handler_t handler) { kb_up_handlers.push_back(handler); } void GlutRender::follow_implicit_position(const ImplicitSurface* surf) { followed_implicit = surf; } void GlutRender::set_camera(const Point& location, const Point& sight) { camera_position = location; camera_sight = sight; } void GlutRender::reshape(int wid, int hei) { if (hei == 0) hei = 1; GLfloat aspect = (GLfloat)wid / (GLfloat)hei; glViewport(0, 0, wid, hei); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Enable perspective projection with fovy, aspect, zNear and zFar gluPerspective(45.0f, aspect, 0.1f, 100.0f); } void GlutRender::display_mesh(Mesh& mesh) const { const Point& mesh_center = mesh.get_center(); const std::vector& points = mesh.get_vertices(); #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 const Color& color = mesh.get_color(); GLfloat material_specular[] = { (float)color[0], (float)color[1], (float)color[2], 1.}; glBegin(GL_TRIANGLES); glColor3f(color[0], color[1], color[2]); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular); 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; Point n0 = mesh.get_normal(face[0]), n1 = mesh.get_normal(face[1]), n2 = mesh.get_normal(face[2]); 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]); } glEnd(); } void GlutRender::display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); // Camera position and orientation glLoadIdentity(); if(followed_implicit != nullptr) { const Point& look_at = followed_implicit->getCenter(); gluLookAt(camera_position.x, camera_position.y, camera_position.z, look_at.x, camera_position.y, look_at.z, 0, 1, 0); } else { gluLookAt(camera_position.x, camera_position.y, camera_position.z, camera_sight.x, camera_position.y, camera_sight.z, 0, 1, 0); } for(Mesh* mesh: meshes) { display_mesh(*mesh); } for(const SurfaceDetails& surface: surfaces) { Mesh mesh = MarchingCubes(*surface.surface, surface.box, surface.resolution) .add_hint(surface.surface->location_hint()) (); display_mesh(mesh); } glutSwapBuffers(); } void GlutRender::on_kb_evt(bool up, unsigned char key, int x, int y) { std::vector& handlers = up? kb_up_handlers : kb_handlers; for(auto& handler: handlers) { handler(key, x, y); } } void GlutRender::reshape_handle(int wid, int hei) { get_instance().reshape(wid, hei); } void GlutRender::display_handle() { get_instance().display(); } void GlutRender::kb_evt_handle(unsigned char key, int x, int y) { get_instance().on_kb_evt(false, key, x, y); } void GlutRender::kb_evt_up_handle(unsigned char key, int x, int y) { get_instance().on_kb_evt(true, key, x, y); }