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