1 #include "app/assets.hpp"
2 #include "app/config.hpp"
3 #include "app/init.hpp"
4 #include "app/keymap.hpp"
5 #include "graphics/camera.hpp"
6 #include "graphics/shader.hpp"
7 #include "graphics/viewport.hpp"
8 #include "graphics/window.hpp"
9 #include "physics/ray.hpp"
10 #include "rand/SimplexNoise.hpp"
11 #include "world/Cursor.hpp"
12 #include "world/Floor.hpp"
16 #include <glm/glm.hpp>
17 #include <glm/gtc/matrix_transform.hpp>
18 #include <glm/gtx/io.hpp>
20 using namespace tacos;
22 int main(int argc, char *argv[]) {
24 config.ReadArgs(argc, argv);
27 AssetLoader asset_loader(config);
28 Window window(1440, 900);
29 Viewport viewport(1440, 900);
34 constexpr float noise_scale = 1.0f/64.0f;
35 constexpr float height_scale = 5.0f;
38 Shader floor_vert(asset_loader.LoadVertexShader("floor"));
39 Shader floor_frag(asset_loader.LoadFragmentShader("floor"));
40 Program floor_program;
41 floor_program.Attach(floor_vert);
42 floor_program.Attach(floor_frag);
44 GLint mv_location = floor_program.UniformLocation("MV");
45 GLint mvp_location = floor_program.UniformLocation("MVP");
47 Shader cursor_vert(asset_loader.LoadVertexShader("cursor"));
48 Shader cursor_frag(asset_loader.LoadFragmentShader("cursor"));
49 Program cursor_program;
50 cursor_program.Attach(cursor_vert);
51 cursor_program.Attach(cursor_frag);
52 cursor_program.Link();
53 GLint vp_location = cursor_program.UniformLocation("VP");
56 SimplexNoise noise(0);
57 for (int z = 0; z < floor.Depth(); ++z) {
58 for (int x = 0; x < floor.Width(); ++x) {
59 floor.SetElevation(x, z, noise(glm::vec3(x * noise_scale, 0.0f, z * noise_scale)) * height_scale);
62 floor.GenerateVertices();
67 camera.Warp(glm::vec3(20.0f, 0.0f, 20.0f));
77 glm::vec2 screen_mouse;
80 SDL_GetMouseState(&x, &y);
87 constexpr float cam_speed = 15.0f; // units per second
88 constexpr float cam_rot_speed = 2.0f; // radians per second
90 glm::vec3 cam_fwd(0.0f);
91 glm::vec3 cam_rev(0.0f);
92 float cam_near = 0.0f;
94 glm::vec2 cam_rot_ccw(0.0f);
95 glm::vec2 cam_rot_cw(0.0f);
98 Uint32 last = SDL_GetTicks();
101 Uint32 now = SDL_GetTicks();
103 while (SDL_PollEvent(&event)) {
104 switch (event.type) {
106 switch (keymap.Lookup(event.key)) {
107 case Keymap::CAMERA_RIGHT:
110 case Keymap::CAMERA_LEFT:
113 case Keymap::CAMERA_UP:
116 case Keymap::CAMERA_DOWN:
119 case Keymap::CAMERA_BACK:
122 case Keymap::CAMERA_FORWARD:
125 case Keymap::CAMERA_NEARER:
128 case Keymap::CAMERA_FARTHER:
131 case Keymap::CAMERA_PITCH_CCW:
132 cam_rot_ccw.x = 1.0f;
134 case Keymap::CAMERA_PITCH_CW:
137 case Keymap::CAMERA_YAW_CCW:
138 cam_rot_ccw.y = 1.0f;
140 case Keymap::CAMERA_YAW_CW:
152 switch (keymap.Lookup(event.key)) {
153 case Keymap::CAMERA_RIGHT:
156 case Keymap::CAMERA_LEFT:
159 case Keymap::CAMERA_UP:
162 case Keymap::CAMERA_DOWN:
165 case Keymap::CAMERA_BACK:
168 case Keymap::CAMERA_FORWARD:
171 case Keymap::CAMERA_NEARER:
174 case Keymap::CAMERA_FARTHER:
177 case Keymap::CAMERA_PITCH_CCW:
178 cam_rot_ccw.x = 0.0f;
180 case Keymap::CAMERA_PITCH_CW:
183 case Keymap::CAMERA_YAW_CCW:
184 cam_rot_ccw.y = 0.0f;
186 case Keymap::CAMERA_YAW_CW:
194 case SDL_MOUSEMOTION:
195 screen_mouse.x = event.motion.x;
196 screen_mouse.y = event.motion.y;
201 case SDL_WINDOWEVENT:
202 if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
203 viewport.Resize(event.window.data1, event.window.data2);
212 float dt = (now - last) * 0.001f;
213 camera.Move((cam_fwd - cam_rev) * cam_speed * dt);
214 camera.BackOff((cam_far - cam_near) * cam_speed * dt);
215 camera.Rotate((cam_rot_ccw - cam_rot_cw) * cam_rot_speed * dt);
218 VP = viewport.Perspective() * V;
220 inverse_VP = glm::inverse(VP);
221 glm::vec2 clip_mouse((screen_mouse / glm::vec2(viewport.Width(), viewport.Height()) - 0.5f) * 2.0f);
222 // viewport space has origin in lower left, but sdl gives coordinates with orgin in upper left,
223 // so Y is inverted here (since it maps from -1 to 1 simply by negating)
224 glm::vec4 ray_begin(inverse_VP * glm::vec4(clip_mouse.x, -clip_mouse.y, -1.0f, 1.0f));
225 glm::vec4 ray_end(inverse_VP * glm::vec4(clip_mouse.x, -clip_mouse.y, 0.0f, 1.0f));
226 world_mouse.origin = glm::vec3(ray_begin) / ray_begin.w;
227 world_mouse.direction = glm::normalize((glm::vec3(ray_end) / ray_end.w) - world_mouse.origin);
230 if (floor.Intersection(world_mouse, pointer)) {
231 cursor.FloorTile(floor, int(pointer.x), int(pointer.z));
237 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
239 for (int z = 0; z < floor.VAODepth(); ++z) {
240 for (int x = 0; x < floor.VAOWidth(); ++x) {
241 M = glm::translate(glm::mat4(1.0f), floor.VAOPosition(x, z));
242 MV = camera.View() * M;
243 MVP = viewport.Perspective() * MV;
244 floor_program.Uniform(mv_location, MV);
245 floor_program.Uniform(mvp_location, MVP);
249 if (cursor.Visible()) {
250 cursor_program.Use();
251 cursor_program.Uniform(vp_location, VP);