diff --git a/source/Component/Terrain.cpp b/source/Component/Terrain.cpp index cb39b50..232dc44 100644 --- a/source/Component/Terrain.cpp +++ b/source/Component/Terrain.cpp @@ -6,11 +6,15 @@ #include "imgui.h" -Component::Terrain::Terrain(const glm::vec3& p_position, int p_size_x, int p_size_z) noexcept +Component::Terrain::Terrain(const glm::vec3& p_position, int p_size_x, int p_size_z, float amplitude) noexcept : m_position{p_position} , m_size_x{p_size_x} , m_size_z{p_size_z} - , m_scale_factor{1.f} + , m_scale_factor{0.03f} + , m_amplitude{amplitude} + , m_lacunarity{2.f} + , m_persistence{0.5f} + , m_octaves{4} , m_texture{} , m_seed{Utility::get_random_number()} , m_mesh{generate_mesh(m_seed)} @@ -20,6 +24,10 @@ Component::Terrain::Terrain(const Terrain& p_other) noexcept , m_size_x{p_other.m_size_x} , m_size_z{p_other.m_size_z} , m_scale_factor{p_other.m_scale_factor} + , m_amplitude{p_other.m_amplitude} + , m_lacunarity{p_other.m_lacunarity} + , m_persistence{p_other.m_persistence} + , m_octaves{p_other.m_octaves} , m_texture{p_other.m_texture} , m_seed{p_other.m_seed} , m_mesh{generate_mesh(m_seed)} // TODO: Implement a Data::Mesh copy. @@ -30,15 +38,32 @@ Component::Terrain& Component::Terrain::operator=(const Terrain& p_other) noexce m_size_x = p_other.m_size_x; m_size_z = p_other.m_size_z; m_scale_factor = p_other.m_scale_factor; + m_amplitude = p_other.m_amplitude; + m_lacunarity = p_other.m_lacunarity; + m_persistence = p_other.m_persistence; + m_octaves = p_other.m_octaves; m_texture = p_other.m_texture; m_seed = p_other.m_seed; m_mesh = generate_mesh(m_seed); // TODO: Implement a Data::Mesh copy. return *this; } -float compute_height(float p_x, float p_z, float p_scale_factor, const siv::PerlinNoise& perlin) +float Component::Terrain::compute_height(float p_x, float p_z, const siv::PerlinNoise& perlin) { - return static_cast(perlin.noise2D(p_x * p_scale_factor, p_z * p_scale_factor)); + float accumulate = 0.f; + float octave_frequency = 1.f; + float octave_amplitude = 1.f; + float max_value = 0.f; + + for (int i = 0; i < m_octaves; i++) + { + accumulate += static_cast(perlin.noise2D(p_x * m_scale_factor * octave_frequency, p_z * m_scale_factor * octave_frequency)) * octave_amplitude; + max_value += octave_amplitude; + octave_amplitude *= m_persistence; + octave_frequency *= m_lacunarity; + } + + return accumulate / max_value * m_amplitude; } Data::Mesh Component::Terrain::generate_mesh(unsigned int p_seed) noexcept @@ -52,10 +77,10 @@ Data::Mesh Component::Terrain::generate_mesh(unsigned int p_seed) noexcept for (float z = 0; z < m_size_z; z++) { mb.add_quad( - glm::vec3(x + 1, compute_height(x + 1, z, m_scale_factor, perlin), z), - glm::vec3(x + 1, compute_height(x + 1, z + 1, m_scale_factor, perlin), z + 1), - glm::vec3(x, compute_height(x, z, m_scale_factor, perlin), z), - glm::vec3(x, compute_height(x, z + 1, m_scale_factor, perlin), z + 1)); + glm::vec3(x + 1, compute_height(x + 1, z, perlin), z), + glm::vec3(x + 1, compute_height(x + 1, z + 1, perlin), z + 1), + glm::vec3(x, compute_height(x, z, perlin), z), + glm::vec3(x, compute_height(x, z + 1, perlin), z + 1)); } return mb.get_mesh(); @@ -83,7 +108,11 @@ void Component::Terrain::draw_UI(System::AssetManager& p_asset_manager) changed |= ImGui::Slider("Position", m_position, -100.f, 100.f, "%.3fm"); changed |= ImGui::Slider("Size X", m_size_x, 1, 1000, "%dm"); changed |= ImGui::Slider("Size Z", m_size_z, 1, 1000, "%dm"); - changed |= ImGui::Slider("Scale factor", m_scale_factor, 0.01f , 10.f); + changed |= ImGui::Slider("Scale factor", m_scale_factor, 0.01f , 0.15f); + changed |= ImGui::Slider("Amplitude", m_amplitude, 0.01f, 100.f); + changed |= ImGui::Slider("Lacunarity", m_lacunarity, 0.01f, 4.f); + changed |= ImGui::Slider("Persistence", m_persistence, 0.01f, 1.f); + changed |= ImGui::Slider("Octaves", m_octaves, 1, 10); changed |= ImGui::InputScalar("Seed", ImGuiDataType_U32, &m_seed); ImGui::SameLine(); if (ImGui::Button("Rand")) diff --git a/source/Component/Terrain.hpp b/source/Component/Terrain.hpp index 56a8b48..bfdc0fb 100644 --- a/source/Component/Terrain.hpp +++ b/source/Component/Terrain.hpp @@ -3,6 +3,10 @@ #include "Component/Texture.hpp" #include "Component/Mesh.hpp" +#include "Utility/PerlinNoise.hpp" + + + namespace System { class AssetManager; @@ -20,11 +24,15 @@ namespace Component int m_size_x; int m_size_z; float m_scale_factor; + float m_amplitude; + float m_lacunarity; + float m_persistence; + int m_octaves; TextureRef m_texture; unsigned int m_seed; // Seed used to generate m_mesh. Data::Mesh m_mesh; - Terrain(const glm::vec3& p_position, int p_size_x, int p_size_z) noexcept; + Terrain(const glm::vec3& p_position, int p_size_x, int p_size_z, float amplitude) noexcept; // Copy constructor has to be implemented because Data::Mesh GL members are not copyable. Terrain(const Terrain& p_other) noexcept; // Copy assignment operator has to be implemented because Data::Mesh GL members are not copyable. @@ -32,6 +40,7 @@ namespace Component Terrain(Terrain&& p_other) noexcept = default; Terrain& operator=(Terrain&& p_other) noexcept = default; + float compute_height(float p_x, float p_z, const siv::PerlinNoise& perlin); void draw_UI(System::AssetManager& p_asset_manager); }; } // namespace Component \ No newline at end of file diff --git a/source/System/SceneSystem.cpp b/source/System/SceneSystem.cpp index a793055..11ba0ba 100644 --- a/source/System/SceneSystem.cpp +++ b/source/System/SceneSystem.cpp @@ -29,6 +29,10 @@ namespace System set_current_scene(scene); add_default_camera(scene); construct_2_sphere_scene(scene); + + Component::Terrain terrain({0.f, 5.f, -100.f}, 100, 100, 20); + terrain.m_texture = m_asset_manager.get_texture(Config::Texture_Directory / "GrassTile.png"); + scene.m_entities.add_entity(terrain); } void SceneSystem::set_current_scene(const Scene& p_scene) @@ -209,9 +213,6 @@ namespace System auto particle_emitter = Component::ParticleEmitter{m_asset_manager.get_texture(Config::Texture_Directory / "smoke.png")}; p_scene.m_entities.add_entity(Component::Label{"Particle emitter"}, particle_emitter); } - { // Terrain - p_scene.m_entities.add_entity(Component::Label{"Terrain"}, Component::Terrain{glm::vec3(0.f), 100, 100}); - } } void SceneSystem::constructBoxScene(Scene& p_scene) @@ -283,7 +284,7 @@ namespace System p_scene.m_entities.add_entity( Component::Label{"Sphere 1"}, Component::RigidBody{}, - Component::Transform{glm::vec3(2.f, 0.f, 0.f)}, + Component::Transform{glm::vec3(50.f, 30.f, -50.f)}, Component::Mesh{icosphere_meshref}, Component::Texture{glm::vec4(0.5f, 0.5f, 0.5f, 0.6f)}, // Grey Component::Collider{}); @@ -291,7 +292,7 @@ namespace System p_scene.m_entities.add_entity( Component::Label{"Sphere 2"}, Component::RigidBody{}, - Component::Transform{glm::vec3(5.f, 0.f, 0.f)}, + Component::Transform{glm::vec3(55.f, 30.f, -50.f)}, Component::Mesh{icosphere_meshref}, Component::Texture{glm::vec4(1.f, 0.647f, 0.f, 0.6f)}, // Orange Component::Collider{}); diff --git a/source/UI/Editor.cpp b/source/UI/Editor.cpp index c484a31..10c9688 100644 --- a/source/UI/Editor.cpp +++ b/source/UI/Editor.cpp @@ -670,7 +670,7 @@ namespace UI { m_scene_system.get_current_scene_entities().add_entity( Component::Label{"Terrain"}, - Component::Terrain{*m_cursor_intersection, 10, 10}); + Component::Terrain{*m_cursor_intersection, 10, 10, 5.f}); } ImGui::EndMenu(); }