Merge branch 'master' into feature/render

This commit is contained in:
2018-10-24 18:53:09 +07:00
16 changed files with 344 additions and 128 deletions

View File

@@ -11,6 +11,7 @@
#include "mat2.hpp"
#include "mat3.hpp"
#include "mat4.hpp"
#include "rect.hpp"
#include "trig.hpp"
#include "unit.hpp"
#include "vec2.hpp"

View File

@@ -28,6 +28,9 @@ namespace e2d
template < typename T >
class mat4;
template < typename T >
class rect;
template < typename T, typename Tag >
class unit;
@@ -79,6 +82,13 @@ namespace e2d
using m4hi = mat4<i16>;
using m4hu = mat4<u16>;
using r4d = rect<f64>;
using r4f = rect<f32>;
using r4i = rect<i32>;
using r4u = rect<u32>;
using r4hi = rect<i16>;
using r4hu = rect<u16>;
struct deg_tag {};
struct rad_tag {};

View File

@@ -0,0 +1,212 @@
/*******************************************************************************
* This file is part of the "Enduro2D"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2018 Matvey Cherevko
******************************************************************************/
#pragma once
#include "_math.hpp"
#include "vec2.hpp"
namespace e2d
{
template < typename T >
class rect final {
static_assert(
std::is_arithmetic<T>::value,
"type of 'rect' must be arithmetic");
public:
using self_type = rect;
using value_type = T;
public:
vec2<T> position;
vec2<T> size;
public:
rect() noexcept = default;
rect(const rect& other) noexcept = default;
rect& operator=(const rect& other) noexcept = default;
rect(T w, T h) noexcept;
rect(T x, T y, T w, T h) noexcept;
rect(const vec2<T>& nsize) noexcept;
rect(const vec2<T>& nposition, const vec2<T>& nsize) noexcept;
template < typename To >
rect<To> cast_to() const noexcept;
};
}
namespace e2d
{
template < typename T >
rect<T>::rect(T w, T h) noexcept
: size(w, h) {}
template < typename T >
rect<T>::rect(T x, T y, T w, T h) noexcept
: position(x, y)
, size(w, h) {}
template < typename T >
rect<T>::rect(const vec2<T>& nsize) noexcept
: size(nsize) {}
template < typename T >
rect<T>::rect(const vec2<T>& nposition, const vec2<T>& nsize) noexcept
: position(nposition)
, size(nsize) {}
template < typename T >
template < typename To >
rect<To> rect<T>::cast_to() const noexcept {
return {
position.template cast_to<To>(),
size.template cast_to<To>()};
}
}
namespace e2d
{
//
// make_rect
//
template < typename T >
rect<T> make_rect(T w, T h) noexcept {
return {w, h};
}
template < typename T >
rect<T> make_rect(T x, T y, T w, T h) noexcept {
return {x, y, w, h};
}
template < typename T >
rect<T> make_rect(const vec2<T>& size) noexcept {
return {size};
}
template < typename T >
rect<T> make_rect(const vec2<T>& position, const vec2<T>& size) noexcept {
return {position, size};
}
//
// rect (==,!=) rect
//
template < typename T >
bool operator==(const rect<T>& l, const rect<T>& r) noexcept {
return l.position == r.position
&& l.size == r.size;
}
template < typename T >
bool operator!=(const rect<T>& l, const rect<T>& r) noexcept {
return !(l == r);
}
//
// rect (<,>,<=,>=) rect
//
template < typename T >
bool operator<(const rect<T>& l, const rect<T>& r) noexcept {
return l.size.x * l.size.y < r.size.x * r.size.y;
}
template < typename T >
bool operator>(const rect<T>& l, const rect<T>& r) noexcept {
return r < l;
}
template < typename T >
bool operator<=(const rect<T>& l, const rect<T>& r) noexcept {
return !(r < l);
}
template < typename T >
bool operator>=(const rect<T>& l, const rect<T>& r) noexcept {
return !(l < r);
}
}
namespace e2d { namespace math
{
//
// approximately
//
template < typename T >
bool approximately(
const rect<T>& l,
const rect<T>& r,
T precision = math::default_precision<T>()) noexcept
{
return math::approximately(l.position, r.position, precision)
&& math::approximately(l.size, r.size, precision);
}
//
// minimum/maximum
//
template < typename T >
vec2<T> minimum(const rect<T>& r) noexcept {
return math::minimized(r.position, r.position + r.size);
}
template < typename T >
vec2<T> maximum(const rect<T>& r) noexcept {
return math::maximized(r.position, r.position + r.size);
}
//
// area
//
template < typename T >
T area(const rect<T>& r) noexcept {
return r.size.x * r.size.y;
}
template < typename T >
T abs_area(const rect<T>& r) noexcept {
return math::abs(r.size.x * r.size.y);
}
//
// merged
//
template < typename T >
rect<T> merged(const rect<T>& l, const rect<T>& r) noexcept {
const vec2<T> min = math::minimized(minimum(l), minimum(r));
const vec2<T> max = math::maximized(maximum(l), maximum(r));
return { min, max - min };
}
//
// inside
//
template < typename T >
bool inside(const rect<T>& r, const vec2<T>& p) noexcept {
const vec2<T> min = minimum(r);
const vec2<T> max = maximum(r);
return p.x >= min.x && p.x <= max.x
&& p.y >= min.y && p.y <= max.y;
}
//
// contains_nan
//
template < typename T >
bool contains_nan(const rect<T>& r) noexcept {
return math::contains_nan(r.position)
|| math::contains_nan(r.size);
}
}}

