修改游戏底层矩阵相关

This commit is contained in:
2025-10-26 14:38:53 +08:00
parent dc0213dc16
commit 88f039348a
50 changed files with 1983 additions and 362 deletions

40
source/math/Constants.h Normal file
View File

@@ -0,0 +1,40 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
namespace ember
{
namespace math
{
constexpr auto PI_F = 3.141592653589793f;
constexpr auto PI_F_2 = 1.570796326794896f;
constexpr auto PI_F_X_2 = 6.283185307179586f;
constexpr auto PI_D = 3.14159265358979323846;
constexpr auto PI_D_2 = 1.57079632679489661923;
constexpr auto PI_D_X_2 = 6.28318530717958647692;
constexpr auto FLOAT_MAX = 3.402823466e+38F;
constexpr auto FLOAT_MIN = 1.175494351e-38F;
} // namespace math
} // namespace ember

278
source/math/EaseFunctions.h Normal file
View File

@@ -0,0 +1,278 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <math/Scalar.h>
namespace ember
{
namespace math
{
inline float Linear(float step)
{
return step;
}
// Ease
inline float EaseIn(float step, float rate)
{
return math::Pow(step, rate);
}
inline float EaseOut(float step, float rate)
{
return math::Pow(step, 1.f / rate);
}
inline float EaseInOut(float step, float rate)
{
if (step < .5f)
return .5f * math::Pow(2 * step, rate);
return 1.f - .5f * math::Pow(2.f - 2 * step, rate);
}
// Exponential Ease
inline float EaseExponentialIn(float step)
{
return math::Pow(2.f, 10 * (step - 1));
}
inline float EaseExponentialOut(float step)
{
return 1.f - math::Pow(2.f, -10 * step);
}
inline float EaseExponentialInOut(float step)
{
if (step < .5f)
return .5f * math::Pow(2.f, 10 * (2 * step - 1));
return 0.5f * (2 - math::Pow(2, -10 * (step * 2 - 1)));
}
// Bounce Ease
inline float EaseBounceOut(float step)
{
if (step < 1 / 2.75f)
{
return 7.5625f * step * step;
}
else if (step < 2 / 2.75f)
{
step -= 1.5f / 2.75f;
return 7.5625f * step * step + 0.75f;
}
else if (step < 2.5f / 2.75f)
{
step -= 2.25f / 2.75f;
return 7.5625f * step * step + 0.9375f;
}
step -= 2.625f / 2.75f;
return 7.5625f * step * step + 0.984375f;
}
inline float EaseBounceIn(float step)
{
return 1 - EaseBounceOut(1 - step);
}
inline float EaseBounceInOut(float step)
{
if (step < 0.5f)
{
return EaseBounceIn(step * 2) * 0.5f;
}
else
{
return EaseBounceOut(step * 2 - 1) * 0.5f + 0.5f;
}
}
// Elastic Ease
inline float EaseElasticIn(float step, float period)
{
if (step == 0 || step == 1)
return step;
step = step - 1;
return -math::Pow(2, 10 * step) * math::Sin((step - period / 4) * 360.f / period);
}
inline float EaseElasticOut(float step, float period)
{
if (step == 0 || step == 1)
return step;
return math::Pow(2, -10 * step) * math::Sin((step - period / 4) * 360.f / period) + 1;
}
inline float EaseElasticInOut(float step, float period)
{
if (step == 0 || step == 1)
return step;
step = step * 2 - 1;
if (step < 0)
{
return -0.5f * math::Pow(2, 10 * step) * math::Sin((step - period / 4) * 360.f / period);
}
return math::Pow(2, -10 * step) * math::Sin((step - period / 4) * 360.f / period) * 0.5f + 1;
}
// Back Ease
inline float EaseBackIn(float step)
{
const float overshoot = 1.70158f;
return step * step * ((overshoot + 1) * step - overshoot);
}
inline float EaseBackOut(float step)
{
const float overshoot = 1.70158f;
step = step - 1;
return step * step * ((overshoot + 1) * step + overshoot) + 1;
}
inline float EaseBackInOut(float step)
{
const float overshoot = 1.70158f * 1.525f;
step = step * 2;
if (step < 1)
{
return (step * step * ((overshoot + 1) * step - overshoot)) / 2;
}
step = step - 2;
return (step * step * ((overshoot + 1) * step + overshoot)) / 2 + 1;
}
// Sine Ease
inline float EaseSineIn(float step)
{
return 1.f - math::Cos(step * 90);
}
inline float EaseSineOut(float step)
{
return math::Sin(step * 90);
}
inline float EaseSineInOut(float step)
{
return -0.5f * (math::Cos(step * 180) - 1);
}
// Quad Ease
inline float EaseQuadIn(float step)
{
return step * step;
}
inline float EaseQuadOut(float step)
{
return -1 * step * (step - 2);
}
inline float EaseQuadInOut(float step)
{
step = step * 2;
if (step < 1)
return 0.5f * step * step;
--step;
return -0.5f * (step * (step - 2) - 1);
}
// Cubic Ease
inline float EaseCubicIn(float step)
{
return step * step * step;
}
inline float EaseCubicOut(float step)
{
step -= 1;
return (step * step * step + 1);
}
inline float EaseCubicInOut(float step)
{
step = step * 2;
if (step < 1)
return 0.5f * step * step * step;
step -= 2;
return 0.5f * (step * step * step + 2);
}
// Quart Ease
inline float EaseQuartIn(float step)
{
return step * step * step * step;
}
inline float EaseQuartOut(float step)
{
step -= 1;
return -(step * step * step * step - 1);
}
inline float EaseQuartInOut(float step)
{
step = step * 2;
if (step < 1)
return 0.5f * step * step * step * step;
step -= 2;
return -0.5f * (step * step * step * step - 2);
}
// Quint Ease
inline float EaseQuintIn(float step)
{
return step * step * step * step * step;
}
inline float EaseQuintOut(float step)
{
step -= 1;
return (step * step * step * step * step + 1);
}
inline float EaseQuintInOut(float step)
{
step = step * 2;
if (step < 1)
return 0.5f * step * step * step * step * step;
step -= 2;
return 0.5f * (step * step * step * step * step + 2);
}
} // namespace math
} // namespace ember

