added new class camera
This commit is contained in:
parent
0a72040110
commit
47da35a401
@ -18,6 +18,8 @@ add_executable(space-game001
|
||||
../src/Environment.h
|
||||
../src/render/Renderer.cpp
|
||||
../src/render/Renderer.h
|
||||
../src/render/Camera.cpp
|
||||
../src/render/Camera.h
|
||||
../src/render/ShaderManager.cpp
|
||||
../src/render/ShaderManager.h
|
||||
../src/render/TextureManager.cpp
|
||||
|
||||
292
src/Game.cpp
292
src/Game.cpp
@ -1,3 +1,4 @@
|
||||
#include "GameConfig.h"
|
||||
#include "Game.h"
|
||||
#include "AnimatedModel.h"
|
||||
#include "BoneAnimatedModel.h"
|
||||
@ -250,12 +251,7 @@ namespace ZL
|
||||
renderer, CONST_ZIP_FILE,
|
||||
"resources/joystick_base.png", "resources/joystick_knob.png");
|
||||
|
||||
/*uiManager.setSliderCallback("musicVolumeSlider", [this](const std::string& name, float value) {
|
||||
std::cerr << "Music volume slider changed to: " << value << std::endl;
|
||||
musicVolume = value;
|
||||
Environment::shipVelocity = musicVolume * 20.0f;
|
||||
});
|
||||
//#endif*/
|
||||
|
||||
|
||||
cubemapTexture = std::make_shared<Texture>(
|
||||
std::array<TextureDataStruct, 6>{
|
||||
@ -275,24 +271,17 @@ namespace ZL
|
||||
|
||||
//Load texture
|
||||
|
||||
//spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/DefaultMaterial_BaseColor_shine.png", CONST_ZIP_FILE));
|
||||
//spaceshipBase = LoadFromTextFile02("resources/spaceship006.txt", CONST_ZIP_FILE);
|
||||
//spaceshipBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI / 2.0, Eigen::Vector3f::UnitY())).toRotationMatrix());// QuatFromRotateAroundY(M_PI / 2.0).toRotationMatrix());
|
||||
|
||||
//spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/cap_D.png", CONST_ZIP_FILE));
|
||||
//spaceshipBase = LoadFromTextFile02("./resources/spaceship006x.txt", CONST_ZIP_FILE);
|
||||
//spaceshipBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI / 2.0, Eigen::Vector3f::UnitY())).toRotationMatrix());// QuatFromRotateAroundY(M_PI / 2.0).toRotationMatrix());
|
||||
|
||||
spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/MainCharacter_Base_color_sRGB.png", CONST_ZIP_FILE));
|
||||
spaceshipBase = LoadFromTextFile02("resources/spaceshipnew001.txt", CONST_ZIP_FILE);
|
||||
spaceshipBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())).toRotationMatrix());// QuatFromRotateAroundY(M_PI / 2.0).toRotationMatrix());
|
||||
|
||||
//spaceshipBase.Move(Vector3f{ 1.2, 0, -5 });
|
||||
//spaceshipBase.Move(Vector3f{ -0.52998, -13, 0 });
|
||||
|
||||
|
||||
|
||||
spaceshipBase.Move(Vector3f{ -0.52998, 0, -10 });
|
||||
//spaceshipBase.Move(Vector3f{ 1.2, 0, -5 });
|
||||
|
||||
|
||||
|
||||
spaceship.AssignFrom(spaceshipBase);
|
||||
@ -308,7 +297,7 @@ namespace ZL
|
||||
for (int i = 0; i < boxCoordsArr.size(); i++)
|
||||
{
|
||||
boxRenderArr[i].AssignFrom(boxBase);
|
||||
//boxRenderArr[i].data = CreateBaseConvexPolyhedron(1999);
|
||||
|
||||
boxRenderArr[i].RefreshVBO();
|
||||
}
|
||||
|
||||
@ -351,8 +340,13 @@ namespace ZL
|
||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
renderer.PushMatrix();
|
||||
|
||||
renderer.LoadIdentity();
|
||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||||
|
||||
// Для скайбокса берем только вращение от камеры
|
||||
Matrix4f view = camera.getViewMatrix();
|
||||
view.block<3, 1>(0, 3) = Vector3f::Zero(); // Убираем смещение
|
||||
renderer.PushSpecialMatrix(view);
|
||||
|
||||
|
||||
Vector3f worldLightDir = Vector3f(1.0f, -1.0f, -1.0f).normalized();
|
||||
@ -392,7 +386,8 @@ namespace ZL
|
||||
CheckGlError();
|
||||
|
||||
|
||||
renderer.PopMatrix();
|
||||
renderer.PopMatrix(); // Pop special matrix
|
||||
renderer.PopMatrix(); // Pop original push
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.DisableVertexAttribArray(vPositionName);
|
||||
|
||||
@ -417,20 +412,20 @@ namespace ZL
|
||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
renderer.PushMatrix();
|
||||
renderer.LoadIdentity();
|
||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||
renderer.TranslateMatrix({ 0, -6.f, 0 }); //Ship camera offset
|
||||
|
||||
// Корабль рисуется с учётом разницы между его ориентацией и камерой
|
||||
// shipWorldOrientation - куда смотрит корабль в мире
|
||||
// Environment::inverseShipMatrix - обратная матрица камеры
|
||||
Matrix3f shipRelativeToCamera = Environment::inverseShipMatrix * shipWorldOrientation;
|
||||
renderer.RotateMatrix(shipRelativeToCamera);
|
||||
renderer.LoadIdentity();
|
||||
|
||||
renderer.PushSpecialMatrix(camera.getViewMatrix());
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix(Environment::shipState.position);
|
||||
renderer.RotateMatrix(shipWorldOrientation);
|
||||
|
||||
if (shipAlive) {
|
||||
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
||||
renderer.DrawVertexRenderStruct(spaceship);
|
||||
}
|
||||
renderer.PopMatrix();
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
@ -453,7 +448,8 @@ namespace ZL
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
renderer.PopMatrix();
|
||||
renderer.PopMatrix(); // Pop special matrix
|
||||
renderer.PopMatrix(); // Pop original push
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.DisableVertexAttribArray(vPositionName);
|
||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||
@ -479,15 +475,17 @@ namespace ZL
|
||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.LoadIdentity();
|
||||
renderer.PushSpecialMatrix(camera.getViewMatrix());
|
||||
|
||||
for (int i = 0; i < boxCoordsArr.size(); i++)
|
||||
{
|
||||
if (!boxAlive[i]) continue;
|
||||
renderer.PushMatrix();
|
||||
|
||||
renderer.LoadIdentity();
|
||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||||
renderer.TranslateMatrix(-Environment::shipState.position);
|
||||
// Коробки рисуются в мировых координатах
|
||||
// Но у них есть offset { 0.f, 0.f, 45000.f }
|
||||
renderer.TranslateMatrix({ 0.f, 0.f, 45000.f });
|
||||
renderer.TranslateMatrix(boxCoordsArr[i].pos);
|
||||
renderer.RotateMatrix(boxCoordsArr[i].m);
|
||||
@ -498,6 +496,8 @@ namespace ZL
|
||||
|
||||
renderer.PopMatrix();
|
||||
}
|
||||
renderer.PopMatrix(); // Pop special matrix
|
||||
renderer.PopMatrix(); // Pop original push
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.DisableVertexAttribArray(vPositionName);
|
||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||
@ -542,8 +542,15 @@ namespace ZL
|
||||
|
||||
glViewport(0, 0, Environment::width, Environment::height);
|
||||
|
||||
glViewport(0, 0, Environment::width, Environment::height);
|
||||
|
||||
CheckGlError();
|
||||
|
||||
|
||||
// Обновляем камеру
|
||||
// camera.follow(Environment::shipState.position, shipWorldOrientation, Environment::zoom, 6.0f);
|
||||
camera.followOrbit(Environment::shipState.position, camYaw, camPitch, Environment::zoom, 6.0f);
|
||||
|
||||
float skyPercent = 0.0;
|
||||
float distance = planetObject.distanceToPlanetSurface(Environment::shipState.position);
|
||||
if (distance > 1500.f)
|
||||
@ -567,7 +574,9 @@ namespace ZL
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
drawShip();
|
||||
#if ENABLE_REMOTE_SHIPS
|
||||
drawRemoteShips();
|
||||
#endif
|
||||
drawBoxes();
|
||||
|
||||
drawUI();
|
||||
@ -615,21 +624,20 @@ namespace ZL
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.LoadIdentity();
|
||||
renderer.PushSpecialMatrix(camera.getViewMatrix());
|
||||
|
||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||
renderer.TranslateMatrix({ 0, -6.f, 0 }); //Ship camera offset
|
||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||||
renderer.TranslateMatrix(-Environment::shipState.position);
|
||||
|
||||
|
||||
Eigen::Vector3f relativePos = playerState.position;// -Environment::shipPosition;
|
||||
renderer.TranslateMatrix(relativePos);
|
||||
renderer.PushMatrix();
|
||||
// Позиция удаленного игрока в мире
|
||||
renderer.TranslateMatrix(playerState.position);
|
||||
|
||||
// 3. Поворот врага
|
||||
renderer.RotateMatrix(playerState.rotation);
|
||||
|
||||
renderer.DrawVertexRenderStruct(spaceship);
|
||||
renderer.PopMatrix();
|
||||
|
||||
renderer.PopMatrix();
|
||||
renderer.PopMatrix();
|
||||
}
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
@ -668,126 +676,82 @@ namespace ZL
|
||||
sparkEmitter.update(static_cast<float>(delta));
|
||||
planetObject.update(static_cast<float>(delta));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Управление: Джойстик (движение) vs Камера (орбита)
|
||||
|
||||
float discreteMag = 0.0f;
|
||||
int discreteAngle = -1;
|
||||
float discreteMag = 0;
|
||||
|
||||
// 1. Joystick Logic (Movement)
|
||||
auto joystick = uiManager.findJoystick("shipJoystick");
|
||||
if (joystick && joystick->isActive) {
|
||||
float joyX = joystick->getDirectionX(); // -1..1
|
||||
float joyY = joystick->getDirectionY(); // -1..1
|
||||
float magnitude = joystick->getMagnitude(); // 0..1
|
||||
|
||||
discreteMag = roundf(magnitude * 10) * 0.1f;
|
||||
|
||||
float angleY = std::atan2(-joyX, -joyY);
|
||||
|
||||
discreteAngle = static_cast<int>(angleY * 180.0f / M_PI);
|
||||
if (discreteAngle < 0) discreteAngle += 360;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//<<<<<<< HEAD
|
||||
// Управление кораблём через джойстик
|
||||
/*auto joystick = uiManager.findJoystick("shipJoystick");
|
||||
if (joystick && joystick->isActive) {
|
||||
float joyX = joystick->getDirectionX(); // -1..1
|
||||
float joyY = joystick->getDirectionY(); // -1..1
|
||||
float magnitude = joystick->getMagnitude(); // 0..1
|
||||
if (isUsingJoystick && joystick && joystick->isActive) {
|
||||
float joyX = joystick->getDirectionX();
|
||||
float joyY = joystick->getDirectionY();
|
||||
float magnitude = joystick->getMagnitude();
|
||||
|
||||
if (magnitude > 0.1f) {
|
||||
// Скорость пропорциональна отклонению джойстика
|
||||
Environment::shipState.velocity = magnitude * 500.0f * static_cast<float>(delta) / 100.0f;
|
||||
|
||||
// Направление джойстика относительно камеры
|
||||
// joyY отрицательный = вперёд, joyX = влево/вправо
|
||||
float angleY = std::atan2(-joyX, -joyY);
|
||||
|
||||
// Локальный поворот в пространстве камеры
|
||||
Eigen::Quaternionf localRotation(Eigen::AngleAxisf(angleY, Eigen::Vector3f::UnitY()));
|
||||
Matrix3f localRotMat = localRotation.toRotationMatrix();
|
||||
|
||||
// Преобразуем в мировую ориентацию: камера * локальный_поворот
|
||||
shipWorldOrientation = Environment::shipState.rotation * localRotMat;
|
||||
}
|
||||
else {
|
||||
// Movement logic
|
||||
Environment::shipState.velocity = 0.0f;
|
||||
}
|
||||
}
|
||||
else if (Environment::tapDownHold && !uiManager.isUiInteraction())
|
||||
{
|
||||
float diffx = Environment::tapDownCurrentPos(0) - Environment::tapDownStartPos(0);
|
||||
float diffy = Environment::tapDownCurrentPos(1) - Environment::tapDownStartPos(1);
|
||||
|
||||
// Только управление камерой через drag (вне зоны джойстика)
|
||||
if (isDraggingCamera) {
|
||||
if (std::abs(diffy) > 5.0f || std::abs(diffx) > 5.0f)
|
||||
{
|
||||
float rotationPower = std::sqrt(diffx * diffx + diffy * diffy);
|
||||
float deltaAlpha = rotationPower * static_cast<float>(delta) * static_cast<float>(M_PI) / 15000.f;
|
||||
float moveSpeed = 0.5f;
|
||||
|
||||
Eigen::Vector3f rotationDirection(diffy, diffx, 0.0f);
|
||||
rotationDirection.normalize();
|
||||
// Local movement vector
|
||||
Vector3f localMove(joyX, 0.0f, joyY);
|
||||
|
||||
Eigen::Quaternionf rotateQuat(Eigen::AngleAxisf(deltaAlpha, rotationDirection));
|
||||
Matrix3f rotateMat = rotateQuat.toRotationMatrix();
|
||||
// Transform to world space using current ship rotation
|
||||
Vector3f worldMove = Environment::shipState.rotation * localMove;
|
||||
|
||||
Environment::shipState.rotation = Environment::shipState.rotation * rotateMat;
|
||||
Environment::inverseShipMatrix = Environment::shipState.rotation.inverse();
|
||||
// Apply to position
|
||||
Environment::shipState.position += worldMove * moveSpeed * static_cast<float>(delta);
|
||||
|
||||
// плавное вращение (ВАЖНО!)
|
||||
Environment::tapDownStartPos = Environment::tapDownCurrentPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float discreteMag;
|
||||
int discreteAngle;
|
||||
|
||||
if (Environment::tapDownHold) {
|
||||
float diffx = Environment::tapDownCurrentPos(0) - Environment::tapDownStartPos(0);
|
||||
float diffy = Environment::tapDownCurrentPos(1) - Environment::tapDownStartPos(1);
|
||||
|
||||
float rawMag = sqrtf(diffx * diffx + diffy * diffy);
|
||||
float maxRadius = 200.0f; // Максимальный вынос джойстика
|
||||
|
||||
if (rawMag > 10.0f) { // Мертвая зона
|
||||
// 1. Дискретизируем отклонение (0.0 - 1.0 с шагом 0.1)
|
||||
float normalizedMag = min(rawMag / maxRadius, 1.0f);
|
||||
discreteMag = std::round(normalizedMag * 10.0f) / 10.0f;
|
||||
|
||||
// 2. Дискретизируем угол (0-359 градусов)
|
||||
// atan2 возвращает радианы, переводим в градусы
|
||||
float radians = atan2f(diffy, diffx);
|
||||
// Calculate discrete values for network
|
||||
// Angle 0-359
|
||||
float radians = atan2f(joyY, joyX);
|
||||
discreteAngle = static_cast<int>(radians * 180.0f / M_PI);
|
||||
if (discreteAngle < 0) discreteAngle += 360;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
discreteAngle = -1;
|
||||
discreteMag = 0.0f;
|
||||
// Magnitude 0.0-1.0
|
||||
discreteMag = (std::min)(magnitude, 1.0f);
|
||||
discreteMag = std::round(discreteMag * 10.0f) / 10.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
discreteAngle = -1;
|
||||
discreteMag = 0.0f;
|
||||
>>>>>>> main*/
|
||||
//}
|
||||
// 2. Camera Drag Logic
|
||||
else if (isDraggingCamera && Environment::tapDownHold && !uiManager.isUiInteraction()) {
|
||||
float diffx = Environment::tapDownCurrentPos(0) - Environment::tapDownStartPos(0);
|
||||
float diffy = Environment::tapDownCurrentPos(1) - Environment::tapDownStartPos(1);
|
||||
|
||||
if (std::abs(diffx) > 1.0f || std::abs(diffy) > 1.0f) {
|
||||
float sensitivity = 0.01f; // Radians per pixel
|
||||
|
||||
camYaw -= diffx * sensitivity; // Yaw: Horizontal drag
|
||||
camPitch -= diffy * sensitivity; // Pitch: Vertical drag
|
||||
|
||||
// Clamp pitch to avoid flipping
|
||||
// -80 to 80 degrees in radians
|
||||
float pitchLimit = 80.0f * static_cast<float>(M_PI) / 180.0f;
|
||||
if (camPitch > pitchLimit) camPitch = pitchLimit;
|
||||
if (camPitch < -pitchLimit) camPitch = -pitchLimit;
|
||||
|
||||
// Reset for incremental update
|
||||
Environment::tapDownStartPos = Environment::tapDownCurrentPos;
|
||||
}
|
||||
}
|
||||
|
||||
// Network Update
|
||||
if (discreteAngle != Environment::shipState.discreteAngle || discreteMag != Environment::shipState.discreteMag) {
|
||||
Environment::shipState.discreteAngle = discreteAngle;
|
||||
Environment::shipState.discreteMag = discreteMag;
|
||||
|
||||
std::string msg = "UPD:" + std::to_string(now_ms) + ":" + Environment::shipState.formPingMessageContent();
|
||||
networkClient->Send(msg);
|
||||
std::cout << "Sending: " << msg << std::endl;
|
||||
//std::cout << "Sending: " << msg << std::endl;
|
||||
}
|
||||
|
||||
|
||||
Environment::shipState.simulate_physics(delta);
|
||||
Environment::inverseShipMatrix = Environment::shipState.rotation.inverse();
|
||||
|
||||
@ -814,6 +778,7 @@ namespace ZL
|
||||
projectileEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
}
|
||||
|
||||
|
||||
std::vector<Vector3f> shipCameraPoints;
|
||||
for (const auto& lp : shipLocalEmissionPoints) {
|
||||
Vector3f adjusted = lp + Vector3f{ 0.0f, -Environment::zoom * 0.03f, 0.0f };
|
||||
@ -1174,24 +1139,20 @@ namespace ZL
|
||||
|
||||
uiManager.onMouseDown(uiX, uiY);
|
||||
|
||||
bool uiHandled = false;
|
||||
|
||||
for (const auto& button : uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
|
||||
(void)button;
|
||||
// Check if joystick became active
|
||||
auto joystick = uiManager.findJoystick("shipJoystick");
|
||||
if (joystick && joystick->isActive) {
|
||||
isUsingJoystick = true;
|
||||
isDraggingCamera = false;
|
||||
Environment::tapDownHold = false; // Don't trigger camera drag
|
||||
}
|
||||
|
||||
auto pressedSlider = [&]() -> std::shared_ptr<UiSlider> {
|
||||
for (const auto& slider : uiManager.findSlider("") ? std::vector<std::shared_ptr<UiSlider>>{} : std::vector<std::shared_ptr<UiSlider>>{}) {
|
||||
(void)slider;
|
||||
}
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
if (!uiManager.isUiInteraction()) {
|
||||
// Джойстик обрабатывает управление кораблём, поэтому
|
||||
// любое нажатие вне UI элементов - это управление камерой
|
||||
isDraggingShip = false;
|
||||
else if (!uiManager.isUiInteraction()) {
|
||||
// No UI interaction (and no joystick), so it's camera drag
|
||||
isUsingJoystick = false;
|
||||
isDraggingCamera = true;
|
||||
Environment::tapDownHold = true;
|
||||
Environment::tapDownStartPos = Vector2f(static_cast<float>(mx), static_cast<float>(my));
|
||||
Environment::tapDownCurrentPos = Environment::tapDownStartPos;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1200,33 +1161,14 @@ namespace ZL
|
||||
int uiX = mx;
|
||||
int uiY = Environment::height - my;
|
||||
|
||||
// Проверяем был ли активен джойстик до отпускания
|
||||
auto joystick = uiManager.findJoystick("shipJoystick");
|
||||
bool wasJoystickActive = joystick && joystick->isActive;
|
||||
|
||||
uiManager.onMouseUp(uiX, uiY);
|
||||
|
||||
// Сбрасываем состояние если отпустили джойстик
|
||||
/*
|
||||
if (wasJoystickActive) {
|
||||
Environment::shipVelocity = 0.0f;
|
||||
shipMoveLockActive = false;
|
||||
rotateShipMat = Matrix3f::Identity();
|
||||
if (isUsingJoystick) {
|
||||
isUsingJoystick = false;
|
||||
}
|
||||
|
||||
if (!uiManager.isUiInteraction()) {
|
||||
Environment::tapDownHold = false;
|
||||
Environment::shipVelocity = 0.0f;
|
||||
|
||||
shipMoveLockActive = false;
|
||||
|
||||
if (isDraggingCamera) {
|
||||
rotateShipMat = Matrix3f::Identity();
|
||||
}
|
||||
|
||||
isDraggingShip = false;
|
||||
isDraggingCamera = false;
|
||||
}*/
|
||||
isDraggingCamera = false;
|
||||
Environment::tapDownHold = false;
|
||||
}
|
||||
|
||||
void Game::handleMotion(int mx, int my)
|
||||
@ -1236,9 +1178,9 @@ namespace ZL
|
||||
|
||||
uiManager.onMouseMove(uiX, uiY);
|
||||
|
||||
if (Environment::tapDownHold && !uiManager.isUiInteraction()) {
|
||||
Environment::tapDownCurrentPos(0) = mx;
|
||||
Environment::tapDownCurrentPos(1) = my;
|
||||
if (isDraggingCamera && !uiManager.isUiInteraction()) {
|
||||
Environment::tapDownCurrentPos(0) = static_cast<float>(mx);
|
||||
Environment::tapDownCurrentPos(1) = static_cast<float>(my);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "render/Renderer.h"
|
||||
#include "Environment.h"
|
||||
#include "render/TextureManager.h"
|
||||
#include "render/Camera.h"
|
||||
#include "SparkEmitter.h"
|
||||
#include "planet/PlanetObject.h"
|
||||
#include "UiManager.h"
|
||||
@ -33,6 +34,7 @@ namespace ZL {
|
||||
bool shouldExit() const { return Environment::exitGameLoop; }
|
||||
|
||||
Renderer renderer;
|
||||
Camera camera;
|
||||
TaskManager taskManager;
|
||||
MainThreadHandler mainThreadHandler;
|
||||
|
||||
@ -95,6 +97,11 @@ namespace ZL {
|
||||
|
||||
bool isDraggingShip = false;
|
||||
bool isDraggingCamera = false;
|
||||
bool isUsingJoystick = false;
|
||||
|
||||
float camYaw = 0.0f;
|
||||
float camPitch = 0.0f;
|
||||
|
||||
Matrix3f rotateShipMat = Matrix3f::Identity(); // Локальный поворот от джойстика
|
||||
Matrix3f shipWorldOrientation = Matrix3f::Identity(); // Ориентация корабля в мире (независимо от камеры)
|
||||
bool shipMoveLockActive = false;
|
||||
|
||||
5
src/GameConfig.h
Normal file
5
src/GameConfig.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
// Feature flags to temporarily disable unstable features
|
||||
#define ENABLE_STONES 0
|
||||
#define ENABLE_REMOTE_SHIPS 0
|
||||
@ -1,4 +1,5 @@
|
||||
#include "PlanetObject.h"
|
||||
#include "GameConfig.h"
|
||||
#include "PlanetObject.h"
|
||||
#include <random>
|
||||
#include <cmath>
|
||||
#include "render/OpenGlExtensions.h"
|
||||
@ -73,7 +74,7 @@ namespace ZL {
|
||||
int lodIndex = planetData.getMaxLodIndex();
|
||||
planetRenderStruct.data = planetData.getLodLevel(lodIndex).vertexData;
|
||||
|
||||
//planetRenderStruct.data.PositionData.resize(9);
|
||||
|
||||
planetRenderStruct.RefreshVBO();
|
||||
|
||||
|
||||
@ -111,34 +112,30 @@ namespace ZL {
|
||||
// 2. Получаем список видимых треугольников
|
||||
auto newIndices = planetData.getTrianglesUnderCameraNew2(Environment::shipState.position);
|
||||
std::sort(newIndices.begin(), newIndices.end());
|
||||
// 3. Запуск генерации для новых индексов
|
||||
for (int idx : newIndices) {
|
||||
if (planetStones.statuses[idx] == ChunkStatus::Empty) {
|
||||
planetStones.statuses[idx] = ChunkStatus::Generating;
|
||||
|
||||
// 3. Анализируем, что нужно загрузить
|
||||
for (int triIdx : newIndices) {
|
||||
if (planetStones.statuses[triIdx] == ChunkStatus::Empty) {
|
||||
// Помечаем, чтобы не спамить задачами
|
||||
planetStones.statuses[triIdx] = ChunkStatus::Generating;
|
||||
// Запускаем задачу в фоне
|
||||
|
||||
// Отправляем тяжелую математику в TaskManager
|
||||
taskManager.EnqueueBackgroundTask([this, triIdx]() {
|
||||
// Выполняется в фоновом потоке: только генерация геометрии в RAM
|
||||
float scaleModifier = 1.0f;
|
||||
VertexDataStruct generatedData = planetStones.inflateOneDataOnly(triIdx, scaleModifier);
|
||||
taskManager.EnqueueBackgroundTask([this, idx]() {
|
||||
// Имитация тяжелой работы (генерация меша)
|
||||
// Тут мы просто копируем базовый камень + скейл/поворот
|
||||
VertexDataStruct newData = planetStones.inflateOneDataOnly(idx, 0.75f); // 0.75f - scaleModifier
|
||||
|
||||
// Передаем задачу на загрузку в GPU в очередь главного потока
|
||||
this->mainThreadHandler.EnqueueMainThreadTask([this, triIdx, data = std::move(generatedData)]() mutable {
|
||||
// Проверяем актуальность: если треугольник всё еще в списке видимых
|
||||
auto it = std::find(triangleIndicesToDraw.begin(), triangleIndicesToDraw.end(), triIdx);
|
||||
if (it != triangleIndicesToDraw.end()) {
|
||||
stonesToRender[triIdx].data = std::move(data);
|
||||
stonesToRender[triIdx].RefreshVBO(); // OpenGL вызов
|
||||
planetStones.statuses[triIdx] = ChunkStatus::Live;
|
||||
// Когда готово — перекидываем в главный поток для загрузки в GPU
|
||||
mainThreadHandler.EnqueueMainThreadTask([this, idx, data = std::move(newData)]() mutable {
|
||||
// Проверяем, всё ли еще актуален этот чанк (вдруг игрок улетел)
|
||||
// Но пока упростим: всегда грузим, а чистильщик (пункт 4) потом удалит если что
|
||||
if (planetStones.statuses[idx] == ChunkStatus::Generating) {
|
||||
stonesToRender[idx].data = std::move(data);
|
||||
stonesToRender[idx].RefreshVBO();
|
||||
planetStones.statuses[idx] = ChunkStatus::Live;
|
||||
}
|
||||
else {
|
||||
// Если уже не нужен — просто сбрасываем статус
|
||||
planetStones.statuses[triIdx] = ChunkStatus::Empty;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,8 +209,7 @@ namespace ZL {
|
||||
float centerX = (minX + maxX) * 0.5f;
|
||||
float centerY = (minY + maxY) * 0.5f;
|
||||
|
||||
//width = width * 0.995;
|
||||
//height = height * 0.995;
|
||||
|
||||
|
||||
renderer.PushProjectionMatrix(
|
||||
centerX - width*0.5, centerX + width * 0.5,
|
||||
@ -263,7 +259,7 @@ namespace ZL {
|
||||
{
|
||||
if (stoneMapFB == nullptr)
|
||||
{
|
||||
//stoneMapFB = std::make_unique<FrameBuffer>(512, 512, true);
|
||||
|
||||
stoneMapFB = std::make_unique<FrameBuffer>(512, 512);
|
||||
}
|
||||
stoneMapFB->Bind();
|
||||
@ -281,7 +277,9 @@ namespace ZL {
|
||||
|
||||
|
||||
drawPlanet(renderer);
|
||||
#if ENABLE_STONES
|
||||
drawStones(renderer);
|
||||
#endif
|
||||
drawAtmosphere(renderer);
|
||||
}
|
||||
|
||||
@ -429,15 +427,6 @@ namespace ZL {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
|
||||
|
||||
/*
|
||||
for (int i : triangleIndicesToDraw)
|
||||
//for (int i = 0; i < stonesToRender.size(); i++)
|
||||
{
|
||||
if (stonesToRender[i].data.PositionData.size() > 0)
|
||||
{
|
||||
renderer.DrawVertexRenderStruct(stonesToRender[i]);
|
||||
}
|
||||
}*/
|
||||
for (int i : triangleIndicesToDraw) {
|
||||
// КРИТИЧЕСКОЕ ИЗМЕНЕНИЕ:
|
||||
// Проверяем, что данные не просто существуют, а загружены в GPU
|
||||
|
||||
@ -110,18 +110,7 @@ namespace ZL {
|
||||
v(2) *= scaleFactors(2);
|
||||
}
|
||||
|
||||
/*
|
||||
// Случайный поворот (например, вокруг трех осей)
|
||||
Vector4f qx = Eigen::Quaternionf(Eigen::AngleAxisf(getRandomFloat(engine, 0.0f, 360.0f), Eigen::Vector3f::UnitX()));//QuatFromRotateAroundX(getRandomFloat(engine, 0.0f, 360.0f));
|
||||
Vector4f qy = Eigen::Quaternionf(Eigen::AngleAxisf(getRandomFloat(engine, 0.0f, 360.0f), Eigen::Vector3f::UnitY()));//QuatFromRotateAroundY(getRandomFloat(engine, 0.0f, 360.0f));
|
||||
Vector4f qz = Eigen::Quaternionf(Eigen::AngleAxisf(getRandomFloat(engine, 0.0f, 360.0f), Eigen::Vector3f::UnitZ()));//QuatFromRotateAroundZ(getRandomFloat(engine, 0.0f, 360.0f));
|
||||
Vector4f qFinal = slerp(qx, qy, 0.5f); // Простой пример комбинирования
|
||||
qFinal = slerp(qFinal, qz, 0.5f).normalized();
|
||||
Matrix3f rotationMatrix = QuatToMatrix(qFinal);
|
||||
|
||||
for (Vector3f& v : initialVertices) {
|
||||
v = MultMatrixVector(rotationMatrix, v);
|
||||
}*/
|
||||
|
||||
// 3. Сглаженные Нормали и Формирование Mesh
|
||||
VertexDataStruct result;
|
||||
@ -259,18 +248,7 @@ namespace ZL {
|
||||
getRandomFloat(engine, SCALE_MIN, SCALE_MAX)
|
||||
};
|
||||
|
||||
/*
|
||||
if (tIdx == 0)
|
||||
{
|
||||
instance.scale = instance.scale * 0.7f;
|
||||
}*/
|
||||
|
||||
/*
|
||||
Vector4f qx = QuatFromRotateAroundX(getRandomFloat(engine, 0.0f, 360.0f));
|
||||
Vector4f qy = QuatFromRotateAroundY(getRandomFloat(engine, 0.0f, 360.0f));
|
||||
Vector4f qz = QuatFromRotateAroundZ(getRandomFloat(engine, 0.0f, 360.0f));
|
||||
instance.rotation = slerp(slerp(qx, qy, 0.5f), qz, 0.5f).normalized();
|
||||
*/
|
||||
instance.rotation = Vector4f(0.f, 0.f, 0.f, 1.f);
|
||||
group.allInstances[tIdx].push_back(instance);
|
||||
}
|
||||
@ -291,9 +269,15 @@ namespace ZL {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Helper to get the singleton base stone data
|
||||
const VertexDataStruct& GetBaseStone() {
|
||||
static VertexDataStruct baseStone = CreateBaseConvexPolyhedron(1337);
|
||||
return baseStone;
|
||||
}
|
||||
|
||||
VertexRenderStruct StoneGroup::inflateOne(int index, float scaleModifier)
|
||||
{
|
||||
static VertexDataStruct baseStone = CreateBaseConvexPolyhedron(1337);
|
||||
const VertexDataStruct& baseStone = GetBaseStone();
|
||||
|
||||
VertexRenderStruct result;
|
||||
|
||||
@ -324,10 +308,11 @@ namespace ZL {
|
||||
|
||||
VertexDataStruct StoneGroup::inflateOneDataOnly(int index, float scaleModifier)
|
||||
{
|
||||
static VertexDataStruct baseStone = CreateBaseConvexPolyhedron(1337);
|
||||
const VertexDataStruct& baseStone = GetBaseStone();
|
||||
|
||||
VertexDataStruct result;
|
||||
|
||||
// Pre-reserve logic? Optional but good.
|
||||
// Since we don't know exact size (depends on stone count), maybe just standard push_back.
|
||||
|
||||
for (const auto& inst : allInstances[index]) {
|
||||
Matrix3f rotMat = inst.rotation.toRotationMatrix();
|
||||
@ -342,7 +327,13 @@ namespace ZL {
|
||||
|
||||
result.PositionData.push_back(rotMat * p + inst.position);
|
||||
result.NormalData.push_back(rotMat * n);
|
||||
result.TexCoordData.push_back(baseStone.TexCoordData[j]);
|
||||
|
||||
if (j < baseStone.TexCoordData.size()) {
|
||||
result.TexCoordData.push_back(baseStone.TexCoordData[j]);
|
||||
}
|
||||
else {
|
||||
result.TexCoordData.push_back({ 0.f, 0.f });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
57
src/render/Camera.cpp
Normal file
57
src/render/Camera.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include "render/Camera.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
using Eigen::Vector3f;
|
||||
using Eigen::Matrix3f;
|
||||
using Eigen::Matrix4f;
|
||||
|
||||
Camera::Camera()
|
||||
: position(Vector3f::Zero())
|
||||
, rotation(Matrix3f::Identity())
|
||||
{
|
||||
}
|
||||
|
||||
void Camera::follow(const Vector3f& targetPos, const Matrix3f& targetRot, float distance, float height)
|
||||
{
|
||||
Vector3f offset(0.0f, height, distance);
|
||||
Vector3f globalOffset = targetRot * offset;
|
||||
|
||||
position = targetPos + globalOffset;
|
||||
rotation = targetRot;
|
||||
}
|
||||
|
||||
void Camera::followOrbit(const Vector3f& targetPos, float yaw, float pitch, float distance, float height)
|
||||
{
|
||||
// Convert yaw/pitch to rotation matrix
|
||||
// Yaw (Y-axis), Pitch (X-axis)
|
||||
|
||||
Eigen::AngleAxisf yawRot(yaw, Vector3f::UnitY());
|
||||
Eigen::AngleAxisf pitchRot(pitch, Vector3f::UnitX());
|
||||
|
||||
// Combine rotations: Yaw * Pitch (order matters)
|
||||
Eigen::Quaternionf q = yawRot * pitchRot;
|
||||
rotation = q.toRotationMatrix();
|
||||
|
||||
Vector3f offset(0.0f, height, distance);
|
||||
Vector3f globalOffset = rotation * offset;
|
||||
|
||||
position = targetPos + globalOffset;
|
||||
}
|
||||
|
||||
Matrix4f Camera::getViewMatrix() const
|
||||
{
|
||||
// View Matrix = (Translate * Rotate)^-1
|
||||
// = Rotate^-1 * Translate^-1
|
||||
|
||||
Matrix3f R_inv = rotation.transpose();
|
||||
Vector3f T_inv = -position;
|
||||
|
||||
Matrix4f view = Matrix4f::Identity();
|
||||
|
||||
view.block<3,3>(0,0) = R_inv;
|
||||
view.block<3,1>(0,3) = R_inv * T_inv;
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
25
src/render/Camera.h
Normal file
25
src/render/Camera.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <Eigen/Dense>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
Camera();
|
||||
|
||||
// Обновление позиции камеры (например, слежение за кораблем)
|
||||
void follow(const Eigen::Vector3f& targetPos, const Eigen::Matrix3f& targetRot, float distance, float height);
|
||||
|
||||
// Follow target with orbital rotation (yaw/pitch) independent of target rotation
|
||||
void followOrbit(const Eigen::Vector3f& targetPos, float yaw, float pitch, float distance, float height);
|
||||
|
||||
// Получить матрицу вида (View Matrix) для шейдера
|
||||
Eigen::Matrix4f getViewMatrix() const;
|
||||
|
||||
Eigen::Vector3f getPosition() const { return position; }
|
||||
|
||||
private:
|
||||
Eigen::Vector3f position;
|
||||
Eigen::Matrix3f rotation; // Ориентация камеры
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user