Compare commits

...

No commits in common. "feature_match" and "main" have entirely different histories.

21 changed files with 238 additions and 113 deletions

View file

@ -15,42 +15,5 @@ set(CMAKE_CXX_STANDARD 14)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED) find_package(GLUT REQUIRED)
if(NOT ${OPENGL_GLU_FOUND}) add_subdirectory(src)
message(FATAL_ERROR "Glu not installed!") add_subdirectory(example)
endif()
add_executable(tests_opengl
src/main.cpp
src/displayers.h
src/displayers.cpp
src/DataHandling/Texture.cpp
src/DataHandling/Texture.h
src/DataHandling/Model3D.cpp
src/DataHandling/Model3D.h
src/Vectors.h
src/InputStatus.cpp
src/InputStatus.h
src/Camera.cpp
src/Camera.h
src/Quaternion.cpp
src/Quaternion.h)
target_link_directories(tests_opengl PRIVATE
src)
target_include_directories(tests_opengl PRIVATE
src)
target_link_libraries(tests_opengl
${OPENGL_LIBRARIES}
${GLUT_LIBRARIES})
target_include_directories(tests_opengl PRIVATE
${OPENGL_INCLUDE_DIR}
${GLUT_INCLUDE_DIR})
if (CMAKE_COMPILER_IS_GNUCXX)
target_compile_options(tests_opengl PRIVATE -Wall -Wpedantic -Wextra)
elseif(MSVC)
target_compile_options(tests_opengl PRIVATE /W4)
endif()

19
example/CMakeLists.txt Normal file
View file

@ -0,0 +1,19 @@
add_executable(tests_opengl
main.cpp
displayers.h
displayers.cpp)
target_link_directories(tests_opengl PRIVATE
${PROJECT_SOURCE_DIR}/src)
target_include_directories(tests_opengl PRIVATE
${PROJECT_SOURCE_DIR}/src)
target_link_libraries(tests_opengl
${OPENGL_LIBRARIES}
${GLUT_LIBRARIES}
engine)
target_include_directories(tests_opengl PRIVATE
${OPENGL_INCLUDE_DIR}
${GLUT_INCLUDE_DIR})

View file

