#pragma once #include "ZLMath.h" #include "Renderer.h" #include "TextureManager.h" #include #include #include #include #include #include #include #include namespace ZL { class PerlinNoise { std::vector p; public: PerlinNoise() { p.resize(256); std::iota(p.begin(), p.end(), 0); // Перемешиваем для случайности (можно задать seed) std::default_random_engine engine(12345); std::shuffle(p.begin(), p.end(), engine); p.insert(p.end(), p.begin(), p.end()); // Дублируем для переполнения } float fade(float t) { return t * t * t * (t * (t * 6 - 15) + 10); } float lerp(float t, float a, float b) { return a + t * (b - a); } float grad(int hash, float x, float y, float z) { int h = hash & 15; float u = h < 8 ? x : y; float v = h < 4 ? y : (h == 12 || h == 14 ? x : z); return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); } float noise(float x, float y, float z) { int X = (int)floor(x) & 255; int Y = (int)floor(y) & 255; int Z = (int)floor(z) & 255; x -= floor(x); y -= floor(y); z -= floor(z); float u = fade(x); float v = fade(y); float w = fade(z); int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z; int B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z; return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z)), lerp(u, grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z))), lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1), grad(p[BA + 1], x - 1, y, z - 1)), lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1)))); } float getSurfaceHeight(Vector3f pos) { // Частота шума (чем больше, тем больше "холмов") float frequency = 7.0f; // Получаем значение шума (обычно от -1 до 1) float noiseValue = noise(pos.v[0] * frequency, pos.v[1] * frequency, pos.v[2] * frequency); // Переводим из диапазона [-1, 1] в [0, 1] noiseValue = (noiseValue + 1.0f) * 0.5f; // Масштабируем: хотим отклонение от 1.0 до 1.1 // Значит амплитуда = 0.1 float height = 1.0f + (noiseValue * 0.1f); // * 0.2 даст вариацию высоты return height; } }; class PlanetObject { private: PerlinNoise perlin; void prepareDrawData(); VertexDataStruct planetMesh; VertexRenderStruct planetRenderStruct; public: PlanetObject(); void init(); void update(float deltaTimeMs); void draw(Renderer& renderer); private: bool drawDataDirty = true; }; } // namespace ZL