]> git.localhorst.tv Git - blank.git/blob - src/world/World.cpp
some code reorganization
[blank.git] / src / world / World.cpp
1 #include "World.hpp"
2
3 #include "../graphics/BlockLighting.hpp"
4 #include "../graphics/DirectionalLighting.hpp"
5
6 #include <limits>
7 #include <glm/gtx/transform.hpp>
8
9
10 namespace blank {
11
12 World::World(const Config &config)
13 : blockType()
14 , blockShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }})
15 , stairShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}, { 0.0f, 0.0f })
16 , slabShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.0f, 0.5f }})
17 , generate(config.gen)
18 , chunks(config.load, blockType, generate)
19 , player()
20 , entities()
21 , light_direction(config.light_direction)
22 , fog_density(config.fog_density) {
23         BlockType::Faces block_fill = {  true,  true,  true,  true,  true,  true };
24         BlockType::Faces slab_fill  = { false,  true, false, false, false, false };
25         BlockType::Faces stair_fill = { false,  true, false, false, false,  true };
26
27         { // white block
28                 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &blockShape);
29                 type.block_light = true;
30                 type.fill = block_fill;
31                 blockType.Add(type);
32         }
33         { // white slab
34                 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &slabShape);
35                 type.block_light = true;
36                 type.fill = slab_fill;
37                 blockType.Add(type);
38         }
39         { // white stair
40                 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &stairShape);
41                 type.block_light = true;
42                 type.fill = stair_fill;
43                 blockType.Add(type);
44         }
45
46         { // red block
47                 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &blockShape);
48                 type.block_light = true;
49                 type.fill = block_fill;
50                 blockType.Add(type);
51         }
52         { // red slab
53                 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &slabShape);
54                 type.block_light = true;
55                 type.fill = slab_fill;
56                 blockType.Add(type);
57         }
58         { // red stair
59                 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &stairShape);
60                 type.block_light = true;
61                 type.fill = stair_fill;
62                 blockType.Add(type);
63         }
64
65         { // green block
66                 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &blockShape);
67                 type.block_light = true;
68                 type.fill = block_fill;
69                 blockType.Add(type);
70         }
71         { // green slab
72                 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &slabShape);
73                 type.block_light = true;
74                 type.fill = slab_fill;
75                 blockType.Add(type);
76         }
77         { // green stair
78                 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &stairShape);
79                 type.block_light = true;
80                 type.fill = stair_fill;
81                 blockType.Add(type);
82         }
83
84         { // blue block
85                 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &blockShape);
86                 type.block_light = true;
87                 type.fill = block_fill;
88                 blockType.Add(type);
89         }
90         { // blue slab
91                 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &slabShape);
92                 type.block_light = true;
93                 type.fill = slab_fill;
94                 blockType.Add(type);
95         }
96         { // blue stair
97                 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &stairShape);
98                 type.block_light = true;
99                 type.fill = stair_fill;
100                 blockType.Add(type);
101         }
102
103         { // glowing yellow block
104                 BlockType type(true, { 1.0f, 1.0f, 0.0f }, &blockShape);
105                 type.luminosity = 15;
106                 type.block_light = true;
107                 type.fill = block_fill;
108                 blockType.Add(type);
109         }
110
111         generate.Space(0);
112         generate.Light(13);
113         generate.Solids({ 1, 4, 7, 10 });
114
115         player = &AddEntity();
116         player->Position(config.spawn);
117
118         chunks.GenerateSurrounding(player->ChunkCoords());
119 }
120
121
122 namespace {
123
124 struct Candidate {
125         Chunk *chunk;
126         float dist;
127 };
128
129 std::vector<Candidate> candidates;
130
131 }
132
133 bool World::Intersection(
134                 const Ray &ray,
135                 const glm::mat4 &M,
136                 Chunk **chunk,
137                 int *blkid,
138                 float *dist,
139                 glm::vec3 *normal) {
140         candidates.clear();
141
142         for (Chunk &cur_chunk : chunks.Loaded()) {
143                 float cur_dist;
144                 if (cur_chunk.Intersection(ray, M * cur_chunk.Transform(player->ChunkCoords()), cur_dist)) {
145                         candidates.push_back({ &cur_chunk, cur_dist });
146                 }
147         }
148
149         if (candidates.empty()) return false;
150
151         Chunk *closest_chunk = nullptr;
152         float closest_dist = std::numeric_limits<float>::infinity();
153         int closest_blkid = -1;
154         glm::vec3 closest_normal;
155
156         for (Candidate &cand : candidates) {
157                 if (cand.dist > closest_dist) continue;
158                 int cur_blkid;
159                 float cur_dist;
160                 glm::vec3 cur_normal;
161                 if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(player->ChunkCoords()), cur_blkid, cur_dist, cur_normal)) {
162                         if (cur_dist < closest_dist) {
163                                 closest_chunk = cand.chunk;
164                                 closest_blkid = cur_blkid;
165                                 closest_dist = cur_dist;
166                                 closest_normal = cur_normal;
167                         }
168                 }
169         }
170
171         if (chunk) {
172                 *chunk = closest_chunk;
173         }
174         if (blkid) {
175                 *blkid = closest_blkid;
176         }
177         if (dist) {
178                 *dist = closest_dist;
179         }
180         if (normal) {
181                 *normal = closest_normal;
182         }
183         return closest_chunk;
184 }
185
186
187 Chunk &World::PlayerChunk() {
188         return chunks.ForceLoad(player->ChunkCoords());
189 }
190
191 Chunk &World::Next(const Chunk &to, const glm::tvec3<int> &dir) {
192         const Chunk::Pos tgt_pos = to.Position() + dir;
193         return chunks.ForceLoad(tgt_pos);
194 }
195
196
197 void World::Update(int dt) {
198         for (Entity &entity : entities) {
199                 entity.Update(dt);
200         }
201         chunks.Rebase(player->ChunkCoords());
202         chunks.Update();
203 }
204
205
206 void World::Render(BlockLighting &chunk_prog, DirectionalLighting &entity_prog) {
207         chunk_prog.Activate();
208         chunk_prog.SetFogDensity(fog_density);
209         chunk_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords())));
210
211         for (Chunk &chunk : chunks.Loaded()) {
212                 glm::mat4 m(chunk.Transform(player->ChunkCoords()));
213                 chunk_prog.SetM(m);
214                 glm::mat4 mvp(chunk_prog.GetVP() * m);
215                 if (!CullTest(Chunk::Bounds(), mvp)) {
216                         chunk.Draw();
217                 }
218         }
219
220         entity_prog.Activate();
221         entity_prog.SetLightDirection(light_direction);
222         entity_prog.SetFogDensity(fog_density);
223         entity_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords())));
224
225         for (Entity &entity : entities) {
226                 if (entity.HasShape()) {
227                         entity_prog.SetM(entity.Transform(player->ChunkCoords()));
228                         entity.Draw();
229                 }
230         }
231 }
232
233 }