@ -1,6 +1,7 @@
#include <GL/glut.h> #include <GL/glut.h>
#include <GL/gl.h> #include <GL/gl.h>
#include "Engine.h"
#include "displayers.h" #include "displayers.h"
#include "DataHandling/Texture.h" #include "DataHandling/Texture.h"
#include "DataHandling/Model3D.h" #include "DataHandling/Model3D.h"
@ -8,11 +9,9 @@
#include "Camera.h" #include "Camera.h"
volatile unsigned long long int timer_ticks = 0; volatile unsigned long long int timer_ticks = 0;
static double aspect_ratio;
static Texture tree_texture; static Texture tree_texture;
static Model3D raptor; static Model3D raptor;
static Texture raptor_texture; static Texture raptor_texture;
static Camera camera({10,0,10},{-10,0,-10},{0,1,0});
void manage_inputs() void manage_inputs()
{ {
@ -37,30 +36,30 @@ void manage_inputs()
if (InputStatus::is_special_key_pressed(GLUT_KEY_RIGHT)) if (InputStatus::is_special_key_pressed(GLUT_KEY_RIGHT))
{ {
timer_ticks += 5; timer_ticks += 5;
camera.translate({0,0,0.1}); OGLE::camera.local_translate({0, 0, 0.1});
} }
if (InputStatus::is_special_key_pressed(GLUT_KEY_LEFT)) if (InputStatus::is_special_key_pressed(GLUT_KEY_LEFT))
{ {
timer_ticks -= 5; timer_ticks -= 5;
camera.translate({0,0,-0.1}); OGLE::camera.local_translate({0, 0, -0.1});
} }
if (InputStatus::is_key_pressed(' ')) if (InputStatus::is_key_pressed(' '))
{ {
camera.translate({0,0.1,0}); OGLE::camera.local_translate({0, 0.1, 0});
} }
if (InputStatus::is_special_key_pressed(GLUT_KEY_PAGE_DOWN)) if (InputStatus::is_special_key_pressed(GLUT_KEY_PAGE_DOWN))
{ {
camera.translate({0,-0.1,0}); OGLE::camera.local_translate({0, -0.1, 0});
} }
if (InputStatus::is_special_key_pressed(GLUT_KEY_UP)) if (InputStatus::is_special_key_pressed(GLUT_KEY_UP))
{ {
camera.translate({0.1,0,0}); OGLE::camera.local_translate({0.1, 0, 0});
} }
if (InputStatus::is_special_key_pressed(GLUT_KEY_DOWN)) if (InputStatus::is_special_key_pressed(GLUT_KEY_DOWN))
{ {
camera.translate({-0.1,0,0}); OGLE::camera.local_translate({-0.1, 0, 0});
} }
// Get mouse delta since last frame // Get mouse delta since last frame
@ -68,7 +67,7 @@ void manage_inputs()
mouse_delta = InputStatus::get_mouse_delta(true); mouse_delta = InputStatus::get_mouse_delta(true);
if (mouse_delta.x != 0 || mouse_delta.y != 0) if (mouse_delta.x != 0 || mouse_delta.y != 0)
{ {
camera.rotate({0, OGLE::camera.rotate({0,
-mouse_delta.x / InputStatus::mouse_sensitivity.x, -mouse_delta.x / InputStatus::mouse_sensitivity.x,
-mouse_delta.y / InputStatus::mouse_sensitivity.y}); -mouse_delta.y / InputStatus::mouse_sensitivity.y});
} }
@ -79,16 +78,6 @@ void display()
manage_inputs(); manage_inputs();
float angleY = 1*timer_ticks; float angleY = 1*timer_ticks;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
// Prepare view
glLoadIdentity();
gluPerspective(60,aspect_ratio,0.1,30000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camera.look();
display_rotating_pyramid(-5,-2,-5,2,4,angleY); display_rotating_pyramid(-5,-2,-5,2,4,angleY);
display_rotating_pyramid(5,-2,0,1,5,angleY); display_rotating_pyramid(5,-2,0,1,5,angleY);
@ -100,17 +89,6 @@ void display()
glRotatef(angleY,0,-1,0); glRotatef(angleY,0,-1,0);
raptor.draw_model(); raptor.draw_model();
glPopMatrix(); glPopMatrix();
glutSwapBuffers();
}
void reshape(int new_x, int new_y)
{
glViewport(0,0,new_x,new_y);
aspect_ratio = (double)new_x/new_y;
InputStatus::window_size.x = new_x;
InputStatus::window_size.y = new_y;
} }
void update_angle(int value) void update_angle(int value)
@ -121,55 +99,26 @@ void update_angle(int value)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
glutInit(&argc,argv); OGLE::setup(argc,argv,display);
// Generate window with GLUT
glutInitDisplayMode(GLUT_RGB| GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("OpenGL custom engine tests");
glutIgnoreKeyRepeat(true);
glutSetCursor(GLUT_CURSOR_NONE);
// Init OpenGL
glClearColor(0,0,0,1);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
// Setup OPenGL to use textures
glEnable(GL_TEXTURE_2D);
glAlphaFunc(GL_GREATER, 0.5);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT/GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT/GL_CLAMP);
glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// Load and generate tree texture // Load and generate tree texture
tree_texture.load_rgba_tga("resources/arbre.tga","resources/arbre_masque.tga"); tree_texture.load_rgba_tga("resources/arbre.tga","resources/arbre_masque.tga");
glGenTextures(1,tree_texture.opengl_id);
// TODO : Put in the Texture class
glBindTexture(GL_TEXTURE_2D,tree_texture.opengl_id[0]);
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,tree_texture.width,tree_texture.height,GL_RGBA,GL_UNSIGNED_BYTE,tree_texture.image_data);
// Load and generate raptor texture // Load and generate raptor texture
raptor_texture.load_rgb_tga("resources/RAPTOR.tga"); raptor_texture.load_rgb_tga("resources/RAPTOR.tga");
glGenTextures(1, raptor_texture.opengl_id);
// TODO : Put in the Texture class
glBindTexture(GL_TEXTURE_2D, raptor_texture.opengl_id[0]);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, raptor_texture.width, raptor_texture.height, GL_RGB, GL_UNSIGNED_BYTE, raptor_texture.image_data);
// Load raptor model
raptor.load_ascii_off_file("resources/RAPTOR.off"); raptor.load_ascii_off_file("resources/RAPTOR.off");
raptor.assign_texture(raptor_texture); raptor.assign_texture(raptor_texture);
raptor.set_scaling(0.01,0.01,0.01); raptor.set_scaling(0.01,0.01,0.01);
raptor.set_rotation(-90,1,0,0); raptor.set_rotation(-90,1,0,0);
raptor.prepare_displaylist();
glViewport(0,0,glutGet(GLUT_WINDOW_WIDTH),glutGet(GLUT_WINDOW_HEIGHT));
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(50,update_angle,0); glutTimerFunc(50,update_angle,0);
InputStatus::register_glut_callbacks();
OGLE::camera.set_position({10,0,10});
OGLE::camera.rotate({0,1.5*M_PI_4,0});
// Enters main loop, managed by GLUT // Enters main loop, managed by GLUT
glutMainLoop(); glutMainLoop();

