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

View file

@ -128,22 +128,28 @@ namespace psemek::geom
struct free_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;
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)
, azimuthal_angle{azimuthal_angle}
, elevation_angle{elevation_angle}
, 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;
};

View file

@ -120,17 +120,35 @@ namespace psemek::geom
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
{
auto tr =
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();
return homogeneous(by_rows(axes[0], axes[1], axes[2])) * translation{geom::point<float, 3>::zero() - pos}.homogeneous_matrix();
}
}