1#include <Core/Asset/Camera.hpp>
2#include <Core/Math/Math.hpp>
3#include <Engine/Scene/CameraComponent.hpp>
5#include <catch2/catch_test_macros.hpp>
8using namespace Ra::Core::Utils;
9using namespace Ra::Core::Asset;
11void testProjectUnproject(
const Camera& cam,
const Vector3& x,
const Vector2& ref ) {
12 std::cout <<
"x" << x.transpose() <<
" ref " <<
ref.transpose() <<
"\n";
14 std::cout <<
"p " << p.transpose() <<
"\n";
15 if (
ref.head<2>().norm() > 0_ra )
16 REQUIRE( p.head<2>().isApprox( ref ) );
21 std::cout <<
"q " << q.transpose() <<
"\n";
22 if ( x.norm() > 0_ra )
23 REQUIRE( q.isApprox( x ) );
28 std::cout <<
"r " << r.transpose() <<
"\n";
31 std::cout <<
"rref " << rRef.transpose() <<
"\n";
36 std::cout <<
"rref " << rRef.transpose() <<
"\n";
37 if ( rRef.norm() > 0_ra )
38 REQUIRE( r.isApprox( rRef ) );
43TEST_CASE(
"Core/Camera",
"[unittests]" ) {
45 auto cam = std::make_unique<Camera>( 10, 20 );
52 Vector3 dir { 1, 1, 1 };
53 Vector3 pos { 0, 0, 0 };
57 REQUIRE( dir.normalized().isApprox( cam->
getDirection() ) );
70 REQUIRE( dir.normalized().isApprox( cam2.
getDirection() ) );
80 SECTION(
"setters" ) {
81 Ra::Core::Vector3 newDir { 2, 3, 4 };
83 REQUIRE( newDir.normalized().isApprox( cam->
getDirection() ) );
89 Ra::Core::Vector3 newPos { 2, 3, 4 };
97 Ra::Core::Vector3 newUp { 2, 3, 4 };
99 REQUIRE( newUp.normalized().isApprox( cam->
getUpVector() ) );
110 REQUIRE( oppositeDir.normalized().isApprox( cam->
getDirection() ) );
122 REQUIRE( cam->
getType() == Camera::ProjType::PERSPECTIVE );
123 cam->
setType( Camera::ProjType::ORTHOGRAPHIC );
124 REQUIRE( cam->
getType() == Camera::ProjType::ORTHOGRAPHIC );
127 Ra::Core::Matrix4
ref;
128 ref << 1_ra, 0_ra, 0_ra, 0_ra, 0_ra, 0.5_ra, 0_ra, 0_ra, 0_ra, 0_ra, -2_ra / 90_ra,
129 -110_ra / 90_ra, 0_ra, 0_ra, 0_ra, 1_ra;
133 cam->
setFrame( Transform::Identity() );
134 REQUIRE( cam->
getFrame().isApprox( Transform::Identity() ) );
135 REQUIRE( cam->getViewMatrix().isApprox( Matrix4::Identity() ) );
139 REQUIRE( cam->
getProjMatrix().isApprox( Matrix4::Identity() ) );
142 cam->
setFOV( Math::PiDiv2 );
144 cam->
setFOV( Math::PiDiv4 );
148 cam->
setXYmag( 1.414_ra, 1.732_ra );
158 SECTION(
"fit aabb" ) {
159 Ra::Core::Aabb aabb { Ra::Core::Vector3 { 3, 3, 3 }, Ra::Core::Vector3 { 6, 6, 6 } };
163 cam->
getZNear() == cam->m_minZNear ) );
166 REQUIRE( ( cam->
getZNear() > cam->m_minZNear ||
172 aabb = { Ra::Core::Vector3 { -1, -1, -1 }, Ra::Core::Vector3 { 1, 1, 1 } };
178 REQUIRE( ( cam->
getZNear() > cam->m_minZNear ||
184 aabb = { Ra::Core::Vector3 { -2, -1, 1 }, Ra::Core::Vector3 { -4, -1, 0 } };
189 aabb = { Ra::Core::Vector3 { 0, -3, 0 }, Ra::Core::Vector3 { 1, -2, 1 } };
195 SECTION(
"projection" ) {
198 auto fov = Math::Pi / 4_ra;
202 auto frustum =
Camera::frustum( -scale, +scale, -scale / aspect, +scale / aspect, n, f );
203 REQUIRE( frustum.allFinite() );
205 REQUIRE( perspective.allFinite() );
207 REQUIRE( frustum.isApprox( perspective ) );
209 Camera projection { 10_ra, 20_ra };
211 projection.setZNear( 1_ra );
212 projection.setZFar( 10_ra );
213 projection.setPosition( { 0_ra, 0_ra, 2_ra } );
214 projection.setDirection( { 0_ra, 0_ra, -1_ra } );
215 projection.updateProjMatrix();
217 Vector3 x { 0_ra, 0_ra, 0_ra };
219 testProjectUnproject( projection, x, Vector2 { 5_ra, 10_ra } );
220 x = { 0_ra, 0_ra, -3_ra };
221 testProjectUnproject( projection, x, Vector2 { 5_ra, 10_ra } );
222 x = { -
std::tan( Math::Pi / 8_ra ), 2_ra *
std::tan( Math::Pi / 8_ra ), 1_ra };
223 testProjectUnproject( projection, x, Vector2 { 0_ra, 0_ra } );
224 x = { +
std::tan( Math::Pi / 8_ra ), -2_ra *
std::tan( Math::Pi / 8_ra ), 1_ra };
225 testProjectUnproject( projection, x, Vector2 { 10_ra, 20_ra } );
Camera class storing the Camera frame and the projection properties The view direction is -z in camer...
void setViewport(Scalar width, Scalar height)
Change the viewport size. Also compute aspectRatio.
Scalar getZFar() const
Return the Z Far plane distance from the camera.
void updateProjMatrix()
Update the projection matrix according to the current parameters.
static Core::Matrix4 frustum(Scalar l, Scalar r, Scalar b, Scalar t, Scalar n, Scalar f)
Build a projection matrix from the parameters of the view volume.
Scalar getWidth() const
Return the width of the viewport.
void setPosition(const Core::Vector3 &position)
Set the position of the camera to position.
static Core::Matrix4 perspective(Scalar a, Scalar y, Scalar n, Scalar f)
Scalar getHeight() const
Return the height of the viewport.
Core::Vector3 unProjectFromScreen(const Core::Vector2 &pix) const
void setDirection(const Core::Vector3 &direction)
void setZNear(Scalar zNear)
Set the Z Near plane distance to zNear.
void setZFar(Scalar zFar)
Set the Z Far plane distance to zFar.
Core::Vector3 getPosition() const
Return the position.
void setZoomFactor(const Scalar &zoomFactor)
Set the zoom factor to zoomFactor.
Core::Vector3 getUpVector() const
Return the up vector.
Scalar getZNear() const
Return the Z Near plane distance from the camera.
void setProjMatrix(Core::Matrix4 projMatrix)
void setUpVector(const Core::Vector3 &upVector)
Core::Matrix4 getProjMatrix() const
Return the projection matrix.
void fitZRange(const Core::Aabb &aabb)
Fit the Z-range of the camera to the scene's aabb. This will maximize z-buffer precision.
void setType(const ProjType &projectionType)
Set the projection type to projectionType.
Scalar getZoomFactor() const
Return the zoom factor.
Core::Vector3 projectToScreen(const Core::Vector3 &p) const
Return the screen coordinates + depth of the given point p (in world coordinates).
void setFrame(const Core::Transform &frame)
Set the frame of the camera to frame.
ProjType getType() const
Return the projection type.
Scalar getAspect() const
Return the aspect ratio of the viewport.
Core::Transform getFrame() const
void setXYmag(Scalar xmag, Scalar ymag)
Set xmag and ymag for orthographic camera.
Core::Vector3 getDirection() const
Return the direction the camera is looking at.
std::pair< Scalar, Scalar > getXYmag() const
Get xmag and ymag for orthographic camera.
std::enable_if<!std::numeric_limits< T >::is_integer, bool >::type areApproxEqual(T x, T y, T espilonBoostFactor=T(10))
Compare two numbers such that |x-y| < espilon*epsilonBoostFactor.
Quaternion scale(const Quaternion &q, const Scalar k)
Returns the quaternion q multipled by a scalar factor of k.
This namespace contains everything "low level", related to data, datastuctures, and computation.