33
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,33 @@
add_library(engine
DataHandling/Texture.cpp
DataHandling/Texture.h
DataHandling/Model3D.cpp
DataHandling/Model3D.h
Math/Vectors.h
Math/Quaternion.cpp
Math/Quaternion.h
InputStatus.cpp
InputStatus.h
Camera.cpp
Camera.h
Engine.h)
target_include_directories(engine PRIVATE
${PROJECT_SOURCE_DIR}/src)
target_link_directories(engine PRIVATE
${PROJECT_SOURCE_DIR}/src)
target_link_libraries(engine
${OPENGL_LIBRARIES}
${GLUT_LIBRARIES})
target_include_directories(engine PRIVATE
${OPENGL_INCLUDE_DIR}
${GLUT_INCLUDE_DIR})
if (CMAKE_COMPILER_IS_GNUCXX)
target_compile_options(engine PRIVATE -Wall -Wpedantic -Wextra)
elseif(MSVC)
target_compile_options(engine PRIVATE /W4)
endif()

View file

@ -17,7 +17,11 @@ Camera::Camera(const Vec3d& eye_pos, const Vec3d& look_direction, const Vec3d& u
compute_base_change(); compute_base_change();
} }
void Camera::translate(const Vec3d& translation) void Camera::translate(const Vec3d &translation) {
eye = eye + translation;
}
void Camera::local_translate(const Vec3d& translation)
{ {
eye = eye + translation * rotation_quaternion; eye = eye + translation * rotation_quaternion;
} }
@ -35,7 +39,7 @@ void Camera::rotate(const Vec3d& rotation)
gaze = z_rotation * gaze; gaze = z_rotation * gaze;
gaze_up = z_rotation * gaze_up; gaze_up = z_rotation * gaze_up;
Quaternion y_rotation{0,sin(rotation.y),0,cos(rotation.y)}; Quaternion y_rotation{0,sin(rotation.y/2),0,cos(rotation.y/2)};
y_rotation.normalize(); y_rotation.normalize();
gaze = y_rotation * gaze; gaze = y_rotation * gaze;
gaze_up = y_rotation * gaze_up; gaze_up = y_rotation * gaze_up;
@ -52,7 +56,22 @@ void Camera::look()
void Camera::set_position(const Vec3d& eye_pos) void Camera::set_position(const Vec3d& eye_pos)
{ {
gaze = eye_pos; eye = eye_pos;
}
const Vec3d& Camera::get_eyepos() const
{
return eye;
}
const Vec3d& Camera::get_gaze() const
{
return gaze;
}
const Vec3d& Camera::get_gazeup() const
{
return gaze_up;
} }
void Camera::compute_base_change() void Camera::compute_base_change()

View file

