psemek/libs/geom/source/camera.cpp
2020-09-23 21:56:25 +03:00

122 lines
3 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/permutation.hpp>
#include <psemek/geom/scale.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() const
{
return -axis_z();
}
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();
}
void perspective_camera::set_fov(float fov_y, float aspect_ratio)
{
this->fov_y = fov_y;
fov_x = 2.f * std::atan(aspect_ratio * std::tan(fov_y / 2.f));
}
matrix<float, 4, 4> spherical_camera::view() const
{
return
translation<float, 3>({0.f, 0.f, -distance}).homogeneous_matrix()
* homogeneous(swap<float, 3>(1, 2).matrix())
* homogeneous(scale<float, 3>({1.f, -1.f, 1.f}).matrix())
* homogeneous(plane_rotation<float, 3>(1, 2, elevation_angle).matrix())
* homogeneous(plane_rotation<float, 3>(1, 0, azimuthal_angle).matrix())
* translation<float, 3>({ -target[0], -target[1], -target[2] }).homogeneous_matrix()
;
}
}