Skip to content

Commit 9c40cff

Browse files
committed
use pimpl
1 parent ac15bb9 commit 9c40cff

File tree

7 files changed

+259
-173
lines changed

7 files changed

+259
-173
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ build/
66
out/
77
CMakeSettings.json
88
.vscode/
9-
.~*
109
# clion files
1110
cmake-build-debug/
1211
cmake-build-release/
1312
.idea/
1413
.clang-format
15-
# baby files
14+
# teacher files
1615
prebuild/
16+
.~*

CMakeLists.txt

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,21 @@ cmake_minimum_required(VERSION 3.10)
33
if (NOT CMAKE_BUILD_TYPE)
44
set(CMAKE_BUILD_TYPE Release)
55
endif()
6-
set(CMAKE_CXX_STANDARD 17)
6+
set(CMAKE_CXX_STANDARD 14)
7+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
78

8-
project(main LANGUAGES CXX C)
9+
project(opengltutor
10+
LANGUAGES CXX C
11+
DESCRIPTION "An indispensable online webinar open course for computer graphics beginners to learn every bit of modern OpenGL and build a popular 3D game engine."
12+
HOMEPAGE_URL https://github.com/parallel101/opengltutor
13+
)
14+
15+
if (PROJECT_BINARY_DIR STREQUAL PROJECT_SOURCE_DIR)
16+
message(FATAL_ERROR "The binary directory of CMake cannot be the same as source directory! "
17+
"Please consider use 'cmake -B build' to specify a different binary directory. "
18+
"Otherwise this project may fail to build, or make Git hard to exclude binary files. "
19+
"For Windows, it is highly recommended to use Visual Studio as IDE for CMake projects.")
20+
endif()
921

1022
if (UNIX AND NOT APPLE)
1123
find_package(X11 QUIET)
@@ -16,14 +28,28 @@ if (UNIX AND NOT APPLE)
1628
add_definitions(-DCMAKE_FOUND_X11)
1729
endif()
1830

