Added planet physics and simple base
This commit is contained in:
parent
96d879076a
commit
d425167dce
6079
resources/platform1.txt
Normal file
6079
resources/platform1.txt
Normal file
File diff suppressed because it is too large
Load Diff
BIN
resources/platform_base.png
(Stored with Git LFS)
Normal file
BIN
resources/platform_base.png
(Stored with Git LFS)
Normal file
Binary file not shown.
17
src/Game.cpp
17
src/Game.cpp
@ -427,6 +427,9 @@ namespace ZL
|
||||
explosionEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
|
||||
}
|
||||
|
||||
//glBindTexture(GL_TEXTURE_2D, basePlatformTexture->getTexID());
|
||||
//renderer.DrawVertexRenderStruct(basePlatform);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
renderer.PopMatrix();
|
||||
renderer.PopProjectionMatrix();
|
||||
@ -1059,7 +1062,7 @@ namespace ZL
|
||||
handleMotion(mx, my);
|
||||
|
||||
}
|
||||
/*
|
||||
|
||||
if (event.type == SDL_MOUSEWHEEL) {
|
||||
static const float zoomstep = 2.0f;
|
||||
if (event.wheel.y > 0) {
|
||||
@ -1076,9 +1079,17 @@ namespace ZL
|
||||
{
|
||||
if (event.key.keysym.sym == SDLK_i)
|
||||
{
|
||||
|
||||
x = x + 1;
|
||||
}
|
||||
if (event.key.keysym.sym == SDLK_k)
|
||||
{
|
||||
x = x - 1;
|
||||
}
|
||||
if (event.key.keysym.sym == SDLK_a)
|
||||
{
|
||||
Environment::shipState.position = { 9466.15820, 1046.00159, 18531.2090 };
|
||||
}
|
||||
}
|
||||
}*/
|
||||
#endif
|
||||
}
|
||||
render();
|
||||
|
||||
@ -75,6 +75,7 @@ namespace ZL {
|
||||
VertexDataStruct spaceshipBase;
|
||||
VertexRenderStruct spaceship;
|
||||
|
||||
|
||||
VertexRenderStruct cubemap;
|
||||
|
||||
std::shared_ptr<Texture> boxTexture;
|
||||
|
||||
@ -45,6 +45,69 @@ void ClientState::simulate_physics(size_t delta) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float distToCenter = position.norm(); // Расстояние до {0,0,0}
|
||||
float landingZone = PLANET_RADIUS * PLANET_ALIGN_ZONE;
|
||||
|
||||
if (distToCenter <= landingZone) {
|
||||
Eigen::Vector3f planetNormal = position.normalized();
|
||||
|
||||
// --- 1. ВЫРАВНИВАНИЕ КРЕНА (Roll - ось Z) ---
|
||||
Eigen::Vector3f localX = rotation.col(0);
|
||||
float rollError = localX.dot(planetNormal);
|
||||
|
||||
if (std::abs(rollError) > 0.001f) {
|
||||
currentAngularVelocity.z() -= rollError * PLANET_ANGULAR_ACCEL * delta;
|
||||
currentAngularVelocity.z() = std::max(-PLANET_MAX_ANGULAR_VELOCITY,
|
||||
std::min(currentAngularVelocity.z(), PLANET_MAX_ANGULAR_VELOCITY));
|
||||
}
|
||||
|
||||
// --- 2. ОГРАНИЧЕНИЕ ТАНГАЖА (Pitch - ось X) ---
|
||||
// Нос корабля в локальных координатах — это -Z (третий столбец матрицы)
|
||||
Eigen::Vector3f forwardDir = -rotation.col(2);
|
||||
|
||||
// В твоем случае dot < 0 означает, что нос направлен К планете
|
||||
float pitchSin = forwardDir.dot(planetNormal);
|
||||
float currentPitchAngle = asinf(std::clamp(pitchSin, -1.0f, 1.0f));
|
||||
|
||||
// Лимит у нас M_PI / 6.0 (примерно 0.523)
|
||||
// По твоим данным: -0.89 < -0.523, значит мы превысили наклон вниз
|
||||
if (currentPitchAngle < -PITCH_LIMIT) {
|
||||
// Вычисляем ошибку (насколько мы ушли "ниже" лимита)
|
||||
// -0.89 - (-0.52) = -0.37
|
||||
float pitchError = currentPitchAngle + PITCH_LIMIT;
|
||||
|
||||
// Теперь важно: нам нужно ПОДНЯТЬ нос.
|
||||
// Если pitchError отрицательный, а нам нужно уменьшить вращение,
|
||||
// пробуем прибавлять или вычитать в зависимости от твоей оси X.
|
||||
// Судя по стандартной логике Eigen, нам нужно ПЛЮСОВАТЬ:
|
||||
currentAngularVelocity.x() -= pitchError * PLANET_ANGULAR_ACCEL * delta;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Вне зоны: тормозим Z (крен) И X (тангаж), если они были активны
|
||||
float drop = ANGULAR_ACCEL * delta;
|
||||
|
||||
if (std::abs(currentAngularVelocity[2]) > 0.0001f) {
|
||||
if (std::abs(currentAngularVelocity[2]) <= drop) {
|
||||
currentAngularVelocity[2] = 0.0f;
|
||||
}
|
||||
else {
|
||||
currentAngularVelocity[2] -= (currentAngularVelocity[2] > 0 ? 1.0f : -1.0f) * drop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ограничение скорости
|
||||
currentAngularVelocity.x() = std::max(-PLANET_MAX_ANGULAR_VELOCITY,
|
||||
std::min(currentAngularVelocity.x(), PLANET_MAX_ANGULAR_VELOCITY));
|
||||
// Ограничение скорости
|
||||
currentAngularVelocity.y() = std::max(-PLANET_MAX_ANGULAR_VELOCITY,
|
||||
std::min(currentAngularVelocity.y(), PLANET_MAX_ANGULAR_VELOCITY));
|
||||
// Ограничение скорости
|
||||
currentAngularVelocity.z() = std::max(-PLANET_MAX_ANGULAR_VELOCITY,
|
||||
std::min(currentAngularVelocity.z(), PLANET_MAX_ANGULAR_VELOCITY));
|
||||
|
||||
float speedScale = currentAngularVelocity.norm();
|
||||
if (speedScale > 0.0001f) {
|
||||
// Коэффициент чувствительности вращения
|
||||
|
||||
@ -13,6 +13,12 @@ constexpr float ANGULAR_ACCEL = 0.005f * 1000.0f;
|
||||
constexpr float SHIP_ACCEL = 1.0f * 1000.0f;
|
||||
constexpr float ROTATION_SENSITIVITY = 0.002f;
|
||||
|
||||
constexpr float PLANET_RADIUS = 20000.f;
|
||||
constexpr float PLANET_ALIGN_ZONE = 1.05f;
|
||||
constexpr float PLANET_ANGULAR_ACCEL = 0.01f; // Подбери под динамику
|
||||
constexpr float PLANET_MAX_ANGULAR_VELOCITY = 10.f;
|
||||
constexpr float PITCH_LIMIT = static_cast<float>(M_PI) / 9.f;//18.0f;
|
||||
|
||||
constexpr long long SERVER_DELAY = 0; //ms
|
||||
constexpr long long CLIENT_DELAY = 200; //ms
|
||||
constexpr long long CUTOFF_TIME = 5000; //ms
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
namespace ZL {
|
||||
|
||||
Matrix3f GetRotationForTriangle(const Triangle& tri);
|
||||
|
||||
const float PlanetData::PLANET_RADIUS = 20000.f;
|
||||
const Vector3f PlanetData::PLANET_CENTER_OFFSET = Vector3f{ 0.f, 0.f, 0.0f };
|
||||
@ -29,9 +30,9 @@ namespace ZL {
|
||||
PlanetData::PlanetData()
|
||||
: perlin(77777)
|
||||
, colorPerlin(123123)
|
||||
, currentLod(0)
|
||||
//, currentLod(0)
|
||||
{
|
||||
currentLod = planetMeshLods.size() - 1; // Start with max LOD
|
||||
// currentLod = planetMeshLods.size() - 1; // Start with max LOD
|
||||
/*
|
||||
initialVertexMap = {
|
||||
{{ 0.0f, 1.0f, 0.0f}, "A"},
|
||||
@ -54,10 +55,29 @@ namespace ZL {
|
||||
planetAtmosphereLod = generateSphere(5, 0);
|
||||
planetAtmosphereLod.Scale(PLANET_RADIUS * 1.03);
|
||||
planetAtmosphereLod.Move(PLANET_CENTER_OFFSET);
|
||||
|
||||
const auto& lodLevel = getLodLevel();
|
||||
|
||||
for (size_t i = 0; i < lodLevel.triangles.size(); i++)
|
||||
{
|
||||
if (i % 100 == 0)
|
||||
{
|
||||
PlanetCampObject campObject;
|
||||
|
||||
campObject.position = (lodLevel.triangles[i].data[0] +
|
||||
lodLevel.triangles[i].data[1] +
|
||||
lodLevel.triangles[i].data[2]) / 3.0f;
|
||||
|
||||
auto newM = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI * 0.5, Eigen::Vector3f::UnitX())).toRotationMatrix();
|
||||
|
||||
campObject.rotation = GetRotationForTriangle(lodLevel.triangles[i]).inverse() * newM;
|
||||
campObjects.push_back(campObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const LodLevel& PlanetData::getLodLevel(int level) const {
|
||||
return planetMeshLods.at(level);
|
||||
const LodLevel& PlanetData::getLodLevel() const {
|
||||
return planetMeshLods.at(MAX_LOD_LEVELS-1);
|
||||
}
|
||||
|
||||
|
||||
@ -65,13 +85,14 @@ namespace ZL {
|
||||
return planetAtmosphereLod;
|
||||
}
|
||||
|
||||
/*
|
||||
int PlanetData::getCurrentLodIndex() const {
|
||||
return currentLod;
|
||||
}
|
||||
|
||||
int PlanetData::getMaxLodIndex() const {
|
||||
return static_cast<int>(planetMeshLods.size() - 1);
|
||||
}
|
||||
}*/
|
||||
|
||||
std::pair<float, float> PlanetData::calculateZRange(float dToPlanetSurface) {
|
||||
|
||||
@ -138,7 +159,7 @@ namespace ZL {
|
||||
|
||||
|
||||
std::vector<int> PlanetData::getBestTriangleUnderCamera(const Vector3f& viewerPosition) {
|
||||
const LodLevel& finalLod = planetMeshLods[currentLod]; // Работаем с текущим активным LOD
|
||||
const LodLevel& finalLod = planetMeshLods[MAX_LOD_LEVELS - 1]; // Работаем с текущим активным LOD
|
||||
Vector3f targetDir = (viewerPosition - PLANET_CENTER_OFFSET).normalized();
|
||||
|
||||
int bestTriangle = -1;
|
||||
@ -167,7 +188,7 @@ namespace ZL {
|
||||
}
|
||||
|
||||
std::vector<int> PlanetData::getTrianglesUnderCameraNew2(const Vector3f& viewerPosition) {
|
||||
const LodLevel& finalLod = planetMeshLods[currentLod];
|
||||
const LodLevel& finalLod = planetMeshLods[MAX_LOD_LEVELS - 1];
|
||||
Vector3f shipLocal = viewerPosition - PLANET_CENTER_OFFSET;
|
||||
float currentDist = shipLocal.norm();
|
||||
Vector3f targetDir = shipLocal.normalized();
|
||||
|
||||
@ -75,6 +75,20 @@ namespace ZL {
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
@ -87,7 +101,7 @@ namespace ZL {
|
||||
std::array<LodLevel, MAX_LOD_LEVELS> planetMeshLods;
|
||||
LodLevel planetAtmosphereLod;
|
||||
|
||||
int currentLod; // Логический текущий уровень детализации
|
||||
//int currentLod; // Логический текущий уровень детализации
|
||||
|
||||
//std::map<Vector3f, VertexID, Vector3fComparator> initialVertexMap;
|
||||
|
||||
@ -100,12 +114,8 @@ namespace ZL {
|
||||
PlanetData();
|
||||
|
||||
void init();
|
||||
|
||||
// Методы доступа к данным (для рендерера)
|
||||
const LodLevel& getLodLevel(int level) const;
|
||||
const LodLevel& getLodLevel() const;
|
||||
const LodLevel& getAtmosphereLod() const;
|
||||
int getCurrentLodIndex() const;
|
||||
int getMaxLodIndex() const;
|
||||
|
||||
// Логика
|
||||
std::pair<float, float> calculateZRange(float distanceToSurface);
|
||||
@ -116,6 +126,9 @@ namespace ZL {
|
||||
std::vector<int> getTrianglesUnderCameraNew2(const Vector3f& viewerPosition);
|
||||
|
||||
void applySphericalRelaxation(LodLevel& lod, int iterations);
|
||||
|
||||
std::vector<PlanetCampObject> campObjects;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ZL
|
||||
@ -5,9 +5,12 @@
|
||||
#include "Environment.h"
|
||||
#include "StoneObject.h"
|
||||
#include "utils/TaskManager.h"
|
||||
#include "TextModel.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
extern float x;
|
||||
|
||||
#if defined EMSCRIPTEN || defined __ANDROID__
|
||||
using std::min;
|
||||
using std::max;
|
||||
@ -70,8 +73,7 @@ namespace ZL {
|
||||
|
||||
// 2. Забираем данные для VBO
|
||||
// Берем максимальный LOD для начальной отрисовки
|
||||
int lodIndex = planetData.getMaxLodIndex();
|
||||
planetRenderStruct.data = planetData.getLodLevel(lodIndex).vertexData;
|
||||
planetRenderStruct.data = planetData.getLodLevel().vertexData;
|
||||
|
||||
//planetRenderStruct.data.PositionData.resize(9);
|
||||
planetRenderStruct.RefreshVBO();
|
||||
@ -87,13 +89,20 @@ namespace ZL {
|
||||
planetAtmosphereRenderStruct.RefreshVBO();
|
||||
}
|
||||
|
||||
planetStones = CreateStoneGroupData(778, planetData.getLodLevel(lodIndex));
|
||||
planetStones = CreateStoneGroupData(778, planetData.getLodLevel());
|
||||
|
||||
//stonesToRender = planetStones.inflate(planetStones.allInstances.size());
|
||||
stonesToRender.resize(planetStones.allInstances.size());
|
||||
planetStones.initStatuses();
|
||||
|
||||
stoneToBake = planetStones.inflateOne(0, 0.75);
|
||||
|
||||
|
||||
campPlatform.data = LoadFromTextFile02("resources/platform1.txt", CONST_ZIP_FILE);
|
||||
campPlatform.RefreshVBO();
|
||||
|
||||
campPlatformTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/platform_base.png", CONST_ZIP_FILE));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -187,7 +196,7 @@ namespace ZL {
|
||||
renderer.EnableVertexAttribArray(vPositionName);
|
||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
||||
|
||||
Triangle tr = planetData.getLodLevel(planetData.getCurrentLodIndex()).triangles[0];
|
||||
Triangle tr = planetData.getLodLevel().triangles[0];
|
||||
|
||||
// 1. Получаем матрицу вращения (оси в столбцах)
|
||||
Matrix3f mr = GetRotationForTriangle(tr);
|
||||
@ -282,6 +291,8 @@ namespace ZL {
|
||||
|
||||
drawPlanet(renderer);
|
||||
drawStones(renderer);
|
||||
drawCamp(renderer);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
drawAtmosphere(renderer);
|
||||
}
|
||||
|
||||
@ -328,7 +339,7 @@ namespace ZL {
|
||||
renderer.RenderUniform1i("BakedTexture", 1);
|
||||
|
||||
|
||||
Triangle tr = planetData.getLodLevel(planetData.getCurrentLodIndex()).triangles[0]; // Берем базовый треугольник
|
||||
Triangle tr = planetData.getLodLevel().triangles[0]; // Берем базовый треугольник
|
||||
Matrix3f mr = GetRotationForTriangle(tr); // Та же матрица, что и при запекании
|
||||
|
||||
// Позиция камеры (корабля) в мире
|
||||
@ -464,7 +475,7 @@ namespace ZL {
|
||||
renderer.shaderManager.PopShader();
|
||||
CheckGlError();
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
}
|
||||
|
||||
void PlanetObject::drawAtmosphere(Renderer& renderer) {
|
||||
@ -568,6 +579,92 @@ namespace ZL {
|
||||
|
||||
}
|
||||
|
||||
void PlanetObject::drawCamp(Renderer& renderer)
|
||||
{
|
||||
static const std::string defaultShaderName2 = "default";
|
||||
static const std::string vPositionName = "vPosition";
|
||||
static const std::string vColorName = "vColor";
|
||||
static const std::string vNormalName = "vNormal";
|
||||
static const std::string vTexCoordName = "vTexCoord";
|
||||
static const std::string textureUniformName = "Texture";
|
||||
|
||||
renderer.shaderManager.PushShader(defaultShaderName2);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
renderer.EnableVertexAttribArray(vPositionName);
|
||||
renderer.EnableVertexAttribArray(vColorName);
|
||||
renderer.EnableVertexAttribArray(vNormalName);
|
||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
||||
|
||||
|
||||
float dist = planetData.distanceToPlanetSurfaceFast(Environment::shipState.position);
|
||||
auto zRange = planetData.calculateZRange(dist);
|
||||
const float currentZNear = zRange.first;
|
||||
const float currentZFar = zRange.second;
|
||||
|
||||
|
||||
// 2. Применяем динамическую матрицу проекции
|
||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||
currentZNear, currentZFar);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.LoadIdentity();
|
||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||||
renderer.TranslateMatrix(-Environment::shipState.position);
|
||||
|
||||
renderer.RenderUniform1f("uDistanceToPlanetSurface", dist);
|
||||
renderer.RenderUniform1f("uCurrentZFar", currentZFar);
|
||||
renderer.RenderUniform3fv("uViewPos", Environment::shipState.position.data());
|
||||
//std::cout << "uViewPos" << Environment::shipState.position << std::endl;
|
||||
// PlanetObject.cpp, метод drawStones
|
||||
Vector3f sunDirWorld = Vector3f(1.0f, -1.0f, -1.0f).normalized();
|
||||
renderer.RenderUniform3fv("uLightDirWorld", sunDirWorld.data());
|
||||
|
||||
Vector3f playerDirWorld = Environment::shipState.position.normalized();
|
||||
float playerLightFactor = max(0.0f, (playerDirWorld.dot(-sunDirWorld) + 0.2f) / 1.2f);
|
||||
renderer.RenderUniform1f("uPlayerLightFactor", playerLightFactor);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
for (int i = 0; i < planetData.campObjects.size(); i++)
|
||||
{
|
||||
|
||||
renderer.PushMatrix();
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix(planetData.campObjects[i].position);
|
||||
renderer.RotateMatrix(planetData.campObjects[i].rotation);
|
||||
renderer.ScaleMatrix(Vector3f{ 2.0f, 2.0f, 2.0f });
|
||||
renderer.TranslateMatrix(planetData.campObjects[i].platformPos[j]);
|
||||
glBindTexture(GL_TEXTURE_2D, campPlatformTexture->getTexID());
|
||||
renderer.DrawVertexRenderStruct(campPlatform);
|
||||
renderer.PopMatrix();
|
||||
}
|
||||
renderer.PopMatrix();
|
||||
|
||||
}
|
||||
|
||||
CheckGlError();
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
renderer.PopMatrix();
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||
renderer.DisableVertexAttribArray(vNormalName);
|
||||
renderer.DisableVertexAttribArray(vColorName);
|
||||
renderer.DisableVertexAttribArray(vPositionName);
|
||||
renderer.shaderManager.PopShader();
|
||||
CheckGlError();
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
float PlanetObject::distanceToPlanetSurface(const Vector3f& viewerPosition)
|
||||
{
|
||||
return planetData.distanceToPlanetSurfaceFast(viewerPosition);
|
||||
|
||||
@ -41,6 +41,10 @@ namespace ZL {
|
||||
|
||||
std::unique_ptr<FrameBuffer> stoneMapFB;
|
||||
|
||||
|
||||
VertexRenderStruct campPlatform;
|
||||
std::shared_ptr<Texture> campPlatformTexture;
|
||||
|
||||
Vector3f lastUpdatePos;
|
||||
|
||||
// External items, set outside
|
||||
@ -57,6 +61,7 @@ namespace ZL {
|
||||
void drawStones(Renderer& renderer);
|
||||
void drawPlanet(Renderer& renderer);
|
||||
void drawAtmosphere(Renderer& renderer);
|
||||
void drawCamp(Renderer& renderer);
|
||||
|
||||
float distanceToPlanetSurface(const Vector3f& viewerPosition);
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user