153
source/math/Interpolator.h Normal file
View File

@@ -0,0 +1,153 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <core/Function.h>
#include <math/Vec2.hpp>
#include <math/Rect.hpp>
#include <math/Transform.hpp>
namespace ember
{
namespace math
{
template <typename _Method = void>
struct InterpolateMethod;
template <>
struct InterpolateMethod<void>
{
inline float operator()(float frac) const noexcept
{
return frac;
}
};
template <>
struct InterpolateMethod<float (*)(float)>
{
float (*method)(float);
InterpolateMethod(float (*method)(float)) noexcept
: method(method)
{
}
inline float operator()(float frac) const noexcept
{
if (method)
return method(frac);
return frac;
}
};
template <>
struct InterpolateMethod<Function<float(float)>>
{
Function<float(float)> method;
InterpolateMethod(const Function<float(float)> &method) noexcept
: method(method)
{
}
inline float operator()(float frac) const noexcept
{
if (method)
return method(frac);
return frac;
}
};
template <typename _Ty>
class Interpolator;
template <typename _Ty>
class Interpolator
{
public:
template <typename _Method = void>
inline _Ty Interpolate(_Ty start, _Ty end, float frac, const InterpolateMethod<_Method> &method = {})
{
if (frac >= 1)
return end;
return start + static_cast<_Ty>(static_cast<float>(end - start) * method(frac));
}
};
template <typename _Ty>
class Interpolator<Vec2T<_Ty>>
{
public:
template <typename _Method = void>
inline Vec2T<_Ty> Interpolate(const Vec2T<_Ty> &start, const Vec2T<_Ty> &end, float frac,
const InterpolateMethod<_Method> &method = {})
{
if (frac >= 1)
return end;
Interpolator<_Ty> fi;
return Vec2T<_Ty>{fi.Interpolate(start.x, end.x, frac, method), fi.Interpolate(start.y, end.y, frac, method)};
}
};
template <typename _Ty>
class Interpolator<RectT<_Ty>>
{
public:
template <typename _Method = void>
inline RectT<_Ty> Interpolate(const RectT<_Ty> &start, const RectT<_Ty> &end, float frac,
const InterpolateMethod<_Method> &method = {})
{
if (frac >= 1)
return end;
Interpolator<Vec2T<_Ty>> vi;
return RectT<_Ty>{vi.Interpolate(start.left_top, end.left_top, frac, method),
vi.Interpolate(start.right_bottom, end.right_bottom, frac, method)};
}
};
template <typename _Ty>
class Interpolator<TransformT<_Ty>>
{
public:
template <typename _Method = void>
inline TransformT<_Ty> Interpolate(const TransformT<_Ty> &start, const TransformT<_Ty> &end, float frac,
const InterpolateMethod<_Method> &method = {})
{
if (frac >= 1)
return end;
Interpolator<_Ty> fi;
Interpolator<Vec2T<_Ty>> vi;
TransformT<_Ty> transform;
transform.rotation = fi.Interpolate(start.rotation, end.rotation, frac, method);
transform.position = vi.Interpolate(start.position, end.position, frac, method);
transform.scale = vi.Interpolate(start.scale, end.scale, frac, method);
transform.skew = vi.Interpolate(start.skew, end.skew, frac, method);
return transform;
}
};
} // namespace math
} // namespace ember

