psemek/libs/geom/source/camera.cpp

107 lines
2.6 KiB
C++

#include <psemek/geom/camera.hpp>
#include <psemek/geom/gauss.hpp>
#include <psemek/geom/orthographic.hpp>
#include <psemek/geom/perspective.hpp>
#include <psemek/geom/translation.hpp>
#include <psemek/geom/rotation.hpp>
#include <psemek/geom/homogeneous.hpp>
#include <cmath>
namespace psemek::geom
{
matrix<float, 4, 4> camera::transform() const
{
return projection() * view();
}
point<float, 3> camera::position() const
{
vector<float, 4> b{ 0.f, 0.f, 0.f, 1.f };
gauss(view(), b);
return { b[0], b[1], b[2] };
}
vector<float, 3> camera::axis_x() const
{
vector<float, 4> b{ 1.f, 0.f, 0.f, 0.f };
gauss(view(), b);
return { b[0], b[1], b[2] };
}
vector<float, 3> camera::axis_y() const
{
vector<float, 4> b{ 0.f, 1.f, 0.f, 0.f };
gauss(view(), b);
return { b[0], b[1], b[2] };
}
vector<float, 3> camera::axis_z() const
{
vector<float, 4> b{ 0.f, 0.f, 1.f, 0.f };
gauss(view(), b);
return { b[0], b[1], b[2] };
}
vector<float, 3> camera::direction(float x, float y) const
{
vector<float, 4> b{ x, y, -1.f, 1.f};
gauss(transform(), b);
point<float, 3> p{ b[0] / b[3], b[1] / b[3], b[2] / b[3] };
return p - position();
}
std::array<vector<float, 4>, 6> camera::clip_planes() const
{
auto const m = transpose(transform());
std::array<vector<float, 4>, 6> p;
p[0] = m * vector{1.f, 0.f, 0.f, 1.f};
p[1] = m * vector{-1.f, 0.f, 0.f, 1.f};
p[2] = m * vector{0.f, 1.f, 0.f, 1.f};
p[3] = m * vector{0.f, -1.f, 0.f, 1.f};
p[4] = m * vector{0.f, 0.f, 1.f, 1.f};
p[5] = m * vector{0.f, 0.f, -1.f, 1.f};
return p;
}
matrix<float, 4, 4> window_camera::view() const
{
return matrix<float, 4, 4>::identity();
}
matrix<float, 4, 4> window_camera::projection() const
{
return orthographic<float, 3>({{ {0.f, width}, {height, 0.f}, {-1.f, 1.f} }}).homogeneous_matrix();
}
matrix<float, 4, 4> orthographic_camera::view() const
{
return matrix<float, 4, 4>::identity();
}
matrix<float, 4, 4> orthographic_camera::projection() const
{
return orthographic<float, 3>(box).homogeneous_matrix();
}
matrix<float, 4, 4> perspective_camera::projection() const
{
return perspective<float, 3>(fov_x, fov_y, near_clip, far_clip).homogeneous_matrix();
}
matrix<float, 4, 4> spherical_camera::view() const
{
return
translation<float, 3>({0.f, 0.f, -distance}).homogeneous_matrix()
* homogeneous(plane_rotation<float, 3>(1, 2, elevation_angle).matrix())
* homogeneous(plane_rotation<float, 3>(2, 0, azimuthal_angle).matrix())
* translation<float, 3>({ -target[0], -target[1], -target[2] }).homogeneous_matrix()
;
}
}