From d34e14b799756e6238873f502a2c9bddb79bc447 Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Wed, 14 Aug 2019 23:36:29 +0800 Subject: [PATCH] update Geometry --- src/kiwano/2d/Actor.cpp | 10 +-- src/kiwano/2d/Actor.h | 8 +- src/kiwano/2d/Canvas.cpp | 2 +- src/kiwano/2d/Canvas.h | 2 +- src/kiwano/2d/ShapeActor.cpp | 12 +-- src/kiwano/2d/action/ActionWalk.cpp | 1 - src/kiwano/math/Matrix.hpp | 70 +++++++-------- src/kiwano/renderer/Geometry.cpp | 132 +++++++++++++++++++++++++--- src/kiwano/renderer/Geometry.h | 72 ++++++++++++++- src/kiwano/renderer/Renderer.cpp | 6 +- src/kiwano/renderer/Renderer.h | 6 +- src/kiwano/renderer/helper.hpp | 8 +- 12 files changed, 249 insertions(+), 80 deletions(-) diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index b5278b31..2db554b4 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -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_; } } diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index d71d5217..55f8f105 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -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_; }; } diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp index 33caed18..c9f01d1b 100644 --- a/src/kiwano/2d/Canvas.cpp +++ b/src/kiwano/2d/Canvas.cpp @@ -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)); } diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h index 59fb2b98..add2a2c1 100644 --- a/src/kiwano/2d/Canvas.h +++ b/src/kiwano/2d/Canvas.h @@ -205,7 +205,7 @@ namespace kiwano // 变换画笔 void SetBrushTransform( - Matrix const& transform + Matrix3x2 const& transform ); // 导出为图片 diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp index 9ff124bb..3cab94c1 100644 --- a/src/kiwano/2d/ShapeActor.cpp +++ b/src/kiwano/2d/ShapeActor.cpp @@ -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_) { diff --git a/src/kiwano/2d/action/ActionWalk.cpp b/src/kiwano/2d/action/ActionWalk.cpp index addf325e..3a4c77aa 100644 --- a/src/kiwano/2d/action/ActionWalk.cpp +++ b/src/kiwano/2d/action/ActionWalk.cpp @@ -86,7 +86,6 @@ namespace kiwano target->SetRotation(rotation); } } - KGE_LOG(L"%.2f, %.2f", target->GetPositionX(), target->GetPositionY()); } void ActionWalk::BeginPath() diff --git a/src/kiwano/math/Matrix.hpp b/src/kiwano/math/Matrix.hpp index 37d29e06..b13e5391 100644 --- a/src/kiwano/math/Matrix.hpp +++ b/src/kiwano/math/Matrix.hpp @@ -31,7 +31,7 @@ namespace kiwano struct MatrixMultiply; template - struct MatrixT + struct Matrix3x2T { using value_type = _Ty; using vec2_type = Vec2T; @@ -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 - 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 - inline MatrixT& operator= (MatrixMultiply const& other) + inline Matrix3x2T& operator= (MatrixMultiply 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 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 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; + using Matrix3x2 = kiwano::math::Matrix3x2T; } diff --git a/src/kiwano/renderer/Geometry.cpp b/src/kiwano/renderer/Geometry.cpp index 9d5ada2e..f56de2ce 100644 --- a/src/kiwano/renderer/Geometry.cpp +++ b/src/kiwano/renderer/Geometry.cpp @@ -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 const& geos, Vector const& modes, Vector 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; + } + } + } diff --git a/src/kiwano/renderer/Geometry.h b/src/kiwano/renderer/Geometry.h index 0217dde9..8a4f5417 100644 --- a/src/kiwano/renderer/Geometry.h +++ b/src/kiwano/renderer/Geometry.h @@ -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 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 geo); + // 组合多个几何体 + // 参数 modes 和 matrixs 的数量应为 1 或 geos 的数量减一 + static Geometry Combine( + Vector const& geos, + Vector const& modes, + Vector 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 GetGeometry() const { return geo_; } @@ -119,6 +173,16 @@ namespace kiwano inline void SetPathGeometry(ComPtr path) { path_geo_ = path; } + inline ComPtr GetGeometrySink() const { return sink_; } + + inline void SetGeometrySink(ComPtr sink) { sink_ = sink; } + + void Init(); + + void OpenSink(); + + void CloseSink(); + protected: ComPtr path_geo_; ComPtr sink_; diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index 9cfe13b1..77361827 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -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 }) diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index 50c9373c..a365a6cb 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -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: diff --git a/src/kiwano/renderer/helper.hpp b/src/kiwano/renderer/helper.hpp index 35e05973..3c781b1b 100644 --- a/src/kiwano/renderer/helper.hpp +++ b/src/kiwano/renderer/helper.hpp @@ -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(matrix); } - inline D2D1_MATRIX_3X2_F& ConvertToMatrix3x2F(Matrix& matrix) + inline D2D1_MATRIX_3X2_F& ConvertToMatrix3x2F(Matrix3x2& matrix) { return reinterpret_cast(matrix); } - inline const D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(const Matrix* matrix) + inline const D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(const Matrix3x2* matrix) { return reinterpret_cast(matrix); } - inline D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(Matrix* matrix) + inline D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(Matrix3x2* matrix) { return reinterpret_cast(matrix); }