Change free camera: any possible orientation now

This commit is contained in:
Nikita Lisitsa 2020-11-08 16:18:34 +03:00
parent 957493e2e2
commit c89deef9cf
3 changed files with 47 additions and 24 deletions

View file

@ -205,8 +205,7 @@ struct grass_app
camera.near_clip = 0.1f; camera.near_clip = 0.1f;
camera.far_clip = 1000.f; camera.far_clip = 1000.f;
camera.pos = {0.5f, 0.5f, 1.5f}; camera.pos = {0.5f, 0.5f, 1.5f};
camera.elevation_angle = geom::rad(15.f); camera.rotateYZ(geom::rad(-90.f));
camera.azimuthal_angle = geom::rad(-90.f);
init_ground(); init_ground();
init_grass(); init_grass();
@ -474,8 +473,8 @@ struct grass_app
if (is_middle_button_down()) if (is_middle_button_down())
{ {
camera.azimuthal_angle -= dx * 0.01f; camera.rotateZX(0.01f * dx);
camera.elevation_angle += dy * 0.01f; camera.rotateYZ(0.01f * dy);
} }
} }

View file

@ -128,22 +128,28 @@ namespace psemek::geom
struct free_camera struct free_camera
: perspective_camera : perspective_camera
{ {
// assumes up is +Z
// azimuthal angle is in XY plane
// both angles zero gives X right, Y forward, and Z up
float azimuthal_angle;
float elevation_angle;
point<float, 3> pos; point<float, 3> pos;
vector<float, 3> axes[3];
free_camera() = default; free_camera()
{
axes[0] = {1.f, 0.f, 0.f};
axes[1] = {0.f, 1.f, 0.f};
axes[2] = {0.f, 0.f, 1.f};
}
free_camera(float fov_x, float fov_y, float near_clip, float far_clip, float azimuthal_angle, float elevation_angle, point<float, 3> const & pos) free_camera(float fov_x, float fov_y, float near_clip, float far_clip, point<float, 3> const & pos)
: perspective_camera(fov_x, fov_y, near_clip, far_clip) : perspective_camera(fov_x, fov_y, near_clip, far_clip)
, azimuthal_angle{azimuthal_angle}
, elevation_angle{elevation_angle}
, pos{pos} , pos{pos}
{} {
axes[0] = {1.f, 0.f, 0.f};
axes[1] = {0.f, 1.f, 0.f};
axes[2] = {0.f, 0.f, 1.f};
}
void rotateXY(float angle);
void rotateYZ(float angle);
void rotateZX(float angle);
matrix<float, 4, 4> view() const override; matrix<float, 4, 4> view() const override;
}; };

View file

@ -120,17 +120,35 @@ namespace psemek::geom
return tr.homogeneous_matrix(); return tr.homogeneous_matrix();
} }
static void rotate(geom::vector<float, 3> & a, geom::vector<float, 3> & b, float angle)
{
auto s = std::sin(angle);
auto c = std::cos(angle);
auto aa = a * c - b * s;
auto bb = a * s + b * c;
a = aa;
b = bb;
}
void free_camera::rotateXY(float angle)
{
rotate(axes[0], axes[1], angle);
}
void free_camera::rotateYZ(float angle)
{
rotate(axes[1], axes[2], angle);
}
void free_camera::rotateZX(float angle)
{
rotate(axes[2], axes[0], angle);
}
matrix<float, 4, 4> free_camera::view() const matrix<float, 4, 4> free_camera::view() const
{ {
auto tr = return homogeneous(by_rows(axes[0], axes[1], axes[2])) * translation{geom::point<float, 3>::zero() - pos}.homogeneous_matrix();
swap<float, 3>(1, 2).transform()
* scale<float, 3>({1.f, -1.f, 1.f}).transform()
* plane_rotation<float, 3>(1, 2, elevation_angle).transform()
* plane_rotation<float, 3>(1, 0, azimuthal_angle).transform()
* translation<float, 3>({ -pos[0], -pos[1], -pos[2] }).transform()
;
return tr.homogeneous_matrix();
} }
} }