109 lines
3.2 KiB
C++
109 lines
3.2 KiB
C++
// Copyright (c) 2022 Dominic Masters
|
|
//
|
|
// This software is released under the MIT License.
|
|
// https://opensource.org/licenses/MIT
|
|
|
|
#include "Camera.hpp"
|
|
#include "game/DawnGame.hpp"
|
|
|
|
using namespace Dawn;
|
|
|
|
Camera::Camera(SceneItem *item) :
|
|
SceneItemComponent(item),
|
|
renderTarget(item->scene->game->renderManager.getBackBuffer()),
|
|
fov(0.785398f),// 45 degrees,
|
|
type(CAMERA_TYPE_PERSPECTIVE),
|
|
orthoLeft(0.0f),
|
|
orthoRight(1.0f),
|
|
orthoBottom(0.0f),
|
|
orthoTop(1.0f),
|
|
clipNear(0.001f),
|
|
clipFar(1000.0f)
|
|
{
|
|
}
|
|
|
|
glm::mat4 Camera::getProjection() {
|
|
if(this->projectionNeedsUpdating) {
|
|
switch(this->type) {
|
|
case CAMERA_TYPE_ORTHONOGRAPHIC:
|
|
this->projection = 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
|
|
);
|
|
break;
|
|
|
|
case CAMERA_TYPE_PERSPECTIVE:
|
|
this->projection = glm::perspective(
|
|
(float_t)this->fov,
|
|
this->getAspect(),
|
|
(float_t)this->clipNear,
|
|
(float_t)this->clipFar
|
|
);
|
|
break;
|
|
}
|
|
this->projectionNeedsUpdating = false;
|
|
}
|
|
|
|
return this->projection;
|
|
}
|
|
|
|
RenderTarget * Camera::getRenderTarget() {
|
|
return (RenderTarget*)this->renderTarget;
|
|
}
|
|
|
|
float_t Camera::getAspect() {
|
|
auto target = this->getRenderTarget();
|
|
return target->getWidth() / target->getHeight();
|
|
}
|
|
|
|
glm::vec3 Camera::getRayDirectionFromScreenSpace(glm::vec2 screenSpace) {
|
|
glm::vec4 clipCoords(screenSpace.x, -screenSpace.y, -1.0f, 1.0f);
|
|
glm::mat4 inverseProjectionMatrix = glm::inverse(this->projection);
|
|
glm::vec4 eyeCoords = inverseProjectionMatrix * clipCoords;
|
|
eyeCoords = glm::vec4(eyeCoords.x, eyeCoords.y, -1.0f, 0.0f);
|
|
|
|
glm::mat4 inverseViewMatrix = glm::inverse(transform->getWorldTransform());
|
|
glm::vec4 t = inverseViewMatrix * eyeCoords;
|
|
|
|
return glm::normalize(glm::vec3(t.x, t.y, t.z));
|
|
}
|
|
|
|
void Camera::onStart() {
|
|
useEffectWithTeardown([&]{
|
|
auto rt = this->getRenderTarget();
|
|
this->projectionNeedsUpdating = true;
|
|
if(rt == nullptr) {
|
|
return evtResized = [&]{
|
|
|
|
};
|
|
}
|
|
this->eventRenderTargetResized.invoke(rt->getWidth(), rt->getHeight());
|
|
|
|
// Subscribe to new render target resized.
|
|
return evtResized = useEventLegacy([&](RenderTarget *rt, float_t w, float_t h){
|
|
this->projectionNeedsUpdating = true;
|
|
this->eventRenderTargetResized.invoke(w, h);
|
|
}, rt->eventRenderTargetResized);
|
|
}, renderTarget);
|
|
|
|
// All regular properties.
|
|
useEffect([&]{
|
|
this->projectionNeedsUpdating = true;
|
|
}, {
|
|
&fov, &type,
|
|
&orthoLeft, &orthoRight, &orthoBottom, &orthoTop,
|
|
&clipNear, &clipFar
|
|
});
|
|
|
|
// Sub to evt legacy, we don't invoke the useTeardown to avoid invoking
|
|
// the state event for this camera when we don't need to.
|
|
if(!this->getRenderTarget()) return;
|
|
evtResized = useEventLegacy([&](RenderTarget *rt, float_t w, float_t h){
|
|
this->projectionNeedsUpdating = true;
|
|
this->eventRenderTargetResized.invoke(w, h);
|
|
}, getRenderTarget()->eventRenderTargetResized);
|
|
} |