View File

@@ -506,20 +506,9 @@ namespace e2d { namespace math
}
//
// contains
// contains_nan
//
template < typename T >
bool contains(
const vec2<T>& v,
T value,
T precision = math::default_precision<T>()) noexcept
{
return
math::approximately(v.x, value, precision) ||
math::approximately(v.y, value, precision);
}
template < typename T >
bool contains_nan(const vec2<T>& v) noexcept {
return

View File

@@ -564,21 +564,9 @@ namespace e2d { namespace math
}
//
// contains
// contains_nan
//
template < typename T >
bool contains(
const vec3<T>& v,
T value,
T precision = math::default_precision<T>()) noexcept
{
return
math::approximately(v.x, value, precision) ||
math::approximately(v.y, value, precision) ||
math::approximately(v.z, value, precision);
}
template < typename T >
bool contains_nan(const vec3<T>& v) noexcept {
return

View File

@@ -598,22 +598,9 @@ namespace e2d { namespace math
}
//
// contains
// contains_nan
//
template < typename T >
bool contains(
const vec4<T>& v,
T value,
T precision = math::default_precision<T>()) noexcept
{
return
math::approximately(v.x, value, precision) ||
math::approximately(v.y, value, precision) ||
math::approximately(v.z, value, precision) ||
math::approximately(v.w, value, precision);
}
template < typename T >
bool contains_nan(const vec4<T>& v) noexcept {
return

View File

@@ -87,10 +87,6 @@ namespace e2d { namespace math
color clamped(const color& c, const color& cmin, const color& cmax) noexcept;
color saturated(const color& c) noexcept;
bool contains(
const color& c,
f32 value,
f32 precision = math::default_precision<f32>()) noexcept;
bool contains_nan(const color& c) noexcept;
}}

View File

@@ -85,11 +85,6 @@ namespace e2d { namespace math
color32 minimized(const color32& c, const color32& cmin) noexcept;
color32 maximized(const color32& c, const color32& cmax) noexcept;
color32 clamped(const color32& c, const color32& cmin, const color32& cmax) noexcept;
bool contains(
const color32& c,
u8 value,
u8 precision = math::default_precision<u8>()) noexcept;
}}
namespace e2d { namespace colors

View File

@@ -125,7 +125,10 @@ namespace e2d
}
color& color::operator/=(const color& other) noexcept {
E2D_ASSERT(!math::contains(other, 0.f, 0.f));
E2D_ASSERT(!math::is_near_zero(other.r, 0.f));
E2D_ASSERT(!math::is_near_zero(other.g, 0.f));
E2D_ASSERT(!math::is_near_zero(other.b, 0.f));
E2D_ASSERT(!math::is_near_zero(other.a, 0.f));
r /= other.r;
g /= other.g;
b /= other.b;
@@ -300,16 +303,9 @@ namespace e2d { namespace math
}
//
// contains
// contains_nan
//
bool contains(const color& c, f32 value, f32 precision) noexcept {
return math::approximately(c.r, value, precision)
|| math::approximately(c.g, value, precision)
|| math::approximately(c.b, value, precision)
|| math::approximately(c.a, value, precision);
}
bool contains_nan(const color& c) noexcept {
return !math::is_finite(c.r)
|| !math::is_finite(c.g)

View File

@@ -125,7 +125,10 @@ namespace e2d
}
color32& color32::operator/=(const color32& other) noexcept {
E2D_ASSERT(!math::contains(other, u8(0), u8(0)));
E2D_ASSERT(!math::is_near_zero(other.r, u8(0)));
E2D_ASSERT(!math::is_near_zero(other.g, u8(0)));
E2D_ASSERT(!math::is_near_zero(other.b, u8(0)));
E2D_ASSERT(!math::is_near_zero(other.a, u8(0)));
r /= other.r;
g /= other.g;
b /= other.b;
@@ -294,17 +297,6 @@ namespace e2d { namespace math
math::clamp(c.b, cmin.b, cmax.b),
math::clamp(c.a, cmin.a, cmax.a));
}
//
// contains
//
bool contains(const color32& c, u8 value, u8 precision) noexcept {
return math::approximately(c.r, value, precision)
|| math::approximately(c.g, value, precision)
|| math::approximately(c.b, value, precision)
|| math::approximately(c.a, value, precision);
}
}}
namespace e2d { namespace colors

View File

@@ -0,0 +1,109 @@
/*******************************************************************************
* This file is part of the "Enduro2D"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2018 Matvey Cherevko
******************************************************************************/
#include "_math.hpp"
using namespace e2d;
TEST_CASE("rect") {
{
REQUIRE(r4i().position == v2i(0,0));
REQUIRE(r4i().size == v2i(0,0));
REQUIRE(r4i(1,2).position == v2i(0,0));
REQUIRE(r4i(1,2).size == v2i(1,2));
REQUIRE(r4i(1,2,3,4).position == v2i(1,2));
REQUIRE(r4i(1,2,3,4).size == v2i(3,4));
REQUIRE(r4i(v2i{1,2}).position == v2i(0,0));
REQUIRE(r4i(v2i{1,2}).size == v2i(1,2));
REQUIRE(r4i(v2i{1,2},v2i{3,4}).position == v2i(1,2));
REQUIRE(r4i(v2i{1,2},v2i{3,4}).size == v2i(3,4));
}
{
REQUIRE(r4f(1,2,3,4).cast_to<i32>() == r4i(1,2,3,4));
}
{
REQUIRE(make_rect(2,1) == r4i(0,0,2,1));
REQUIRE(make_rect(4,3,2,1) == r4i(4,3,2,1));
REQUIRE(make_rect(v2i{2,1}) == r4i(0,0,2,1));
REQUIRE(make_rect(v2i{4,3},v2i{2,1}) == r4i(4,3,2,1));
}
{
auto r0 = r4i(1,2,3,4);
auto r1 = r4i(r0);
REQUIRE(r1 == r4i(1,2,3,4));
r1 = r4i(4,3,2,1);
REQUIRE(r1 == r4i(4,3,2,1));
}
{
REQUIRE(r4i(1,2,3,4) == r4i(1,2,3,4));
REQUIRE_FALSE(r4i(1,2,3,4) == r4i(1,2,4,3));
REQUIRE_FALSE(r4i(1,2,3,4) == r4i(2,1,3,4));
REQUIRE_FALSE(r4i(1,2,3,4) == r4i(2,1,4,3));
REQUIRE_FALSE(r4i(1,2,3,4) != r4i(1,2,3,4));
REQUIRE(r4i(1,2,3,4) != r4i(1,2,4,3));
REQUIRE(r4i(1,2,3,4) != r4i(2,1,3,4));
REQUIRE(r4i(1,2,3,4) != r4i(2,1,4,3));
}
{
REQUIRE(r4i(4,4) < r4i(4,5));
REQUIRE_FALSE(r4i(4,4) < r4i(3,4));
REQUIRE_FALSE(r4i(4,4) < r4i(4,3));
}
{
REQUIRE(math::approximately(r4i(1,2,3,4), r4i(1,2,4,5), 1));
REQUIRE_FALSE(math::approximately(r4i(1,2,3,4), r4i(1,2,4,5)));
}
{
REQUIRE(math::minimum(r4i(1,2,3,4)) == v2i(1,2));
REQUIRE(math::minimum(r4i(1,2,-3,5)) == v2i(-2,2));
REQUIRE(math::minimum(r4i(1,2,3,-5)) == v2i(1,-3));
REQUIRE(math::minimum(r4i(1,2,-3,-5)) == v2i(-2,-3));
REQUIRE(math::maximum(r4i(1,2,3,4)) == v2i(4,6));
REQUIRE(math::maximum(r4i(1,2,-3,5)) == v2i(1,7));
REQUIRE(math::maximum(r4i(1,2,3,-5)) == v2i(4,2));
REQUIRE(math::maximum(r4i(1,2,-3,-5)) == v2i(1,2));
REQUIRE(math::area(r4i(1,2,3,4)) == 12);
REQUIRE(math::area(r4i(1,2,3,-4)) == -12);
REQUIRE(math::area(r4i(1,2,-3,4)) == -12);
REQUIRE(math::area(r4i(1,2,-3,-4)) == 12);
REQUIRE(math::abs_area(r4i(1,2,3,4)) == 12);
REQUIRE(math::abs_area(r4i(1,2,3,-4)) == 12);
REQUIRE(math::abs_area(r4i(1,2,-3,4)) == 12);
REQUIRE(math::abs_area(r4i(1,2,-3,-4)) == 12);
REQUIRE(math::merged(r4i(1,2,3,4), r4i(1,2,3,4)) == r4i(1,2,3,4));
REQUIRE(math::merged(r4i(1,2,3,4), r4i(0,1,3,4)) == r4i(0,1,4,5));
REQUIRE(math::merged(r4i(1,2,3,4), r4i(1,2,4,5)) == r4i(1,2,4,5));
REQUIRE(math::merged(r4i(1,2,3,4), r4i(0,1,4,5)) == r4i(0,1,4,5));
REQUIRE(math::merged(r4i(1,2,3,4), r4i(1,2,-3,-5)) == r4i(-2,-3,6,9));
REQUIRE(math::merged(r4i(-1,-2,3,4), r4i(1,2,-3,-5)) == r4i(-2,-3,4,5));
REQUIRE(math::inside(r4i(1,2,3,4), v2i(1,2)));
REQUIRE(math::inside(r4i(1,2,3,4), v2i(4,5)));
REQUIRE_FALSE(math::inside(r4i(1,2,3,4), v2i(4,7)));
REQUIRE_FALSE(math::inside(r4i(1,2,3,4), v2i(0,5)));
REQUIRE(math::inside(r4i(1,2,-3,-4), v2i(1,2)));
REQUIRE(math::inside(r4i(1,2,-3,-4), v2i(-1,-2)));
REQUIRE_FALSE(math::inside(r4i(1,2,-3,-4), v2i(2,2)));
REQUIRE_FALSE(math::inside(r4i(1,2,-3,-4), v2i(1,3)));
REQUIRE_FALSE(math::inside(r4i(1,2,-3,-4), v2i(-3,2)));
REQUIRE_FALSE(math::inside(r4i(1,2,-3,-4), v2i(1,-3)));
REQUIRE_FALSE(math::contains_nan(r4i(1,2,3,4)));
REQUIRE_FALSE(math::contains_nan(r4f(1.f,2.f,3.f,4.f)));
REQUIRE(math::contains_nan(r4f(1.f,std::numeric_limits<f32>::quiet_NaN())));
REQUIRE(math::contains_nan(r4f(std::numeric_limits<f32>::infinity(), 1.f)));
}
}

View File

@@ -253,17 +253,5 @@ TEST_CASE("vec2") {
REQUIRE_FALSE(math::contains_nan(v2f(0.f,1.f)));
REQUIRE(math::contains_nan(v2f(0.f,std::numeric_limits<f32>::quiet_NaN())));
REQUIRE(math::contains_nan(v2f(std::numeric_limits<f32>::infinity(),1.f)));
REQUIRE_FALSE(math::contains(v2i(1,1), 0));
REQUIRE(math::contains(v2i(1,1), 0, 1));
REQUIRE(math::contains(v2i(0,1), 0));
REQUIRE(math::contains(v2i(1,0), 0));
REQUIRE(math::contains(v2i(0,0), 0));
REQUIRE_FALSE(math::contains(v2f(0.1f,0.2f), 0.f));
REQUIRE(math::contains(v2f(0.1f,0.2f), 0.f, 0.25f));
REQUIRE(math::contains(v2f(0,1.f), 0.f));
REQUIRE(math::contains(v2f(1.f,0), 0.f));
REQUIRE(math::contains(v2f(0,0), 0.f));
}
}

