A 3D game engine from scratch.
1// (c) 2020 Vlad-Stefan Harbuz <vlad@vladh.net>
2
3#include <thread>
4#include "../src_external/pstr.h"
5#include "types.hpp"
6#include "logs.hpp"
7#include "util.hpp"
8#include "renderer.hpp"
9#include "internals.hpp"
10#include "engine.hpp"
11#include "state.hpp"
12#include "peony_parser.hpp"
13#include "constants.hpp"
14#include "core.hpp"
15#include "intrinsics.hpp"
16
17
18State *core::state = nullptr;
19
20
21WindowSize *
22core::get_window_size()
23{
24 return &core::state->window_size;
25}
26
27
28memory::Pool *
29core::get_asset_memory_pool()
30{
31 return core::state->asset_memory_pool;
32}
33
34
35int
36core::run()
37{
38 // Allocate memory
39 State *state = (State*)calloc(1, sizeof(State));
40 defer { free(state); };
41 memory::Pool asset_memory_pool = { .size = util::mb_to_b(1024) };
42 defer { memory::destroy_memory_pool(&asset_memory_pool); };
43
44 // Make state
45 if (!init_state(state, &asset_memory_pool)) {
46 return EXIT_FAILURE;
47 }
48 defer { destroy_state(state); };
49
50 // Set up loading threads
51 std::mutex loading_thread_mutex;
52 std::thread loading_threads[N_LOADING_THREADS];
53 range (0, N_LOADING_THREADS) {
54 loading_threads[idx] = std::thread(
55 tasks::run_loading_loop,
56 &loading_thread_mutex,
57 &state->engine_state.should_stop,
58 idx);
59 }
60 defer { range (0, N_LOADING_THREADS) { loading_threads[idx].join(); } };
61
62 // Run main loop
63 engine::run_main_loop(state->window);
64
65 return EXIT_SUCCESS;
66}
67
68
69void
70core::framebuffer_size_callback(GLFWwindow* window, int width, int height)
71{
72 memory::Pool *asset_memory_pool = get_asset_memory_pool();
73 WindowSize *window_size = get_window_size();
74 logs::info("Window is now: %d x %d", window_size->width, window_size->height);
75 window_size->width = width;
76 window_size->height = height;
77 cameras::Camera *camera = cameras::get_main();
78 cameras::update_matrices(camera);
79 cameras::update_ui_matrices(camera);
80 gui::update_screen_dimensions(window_size->width, window_size->height);
81
82 auto *builtin_textures = renderer::get_builtin_textures();
83 renderer::resize_renderer_buffers(asset_memory_pool, builtin_textures,
84 width, height);
85}
86
87
88void
89core::mouse_button_callback(GLFWwindow *window, int button, int action, int mods)
90{
91 input::update_mouse_button(button, action, mods);
92 gui::update_mouse_button();
93}
94
95
96void
97core::mouse_callback(GLFWwindow *window, f64 x, f64 y)
98{
99 v2 mouse_pos = v2(x, y);
100 input::update_mouse(mouse_pos);
101
102 if (input::is_cursor_enabled()) {
103 gui::update_mouse();
104 } else {
105 cameras::Camera *camera = cameras::get_main();
106 cameras::update_mouse(camera, input::get_mouse_3d_offset());
107 }
108}
109
110
111void
112core::key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
113{
114 input::update_keys(key, scancode, action, mods);
115}
116
117
118void
119core::char_callback(GLFWwindow* window, u32 codepoint) {
120 input::update_text_input(codepoint);
121}
122
123
124bool
125core::init_state(State *state, memory::Pool *asset_memory_pool)
126{
127 core::state = state;
128 state->window = renderer::init_window(&state->window_size);
129 if (!state->window) { return false; }
130
131 state->asset_memory_pool = asset_memory_pool;
132
133 spatial::init(&state->spatial_state, asset_memory_pool);
134 drawable::init(&state->drawable_state, asset_memory_pool);
135 lights::init(&state->lights_state, asset_memory_pool);
136 anim::init(&state->anim_state, asset_memory_pool);
137 physics::init(&state->physics_state, asset_memory_pool);
138 entities::init(&state->entities_state, asset_memory_pool);
139 behavior::init(
140 &state->behavior_state,
141 asset_memory_pool,
142 // NOTE: behavior needs the global state to pass to the behavior functions
143 state);
144 engine::init(&state->engine_state, asset_memory_pool);
145 mats::init(&state->materials_state, asset_memory_pool);
146 input::init(&state->input_state, state->window);
147 renderer::init(
148 &state->renderer_state, asset_memory_pool,
149 state->window_size.width, state->window_size.height, state->window);
150 internals::init();
151 gui::init(asset_memory_pool,
152 &state->gui_state,
153 renderer::get_gui_texture_atlas_size(),
154 renderer::get_gui_font_assets(),
155 state->window_size.width, state->window_size.height);
156 debugdraw::init(&state->debug_draw_state, asset_memory_pool);
157 tasks::init(&state->tasks_state, asset_memory_pool);
158 cameras::init(&state->cameras_state, state->window_size.width, state->window_size.height);
159
160 return true;
161}
162
163
164void
165core::destroy_state(State *state)
166{
167 glfwTerminate();
168}