X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld.cpp;h=137fd2a6cf29abcc9cfd2fca2fc950c75f94aa81;hb=e74f1ad236429f05db90c0ace825277e2a3fbc05;hp=2dd7b307a6ffa292fd24027414af746a5123504b;hpb=482114e156e91729f2529ea6bb1fe98dacdee97f;p=blank.git diff --git a/src/world.cpp b/src/world.cpp index 2dd7b30..137fd2a 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,102 +1,230 @@ #include "world.hpp" +#include +#include + namespace blank { -const BlockType BlockType::DEFAULT; - -void BlockType::FillVBO( - const glm::vec3 &pos, - std::vector &vertices, - std::vector &colors, - std::vector &normals -) const { - vertices.emplace_back(pos.x , pos.y , pos.z + 1); // front - vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); - vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); - vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); - vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z + 1); - vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); - vertices.emplace_back(pos.x , pos.y , pos.z ); // back - vertices.emplace_back(pos.x , pos.y + 1, pos.z ); - vertices.emplace_back(pos.x + 1, pos.y , pos.z ); - vertices.emplace_back(pos.x + 1, pos.y , pos.z ); - vertices.emplace_back(pos.x , pos.y + 1, pos.z ); - vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); - vertices.emplace_back(pos.x , pos.y + 1, pos.z ); // top - vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); - vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); - vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); - vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); - vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z + 1); - vertices.emplace_back(pos.x , pos.y , pos.z ); // bottom - vertices.emplace_back(pos.x + 1, pos.y , pos.z ); - vertices.emplace_back(pos.x , pos.y , pos.z + 1); - vertices.emplace_back(pos.x + 1, pos.y , pos.z ); - vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); - vertices.emplace_back(pos.x , pos.y , pos.z + 1); - vertices.emplace_back(pos.x , pos.y , pos.z ); // left - vertices.emplace_back(pos.x , pos.y , pos.z + 1); - vertices.emplace_back(pos.x , pos.y + 1, pos.z ); - vertices.emplace_back(pos.x , pos.y + 1, pos.z ); - vertices.emplace_back(pos.x , pos.y , pos.z + 1); - vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); - vertices.emplace_back(pos.x + 1, pos.y , pos.z ); // right - vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); - vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); - vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); - vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); - vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z + 1); - - colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // front - colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // back - colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // top - colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // bottom - colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // left - colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // right - - normals.insert(normals.end(), 6, glm::vec3( 0.0f, 0.0f, 1.0f)); // front - normals.insert(normals.end(), 6, glm::vec3( 0.0f, 0.0f, -1.0f)); // back - normals.insert(normals.end(), 6, glm::vec3( 0.0f, 1.0f, 0.0f)); // top - normals.insert(normals.end(), 6, glm::vec3( 0.0f, -1.0f, 0.0f)); // bottom - normals.insert(normals.end(), 6, glm::vec3(-1.0f, 0.0f, 0.0f)); // left - normals.insert(normals.end(), 6, glm::vec3( 1.0f, 0.0f, 0.0f)); // right +World::World(const Config &config) +: blockType() +, blockShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}) +, stairShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}, { 0.0f, 0.0f }) +, slabShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.0f, 0.5f }}) +, generate(config.gen) +, chunks(config.load, blockType, generate) +, player() +, entities() +, light_direction(config.light_direction) +, fog_density(config.fog_density) { + BlockType::Faces block_fill = { true, true, true, true, true, true }; + BlockType::Faces slab_fill = { false, true, false, false, false, false }; + BlockType::Faces stair_fill = { false, true, false, false, false, true }; + + { // white block + BlockType type(true, { 1.0f, 1.0f, 1.0f }, &blockShape); + type.block_light = true; + type.fill = block_fill; + blockType.Add(type); + } + { // white slab + BlockType type(true, { 1.0f, 1.0f, 1.0f }, &slabShape); + type.block_light = true; + type.fill = slab_fill; + blockType.Add(type); + } + { // white stair + BlockType type(true, { 1.0f, 1.0f, 1.0f }, &stairShape); + type.block_light = true; + type.fill = stair_fill; + blockType.Add(type); + } + + { // red block + BlockType type(true, { 1.0f, 0.0f, 0.0f }, &blockShape); + type.block_light = true; + type.fill = block_fill; + blockType.Add(type); + } + { // red slab + BlockType type(true, { 1.0f, 0.0f, 0.0f }, &slabShape); + type.block_light = true; + type.fill = slab_fill; + blockType.Add(type); + } + { // red stair + BlockType type(true, { 1.0f, 0.0f, 0.0f }, &stairShape); + type.block_light = true; + type.fill = stair_fill; + blockType.Add(type); + } + + { // green block + BlockType type(true, { 0.0f, 1.0f, 0.0f }, &blockShape); + type.block_light = true; + type.fill = block_fill; + blockType.Add(type); + } + { // green slab + BlockType type(true, { 0.0f, 1.0f, 0.0f }, &slabShape); + type.block_light = true; + type.fill = slab_fill; + blockType.Add(type); + } + { // green stair + BlockType type(true, { 0.0f, 1.0f, 0.0f }, &stairShape); + type.block_light = true; + type.fill = stair_fill; + blockType.Add(type); + } + + { // blue block + BlockType type(true, { 0.0f, 0.0f, 1.0f }, &blockShape); + type.block_light = true; + type.fill = block_fill; + blockType.Add(type); + } + { // blue slab + BlockType type(true, { 0.0f, 0.0f, 1.0f }, &slabShape); + type.block_light = true; + type.fill = slab_fill; + blockType.Add(type); + } + { // blue stair + BlockType type(true, { 0.0f, 0.0f, 1.0f }, &stairShape); + type.block_light = true; + type.fill = stair_fill; + blockType.Add(type); + } + + { // glowing yellow block + BlockType type(true, { 1.0f, 1.0f, 0.0f }, &blockShape); + type.luminosity = 15; + type.block_light = true; + type.fill = block_fill; + blockType.Add(type); + } + + generate.Space(0); + generate.Light(13); + generate.Solids({ 1, 4, 7, 10 }); + + player = &AddEntity(); + player->Position(config.spawn); + + chunks.GenerateSurrounding(player->ChunkCoords()); } -Chunk::Chunk() -: blocks(Size()) -, model() -, dirty(false) { +namespace { + +struct Candidate { + Chunk *chunk; + float dist; +}; + +std::vector candidates; } +bool World::Intersection( + const Ray &ray, + const glm::mat4 &M, + Chunk **chunk, + int *blkid, + float *dist, + glm::vec3 *normal) { + candidates.clear(); + + for (Chunk &cur_chunk : chunks.Loaded()) { + float cur_dist; + if (cur_chunk.Intersection(ray, M * cur_chunk.Transform(player->ChunkCoords()), cur_dist)) { + candidates.push_back({ &cur_chunk, cur_dist }); + } + } + + if (candidates.empty()) return false; + + Chunk *closest_chunk = nullptr; + float closest_dist = std::numeric_limits::infinity(); + int closest_blkid = -1; + glm::vec3 closest_normal; + + for (Candidate &cand : candidates) { + if (cand.dist > closest_dist) continue; + int cur_blkid; + float cur_dist; + glm::vec3 cur_normal; + if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(player->ChunkCoords()), cur_blkid, cur_dist, cur_normal)) { + if (cur_dist < closest_dist) { + closest_chunk = cand.chunk; + closest_blkid = cur_blkid; + closest_dist = cur_dist; + closest_normal = cur_normal; + } + } + } -void Chunk::Draw() { - if (dirty) { - Update(); + if (chunk) { + *chunk = closest_chunk; + } + if (blkid) { + *blkid = closest_blkid; + } + if (dist) { + *dist = closest_dist; + } + if (normal) { + *normal = closest_normal; } - model.Draw(); + return closest_chunk; } -int Chunk::VertexCount() const { - // TODO: query blocks as soon as type shapes are implemented - return Size() * 6 * 6; +Chunk &World::PlayerChunk() { + return chunks.ForceLoad(player->ChunkCoords()); } -void Chunk::Update() { - model.Clear(); - model.Reserve(VertexCount()); +Chunk &World::Next(const Chunk &to, const glm::tvec3 &dir) { + const Chunk::Pos tgt_pos = to.Position() + dir; + return chunks.ForceLoad(tgt_pos); +} + + +void World::Update(int dt) { + for (Entity &entity : entities) { + entity.Update(dt); + } + chunks.Rebase(player->ChunkCoords()); + chunks.Update(); +} - for (int i = 0; i < Size(); ++i) { - if (blocks[i].type->visible) { - blocks[i].type->FillModel(ToCoords(i), model); + +void World::Render(BlockLighting &chunk_prog, DirectionalLighting &entity_prog) { + chunk_prog.Activate(); + chunk_prog.SetFogDensity(fog_density); + chunk_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords()))); + + for (Chunk &chunk : chunks.Loaded()) { + glm::mat4 m(chunk.Transform(player->ChunkCoords())); + chunk_prog.SetM(m); + glm::mat4 mvp(chunk_prog.GetVP() * m); + if (!CullTest(Chunk::Bounds(), mvp)) { + chunk.Draw(); } } - model.Invalidate(); - dirty = false; + entity_prog.Activate(); + entity_prog.SetLightDirection(light_direction); + entity_prog.SetFogDensity(fog_density); + entity_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords()))); + + for (Entity &entity : entities) { + if (entity.HasShape()) { + entity_prog.SetM(entity.Transform(player->ChunkCoords())); + entity.Draw(); + } + } } }