optimize: use expression template to calculate matrixs multiply

This commit is contained in:
Haibo 2018-11-15 01:02:05 +08:00 committed by Nomango
parent 32ecc0cbe8
commit 4ce0a470de
12 changed files with 202 additions and 123 deletions

View File

@ -75,7 +75,7 @@ namespace easy2d
this->Reset();
}
virtual void Init(Node* target) {}
virtual void Init(Node* target) { initialized_ = true; }
virtual void Update(Node* target, Duration const& dt)
{

View File

@ -356,8 +356,8 @@ namespace easy2d
RotateBy::RotateBy(Duration const& duration, float rotation)
: FiniteTimeAction(duration)
, delta_val_(rotation)
{
delta_val_ = rotation;
}
void RotateBy::Init(Node* target)

View File

@ -68,12 +68,14 @@ namespace easy2d
bool Image::Load(Resource& res)
{
HRESULT hr = devices::Graphics::Instance().CreateBitmapFromResource(res, &bitmap_);
ID2D1Bitmap* bitmap;
HRESULT hr = devices::Graphics::Instance().CreateBitmapFromResource(res, &bitmap);
if (FAILED(hr))
{
logs::Trace(L"Load Image from resource failed!", hr);
return false;
}
this->SetBitmap(bitmap);
return true;
}
@ -92,12 +94,14 @@ namespace easy2d
// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
String image_file_path = image_file.GetPath();
HRESULT hr = devices::Graphics::Instance().CreateBitmapFromFile(image_file_path, &bitmap_);
ID2D1Bitmap* bitmap;
HRESULT hr = devices::Graphics::Instance().CreateBitmapFromFile(image_file_path, &bitmap);
if (FAILED(hr))
{
logs::Trace(L"Load Image from file failed!", hr);
return false;
}
this->SetBitmap(bitmap);
return true;
}

View File

