diff --git a/Environment.cpp b/Environment.cpp index cdd6088..d71c040 100644 --- a/Environment.cpp +++ b/Environment.cpp @@ -36,4 +36,8 @@ Vector3f Environment::shipPosition = {0,0,0}; float Environment::shipVelocity = 0.f; +const float Environment::CONST_Z_NEAR = 10.f; +const float Environment::CONST_Z_FAR = 10000.f; + + } // namespace ZL diff --git a/Environment.h b/Environment.h index 96487ce..b68f123 100644 --- a/Environment.h +++ b/Environment.h @@ -37,6 +37,10 @@ public: static Vector3f shipPosition; static float shipVelocity; + static const float CONST_Z_NEAR; + static const float CONST_Z_FAR; + + }; diff --git a/Game.cpp b/Game.cpp index 7d4365b..fb94ba9 100755 --- a/Game.cpp +++ b/Game.cpp @@ -280,7 +280,7 @@ namespace ZL renderer.EnableVertexAttribArray(vPositionName); renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, static_cast(Environment::width) / static_cast(Environment::height), - 1, 1000); + Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR); renderer.PushMatrix(); renderer.LoadIdentity(); renderer.RotateMatrix(Environment::inverseShipMatrix); @@ -316,7 +316,7 @@ namespace ZL renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, static_cast(Environment::width) / static_cast(Environment::height), - 1, 1000); + Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR); renderer.PushMatrix(); renderer.LoadIdentity(); @@ -351,7 +351,7 @@ namespace ZL renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, static_cast(Environment::width) / static_cast(Environment::height), - 1, 1000); + Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR); for (int i = 0; i < boxCoordsArr.size(); i++) { @@ -612,11 +612,11 @@ namespace ZL { if (event.key.keysym.sym == SDLK_i) { - Environment::shipVelocity += 5.f; + Environment::shipVelocity += 5000.f; } if (event.key.keysym.sym == SDLK_k) { - Environment::shipVelocity -= 5.f; + Environment::shipVelocity -= 5000.f; } } } diff --git a/PlanetObject.cpp b/PlanetObject.cpp index 1fddf74..ce25b5b 100644 --- a/PlanetObject.cpp +++ b/PlanetObject.cpp @@ -6,6 +6,85 @@ namespace ZL { + static constexpr float PLANET_RADIUS = 1000000.f; + static Vector3f PLANET_CENTER_OFFSET = Vector3f{ 0.f, 0.f, -2250000.f }; + + // --- 1. Дальний диапазон (FAR) --- + static constexpr float FAR_Z_NEAR = 50000.0f; + static constexpr float FAR_Z_FAR = 10000000.0f; + + // Дистанция, где НАЧИНАЕТСЯ переход FAR -> MIDDLE + static constexpr float TRANSITION_FAR_START = 400000.0f; + + // --- 2. Средний диапазон (MIDDLE) --- + static constexpr float MIDDLE_Z_NEAR = 500.f; + static constexpr float MIDDLE_Z_FAR = 50000.f; + + // Дистанция, где ЗАВЕРШАЕТСЯ переход FAR -> MIDDLE и НАЧИНАЕТСЯ MIDDLE -> NEAR + static constexpr float TRANSITION_MIDDLE_START = 10000.f; + + // --- 3. Ближний диапазон (NEAR) --- + // Новые константы для максимальной точности + static constexpr float NEAR_Z_NEAR = 50.0f; + static constexpr float NEAR_Z_FAR = 50000.0f; + + // Дистанция, где ЗАВЕРШАЕТСЯ переход MIDDLE -> NEAR + static constexpr float TRANSITION_NEAR_END = 10.f; + + std::pair calculateZRange(const Vector3f& shipPosition) { + + // 1. Вычисление расстояния до поверхности планеты + const Vector3f planetWorldPosition = PLANET_CENTER_OFFSET; + const float distanceToPlanetCenter = (planetWorldPosition - shipPosition).length(); + const float distanceToPlanetSurface = distanceToPlanetCenter - PLANET_RADIUS; + std::cout << "distanceToPlanetSurface " << distanceToPlanetSurface << std::endl; + + float currentZNear; + float currentZFar; + float alpha; // Коэффициент интерполяции для текущего сегмента + + // Диапазон I: Далеко (FAR) -> Средне (MIDDLE) + if (distanceToPlanetSurface >= TRANSITION_FAR_START) { + // Полностью дальний диапазон + currentZNear = FAR_Z_NEAR; + currentZFar = FAR_Z_FAR; + + } + else if (distanceToPlanetSurface > TRANSITION_MIDDLE_START) { + // Плавный переход от FAR к MIDDLE + const float transitionLength = TRANSITION_FAR_START - TRANSITION_MIDDLE_START; + + // Нормализация расстояния, 0 при TRANSITION_FAR_START (Далеко), 1 при TRANSITION_MIDDLE_START (Близко) + float normalizedDist = (distanceToPlanetSurface - TRANSITION_MIDDLE_START) / transitionLength; + alpha = 1.0f - normalizedDist; // alpha = 0 (Далеко) ... 1 (Близко) + + // Интерполяция: FAR * (1-alpha) + MIDDLE * alpha + currentZNear = FAR_Z_NEAR * (1.0f - alpha) + MIDDLE_Z_NEAR * alpha; + currentZFar = FAR_Z_FAR * (1.0f - alpha) + MIDDLE_Z_FAR * alpha; + + // Диапазон II: Средне (MIDDLE) -> Близко (NEAR) + } + else if (distanceToPlanetSurface > TRANSITION_NEAR_END) { + // Плавный переход от MIDDLE к NEAR + const float transitionLength = TRANSITION_MIDDLE_START - TRANSITION_NEAR_END; + + // Нормализация расстояния, 0 при TRANSITION_MIDDLE_START (Далеко), 1 при TRANSITION_NEAR_END (Близко) + float normalizedDist = (distanceToPlanetSurface - TRANSITION_NEAR_END) / transitionLength; + alpha = 1.0f - normalizedDist; // alpha = 0 (Далеко) ... 1 (Близко) + + // Интерполяция: MIDDLE * (1-alpha) + NEAR * alpha + currentZNear = MIDDLE_Z_NEAR * (1.0f - alpha) + NEAR_Z_NEAR * alpha; + currentZFar = MIDDLE_Z_FAR * (1.0f - alpha) + NEAR_Z_FAR * alpha; + + } + else { + // Полностью ближний диапазон (distanceToPlanetSurface <= TRANSITION_NEAR_END) + currentZNear = NEAR_Z_NEAR; + currentZFar = NEAR_Z_FAR; + } + + return { currentZNear, currentZFar }; + } PerlinNoise::PerlinNoise() { p.resize(256); @@ -64,11 +143,11 @@ namespace ZL { 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; + //noiseValue = (noiseValue + 1.0f) * 0.5f; // Масштабируем: хотим отклонение от 1.0 до 1.1 // Значит амплитуда = 0.1 - float height = 1.0f + (noiseValue * 0.1f); // * 0.2 даст вариацию высоты + float height = 1.0f + (noiseValue * 0.002f); // * 0.2 даст вариацию высоты return height; } @@ -85,10 +164,10 @@ namespace ZL { void PlanetObject::init() { - planetMesh = generateSphere(7); + planetMesh = generateSphere(8); - planetMesh.Scale(300.f); - planetMesh.Move({ 0,0,-600 }); + planetMesh.Scale(PLANET_RADIUS); + planetMesh.Move(PLANET_CENTER_OFFSET); planetRenderStruct.data = planetMesh; planetRenderStruct.RefreshVBO(); @@ -123,9 +202,16 @@ namespace ZL { renderer.EnableVertexAttribArray(vNormalName); renderer.EnableVertexAttribArray(vTexCoordName); //renderer.EnableVertexAttribArray(vTexCoord3Name); + + const auto zRange = calculateZRange(Environment::shipPosition); + const float currentZNear = zRange.first; + const float currentZFar = zRange.second; + + // 2. Применяем динамическую матрицу проекции renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, static_cast(Environment::width) / static_cast(Environment::height), - 1, 1000); + currentZNear, currentZFar); + renderer.PushMatrix(); renderer.LoadIdentity(); renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom }); diff --git a/PlanetObject.h b/PlanetObject.h index 5f4741b..a3c0dc1 100644 --- a/PlanetObject.h +++ b/PlanetObject.h @@ -66,7 +66,6 @@ namespace ZL { std::vector subdivideTriangles(const std::vector& inputTriangles); Vector3f calculateSurfaceNormal(Vector3f p_sphere); VertexDataStruct trianglesToVertices(const std::vector& triangles); - VertexDataStruct generateOctahedron(); VertexDataStruct generateSphere(int subdivisions); }; diff --git a/SparkEmitter.cpp b/SparkEmitter.cpp index f5c8dd7..a374725 100644 --- a/SparkEmitter.cpp +++ b/SparkEmitter.cpp @@ -2,6 +2,8 @@ #include #include #include "OpenGlExtensions.h" +#include "Environment.h" + namespace ZL { @@ -125,7 +127,7 @@ namespace ZL { renderer.EnableVertexAttribArray(vTexCoordName); float aspectRatio = static_cast(screenWidth) / static_cast(screenHeight); - renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, aspectRatio, 1, 1000); + renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, aspectRatio, Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR); glBindTexture(GL_TEXTURE_2D, texture->getTexID()); diff --git a/ZLMath.h b/ZLMath.h index e1e5dd6..23b3017 100755 --- a/ZLMath.h +++ b/ZLMath.h @@ -56,6 +56,11 @@ namespace ZL { return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; } + float length() const + { + return sqrt(squaredNorm()); + } + float dot(const Vector3f& other) const { return v[0] * other.v[0] + v[1] * other.v[1] + v[2] * other.v[2]; }