39
source/math/Math.h Normal file
View File

@@ -0,0 +1,39 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <math/Vec2.hpp>
#include <math/Rect.hpp>
#include <math/Matrix.hpp>
#include <math/Transform.hpp>
#include <math/Constants.h>
#include <math/EaseFunctions.h>
#include <math/Scalar.h>
using Vec2 = ember::math::Vec2T<float>;
using VecPos = ember::math::Vec2T<int>;
using Rect = ember::math::RectT<float>;
using Matrix3x2 = ember::math::Matrix3x2T<float>;
using Transform = ember::math::TransformT<float>;
using GlMatrix = std::array<float, 16>;
using Point = Vec2;
using Size = Vec2;

268
source/math/Matrix.hpp Normal file
View File

@@ -0,0 +1,268 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <algorithm>
#include <math/Rect.hpp>
#include <math/Vec2.hpp>
namespace ember
{
namespace math
{
template <typename _Ty, typename _Lty, typename _Rty>
struct MatrixMultiply;
template <typename _Ty>
struct Matrix3x2T
{
using ValueType = _Ty;
using Vec2Type = Vec2T<ValueType>;
using RectType = RectT<ValueType>;
union
{
struct
{
_Ty m[6]; // m[3][2]
};
struct
{
_Ty _11, _12, _21, _22, _31, _32;
};
};
Matrix3x2T()
: _11(1.f), _12(0.f), _21(0.f), _22(1.f), _31(0.f), _32(0.f)
{
}
Matrix3x2T(ValueType _11, ValueType _12, ValueType _21, ValueType _22, ValueType _31, ValueType _32)
: _11(_11), _12(_12), _21(_21), _22(_22), _31(_31), _32(_32)
{
}
explicit Matrix3x2T(const ValueType *p)
{
for (int i = 0; i < 6; i++)
m[i] = p[i];
}
Matrix3x2T(const Matrix3x2T &other)
: _11(other._11), _12(other._12), _21(other._21), _22(other._22), _31(other._31), _32(other._32)
{
}
template <typename _MTy>
Matrix3x2T(const _MTy &other)
{
for (int i = 0; i < 6; i++)
m[i] = other[i];
}
inline ValueType operator[](uint32_t index) const
{
return m[index];
}
inline ValueType &operator[](uint32_t index)
{
return m[index];
}
inline Matrix3x2T &operator=(const Matrix3x2T &other)
{
for (int i = 0; i < 6; i++)
m[i] = other[i];
return (*this);
}
template <typename _Lty, typename _Rty>
inline Matrix3x2T &operator=(const MatrixMultiply<ValueType, _Lty, _Rty> &other)
{
Matrix3x2T result(other);
(*this) = result;
return (*this);
}
inline Matrix3x2T &operator*=(const Matrix3x2T &other)
{
return operator=((*this) * other);
}
inline void Identity()
{
_11 = 1.f;
_12 = 0.f;
_21 = 0.f;
_22 = 1.f;
_31 = 0.f;
_32 = 0.f;
}
inline bool IsIdentity() const
{
return _11 == 1.f && _12 == 0.f && _21 == 0.f && _22 == 1.f && _31 == 0.f && _32 == 0.f;
}
inline Matrix3x2T Invert() const
{
ValueType det = 1.f / Determinant();
return Matrix3x2T(det * _22, -det * _12, -det * _21, det * _11, det * (_21 * _32 - _22 * _31),
det * (_12 * _31 - _11 * _32));
}
inline bool IsInvertible() const
{
return 0 != Determinant();
}
inline ValueType Determinant() const
{
return (_11 * _22) - (_12 * _21);
}
inline Vec2Type Transform(const Vec2Type &v) const
{
return Vec2Type(v.x * _11 + v.y * _21 + _31, v.x * _12 + v.y * _22 + _32);
}
RectType Transform(const RectType &rect) const
{
Vec2Type top_left = Transform(rect.GetLeftTop());
Vec2Type top_right = Transform(rect.GetRightTop());
Vec2Type bottom_left = Transform(rect.GetLeftBottom());
Vec2Type bottom_right = Transform(rect.GetRightBottom());
ValueType left = (std::min)((std::min)(top_left.x, top_right.x), (std::min)(bottom_left.x, bottom_right.x));
ValueType right = (std::max)((std::max)(top_left.x, top_right.x), (std::max)(bottom_left.x, bottom_right.x));
ValueType top = (std::min)((std::min)(top_left.y, top_right.y), (std::min)(bottom_left.y, bottom_right.y));
ValueType bottom = (std::max)((std::max)(top_left.y, top_right.y), (std::max)(bottom_left.y, bottom_right.y));
return RectType{left, top, right, bottom};
}
inline void Translate(const Vec2Type &v)
{
_31 += _11 * v.x + _21 * v.y;
_32 += _12 * v.x + _22 * v.y;
}
static inline Matrix3x2T Translation(const Vec2Type &v)
{
return Matrix3x2T(1.f, 0.f, 0.f, 1.f, v.x, v.y);
}
static inline Matrix3x2T Scaling(const Vec2Type &v)
{
return Matrix3x2T(v.x, 0.f, 0.f, v.y, 0.f, 0.f);
}
static inline Matrix3x2T Scaling(const Vec2Type &v, const Vec2Type &center)
{
return Matrix3x2T(v.x, 0.f, 0.f, v.y, center.x - v.x * center.x, center.y - v.y * center.y);
}
static inline Matrix3x2T Rotation(ValueType angle)
{
ValueType s = math::Sin(angle);
ValueType c = math::Cos(angle);
return Matrix3x2T(c, s, -s, c, 0.f, 0.f);
}
static inline Matrix3x2T Rotation(ValueType angle, const Vec2Type &center)
{
ValueType s = math::Sin(angle);
ValueType c = math::Cos(angle);
return Matrix3x2T(c, s, -s, c, center.x * (1 - c) + center.y * s, center.y * (1 - c) - center.x * s);
}
static inline Matrix3x2T SRT(const Vec2Type &trans, const Vec2Type &scale, ValueType angle)
{
ValueType s = math::Sin(angle);
ValueType c = math::Cos(angle);
return Matrix3x2T(c * scale.x, s * scale.x, -s * scale.y, c * scale.y, trans.x, trans.y);
}
static inline Matrix3x2T Skewing(const Vec2Type &angle)
{
ValueType tx = math::Tan(angle.x);
ValueType ty = math::Tan(angle.y);
return Matrix3x2T(1.f, -ty, -tx, 1.f, 0.f, 0.f);
}
static inline Matrix3x2T Skewing(const Vec2Type &angle, const Vec2Type &center)
{
ValueType tx = math::Tan(angle.x);
ValueType ty = math::Tan(angle.y);
return Matrix3x2T(1.f, -ty, -tx, 1.f, center.y * tx, center.x * ty);
}
};
// Use template expression to optimize matrix multiply
template <typename _Ty, typename _Lty, typename _Rty>
struct MatrixMultiply
{
const _Lty &lhs;
const _Rty &rhs;
MatrixMultiply(const _Lty &lhs, const _Rty &rhs)
: lhs(lhs), rhs(rhs)
{
}
inline _Ty operator[](uint32_t index) const
{
switch (index)
{
case 0:
return lhs[0] * rhs[0] + lhs[1] * rhs[2];
case 1:
return lhs[0] * rhs[1] + lhs[1] * rhs[3];
case 2:
return lhs[2] * rhs[0] + lhs[3] * rhs[2];
case 3:
return lhs[2] * rhs[1] + lhs[3] * rhs[3];
case 4:
return lhs[4] * rhs[0] + lhs[5] * rhs[2] + rhs[4];
case 5:
return lhs[4] * rhs[1] + lhs[5] * rhs[3] + rhs[5];
default:
return 0.f;
}
}
};
template <typename _Ty>
inline MatrixMultiply<_Ty, Matrix3x2T<_Ty>, Matrix3x2T<_Ty>> operator*(const Matrix3x2T<_Ty> &lhs,
const Matrix3x2T<_Ty> &rhs)
{
return MatrixMultiply<_Ty, Matrix3x2T<_Ty>, Matrix3x2T<_Ty>>(lhs, rhs);
}
template <typename _Ty, typename _Lty, typename _Rty>
inline MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, Matrix3x2T<_Ty>>
operator*(const MatrixMultiply<_Ty, _Lty, _Rty> &lhs, const Matrix3x2T<_Ty> &rhs)
{
return MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, Matrix3x2T<_Ty>>(lhs, rhs);
}
} // namespace math
} // namespace ember