@ -8,16 +8,19 @@
#include <cmath> #include <cmath>
#include <GL/glut.h> #include <GL/glut.h>
#include "Quaternion.h" #include "Math/Quaternion.h"
#include "Vectors.h" #include "Math/Vectors.h"
class Camera { class Camera {
public: public:
Camera(const Vec3d& eye_pos,const Vec3d& look_direction,const Vec3d& up_vector); Camera(const Vec3d& eye_pos,const Vec3d& look_direction,const Vec3d& up_vector);
/// Translates the camera according to the world axises.
/// \param translation Translation in the world coordinates system.
void translate(const Vec3d& translation);
/// Translates the camera relative to its current position and look direction. /// Translates the camera relative to its current position and look direction.
/// \param translation Translation where x is pointing in the direction of vision. /// \param translation Translation where x is pointing in the direction of vision.
void translate(const Vec3d& translation); void local_translate(const Vec3d& translation);
/// Rotates the gaze around its local x and z but around global y, relatively to the current orientation. /// Rotates the gaze around its local x and z but around global y, relatively to the current orientation.
/// This is to provide a coherent movement in regards to mouse movement. /// This is to provide a coherent movement in regards to mouse movement.
/// \param rotation Angles are radians to rotate about each axis. /// \param rotation Angles are radians to rotate about each axis.
@ -27,6 +30,10 @@ public:
void look(); void look();
void set_position(const Vec3d& eye_pos); void set_position(const Vec3d& eye_pos);
const Vec3d& get_eyepos() const;
const Vec3d& get_gaze() const;
const Vec3d& get_gazeup() const;
private: private:
Vec3d eye; Vec3d eye;
Vec3d gaze; Vec3d gaze;

View file

@ -5,7 +5,7 @@
#include "Model3D.h" #include "Model3D.h"
Model3D::Model3D() : vertex_count(0), face_count(0), texture_count(0), is_textured(false) Model3D::Model3D() :is_textured(false), vertex_count(0), face_count(0), texture_count(0)
{} {}
Model3D::Model3D(const std::string& file_name) : Model3D() Model3D::Model3D(const std::string& file_name) : Model3D()
@ -30,10 +30,23 @@ Model3D::~Model3D()
delete(face_textures); delete(face_textures);
delete(normals); delete(normals);
} }
if (has_displaylist)
{
glDeleteLists(display_list_index,1);
}
} }
void Model3D::draw_model() void Model3D::draw_model()
{ {
if (has_displaylist)
{
glCallList(display_list_index);
return; // Executing the regular draw calls is unnecessary
}
// If there is no display list available, draw each triangles and texture them if necessary.
if (is_textured) if (is_textured)
{ {
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
@ -84,6 +97,17 @@ void Model3D::draw_model()
} }
} }
void Model3D::prepare_displaylist()
{
display_list_index = glGenLists(1);
glNewList(display_list_index,GL_COMPILE);
draw_model();
glEndList();
has_displaylist = true;
}
bool Model3D::load_ascii_off_file(const std::string& file_name) bool Model3D::load_ascii_off_file(const std::string& file_name)
{ {
std::fstream file_stream(file_name, std::ios_base::in); std::fstream file_stream(file_name, std::ios_base::in);

View file

@ -10,7 +10,7 @@
#include <iostream> #include <iostream>
#include "GL/glut.h" #include "GL/glut.h"
#include "Vectors.h" #include "Math/Vectors.h"
#include "Texture.h" #include "Texture.h"
class Model3D { class Model3D {
@ -26,9 +26,13 @@ public:
void set_scaling(float x_scale, float y_scale, float z_scale); void set_scaling(float x_scale, float y_scale, float z_scale);
void set_rotation(float angle, float x, float y, float z); void set_rotation(float angle, float x, float y, float z);
/// Draws the model, using a display list if available.
void draw_model(); void draw_model();
/// Sets up an OpenGL display list for the model
void prepare_displaylist();
bool is_textured; bool is_textured;
bool has_displaylist = false;
private: private:
uint32_t vertex_count; uint32_t vertex_count;
uint32_t face_count; uint32_t face_count;
@ -51,6 +55,8 @@ private:
Vec3f scaling{}; Vec3f scaling{};
Vec3f rotation_axis{}; Vec3f rotation_axis{};
float rotation_angle{}; float rotation_angle{};
GLuint display_list_index;
}; };

View file

@ -73,6 +73,7 @@ bool Texture::load_rgb_tga(const std::string& rgb_filename)
{ {
bool return_value = load_tga(rgb_filename,image_data); bool return_value = load_tga(rgb_filename,image_data);
invert_channels(0,2); invert_channels(0,2);
generate_texture();
return return_value; return return_value;
} }
@ -117,9 +118,25 @@ bool Texture::load_rgba_tga(const std::string& rgb_filename, const std::string&
// Now we have an RGBA image, update color_bits // Now we have an RGBA image, update color_bits
color_bits = 32; color_bits = 32;
invert_channels(0,2);
generate_texture();
return true; return true;
} }
void Texture::generate_texture()
{
glGenTextures(1,opengl_id);
glBindTexture(GL_TEXTURE_2D,opengl_id[0]);
if (color_bits == 24)
{
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGB8,width,height,GL_RGB,GL_UNSIGNED_BYTE,image_data);
}
else if (color_bits == 32)
{
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,width,height,GL_RGBA,GL_UNSIGNED_BYTE,image_data);
}
}
void Texture::invert_channels(uint8_t first_channel, uint8_t second_channel) void Texture::invert_channels(uint8_t first_channel, uint8_t second_channel)
{ {
uint8_t increment = color_bits/8; uint8_t increment = color_bits/8;

View file

@ -33,6 +33,9 @@ private:
/// Load and RGB TGA image file to an array /// Load and RGB TGA image file to an array
bool load_tga(const std::string& filename, uint8_t*& data_array); bool load_tga(const std::string& filename, uint8_t*& data_array);
/// Initialize the texture for OpenGL
void generate_texture();
void invert_channels(uint8_t first_channel,uint8_t second_channel); void invert_channels(uint8_t first_channel,uint8_t second_channel);
}; };

