gltest/src/OGL.cpp

182 lines
4.7 KiB
C++

#include "OGL.h"
#include "Camera.h"
#include "utils.h"
#include "GLObjects/WaveMesh.h"
#include <iostream>
#include <stdexcept>
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<WaveMesh*>(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();
}