2024-12-02 14:53:41 -06:00

143 lines
3.9 KiB
C++

// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "assert/assert.hpp"
#include "Camera.hpp"
#include "game/Game.hpp"
using namespace Dawn;
void Camera::onInit() {
this->onResizeListener = this->getRenderTarget()->onResize.listen([&](
float_t width, float_t height
) {
this->onResize.emit(this->getRenderTarget(), width, height);
});
}
void Camera::onDispose() {
renderTarget = nullptr;
}
void Camera::load(const SceneComponentLoadContext &ctx) {
SceneComponent::load(ctx);
if(ctx.data.contains("fov")) {
this->fov = Math::deg2rad(ctx.data["fov"].get<float_t>());
}
if(ctx.data.contains("cameraType")) {
if(
ctx.data["cameraType"] == "orthogonal" ||
ctx.data["cameraType"] == "orthographic" ||
ctx.data["cameraType"] == "ortho"
) {
this->type = CameraType::ORTHOGONAL;
} else if(ctx.data["cameraType"] == "perspective") {
this->type = CameraType::PERSPECTIVE;
} else {
assertUnreachable("Invalid Camera Type!");
}
}
if(ctx.data.contains("orthoLeft")) {
this->orthoLeft = ctx.data["orthoLeft"].get<float_t>();
} else if(ctx.data.contains("left")) {
this->orthoLeft = ctx.data["left"].get<float_t>();
}
if(ctx.data.contains("orthoRight")) {
this->orthoRight = ctx.data["orthoRight"].get<float_t>();
} else if(ctx.data.contains("right")) {
this->orthoRight = ctx.data["right"].get<float_t>();
}
if(ctx.data.contains("orthoBottom")) {
this->orthoBottom = ctx.data["orthoBottom"].get<float_t>();
} else if(ctx.data.contains("bottom")) {
this->orthoBottom = ctx.data["bottom"].get<float_t>();
}
if(ctx.data.contains("orthoTop")) {
this->orthoTop = ctx.data["orthoTop"].get<float_t>();
} else if(ctx.data.contains("top")) {
this->orthoTop = ctx.data["top"].get<float_t>();
}
if(ctx.data.contains("clipNear")) {
this->clipNear = ctx.data["clipNear"].get<float_t>();
} else if(ctx.data.contains("near")) {
this->clipNear = ctx.data["near"].get<float_t>();
} else if(ctx.data.contains("zNear")) {
this->clipNear = ctx.data["zNear"].get<float_t>();
}
if(ctx.data.contains("clipFar")) {
this->clipFar = ctx.data["clipFar"].get<float_t>();
} else if(ctx.data.contains("far")) {
this->clipFar = ctx.data["far"].get<float_t>();
} else if(ctx.data.contains("zFar")) {
this->clipFar = ctx.data["zFar"].get<float_t>();
}
}
std::shared_ptr<RenderTarget> Camera::getRenderTarget() {
if(this->renderTarget) return this->renderTarget;
return getGame()->renderHost->getBackBufferRenderTarget();
}
glm::mat4 Camera::getProjection() {
switch(this->type) {
case CameraType::ORTHOGONAL:
return glm::ortho(
(float_t)this->orthoLeft,
(float_t)this->orthoRight,
(float_t)this->orthoBottom,
(float_t)this->orthoTop,
(float_t)this->clipNear,
(float_t)this->clipFar
);
case CameraType::PERSPECTIVE:
return glm::perspective(
(float_t)this->fov,
this->getAspect(),
(float_t)this->clipNear,
(float_t)this->clipFar
);
}
assertUnreachable("Invalid Camera Type!");
return glm::mat4(1.0f);
}
float_t Camera::getAspect() {
auto rt = this->getRenderTarget();
return rt->getWidth() / rt->getHeight();
}
float_t Camera::lookAtPixelPerfect(
const glm::vec3 &position,
const glm::vec3 &look,
const float_t &scale
) {
return this->getItem()->lookAtPixelPerfect(
position,
look,
this->getRenderTarget()->getHeight(),
this->fov,
scale
);
}
void Camera::setRenderTarget(std::shared_ptr<RenderTarget> renderTarget) {
onResizeListener();
this->renderTarget = renderTarget;
this->onResizeListener = this->getRenderTarget()->onResize.listen([&](
float_t width, float_t height
) {
this->onResize.emit(this->getRenderTarget(), width, height);
});
}