114
source/math/Random.h Normal file
View File

@@ -0,0 +1,114 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <random>
namespace ember
{
namespace math
{
//
// 随机数
//
// 获取指定范围内的一个随机数, 如:
// int n = math::Random(1, 5); // 获取 1~5 内的随机整数, 包含 1 和 5
// 产生的随机数类型取决于参数的类型, 如获取随机浮点数:
// float d = math::Random(1.2f, 1.5f);
//
int Random(int min, int max);
unsigned int Random(unsigned int min, unsigned int max);
long Random(long min, long max);
unsigned long Random(unsigned long min, unsigned long max);
char Random(char min, char max);
float Random(float min, float max);
double Random(double min, double max);
//
// Details of math::Rand
//
namespace __rand_detail
{
inline std::default_random_engine &GetRandomEngine()
{
static std::random_device device;
static std::default_random_engine engine(device());
return engine;
}
template <typename T>
inline T RandomInt(T min, T max)
{
std::uniform_int_distribution<T> dist(min, max);
return dist(GetRandomEngine());
}
template <typename T>
inline T RandomReal(T min, T max)
{
std::uniform_real_distribution<T> dist(min, max);
return dist(GetRandomEngine());
}
} // namespace __rand_detail
inline int Random(int min, int max)
{
return __rand_detail::RandomInt(min, max);
}
inline unsigned int Random(unsigned int min, unsigned int max)
{
return __rand_detail::RandomInt(min, max);
}
inline long Random(long min, long max)
{
return __rand_detail::RandomInt(min, max);
}
inline unsigned long Random(unsigned long min, unsigned long max)
{
return __rand_detail::RandomInt(min, max);
}
inline char Random(char min, char max)
{
return static_cast<char>(__rand_detail::RandomInt(static_cast<int>(min), static_cast<int>(max)));
}
inline float Random(float min, float max)
{
return __rand_detail::RandomReal(min, max);
}
inline double Random(double min, double max)
{
return __rand_detail::RandomReal(min, max);
}
} // namespace math
} // namespace ember

