1
0
forked from 0ad/0ad

Fixes big screenshots, implements CCamera::GetViewQuad properly for custom projections.

Differential Revision: https://code.wildfiregames.com/D4165
This was SVN commit r25794.
This commit is contained in:
Vladislav Belov 2021-06-13 17:42:37 +00:00
parent 08400276e1
commit 6b493aa52c
2 changed files with 64 additions and 1 deletions

View File

@ -28,6 +28,7 @@
#include "graphics/Terrain.h"
#include "lib/ogl.h"
#include "maths/MathUtil.h"
#include "maths/Vector2D.h"
#include "maths/Vector4D.h"
#include "ps/Game.h"
#include "ps/World.h"
@ -166,7 +167,29 @@ float CCamera::GetAspectRatio() const
void CCamera::GetViewQuad(float dist, Quad& quad) const
{
ENSURE(m_ProjType == ProjectionType::PERSPECTIVE || m_ProjType == ProjectionType::ORTHO);
if (m_ProjType == ProjectionType::CUSTOM)
{
const CMatrix3D invProjection = m_ProjMat.GetInverse();
const std::array<CVector2D, 4> ndcCorners = {
CVector2D{-1.0f, -1.0f}, CVector2D{1.0f, -1.0f},
CVector2D{1.0f, 1.0f}, CVector2D{-1.0f, 1.0f}};
for (size_t idx = 0; idx < 4; ++idx)
{
const CVector2D& corner = ndcCorners[idx];
CVector4D nearCorner =
invProjection.Transform(CVector4D(corner.X, corner.Y, -1.0f, 1.0f));
nearCorner /= nearCorner.W;
CVector4D farCorner =
invProjection.Transform(CVector4D(corner.X, corner.Y, 1.0f, 1.0f));
farCorner /= farCorner.W;
const float t = (dist - nearCorner.Z) / (farCorner.Z - nearCorner.Z);
const CVector4D quadCorner = nearCorner * (1.0 - t) + farCorner * t;
quad[idx].X = quadCorner.X;
quad[idx].Y = quadCorner.Y;
quad[idx].Z = quadCorner.Z;
}
return;
}
const float y = m_ProjType == ProjectionType::PERSPECTIVE ? dist * tanf(m_FOV * 0.5f) : m_OrthoScale * 0.5f;
const float x = y * GetAspectRatio();

View File

@ -284,6 +284,46 @@ public:
CompareQuadsInWorldSpace(camera, farQuad, expectedWorldSpaceFarQuad);
}
void test_custom_plane_points()
{
SViewPort viewPort;
viewPort.m_X = 0;
viewPort.m_Y = 0;
viewPort.m_Width = 512;
viewPort.m_Height = 512;
CCamera camera;
camera.SetViewPort(viewPort);
camera.LookAt(
CVector3D(10.0f, 20.0f, 10.0f),
CVector3D(10.0f, 10.0f, 20.0f),
CVector3D(0.0f, 1.0f, 1.0f).Normalized()
);
CCamera cameraPerspective = camera;
cameraPerspective.SetPerspectiveProjection(1.0f, 101.0f, DEGTORAD(90.0f));
CMatrix3D projection;
projection.SetPerspective(
cameraPerspective.GetFOV(), cameraPerspective.GetAspectRatio(),
cameraPerspective.GetNearPlane(), cameraPerspective.GetFarPlane());
camera.SetProjection(projection);
const std::vector<float> distances = {
cameraPerspective.GetNearPlane(),
(cameraPerspective.GetNearPlane() + cameraPerspective.GetFarPlane()) / 2.0f,
cameraPerspective.GetFarPlane()
};
CCamera::Quad quad, expectedQuad;
for (const float distance : distances)
{
camera.GetViewQuad(distance, quad);
cameraPerspective.GetViewQuad(distance, expectedQuad);
CompareQuads(quad, expectedQuad);
}
}
void test_perspective_screen_rays()
{
const float EPS = 1e-4f;