#include "OGL.h" #include "Camera.h" #include "utils.h" #include "GLObjects/WaveMesh.h" #include #include bool wiredFlag = false; double lastX = 0.0, lastY = 0.0; void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { const float turnStep = 0.1f; // in radians const float moveStep = 0.1f; if (key == GLFW_KEY_M && action == GLFW_PRESS) { glPolygonMode(GL_FRONT_AND_BACK, wiredFlag ? GL_FILL : GL_LINE); wiredFlag = !wiredFlag; } if(action == GLFW_PRESS || action == GLFW_REPEAT) { switch (key) { case GLFW_KEY_LEFT: Camera::instance()->turnLeft(turnStep); break; case GLFW_KEY_RIGHT: Camera::instance()->turnRight(turnStep); break; case GLFW_KEY_UP: Camera::instance()->turnUp(turnStep); break; case GLFW_KEY_DOWN: Camera::instance()->turnDown(turnStep); break; case GLFW_KEY_PAGE_UP: Camera::instance()->rotateCW(turnStep); break; case GLFW_KEY_PAGE_DOWN: Camera::instance()->rotateCCW(turnStep); break; case GLFW_KEY_W: Camera::instance()->moveToCenter(moveStep); break; case GLFW_KEY_S: Camera::instance()->moveFromCenter(moveStep); break; } } } void cursorPositionCallback(GLFWwindow* window, double xpos, double ypos) { if(lastX != 0 || lastY != 0) { float dx = (float)(xpos - lastX); float dy = (float)(ypos - lastY); static const float coeff = 0.01f; if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) { Camera::instance()->mouseMoveAroundCenter(coeff*dx, coeff*dy); // for(IGLObject* obj: OGL::instance()->_glObjects) { // obj->rotate(glm::vec3(coeff*dy, 0.f, coeff*dx)); // obj->update(); // } } } lastX = xpos; lastY = ypos; } void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) { if(yoffset > 0) { Camera::instance()->moveToCenter(0.1f); } else { Camera::instance()->moveFromCenter(0.1f); } } void glfwErr(int code, const char* description) { std::cout << "GLFW error - code: " << code << ", description: " << description << std::endl; } OGL::OGL() { } OGL::~OGL() { glfwTerminate(); } OGL *OGL::instance() { static OGL app; return &app; } void OGL::updateFpsCounter() const { static double previous_seconds = glfwGetTime (); static int frame_count; double current_seconds = glfwGetTime (); double elapsed_seconds = current_seconds - previous_seconds; if (elapsed_seconds > 0.25) { previous_seconds = current_seconds; double fps = (double)frame_count / elapsed_seconds; char tmp[128]; sprintf (tmp, "opengl @ fps: %.2f", fps); glfwSetWindowTitle (_window, tmp); frame_count = 0; } frame_count++; } void OGL::init() { std::cout << glfwGetVersionString() << std::endl; if(glfwInit() == GLFW_FALSE) { throw new std::runtime_error("GLFW initialization error"); } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); glfwWindowHint (GLFW_SAMPLES, 4); glfwSetErrorCallback(glfwErr); _window = glfwCreateWindow(1024, 1024, "OpenGL", nullptr, nullptr); // Windowed glfwMakeContextCurrent(_window); glfwSetKeyCallback(_window, keyCallback); glfwSetCursorPosCallback(_window, cursorPositionCallback); glfwSetScrollCallback(_window, scrollCallback); glewExperimental = GL_TRUE; GLenum err = glewInit(); if(err != GLEW_OK) { std::string errMsg = std::string("GLEW init error: ") + (char*)glewGetErrorString(err); throw new std::runtime_error(errMsg); } // even successful call to glewInit() may cause setting global error GL_INVALID_ENUM, // so we need clear it in order to use glGetError() later // https://www.opengl.org/wiki/OpenGL_Loading_Library#GLEW_.28OpenGL_Extension_Wrangler.29 utils::clearGLError(); glEnable(GL_DEPTH_TEST); glClearDepth(1.0); glDepthFunc(GL_LEQUAL); } void OGL::run() { while(!glfwWindowShouldClose(_window)) { updateFpsCounter(); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // double time = glfwGetTime(); // float shift = (float)fmod(time, 2*3.1415926); for(IGLObject* obj: _glObjects) { // WaveMesh* mesh = dynamic_cast(obj); // mesh->setShift(shift*2); //obj->scale(glm::vec3(1.0f, 1.0f, 1.0f)); obj->update(); obj->draw(); } glfwPollEvents(); glfwSwapBuffers(_window); } } void OGL::addObject(IGLObject *object) { _glObjects.push_back(object); } ShaderProgram *OGL::getCurShaderProgram() { return _curShaderProgram; } void OGL::setCurShaderProgram(ShaderProgram *sp) { _curShaderProgram = sp; _curShaderProgram->use(); }