154
source/math/Rect.hpp Normal file
View File

@@ -0,0 +1,154 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <math/Vec2.hpp>
namespace ember
{
namespace math
{
template <typename _Ty>
struct RectT
{
public:
using ValueType = _Ty;
Vec2T<ValueType> left_top;
Vec2T<ValueType> right_bottom;
public:
RectT() {}
RectT(ValueType left, ValueType top, ValueType right, ValueType bottom)
: left_top(left, top), right_bottom(right, bottom)
{
}
RectT(const Vec2T<ValueType> &left_top, const Vec2T<ValueType> &right_bottom)
: left_top(left_top), right_bottom(right_bottom)
{
}
RectT(const RectT &other)
: left_top(other.left_top), right_bottom(other.right_bottom)
{
}
RectT &operator=(const RectT &other)
{
left_top = other.left_top;
right_bottom = other.right_bottom;
return *this;
}
inline bool operator==(const RectT &rect) const
{
return (left_top == rect.left_top) && (right_bottom == rect.right_bottom);
}
inline void Set(ValueType left, ValueType top, ValueType right, ValueType bottom)
{
left_top = Vec2T<ValueType>{left, top};
right_bottom = Vec2T<ValueType>{right, bottom};
}
inline Vec2T<ValueType> GetCenter() const
{
return Vec2T<ValueType>{(left_top.x + right_bottom.x) / 2, (left_top.y + right_bottom.y) / 2};
}
inline Vec2T<ValueType> GetLeftTop() const
{
return left_top;
}
inline Vec2T<ValueType> GetRightBottom() const
{
return right_bottom;
}
inline Vec2T<ValueType> GetRightTop() const
{
return Vec2T<ValueType>{right_bottom.x, left_top.y};
}
inline Vec2T<ValueType> GetLeftBottom() const
{
return Vec2T<ValueType>{left_top.x, right_bottom.y};
}
inline ValueType GetLeft() const
{
return left_top.x;
}
inline ValueType GetTop() const
{
return left_top.y;
}
inline ValueType GetRight() const
{
return right_bottom.x;
}
inline ValueType GetBottom() const
{
return right_bottom.y;
}
inline ValueType GetWidth() const
{
return right_bottom.x - left_top.x;
}
inline ValueType GetHeight() const
{
return right_bottom.y - left_top.y;
}
inline Vec2T<ValueType> GetSize() const
{
return Vec2T<ValueType>{GetWidth(), GetHeight()};
}
inline bool IsEmpty() const
{
return left_top.IsOrigin() && right_bottom.IsOrigin();
}
inline bool ContainsPoint(const Vec2T<ValueType> &point) const
{
return point.x >= left_top.x && point.x <= right_bottom.x && point.y >= left_top.y && point.y <= right_bottom.y;
}
inline bool Intersects(const RectT &rect) const
{
return !(right_bottom.x < rect.left_top.x || rect.right_bottom.x < left_top.x || right_bottom.y < rect.left_top.y || rect.right_bottom.y < left_top.y);
}
static inline RectT Infinite()
{
return RectT{-math::FLOAT_MAX, -math::FLOAT_MAX, math::FLOAT_MAX, math::FLOAT_MAX};
}
};
} // namespace math
} // namespace ember