View File

@@ -277,19 +277,5 @@ TEST_CASE("vec3") {
REQUIRE(math::contains_nan(v3f(0.f,1.f,std::numeric_limits<f32>::quiet_NaN())));
REQUIRE(math::contains_nan(v3f(std::numeric_limits<f32>::infinity(),1.f,2.f)));
REQUIRE(math::contains_nan(v3f(1.f,std::numeric_limits<f32>::infinity(),2.f)));
REQUIRE_FALSE(math::contains(v3i(1,1,1), 0));
REQUIRE(math::contains(v3i(1,1,1), 0, 1));
REQUIRE(math::contains(v3i(0,1,1), 0));
REQUIRE(math::contains(v3i(1,0,1), 0));
REQUIRE(math::contains(v3i(1,1,0), 0));
REQUIRE(math::contains(v3i(0,0,0), 0));
REQUIRE_FALSE(math::contains(v3f(0.1f,0.2f,0.3f), 0.f));
REQUIRE(math::contains(v3f(0.1f,0.2f,0.3f), 0.f, 0.35f));
REQUIRE(math::contains(v3f(0,1.f,2.f), 0.f));
REQUIRE(math::contains(v3f(1.f,0,2.f), 0.f));
REQUIRE(math::contains(v3f(1.f,2.f,0), 0.f));
REQUIRE(math::contains(v3f(0,0,0), 0.f));
}
}

