space-game001/src/planet/PlanetData.h
2026-01-25 20:55:36 +03:00

134 lines
3.7 KiB
C++

#pragma once
#include "utils/Perlin.h"
#include "render/Renderer.h"
#include <vector>
#include <array>
#include <string>
#include <map>
#include <set>
namespace ZL {
using VertexID = std::string;
using V2TMap = std::map<VertexID, std::vector<int>>;
struct Vector3fComparator {
bool operator()(const Eigen::Vector3f& a, const Eigen::Vector3f& b) const {
// Лексикографическое сравнение (x, затем y, затем z)
if (a.x() != b.x()) return a.x() < b.x();
if (a.y() != b.y()) return a.y() < b.y();
return a.z() < b.z();
}
};
VertexID generateEdgeID(const VertexID& id1, const VertexID& id2);
constexpr static int MAX_LOD_LEVELS = 6;
struct Triangle
{
std::array<Vector3f, 3> data;
std::array<VertexID, 3> ids;
Triangle()
{
}
Triangle(Vector3f p1, Vector3f p2, Vector3f p3)
: data{ p1, p2, p3 }
{
}
Triangle(std::array<Vector3f, 3> idata, std::array<VertexID, 3> iids)
: data{ idata }
, ids{ iids }
{
}
};
struct LodLevel
{
std::vector<Triangle> triangles;
VertexDataStruct vertexData;
std::vector<VertexID> VertexIDs;
V2TMap v2tMap;
void Scale(float s)
{
vertexData.Scale(s);
for (auto& t : triangles) {
for (int i = 0; i < 3; i++) {
t.data[i] = t.data[i] * s;
}
}
}
void Move(Vector3f pos)
{
vertexData.Move(pos);
for (auto& t : triangles) {
for (int i = 0; i < 3; i++) {
t.data[i] = t.data[i] + pos;
}
}
}
};
struct PlanetCampObject
{
Vector3f position;
Matrix3f rotation;
std::array<Vector3f, 5> platformPos = {
Vector3f{ 0.f, 0.f,-38.f },
Vector3f{ 20.f, 0.f,-18.f },
Vector3f{ 20.f, 0.f,-58.f },
Vector3f{ -20.f, 0.f,-58.f },
Vector3f{ -20.f, 0.f,-18.f }
};
};
class PlanetData {
public:
static const float PLANET_RADIUS;
static const Vector3f PLANET_CENTER_OFFSET;
private:
PerlinNoise perlin;
PerlinNoise colorPerlin;
std::array<LodLevel, MAX_LOD_LEVELS> planetMeshLods;
LodLevel planetAtmosphereLod;
//int currentLod; // Логический текущий уровень детализации
//std::map<Vector3f, VertexID, Vector3fComparator> initialVertexMap;
// Внутренние методы генерации
std::vector<Triangle> subdivideTriangles(const std::vector<Triangle>& inputTriangles, float noiseCoeff);
LodLevel createLodLevel(const std::vector<Triangle>& triangles);
void recalculateMeshAttributes(LodLevel& lod);
LodLevel generateSphere(int subdivisions, float noiseCoeff);
public:
PlanetData();
void init();
const LodLevel& getLodLevel() const;
const LodLevel& getAtmosphereLod() const;
// Логика
std::pair<float, float> calculateZRange(float distanceToSurface);
float distanceToPlanetSurfaceFast(const Vector3f& viewerPosition);
// Возвращает индексы треугольников, видимых камерой
std::vector<int> getBestTriangleUnderCamera(const Vector3f& viewerPosition);
std::vector<int> getTrianglesUnderCameraNew2(const Vector3f& viewerPosition);
void applySphericalRelaxation(LodLevel& lod, int iterations);
std::vector<PlanetCampObject> campObjects;
};
} // namespace ZL