update Geometry

This commit is contained in:
Nomango 2019-08-14 23:36:29 +08:00
parent 0583ad8839
commit d34e14b799
12 changed files with 249 additions and 80 deletions

View File

@ -201,13 +201,13 @@ namespace kiwano
EventDispatcher::Dispatch(evt);
}
Matrix const & Actor::GetTransformMatrix() const
Matrix3x2 const & Actor::GetTransformMatrix() const
{
UpdateTransform();
return transform_matrix_;
}
Matrix const & Actor::GetTransformInverseMatrix() const
Matrix3x2 const & Actor::GetTransformInverseMatrix() const
{
UpdateTransform();
if (dirty_transform_inverse_)
@ -228,16 +228,16 @@ namespace kiwano
if (is_fast_transform_)
{
transform_matrix_ = Matrix::Translation(transform_.position);
transform_matrix_ = Matrix3x2::Translation(transform_.position);
}
else
{
// matrix multiplication is optimized by expression template
transform_matrix_ = Matrix::SRT(transform_.position, transform_.scale, transform_.rotation);
transform_matrix_ = Matrix3x2::SRT(transform_.position, transform_.scale, transform_.rotation);
if (!transform_.skew.IsOrigin())
{
transform_matrix_ = Matrix::Skewing(transform_.skew) * transform_matrix_;
transform_matrix_ = Matrix3x2::Skewing(transform_.skew) * transform_matrix_;
}
}

View File

@ -142,10 +142,10 @@ namespace kiwano
virtual Rect GetBoundingBox() const;
// 获取二维变换矩阵
Matrix const& GetTransformMatrix() const;
Matrix3x2 const& GetTransformMatrix() const;
// 获取二维变换的逆矩阵
Matrix const& GetTransformInverseMatrix() const;
Matrix3x2 const& GetTransformInverseMatrix() const;
// 获取父角色
inline Actor* GetParent() const { return parent_; }
@ -447,8 +447,8 @@ namespace kiwano
bool is_fast_transform_;
mutable bool dirty_transform_;
mutable bool dirty_transform_inverse_;
mutable Matrix transform_matrix_;
mutable Matrix transform_matrix_inverse_;
mutable Matrix3x2 transform_matrix_;
mutable Matrix3x2 transform_matrix_inverse_;
};
}

View File

@ -161,7 +161,7 @@ namespace kiwano
return stroke_width_;
}
void Canvas::SetBrushTransform(Matrix const & transform)
void Canvas::SetBrushTransform(Matrix3x2 const & transform)
{
render_target_->SetTransform(DX::ConvertToMatrix3x2F(transform));
}

View File

@ -205,7 +205,7 @@ namespace kiwano
// 变换画笔
void SetBrushTransform(
Matrix const& transform
Matrix3x2 const& transform
);
// 导出为图片

View File