165
source/math/Scalar.h Normal file
View File

@@ -0,0 +1,165 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <cmath>
#include <math/Constants.h>
namespace ember
{
namespace math
{
inline int Abs(int val)
{
return ::abs(val);
}
inline float Abs(float val)
{
return ::fabsf(val);
}
inline double Abs(double val)
{
return ::fabs(val);
}
inline float Sqrt(float val)
{
return ::sqrtf(val);
}
inline double Sqrt(double val)
{
return ::sqrt(val);
}
inline float Pow(float core, float exponent)
{
return ::powf(core, exponent);
}
inline double Pow(double core, double exponent)
{
return ::pow(core, exponent);
}
inline int Sign(int val)
{
return val < 0 ? -1 : 1;
}
inline float Sign(float val)
{
return val < 0 ? -1.f : 1.f;
}
inline double Sign(double val)
{
return val < 0 ? -1.0 : 1.0;
}
inline float Degree2Radian(float angle)
{
return angle * math::PI_F / 180.f;
}
inline double Degree2Radian(double angle)
{
return angle * math::PI_D / 180.0;
}
inline float Radian2Degree(float radian)
{
return radian * 180.f / math::PI_F;
}
inline double Radian2Degree(double radian)
{
return radian * 180.0 / math::PI_D;
}
inline float Sin(float val)
{
return ::sinf(Degree2Radian(val));
}
inline double Sin(double val)
{
return ::sin(Degree2Radian(val));
}
inline float Cos(float val)
{
return ::cosf(Degree2Radian(val));
}
inline double Cos(double val)
{
return ::cos(Degree2Radian(val));
}
inline float Tan(float val)
{
return ::tanf(Degree2Radian(val));
}
inline double Tan(double val)
{
return ::tan(Degree2Radian(val));
}
inline float Asin(float val)
{
return Radian2Degree(::asinf(val));
}
inline double Asin(double val)
{
return Radian2Degree(::asin(val));
}
inline float Acos(float val)
{
return Radian2Degree(::acosf(val));
}
inline double Acos(double val)
{
return Radian2Degree(::acos(val));
}
inline float Atan(float val)
{
return Radian2Degree(::atanf(val));
}
inline double Atan(double val)
{
return Radian2Degree(::atan(val));
}
inline float Ceil(float val)
{
return ::ceil(val);
}
inline double Ceil(double val)
{
return ::ceil(val);
}
inline float Floor(float val)
{
return ::floor(val);
}
inline double Floor(double val)
{
return ::floor(val);
}
} // namespace math
} // namespace ember