View File

@@ -295,21 +295,5 @@ TEST_CASE("vec4") {
REQUIRE(math::contains_nan(v4f(0.f,1.f,std::numeric_limits<f32>::quiet_NaN(),2.f)));
REQUIRE(math::contains_nan(v4f(std::numeric_limits<f32>::infinity(),1.f,2.f,3.f)));
REQUIRE(math::contains_nan(v4f(1.f,std::numeric_limits<f32>::infinity(),2.f,3.f)));
REQUIRE_FALSE(math::contains(v4i(1,1,1,1), 0));
REQUIRE(math::contains(v4i(1,1,1,1), 0, 1));
REQUIRE(math::contains(v4i(0,1,1,1), 0));
REQUIRE(math::contains(v4i(1,0,1,1), 0));
REQUIRE(math::contains(v4i(1,1,0,1), 0));
REQUIRE(math::contains(v4i(1,1,1,0), 0));
REQUIRE(math::contains(v4i(0,0,0,0), 0));
REQUIRE_FALSE(math::contains(v4f(0.1f,0.2f,0.3f,0.4f), 0.f));
REQUIRE(math::contains(v4f(0.1f,0.2f,0.3f,0.4f), 0.f, 0.45f));
REQUIRE(math::contains(v4f(0,1.f,2.f,3.f), 0.f));
REQUIRE(math::contains(v4f(1.f,0,2.f,3.f), 0.f));
REQUIRE(math::contains(v4f(1.f,2.f,0,3.f), 0.f));
REQUIRE(math::contains(v4f(1.f,2.f,3.f,0), 0.f));
REQUIRE(math::contains(v4f(0,0,0,0), 0.f));
}
}

