more flexible orthographic matrix

This commit is contained in:
2020-01-30 08:24:05 +07:00
parent 3237d7a0e4
commit abf7bb81fd
7 changed files with 89 additions and 69 deletions

View File

@@ -534,57 +534,61 @@ namespace e2d::math
{ {
template < typename T > template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>> std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
make_orthographic_lh_zo_matrix4(T width, T height, T znear, T zfar) noexcept { make_orthographic_lh_zo_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
E2D_ASSERT(!math::is_near_zero(width, T(0))); E2D_ASSERT(!math::approximately(left, right, T(0)));
E2D_ASSERT(!math::is_near_zero(height, T(0))); E2D_ASSERT(!math::approximately(bottom, top, T(0)));
E2D_ASSERT(!math::approximately(znear, zfar, T(0))); E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
const T sx = T(2) / width;
const T sy = T(2) / height; const T sx = T(2) / (right - left);
const T sy = T(2) / (top - bottom);
const T sz = T(1) / (zfar - znear); const T sz = T(1) / (zfar - znear);
const T tz = -znear / (zfar - znear);
const T tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
const T tz = - znear / (zfar - znear);
return { return {
sx, T(0), T(0), T(0), sx, T(0), T(0), T(0),
T(0), sy, T(0), T(0), T(0), sy, T(0), T(0),
T(0), T(0), sz, T(0), T(0), T(0), sz, T(0),
T(0), T(0), tz, T(1)}; tx, ty, tz, T(1)};
} }
template < typename T > template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>> std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
make_orthographic_lh_no_matrix4(T width, T height, T znear, T zfar) noexcept { make_orthographic_lh_no_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
E2D_ASSERT(!math::is_near_zero(width, T(0))); E2D_ASSERT(!math::approximately(left, right, T(0)));
E2D_ASSERT(!math::is_near_zero(height, T(0))); E2D_ASSERT(!math::approximately(bottom, top, T(0)));
E2D_ASSERT(!math::approximately(znear, zfar, T(0))); E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
const T sx = T(2) / width;
const T sy = T(2) / height; const T sx = T(2) / (right - left);
const T sy = T(2) / (top - bottom);
const T sz = T(2) / (zfar - znear); const T sz = T(2) / (zfar - znear);
const T tz = -(zfar + znear) / (zfar - znear);
const T tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
const T tz = - (zfar + znear) / (zfar - znear);
return { return {
sx, T(0), T(0), T(0), sx, T(0), T(0), T(0),
T(0), sy, T(0), T(0), T(0), sy, T(0), T(0),
T(0), T(0), sz, T(0), T(0), T(0), sz, T(0),
T(0), T(0), tz, T(1)}; tx, ty, tz, T(1)};
} }
} }
template < typename T > template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>> std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
make_orthographic_lh_matrix4(T width, T height, T znear, T zfar) noexcept { make_orthographic_lh_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
#if defined(E2D_CLIPPING_MODE) && E2D_CLIPPING_MODE == E2D_CLIPPING_MODE_ZO #if defined(E2D_CLIPPING_MODE) && E2D_CLIPPING_MODE == E2D_CLIPPING_MODE_ZO
return impl::make_orthographic_lh_zo_matrix4(width, height, znear, zfar); return impl::make_orthographic_lh_zo_matrix4(left, right, bottom, top, znear, zfar);
#elif defined(E2D_CLIPPING_MODE) && E2D_CLIPPING_MODE == E2D_CLIPPING_MODE_NO #elif defined(E2D_CLIPPING_MODE) && E2D_CLIPPING_MODE == E2D_CLIPPING_MODE_NO
return impl::make_orthographic_lh_no_matrix4(width, height, znear, zfar); return impl::make_orthographic_lh_no_matrix4(left, right, bottom, top, znear, zfar);
#else #else
# error "E2D_CLIPPING_MODE not detected" # error "E2D_CLIPPING_MODE not detected"
#endif #endif
} }
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
make_orthographic_lh_matrix4(const vec2<T>& size, T znear, T zfar) noexcept {
return make_orthographic_lh_matrix4(size.x, size.y, znear, zfar);
}
// //
// make_orthographic_rh_matrix4 // make_orthographic_rh_matrix4
// //
@@ -593,57 +597,61 @@ namespace e2d::math
{ {
template < typename T > template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, mat4<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 { make_orthographic_rh_zo_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
E2D_ASSERT(!math::is_near_zero(width, T(0))); E2D_ASSERT(!math::approximately(left, right, T(0)));
E2D_ASSERT(!math::is_near_zero(height, T(0))); E2D_ASSERT(!math::approximately(bottom, top, T(0)));
E2D_ASSERT(!math::approximately(znear, zfar, T(0))); E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
const T sx = T(2) / width;
const T sy = T(2) / height; const T sx = T(2) / (right - left);
const T sy = T(2) / (top - bottom);
const T sz = T(-1) / (zfar - znear); const T sz = T(-1) / (zfar - znear);
const T tz = -znear / (zfar - znear);
const T tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
const T tz = - znear / (zfar - znear);
return { return {
sx, T(0), T(0), T(0), sx, T(0), T(0), T(0),
T(0), sy, T(0), T(0), T(0), sy, T(0), T(0),
T(0), T(0), sz, T(0), T(0), T(0), sz, T(0),
T(0), T(0), tz, T(1)}; tx, ty, tz, T(1)};
} }
template < typename T > template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, mat4<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 { make_orthographic_rh_no_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
E2D_ASSERT(!math::is_near_zero(width, T(0))); E2D_ASSERT(!math::approximately(left, right, T(0)));
E2D_ASSERT(!math::is_near_zero(height, T(0))); E2D_ASSERT(!math::approximately(bottom, top, T(0)));
E2D_ASSERT(!math::approximately(znear, zfar, T(0))); E2D_ASSERT(!math::approximately(znear, zfar, T(0)));
const T sx = T(2) / width;
const T sy = T(2) / height; const T sx = T(2) / (right - left);
const T sy = T(2) / (top - bottom);
const T sz = T(-2) / (zfar - znear); const T sz = T(-2) / (zfar - znear);
const T tz = -(zfar + znear) / (zfar - znear);
const T tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
const T tz = - (zfar + znear) / (zfar - znear);
return { return {
sx, T(0), T(0), T(0), sx, T(0), T(0), T(0),
T(0), sy, T(0), T(0), T(0), sy, T(0), T(0),
T(0), T(0), sz, T(0), T(0), T(0), sz, T(0),
T(0), T(0), tz, T(1)}; tx, ty, tz, T(1)};
} }
} }
template < typename T > template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>> std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
make_orthographic_rh_matrix4(T width, T height, T znear, T zfar) noexcept { make_orthographic_rh_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
#if defined(E2D_CLIPPING_MODE) && E2D_CLIPPING_MODE == E2D_CLIPPING_MODE_ZO #if defined(E2D_CLIPPING_MODE) && E2D_CLIPPING_MODE == E2D_CLIPPING_MODE_ZO
return impl::make_orthographic_rh_zo_matrix4(width, height, znear, zfar); return impl::make_orthographic_rh_zo_matrix4(left, right, bottom, top, znear, zfar);
#elif defined(E2D_CLIPPING_MODE) && E2D_CLIPPING_MODE == E2D_CLIPPING_MODE_NO #elif defined(E2D_CLIPPING_MODE) && E2D_CLIPPING_MODE == E2D_CLIPPING_MODE_NO
return impl::make_orthographic_rh_no_matrix4(width, height, znear, zfar); return impl::make_orthographic_rh_no_matrix4(left, right, bottom, top, znear, zfar);
#else #else
# error "E2D_CLIPPING_MODE not detected" # error "E2D_CLIPPING_MODE not detected"
#endif #endif
} }
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, mat4<T>>
make_orthographic_rh_matrix4(const vec2<T>& size, T znear, T zfar) noexcept {
return make_orthographic_rh_matrix4(size.x, size.y, znear, zfar);
}
// //
// make_perspective_lh_matrix4 // make_perspective_lh_matrix4
// //

