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 >
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 {
E2D_ASSERT(!math::is_near_zero(width, T(0)));
E2D_ASSERT(!math::is_near_zero(height, T(0)));
make_orthographic_lh_zo_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
E2D_ASSERT(!math::approximately(left, right, T(0)));
E2D_ASSERT(!math::approximately(bottom, top, 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 tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
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)};
tx, ty, tz, T(1)};
}
template < typename 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 {
E2D_ASSERT(!math::is_near_zero(width, T(0)));
E2D_ASSERT(!math::is_near_zero(height, T(0)));
make_orthographic_lh_no_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
E2D_ASSERT(!math::approximately(left, right, T(0)));
E2D_ASSERT(!math::approximately(bottom, top, 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 tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
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)};
tx, ty, tz, T(1)};
}
}
template < typename 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
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
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
# error "E2D_CLIPPING_MODE not detected"
#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
//
@@ -593,57 +597,61 @@ namespace e2d::math
{
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)));
make_orthographic_rh_zo_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
E2D_ASSERT(!math::approximately(left, right, T(0)));
E2D_ASSERT(!math::approximately(bottom, top, 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 tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
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)};
tx, ty, tz, T(1)};
}
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)));
make_orthographic_rh_no_matrix4(T left, T right, T bottom, T top, T znear, T zfar) noexcept {
E2D_ASSERT(!math::approximately(left, right, T(0)));
E2D_ASSERT(!math::approximately(bottom, top, 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 tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
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)};
tx, ty, tz, T(1)};
}
}
template < typename 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
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
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
# error "E2D_CLIPPING_MODE not detected"
#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
//

View File

@@ -50,15 +50,23 @@ function m4f.make_look_at_lh(eye, at, up) end
---@return m4f
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
---@param left number
---@param right number
---@param bottom number
---@param top number
---@param znear number
---@param zfar number
---@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
---@overload fun(size: v2f, znear: number, zfar: number): m4f
---@param left number
---@param right number
---@param bottom number
---@param top number
---@param znear number
---@param zfar number
---@return m4f
function m4f.make_orthographic_rh(...) end
function m4f.make_orthographic_rh(left, right, bottom, top, znear, zfar) end
---@param angle number
---@param aspect number

View File

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

View File

@@ -23,7 +23,7 @@ namespace
void main(){
v_color = a_color;
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";

View File

@@ -67,12 +67,10 @@ namespace
mat4<T>(const vec3<T>&,const vec3<T>&,const vec3<T>&)>(&math::make_look_at_rh_matrix4),
"make_orthographic_lh", sol::overload(
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthographic_lh_matrix4),
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthographic_lh_matrix4)),
sol::resolve<mat4<T>(T,T,T,T,T,T)>(&math::make_orthographic_lh_matrix4)),
"make_orthographic_rh", sol::overload(
sol::resolve<mat4<T>(T,T,T,T)>(&math::make_orthographic_rh_matrix4),
sol::resolve<mat4<T>(const vec2<T>&,T,T)>(&math::make_orthographic_rh_matrix4)),
sol::resolve<mat4<T>(T,T,T,T,T,T)>(&math::make_orthographic_rh_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);

View File

@@ -19,6 +19,14 @@ namespace
: 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 {
const f32 ortho_znear = camera.znear();
const f32 ortho_zfar = math::max(
@@ -45,24 +53,24 @@ namespace
case camera::modes::manual:
return camera.projection();
case camera::modes::stretch:
return math::make_orthographic_lh_matrix4(
return make_camera_orthographic(
virtual_size,
ortho_znear,
ortho_zfar);
case camera::modes::flexible:
return math::make_orthographic_lh_matrix4(
return make_camera_orthographic(
viewport_size,
ortho_znear,
ortho_zfar);
case camera::modes::fixed_fit:
return math::make_orthographic_lh_matrix4(
return make_camera_orthographic(
viewport_aspect < virtual_aspect
? v2f(virtual_size.x, virtual_size.y * (virtual_aspect / viewport_aspect))
: v2f(virtual_size.x * (viewport_aspect / virtual_aspect), virtual_size.y),
ortho_znear,
ortho_zfar);
case camera::modes::fixed_crop:
return math::make_orthographic_lh_matrix4(
return make_camera_orthographic(
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),

View File

@@ -27,15 +27,12 @@ namespace
, inspector_(i) {}
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;
}
const camera& cam = cam_e.get_component<camera>();
const actor& cam_a = cam_e.get_component<actor>();
const const_node_iptr& cam_n = cam_a.node();
if ( !cam_n ) {
if ( cam.target() ) {
return false;
}