diff --git a/Application/Block.h b/Application/Block.h index 930c621..4136b67 100644 --- a/Application/Block.h +++ b/Application/Block.h @@ -5,6 +5,16 @@ #include +enum class BlockType : std::uint32_t +{ + Air = 0, + Dirt, + Stone, + + EndEnum +}; +constexpr std::size_t BlocksCount = static_cast(BlockType::EndEnum); + static const std::vector BLOCK_MESH = { //Front face Scop::Vertex{ Scop::Vec4f{ 0.0f, 0.0f, 1.0f, 1.0f }, Scop::Vec4f{ 0.0f, 0.0f, 1.0f, 1.0f }, Scop::Vec2f{ 0.0f, 0.0f } }, diff --git a/Application/Chunk.cpp b/Application/Chunk.cpp index 66c2187..eb5833b 100644 --- a/Application/Chunk.cpp +++ b/Application/Chunk.cpp @@ -4,6 +4,22 @@ #define POS_TO_INDEX(posx, posz) (posx * CHUNK_SIZE.x + posz) +constexpr Scop::Vec2ui SPRITE_SIZE = { 16, 16 }; +constexpr Scop::Vec2ui ATLAS_SIZE = { 64, 64 }; +constexpr Scop::Vec2f SPRITE_UNIT = Scop::Vec2f(SPRITE_SIZE) / Scop::Vec2f(ATLAS_SIZE); + +constexpr std::array BLOCKS_TO_ATLAS = { + Scop::Vec2ui{ 0, 0 }, // Air + Scop::Vec2ui{ 0, 0 }, // Dirt + Scop::Vec2ui{ 1, 0 }, // Stone +}; + +Scop::Vec2f GetAtlasOffset(BlockType type) +{ + Scop::Vec2ui pos = BLOCKS_TO_ATLAS[static_cast(type)]; + return Scop::Vec2f(Scop::Vec2f(pos.x, SPRITE_SIZE.y - pos.y - 1) * SPRITE_UNIT); +} + Chunk::Chunk(World& world, Scop::Vec2i offset) : m_offset(offset), m_position(std::move(offset) * Scop::Vec2i{ CHUNK_SIZE.x, CHUNK_SIZE.z }), m_world(world) { } @@ -37,7 +53,8 @@ void Chunk::GenerateMesh() { for(std::int32_t y = 0; y < CHUNK_SIZE.y; y++) { - if(!GetBlock(Scop::Vec3i(x, y, z))) + BlockType type = static_cast(GetBlock(Scop::Vec3i(x, y, z))); + if(type == BlockType::Air) continue; if(!GetBlock(Scop::Vec3i(x, y, z + 1))) @@ -49,10 +66,10 @@ void Chunk::GenerateMesh() m_mesh_index_data.push_back(offset + 3); m_mesh_index_data.push_back(offset + 1); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[0].position + Scop::Vec3f(x, y, z), BLOCK_MESH[0].normal, BLOCK_MESH[0].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[1].position + Scop::Vec3f(x, y, z), BLOCK_MESH[1].normal, BLOCK_MESH[1].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[2].position + Scop::Vec3f(x, y, z), BLOCK_MESH[2].normal, BLOCK_MESH[2].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[3].position + Scop::Vec3f(x, y, z), BLOCK_MESH[3].normal, BLOCK_MESH[3].uv)); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[0].position + Scop::Vec3f(x, y, z), BLOCK_MESH[0].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[0].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[1].position + Scop::Vec3f(x, y, z), BLOCK_MESH[1].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[1].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[2].position + Scop::Vec3f(x, y, z), BLOCK_MESH[2].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[2].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[3].position + Scop::Vec3f(x, y, z), BLOCK_MESH[3].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[3].uv))); offset += 4; } @@ -66,10 +83,10 @@ void Chunk::GenerateMesh() m_mesh_index_data.push_back(offset + 1); m_mesh_index_data.push_back(offset); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[4].position + Scop::Vec3f(x, y, z), BLOCK_MESH[4].normal, BLOCK_MESH[4].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[5].position + Scop::Vec3f(x, y, z), BLOCK_MESH[5].normal, BLOCK_MESH[5].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[6].position + Scop::Vec3f(x, y, z), BLOCK_MESH[6].normal, BLOCK_MESH[6].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[7].position + Scop::Vec3f(x, y, z), BLOCK_MESH[7].normal, BLOCK_MESH[7].uv)); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[4].position + Scop::Vec3f(x, y, z), BLOCK_MESH[4].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[4].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[5].position + Scop::Vec3f(x, y, z), BLOCK_MESH[5].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[5].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[6].position + Scop::Vec3f(x, y, z), BLOCK_MESH[6].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[6].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[7].position + Scop::Vec3f(x, y, z), BLOCK_MESH[7].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[7].uv))); offset += 4; } @@ -83,10 +100,10 @@ void Chunk::GenerateMesh() m_mesh_index_data.push_back(offset + 2); m_mesh_index_data.push_back(offset + 3); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[8].position + Scop::Vec3f(x, y, z), BLOCK_MESH[0].normal, BLOCK_MESH[8].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[9].position + Scop::Vec3f(x, y, z), BLOCK_MESH[9].normal, BLOCK_MESH[9].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[10].position + Scop::Vec3f(x, y, z), BLOCK_MESH[10].normal, BLOCK_MESH[10].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[11].position + Scop::Vec3f(x, y, z), BLOCK_MESH[11].normal, BLOCK_MESH[11].uv)); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[8].position + Scop::Vec3f(x, y, z), BLOCK_MESH[0].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[8].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[9].position + Scop::Vec3f(x, y, z), BLOCK_MESH[9].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[9].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[10].position + Scop::Vec3f(x, y, z), BLOCK_MESH[10].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[10].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[11].position + Scop::Vec3f(x, y, z), BLOCK_MESH[11].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[11].uv))); offset += 4; } @@ -100,10 +117,10 @@ void Chunk::GenerateMesh() m_mesh_index_data.push_back(offset); m_mesh_index_data.push_back(offset + 2); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[12].position + Scop::Vec3f(x, y, z), BLOCK_MESH[12].normal, BLOCK_MESH[12].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[13].position + Scop::Vec3f(x, y, z), BLOCK_MESH[13].normal, BLOCK_MESH[13].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[14].position + Scop::Vec3f(x, y, z), BLOCK_MESH[14].normal, BLOCK_MESH[14].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[15].position + Scop::Vec3f(x, y, z), BLOCK_MESH[15].normal, BLOCK_MESH[15].uv)); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[12].position + Scop::Vec3f(x, y, z), BLOCK_MESH[12].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[12].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[13].position + Scop::Vec3f(x, y, z), BLOCK_MESH[13].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[13].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[14].position + Scop::Vec3f(x, y, z), BLOCK_MESH[14].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[14].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[15].position + Scop::Vec3f(x, y, z), BLOCK_MESH[15].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[15].uv))); offset += 4; } @@ -117,10 +134,10 @@ void Chunk::GenerateMesh() m_mesh_index_data.push_back(offset + 1); m_mesh_index_data.push_back(offset); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[16].position + Scop::Vec3f(x, y, z), BLOCK_MESH[16].normal, BLOCK_MESH[16].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[17].position + Scop::Vec3f(x, y, z), BLOCK_MESH[17].normal, BLOCK_MESH[17].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[18].position + Scop::Vec3f(x, y, z), BLOCK_MESH[18].normal, BLOCK_MESH[18].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[19].position + Scop::Vec3f(x, y, z), BLOCK_MESH[19].normal, BLOCK_MESH[19].uv)); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[16].position + Scop::Vec3f(x, y, z), BLOCK_MESH[16].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[16].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[17].position + Scop::Vec3f(x, y, z), BLOCK_MESH[17].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[17].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[18].position + Scop::Vec3f(x, y, z), BLOCK_MESH[18].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[18].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[19].position + Scop::Vec3f(x, y, z), BLOCK_MESH[19].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[19].uv))); offset += 4; } @@ -134,10 +151,10 @@ void Chunk::GenerateMesh() m_mesh_index_data.push_back(offset + 3); m_mesh_index_data.push_back(offset + 1); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[20].position + Scop::Vec3f(x, y, z), BLOCK_MESH[20].normal, BLOCK_MESH[20].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[21].position + Scop::Vec3f(x, y, z), BLOCK_MESH[21].normal, BLOCK_MESH[21].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[22].position + Scop::Vec3f(x, y, z), BLOCK_MESH[22].normal, BLOCK_MESH[22].uv)); - m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[23].position + Scop::Vec3f(x, y, z), BLOCK_MESH[23].normal, BLOCK_MESH[23].uv)); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[20].position + Scop::Vec3f(x, y, z), BLOCK_MESH[20].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[20].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[21].position + Scop::Vec3f(x, y, z), BLOCK_MESH[21].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[21].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[22].position + Scop::Vec3f(x, y, z), BLOCK_MESH[22].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[22].uv))); + m_mesh_data.push_back(Scop::Vertex(BLOCK_MESH[23].position + Scop::Vec3f(x, y, z), BLOCK_MESH[23].normal, GetAtlasOffset(type) + (Scop::Vec2f(SPRITE_UNIT) * BLOCK_MESH[23].uv))); offset += 4; } @@ -163,26 +180,26 @@ void Chunk::UploadMesh() std::uint32_t Chunk::GetBlock(Scop::Vec3i position) const noexcept { if(position.y < 0 || position.y >= CHUNK_SIZE.y) [[unlikely]] // No chunk under or above - return 1; + return static_cast(BlockType::Dirt); if(position.x < 0) [[unlikely]] { Scop::NonOwningPtr neighbour = m_world.GetChunk(Scop::Vec2i{ m_offset.x - 1, m_offset.y }); - return neighbour ? neighbour->GetBlock(Scop::Vec3i(CHUNK_SIZE.x - 1, position.y, position.z)) : 1; + return neighbour ? neighbour->GetBlock(Scop::Vec3i(CHUNK_SIZE.x - 1, position.y, position.z)) : static_cast(BlockType::Dirt); } if(position.x >= CHUNK_SIZE.x) [[unlikely]] { Scop::NonOwningPtr neighbour = m_world.GetChunk(Scop::Vec2i{ m_offset.x + 1, m_offset.y }); - return neighbour ? neighbour->GetBlock(Scop::Vec3i(0, position.y, position.z)) : 1; + return neighbour ? neighbour->GetBlock(Scop::Vec3i(0, position.y, position.z)) : static_cast(BlockType::Dirt); } if(position.z < 0) [[unlikely]] { Scop::NonOwningPtr neighbour = m_world.GetChunk(Scop::Vec2i{ m_offset.x, m_offset.y - 1 }); - return neighbour ? neighbour->GetBlock(Scop::Vec3i(position.x, position.y, CHUNK_SIZE.x - 1)) : 1; + return neighbour ? neighbour->GetBlock(Scop::Vec3i(position.x, position.y, CHUNK_SIZE.x - 1)) : static_cast(BlockType::Dirt); } if(position.z >= CHUNK_SIZE.z) [[unlikely]] { Scop::NonOwningPtr neighbour = m_world.GetChunk(Scop::Vec2i{ m_offset.x, m_offset.y + 1 }); - return neighbour ? neighbour->GetBlock(Scop::Vec3i(position.x, position.y, 0)) : 1; + return neighbour ? neighbour->GetBlock(Scop::Vec3i(position.x, position.y, 0)) : static_cast(BlockType::Dirt); } return m_data[POS_TO_INDEX(position.x, position.z)][position.y]; } diff --git a/Application/Noise.cpp b/Application/Noise.cpp index 89a7a1d..5329fd3 100644 --- a/Application/Noise.cpp +++ b/Application/Noise.cpp @@ -1,13 +1,19 @@ #include +#include [[nodiscard]] std::array Noise::GetHeight(Scop::Vec2i pos) { std::array data; - std::memset(data.data(), 0, data.size() * sizeof(std::uint32_t)); + std::memset(data.data(), static_cast(BlockType::Air), data.size() * sizeof(std::uint32_t)); std::uint32_t height = std::abs(std::sin((float)pos.x / 20.0f) * std::cos((float)pos.y / 20.0f) * 60.0f) + 1; for(std::uint32_t y = 0; y < std::min(height, CHUNK_SIZE.y); y++) - data[y] = 1; + { + if(y > std::min(height, CHUNK_SIZE.y) - 2) + data[y] = static_cast(BlockType::Dirt); + else + data[y] = static_cast(BlockType::Stone); + } return data; } diff --git a/Application/World.cpp b/Application/World.cpp index a725c8a..5a68017 100644 --- a/Application/World.cpp +++ b/Application/World.cpp @@ -9,7 +9,7 @@ World::World(Scop::Scene& scene) : m_scene(scene), m_previous_chunk_position(-10 { Scop::Vec2ui32 map_size; Scop::MaterialTextures material_params; - material_params.albedo = std::make_shared(Scop::LoadBMPFile(GetResourcesPath() / "dirt.bmp", map_size), map_size.x, map_size.y); + material_params.albedo = std::make_shared(Scop::LoadBMPFile(GetResourcesPath() / "atlas.bmp", map_size), map_size.x, map_size.y); p_block_material = std::make_shared(material_params); std::thread(&World::GenerateWorld, this).detach(); diff --git a/Resources/atlas.bmp b/Resources/atlas.bmp new file mode 100644 index 0000000..7bec11a Binary files /dev/null and b/Resources/atlas.bmp differ diff --git a/Resources/dirt.bmp b/Resources/dirt.bmp deleted file mode 100644 index 016f7a0..0000000 Binary files a/Resources/dirt.bmp and /dev/null differ diff --git a/Resources/prototype.bmp b/Resources/prototype.bmp deleted file mode 100644 index 160be7b..0000000 Binary files a/Resources/prototype.bmp and /dev/null differ