]> git.localhorst.tv Git - blank.git/blob - src/app.cpp
8c40c61fbc5ab2c74ea00257ff40fe4823b79264
[blank.git] / src / app.cpp
1 #include "app.hpp"
2
3 #include "geometry.hpp"
4
5 #include <iostream>
6 #include <stdexcept>
7
8
9 namespace blank {
10
11 Application::Application()
12 : init_sdl()
13 , init_img()
14 , init_gl()
15 , window()
16 , ctx(window.CreateContext())
17 , init_glew()
18 , program()
19 , move_velocity(0.003f)
20 , pitch_sensitivity(-0.0025f)
21 , yaw_sensitivity(-0.001f)
22 , cam()
23 , world()
24 , outline()
25 , outline_visible(false)
26 , outline_transform(1.0f)
27 , running(false)
28 , front(false)
29 , back(false)
30 , left(false)
31 , right(false)
32 , up(false)
33 , down(false)
34 , place(false)
35 , remove(false)
36 , pick(false)
37 , remove_id(0)
38 , place_id(1) {
39         GLContext::EnableVSync();
40
41         GLuint VertexArrayID;
42         glGenVertexArrays(1, &VertexArrayID);
43         glBindVertexArray(VertexArrayID);
44
45         cam.Position(glm::vec3(0, 4, 4));
46
47         world.Generate();
48
49         outline.vertices = std::vector<glm::vec3>({
50                 { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f },
51                 { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 0.0f },
52                 { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f },
53                 { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f },
54                 { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f },
55                 { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 1.0f },
56                 { 1.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f },
57                 { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 1.0f },
58                 { 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 1.0f },
59                 { 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f },
60                 { 1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 1.0f },
61                 { 0.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f },
62         });
63         outline.colors.resize(24, { -1, -1, -1 });
64         outline.Invalidate();
65
66         glClearColor(0.0, 0.0, 0.0, 1.0);
67 }
68
69
70 void Application::Run() {
71         running = true;
72         Uint32 last = SDL_GetTicks();
73         window.GrabMouse();
74         while (running) {
75                 Uint32 now = SDL_GetTicks();
76                 int delta = now - last;
77                 Loop(delta);
78                 last = now;
79         }
80 }
81
82 void Application::Loop(int dt) {
83         HandleEvents();
84         Update(dt);
85         Render();
86 }
87
88
89 void Application::HandleEvents() {
90         SDL_Event event;
91         while (SDL_PollEvent(&event)) {
92                 switch (event.type) {
93                         case SDL_KEYDOWN:
94                         case SDL_KEYUP:
95                                 switch (event.key.keysym.sym) {
96                                         case SDLK_w:
97                                                 front = event.key.state == SDL_PRESSED;
98                                                 break;
99                                         case SDLK_s:
100                                                 back = event.key.state == SDL_PRESSED;
101                                                 break;
102                                         case SDLK_a:
103                                                 left = event.key.state == SDL_PRESSED;
104                                                 break;
105                                         case SDLK_d:
106                                                 right = event.key.state == SDL_PRESSED;
107                                                 break;
108                                         case SDLK_q:
109                                                 up = event.key.state == SDL_PRESSED;
110                                                 break;
111                                         case SDLK_e:
112                                                 down = event.key.state == SDL_PRESSED;
113                                                 break;
114                                 }
115                                 break;
116                         case SDL_MOUSEBUTTONDOWN:
117                                 if (event.button.button == 1) {
118                                         // left
119                                         remove = true;
120                                 } else if (event.button.button == 2) {
121                                         // middle
122                                         pick = true;
123                                 } else if (event.button.button == 3) {
124                                         // right
125                                         place = true;
126                                 }
127                                 break;
128                         case SDL_MOUSEMOTION:
129                                 cam.RotateYaw(event.motion.xrel * yaw_sensitivity);
130                                 cam.RotatePitch(event.motion.yrel * pitch_sensitivity);
131                                 break;
132                         case SDL_QUIT:
133                                 running = false;
134                                 break;
135                         case SDL_WINDOWEVENT:
136                                 switch (event.window.event) {
137                                         case SDL_WINDOWEVENT_RESIZED:
138                                                 cam.Viewport(event.window.data1, event.window.data2);
139                                                 break;
140                                         default:
141                                                 break;
142                                 }
143                                 break;
144                         default:
145                                 break;
146                 }
147         }
148 }
149
150 void Application::Update(int dt) {
151         glm::vec3 vel;
152         if (right && !left) {
153                 vel.x = move_velocity;
154         } else if (left && !right) {
155                 vel.x = -move_velocity;
156         }
157         if (up && !down) {
158                 vel.y = move_velocity;
159         } else if (down && !up) {
160                 vel.y = -move_velocity;
161         }
162         if (back && !front) {
163                 vel.z = move_velocity;
164         } else if (front && !back) {
165                 vel.z = -move_velocity;
166         }
167         cam.OrientationVelocity(vel);
168
169         cam.Update(dt);
170
171         Ray aim = cam.Aim();
172         Chunk *chunk;
173         int blkid;
174         float dist;
175         glm::vec3 normal;
176         if (world.Intersection(aim, glm::mat4(1.0f), &chunk, &blkid, &dist, &normal)) {
177                 glm::vec3 pos = Chunk::ToCoords(blkid);
178                 outline_visible = true;
179                 outline_transform = glm::translate(chunk->Transform(), pos);
180         } else {
181                 outline_visible = false;
182         }
183
184         if (pick) {
185                 if (chunk) {
186                         place_id = chunk->BlockAt(blkid).type->id;
187                 }
188                 pick = false;
189         }
190         if (remove) {
191                 if (chunk) {
192                         chunk->BlockAt(blkid).type = world.BlockTypes()[remove_id];
193                         chunk->Invalidate();
194                 }
195                 remove = false;
196         }
197         if (place) {
198                 if (chunk) {
199                         Chunk *mod_chunk = chunk;
200                         glm::vec3 next_pos = Chunk::ToCoords(blkid) + normal;
201                         if (!Chunk::InBounds(next_pos)) {
202                                 mod_chunk = &world.Next(*chunk, normal);
203                                 next_pos -= normal * Chunk::Extent();
204                         }
205                         mod_chunk->BlockAt(next_pos).type = world.BlockTypes()[place_id];
206                         mod_chunk->Invalidate();
207                 }
208                 place = false;
209         }
210 }
211
212 void Application::Render() {
213         GLContext::Clear();
214
215         program.Activate();
216
217         program.SetVP(cam.View(), cam.Projection());
218
219         for (Chunk &chunk : world.LoadedChunks()) {
220                 program.SetM(chunk.Transform());
221                 chunk.Draw();
222         }
223
224         if (outline_visible) {
225                 program.SetM(outline_transform);
226                 outline.Draw();
227         }
228
229         window.Flip();
230 }
231
232 }