85
src/Engine.h Normal file
View file

@ -0,0 +1,85 @@
//
// Created by trotFunky on 02/11/2019.
//
#ifndef TESTS_OPENGL_ENGINE_H
#define TESTS_OPENGL_ENGINE_H
#include <GL/glut.h>
#include <GL/gl.h>
#include "InputStatus.h"
#include "Camera.h"
/// OpenGL Engine
namespace OGLE
{
/// Display function provided at setup.
void (*custom_display)();
static double aspect_ratio;
static Camera camera({0,0,0},{1,0,0},{0,1,0});
void reshape(int new_x, int new_y)
{
glViewport(0,0,new_x,new_y);
aspect_ratio = (double)new_x/new_y;
InputStatus::window_size.x = new_x;
InputStatus::window_size.y = new_y;
}
/// Used for glutDisplay. Wraps the custom_display function with the required OpenGL calls.
void display_wrapper()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
// Prepare view
glLoadIdentity();
gluPerspective(60,OGLE::aspect_ratio,0.1,30000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
OGLE::camera.look();
custom_display();
glutSwapBuffers();
}
void setup(int& argc, char** argv, void (*display_callback)(), const std::string& window_name = "OpenGL custom engine")
{
glutInit(&argc,argv);
// Generate window with GLUT
glutInitDisplayMode(GLUT_RGB| GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow(window_name.c_str());
glutIgnoreKeyRepeat(true);
glutSetCursor(GLUT_CURSOR_NONE);
// Init OpenGL
glClearColor(0,0,0,1);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
// Setup OPenGL to use textures
glEnable(GL_TEXTURE_2D);
glAlphaFunc(GL_GREATER, 0.5);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT/GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT/GL_CLAMP);
glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glViewport(0,0,glutGet(GLUT_WINDOW_WIDTH),glutGet(GLUT_WINDOW_HEIGHT));
custom_display = display_callback;
glutDisplayFunc(display_wrapper);
glutIdleFunc(display_wrapper);
glutReshapeFunc(reshape);
InputStatus::register_glut_callbacks();
}
}
#endif //TESTS_OPENGL_ENGINE_H

View file

@ -9,7 +9,7 @@
#include <iostream> #include <iostream>
#include <GL/glut.h> #include <GL/glut.h>
#include "Vectors.h" #include "Math/Vectors.h"
/// Handles the key and mouse events from glut and keep their status up to date. /// Handles the key and mouse events from glut and keep their status up to date.