182 lines
4.7 KiB
C++
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();
|
|
}
|