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