View File

@@ -50,15 +50,23 @@ function m4f.make_look_at_lh(eye, at, up) end
---@return m4f ---@return m4f
function m4f.make_look_at_rh(eye, at, up) end function m4f.make_look_at_rh(eye, at, up) end
---@overload fun(width: number, height: number, znear: number, zfar: number): m4f ---@param left number
---@overload fun(size: v2f, znear: number, zfar: number): m4f ---@param right number
---@param bottom number
---@param top number
---@param znear number
---@param zfar number
---@return m4f ---@return m4f
function m4f.make_orthographic_lh(...) end function m4f.make_orthographic_lh(left, right, bottom, top, znear, zfar) end
---@overload fun(width: number, height: number, znear: number, zfar: number): m4f ---@param left number
---@overload fun(size: v2f, znear: number, zfar: number): m4f ---@param right number
---@param bottom number
---@param top number
---@param znear number
---@param zfar number
---@return m4f ---@return m4f
function m4f.make_orthographic_rh(...) end function m4f.make_orthographic_rh(left, right, bottom, top, znear, zfar) end
---@param angle number ---@param angle number
---@param aspect number ---@param aspect number

View File

@@ -128,9 +128,10 @@ namespace e2d
const v2f display_size = draw_data->DisplaySize; const v2f display_size = draw_data->DisplaySize;
const v2f framebuffer_size = display_size * v2f(draw_data->FramebufferScale); const v2f framebuffer_size = display_size * v2f(draw_data->FramebufferScale);
const m4f projection = const m4f projection = math::make_orthographic_lh_matrix4(
math::make_orthographic_lh_matrix4(display_size, 0.f, 1.f) * 0.f, display_size.x,
math::make_translation_matrix4(-1.f, 1.f); display_size.y, 0.f,
-1.f, 1.f);
for ( int i = 0; i < draw_data->CmdListsCount; ++i ) { for ( int i = 0; i < draw_data->CmdListsCount; ++i ) {
const ImDrawList* cmd_list = draw_data->CmdLists[i]; const ImDrawList* cmd_list = draw_data->CmdLists[i];

View File

@@ -23,7 +23,7 @@ namespace
void main(){ void main(){
v_color = a_color; v_color = a_color;
v_uv = a_uv; v_uv = a_uv;
gl_Position = vec4(a_position.x, -a_position.y, 0.0, 1.0) * u_MVP; gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0) * u_MVP;
} }
)glsl"; )glsl";

