mirror of
https://github.com/whoahq/whoa.git
synced 2026-03-18 05:31:07 +03:00
189 lines
4.7 KiB
C++
189 lines
4.7 KiB
C++
#include "ui/game/CGCamera.hpp"
|
|
#include "common/Time.hpp"
|
|
#include "console/CVar.hpp"
|
|
#include "object/Client.hpp"
|
|
#include "object/client/CVehicleCamera_C.hpp"
|
|
#include "ui/game/Types.hpp"
|
|
#include "world/World.hpp"
|
|
#include <algorithm>
|
|
#include <storm/String.hpp>
|
|
#include <tempest/Math.hpp>
|
|
|
|
static CVar* s_cameraView;
|
|
|
|
CGCamera::CameraViewData CGCamera::s_cameraViewDataDefault[MAX_CAMERA_VIEWS] = {
|
|
{ "0.0", "0.0", "0.0" }, // VIEW_FIRST_PERSON
|
|
{ "0.0", "0.0", "0.0" }, // VIEW_THIRD_PERSON_A
|
|
{ "5.55", "10.0", "0.0" }, // VIEW_THIRD_PERSON_B
|
|
{ "5.55", "20.0", "0.0" }, // VIEW_THIRD_PERSON_C
|
|
{ "13.88", "30.0", "0.0" }, // VIEW_THIRD_PERSON_D
|
|
{ "13.88", "10.0", "0.0" }, // VIEW_THIRD_PERSON_E
|
|
{ "0.0", "0.0", "0.0" }, // VIEW_COMMENTATOR
|
|
{ "5.0", "10.0", "0.0" }, // VIEW_BARBER_SHOP
|
|
};
|
|
|
|
namespace {
|
|
|
|
bool ValidateCameraView(CVar* var, const char* oldValue, const char* value, void* arg) {
|
|
auto view = SStrToFloat(value);
|
|
auto min = static_cast<float>(VIEW_FIRST_PERSON);
|
|
auto max = static_cast<float>(VIEW_BARBER_SHOP);
|
|
|
|
if (view >= min && view <= max) {
|
|
return true;
|
|
}
|
|
|
|
// TODO ConsoleWriteA("Value out of range (%f - %f)\n", DEFAULT_COLOR, min, max);
|
|
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
int32_t CGCamera::UpdateCallback(const void*, void* param) {
|
|
auto camera = static_cast<CGCamera*>(param);
|
|
|
|
if (!camera) {
|
|
return true;
|
|
}
|
|
|
|
auto timestamp = OsGetAsyncTimeMsPrecise();
|
|
|
|
camera->m_nearZ = CWorld::GetNearClip();
|
|
camera->m_farZ = CWorld::GetFarClip();
|
|
|
|
// Model camera
|
|
|
|
if (camera->HasModel()) {
|
|
camera->CalcModelCamera(timestamp);
|
|
camera->CheckUnderwater();
|
|
|
|
return true;
|
|
}
|
|
|
|
// Target camera
|
|
|
|
auto target = ClntObjMgrObjectPtr(camera->m_target, TYPE_OBJECT, __FILE__, __LINE__);
|
|
|
|
if (target) {
|
|
camera->CalcTargetCamera(target, timestamp);
|
|
camera->CheckUnderwater();
|
|
|
|
return true;
|
|
}
|
|
|
|
// Unknown camera
|
|
|
|
auto object90 = ClntObjMgrObjectPtr(camera->guid90, TYPE_OBJECT, __FILE__, __LINE__);
|
|
|
|
if (object90) {
|
|
// TODO
|
|
|
|
return true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
CGCamera::CGCamera() : CSimpleCamera(CWorld::GetNearClip(), CWorld::GetFarClip(), 90.0f * CMath::DEG2RAD) {
|
|
this->m_model = nullptr;
|
|
|
|
this->m_target = 0;
|
|
this->guid90 = 0;
|
|
this->m_relativeTo = 0;
|
|
|
|
this->m_view = s_cameraView->GetInt();
|
|
|
|
this->m_distance = SStrToFloat(CGCamera::s_cameraViewDataDefault[this->m_view].m_distance);
|
|
this->m_yaw = 0.0f;
|
|
this->m_pitch = SStrToFloat(CGCamera::s_cameraViewDataDefault[this->m_view].m_pitch);
|
|
this->m_roll = 0.0f;
|
|
|
|
this->m_fovOffset = 0.0f;
|
|
}
|
|
|
|
void CGCamera::CalcModelCamera(uint32_t timestamp) {
|
|
// TODO
|
|
}
|
|
|
|
void CGCamera::CalcTargetCamera(CGObject_C* target, uint32_t timestamp) {
|
|
// TODO
|
|
}
|
|
|
|
void CGCamera::CheckUnderwater() {
|
|
// TODO
|
|
}
|
|
|
|
float CGCamera::FOV() const {
|
|
// Clamp offset-adjusted FOV between 0pi and 1pi
|
|
return std::min(std::max(this->m_fov + this->m_fovOffset, 0.0f), CMath::PI);
|
|
}
|
|
|
|
C3Vector CGCamera::Forward() const {
|
|
if (this->m_relativeTo) {
|
|
return this->CSimpleCamera::Forward() * this->ParentToWorld();
|
|
}
|
|
|
|
return this->CSimpleCamera::Forward();
|
|
}
|
|
|
|
const WOWGUID& CGCamera::GetTarget() const {
|
|
return this->m_target;
|
|
}
|
|
|
|
int32_t CGCamera::HasModel() const {
|
|
return this->m_model != nullptr;
|
|
}
|
|
|
|
C33Matrix CGCamera::ParentToWorld() const {
|
|
auto relativeTo = ClntObjMgrObjectPtr(this->m_relativeTo, TYPE_OBJECT, __FILE__, __LINE__);
|
|
|
|
if (!relativeTo) {
|
|
return {};
|
|
}
|
|
|
|
float facing;
|
|
|
|
if (relativeTo->IsA(TYPE_UNIT)) {
|
|
facing = static_cast<CGUnit_C*>(relativeTo)->GetRawSmoothFacing();
|
|
auto transport = ClntObjMgrObjectPtr(relativeTo->GetTransportGUID(), TYPE_OBJECT, __FILE__, __LINE__);
|
|
CVehicleCamera_C::ConvertSmoothFacingFromRawToWorld(facing, transport);
|
|
} else {
|
|
facing = relativeTo->GetFacing();
|
|
}
|
|
|
|
return C33Matrix::RotationAroundZ(facing);
|
|
}
|
|
|
|
C3Vector CGCamera::Right() const {
|
|
if (this->m_relativeTo) {
|
|
return this->CSimpleCamera::Right() * this->ParentToWorld();
|
|
}
|
|
|
|
return this->CSimpleCamera::Right();
|
|
}
|
|
|
|
void CGCamera::SetupWorldProjection(const CRect& projRect) {
|
|
this->SetGxProjectionAndView(projRect);
|
|
}
|
|
|
|
C3Vector CGCamera::Target() const {
|
|
return this->m_position + this->Forward();
|
|
}
|
|
|
|
C3Vector CGCamera::Up() const {
|
|
if (this->m_relativeTo) {
|
|
return this->CSimpleCamera::Up() * this->ParentToWorld();
|
|
}
|
|
|
|
return this->CSimpleCamera::Up();
|
|
}
|
|
|
|
void CameraRegisterCVars() {
|
|
// TODO
|
|
|
|
s_cameraView = CVar::Register("cameraView", nullptr, 0x10, "2", &ValidateCameraView, DEFAULT);
|
|
|
|
// TODO
|
|
}
|