@ -47,7 +47,7 @@ namespace kiwano
if (!geo_)
return Rect{};
return geo_.GetBoundingBox(Matrix());
return geo_.GetBoundingBox(Matrix3x2());
}
Rect ShapeActor::GetBoundingBox() const
@ -117,7 +117,7 @@ namespace kiwano
void LineActor::SetEndPoint(Point const& end)
{
Renderer::GetInstance()->CreateLineGeometry(geo_, Point{}, end);
geo_ = Geometry::CreateLine(Point{}, end);
if (geo_)
{
@ -145,7 +145,7 @@ namespace kiwano
void RectActor::SetRectSize(Size const& size)
{
Renderer::GetInstance()->CreateRectGeometry(geo_, Rect{ Point{}, size });
geo_ = Geometry::CreateRect(Rect{ Point{}, size });
if (geo_)
{
@ -183,7 +183,7 @@ namespace kiwano
void RoundRectActor::SetRoundedRect(Size const& size, Vec2 const& radius)
{
Renderer::GetInstance()->CreateRoundedRectGeometry(geo_, Rect{ Point{}, size }, radius);
geo_ = Geometry::CreateRoundedRect(Rect{ Point{}, size }, radius);
if (geo_)
{
@ -212,7 +212,7 @@ namespace kiwano
void CircleActor::SetRadius(float radius)
{
Renderer::GetInstance()->CreateEllipseGeometry(geo_, Point{}, Vec2{ radius, radius });
geo_ = Geometry::CreateCircle(Point{}, radius);
if (geo_)
{
@ -240,7 +240,7 @@ namespace kiwano
void EllipseActor::SetRadius(Vec2 const& radius)
{
Renderer::GetInstance()->CreateEllipseGeometry(geo_, Point{}, radius);
geo_ = Geometry::CreateEllipse(Point{}, radius);
if (geo_)
{

View File

@ -86,7 +86,6 @@ namespace kiwano
target->SetRotation(rotation);
}
}
KGE_LOG(L"%.2f, %.2f", target->GetPositionX(), target->GetPositionY());
}
void ActionWalk::BeginPath()

View File

@ -31,7 +31,7 @@ namespace kiwano
struct MatrixMultiply;
template <typename _Ty>
struct MatrixT
struct Matrix3x2T
{
using value_type = _Ty;
using vec2_type = Vec2T<value_type>;
@ -53,25 +53,25 @@ namespace kiwano
};
};
MatrixT()
Matrix3x2T()
: _11(1.f), _12(0.f)
, _21(0.f), _22(1.f)
, _31(0.f), _32(0.f)
{
}
MatrixT(value_type _11, value_type _12, value_type _21, value_type _22, value_type _31, value_type _32)
Matrix3x2T(value_type _11, value_type _12, value_type _21, value_type _22, value_type _31, value_type _32)
: _11(_11), _12(_12), _21(_21), _22(_22), _31(_31), _32(_32)
{
}
explicit MatrixT(const value_type* p)
explicit Matrix3x2T(const value_type* p)
{
for (int i = 0; i < 6; i++)
m[i] = p[i];
}
MatrixT(MatrixT const& other)
Matrix3x2T(Matrix3x2T const& other)
: _11(other._11), _12(other._12)
, _21(other._21), _22(other._22)
, _31(other._31), _32(other._32)
@ -79,7 +79,7 @@ namespace kiwano
}
template <typename _MTy>
MatrixT(_MTy const& other)
Matrix3x2T(_MTy const& other)
{
for (int i = 0; i < 6; i++)
m[i] = other[i];
@ -95,7 +95,7 @@ namespace kiwano
return m[index];
}
inline MatrixT& operator= (MatrixT const& other)
inline Matrix3x2T& operator= (Matrix3x2T const& other)
{
for (int i = 0; i < 6; i++)
m[i] = other[i];
@ -103,14 +103,14 @@ namespace kiwano
}
template <typename _Lty, typename _Rty>
inline MatrixT& operator= (MatrixMultiply<value_type, _Lty, _Rty> const& other)
inline Matrix3x2T& operator= (MatrixMultiply<value_type, _Lty, _Rty> const& other)
{
MatrixT result(other);
Matrix3x2T result(other);
(*this) = result;
return (*this);
}
inline MatrixT& operator*= (MatrixT const& other)
inline Matrix3x2T& operator*= (Matrix3x2T const& other)
{
return operator=((*this) * other);
}
@ -129,10 +129,10 @@ namespace kiwano
_31 == 0.f && _32 == 0.f;
}
inline MatrixT Invert() const
inline Matrix3x2T Invert() const
{
value_type det = 1.f / Determinant();
return MatrixT(
return Matrix3x2T(
det * _22,
-det * _12,
-det * _21,
@ -181,29 +181,29 @@ namespace kiwano
_32 += _12 * v.x + _22 * v.y;
}
static inline MatrixT Translation(const vec2_type& v)
static inline Matrix3x2T Translation(const vec2_type& v)
{
return MatrixT(
return Matrix3x2T(
1.f, 0.f,
0.f, 1.f,
v.x, v.y
);
}
static inline MatrixT Scaling(const vec2_type& v)
static inline Matrix3x2T Scaling(const vec2_type& v)
{
return MatrixT(
return Matrix3x2T(
v.x, 0.f,
0.f, v.y,
0.f, 0.f
);
}
static inline MatrixT Scaling(
static inline Matrix3x2T Scaling(
const vec2_type& v,
const vec2_type& center)
{
return MatrixT(
return Matrix3x2T(
v.x, 0.f,
0.f, v.y,
center.x - v.x * center.x,
@ -211,24 +211,24 @@ namespace kiwano
);
}
static inline MatrixT Rotation(value_type angle)
static inline Matrix3x2T Rotation(value_type angle)
{
value_type s = math::Sin(angle);
value_type c = math::Cos(angle);
return MatrixT(
return Matrix3x2T(
c, s,
-s, c,
0.f, 0.f
);
}
static inline MatrixT Rotation(
static inline Matrix3x2T Rotation(
value_type angle,
const vec2_type& center)
{
value_type s = math::Sin(angle);
value_type c = math::Cos(angle);
return MatrixT(
return Matrix3x2T(
c, s,
-s, c,
center.x * (1 - c) + center.y * s,
@ -236,35 +236,35 @@ namespace kiwano
);
}
static inline MatrixT SRT(const vec2_type& trans, const vec2_type& scale, value_type angle)
static inline Matrix3x2T SRT(const vec2_type& trans, const vec2_type& scale, value_type angle)
{
value_type s = math::Sin(angle);
value_type c = math::Cos(angle);
return MatrixT(
return Matrix3x2T(
c * scale.x, s * scale.x,
-s * scale.y, c * scale.y,
trans.x, trans.y
);
}
static inline MatrixT Skewing(const vec2_type& angle)
static inline Matrix3x2T Skewing(const vec2_type& angle)
{
value_type tx = math::Tan(angle.x);
value_type ty = math::Tan(angle.y);
return MatrixT(
return Matrix3x2T(
1.f, -ty,
-tx, 1.f,
0.f, 0.f
);
}
static inline MatrixT Skewing(
static inline Matrix3x2T Skewing(
const vec2_type& angle,
const vec2_type& center)
{
value_type tx = math::Tan(angle.x);
value_type ty = math::Tan(angle.y);
return MatrixT(
return Matrix3x2T(
1.f, -ty,
-tx, 1.f,
center.y * tx, center.x * ty
@ -309,23 +309,23 @@ namespace kiwano
template <typename _Ty>
inline
MatrixMultiply<_Ty, MatrixT<_Ty>, MatrixT<_Ty>>
operator *(MatrixT<_Ty> const& lhs, MatrixT<_Ty> const& rhs)
MatrixMultiply<_Ty, Matrix3x2T<_Ty>, Matrix3x2T<_Ty>>
operator *(Matrix3x2T<_Ty> const& lhs, Matrix3x2T<_Ty> const& rhs)
{
return MatrixMultiply<_Ty, MatrixT<_Ty>, MatrixT<_Ty>>(lhs, rhs);
return MatrixMultiply<_Ty, Matrix3x2T<_Ty>, Matrix3x2T<_Ty>>(lhs, rhs);
}
template <typename _Ty, typename _Lty, typename _Rty>
inline
MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, MatrixT<_Ty>>
operator *(MatrixMultiply<_Ty, _Lty, _Rty> const& lhs, MatrixT<_Ty> const& rhs)
MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, Matrix3x2T<_Ty>>
operator *(MatrixMultiply<_Ty, _Lty, _Rty> const& lhs, Matrix3x2T<_Ty> const& rhs)
{
return MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, MatrixT<_Ty>>(lhs, rhs);
return MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, Matrix3x2T<_Ty>>(lhs, rhs);
}
}
}
namespace kiwano
{
using Matrix = kiwano::math::MatrixT<float>;
using Matrix3x2 = kiwano::math::Matrix3x2T<float>;
}

View File

@ -38,7 +38,7 @@ namespace kiwano
{
}
Rect Geometry::GetBoundingBox(Matrix const& transform) const
Rect Geometry::GetBoundingBox(Matrix3x2 const& transform) const
{
if (!geo_)
return Rect{};
@ -76,6 +76,59 @@ namespace kiwano
return false;
}
Geometry Geometry::CombineWith(Geometry input, CombineMode mode, Matrix3x2 const& input_matrix)
{
if (geo_ && input.geo_)
{
GeometrySink sink;
sink.Init();
sink.OpenSink();
ThrowIfFailed(
geo_->CombineWithGeometry(
input.geo_.get(),
D2D1_COMBINE_MODE(mode),
DX::ConvertToMatrix3x2F(input_matrix),
sink.GetGeometrySink().get()
)
);
sink.CloseSink();
return sink.GetGeometry();
}
return Geometry();
}
Geometry Geometry::Combine(Vector<Geometry> const& geos, Vector<CombineMode> const& modes, Vector<Matrix3x2> const& matrixs)
{
if ((geos.size() == (modes.size() + 1) || modes.size() == 1)
&& (geos.size() == (matrixs.size() + 1) || matrixs.size() == 1))
{
GeometrySink sink;
sink.Init();
sink.OpenSink();
for (size_t i = 0; i < geos.size() - 1; i++)
{
CombineMode mode = (modes.size() == 1) ? modes[0] : modes[i];
const Matrix3x2& matrix = (matrixs.size() == 1) ? matrixs[0] : matrixs[i];
ThrowIfFailed(
geos[i].geo_->CombineWithGeometry(
geos[i + 1].geo_.get(),
D2D1_COMBINE_MODE(mode),
DX::ConvertToMatrix3x2F(matrix),
sink.GetGeometrySink().get()
)
);
}
sink.CloseSink();
return sink.GetGeometry();
}
return Geometry();
}
float Geometry::ComputeArea()
{
if (!geo_)
@ -102,6 +155,41 @@ namespace kiwano
return !!ret;
}
Geometry Geometry::CreateLine(Point const& begin, Point const& end)
{
Geometry output;
Renderer::GetInstance()->CreateLineGeometry(output, begin, end);
return output;
}
Geometry Geometry::CreateRect(Rect const& rect)
{
Geometry output;
Renderer::GetInstance()->CreateRectGeometry(output, rect);
return output;
}
Geometry Geometry::CreateRoundedRect(Rect const& rect, Vec2 const& radius)
{
Geometry output;
Renderer::GetInstance()->CreateRoundedRectGeometry(output, rect, radius);
return output;
}
Geometry Geometry::CreateCircle(Point const& center, float radius)
{
Geometry output;
Renderer::GetInstance()->CreateEllipseGeometry(output, center, Vec2{ radius, radius });
return output;
}
Geometry Geometry::CreateEllipse(Point const& center, Vec2 const& radius)
{
Geometry output;
Renderer::GetInstance()->CreateEllipseGeometry(output, center, radius);
return output;
}
//
// GeometrySink
//
@ -112,20 +200,14 @@ namespace kiwano
GeometrySink& GeometrySink::BeginPath(Point const& begin_pos)
{
if (!path_geo_)
{
Renderer::GetInstance()->CreatePathGeometrySink(*this);
}
Init();
if (!sink_)
{
ThrowIfFailed(path_geo_->Open(&sink_));
OpenSink();
}
if (sink_)
{
sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
}
sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
return (*this);
}
@ -135,9 +217,7 @@ namespace kiwano
{
sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
ThrowIfFailed(sink_->Close());
sink_ = nullptr;
CloseSink();
}
return (*this);
}
@ -200,4 +280,30 @@ namespace kiwano
return Geometry(path_geo_);
}
void GeometrySink::Init()
{
if (!path_geo_)
{
Renderer::GetInstance()->CreatePathGeometrySink(*this);
}
}
void GeometrySink::OpenSink()
{
if (!sink_)
{
ThrowIfFailed(path_geo_->Open(&sink_));
}
}
void GeometrySink::CloseSink()
{
if (sink_)
{
ThrowIfFailed(sink_->Close());
sink_ = nullptr;
}
}
}

View File

@ -24,13 +24,28 @@
namespace kiwano
{
// 섯부竟
class KGE_API Geometry
{
public:
// 几何体组合模式
enum class CombineMode
{
Union, /* 并集 (A + B) */
Intersect, /* 交集 (A + B) */
Xor, /* 对称差集 ((A - B) + (B - A)) */
Exclude /* 差集 (A - B) */
};
public:
Geometry();
Geometry(ComPtr<ID2D1Geometry> geo);
// 삿혤棍학관鍋분
Rect GetBoundingBox(
Matrix const& transform = Matrix()
Matrix3x2 const& transform = Matrix3x2()
) const;
// 털뙤暠近角뤠관벵듐
@ -51,10 +66,49 @@ namespace kiwano
Vec2& tangent
);
public:
Geometry();
// 组合几何体
Geometry CombineWith(
Geometry input,
CombineMode mode,
Matrix3x2 const& input_matrix = Matrix3x2()
);
Geometry(ComPtr<ID2D1Geometry> geo);
// 组合多个几何体
// 参数 modes 和 matrixs 的数量应为 1 或 geos 的数量减一
static Geometry Combine(
Vector<Geometry> const& geos,
Vector<CombineMode> const& modes,
Vector<Matrix3x2> const& matrixs = { Matrix3x2() }
);
// 创建直线
static Geometry CreateLine(
Point const& begin,
Point const& end
);
// 创建矩形
static Geometry CreateRect(
Rect const& rect
);
// 创建圆角矩形
static Geometry CreateRoundedRect(
Rect const& rect,
Vec2 const& radius
);
// 创建圆形
static Geometry CreateCircle(
Point const& center,
float radius
);
// 创建椭圆形
static Geometry CreateEllipse(
Point const& center,
Vec2 const& radius
);
public:
inline ComPtr<ID2D1Geometry> GetGeometry() const { return geo_; }
@ -119,6 +173,16 @@ namespace kiwano
inline void SetPathGeometry(ComPtr<ID2D1PathGeometry> path) { path_geo_ = path; }
inline ComPtr<ID2D1GeometrySink> GetGeometrySink() const { return sink_; }
inline void SetGeometrySink(ComPtr<ID2D1GeometrySink> sink) { sink_ = sink; }
void Init();
void OpenSink();
void CloseSink();
protected:
ComPtr<ID2D1PathGeometry> path_geo_;
ComPtr<ID2D1GeometrySink> sink_;

View File

@ -523,7 +523,7 @@ namespace kiwano
vsync_ = enabled;
}
void Renderer::PushClip(const Matrix & clip_matrix, const Size & clip_size)
void Renderer::PushClip(const Matrix3x2 & clip_matrix, const Size & clip_size)
{
HRESULT hr = S_OK;
if (!device_context_)
@ -630,7 +630,7 @@ namespace kiwano
clear_color_ = color;
}
void Renderer::SetTransform(const Matrix & matrix)
void Renderer::SetTransform(const Matrix3x2 & matrix)
{
HRESULT hr = S_OK;
if (!device_context_)
@ -750,7 +750,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
bool Renderer::CheckVisibility(Size const& content_size, Matrix const& transform)
bool Renderer::CheckVisibility(Size const& content_size, Matrix3x2 const& transform)
{
return Rect{ Point{}, output_size_ }.Intersects(
transform.Transform(Rect{ Point{}, content_size })

View File

@ -143,7 +143,7 @@ namespace kiwano
);
void SetTransform(
const Matrix& matrix
const Matrix3x2& matrix
);
void SetTextStyle(
@ -156,7 +156,7 @@ namespace kiwano
);
void PushClip(
const Matrix& clip_matrix,
const Matrix3x2& clip_matrix,
const Size& clip_size
);
@ -176,7 +176,7 @@ namespace kiwano
bool CheckVisibility(
Size const& content_size,
Matrix const& transform
Matrix3x2 const& transform
);
public:

View File

@ -122,22 +122,22 @@ namespace kiwano
// SizeF
//
inline D2D1_MATRIX_3X2_F const& ConvertToMatrix3x2F(Matrix const& matrix)
inline D2D1_MATRIX_3X2_F const& ConvertToMatrix3x2F(Matrix3x2 const& matrix)
{
return reinterpret_cast<D2D1_MATRIX_3X2_F const&>(matrix);
}
inline D2D1_MATRIX_3X2_F& ConvertToMatrix3x2F(Matrix& matrix)
inline D2D1_MATRIX_3X2_F& ConvertToMatrix3x2F(Matrix3x2& matrix)
{
return reinterpret_cast<D2D1_MATRIX_3X2_F&>(matrix);
}
inline const D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(const Matrix* matrix)
inline const D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(const Matrix3x2* matrix)
{
return reinterpret_cast<const D2D1_MATRIX_3X2_F*>(matrix);
}
inline D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(Matrix* matrix)
inline D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(Matrix3x2* matrix)
{
return reinterpret_cast<D2D1_MATRIX_3X2_F*>(matrix);
}