View File

@@ -131,14 +131,6 @@ TEST_CASE("color") {
REQUIRE(math::contains_nan(color(0.f,1.f,std::numeric_limits<f32>::quiet_NaN(),2.f)));
REQUIRE(math::contains_nan(color(std::numeric_limits<f32>::infinity(),1.f,2.f,3.f)));
REQUIRE(math::contains_nan(color(1.f,std::numeric_limits<f32>::infinity(),2.f,3.f)));
REQUIRE_FALSE(math::contains(color(0.1f,0.2f,0.3f,0.4f), 0.f));
REQUIRE(math::contains(color(0.1f,0.2f,0.3f,0.4f), 0.f, 0.45f));
REQUIRE(math::contains(color(0,1.f,2.f,3.f), 0.f));
REQUIRE(math::contains(color(1.f,0,2.f,3.f), 0.f));
REQUIRE(math::contains(color(1.f,2.f,0,3.f), 0.f));
REQUIRE(math::contains(color(1.f,2.f,3.f,0), 0.f));
REQUIRE(math::contains(color(0,0,0,0), 0.f));
}
}
{

View File

@@ -118,15 +118,6 @@ TEST_CASE("color32") {
REQUIRE(math::minimized(c0, color32(2,3,4,5)) == color32(1,2,3,4));
REQUIRE(c0 == color32(1,2,3,4));
}
{
REQUIRE_FALSE(math::contains(color32(1,1,1,1), 0));
REQUIRE(math::contains(color32(1,1,1,1), 0, 1));
REQUIRE(math::contains(color32(0,1,1,1), 0));
REQUIRE(math::contains(color32(1,0,1,1), 0));
REQUIRE(math::contains(color32(1,1,0,1), 0));
REQUIRE(math::contains(color32(1,1,1,0), 0));
REQUIRE(math::contains(color32(0,0,0,0), 0));
}
{
REQUIRE(colors::pack_color32(color32(1,2,3,4)) == 0x04010203);
REQUIRE(colors::pack_color32(color32(0x12,0x34,0x56,0x78)) == 0x78123456);