From 6b3ac4dc048f571984b090ef283c461cde044e38 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Sun, 8 Feb 2026 13:27:18 +0300 Subject: [PATCH] Added optimization to clip brush strokes from camera view --- .../BrushStrokeCanvasComponent.cpp | 43 +++++++++++++------ .../BrushStrokeCanvasComponent.hpp | 1 + src/CanvasComponents/CanvasComponent.cpp | 4 ++ src/CanvasComponents/CanvasComponent.hpp | 2 + .../CanvasComponentContainer.cpp | 2 +- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/CanvasComponents/BrushStrokeCanvasComponent.cpp b/src/CanvasComponents/BrushStrokeCanvasComponent.cpp index cb28110..11a1eb3 100644 --- a/src/CanvasComponents/BrushStrokeCanvasComponent.cpp +++ b/src/CanvasComponents/BrushStrokeCanvasComponent.cpp @@ -79,22 +79,23 @@ std::shared_ptr BrushStrokeCanvasComponent::get_predraw_data_accurate(cons auto pathsToDraw = std::make_shared>(); + SCollision::AABB viewGenerousColliderInObjSpace = coords.world_collider_to_coords>(drawData.cam.viewingAreaGenerousCollider); + viewGenerousColliderInObjSpace.min -= Vector2f{1.0f, 1.0f}; + viewGenerousColliderInObjSpace.max += Vector2f{1.0f, 1.0f}; + auto triangleFunc = [&](Vector2f a, Vector2f b, Vector2f c) { - SCollision::Triangle worldTri = { - coords.from_space(a), - coords.from_space(b), - coords.from_space(c) - }; + SCollision::Triangle triCollider = {a, b, c}; - auto clipListFunc = [](const std::vector>& clipList, const std::array& axisLineSegment, const std::function& isInClippingAreaFunc) { - std::vector> resultList; - for(auto& t : clipList) - clip_triangle_against_axis(resultList, t, axisLineSegment, isInClippingAreaFunc); - return resultList; - }; + if(SCollision::collide(triCollider.bounds, viewGenerousColliderInObjSpace)) { + auto clipListFunc = [](const std::vector>& clipList, const std::array& axisLineSegment, const std::function& isInClippingAreaFunc) { + std::vector> resultList; + for(auto& t : clipList) + clip_triangle_against_axis(resultList, t, axisLineSegment, isInClippingAreaFunc); + return resultList; + }; - if(SCollision::collide(worldTri.bounds, drawData.cam.viewingAreaGenerousCollider)) { - std::vector> clipList = {worldTri.p}; + std::vector> clipList; + clipList.emplace_back(std::array{coords.from_space(a), coords.from_space(b), coords.from_space(c)}); clipList = clipListFunc(clipList, {drawData.cam.viewingAreaGenerousCollider.min, drawData.cam.viewingAreaGenerousCollider.top_right()}, [&](const WorldVec& p) { return p.y() > drawData.cam.viewingAreaGenerousCollider.min.y(); }); @@ -495,6 +496,22 @@ bool BrushStrokeCanvasComponent::collides_within_coords(const SCollision::Collid return toRet; } +bool BrushStrokeCanvasComponent::should_draw_extra(const DrawData& drawData, const CoordSpaceHelper& coords) const { + SCollision::AABB viewGenerousColliderInObjSpace = coords.world_collider_to_coords>(drawData.cam.viewingAreaGenerousCollider); + viewGenerousColliderInObjSpace.min -= Vector2f{1.0f, 1.0f}; + viewGenerousColliderInObjSpace.max += Vector2f{1.0f, 1.0f}; + bool deepPrecheck = false; + for(auto& aabb : precheckAABBLevels) { + if(SCollision::collide(viewGenerousColliderInObjSpace, aabb)) { + deepPrecheck = true; + break; + } + } + if(!deepPrecheck && !precheckAABBLevels.empty()) + return false; + return true; +} + SCollision::AABB BrushStrokeCanvasComponent::get_obj_coord_bounds() const { return bounds; } diff --git a/src/CanvasComponents/BrushStrokeCanvasComponent.hpp b/src/CanvasComponents/BrushStrokeCanvasComponent.hpp index 968dc8b..bceb305 100644 --- a/src/CanvasComponents/BrushStrokeCanvasComponent.hpp +++ b/src/CanvasComponents/BrushStrokeCanvasComponent.hpp @@ -41,6 +41,7 @@ class BrushStrokeCanvasComponent : public CanvasComponent { virtual void initialize_draw_data(DrawingProgram& drawP) override; virtual bool collides_within_coords(const SCollision::ColliderCollection& checkAgainst) const override; void create_collider(); + bool should_draw_extra(const DrawData& drawData, const CoordSpaceHelper& coords) const override; virtual SCollision::AABB get_obj_coord_bounds() const override; diff --git a/src/CanvasComponents/CanvasComponent.cpp b/src/CanvasComponents/CanvasComponent.cpp index 0d54b94..bb431fc 100644 --- a/src/CanvasComponents/CanvasComponent.cpp +++ b/src/CanvasComponents/CanvasComponent.cpp @@ -49,4 +49,8 @@ std::shared_ptr CanvasComponent::get_predraw_data_accurate(const DrawData& return nullptr; } +bool CanvasComponent::should_draw_extra(const DrawData& drawData, const CoordSpaceHelper& coords) const { + return true; +} + CanvasComponent::~CanvasComponent() {} diff --git a/src/CanvasComponents/CanvasComponent.hpp b/src/CanvasComponents/CanvasComponent.hpp index 6507761..9bec924 100644 --- a/src/CanvasComponents/CanvasComponent.hpp +++ b/src/CanvasComponents/CanvasComponent.hpp @@ -34,6 +34,8 @@ class CanvasComponent { virtual std::shared_ptr get_predraw_data(const DrawData& drawData) const; virtual std::shared_ptr get_predraw_data_accurate(const DrawData& drawData, const CoordSpaceHelper& coords) const; + virtual bool should_draw_extra(const DrawData& drawData, const CoordSpaceHelper& coords) const; + virtual void draw(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr& predrawData) const = 0; virtual void initialize_draw_data(DrawingProgram& drawP) = 0; virtual bool collides_within_coords(const SCollision::ColliderCollection& checkAgainst) const = 0; diff --git a/src/CanvasComponents/CanvasComponentContainer.cpp b/src/CanvasComponents/CanvasComponentContainer.cpp index 90ac6e9..8f59c0d 100644 --- a/src/CanvasComponents/CanvasComponentContainer.cpp +++ b/src/CanvasComponents/CanvasComponentContainer.cpp @@ -158,7 +158,7 @@ void CanvasComponentContainer::canvas_do_transform(SkCanvas* canvas, const Trans } bool CanvasComponentContainer::should_draw(const DrawData& drawData) const { - return (!drawData.clampDrawBetween || (drawData.clampDrawMinimum < coords.inverseScale)) && SCollision::collide(worldAABB.value(), drawData.cam.viewingAreaGenerousCollider); + return (!drawData.clampDrawBetween || (drawData.clampDrawMinimum < coords.inverseScale)) && SCollision::collide(worldAABB.value(), drawData.cam.viewingAreaGenerousCollider) && get_comp().should_draw_extra(drawData, coords); } CanvasComponentContainer::PreDrawData CanvasComponentContainer::calculate_predraw_data(const DrawData& drawData) const {