]> git.localhorst.tv Git - blank.git/blob - src/app.cpp
limit number of chunks generated per frame
[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 , cam()
20 , hud()
21 , world()
22 , outline()
23 , outline_visible(false)
24 , outline_transform(1.0f)
25 , running(false)
26 , place(false)
27 , remove(false)
28 , pick(false)
29 , remove_id(0)
30 , place_id(1) {
31         GLContext::EnableVSync();
32
33         GLuint VertexArrayID;
34         glGenVertexArrays(1, &VertexArrayID);
35         glBindVertexArray(VertexArrayID);
36
37         world.Generate({ -4, -4, -4 }, { 5, 5, 5});
38
39         hud.Viewport(960, 600);
40         hud.Display(*world.BlockTypes()[place_id]);
41
42         glClearColor(0.0, 0.0, 0.0, 1.0);
43 }
44
45
46 void Application::Run() {
47         running = true;
48         Uint32 last = SDL_GetTicks();
49         window.GrabMouse();
50         while (running) {
51                 Uint32 now = SDL_GetTicks();
52                 int delta = now - last;
53                 Loop(delta);
54                 last = now;
55         }
56 }
57
58 void Application::Loop(int dt) {
59         HandleEvents();
60         Update(dt);
61         Render();
62 }
63
64
65 void Application::HandleEvents() {
66         SDL_Event event;
67         while (SDL_PollEvent(&event)) {
68                 switch (event.type) {
69                         case SDL_KEYDOWN:
70                         case SDL_KEYUP:
71                                 world.Controller().HandleKeyboard(event.key);
72                                 break;
73                         case SDL_MOUSEBUTTONDOWN:
74                                 if (event.button.button == 1) {
75                                         // left
76                                         remove = true;
77                                 } else if (event.button.button == 2) {
78                                         // middle
79                                         pick = true;
80                                 } else if (event.button.button == 3) {
81                                         // right
82                                         place = true;
83                                 }
84                                 break;
85                         case SDL_MOUSEMOTION:
86                                 world.Controller().HandleMouse(event.motion);
87                                 break;
88                         case SDL_QUIT:
89                                 running = false;
90                                 break;
91                         case SDL_WINDOWEVENT:
92                                 switch (event.window.event) {
93                                         case SDL_WINDOWEVENT_RESIZED:
94                                                 cam.Viewport(event.window.data1, event.window.data2);
95                                                 hud.Viewport(event.window.data1, event.window.data2);
96                                                 break;
97                                         default:
98                                                 break;
99                                 }
100                                 break;
101                         default:
102                                 break;
103                 }
104         }
105 }
106
107 void Application::Update(int dt) {
108         world.Update(dt);
109
110         Ray aim = world.Controller().Aim();
111         Chunk *chunk;
112         int blkid;
113         float dist;
114         glm::vec3 normal;
115         if (world.Intersection(aim, glm::mat4(1.0f), &chunk, &blkid, &dist, &normal)) {
116                 glm::vec3 pos = Chunk::ToCoords(blkid);
117                 outline_visible = true;
118                 outline.Clear();
119                 chunk->BlockAt(blkid).type->FillOutlineModel(outline);
120                 outline_transform = glm::translate(chunk->Transform(), pos);
121                 outline_transform = glm::scale(outline_transform, glm::vec3(1.0001f));
122         } else {
123                 outline_visible = false;
124         }
125
126         if (pick) {
127                 if (chunk) {
128                         place_id = chunk->BlockAt(blkid).type->id;
129                         hud.Display(*world.BlockTypes()[place_id]);
130                 }
131                 pick = false;
132         }
133         if (remove) {
134                 if (chunk) {
135                         chunk->BlockAt(blkid).type = world.BlockTypes()[remove_id];
136                         chunk->Invalidate();
137                 }
138                 remove = false;
139         }
140         if (place) {
141                 if (chunk) {
142                         Chunk *mod_chunk = chunk;
143                         glm::vec3 next_pos = Chunk::ToCoords(blkid) + normal;
144                         if (!Chunk::InBounds(next_pos)) {
145                                 mod_chunk = &world.Next(*chunk, normal);
146                                 next_pos -= normal * Chunk::Extent();
147                         }
148                         mod_chunk->BlockAt(next_pos).type = world.BlockTypes()[place_id];
149                         mod_chunk->Invalidate();
150                 }
151                 place = false;
152         }
153 }
154
155 void Application::Render() {
156         GLContext::Clear();
157
158         program.Activate();
159
160         program.SetProjection(cam.Projection());
161         world.Render(program);
162
163         if (outline_visible) {
164                 program.SetM(outline_transform);
165                 outline.Draw();
166         }
167
168         hud.Render(program);
169
170         window.Flip();
171 }
172
173 }