31+
if (NOT MSVC)
32+
find_program(CCACHE_PROGRAM ccache) # See https://ccache.dev
33+
if (CCACHE_PROGRAM)
34+
message(STATUS "Found CCache: ${CCACHE_PROGRAM}")
35+
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PROGRAM})
36+
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PROGRAM})
37+
endif()
38+
endif()
39+
40+
if (MSVC)
41+
add_compile_options($<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/utf-8$<SEMICOLON>/DNOMINMAX$<SEMICOLON>/D_USE_MATH_DEFINES>)
42+
add_compile_options($<$<COMPILE_LANG_AND_ID:C,MSVC>:/utf-8$<SEMICOLON>/DNOMINMAX$<SEMICOLON>/D_USE_MATH_DEFINES>)
43+
endif()
44+
1945
file(GLOB_RECURSE sources CONFIGURE_DEPENDS src/*.cpp)
2046
file(GLOB_RECURSE headers CONFIGURE_DEPENDS include/*.h include/*.hpp)
21-
add_executable(main ${sources} ${headers})
22-
target_include_directories(main PUBLIC include)
47+
add_executable(${PROJECT_NAME} ${sources} ${headers})
48+
target_include_directories(${PROJECT_NAME} PUBLIC include)
2349

2450
add_subdirectory(glm)
25-
target_link_libraries(main PUBLIC glm)
51+
target_link_libraries(${PROJECT_NAME} PUBLIC glm)
2652
add_subdirectory(glfw)
27-
target_link_libraries(main PUBLIC glfw)
53+
target_link_libraries(${PROJECT_NAME} PUBLIC glfw)
2854
add_subdirectory(glad)
29-
target_link_libraries(main PUBLIC glad)
55+
target_link_libraries(${PROJECT_NAME} PUBLIC glad)

include/Game.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include "check_gl.hpp"
4+
#include <glm/glm.hpp>
5+
#include <glm/ext.hpp>
6+
#include <memory>
7+
8+
struct Game {
9+
struct Private;
10+
std::unique_ptr<Private> m_private;
11+
GLFWwindow *m_window;
12+
13+
Game(GLFWwindow *window);
14+
~Game();
15+
16+
Game(Game &&) = delete;
17+
18+
void initialize();
19+
void render();
20+
void mouse_button_callback(int button, int action, int mods);
21+
};

include/OBJ.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <glm/glm.hpp>
2+
#include <glm/ext.hpp>
3+
#include <vector>
4+
#include <string>
5+
6+
struct OBJ {
7+
std::vector<glm::vec3> vertices;
8+
std::vector<glm::vec2> uvs;
9+
std::vector<glm::vec3> normals;
10+
std::vector<glm::umat3x3> faces;
11+
12+
void load_obj(std::string path);
13+
void draw_obj();
14+
};

src/Game.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include "Game.hpp"
2+
#include "OBJ.hpp"
3+
#include "check_gl.hpp"
4+
5+
struct Game::Private {
6+
OBJ monkey;
7+
};
8+
9+
Game::Game(GLFWwindow *window) : m_private(new Private), m_window(window) {
10+
glfwSetWindowUserPointer(window, this);
11+
}
12+
13+
Game::~Game() = default;
14+
15+
void Game::render() {
16+
int width, height;
17+
glfwGetWindowSize(m_window, &width, &height);
18+
CHECK_GL(glViewport(0, 0, width, height));
19+
20+
CHECK_GL(glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT));
21+
22+
glm::mat4x4 projection = glm::perspective(glm::radians(40.0f), (float)width / height, 0.01f, 100.0f);
23+
/* projection = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 0.0f, 100.0f); */
24+
/* projection = glm::frustum(-0.005f, 0.005f, -0.005f, 0.005f, 0.01f, 100.0f); */
25+
CHECK_GL(glMatrixMode(GL_PROJECTION));
26+
CHECK_GL(glLoadMatrixf(glm::value_ptr(projection)));
27+
28+
glm::vec3 eye(0, 0, 5);
29+
glm::vec3 center(0, 0, 0);
30+
glm::vec3 up(0, 1, 0);
31+
glm::mat4x4 view = glm::lookAt(eye, center, up);
32+
33+
static float angle = 0.0f;
34+
glm::mat4x4 model(1.0f);
35+
model = glm::rotate(model, glm::radians(angle), glm::vec3(0.0f, 1.0f, 0.0f));
36+
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
37+
angle += 0.5f;
38+
39+
CHECK_GL(glMatrixMode(GL_MODELVIEW));
40+
CHECK_GL(glLoadMatrixf(glm::value_ptr(view * model)));
41+
42+
m_monkey.draw_obj();
43+
}
44+
45+
void Game::mouse_button_callback(int button, int action, int mods) {
46+
double xpos, ypos;
47+
int width, height;
48+
glfwGetCursorPos(m_window, &xpos, &ypos);
49+
glfwGetWindowSize(m_window, &width, &height);
50+
51+
float x = (float)(2 * xpos / width - 1);
52+
float y = (float)(2 * (height - ypos) / height - 1);
53+
54+
if ( button == GLFW_MOUSE_BUTTON_LEFT
55+
&& action == GLFW_PRESS
56+
) { // when left mouse button is pressed:
57+
}
58+
}
59+
60+
void Game::initialize() {
61+
m_private->monkey.load_obj("/home/bate/Codes/opengltutor/assets/monkey.obj");
62+
CHECK_GL(glEnable(GL_DEPTH_TEST));
63+
CHECK_GL(glEnable(GL_MULTISAMPLE));
64+
CHECK_GL(glEnable(GL_BLEND));
65+
CHECK_GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
66+
CHECK_GL(glEnable(GL_LIGHTING));
67+
CHECK_GL(glEnable(GL_LIGHT0));
68+
CHECK_GL(glEnable(GL_COLOR_MATERIAL));
69+
CHECK_GL(glEnable(GL_CULL_FACE));
70+
CHECK_GL(glCullFace(GL_BACK));
71+
CHECK_GL(glFrontFace(GL_CCW));
72+
}

