I have tried to abtract my OpenGl code into classes, which has worked fine so far. It would always render until I recently build a Game class which is a derived class of the Window2 class (which I have also only recently created).
I am pretty sure that the bug is not to be found in the Mesh, Shader, PointLight or the Material class (as they have worked properly in the past).
The window does appear and has the correct background color. The render function is also called in the game loop so I am not sure what the problem is. Here is the code...
Game.h
#ifndef GAME_H
#define GAME_H
#include <iostream>
#include <stdio.h>
#include <vector>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include "GameBlock.h"
#include "blocks/NormalGameBlock.h"
#include <PointLight.h>
#include <Window2.h>
#include <memory>
#include <Renderer.h>
#include <Mesh.h>
#include <Shader.h>
#include <Material.h>
#include <Utils.h>
class Game : private Window2 {
private:
Mesh* mesh;
Shader* shader;
Material* material;
PointLight* pointLight;
glm::mat4 projection;
glm::vec3 viewPosition;
glm::mat4 view;
public:
Game();
~Game();
void initialize();
void start();
void stop();
// override the functions provided by base class Window2
void input(Keys k) override;
void update() override;
void render() override;
};
#endif
Game.cpp
#include "Game.h"
Game::Game()
:
Window2((int)(1080 * 0.7f), (int)(1920 * 0.7f), "Game", false)
{
PRINT_FUNC;
pointLight = new PointLight
(
glm::vec3(0.0, 0.0, 1.0),
glm::vec3(1.0, 1.0, 1.0) * 0.0f,
glm::vec3(1.0, 1.0, 1.0) * 0.3f,
glm::vec3(1.0, 1.0, 1.0) * 1.0f,
1.0f,
0.01f,
0.01f
);
material = new Material
(
glm::vec3(0.0f, 0.0f, 1.0f) * 1.0f,
glm::vec3(0.0f, 0.0f, 1.0f) * 1.0f,
glm::vec3(0.0f, 0.0f, 1.0f) * 1.0f,
1.0f,
256.0f,
1.0f
);
}
Game::~Game() {
PRINT_FUNC;
delete mesh;
delete shader;
delete material;
delete pointLight;
}
void Game::initialize() {
PRINT_FUNC;
Window2::intitialize2();
mesh = new Mesh(Mesh::loadVertices("assets/box2.obj", false));
shader = new Shader("shaders/vertex_shader copy.glsl", "shaders/fragment_shader copy.glsl");
projection = glm::perspective(glm::radians(35.0f), 9.0f / 16.0f, 0.1f, 1000.0f);
viewPosition = glm::vec3(0, 1, 0);
view = glm::lookAt(
viewPosition, // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void Game::start() {
run();
}
void Game::stop() {
close();
}
void Game::input(Keys k) {
}
void Game::update() {
}
void Game::render() {
shader->activate();
shader->setMat4("P", projection);
shader->setMat4("V", view);
shader->setVec3("viewPos", viewPosition);
Renderer::render(mesh, shader, material, pointLight);
}
Window2.h
#ifndef WINDOW_2_H
#define WINDOW_2_H
#define GLEW_STATIC
#include <GL/glew.h> // include GLEW and new version of GL on Windows
#include <glfw3.h> // GLFW helper library
#include <iostream>
struct Keys {
bool W, A, S, D;
bool Left, Right, Up, Down;
bool N0, N1, N2, N3, N4, N5, N6, N7, N8, N9;
bool Space, Esc;
bool Shift;
};
class Window2 {
private:
GLFWmonitor* m_monitor;
unsigned int m_width;
unsigned int m_height;
int m_posX;
int m_posY;
const char* m_title;
const bool m_fullscreen;
float aspectRatio;
public:
GLFWwindow* m_window;
Window2(unsigned int width, unsigned int height, const char* title, const bool fullscreen);
~Window2();
void intitialize2();
void run();
void close();
// override functions
virtual void input(Keys k);
virtual void update();
virtual void render();
void setResizeCallback(void(*ptr)(GLFWwindow*, int, int));
void setSize(int width, int height);
float getAspectRatio();
void makeCurrent() const;
// clear window
void clear(float r, float g, float b);
// swap
void swap();
// poll events
void poll();
// get time in milliseconds
static unsigned int getTimeMS();
};
#endif
Window2.cpp
#include "Window2.h"
#include <iostream>
#include <chrono>
#include <Utils.h>
Window2::Window2
(
unsigned int width,
unsigned int height,
const char* title,
const bool fullscreen
)
:
m_width(width),
m_height(height),
m_title(title),
m_fullscreen(fullscreen)
{
PRINT_FUNC;
}
Window2::~Window2() {
PRINT_FUNC;
glfwDestroyWindow(m_window);
}
void Window2::intitialize2() {
PRINT_FUNC;
if (!glfwInit())
{
fprintf(stderr, "ERROR: could not start GLFW3\n");
return;
}
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
m_width = m_fullscreen ? mode->width : m_width;
m_height = m_fullscreen ? mode->height : m_height;
aspectRatio = (float)m_width / (float)m_height;
m_window = glfwCreateWindow(m_width, m_height, m_title, m_fullscreen ? glfwGetPrimaryMonitor() : NULL, NULL);
if (!m_window) {
fprintf(stderr, "ERROR: could not open Window2 with GLFW3\n");
glfwTerminate();
return;
}
glfwMakeContextCurrent(m_window);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
//setSize(m_width, m_height);
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER);
const GLubyte* version = glGetString(GL_VERSION);
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n\n", version);
}
void Window2::run() {
PRINT_FUNC;
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int previous = getTimeMS();
unsigned int lag = 0;
const unsigned int msPerUpdate = 1000 / 60;
while (!glfwWindowShouldClose(m_window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.8, 0.8, 0.8, 1);
unsigned int current = getTimeMS();
unsigned int elapsed = current - previous;
previous = current;
lag += elapsed;
const Keys k{
glfwGetKey(m_window, GLFW_KEY_W) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_A) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_S) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_D) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_LEFT) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_RIGHT) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_UP) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_DOWN) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_0) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_1) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_2) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_3) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_4) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_5) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_6) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_7) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_8) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_9) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_SPACE) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_ESCAPE) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS
};
//input
input(k);
while (lag >= msPerUpdate)
{
// update
update();
lag -= msPerUpdate;
}
// render
render();
glfwSwapBuffers(m_window);
glfwPollEvents();
}
}
void Window2::input(Keys k) {
}
void Window2::update() {
}
void Window2::render() {
}
void Window2::close() {
glfwSetWindowShouldClose(m_window, GLFW_TRUE);
}
void Window2::setSize(int width, int height) {
m_width = width;
m_height = height;
aspectRatio = (float)m_width / (float)m_height;
glViewport(0, 0, width, height);
}
void Window2::setResizeCallback(void(*ptr)(GLFWwindow*, int, int)) {
glfwSetWindowSizeCallback(m_window, ptr);
}
void Window2::makeCurrent() const {
glfwMakeContextCurrent(m_window);
}
float Window2::getAspectRatio() {
return aspectRatio;
}
unsigned int Window2::getTimeMS() {
std::chrono::milliseconds mt = std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now().time_since_epoch());
return mt.count();
}
This is how the class is created in Main.cpp:
int main(int argc, char* argv[])
{
Game game;
game.initialize();
game.start();
glfwTerminate();
return 0;
}
Just a guess, I would expect you to set the version of OpenGL, after glfwInit(). For instance set it to version 3.3, I use 4.6:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
The general rendering routine looks like this. Check where and if glUseProgram called somewhere, and if it is called:
glUseProgram(progId);
glBindVertexArray(vao); //vertex array object here, (not vertex buffer object)
glDrawXXX(GL_XXX, args); //for instance glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 3);
I suppose shaders are compiled and program is linked successfully. So far is hard to guess from provided code. Other guesses might be missing some transformation, or missing any bind before drawing. The MVP transformation might send the object outside the window just by a small mistake. Transforming GL routines to OOP should be done in small steps. The way it is implemented really shows the level of understanding it.
Related
I am currently developing a test project for OpenGL to discover its possibilities.
I am experiencing a weird bug with GLFW 4.0 apparently called "mouse drift" (from different github issues). It means that even though my mouse is not moving, the glfw input callback will still be called with small x and y values (generally 1 or -1).
I provided my code here : https://github.com/Lygaen/testgl (not ads or promoting, just giving the link to the full project to help reproduce). I am using a basic GLFW, GLAD and GLM framework.
My goal is to calculate the delta position of the mouse, to have correct camera movement.
Thank you for any help that you could provide !
Here is the code that calculates input :
window.h
#ifndef __WINDOW_H__
#define __WINDOW_H__
#include <string>
#include <glad/gl.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <vector>
class Window
{
private:
GLFWwindow *window;
bool correctlyLoaded;
static void resizeCallback(GLFWwindow *, int, int);
public:
Window(const std::string &, int, int);
~Window();
const bool hasCorrectlyLoaded();
const bool shouldClose();
const void pollEvents();
const void exitNextFrame();
};
class Input
{
private:
static char *keyStates;
static bool *mouseStates;
static glm::dvec2 pos;
static glm::dvec2 delta;
static std::vector<int> pressed;
static void keyCallback(GLFWwindow *, int, int, int, int);
static void mouseCallback(GLFWwindow *, double, double);
static void mouseButtonCallback(GLFWwindow *, int, int, int);
public:
static const bool isPressed(int);
static const bool isDown(int);
static const bool isReleased(int);
static const glm::dvec2 getMousePosition();
static const glm::dvec2 getMouseDelta();
static const bool isMouseButtonDown(int);
static const void setCallbacks(GLFWwindow *);
static const void loopClear();
static const void terminate();
};
#endif // __WINDOW_H__
window.cpp
#include "window.h"
#include <spdlog/spdlog.h>
#include <algorithm>
Window::Window(const std::string &title, int width, int height)
{
correctlyLoaded = false;
if (!glfwInit())
{
spdlog::default_logger()->critical("Could not load GLFW");
return;
}
spdlog::default_logger()->info("Loaded GLFW {}", glfwGetVersionString());
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, GLFW_TRUE);
window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
if (!window)
{
spdlog::default_logger()->critical("Failed to create GLFW window !");
return;
}
glfwMakeContextCurrent(window);
if (!gladLoadGL(glfwGetProcAddress))
{
spdlog::default_logger()->critical("Failed to load OpenGL !");
return;
}
spdlog::default_logger()->info("Loaded OpenGL {}", glfwGetVersionString());
glViewport(0, 0, width, height);
glEnable(GL_MULTISAMPLE);
glfwSetFramebufferSizeCallback(window, Window::resizeCallback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
Input::setCallbacks(window);
correctlyLoaded = true;
}
Window::~Window()
{
glfwTerminate();
}
void Window::resizeCallback(GLFWwindow *, int width, int height)
{
glViewport(0, 0, width, height);
}
const bool Window::hasCorrectlyLoaded()
{
return correctlyLoaded;
}
const bool Window::shouldClose()
{
return glfwWindowShouldClose(window);
}
const void Window::pollEvents()
{
Input::loopClear();
glfwSwapBuffers(window);
glfwPollEvents();
}
const void Window::exitNextFrame()
{
glfwSetWindowShouldClose(window, true);
}
char *Input::keyStates;
bool *Input::mouseStates;
glm::tvec2<double> Input::pos;
glm::tvec2<double> Input::delta;
std::vector<int> Input::pressed;
void Input::keyCallback(GLFWwindow *, int key, int /*scancode*/, int action, int /*mods*/)
{
if (key < 0 || key > GLFW_KEY_LAST)
return;
keyStates[key] = action;
if (action == GLFW_PRESS)
{
pressed.push_back(key);
}
}
void Input::mouseCallback(GLFWwindow *window, double nXPos, double nYPos)
{
glm::dvec2 newPos = {nXPos, nYPos};
delta = newPos - pos;
pos = newPos;
glfwSetCursorPos(window, 0, 0);
}
void Input::mouseButtonCallback(GLFWwindow *window, int button, int action, int /*mods*/)
{
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
return;
mouseStates[button] = action;
}
const bool Input::isPressed(int key)
{
return std::count(pressed.begin(), pressed.end(), key);
}
const bool Input::isDown(int key)
{
return keyStates[key] != GLFW_RELEASE;
}
const bool Input::isReleased(int key)
{
return keyStates[key] == GLFW_RELEASE;
}
const glm::dvec2 Input::getMousePosition()
{
return pos;
}
const glm::dvec2 Input::getMouseDelta()
{
return delta;
}
const bool Input::isMouseButtonDown(int mouseButton)
{
return mouseStates[mouseButton] == GLFW_PRESS;
}
const void Input::setCallbacks(GLFWwindow *window)
{
keyStates = new char[GLFW_KEY_LAST];
mouseStates = new bool[GLFW_MOUSE_BUTTON_LAST];
glfwSetKeyCallback(window, Input::keyCallback);
glfwSetCursorPosCallback(window, Input::mouseCallback);
glfwSetMouseButtonCallback(window, Input::mouseButtonCallback);
}
const void Input::loopClear()
{
pressed.clear();
}
const void Input::terminate()
{
delete[] keyStates;
delete[] mouseStates;
}
main.cpp
#include <iostream>
#include "gui/window.h"
#include "gui/gl/shader.h"
#include <spdlog/spdlog.h>
#include <spdlog/fmt/bin_to_hex.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/scalar_multiplication.hpp>
glm::mat4 fpsView(glm::vec3 cam, float pitch, float yaw)
{
float cosPitch = cos(pitch);
float sinPitch = sin(pitch);
float cosYaw = cos(yaw);
float sinYaw = sin(yaw);
glm::vec3 xaxis = {cosYaw, 0, -sinYaw};
glm::vec3 yaxis = {sinYaw * sinPitch, cosPitch, cosYaw * sinPitch};
glm::vec3 zaxis = {sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw};
// Create a 4x4 view matrix from the right, up, forward and eye position vectors
glm::mat4 viewMatrix = {
glm::vec4(xaxis.x, yaxis.x, zaxis.x, 0),
glm::vec4(xaxis.y, yaxis.y, zaxis.y, 0),
glm::vec4(xaxis.z, yaxis.z, zaxis.z, 0),
glm::vec4(-glm::dot(xaxis, cam), -glm::dot(yaxis, cam), -glm::dot(zaxis, cam), 1)};
return viewMatrix;
}
int main(int, char **)
{
#ifndef NDEBUG
spdlog::set_level(spdlog::level::trace);
#endif
Window window("Test GL", 800, 600);
if (!window.hasCorrectlyLoaded())
{
return 1;
}
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = {
// note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
Shader shader;
unsigned int VAO;
GL(glGenVertexArrays(1, &VAO));
GL(glBindVertexArray(VAO));
unsigned int VBO;
GL(glGenBuffers(1, &VBO));
GL(glBindBuffer(GL_ARRAY_BUFFER, VBO));
GL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
unsigned int EBO;
GL(glGenBuffers(1, &EBO));
GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW));
GL(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *)0));
GL(glEnableVertexAttribArray(0));
glm::mat4 Projection = glm::perspective(glm::radians(90.0f), (float)800 / (float)600, 0.1f, 100.0f);
glm::vec3 cam{4, 3, 3};
glm::vec2 dir{0, 0};
glm::mat4 Model = glm::mat4(1.0f);
while (!window.shouldClose())
{
GL(glClearColor(0.2f, 0.3f, 0.3f, 1.0f));
GL(glClear(GL_COLOR_BUFFER_BIT));
glm::mat4 View = fpsView(cam, dir.y, dir.x);
glm::mat4 mvp = Projection * View * Model;
shader.setUniform("MVP", &mvp);
shader.bind();
GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
GL(glBindVertexArray(VAO));
GL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
GL(glBindVertexArray(0));
window.pollEvents();
if (Input::isPressed(GLFW_KEY_ESCAPE))
{
window.exitNextFrame();
}
if (Input::isPressed(GLFW_KEY_F6))
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
else if (Input::isReleased(GLFW_KEY_F6))
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glm::dvec2 d = Input::getMouseDelta();
dir += d * 0.001;
}
spdlog::default_logger()->info("Quitting !");
}
Ive been working in glfw c++ and want to get input from the mouse wheel by using the glfwSetScrollCallback() and I put it in a window class that I created because it requires a glfw window. I created a scroll_callback function that adjusts the fov for the camera that I initialize in a camera class. The glfwSetScrollCallback() uses that static void of my scroll_callback function in my camera class. However, I cant seem how to initialize a the fov variable in my camera.h and use it in the static void in my camera.cpp. I tried changing it to a static public variable because I need to call it in my main class but it didnt work. Any thoughts thank you!!!
camera.h
#pragma once
#include <GL\glew.h>
#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <GLFW\glfw3.h>
class Camera
{
public:
Camera();
Camera(glm::vec3 startPosition, glm::vec3 startUp, GLfloat startYaw, GLfloat startPitch, GLfloat startMoveSpeed, GLfloat startTurnSpeed);
void keyControl(bool* keys, GLfloat deltaTime);
void mouseControl(GLfloat xChange, GLfloat yChange);
static float fov;
glm::mat4 calculateViewMatrix();
~Camera();
static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
private:
glm::vec3 position;
glm::vec3 front;
glm::vec3 up;
glm::vec3 right;
glm::vec3 worldUp;
GLfloat yaw;
GLfloat pitch;
GLfloat moveSpeed;
GLfloat turnSpeed;
void update();
};
Camera.cpp
#include "Camera.h"
#include <iostream>
Camera::Camera() {}
Camera::Camera(glm::vec3 startPosition, glm::vec3 startUp, GLfloat startYaw, GLfloat startPitch, GLfloat startMoveSpeed, GLfloat startTurnSpeed)
{
position = startPosition;
worldUp = startUp;
yaw = startYaw;
pitch = startPitch;
front = glm::vec3(0.0f, 0.0f, -1.0f);
moveSpeed = startMoveSpeed;
turnSpeed = startTurnSpeed;
update();
}
void Camera::keyControl(bool* keys, GLfloat deltaTime)
{
GLfloat velocity = moveSpeed * deltaTime;
if (keys[GLFW_KEY_W] || keys[GLFW_KEY_UP])
{
position += front * velocity;
}
if (keys[GLFW_KEY_S] || keys[GLFW_KEY_DOWN])
{
position -= front * velocity;
}
if (keys[GLFW_KEY_A] || keys[GLFW_KEY_LEFT])
{
position -= right * velocity;
}
if (keys[GLFW_KEY_D] || keys[GLFW_KEY_RIGHT])
{
position += right * velocity;
}
}
void Camera::mouseControl(GLfloat xChange, GLfloat yChange)
{
xChange *= turnSpeed;
yChange *= turnSpeed;
yaw += xChange;
pitch += yChange;
if (pitch > 89.0f)
{
pitch = 89.0f;
}
if (pitch < -89.0f)
{
pitch = -89.0f;
}
update();
}
void Camera::scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if (fov > 1.0f && fov < 45.0f)
fov -= yoffset;
else if (fov <= 1.0f)
fov = 1.0f;
else if (fov >= 45.0f)
fov = 45.0f;
}
glm::mat4 Camera::calculateViewMatrix()
{
return glm::lookAt(position, position + front, up);
}
void Camera::update()
{
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
front = glm::normalize(front);
right = glm::normalize(glm::cross(front, worldUp));
up = glm::normalize(glm::cross(right, front));
}
Camera::~Camera()
{
}
window.cpp
#include "Window.h"
#include "Camera.h"
#include <iostream>
Window::Window()
{
width = 800;
height = 800;
for (size_t i = 0; i < 1024; i++)
{
keys[i] = 0;
}
}
Window::Window(GLint windowWidth, GLint windowHeight)
{
width = windowWidth;
height = windowHeight;
for (size_t i = 0; i < 1024; i++)
{
keys[i] = 0;
}
}
int Window::Initialise()
{
if (!glfwInit())
{
printf("Error Initialising GLFW");
glfwTerminate();
return 1;
}
// Setup GLFW Windows Properties
// OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// Core Profile
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Allow forward compatiblity
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Create the window
mainWindow = glfwCreateWindow(width, height, "Test Window", NULL, NULL);
if (!mainWindow)
{
printf("Error creating GLFW window!");
glfwTerminate();
return 1;
}
// Get buffer size information
glfwGetFramebufferSize(mainWindow, &bufferWidth, &bufferHeight);
// Set the current context
glfwMakeContextCurrent(mainWindow);
// Handle Key + Mouse Input
createCallbacks();
glfwSetScrollCallback(mainWindow, Camera::scroll_callback);
glfwSetInputMode(mainWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Allow modern extension access
glewExperimental = GL_TRUE;
GLenum error = glewInit();
if (error != GLEW_OK)
{
printf("Error: %s", glewGetErrorString(error));
glfwDestroyWindow(mainWindow);
glfwTerminate();
return 1;
}
glEnable(GL_DEPTH_TEST);
// Create Viewport
glViewport(0, 0, bufferWidth, bufferHeight);
glfwSetWindowUserPointer(mainWindow, this);
}
void Window::createCallbacks()
{
glfwSetKeyCallback(mainWindow, handleKeys);
glfwSetCursorPosCallback(mainWindow, handleMouse);
}
GLfloat Window::getXChange()
{
GLfloat theChange = xChange;
xChange = 0.0f;
return theChange;
}
GLfloat Window::getYChange()
{
GLfloat theChange = yChange;
yChange = 0.0f;
return theChange;
}
void Window::handleKeys(GLFWwindow* window, int key, int code, int action, int mode)
{
Window* theWindow = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key >= 0 && key < 1024)
{
if (action == GLFW_PRESS)
{
theWindow->keys[key] = true;
}
else if (action == GLFW_RELEASE)
{
theWindow->keys[key] = false;
}
}
}
void Window::handleMouse(GLFWwindow* window, double xPos, double yPos)
{
Window* theWindow = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (theWindow->mouseFirstMoved)
{
theWindow->lastX = xPos;
theWindow->lastY = yPos;
theWindow->mouseFirstMoved = false;
}
theWindow->xChange = xPos - theWindow->lastX;
theWindow->yChange = theWindow->lastY - yPos;
theWindow->lastX = xPos;
theWindow->lastY = yPos;
}
Window::~Window()
{
glfwDestroyWindow(mainWindow);
glfwTerminate();
}
I have made a simple game window that loads 2 sprites but i changed my way of loading it so it would be better then creating for every Sprite a other variable.
I'm getting the following error:
c2227 left of '->Init' must point to class/struct/union/generic type
c2227 left of '->Init' must point to class/struct/union/generic type
And this is my code:
MainGame.h
#pragma once
#include <SDL/SDL.h>
#include <GL/glew.h>
#include <vector>
#include "GLTexture.h"
#include "GLSLProgram.h"
#include "Sprite.h"
enum class GameState {PLAY, EXIT};
class MainGame
{
public:
MainGame();
~MainGame();
void run();
void drawGame();
private:
void initSystems();
void initShaders();
void gameLoop();
void processInput();
SDL_Window* _window;
int _ScreenWidth;
int _ScreenHeight;
GameState _gameState;
std::vector <Sprite*> _sprites;
GLSLProgram _colorProgram;
float _time;
};
MainGame.ccp
#include "MainGame.h"
#include <iostream>
#include <string>
#include "Errors.h"
MainGame::MainGame() : _ScreenWidth(1024),
_ScreenHeight(768),
_window(nullptr),
_gameState(GameState::PLAY)
{
}
//Destructer
MainGame::~MainGame()
{
}
void MainGame::run() {
initSystems();
_sprites.push_back(new Sprite());
_sprites.back->Init(0.0f, -1.0f, 1.0f, 1.0f, "Textures/jimmyJump_pack/PNG/CharacterRight_Standing.png");
_sprites.push_back(new Sprite());
_sprites.back->Init(-1.0f, -1.0f, 1.0f, 1.0f, "Textures/jimmyJump_pack/PNG/CharacterRight_Standing.png");
//_playerTexture = ImageLoader::loadPNG("Textures/jimmyJump_pack/PNG/CharacterRight_Standing.png");
gameLoop();
}
void MainGame::initSystems() {
//Init SDL
SDL_Init(SDL_INIT_EVERYTHING);
//Set up Window
_window = SDL_CreateWindow("Iskallium Engine >> Game Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _ScreenWidth, _ScreenHeight, SDL_WINDOW_OPENGL);
if (_window == nullptr) {
fatalError("Iskallium Engine could not be opened");
}
//Set up OpenGL
SDL_GLContext glContext = SDL_GL_CreateContext(_window);
if (glContext == nullptr) {
fatalError("Iskallium Engine could not start Model-Loader");
}
//Set up glew
glewExperimental = true;
GLenum error = glewInit();
if (error != GLEW_OK) {
fatalError("Could not initialize glew!");
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
glClearColor(0.0f, 0.0f ,1.0f, 1.0f);
initShaders();
}
void MainGame::initShaders() {
_colorProgram.compileShaders("Shaders/colorShading.vert", "Shaders/colorShading.frag");
_colorProgram.addAttribute("vertexPosition");
_colorProgram.addAttribute("vertexColor");
_colorProgram.addAttribute("vertexUV");
_colorProgram.linkSchaders();
}
void MainGame::gameLoop() {
while (_gameState != GameState::EXIT) {
processInput();
drawGame();
}
}
void MainGame::processInput() {
SDL_Event evnt;
while (SDL_PollEvent(&evnt)) {
switch (evnt.type) {
case SDL_QUIT:
_gameState = GameState::EXIT;
break;
case SDL_MOUSEMOTION:
//std::cout << evnt.motion.x << " " << evnt.motion.y << std::endl;
break;
}
}
}
void MainGame::drawGame() {
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_colorProgram.use();
glActiveTexture(GL_TEXTURE0);
GLint textureLocation = _colorProgram.getUniformLocation("mySampler");
glUniform1i(textureLocation, 0);
//Draw sprite
for (int i = 0; i < _sprites.size(); i++) {
_sprites[i]->draw();
}
glBindTexture(GL_TEXTURE_2D, 0);
_colorProgram.unuse();
//Swapping buffer Window
SDL_GL_SwapWindow(_window);
}
if you need any more code or other classes just ask :)
This should load 2 Sprites of on the screen as you can see from my code, im fearly new to this so some of the code will look like noob code :(, please don't correct me on that because i know somethings i do not 100% correctly but nothing of the other code should corrupt my ->Init Sprite line so please help me on that and not on how to make my code don't look noob code :D
Already a HUGE thank you for all the replies i will get, hope we can solve it.
Try with
_sprites.back()->Init(0.0f, -1.0f, 1.0f, 1.0f, "Textures/jimmyJump_pack/PNG/CharacterRight_Standing.png");
Parenthesis after ->back are needed, it's a method.
I'm currently working on a project involving two cubes. The first cube meant to be static, while the second is going to rotate, or orbit, around the first. I'm very new to OpenGL programming, so I'm having quite a bit of difficulty getting this to work. Can anyone point me in the right direction? So far, I just have two cubes, but I am unable to get them to move as if they were animated. Here is my code if you would like to offer suggestions. Thank you so much!
Main:
#include "vgl.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
#include "Box.h"
#include "Camera.h"
#include "VertexBufferData.h"
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
using namespace std;
using namespace glm;
#define SPACEBAR_KEY 32
#define ESCAPE_KEY 033
Camera* camera;
vector<Box * > gameObjects;
bool keyDown[255];
void CheckKeyboard(){
if (keyDown['a'])
camera->RotateLeft();
if (keyDown['d'])
camera->RotateRight();
if (keyDown['w'])
camera->MoveForward();
if (keyDown['s'])
camera->MoveBackWard();
if (keyDown['e'])
camera->StrafeRight();
if (keyDown['q'])
camera->StrafeLeft();
}
void closeApp()
{
delete camera;
for (auto it = gameObjects.begin(); it != gameObjects.end(); ++it) {
delete (*it);
}
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case ESCAPE_KEY: // ASCII Escape Key Code
closeApp();
exit(EXIT_SUCCESS);
break;
default:
keyDown[key] = true;
}
glutPostRedisplay();
}
void keyboardUp(unsigned char key, int x, int y)
{
keyDown[key] = false;
}
void mouseWheel(int button, int direction, int x, int y)
{
if (button == 16)
camera->ResetFOV();
else if (direction > 0)
camera->ZoomIn();
else
camera->ZoomOut();
}
void mouseMovement(int x, int y)
{
static bool warp = true;
if (warp)
{
if (x>glutGet(GLUT_WINDOW_WIDTH) / 2)
camera->RotateRight();
else if (x<glutGet(GLUT_WINDOW_WIDTH) / 2)
camera->RotateLeft();
if (y>glutGet(GLUT_WINDOW_HEIGHT) / 2)
camera->RotateUp();
else if (y<glutGet(GLUT_WINDOW_HEIGHT) / 2)
camera->RotateDown();
glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
warp = false;
}
else
warp = true;
}
void timer(int value)
{
glutPostRedisplay();
glutTimerFunc(25, timer, 0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
CheckKeyboard();
camera->Update();
for (auto it = gameObjects.begin(); it != gameObjects.end(); ++it) {
(*it)->shaderProgram->bindShader();
glm::mat4 MVP = camera->ProjectionMatrix * camera->ViewMatrix * (*it)->getModelMatrix();
(*it)->shaderProgram->sendUniform4x4("MVP", glm::value_ptr(MVP));
(*it)->Draw();
}
glutSwapBuffers();
}
void init()
{
int i = 0, forever = 0;
camera = new Camera();
memset(keyDown, false, sizeof(keyDown));
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
VertexBufferData vertexBufferData = VertexBufferData("Data\\Models\\Objects.xml");
gameObjects.push_back(new Box(vertexBufferData, glm::vec3(-2.0f, 0.0f, 0.0f), "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader"));
gameObjects.push_back(new Box(vertexBufferData, glm::vec3(2.0f, 0.0f, 0.0f), "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader"));
gameObjects[1]->setRotation(45.0f, vec3(0.0f, 0.0f, 1.0f));
gameObjects[0]->setScaleMatrix(vec3(2, 2, 2));
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(1024, 768);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow("Satterwhite_Project_3");
if (glewInit())
{
cerr << "Unable to init glew" << endl;
exit(EXIT_FAILURE);
}
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboardUp);
glutPassiveMotionFunc(mouseMovement);
glutMouseWheelFunc(mouseWheel);
glutTimerFunc(25, timer, 0);
glutMainLoop();
return 0;
}
Box.cpp
#include "Box.h"
Box::Box(VertexBufferData &vbd, vec3 initialPosition,const string vertexShader, const string fragmentShader):GameObject(vertexShader, fragmentShader)
{
Position=initialPosition;
vertexBufferData =vbd;
RotationMatrix=mat4(1.0f);
OrbitMatrix = mat4(1.0f);
ScaleMatrix=mat4(1.0f);
TranslationMatrix =translate(glm::mat4(1.0f), Position);
if (!shaderProgram->initialize())
{
std::cerr << "Could not initialize the shaders" << std::endl;
}
shaderProgram->bindShader();
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexBufferData.verticiesSize, &vertexBufferData.verticies[0], GL_STATIC_DRAW);
glGenBuffers(1, &fragmentBuffer);
glBindBuffer(GL_ARRAY_BUFFER, fragmentBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexBufferData.colorSize, &vertexBufferData.colors[0], GL_STATIC_DRAW);
shaderProgram->linkProgram();
}
void Box::setRotation(float degrees, vec3 axis)
{
RotationMatrix=rotate(glm::mat4(1.0f), degrees, axis);
RotationMatrix=rotate(RotationMatrix, degrees, vec3(1.0f,0.0f,0.0f));
}
void Box::setScaleMatrix(vec3 scale)
{
ScaleMatrix = glm::scale(mat4(1.0f), scale);
}
/*void Box::setOrbitMatrix(vec3 Position, vec3 axis)
{
OrbitMatrix =
}*/
void Box::Draw()
{
shaderProgram->bindShader();
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT,GL_FALSE, 0, BUFFER_OFFSET(0));
glBindBuffer(GL_ARRAY_BUFFER, fragmentBuffer);
glVertexAttribPointer(1, 3, GL_FLOAT,GL_FALSE, 0, BUFFER_OFFSET(0));
glDrawArrays(GL_TRIANGLES, 0, vertexBufferData.verticies.size());
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
Box.h
#pragma once
#include "GameObject.h"
class Box : public GameObject
{
private:
mat4 ModelMatrix;
mat4 RotationMatrix;
mat4 OrbitMatrix;
mat4 TranslationMatrix;
mat4 ScaleMatrix;
public:
void Draw();
virtual ObjectType getType() const { return BOX; }
mat4 getModelMatrix() {return TranslationMatrix*RotationMatrix*ScaleMatrix;}
mat4 getMRotationMatrix() {return RotationMatrix;}
mat4 getTranslationMatrix() {return TranslationMatrix;}
mat4 getOrbitMatrix(){ return OrbitMatrix; }
mat4 getScaleMatrix() {return ScaleMatrix;}
void setRotation(float degrees, vec3 axis);
void setScaleMatrix(vec3 scale);
void setOrbitMatrix(vec3 Position, vec3 axis);
Box(VertexBufferData &vertexBufferData, vec3 initialPosition, const string vertexShader, const string fragmentShader);
vec3 Position;
mat4 rot;
mat4 scale;
};
This program builds with no problem, and the executable starts up, but no triangle shows up. I am following a GLSL tutorial where a Shader class is made to handle GLSL files.
Shader.h
#ifndef SHADER_H_
#define SHADER_H_
#include <GL/glew.h>
#include <GL/glfw.h>
#include <string>
class Shader {
public:
Shader();
Shader(const char *vsFile, const char *fsFile);
~Shader();
void init(const char *vsFile, const char *fsFile);
void bind();
void unbind();
unsigned int id();
private:
unsigned int shader_id;
unsigned int shader_vp;
unsigned int shader_fp;
};
#endif // SHADER_H_
Shader.cpp
#include "Shader.h"
#include <cstring>
#include <iostream>
#include <ftream>
#include <cstdlib>
using namespace std;
static char* textFileRead(const char *fileName) {
char* text;
if (fileName != NULL) {
FILE *file = fopen(fileName, "rt");
if (file != NULL) {
fseek(file, 0, SEEK_END);
int count = ftell(file);
rewind(file);
if (count > 0) {
text = (char*)malloc(sizeof(char) * (count + 1));
count = fread(text, sizeof(char), count, file);
text[count] = '\0';
}
fclose(file);
}
}
return text;
}
Shader::Shader() {}
Shader::Shader(const char *vsFile, const char *fsFile)
{
init(vsFile, fsFile);
}
void Shader::init(const char *vsFile, const char *fsFile)
{
shader_vp = glCreateShader(GL_VERTEX_SHADER);
shader_fp = glCreateShader(GL_FRAGMENT_SHADER);
const char *vsText = textFileRead(vsFile);
const char *fsText = textFileRead(fsFile);
if (vsText == NULL || fsText == NULL)
{
cerr << "Either vertex shader or fragment shader file is not found" << endl;
return;
}
glShaderSource(shader_vp, 1, &vsText, 0);
glShaderSource(shader_fp, 1, &fsText, 0);
glCompileShader(shader_vp);
glCompileShader(shader_fp);
shader_id = glCreateProgram();
glAttachShader(shader_id, shader_fp);
glAttachShader(shader_id, shader_vp);
glLinkProgram(shader_id);
}
Shader::~Shader()
{
glDetachShader(shader_id, shader_fp);
glDetachShader(shader_id, shader_vp);
glDeleteShader(shader_fp);
glDeleteShader(shader_vp);
glDeleteShader(shader_id);
}
unsigned int Shader::id()
{
return shader_id;
}
void Shader::bind()
{
glUseProgram(shader_id);
}
void Shader::unbind()
{
glUseProgram(0);
}
Main.cpp
#include "Shader.h"
#include <cstdlib>
#include <iostream>
using namespace std;
Shader shader;
void init()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
shader.init("shader.vert", "shader.frag");
}
void resize(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
int main()
{
int running = GL_TRUE;
// init GLFW
if (!glfwInit())
exit(EXIT_FAILURE);
if (!glfwOpenWindow(300, 300, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetWindowTitle("ohhai.");
glfwSetWindowSizeCallback(resize);
/* CHECK GLEW */
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
cout << "Error: " << glewGetErrorString(err) << endl;
}
cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
if (!GLEW_ARB_vertex_buffer_object)
{
cerr << "VBO not supported\n";
exit(1);
}
init();
while (running)
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glShadeModel(GL_SMOOTH);
shader.bind();
glBegin(GL_TRIANGLES);
//glColor3f(0.2f, 0.5f, 0.54f);
glVertex2f(0.0f, 0.5f);
//glColor3f(0.75f, 0.8f, 0.1f);
glVertex2f(-.5f, -.5f);
//glColor3f(0.0f, 0.9f, 0.2f);
glVertex2f(0.5f, -0.5f);
glEnd();
shader.unbind();
glfwSwapBuffers();
running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED);
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
shader.vert
void main()
{
// set the posistion of the current matrix
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
shader.frag
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Again, when this compiles under g++, it goes through fine, but no triangle was shown.
I haven't found the part where you setup the camera (modelview matrix) with gluLookAt or glTranslate/glRotate/glScale. So you use the default, corresponding to a camera at the origin and looking into -z, thus your triangle (which lies in the z=0 plane) is behind the near plane.