View File

@@ -67,12 +67,10 @@ namespace
mat4<T>(const vec3<T>&,const vec3<T>&,const vec3<T>&)>(&math::make_look_at_rh_matrix4), mat4<T>(const vec3<T>&,const vec3<T>&,const vec3<T>&)>(&math::make_look_at_rh_matrix4),
"make_orthographic_lh", sol::overload( "make_orthographic_lh", sol::overload(
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthographic_lh_matrix4), sol::resolve<mat4<T>(T,T,T,T,T,T)>(&math::make_orthographic_lh_matrix4)),
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthographic_lh_matrix4)),
"make_orthographic_rh", sol::overload( "make_orthographic_rh", sol::overload(
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthographic_rh_matrix4), sol::resolve<mat4<T>(T,T,T,T,T,T)>(&math::make_orthographic_rh_matrix4)),
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthographic_rh_matrix4)),
"make_perspective_lh", [](T angle, T aspect, T znear, T zfar) -> mat4<T> { "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); return math::make_perspective_lh_matrix4(make_rad(angle), aspect, znear, zfar);

View File

@@ -19,6 +19,14 @@ namespace
: m4f::identity(); : m4f::identity();
} }
m4f make_camera_orthographic(const v2f& size, f32 znear, f32 zfar) noexcept {
return
math::make_orthographic_lh_matrix4(
-0.5f * size.x, 0.5f * size.x,
-0.5f * size.y, 0.5f * size.y,
znear, zfar);
}
m4f make_camera_projection(const camera& camera, const window& window) noexcept { m4f make_camera_projection(const camera& camera, const window& window) noexcept {
const f32 ortho_znear = camera.znear(); const f32 ortho_znear = camera.znear();
const f32 ortho_zfar = math::max( const f32 ortho_zfar = math::max(
@@ -45,24 +53,24 @@ namespace
case camera::modes::manual: case camera::modes::manual:
return camera.projection(); return camera.projection();
case camera::modes::stretch: case camera::modes::stretch:
return math::make_orthographic_lh_matrix4( return make_camera_orthographic(
virtual_size, virtual_size,
ortho_znear, ortho_znear,
ortho_zfar); ortho_zfar);
case camera::modes::flexible: case camera::modes::flexible:
return math::make_orthographic_lh_matrix4( return make_camera_orthographic(
viewport_size, viewport_size,
ortho_znear, ortho_znear,
ortho_zfar); ortho_zfar);
case camera::modes::fixed_fit: case camera::modes::fixed_fit:
return math::make_orthographic_lh_matrix4( return make_camera_orthographic(
viewport_aspect < virtual_aspect viewport_aspect < virtual_aspect
? v2f(virtual_size.x, virtual_size.y * (virtual_aspect / viewport_aspect)) ? v2f(virtual_size.x, virtual_size.y * (virtual_aspect / viewport_aspect))
: v2f(virtual_size.x * (viewport_aspect / virtual_aspect), virtual_size.y), : v2f(virtual_size.x * (viewport_aspect / virtual_aspect), virtual_size.y),
ortho_znear, ortho_znear,
ortho_zfar); ortho_zfar);
case camera::modes::fixed_crop: case camera::modes::fixed_crop:
return math::make_orthographic_lh_matrix4( return make_camera_orthographic(
virtual_aspect < viewport_aspect virtual_aspect < viewport_aspect
? v2f(virtual_size.x, virtual_size.y * (virtual_aspect / viewport_aspect)) ? v2f(virtual_size.x, virtual_size.y * (virtual_aspect / viewport_aspect))
: v2f(virtual_size.x * (viewport_aspect / virtual_aspect), virtual_size.y), : v2f(virtual_size.x * (viewport_aspect / virtual_aspect), virtual_size.y),

View File

@@ -27,15 +27,12 @@ namespace
, inspector_(i) {} , inspector_(i) {}
bool setup_camera(const ecs::const_entity& cam_e) { bool setup_camera(const ecs::const_entity& cam_e) {
if ( !cam_e.valid() || !ecs::exists_all<actor, camera, camera::gizmos>()(cam_e) ) { if ( !cam_e.valid() || !ecs::exists_all<camera, camera::gizmos>()(cam_e) ) {
return false; return false;
} }
const camera& cam = cam_e.get_component<camera>(); const camera& cam = cam_e.get_component<camera>();
const actor& cam_a = cam_e.get_component<actor>(); if ( cam.target() ) {
const const_node_iptr& cam_n = cam_a.node();
if ( !cam_n ) {
return false; return false;
} }