Added optimization to clip brush strokes from camera view

This commit is contained in:
Yousef Khadadeh 2026-02-08 13:27:18 +03:00
parent f2f215fa91
commit 6b3ac4dc04
5 changed files with 38 additions and 14 deletions

View file

@ -79,22 +79,23 @@ std::shared_ptr<void> BrushStrokeCanvasComponent::get_predraw_data_accurate(cons
auto pathsToDraw = std::make_shared<std::vector<SkPath>>();
SCollision::AABB<float> viewGenerousColliderInObjSpace = coords.world_collider_to_coords<SCollision::AABB<float>>(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<float> triCollider = {a, b, c};
auto clipListFunc = [](const std::vector<std::array<WorldVec, 3>>& clipList, const std::array<WorldVec, 2>& axisLineSegment, const std::function<bool(const WorldVec&)>& isInClippingAreaFunc) {
std::vector<std::array<WorldVec, 3>> 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<std::array<WorldVec, 3>>& clipList, const std::array<WorldVec, 2>& axisLineSegment, const std::function<bool(const WorldVec&)>& isInClippingAreaFunc) {
std::vector<std::array<WorldVec, 3>> 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<std::array<WorldVec, 3>> clipList = {worldTri.p};
std::vector<std::array<WorldVec, 3>> clipList;
clipList.emplace_back(std::array<WorldVec, 3>{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<float> viewGenerousColliderInObjSpace = coords.world_collider_to_coords<SCollision::AABB<float>>(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<float> BrushStrokeCanvasComponent::get_obj_coord_bounds() const {
return bounds;
}

View file

@ -41,6 +41,7 @@ class BrushStrokeCanvasComponent : public CanvasComponent {
virtual void initialize_draw_data(DrawingProgram& drawP) override;
virtual bool collides_within_coords(const SCollision::ColliderCollection<float>& checkAgainst) const override;
void create_collider();
bool should_draw_extra(const DrawData& drawData, const CoordSpaceHelper& coords) const override;
virtual SCollision::AABB<float> get_obj_coord_bounds() const override;

View file

@ -49,4 +49,8 @@ std::shared_ptr<void> 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() {}

View file

@ -34,6 +34,8 @@ class CanvasComponent {
virtual std::shared_ptr<void> get_predraw_data(const DrawData& drawData) const;
virtual std::shared_ptr<void> 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<void>& predrawData) const = 0;
virtual void initialize_draw_data(DrawingProgram& drawP) = 0;
virtual bool collides_within_coords(const SCollision::ColliderCollection<float>& checkAgainst) const = 0;

View file

@ -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 {