space-game001/src/planet/PlanetData.h
2026-01-09 20:49:03 +03:00

121 lines
3.3 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;
}
}
}
};
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(int level) const;
const LodLevel& getAtmosphereLod() const;
int getCurrentLodIndex() const;
int getMaxLodIndex() 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);
};
} // namespace ZL