mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-14 16:09:06 +07:00
clipping planes for camera
This commit is contained in:
@@ -21,20 +21,23 @@ namespace e2d
|
||||
camera() = default;
|
||||
|
||||
camera& depth(i32 value) noexcept;
|
||||
camera& znear(f32 value) noexcept;
|
||||
camera& zfar(f32 value) noexcept;
|
||||
camera& viewport(const b2f& value) noexcept;
|
||||
camera& projection(const m4f& value) noexcept;
|
||||
camera& target(const render_target_ptr& value) noexcept;
|
||||
camera& background(const color& value) noexcept;
|
||||
|
||||
[[nodiscard]] i32 depth() const noexcept;
|
||||
[[nodiscard]] f32 znear() const noexcept;
|
||||
[[nodiscard]] f32 zfar() const noexcept;
|
||||
[[nodiscard]] const b2f& viewport() const noexcept;
|
||||
[[nodiscard]] const m4f& projection() const noexcept;
|
||||
[[nodiscard]] const render_target_ptr& target() const noexcept;
|
||||
[[nodiscard]] const color& background() const noexcept;
|
||||
private:
|
||||
i32 depth_ = 0;
|
||||
f32 znear_ = 0.f;
|
||||
f32 zfar_ = 1000.f;
|
||||
b2f viewport_ = b2f::unit();
|
||||
m4f projection_ = m4f::identity();
|
||||
render_target_ptr target_ = nullptr;
|
||||
color background_ = color::clear();
|
||||
};
|
||||
@@ -89,13 +92,18 @@ namespace e2d
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline camera& camera::viewport(const b2f& value) noexcept {
|
||||
viewport_ = value;
|
||||
inline camera& camera::znear(f32 value) noexcept {
|
||||
znear_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline camera& camera::projection(const m4f& value) noexcept {
|
||||
projection_ = value;
|
||||
inline camera& camera::zfar(f32 value) noexcept {
|
||||
zfar_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline camera& camera::viewport(const b2f& value) noexcept {
|
||||
viewport_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -113,12 +121,16 @@ namespace e2d
|
||||
return depth_;
|
||||
}
|
||||
|
||||
inline const b2f& camera::viewport() const noexcept {
|
||||
return viewport_;
|
||||
inline f32 camera::znear() const noexcept {
|
||||
return znear_;
|
||||
}
|
||||
|
||||
inline const m4f& camera::projection() const noexcept {
|
||||
return projection_;
|
||||
inline f32 camera::zfar() const noexcept {
|
||||
return zfar_;
|
||||
}
|
||||
|
||||
inline const b2f& camera::viewport() const noexcept {
|
||||
return viewport_;
|
||||
}
|
||||
|
||||
inline const render_target_ptr& camera::target() const noexcept {
|
||||
@@ -129,3 +141,16 @@ namespace e2d
|
||||
return background_;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::cameras
|
||||
{
|
||||
inline m4f make_projection_matrix(const camera& camera, const window& window) noexcept {
|
||||
const v2u target_size = camera.target()
|
||||
? camera.target()->size()
|
||||
: window.real_size();
|
||||
return math::make_orthographic_lh_no_matrix4(
|
||||
target_size.cast_to<f32>(),
|
||||
camera.znear(),
|
||||
math::max(camera.zfar(), camera.znear() + math::default_precision<f32>()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,23 +517,23 @@ namespace e2d::math
|
||||
ax.x, ay.x, az.x, T(0),
|
||||
ax.y, ay.y, az.y, T(0),
|
||||
ax.z, ay.z, az.z, T(0),
|
||||
dx, dy, dz, T(1)};
|
||||
-dx, -dy, -dz, T(1)};
|
||||
}
|
||||
|
||||
//
|
||||
// make_orthogonal_lh_matrix4
|
||||
// make_orthographic_lh_zo_matrix4
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_orthogonal_lh_matrix4(T width, T height, T znear, T zfar) noexcept {
|
||||
make_orthographic_lh_zo_matrix4(T width, T height, T znear, T zfar) noexcept {
|
||||
E2D_ASSERT(!math::is_near_zero(width, T(0)));
|
||||
E2D_ASSERT(!math::is_near_zero(height, T(0)));
|
||||
E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
|
||||
const T sx = T(2) / width;
|
||||
const T sy = T(2) / height;
|
||||
const T sz = T(1) / (zfar - znear);
|
||||
const T tz = -znear * sz;
|
||||
const T tz = -znear / (zfar - znear);
|
||||
return {
|
||||
sx, T(0), T(0), T(0),
|
||||
T(0), sy, T(0), T(0),
|
||||
@@ -543,24 +543,24 @@ namespace e2d::math
|
||||
|
||||
template < typename T >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_orthogonal_lh_matrix4(const vec2<T>& size, T znear, T zfar) {
|
||||
return make_orthogonal_lh_matrix4(size.x, size.y, znear, zfar);
|
||||
make_orthographic_lh_zo_matrix4(const vec2<T>& size, T znear, T zfar) noexcept {
|
||||
return make_orthographic_lh_zo_matrix4(size.x, size.y, znear, zfar);
|
||||
}
|
||||
|
||||
//
|
||||
// make_orthogonal_rh_matrix4
|
||||
// make_orthographic_lh_no_matrix4
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_orthogonal_rh_matrix4(T width, T height, T znear, T zfar) noexcept {
|
||||
make_orthographic_lh_no_matrix4(T width, T height, T znear, T zfar) noexcept {
|
||||
E2D_ASSERT(!math::is_near_zero(width, T(0)));
|
||||
E2D_ASSERT(!math::is_near_zero(height, T(0)));
|
||||
E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
|
||||
const T sx = T(2) / width;
|
||||
const T sy = T(2) / height;
|
||||
const T sz = T(1) / (znear - zfar);
|
||||
const T tz = znear * sz;
|
||||
const T sz = T(2) / (zfar - znear);
|
||||
const T tz = -(zfar + znear) / (zfar - znear);
|
||||
return {
|
||||
sx, T(0), T(0), T(0),
|
||||
T(0), sy, T(0), T(0),
|
||||
@@ -570,24 +570,78 @@ namespace e2d::math
|
||||
|
||||
template < typename T >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_orthogonal_rh_matrix4(const vec2<T>& size, T znear, T zfar) {
|
||||
return make_orthogonal_rh_matrix4(size.x, size.y, znear, zfar);
|
||||
make_orthographic_lh_no_matrix4(const vec2<T>& size, T znear, T zfar) noexcept {
|
||||
return make_orthographic_lh_no_matrix4(size.x, size.y, znear, zfar);
|
||||
}
|
||||
|
||||
//
|
||||
// make_perspective_lh_matrix4
|
||||
// make_orthographic_rh_zo_matrix4
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_orthographic_rh_zo_matrix4(T width, T height, T znear, T zfar) noexcept {
|
||||
E2D_ASSERT(!math::is_near_zero(width, T(0)));
|
||||
E2D_ASSERT(!math::is_near_zero(height, T(0)));
|
||||
E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
|
||||
const T sx = T(2) / width;
|
||||
const T sy = T(2) / height;
|
||||
const T sz = T(-1) / (zfar - znear);
|
||||
const T tz = -znear / (zfar - znear);
|
||||
return {
|
||||
sx, T(0), T(0), T(0),
|
||||
T(0), sy, T(0), T(0),
|
||||
T(0), T(0), sz, T(0),
|
||||
T(0), T(0), tz, T(1)};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_orthographic_rh_zo_matrix4(const vec2<T>& size, T znear, T zfar) noexcept {
|
||||
return make_orthographic_rh_zo_matrix4(size.x, size.y, znear, zfar);
|
||||
}
|
||||
|
||||
//
|
||||
// make_orthographic_rh_no_matrix4
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_orthographic_rh_no_matrix4(T width, T height, T znear, T zfar) noexcept {
|
||||
E2D_ASSERT(!math::is_near_zero(width, T(0)));
|
||||
E2D_ASSERT(!math::is_near_zero(height, T(0)));
|
||||
E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
|
||||
const T sx = T(2) / width;
|
||||
const T sy = T(2) / height;
|
||||
const T sz = T(-2) / (zfar - znear);
|
||||
const T tz = -(zfar + znear) / (zfar - znear);
|
||||
return {
|
||||
sx, T(0), T(0), T(0),
|
||||
T(0), sy, T(0), T(0),
|
||||
T(0), T(0), sz, T(0),
|
||||
T(0), T(0), tz, T(1)};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_orthographic_rh_no_matrix4(const vec2<T>& size, T znear, T zfar) noexcept {
|
||||
return make_orthographic_rh_no_matrix4(size.x, size.y, znear, zfar);
|
||||
}
|
||||
|
||||
//
|
||||
// make_perspective_lh_zo_matrix4
|
||||
//
|
||||
|
||||
template < typename T, typename AngleTag >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_perspective_lh_matrix4(const unit<T, AngleTag>& fov, T aspect, T znear, T zfar) noexcept {
|
||||
make_perspective_lh_zo_matrix4(const unit<T, AngleTag>& fov, T aspect, T znear, T zfar) noexcept {
|
||||
E2D_ASSERT(!math::is_near_zero(aspect, T(0)));
|
||||
E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
|
||||
E2D_ASSERT(!math::approximately(fov, unit<T, AngleTag>::zero(), T(0)));
|
||||
const T sy = T(1) / math::tan(fov * T(0.5));
|
||||
const T sx = sy / aspect;
|
||||
const T sz = zfar / (zfar - znear);
|
||||
const T tz = -znear * zfar / (zfar - znear);
|
||||
const T tz = -(zfar * znear) / (zfar - znear);
|
||||
return {
|
||||
sx, T(0), T(0), T(0),
|
||||
T(0), sy, T(0), T(0),
|
||||
@@ -596,19 +650,61 @@ namespace e2d::math
|
||||
}
|
||||
|
||||
//
|
||||
// make_perspective_rh_matrix4
|
||||
// make_perspective_lh_no_matrix4
|
||||
//
|
||||
|
||||
template < typename T, typename AngleTag >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_perspective_rh_matrix4(const unit<T, AngleTag>& fov, T aspect, T znear, T zfar) noexcept {
|
||||
make_perspective_lh_no_matrix4(const unit<T, AngleTag>& fov, T aspect, T znear, T zfar) noexcept {
|
||||
E2D_ASSERT(!math::is_near_zero(aspect, T(0)));
|
||||
E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
|
||||
E2D_ASSERT(!math::approximately(fov, unit<T, AngleTag>::zero(), T(0)));
|
||||
const T sy = T(1) / math::tan(fov * T(0.5));
|
||||
const T sx = sy / aspect;
|
||||
const T sz = (zfar + znear) / (zfar - znear);
|
||||
const T tz = -(T(2) * zfar * znear) / (zfar - znear);
|
||||
return {
|
||||
sx, T(0), T(0), T(0),
|
||||
T(0), sy, T(0), T(0),
|
||||
T(0), T(0), sz, T(1),
|
||||
T(0), T(0), tz, T(0)};
|
||||
}
|
||||
|
||||
//
|
||||
// make_perspective_rh_zo_matrix4
|
||||
//
|
||||
|
||||
template < typename T, typename AngleTag >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_perspective_rh_zo_matrix4(const unit<T, AngleTag>& fov, T aspect, T znear, T zfar) noexcept {
|
||||
E2D_ASSERT(!math::is_near_zero(aspect, T(0)));
|
||||
E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
|
||||
E2D_ASSERT(!math::approximately(fov, unit<T, AngleTag>::zero(), T(0)));
|
||||
const T sy = T(1) / math::tan(fov * T(0.5));
|
||||
const T sx = sy / aspect;
|
||||
const T sz = zfar / (znear - zfar);
|
||||
const T tz = znear * zfar / (znear - zfar);
|
||||
const T tz = -(zfar * znear) / (zfar - znear);
|
||||
return {
|
||||
sx, T(0), T(0), T(0),
|
||||
T(0), sy, T(0), T(0),
|
||||
T(0), T(0), sz, T(-1),
|
||||
T(0), T(0), tz, T(0)};
|
||||
}
|
||||
|
||||
//
|
||||
// make_perspective_rh_no_matrix4
|
||||
//
|
||||
|
||||
template < typename T, typename AngleTag >
|
||||
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
|
||||
make_perspective_rh_no_matrix4(const unit<T, AngleTag>& fov, T aspect, T znear, T zfar) noexcept {
|
||||
E2D_ASSERT(!math::is_near_zero(aspect, T(0)));
|
||||
E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
|
||||
E2D_ASSERT(!math::approximately(fov, unit<T, AngleTag>::zero(), T(0)));
|
||||
const T sy = T(1) / math::tan(fov * T(0.5));
|
||||
const T sx = sy / aspect;
|
||||
const T sz = -(zfar + znear) / (zfar - znear);
|
||||
const T tz = -(T(2) * zfar * znear) / (zfar - znear);
|
||||
return {
|
||||
sx, T(0), T(0), T(0),
|
||||
T(0), sy, T(0), T(0),
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
"renderer" : {
|
||||
"materials" : [
|
||||
"../models/gnome/gnome_material.json"
|
||||
]
|
||||
],
|
||||
"transform" : {
|
||||
"translation" : [0,0,5]
|
||||
}
|
||||
},
|
||||
"model_renderer" : {
|
||||
"model" : "../models/gnome/gnome_model.json"
|
||||
|
||||
@@ -9,12 +9,15 @@ local camera = {
|
||||
---@type integer
|
||||
depth = 0,
|
||||
|
||||
---@type number
|
||||
znear = 0.0,
|
||||
|
||||
---@type number
|
||||
zfar = 1000.0,
|
||||
|
||||
---@type rect
|
||||
viewport = rect.zero(),
|
||||
|
||||
---@type m4f
|
||||
projection = m4f.identity(),
|
||||
|
||||
---@type color
|
||||
background = color.white()
|
||||
}
|
||||
|
||||
@@ -53,26 +53,50 @@ function m4f.make_look_at_rh(eye, at, up) end
|
||||
---@overload fun(width: number, height: number, znear: number, zfar: number): m4f
|
||||
---@overload fun(size: v2f, znear: number, zfar: number): m4f
|
||||
---@return m4f
|
||||
function m4f.make_orthogonal_lh(...) end
|
||||
function m4f.make_orthographic_lh_zo(...) end
|
||||
|
||||
---@overload fun(width: number, height: number, znear: number, zfar: number): m4f
|
||||
---@overload fun(size: v2f, znear: number, zfar: number): m4f
|
||||
---@return m4f
|
||||
function m4f.make_orthogonal_rh(...) end
|
||||
function m4f.make_orthographic_lh_no(...) end
|
||||
|
||||
---@overload fun(width: number, height: number, znear: number, zfar: number): m4f
|
||||
---@overload fun(size: v2f, znear: number, zfar: number): m4f
|
||||
---@return m4f
|
||||
function m4f.make_orthographic_rh_zo(...) end
|
||||
|
||||
---@overload fun(width: number, height: number, znear: number, zfar: number): m4f
|
||||
---@overload fun(size: v2f, znear: number, zfar: number): m4f
|
||||
---@return m4f
|
||||
function m4f.make_orthographic_rh_no(...) end
|
||||
|
||||
---@param angle number
|
||||
---@param aspect number
|
||||
---@param znear number
|
||||
---@param zfar number
|
||||
---@return m4f
|
||||
function m4f.make_perspective_lh(angle, aspect, znear, zfar) end
|
||||
function m4f.make_perspective_lh_zo(angle, aspect, znear, zfar) end
|
||||
|
||||
---@param angle number
|
||||
---@param aspect number
|
||||
---@param znear number
|
||||
---@param zfar number
|
||||
---@return m4f
|
||||
function m4f.make_perspective_rh(angle, aspect, znear, zfar) end
|
||||
function m4f.make_perspective_lh_no(angle, aspect, znear, zfar) end
|
||||
|
||||
---@param angle number
|
||||
---@param aspect number
|
||||
---@param znear number
|
||||
---@param zfar number
|
||||
---@return m4f
|
||||
function m4f.make_perspective_rh_zo(angle, aspect, znear, zfar) end
|
||||
|
||||
---@param angle number
|
||||
---@param aspect number
|
||||
---@param znear number
|
||||
---@param zfar number
|
||||
---@return m4f
|
||||
function m4f.make_perspective_rh_no(angle, aspect, znear, zfar) end
|
||||
|
||||
---@param l m4f
|
||||
---@param r m4f
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace
|
||||
|
||||
void frame_render() final {
|
||||
const auto framebuffer_size = the<window>().real_size().cast_to<f32>();
|
||||
const auto projection = math::make_orthogonal_lh_matrix4(
|
||||
const auto projection = math::make_orthographic_lh_no_matrix4(
|
||||
framebuffer_size, 0.f, 1.f);
|
||||
|
||||
material_.properties()
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace
|
||||
|
||||
void frame_render() final {
|
||||
const auto framebuffer_size = the<window>().real_size().cast_to<f32>();
|
||||
const auto projection = math::make_perspective_lh_matrix4(
|
||||
const auto projection = math::make_perspective_lh_no_matrix4(
|
||||
make_deg(45.f),
|
||||
framebuffer_size.x / framebuffer_size.y,
|
||||
0.1f,
|
||||
|
||||
@@ -205,7 +205,7 @@ namespace
|
||||
|
||||
void frame_render() final {
|
||||
const auto framebuffer_size = the<window>().real_size().cast_to<f32>();
|
||||
const auto projection = math::make_perspective_lh_matrix4(
|
||||
const auto projection = math::make_perspective_lh_no_matrix4(
|
||||
make_deg(45.f),
|
||||
framebuffer_size.x / framebuffer_size.y,
|
||||
0.1f,
|
||||
|
||||
@@ -39,23 +39,6 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
class camera_system final : public systems::post_update_system {
|
||||
public:
|
||||
void process(
|
||||
ecs::registry& owner,
|
||||
const systems::post_update_event& event) override
|
||||
{
|
||||
E2D_UNUSED(event);
|
||||
owner.for_joined_components<camera>(
|
||||
[](const ecs::const_entity&, camera& cam){
|
||||
if ( !cam.target() ) {
|
||||
cam.projection(math::make_orthogonal_lh_matrix4(
|
||||
the<window>().real_size().cast_to<f32>(), 0.f, 1000.f));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class rotator_system final : public systems::update_system {
|
||||
public:
|
||||
void process(
|
||||
@@ -118,7 +101,9 @@ namespace
|
||||
.component<named>(named()
|
||||
.name("gnome"))
|
||||
.component<renderer_rotator>(v3f::unit_y())
|
||||
.component<renderer>(renderer().materials({model_mat}))
|
||||
.component<renderer>(renderer()
|
||||
.materials({model_mat})
|
||||
.translation({0.f, 0.f, 5.f}))
|
||||
.component<model_renderer>(model_res);
|
||||
|
||||
the<world>().instantiate(
|
||||
@@ -189,8 +174,7 @@ namespace
|
||||
ecs::registry_filler(the<world>().registry())
|
||||
.feature<struct game_feature>(ecs::feature()
|
||||
.add_system<game_system>()
|
||||
.add_system<rotator_system>()
|
||||
.add_system<camera_system>());
|
||||
.add_system<rotator_system>());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,23 +32,6 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
class camera_system final : public systems::post_update_system {
|
||||
public:
|
||||
void process(
|
||||
ecs::registry& owner,
|
||||
const systems::post_update_event& event) override
|
||||
{
|
||||
E2D_UNUSED(event);
|
||||
owner.for_joined_components<camera>(
|
||||
[](const ecs::const_entity&, camera& cam){
|
||||
if ( !cam.target() ) {
|
||||
cam.projection(math::make_orthogonal_lh_matrix4(
|
||||
the<window>().real_size().cast_to<f32>(), 0.f, 1000.f));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class game final : public starter::application {
|
||||
public:
|
||||
bool initialize() final {
|
||||
@@ -67,8 +50,7 @@ namespace
|
||||
bool create_systems() {
|
||||
ecs::registry_filler(the<world>().registry())
|
||||
.feature<struct game_feature>(ecs::feature()
|
||||
.add_system<game_system>()
|
||||
.add_system<camera_system>());
|
||||
.add_system<game_system>());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,23 +70,6 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
class camera_system final : public systems::post_update_system {
|
||||
public:
|
||||
void process(
|
||||
ecs::registry& owner,
|
||||
const systems::post_update_event& event) override
|
||||
{
|
||||
E2D_UNUSED(event);
|
||||
owner.for_joined_components<camera>(
|
||||
[](const ecs::const_entity&, camera& cam){
|
||||
if ( !cam.target() ) {
|
||||
cam.projection(math::make_orthogonal_lh_matrix4(
|
||||
the<window>().real_size().cast_to<f32>(), 0.f, 1000.f));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class game final : public starter::application {
|
||||
public:
|
||||
bool initialize() final {
|
||||
@@ -105,8 +88,7 @@ namespace
|
||||
bool create_systems() {
|
||||
ecs::registry_filler(the<world>().registry())
|
||||
.feature<struct game_feature>(ecs::feature()
|
||||
.add_system<game_system>()
|
||||
.add_system<camera_system>());
|
||||
.add_system<game_system>());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,23 +32,6 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
class camera_system final : public systems::post_update_system {
|
||||
public:
|
||||
void process(
|
||||
ecs::registry& owner,
|
||||
const systems::post_update_event& event) override
|
||||
{
|
||||
E2D_UNUSED(event);
|
||||
owner.for_joined_components<camera>(
|
||||
[](const ecs::const_entity&, camera& cam){
|
||||
if ( !cam.target() ) {
|
||||
cam.projection(math::make_orthogonal_lh_matrix4(
|
||||
the<window>().real_size().cast_to<f32>(), 0.f, 1000.f));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class game final : public starter::application {
|
||||
public:
|
||||
bool initialize() final {
|
||||
@@ -67,8 +50,7 @@ namespace
|
||||
bool create_systems() {
|
||||
ecs::registry_filler(the<world>().registry())
|
||||
.feature<struct game_feature>(ecs::feature()
|
||||
.add_system<game_system>()
|
||||
.add_system<camera_system>());
|
||||
.add_system<game_system>());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -129,8 +129,8 @@ namespace e2d
|
||||
const v2f framebuffer_size = display_size * v2f(draw_data->FramebufferScale);
|
||||
|
||||
const m4f projection =
|
||||
math::make_translation_matrix4(display_size * v2f(-0.5f, 0.5f)) *
|
||||
math::make_orthogonal_lh_matrix4(display_size, 0.f, 1.f);
|
||||
math::make_orthographic_lh_no_matrix4(display_size, 0.f, 1.f) *
|
||||
math::make_translation_matrix4(-1.f, 1.f);
|
||||
|
||||
for ( int i = 0; i < draw_data->CmdListsCount; ++i ) {
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[i];
|
||||
|
||||
@@ -58,6 +58,22 @@ namespace e2d::bindings::high
|
||||
c->depth(v);
|
||||
}),
|
||||
|
||||
"znear", sol::property(
|
||||
[](const gcomponent<camera>& c) -> f32 {
|
||||
return c->znear();
|
||||
},
|
||||
[](gcomponent<camera>& c, f32 v){
|
||||
c->znear(v);
|
||||
}),
|
||||
|
||||
"zfar", sol::property(
|
||||
[](const gcomponent<camera>& c) -> f32 {
|
||||
return c->zfar();
|
||||
},
|
||||
[](gcomponent<camera>& c, f32 v){
|
||||
c->zfar(v);
|
||||
}),
|
||||
|
||||
"viewport", sol::property(
|
||||
[](const gcomponent<camera>& c) -> b2f {
|
||||
return c->viewport();
|
||||
@@ -66,14 +82,6 @@ namespace e2d::bindings::high
|
||||
c->viewport(v);
|
||||
}),
|
||||
|
||||
"projection", sol::property(
|
||||
[](const gcomponent<camera>& c) -> m4f {
|
||||
return c->projection();
|
||||
},
|
||||
[](gcomponent<camera>& c, const m4f& v){
|
||||
c->projection(v);
|
||||
}),
|
||||
|
||||
"background", sol::property(
|
||||
[](const gcomponent<camera>& c) -> color {
|
||||
return c->background();
|
||||
|
||||
@@ -66,20 +66,36 @@ namespace
|
||||
"make_look_at_rh", sol::resolve<
|
||||
mat4<T>(const vec3<T>&,const vec3<T>&,const vec3<T>&)>(&math::make_look_at_rh_matrix4),
|
||||
|
||||
"make_orthogonal_lh", sol::overload(
|
||||
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthogonal_lh_matrix4),
|
||||
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthogonal_lh_matrix4)),
|
||||
"make_orthographic_lh_zo", sol::overload(
|
||||
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthographic_lh_zo_matrix4),
|
||||
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthographic_lh_zo_matrix4)),
|
||||
|
||||
"make_orthogonal_rh", sol::overload(
|
||||
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthogonal_rh_matrix4),
|
||||
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthogonal_rh_matrix4)),
|
||||
"make_orthographic_lh_no", sol::overload(
|
||||
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthographic_lh_no_matrix4),
|
||||
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthographic_lh_no_matrix4)),
|
||||
|
||||
"make_perspective_lh", [](T angle, T aspect, T znear, T zfar) -> mat4<T> {
|
||||
return math::make_perspective_lh_matrix4(make_rad(angle), aspect, znear, zfar);
|
||||
"make_orthographic_rh_zo", sol::overload(
|
||||
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthographic_rh_zo_matrix4),
|
||||
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthographic_rh_zo_matrix4)),
|
||||
|
||||
"make_orthographic_rh_no", sol::overload(
|
||||
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthographic_rh_no_matrix4),
|
||||
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthographic_rh_no_matrix4)),
|
||||
|
||||
"make_perspective_lh_zo", [](T angle, T aspect, T znear, T zfar) -> mat4<T> {
|
||||
return math::make_perspective_lh_zo_matrix4(make_rad(angle), aspect, znear, zfar);
|
||||
},
|
||||
|
||||
"make_perspective_rh", [](T angle, T aspect, T znear, T zfar) -> mat4<T> {
|
||||
return math::make_perspective_rh_matrix4(make_rad(angle), aspect, znear, zfar);
|
||||
"make_perspective_lh_no", [](T angle, T aspect, T znear, T zfar) -> mat4<T> {
|
||||
return math::make_perspective_lh_no_matrix4(make_rad(angle), aspect, znear, zfar);
|
||||
},
|
||||
|
||||
"make_perspective_rh_zo", [](T angle, T aspect, T znear, T zfar) -> mat4<T> {
|
||||
return math::make_perspective_rh_zo_matrix4(make_rad(angle), aspect, znear, zfar);
|
||||
},
|
||||
|
||||
"make_perspective_rh_no", [](T angle, T aspect, T znear, T zfar) -> mat4<T> {
|
||||
return math::make_perspective_rh_no_matrix4(make_rad(angle), aspect, znear, zfar);
|
||||
},
|
||||
|
||||
"approximately", [](const mat4<T>& l, const mat4<T>& r) -> bool {
|
||||
|
||||
@@ -14,8 +14,9 @@ namespace e2d
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"depth" : { "type" : "number" },
|
||||
"znear" : { "type" : "number" },
|
||||
"zfar" : { "type" : "number" },
|
||||
"viewport" : { "$ref": "#/common_definitions/b2" },
|
||||
"projection" : { "$ref": "#/common_definitions/m4" },
|
||||
"background" : { "$ref": "#/common_definitions/color" }
|
||||
}
|
||||
})json";
|
||||
@@ -33,6 +34,24 @@ namespace e2d
|
||||
component.depth(depth);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("znear") ) {
|
||||
f32 znear = component.znear();
|
||||
if ( !json_utils::try_parse_value(ctx.root["znear"], znear) ) {
|
||||
the<debug>().error("CAMERA: Incorrect formatting of 'znear' property");
|
||||
return false;
|
||||
}
|
||||
component.znear(znear);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("zfar") ) {
|
||||
f32 zfar = component.zfar();
|
||||
if ( !json_utils::try_parse_value(ctx.root["zfar"], zfar) ) {
|
||||
the<debug>().error("CAMERA: Incorrect formatting of 'zfar' property");
|
||||
return false;
|
||||
}
|
||||
component.zfar(zfar);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("viewport") ) {
|
||||
b2f viewport = component.viewport();
|
||||
if ( !json_utils::try_parse_value(ctx.root["viewport"], viewport) ) {
|
||||
@@ -42,15 +61,6 @@ namespace e2d
|
||||
component.viewport(viewport);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("projection") ) {
|
||||
m4f projection = component.projection();
|
||||
if ( !json_utils::try_parse_value(ctx.root["projection"], projection) ) {
|
||||
the<debug>().error("CAMERA: Incorrect formatting of 'projection' property");
|
||||
return false;
|
||||
}
|
||||
component.projection(projection);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("target") ) {
|
||||
//TODO(BlackMat): add 'target' property parsing
|
||||
}
|
||||
@@ -118,11 +128,29 @@ namespace e2d
|
||||
}
|
||||
|
||||
if ( i32 depth = c->depth();
|
||||
ImGui::DragInt("depth", &depth) )
|
||||
ImGui::DragInt("depth", &depth, 1.f) )
|
||||
{
|
||||
c->depth(depth);
|
||||
}
|
||||
|
||||
if ( ImGui::TreeNode("clipping") ) {
|
||||
E2D_DEFER([](){ ImGui::TreePop(); });
|
||||
|
||||
if ( f32 znear = c->znear();
|
||||
ImGui::DragFloat("znear", &znear, 1.f) )
|
||||
{
|
||||
c->znear(znear);
|
||||
c->zfar(math::max(c->zfar(), c->znear()));
|
||||
}
|
||||
|
||||
if ( f32 zfar = c->zfar();
|
||||
ImGui::DragFloat("zfar", &zfar, 1.f) )
|
||||
{
|
||||
c->zfar(zfar);
|
||||
c->znear(math::min(c->znear(), c->zfar()));
|
||||
}
|
||||
}
|
||||
|
||||
if ( ImGui::TreeNode("viewport") ) {
|
||||
E2D_DEFER([](){ ImGui::TreePop(); });
|
||||
|
||||
@@ -133,13 +161,12 @@ namespace e2d
|
||||
}
|
||||
|
||||
if ( b2f viewport = c->viewport();
|
||||
ImGui::DragFloat2("size", viewport.size.data(), 0.01f) )
|
||||
ImGui::DragFloat2("size", viewport.size.data(), 0.01f, 0.f, std::numeric_limits<f32>::max()) )
|
||||
{
|
||||
c->viewport(viewport);
|
||||
}
|
||||
}
|
||||
|
||||
///TODO(BlackMat): add 'projection' inspector
|
||||
///TODO(BlackMat): add 'target' inspector
|
||||
|
||||
if ( color background = c->background();
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace e2d
|
||||
|
||||
void component_inspector<renderer>::operator()(gcomponent<renderer>& c) const {
|
||||
if ( v3f translation = c->translation();
|
||||
ImGui::DragFloat3("translation", translation.data(), 1.f) )
|
||||
ImGui::DragFloat3("translation", translation.data(), 0.01f) )
|
||||
{
|
||||
c->translation(translation);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,9 @@ namespace
|
||||
|
||||
class imgui_gizmos_context final : public component_inspector<>::gizmos_context {
|
||||
public:
|
||||
imgui_gizmos_context(editor& e, inspector& i)
|
||||
imgui_gizmos_context(editor& e, window& w, inspector& i)
|
||||
: editor_(e)
|
||||
, window_(w)
|
||||
, inspector_(i) {}
|
||||
|
||||
bool setup_camera(const ecs::const_entity& cam_e) {
|
||||
@@ -41,7 +42,7 @@ namespace
|
||||
|
||||
camera_vp_ =
|
||||
math::inversed(cam_n->world_matrix()).first *
|
||||
cam.projection() *
|
||||
cameras::make_projection_matrix(cam, window_) *
|
||||
math::make_scale_matrix4(0.5f, 0.5f) *
|
||||
math::make_translation_matrix4(0.5f, 0.5f) *
|
||||
math::make_scale_matrix4(cam.viewport().size) *
|
||||
@@ -185,6 +186,7 @@ namespace
|
||||
}
|
||||
private:
|
||||
editor& editor_;
|
||||
window& window_;
|
||||
inspector& inspector_;
|
||||
m4f camera_vp_ = m4f::identity();
|
||||
m4f go_matrix_ = m4f::identity();
|
||||
@@ -227,9 +229,9 @@ namespace e2d
|
||||
|
||||
class gizmos_system::internal_state final : private noncopyable {
|
||||
public:
|
||||
internal_state(dbgui& d, editor& e, inspector& i)
|
||||
internal_state(dbgui& d, window& w, editor& e, inspector& i)
|
||||
: dbgui_(d)
|
||||
, gcontext_(e, i) {}
|
||||
, gcontext_(e, w, i) {}
|
||||
~internal_state() noexcept = default;
|
||||
|
||||
void process_render(const ecs::const_entity& cam_e, ecs::registry& owner) {
|
||||
@@ -254,7 +256,7 @@ namespace e2d
|
||||
//
|
||||
|
||||
gizmos_system::gizmos_system()
|
||||
: state_(new internal_state(the<dbgui>(), the<editor>(), the<inspector>())) {}
|
||||
: state_(new internal_state(the<dbgui>(), the<window>(), the<editor>(), the<inspector>())) {}
|
||||
gizmos_system::~gizmos_system() noexcept = default;
|
||||
|
||||
void gizmos_system::process(
|
||||
|
||||
@@ -58,7 +58,8 @@ namespace e2d::render_system_impl
|
||||
const m4f& m_v = cam_w_inv.second
|
||||
? cam_w_inv.first
|
||||
: m4f::identity();
|
||||
const m4f& m_p = cam.projection();
|
||||
|
||||
const m4f& m_p = cameras::make_projection_matrix(cam, window);
|
||||
|
||||
batcher_.flush()
|
||||
.property(screen_s_property_hash, cam.target()
|
||||
|
||||
@@ -35,8 +35,11 @@ TEST_CASE("mat4") {
|
||||
REQUIRE(math::make_rotation_matrix4(make_rad(1.f),1.f,1.f,1.f) == math::make_rotation_matrix4(make_rad(1.f), v3f::unit()));
|
||||
REQUIRE(math::make_rotation_matrix4(make_rad(1.f),v3f(1.f,1.f,1.f)) == math::make_rotation_matrix4(make_rad(1.f), v3f::unit()));
|
||||
|
||||
REQUIRE(math::make_orthogonal_lh_matrix4(640.f, 480.f, 0.f, 1.f) == math::make_orthogonal_lh_matrix4(v2f(640,480), 0.f, 1.f));
|
||||
REQUIRE(math::make_orthogonal_lh_matrix4(640.0, 480.0, 0.0, 1.0) == math::make_orthogonal_lh_matrix4(v2d(640,480), 0.0, 1.0));
|
||||
REQUIRE(math::make_orthographic_lh_no_matrix4(640.f, 480.f, 0.f, 1.f) == math::make_orthographic_lh_no_matrix4(v2f(640,480), 0.f, 1.f));
|
||||
REQUIRE(math::make_orthographic_lh_no_matrix4(640.0, 480.0, 0.0, 1.0) == math::make_orthographic_lh_no_matrix4(v2d(640,480), 0.0, 1.0));
|
||||
|
||||
REQUIRE(math::make_orthographic_lh_zo_matrix4(640.f, 480.f, 0.f, 1.f) == math::make_orthographic_lh_zo_matrix4(v2f(640,480), 0.f, 1.f));
|
||||
REQUIRE(math::make_orthographic_lh_zo_matrix4(640.0, 480.0, 0.0, 1.0) == math::make_orthographic_lh_zo_matrix4(v2d(640,480), 0.0, 1.0));
|
||||
}
|
||||
{
|
||||
REQUIRE(m4f(m4f::identity()) == m4f::identity());
|
||||
|
||||
Reference in New Issue
Block a user