100 lines
3.1 KiB
C++
100 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include "ZLMath.h"
|
|
#include "Renderer.h"
|
|
#include "TextureManager.h"
|
|
#include <vector>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <array>
|
|
#include <numeric>
|
|
#include <random>
|
|
#include <algorithm>
|
|
|
|
namespace ZL {
|
|
|
|
class PerlinNoise {
|
|
std::vector<int> 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
|