#include "Clouds.hpp" #include "../Time.hpp" #include "../Math/MVP.hpp" #include "../Math/Perlin.hpp" #include "../Math/AABB.hpp" #include "../GFX/Util/Primitives.hpp" #include "../GFX/Util/MeshBuilder.hpp" #include namespace MC::World { void Clouds::update(Time const& time) { m_x_offset += 5.0 * time.delta(); } void Clouds::render(GFX::Actions& actions, Position::World player_position) { I32 center_x = std::round((player_position.x() - m_x_offset) / TileSize); I32 center_y = std::round(player_position.z() / TileSize); for (Int x = -1; x <= 1; x++) { for (Int y = -1; y <= 1; y++) { render_single_instance(actions, center_x + x, center_y + y); } } } void Clouds::render_single_instance(GFX::Actions& actions, Int x, Int y) { Vector<3> position{TileSize * x + m_x_offset, Height, TileSize * y}; // m_program.bind(); // // m_view_uniform.set(Math::MVP::view(camera.position(), camera.angles())); // m_model_uniform.set(Math::MVP::model(position, Vector<3>{Scale}, {})); // // m_mesh.bind(); // glDrawElements(GL_TRIANGLES, m_mesh.size(), GL_UNSIGNED_INT, nullptr); // m_mesh.unbind(); // // m_program.unbind(); actions.add({ .mesh = &m_mesh, .program = GFX::Resources::Program::Clouds, .transform = Transform( position, Rotation::zero(), Vec3(Scale) ), }); } Clouds::CloudMatrix Clouds::create_cloud_matrix() { Math::Perlin::Noise<2> noise{}; CloudMatrix clouds{false}; for (Int x = 1; x < CloudMatrixSize; x++) { for (Int y = 1; y < CloudMatrixSize; y++) { if (noise.at({x, y * 2}) > 0.55) { clouds(x, y) = true; } } } return clouds; } GFX::Mesh Clouds::create_mesh(CloudMatrix const& cloud_matrix) { GFX::Util::MeshBuilder> builder{}; for (Int x = 0; x < CloudMatrixSize; x++) { for (Int y = 0; y < CloudMatrixSize; y++) { if (!cloud_matrix(x, y)) continue; auto is_occupied = [&](Int xn, Int yn) { if (xn < 0 || xn >= CloudMatrixSize || yn < 0 || yn >= CloudMatrixSize) return false; return cloud_matrix(xn, yn); }; std::array neighbors = { is_occupied(x - 1, y), is_occupied(x + 1, y), is_occupied(x, y - 1), is_occupied(x, y + 1), }; using FaceSet = GFX::Util::Primitives::FaceSet; U8 faces = FaceSet::Top | FaceSet::Bottom; if (!neighbors[0]) faces |= FaceSet::Left; if (!neighbors[1]) faces |= FaceSet::Right; if (!neighbors[2]) faces |= FaceSet::Front; if (!neighbors[3]) faces |= FaceSet::Back; auto aabb = AABB{{x, 0, y}, {x + 1, 1, y + 1}}; auto box = GFX::Util::Primitives::box(aabb, (FaceSet::Value)faces); builder.primitive(box); } } return builder.mesh(); } }