86
source/math/Transform.hpp Normal file
View File

@@ -0,0 +1,86 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <math/Vec2.hpp>
#include <math/Matrix.hpp>
namespace ember
{
namespace math
{
/**
* \~chinese
* @brief ¶þά·ÅÉä±ä»»
*/
template <typename _Ty>
class TransformT
{
public:
using ValueType = _Ty;
float rotation; ///< Ðýת
Vec2T<ValueType> position; ///< ×ø±ê
Vec2T<ValueType> scale; ///< Ëõ·Å
Vec2T<ValueType> skew; ///< ´íÇнǶÈ
public:
TransformT();
/// \~chinese
/// @brief ½«¶þά·ÅÉä±ä»»×ª»»Îª¾ØÕó
Matrix3x2T<ValueType> ToMatrix() const;
bool IsFast() const;
bool operator==(const TransformT &rhs) const;
};
template <typename _Ty>
inline TransformT<_Ty>::TransformT()
: position(), rotation(0.f), scale(1.f, 1.f), skew(0.f, 0.f)
{
}
template <typename _Ty>
Matrix3x2T<_Ty> TransformT<_Ty>::ToMatrix() const
{
if (!skew.IsOrigin())
{
return Matrix3x2T<_Ty>::Skewing(skew) * Matrix3x2T<_Ty>::SRT(position, scale, rotation);
}
return Matrix3x2T<_Ty>::SRT(position, scale, rotation);
}
template <typename _Ty>
inline bool TransformT<_Ty>::IsFast() const
{
return skew.x == 0.f && skew.y == 0.f && scale.x == 1.f && scale.y == 1.f && rotation == 0.f;
}
template <typename _Ty>
bool TransformT<_Ty>::operator==(const TransformT &rhs) const
{
return position == rhs.position && rotation == rhs.rotation && scale == rhs.scale && skew == rhs.skew;
}
} // namespace math
} // namespace ember

136
source/math/Vec2.hpp Normal file
View File

@@ -0,0 +1,136 @@
// Copyright (c) 2016-2018 Ember - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <math/Scalar.h>
namespace ember
{
namespace math
{
template <typename _Ty>
struct Vec2T
{
using ValueType = _Ty;
ValueType x;
ValueType y;
Vec2T()
: x(ValueType(0)), y(ValueType(0))
{
}
Vec2T(ValueType x, ValueType y)
: x(x), y(y)
{
}
Vec2T(const Vec2T &other)
: x(other.x), y(other.y)
{
}
inline ValueType Length() const
{
return static_cast<ValueType>(math::Sqrt(static_cast<float>(x * x + y * y)));
}
inline bool IsOrigin() const
{
return (x == 0) && (y == 0);
}
inline void Set(ValueType x, ValueType y)
{
this->x = x;
this->y = y;
}
inline const Vec2T operator+(const Vec2T &other) const
{
return Vec2T(x + other.x, y + other.y);
}
inline const Vec2T operator-(const Vec2T &other) const
{
return Vec2T(x - other.x, y - other.y);
}
inline const Vec2T operator*(ValueType val) const
{
return Vec2T(x * val, y * val);
}
inline const Vec2T operator*(const Vec2T &other) const
{
return Vec2T(x * other.x, y * other.y);
}
inline const Vec2T operator/(ValueType val) const
{
return Vec2T(x / val, y / val);
}
inline const Vec2T operator-() const
{
return Vec2T(-x, -y);
}
inline Vec2T &operator+=(const Vec2T &other)
{
x += other.x;
y += other.y;
return (*this);
}
inline Vec2T &operator-=(const Vec2T &other)
{
x -= other.x;
y -= other.y;
return (*this);
}
inline Vec2T &operator*=(ValueType val)
{
x *= val;
y *= val;
return (*this);
}
inline Vec2T &operator/=(ValueType val)
{
x /= val;
y /= val;
return (*this);
}
inline bool operator==(const Vec2T &other) const
{
return (x == other.x) && (y == other.y);
}
inline bool operator!=(const Vec2T &other) const
{
return (x != other.x) || (y != other.y);
}
};
} // namespace math
} // namespace ember