3 #include "WorldCollision.hpp"
4 #include "../graphics/BlockLighting.hpp"
5 #include "../graphics/DirectionalLighting.hpp"
9 #include <glm/gtx/transform.hpp>
14 World::World(const Config &config)
16 , blockShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }})
17 , stairShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}, { 0.0f, 0.0f })
18 , slabShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.0f, 0.5f }})
19 , generate(config.gen)
20 , chunks(config.load, blockType, generate)
23 , light_direction(config.light_direction)
24 , fog_density(config.fog_density) {
25 BlockType::Faces block_fill = { true, true, true, true, true, true };
26 BlockType::Faces slab_fill = { false, true, false, false, false, false };
27 BlockType::Faces stair_fill = { false, true, false, false, false, true };
30 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &blockShape);
31 type.block_light = true;
32 type.fill = block_fill;
36 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &slabShape);
37 type.block_light = true;
38 type.fill = slab_fill;
42 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &stairShape);
43 type.block_light = true;
44 type.fill = stair_fill;
49 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &blockShape);
50 type.block_light = true;
51 type.fill = block_fill;
55 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &slabShape);
56 type.block_light = true;
57 type.fill = slab_fill;
61 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &stairShape);
62 type.block_light = true;
63 type.fill = stair_fill;
68 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &blockShape);
69 type.block_light = true;
70 type.fill = block_fill;
74 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &slabShape);
75 type.block_light = true;
76 type.fill = slab_fill;
80 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &stairShape);
81 type.block_light = true;
82 type.fill = stair_fill;
87 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &blockShape);
88 type.block_light = true;
89 type.fill = block_fill;
93 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &slabShape);
94 type.block_light = true;
95 type.fill = slab_fill;
99 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &stairShape);
100 type.block_light = true;
101 type.fill = stair_fill;
105 { // glowing yellow block
106 BlockType type(true, { 1.0f, 1.0f, 0.0f }, &blockShape);
107 type.luminosity = 15;
108 type.block_light = true;
109 type.fill = block_fill;
115 generate.Solids({ 1, 4, 7, 10 });
117 player = &AddEntity();
118 player->Name("player");
119 player->Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } });
120 player->WorldCollidable(true);
121 player->Position(config.spawn);
123 chunks.GenerateSurrounding(player->ChunkCoords());
134 std::vector<Candidate> candidates;
138 bool World::Intersection(
148 for (Chunk &cur_chunk : chunks.Loaded()) {
150 if (cur_chunk.Intersection(ray, M * cur_chunk.Transform(player->ChunkCoords()), cur_dist)) {
151 candidates.push_back({ &cur_chunk, cur_dist });
155 if (candidates.empty()) return false;
158 dist = std::numeric_limits<float>::infinity();
161 for (Candidate &cand : candidates) {
162 if (cand.dist > dist) continue;
165 glm::vec3 cur_normal;
166 if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(player->ChunkCoords()), cur_blkid, cur_dist, cur_normal)) {
167 if (cur_dist < dist) {
179 bool World::Intersection(const Entity &e, std::vector<WorldCollision> &col) {
180 AABB box = e.Bounds();
181 glm::mat4 M = e.Transform(player->ChunkCoords());
182 // TODO: this only needs to check the chunks surrounding the entity's chunk position
183 // need find out if that is quicker than the rough chunk bounds test
184 for (Chunk &cur_chunk : chunks.Loaded()) {
185 if (cur_chunk.Intersection(box, M, cur_chunk.Transform(player->ChunkCoords()), col)) {
193 Chunk &World::PlayerChunk() {
194 return chunks.ForceLoad(player->ChunkCoords());
197 Chunk &World::Next(const Chunk &to, const glm::tvec3<int> &dir) {
198 const Chunk::Pos tgt_pos = to.Position() + dir;
199 return chunks.ForceLoad(tgt_pos);
205 std::vector<WorldCollision> col;
209 void World::Update(int dt) {
210 for (Entity &entity : entities) {
213 for (Entity &entity : entities) {
215 if (entity.WorldCollidable() && Intersection(entity, col)) {
216 // entity collides with the world
217 Resolve(entity, col);
220 chunks.Rebase(player->ChunkCoords());
224 void World::Resolve(const Entity &e, std::vector<WorldCollision> &col) {
225 std::cout << e.Name() << " entity intersects world at " << col.size() << " blocks" << std::endl;
229 void World::Render(BlockLighting &chunk_prog, DirectionalLighting &entity_prog) {
230 chunk_prog.Activate();
231 chunk_prog.SetFogDensity(fog_density);
232 chunk_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords())));
234 for (Chunk &chunk : chunks.Loaded()) {
235 glm::mat4 m(chunk.Transform(player->ChunkCoords()));
237 glm::mat4 mvp(chunk_prog.GetVP() * m);
238 if (!CullTest(Chunk::Bounds(), mvp)) {
243 entity_prog.Activate();
244 entity_prog.SetLightDirection(light_direction);
245 entity_prog.SetFogDensity(fog_density);
246 entity_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords())));
248 for (Entity &entity : entities) {
249 if (entity.HasShape()) {
250 entity_prog.SetM(entity.Transform(player->ChunkCoords()));