Planet properties
This commit is contained in:
parent
e7d34b82be
commit
dc7c70d871
4
TODO.md
4
TODO.md
|
@ -28,7 +28,7 @@
|
|||
- [x] Area
|
||||
- [x] Offset
|
||||
- [ ] Rotation
|
||||
- [ ] Planet
|
||||
- [~] Planet
|
||||
- [ ] CubicSphere
|
||||
- [ ] Healpix
|
||||
- [ ] Galaxy
|
||||
|
@ -46,7 +46,7 @@
|
|||
- [ ] ZeroMQ
|
||||
- [~] Workers
|
||||
- [x] Basic
|
||||
- [ ] Use system infos
|
||||
- [x] Use system infos
|
||||
- [ ] Pool
|
||||
- [x] Logger
|
||||
- [ ] FastNoiseSIMD / HastyNoise double precision
|
||||
|
|
|
@ -7,12 +7,21 @@ namespace glm {
|
|||
constexpr ivec3 inline iround(const vec3& p) {
|
||||
return ivec3(std::round<int>(p.x), std::round<int>(p.y), std::round<int>(p.z));
|
||||
}
|
||||
constexpr long inline length2(const ivec3& a) {
|
||||
constexpr float inline length2(const vec3& a) {
|
||||
return a.x * a.x + a.y * a.y + a.z * a.z;
|
||||
}
|
||||
constexpr long inline length2(const lvec3& a) {
|
||||
return a.x * a.x + a.y * a.y + a.z * a.z;
|
||||
}
|
||||
constexpr long long inline length2(const llvec3& a) {
|
||||
return a.x * a.x + a.y * a.y + a.z * a.z;
|
||||
}
|
||||
constexpr long inline pow2(int v) {
|
||||
return v * v;
|
||||
}
|
||||
constexpr long long inline pow2(long v) {
|
||||
return v * v;
|
||||
}
|
||||
constexpr ivec3 inline diff(const ivec3& a, const ivec3& b) {
|
||||
return glm::abs(glm::abs(a) - glm::abs(b));
|
||||
}
|
||||
|
@ -57,4 +66,8 @@ namespace glm {
|
|||
constexpr std::pair<lvec3, idx> inline splitIdx(const llvec3 &value, const ucvec3 &m = ucvec3(IDX_LENGTH)) {
|
||||
return {divide(value, m), toIdx(rem(value.x, m.x), rem(value.y, m.y), rem(value.z, m.z))};
|
||||
}
|
||||
template <typename T>
|
||||
constexpr T inline max_axis(const vec<3, T> &v) {
|
||||
return std::max({v.x, v.y, v.z});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,11 +34,11 @@ namespace world {
|
|||
struct params {
|
||||
voxel_pos center;
|
||||
int radius;
|
||||
int seed = 42;
|
||||
Generator::Properties properties;
|
||||
};
|
||||
|
||||
/// radius: size in chunk (length = radius * 2 + 1)
|
||||
Area(const params& p): center(p.center), chunks(p.radius), generator(p.seed) { }
|
||||
Area(const params& p): center(p.center), chunks(p.radius), generator(p.properties) { }
|
||||
|
||||
inline const area_pos &getOffset() const { return center; }
|
||||
inline geometry::IBox getBounding() const {
|
||||
|
@ -61,7 +61,7 @@ namespace world {
|
|||
|
||||
inline Generator &getGenerator() { return generator; }
|
||||
|
||||
inline params getParams() const { return params{center.as_voxel(), chunks.getRadius(), generator.getSeed()}; }
|
||||
inline params getParams() const { return params{center.as_voxel(), chunks.getRadius(), generator.getProperties()}; }
|
||||
|
||||
private:
|
||||
area_pos center;
|
||||
|
|
|
@ -6,16 +6,24 @@
|
|||
|
||||
using namespace world;
|
||||
|
||||
constexpr auto DENSITY = 0.f;
|
||||
constexpr auto GRANULARITY = 30.f;
|
||||
constexpr auto HEIGHT = 2;
|
||||
|
||||
Chunk::Chunk(const chunk_pos& pos, Generator& rnd) {
|
||||
const auto [densitySet, materialSet] = rnd.getChunk(pos, CHUNK_LENGTH);
|
||||
const auto &p = rnd.getProperties();
|
||||
if(!(std::holds_alternative<Generator::Properties::cheese>(p.shape) || std::holds_alternative<Generator::Properties::planet>(p.shape)))
|
||||
return;
|
||||
|
||||
const auto &cheese = std::holds_alternative<Generator::Properties::cheese>(p.shape) ? std::get<Generator::Properties::cheese>(p.shape) :
|
||||
std::get<Generator::Properties::planet>(p.shape);
|
||||
|
||||
const auto [densitySet, materialSet] = rnd.getChunk(pos, CHUNK_LENGTH);
|
||||
const auto verticalDensity = [p, pos](glm::idx i){
|
||||
if(const auto planet = std::get_if<Generator::Properties::planet>(&p.shape)) {
|
||||
const auto heightRatio = static_cast<float>(glm::max_axis(glm::abs(glm::multiply(pos) + glm::llvec3(glm::fromIdx(i)))) - planet->height) / planet->height;
|
||||
return heightRatio / (heightRatio >= 0 ? planet->surface_roughness : planet->cave_depth);
|
||||
}
|
||||
return 0.f;
|
||||
};
|
||||
for (size_t i = 0; i < CHUNK_SIZE; i++) {
|
||||
const auto height = std::max(0l, pos.y * CHUNK_LENGTH + glm::fromIdx(i).y);
|
||||
const auto density = std::clamp((densitySet[i] + DENSITY) * GRANULARITY - height / HEIGHT, 0.f, 1.f) * Voxel::DENSITY_MAX;
|
||||
const auto density = std::clamp((densitySet[i] + cheese.density - verticalDensity(i)) * cheese.granularity, 0.f, 1.f) * Voxel::DENSITY_MAX;
|
||||
const auto material = density > 0 ? 1 + std::clamp(static_cast<int>(std::lrint((materialSet[i] + 1) / 2 * (materials::count - 2))),
|
||||
0, materials::count - 2) : 0; //NOTE: map (approx -1, 1) to (1, mat_max)
|
||||
voxels[i] = Voxel(material, density);
|
||||
|
|
|
@ -6,19 +6,55 @@
|
|||
#include <FastNoiseSIMD.h>
|
||||
#endif
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
#include "position.h"
|
||||
|
||||
namespace world {
|
||||
/// Noise generator
|
||||
class Generator {
|
||||
public:
|
||||
/// Generation caracteristics
|
||||
struct Properties {
|
||||
/// Default cheese
|
||||
Properties(int seed = 42): shape(cheese()), density(noise(seed)), material(noise(seed * 5, .1)) { }
|
||||
/// Default planet
|
||||
Properties(voxel_pos::value_type height, int seed = 42): shape(planet(height)), density(seed), material(seed * 5, .1) { }
|
||||
|
||||
/// Endless cave network
|
||||
struct cheese {
|
||||
cheese(float density = 0, float gran = 30): density(density), granularity(gran) { }
|
||||
/// Offset density overrage
|
||||
float density;
|
||||
/// Speed of density change
|
||||
float granularity;
|
||||
};
|
||||
// Cube planet
|
||||
struct planet: cheese {
|
||||
planet(voxel_pos::value_type height, float surface_roughness = .1, float cave_depth = .2, float density = 0, float gran = 30): cheese(density, gran),
|
||||
height(height), surface_roughness(surface_roughness), cave_depth(cave_depth) { }
|
||||
/// Sea level (minimal density)
|
||||
voxel_pos::value_type height;
|
||||
/// Density decrease over height
|
||||
float surface_roughness;
|
||||
/// Density decrease under height
|
||||
float cave_depth;
|
||||
};
|
||||
std::variant<cheese, planet> shape;
|
||||
struct noise {
|
||||
noise(int seed, float freq = .01): seed(seed), frequency(freq) { }
|
||||
int seed;
|
||||
float frequency;
|
||||
};
|
||||
noise density;
|
||||
noise material;
|
||||
};
|
||||
using set = float *;
|
||||
#if HASTY
|
||||
using noise = std::unique_ptr<HastyNoise::NoiseSIMD>;
|
||||
#else
|
||||
using noise = FastNoiseSIMD *;
|
||||
#endif
|
||||
Generator(int seed = 42): seed(seed) {
|
||||
Generator(const Properties& properties): properties(properties) {
|
||||
#if HASTY
|
||||
printf("double!!!\n");
|
||||
const size_t fastestSimd = HastyNoise::GetFastestSIMD();
|
||||
|
@ -29,12 +65,13 @@ namespace world {
|
|||
materialNoise->SetCellularDistanceFunction(HastyNoise::CellularDistance::Natural);
|
||||
materialNoise->SetFrequency(.1);
|
||||
#else
|
||||
densityNoise = FastNoiseSIMD::NewFastNoiseSIMD(seed);
|
||||
materialNoise = FastNoiseSIMD::NewFastNoiseSIMD(seed * 5);
|
||||
densityNoise = FastNoiseSIMD::NewFastNoiseSIMD(properties.density.seed);
|
||||
densityNoise->SetFrequency(properties.density.frequency);
|
||||
materialNoise = FastNoiseSIMD::NewFastNoiseSIMD(properties.material.seed);
|
||||
materialNoise->SetNoiseType(FastNoiseSIMD::Cellular); // NOTE: probably heavy
|
||||
materialNoise->SetCellularReturnType(FastNoiseSIMD::CellValue);
|
||||
materialNoise->SetCellularDistanceFunction(FastNoiseSIMD::Natural);
|
||||
materialNoise->SetFrequency(.1);
|
||||
materialNoise->SetFrequency(properties.material.frequency);
|
||||
#endif
|
||||
}
|
||||
~Generator() {
|
||||
|
@ -65,10 +102,10 @@ namespace world {
|
|||
#endif
|
||||
}
|
||||
|
||||
inline int getSeed() const { return seed; }
|
||||
constexpr inline const Properties& getProperties() const { return properties; }
|
||||
|
||||
private:
|
||||
int seed;
|
||||
Properties properties;
|
||||
noise densityNoise;
|
||||
noise materialNoise;
|
||||
};
|
||||
|
|
|
@ -31,12 +31,12 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
|
|||
while(!index.eof()) {
|
||||
size_t id = UINT32_MAX;
|
||||
index.read(reinterpret_cast<char *>(&id), sizeof(size_t));
|
||||
Area::params params{voxel_pos(0), 0};
|
||||
Area::params params{voxel_pos(0), 0, Generator::Properties(0)};
|
||||
index.read(reinterpret_cast<char *>(¶ms.center.x), sizeof(voxel_pos::value_type));
|
||||
index.read(reinterpret_cast<char *>(¶ms.center.y), sizeof(voxel_pos::value_type));
|
||||
index.read(reinterpret_cast<char *>(¶ms.center.z), sizeof(voxel_pos::value_type));
|
||||
index.read(reinterpret_cast<char *>(¶ms.radius), sizeof(int));
|
||||
index.read(reinterpret_cast<char *>(¶ms.seed), sizeof(int));
|
||||
index.read(reinterpret_cast<char *>(¶ms.properties), sizeof(Generator::Properties));
|
||||
[[maybe_unused]]
|
||||
auto ok = tmp.emplace(id, params).second;
|
||||
assert(ok && "Duplicated area");
|
||||
|
@ -48,8 +48,8 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
|
|||
} else {
|
||||
LOG_E("No index file!!! Probably a new world...");
|
||||
//TODO: generate universe
|
||||
far_areas.emplace(Area::params{voxel_pos(0), 1 << 20});
|
||||
//far_areas.emplace(Area::params{voxel_pos(0), 1, 43});
|
||||
const auto radius = 1 << 4;
|
||||
far_areas.emplace(Area::params{glm::multiply(voxel_pos(radius)), radius, Generator::Properties(radius * CHUNK_LENGTH * 3 / 4, 42)});
|
||||
}
|
||||
index.close();
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ void Universe::saveAreas() const {
|
|||
index.write(reinterpret_cast<char *>(¶ms.center.y), sizeof(voxel_pos::value_type));
|
||||
index.write(reinterpret_cast<char *>(¶ms.center.z), sizeof(voxel_pos::value_type));
|
||||
index.write(reinterpret_cast<char *>(¶ms.radius), sizeof(int));
|
||||
index.write(reinterpret_cast<char *>(¶ms.seed), sizeof(int));
|
||||
index.write(reinterpret_cast<char *>(¶ms.properties), sizeof(Generator::Properties)); // MAYBE: use binary structured format (protobuf/messagebuf)
|
||||
};
|
||||
for(const auto& area: areas) {
|
||||
write(area.first, area.second->getParams());
|
||||
|
|
Loading…
Reference in New Issue