@ -19,6 +19,7 @@
// THE SOFTWARE.
#include "input.h"
#include <cstring>
namespace easy2d
{
@ -28,6 +29,7 @@ namespace easy2d
: initialized(false)
{
ZeroMemory(keys_, sizeof(keys_));
ZeroMemory(keys_cache_, sizeof(keys_cache_));
}
InputDevice::~InputDevice()
@ -44,11 +46,12 @@ namespace easy2d
void InputDevice::Update(HWND hwnd, float scale_x, float scale_y)
{
::GetKeyboardState(keys_);
memcpy(keys_cache_, keys_, sizeof(keys_cache_));
GetKeyboardState(keys_);
POINT client_cursor_pos;
::GetCursorPos(&client_cursor_pos);
::ScreenToClient(hwnd, &client_cursor_pos);
GetCursorPos(&client_cursor_pos);
ScreenToClient(hwnd, &client_cursor_pos);
mouse_pos_ = Point(client_cursor_pos.x * scale_x, client_cursor_pos.y * scale_y);
}
@ -67,6 +70,22 @@ namespace easy2d
return false;
}
bool InputDevice::WasPressed(KeyCode code)
{
if (keys_cache_[static_cast<int>(code)] & 0x80 &&
!(keys_[static_cast<int>(code)] & 0x80))
return true;
return false;
}
bool InputDevice::WasPressed(MouseCode code)
{
if (keys_cache_[static_cast<int>(code)] & 0x80 &&
!(keys_[static_cast<int>(code)] & 0x80))
return true;
return false;
}
float InputDevice::GetMouseX()
{
return mouse_pos_.x;

View File

@ -45,6 +45,16 @@ namespace easy2d
MouseCode code
);
// 检测键盘某按键是否点击
bool WasPressed(
KeyCode code
);
// 检测鼠标按键是否点击
bool WasPressed(
MouseCode code
);
// 資誼報炎X已恫炎峙
float GetMouseX();
@ -69,6 +79,7 @@ namespace easy2d
protected:
bool initialized;
BYTE keys_[256];
BYTE keys_cache_[256];
Point mouse_pos_;
};

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include <cassert>
#include "macros.h"
namespace easy2d
{
@ -51,7 +51,11 @@ namespace easy2d
IntrusivePtrAddRef(ptr_);
}
IntrusivePtr(IntrusivePtr&& other) : ptr_(::std::move(other.ptr_)) {}
IntrusivePtr(IntrusivePtr&& other)
{
ptr_ = other.ptr_;
other.ptr_ = nullptr;
}
~IntrusivePtr()
{
@ -67,14 +71,14 @@ namespace easy2d
inline ElemType* operator ->() const
{
assert(ptr_ && ptr_->GetRefCount() > 0 &&
E2D_WARNING_IF(!ptr_ || ptr_->GetRefCount() <= 0,
"Invalid pointer!");
return ptr_;
}
inline ElemType& operator *() const
{
assert(ptr_ && ptr_->GetRefCount() > 0 &&
E2D_WARNING_IF(!ptr_ || ptr_->GetRefCount() <= 0,
"Invalid pointer!");
return *ptr_;
}
@ -89,6 +93,14 @@ namespace easy2d
return *this;
}
inline IntrusivePtr& operator =(IntrusivePtr&& other)
{
IntrusivePtrRelease(ptr_);
ptr_ = other.ptr_;
other.ptr_ = nullptr;
return *this;
}
inline IntrusivePtr& operator =(ElemType* p)
{
IntrusivePtr(p).Swap(*this);

View File

@ -23,7 +23,6 @@
#include "Task.h"
#include "Action.hpp"
#include "render.h"
#include <iterator>
namespace easy2d
{
@ -56,14 +55,16 @@ namespace easy2d
if (!visible_)
return;
auto& graphics = devices::Graphics::Instance();
if (clip_enabled_)
{
devices::Graphics::Instance().PushClip(final_matrix_, transform_.size);
graphics.PushClip(final_matrix_, transform_.size);
}
if (children_.empty())
{
devices::Graphics::Instance().SetTransform(final_matrix_);
graphics.SetTransform(final_matrix_);
OnDraw();
}
else
@ -72,8 +73,8 @@ namespace easy2d
if (dirty_sort_)
{
std::sort(
std::begin(children_),
std::end(children_),
children_.begin(),
children_.end(),
[](spNode const& n1, spNode const& n2) { return n1->GetOrder() < n2->GetOrder(); }
);
@ -95,7 +96,7 @@ namespace easy2d
}
}
devices::Graphics::Instance().SetTransform(final_matrix_);
graphics.SetTransform(final_matrix_);
OnDraw();
// 访问剩余节点
@ -105,7 +106,7 @@ namespace easy2d
if (clip_enabled_)
{
devices::Graphics::Instance().PopClip();
graphics.PopClip();
}
}
@ -170,13 +171,9 @@ namespace easy2d
dirty_transform_ = false;
final_matrix_ = transform_.ToMatrix();
// 根据自身支点计算 Initial 矩阵,子节点将根据这个矩阵进行变换
auto pivot = Point(
transform_.size.width * transform_.pivot.x,
transform_.size.height * transform_.pivot.y
initial_matrix_ = final_matrix_ * math::Matrix::Translation(
Point{ transform_.size.width * transform_.pivot.x, transform_.size.height * transform_.pivot.y }
);
initial_matrix_ = final_matrix_ * math::Matrix::Translation(pivot);
if (parent_)
{
@ -186,13 +183,11 @@ namespace easy2d
// 重新构造轮廓
SafeRelease(border_);
ThrowIfFailed(
devices::Graphics::Instance().CreateRectGeometry(final_matrix_, transform_.size, &border_)
);
// 通知子节点进行转换
for (const auto& child : children_)
for (auto& child : children_)
{
child->dirty_transform_ = true;
}

View File

@ -85,8 +85,10 @@
#if VS_VER >= VS_2015
# define E2D_NOEXCEPT noexcept
# define E2D_CONSTEXPR constexpr
#else
# define E2D_NOEXCEPT throw()
# define E2D_CONSTEXPR const
#endif

View File

@ -26,127 +26,105 @@ namespace easy2d
{
namespace math
{
class Matrix;
template <typename L, typename R>
struct MatrixMultiply;
inline MatrixMultiply<Matrix, Matrix>
operator *(Matrix const& lhs, Matrix const& rhs);
template <typename L, typename R>
inline MatrixMultiply<MatrixMultiply<L, R>, Matrix>
operator *(MatrixMultiply<L, R> const& lhs, Matrix const& rhs);
class Matrix
{
float _11;
float _12;
float _21;
float _22;
float _31;
float _32;
float m[6]; // m[3][2]
public:
Matrix()
: _11(1.f)
, _12(0.f)
, _21(0.f)
, _22(1.f)
, _31(0.f)
, _32(0.f)
{
m[0] = 1.f; m[1] = 0.f;
m[2] = 0.f; m[3] = 1.f;
m[4] = 0.f; m[5] = 0.f;
}
Matrix(
float _11,
float _12,
float _21,
float _22,
float _31,
float _32)
Matrix(float val[6])
{
this->_11 = _11;
this->_12 = _12;
this->_21 = _21;
this->_22 = _22;
this->_31 = _31;
this->_32 = _32;
m[0] = val[0]; m[1] = val[1];
m[2] = val[2]; m[3] = val[3];
m[4] = val[4]; m[5] = val[5];
}
inline const Matrix operator*(const Matrix &matrix) const
Matrix(float _11, float _12, float _21, float _22, float _31, float _32)
{
return Matrix(
_11 * matrix._11 + _12 * matrix._21,
_11 * matrix._12 + _12 * matrix._22,
_21 * matrix._11 + _22 * matrix._21,
_21 * matrix._12 + _22 * matrix._22,
_31 * matrix._11 + _32 * matrix._21 + matrix._31,
_31 * matrix._12 + _32 * matrix._22 + matrix._32
);
m[0] = _11; m[1] = _12;
m[2] = _21; m[3] = _22;
m[4] = _31; m[5] = _32;
}
Matrix(Matrix const& other)
{
m[0] = other.m[0]; m[1] = other.m[1];
m[2] = other.m[2]; m[3] = other.m[3];
m[4] = other.m[4]; m[5] = other.m[5];
}
template <typename T>
Matrix(T const& other)
{
m[0] = other[0]; m[1] = other[1];
m[2] = other[2]; m[3] = other[3];
m[4] = other[4]; m[5] = other[5];
}
inline float operator [](unsigned int index) const { return m[index]; }
template <typename T>
inline Matrix& operator =(T const& other)
{
m[0] = other[0]; m[1] = other[1];
m[2] = other[2]; m[3] = other[3];
m[4] = other[4]; m[5] = other[5];
return *this;
}
inline operator D2D1_MATRIX_3X2_F () const
{
return D2D1_MATRIX_3X2_F{
_11, _12,
_21, _22,
_31, _32
m[0], m[1],
m[2], m[3],
m[4], m[5]
};
}
inline Matrix& Identity()
{
_11 = 1.f;
_12 = 0.f;
_21 = 0.f;
_22 = 1.f;
_31 = 0.f;
_32 = 0.f;
return *this;
}
inline Matrix& Translate(const Vector2& v)
{
*this = *this * Matrix::Translation(v);
return *this;
}
inline Matrix& Translate(float x, float y)
{
*this = *this * Matrix::Translation(x, y);
return *this;
}
inline Matrix& Scale(const Vector2& v, const Vector2& center)
{
*this = *this * Matrix::Scaling(v, center);
return *this;
}
inline Matrix& Scale(float scale_x, float scale_y, const Vector2& center)
{
*this = *this * Matrix::Scaling(scale_x, scale_y, center);
return *this;
}
inline Matrix& Rotate(float angle, const Vector2& center)
{
*this = *this * Matrix::Rotation(angle, center);
return *this;
}
inline Matrix& Skew(float angle_x, float angle_y, const Vector2& center)
{
*this = *this * Matrix::Skewing(angle_x, angle_y, center);
m[0] = 1.f; m[1] = 0.f;
m[2] = 0.f; m[3] = 1.f;
m[4] = 0.f; m[5] = 0.f;
return *this;
}
inline float Determinant() const
{
return (_11 * _22) - (_12 * _21);
return (m[0] * m[3]) - (m[1] * m[2]);
}
inline bool IsIdentity() const
{
return _11 == 1.f && _12 == 0.f &&
_21 == 0.f && _22 == 1.f &&
_31 == 0.f && _32 == 0.f;
return m[0] == 1.f && m[1] == 0.f &&
m[2] == 0.f && m[3] == 1.f &&
m[4] == 0.f && m[5] == 0.f;
}
Vector2 Transform(const Vector2& v) const
{
return Vector2(
v.x * _11 + v.y * _21 + _31,
v.x * _12 + v.y * _22 + _32
v.x * m[0] + v.y * m[2] + m[4],
v.x * m[1] + v.y * m[3] + m[5]
);
}
@ -214,5 +192,50 @@ namespace easy2d
);
}
};
template <typename L, typename R>
struct MatrixMultiply
{
L const& lhs;
R const& rhs;
MatrixMultiply(L const& lhs, R const& rhs)
: lhs(lhs)
, rhs(rhs)
{}
inline float operator [](unsigned int 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;
}
}
};
inline MatrixMultiply<Matrix, Matrix> operator *(Matrix const& lhs, Matrix const& rhs)
{
return MatrixMultiply<Matrix, Matrix>(lhs, rhs);
}
template <typename L, typename R>
inline MatrixMultiply<MatrixMultiply<L, R>, Matrix> operator *(MatrixMultiply<L, R> const& lhs, Matrix const& rhs)
{
return MatrixMultiply<MatrixMultiply<L, R>, Matrix>(lhs, rhs);
}
}
}

View File

@ -49,10 +49,10 @@ namespace easy2d
inline Matrix ToMatrix() const
{
auto center = Vector2{ size.width * pivot.x, size.height * pivot.y };
return Matrix{}.Scale(scale.x, scale.y, center)
.Skew(skew.x, skew.y, center)
.Rotate(rotation, center)
.Translate(position - center);
return Matrix{} * Matrix::Scaling(scale.x, scale.y, center)
* Matrix::Skewing(skew.x, skew.y, center)
* Matrix::Rotation(rotation, center)
* Matrix::Translation(position - center);
}
bool operator== (const Transform& other) const

View File

@ -21,10 +21,23 @@
#pragma once
#include <cmath>
#if _MSC_VER >= 1900
# define E2D_CONSTEXPR constexpr
#else
# define E2D_CONSTEXPR const
#endif
namespace easy2d
{
namespace math
{
namespace constants
{
E2D_CONSTEXPR auto PIf = 3.14159265358979f;
E2D_CONSTEXPR auto PId = 3.14159265358979323846;
}
inline int Abs(int val) { return ::abs(val); }
inline float Abs(float val) { return ::fabsf(val); }
@ -41,17 +54,17 @@ namespace easy2d
inline double Sign(double val) { return val < 0 ? -1.0 : 1.0; }
inline float Sin(float val) { return ::sinf(val); }
inline float Sin(float val) { return ::sinf(val * constants::PIf / 180.f); }
inline double Sin(double val) { return ::sin(val); }
inline double Sin(double val) { return ::sin(val * constants::PId / 180.0); }
inline float Cos(float val) { return ::cosf(val); }
inline float Cos(float val) { return ::cosf(val * constants::PIf / 180.f); }
inline double Cos(double val) { return ::cos(val); }
inline double Cos(double val) { return ::cos(val * constants::PId / 180.0); }
inline float Tan(float val) { return ::tanf(val); }
inline float Tan(float val) { return ::tanf(val * constants::PIf / 180.f); }
inline double Tan(double val) { return ::tan(val); }
inline double Tan(double val) { return ::tan(val * constants::PId / 180.0); }
inline float Ceil(float val) { return ::ceil(val); }

View File

@ -160,7 +160,7 @@ namespace easy2d
auto iter = std::find(search_paths_.cbegin(), search_paths_.cend(), tmp);
if (iter == search_paths_.cend())
{
search_paths_.push_front(path);
search_paths_.push_front(tmp);
}
}