src/OBJ.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include "check_gl.hpp"
2+
#include "OBJ.hpp"
3+
#include <stdexcept>
4+
#include <iostream>
5+
#include <fstream>
6+
#include <sstream>
7+
8+
void OBJ::load_obj(std::string path) {
9+
std::ifstream file(path);
10+
if (!file.is_open()) {
11+
std::cerr << "Failed to open file: " << path << '\n';
12+
return;
13+
}
14+
15+
std::string line;
16+
while (std::getline(file, line)) {
17+
if (line.substr(0, 2) == "v ") {
18+
std::istringstream s(line.substr(2));
19+
glm::vec3 vertex;
20+
s >> vertex.x >> vertex.y >> vertex.z;
21+
vertices.push_back(vertex);
22+
23+
} else if (line.substr(0, 3) == "vt ") {
24+
std::istringstream s(line.substr(3));
25+
glm::vec2 uv;
26+
s >> uv.x >> uv.y;
27+
uvs.push_back(uv);
28+
29+
} else if (line.substr(0, 3) == "vn ") {
30+
std::istringstream s(line.substr(3));
31+
glm::vec3 normal;
32+
s >> normal.x >> normal.y >> normal.z;
33+
normals.push_back(glm::normalize(normal));
34+
35+
} else if (line.substr(0, 2) == "f ") {
36+
std::istringstream s(line.substr(2));
37+
std::string splitted;
38+
std::vector<glm::uvec3> indices;
39+
while (std::getline(s, splitted, ' ')) {
40+
glm::uvec3 index(1);
41+
std::istringstream ss(splitted);
42+
std::string slashsplitted;
43+
size_t indexsubs = 0;
44+
while (std::getline(ss, slashsplitted, '/') && indexsubs < 3) {
45+
std::istringstream(slashsplitted) >> index[indexsubs++];
46+
}
47+
indices.push_back(index - 1u);
48+
}
49+
for (size_t i = 2; i < indices.size(); i++) {
50+
glm::umat3x3 face = glm::umat3x3(indices[0], indices[i - 1], indices[i]);
51+
faces.push_back(face);
52+
}
53+
}
54+
}
55+
56+
if (!normals.size()) {
57+
normals.push_back(glm::vec3(0, 0, 1));
58+
}
59+
if (!uvs.size()) {
60+
uvs.push_back(glm::vec3(0));
61+
}
62+
63+
file.close();
64+
std::cout << "Loaded " << vertices.size() << " vertices, " << faces.size() << " faces.\n";
65+
}
66+
67+
void OBJ::draw_obj() {
68+
glBegin(GL_TRIANGLES);
69+
70+
glColor3f(0.9f, 0.6f, 0.1f);
71+
72+
for (auto face : faces) {
73+
auto const &a_pos = vertices.at(face[0][0]);
74+
auto const &b_pos = vertices.at(face[1][0]);
75+
auto const &c_pos = vertices.at(face[2][0]);
76+
auto const &a_uv = uvs.at(face[0][1]);
77+
auto const &b_uv = uvs.at(face[1][1]);
78+
auto const &c_uv = uvs.at(face[2][1]);
79+
auto const &a_norm = normals.at(face[0][2]);
80+
auto const &b_norm = normals.at(face[1][2]);
81+
auto const &c_norm = normals.at(face[2][2]);
82+
83+
glNormal3fv(glm::value_ptr(a_norm));
84+
85+
glVertex3fv(glm::value_ptr(a_pos));
86+
glTexCoord2fv(glm::value_ptr(b_uv));
87+
88+
glVertex3fv(glm::value_ptr(b_pos));
89+
glTexCoord2fv(glm::value_ptr(b_uv));
90+
91+
glVertex3fv(glm::value_ptr(c_pos));
92+
glTexCoord2fv(glm::value_ptr(c_uv));
93+
}
94+
95+
CHECK_GL(glEnd());
96+
}

0 commit comments

Comments
 (0)