Compare commits

..

3 commits

7 changed files with 213 additions and 38 deletions

View file

@ -18,7 +18,9 @@ add_executable(tests_opengl
src/DataHandling/Texture.h
src/DataHandling/Model3D.cpp
src/DataHandling/Model3D.h
src/types.h)
src/types.h
src/KeyStateManager.cpp
src/KeyStateManager.h)
target_link_directories(tests_opengl PRIVATE
src)

19
README.md Normal file
View file

@ -0,0 +1,19 @@
# OpenGL course
The goal of the course is to introduce us to the OpenGL render pipeline and how to use the library.
The code here was, in part, inspired by the code which was given as part of the course but could not run on windows.
It is aimed to replace it and serve as a base for my own project as part of the course.
## TODOs
- [ ] Camera movement
- [ ] Entities
- [ ] Quaternion computations? Maybe use OpenGLMathematics
- [ ] Loading other file types
## Dependencies
The following libraries must be installed and findable by CMake:
- OpenGL
- Freeglut 3

View file

@ -55,36 +55,24 @@ void Model3D::draw_model()
{
Vec3i face = faces[i];
Vec3i face_texture;
Vec3i* face_texture;
if (is_textured)
{
face_texture = face_textures[i];
face_texture = &face_textures[i];
}
// FIXME : Find a better way to draw the three vertices
Vec3f vertex = vertices[face.x];
// Draw each vertex and texture it if needed
for (int j = 0; j < 3; j++)
{
Vec3f& vertex = vertices[face.coordinates[j]];
if (is_textured)
{
Vec2f vertex_texture = texture_coordinates[face_texture.x];
Vec2f vertex_texture = texture_coordinates[face_texture->coordinates[j]];
glTexCoord2f(vertex_texture.x,vertex_texture.y);
}
glVertex3f(vertex.x,vertex.y,vertex.z);
vertex = vertices[face.y];
if (is_textured)
{
Vec2f vertex_texture = texture_coordinates[face_texture.y];
glTexCoord2f(vertex_texture.x,vertex_texture.y);
}
glVertex3f(vertex.x,vertex.y,vertex.z);
vertex = vertices[face.z];
if (is_textured)
{
Vec2f vertex_texture = texture_coordinates[face_texture.z];
glTexCoord2f(vertex_texture.x,vertex_texture.y);
}
glVertex3f(vertex.x,vertex.y,vertex.z);
}
glEnd();

79
src/KeyStateManager.cpp Normal file
View file

@ -0,0 +1,79 @@
//
// Created by trotfunky on 07/10/2019.
//
#include "KeyStateManager.h"
#include <iostream>
std::map<unsigned char,bool> KeyStateManager::ascii_keys_status = {};
std::map<int,bool> KeyStateManager::special_keys_status = {};
void KeyStateManager::register_glut_callbacks()
{
glutKeyboardFunc(KeyStateManager::key_press);
glutKeyboardUpFunc(KeyStateManager::key_up);
glutSpecialFunc(KeyStateManager::special_key_press);
glutSpecialUpFunc(KeyStateManager::special_key_up);
}
bool KeyStateManager::is_key_pressed(unsigned char key)
{
if (ascii_keys_status.find(key) == ascii_keys_status.end())
{
return false;
}
return ascii_keys_status.at(key);
}
bool KeyStateManager::is_special_key_pressed(int key)
{
if (special_keys_status.find(key) == special_keys_status.end())
{
return false;
}
return special_keys_status.at(key);
}
void KeyStateManager::key_press(unsigned char event_key, int mouse_x, int mouse_y)
{
update_key(event_key,true);
}
void KeyStateManager::key_up(unsigned char event_key, int mouse_x, int mouse_y)
{
update_key(event_key,false);
}
void KeyStateManager::special_key_press(int event_key, int mouse_x, int mouse_y)
{
update_special_key(event_key,true);
}
void KeyStateManager::special_key_up(int event_key, int mouse_x, int mouse_y)
{
update_special_key(event_key,false);
}
void KeyStateManager::update_key(unsigned char event_key, bool new_status)
{
if (ascii_keys_status.find(event_key) != ascii_keys_status.end())
{
ascii_keys_status.at(event_key) = new_status;
}
else
{
ascii_keys_status.insert({event_key,new_status});
}
}
void KeyStateManager::update_special_key(int event_key, bool new_status)
{
if (special_keys_status.find(event_key) != special_keys_status.end())
{
special_keys_status.at(event_key) = new_status;
}
else
{
special_keys_status.insert({event_key,new_status});
}
}

41
src/KeyStateManager.h Normal file
View file

@ -0,0 +1,41 @@
//
// Created by trotfunky on 07/10/2019.
//
#ifndef TESTS_OPENGL_KEYSTATEMANAGER_H
#define TESTS_OPENGL_KEYSTATEMANAGER_H
#include <map>
#include <GL/glut.h>
/// Handles the key events from glut and keep the status of keys up to date.
/// "Static class"
class KeyStateManager {
public:
KeyStateManager() = delete;
static void register_glut_callbacks();
// FIXME: Not happy with having two functions : char auto promoted to int if same name
static bool is_key_pressed(unsigned char key);
static bool is_special_key_pressed(int key);
// Glut callbacks for input events
static void key_press(unsigned char event_key, int mouse_x, int mouse_y);
static void key_up(unsigned char event_key, int mouse_x, int mouse_y);
static void special_key_press(int event_key, int mouse_x, int mouse_y);
static void special_key_up(int event_key, int mouse_x, int mouse_y);
private:
// The maps are used to keep track of the keys which were pressed or released during runtime.
static std::map<unsigned char,bool> ascii_keys_status;
static std::map<int,bool> special_keys_status;
// These functions are called by *_press and *_up to update their values
static void update_key(unsigned char event_key, bool new_status);
static void update_special_key(int event_key, bool new_status);
};
#endif //TESTS_OPENGL_KEYSTATEMANAGER_H

View file

@ -4,15 +4,38 @@
#include "displayers.h"
#include "DataHandling/Texture.h"
#include "DataHandling/Model3D.h"
#include "KeyStateManager.h"
volatile unsigned long long int timer_ticks = 0;
static Texture tree_texture;
static Model3D raptor;
static Texture raptor_texture;
void manage_inputs()
{
if (KeyStateManager::is_key_pressed(' '))
{
glClearColor(0.5,0,0,1);
}
else
{
glClearColor(0,0,0,1);
}
if (KeyStateManager::is_special_key_pressed(GLUT_KEY_RIGHT))
{
timer_ticks += 5;
}
if (KeyStateManager::is_special_key_pressed(GLUT_KEY_LEFT))
{
timer_ticks -= 5;
}
}
void display()
{
manage_inputs();
float angleY = 1*timer_ticks;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -54,6 +77,7 @@ int main(int argc, char** argv)
// Generate window with GLUT
glutInitDisplayMode(GLUT_RGB| GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("Hello");
glutIgnoreKeyRepeat(true);
// Init OpenGL
glClearColor(0,0,0,1);
@ -96,6 +120,7 @@ int main(int argc, char** argv)
glutIdleFunc(display);
glutTimerFunc(50,update_angle,0);
KeyStateManager::register_glut_callbacks();
// Enters main loop, managed by GLUT
glutMainLoop();

View file

@ -7,14 +7,33 @@
#include <fstream>
/// Group of coordinates with the input operator overloaded.
/// \tparam T Content of the vector
/// \tparam N Number of coordinates
template <typename T, unsigned int N>
struct CoordinatesVector
{
T coordinates[N];
friend std::fstream& operator>>(std::fstream& stream, CoordinatesVector<T,N>& vector)
{
for (unsigned int i = 0;i<N;i++)
{
stream >> vector.coordinates[i];
}
return stream;
}
};
template <typename T>
struct Vec2
struct CoordinatesVector<T,2>
{
T x;
T y;
T coordinates[2];
T& x = coordinates[0];
T& y = coordinates[1];
friend std::fstream& operator>>(std::fstream& stream, Vec2& vec2)
friend std::fstream& operator>>(std::fstream& stream, CoordinatesVector<T,2>& vec2)
{
stream >> vec2.x >> vec2.y;
return stream;
@ -22,13 +41,15 @@ struct Vec2
};
template <typename T>
struct Vec3
struct CoordinatesVector<T,3>
{
T x;
T y;
T z;
T coordinates[3];
friend std::fstream& operator>>(std::fstream& stream, Vec3& vec3)
T& x = coordinates[0];
T& y = coordinates[1];
T& z = coordinates[2];
friend std::fstream& operator>>(std::fstream& stream, CoordinatesVector<T,3>& vec3)
{
stream >> vec3.x >> vec3.y >> vec3.z;
return stream;
@ -37,11 +58,11 @@ struct Vec3
// Define aliases for common types
typedef Vec2<int> Vec2i;
typedef Vec2<float> Vec2f;
typedef CoordinatesVector<int,2> Vec2i;
typedef CoordinatesVector<float,2> Vec2f;
typedef Vec3<int> Vec3i;
typedef Vec3<float> Vec3f;
typedef CoordinatesVector<int,3> Vec3i;
typedef CoordinatesVector<float,3> Vec3f;
#endif //TESTS_OPENGL_TYPES_H