From c32b09efb4585be6d307bd1d76c02aa1fbf60b30 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Sat, 24 Aug 2024 23:59:39 +0200 Subject: [PATCH 1/2] Add textureContainsPoint() method to CpuTextureManager --- src/cputexturemanager.cpp | 15 +++++++++ src/cputexturemanager.h | 3 ++ test/texture/cputexturemanager_test.cpp | 41 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/cputexturemanager.cpp b/src/cputexturemanager.cpp index 00b2671..c97b37d 100644 --- a/src/cputexturemanager.cpp +++ b/src/cputexturemanager.cpp @@ -51,6 +51,12 @@ const std::vector &CpuTextureManager::getTextureConvexHullPoints(const T return it->second; } +bool CpuTextureManager::textureContainsPoint(const Texture &texture, const QPointF &localPoint) +{ + // https://github.com/scratchfoundation/scratch-render/blob/7b823985bc6fe92f572cc3276a8915e550f7c5e6/src/Silhouette.js#L219-L226 + return getPointAlpha(texture, localPoint.x(), localPoint.y()) > 0; +} + void CpuTextureManager::removeTexture(const Texture &texture) { if (!texture.isValid()) @@ -131,3 +137,12 @@ bool CpuTextureManager::addTexture(const Texture &texture) return true; } + +int CpuTextureManager::getPointAlpha(const Texture &texture, int x, int y) +{ + if ((x < 0 || x >= texture.width()) || (y < 0 || y >= texture.height())) + return 0; + + GLubyte *pixels = getTextureData(texture); + return pixels[(y * texture.width() + x) * 4 + 3]; +} diff --git a/src/cputexturemanager.h b/src/cputexturemanager.h index 561e9d5..df19588 100644 --- a/src/cputexturemanager.h +++ b/src/cputexturemanager.h @@ -20,10 +20,13 @@ class CpuTextureManager GLubyte *getTextureData(const Texture &texture); const std::vector &getTextureConvexHullPoints(const Texture &texture); + bool textureContainsPoint(const Texture &texture, const QPointF &localPoint); + void removeTexture(const Texture &texture); private: bool addTexture(const Texture &texture); + int getPointAlpha(const Texture &texture, int x, int y); std::unordered_map m_textureData; std::unordered_map> m_convexHullPoints; diff --git a/test/texture/cputexturemanager_test.cpp b/test/texture/cputexturemanager_test.cpp index ca6ca7b..89ae51d 100644 --- a/test/texture/cputexturemanager_test.cpp +++ b/test/texture/cputexturemanager_test.cpp @@ -129,3 +129,44 @@ TEST_F(CpuTextureManagerTest, TextureDataAndHullPoints) // Cleanup context.doneCurrent(); } + +TEST_F(CpuTextureManagerTest, TextureContainsPoint) +{ + // Create OpenGL context + QOpenGLContext context; + QOffscreenSurface surface; + createContextAndSurface(&context, &surface); + + // Paint + QNanoPainter painter; + ImagePainter imgPainter(&painter, "image.png"); + + // Read texture data + Texture texture(imgPainter.fbo()->texture(), imgPainter.fbo()->size()); + + // Test + CpuTextureManager manager; + ASSERT_FALSE(manager.textureContainsPoint(texture, { 0, 0 })); + ASSERT_FALSE(manager.textureContainsPoint(texture, { 1, 0 })); + ASSERT_FALSE(manager.textureContainsPoint(texture, { 2, 0 })); + ASSERT_FALSE(manager.textureContainsPoint(texture, { 3, 0 })); + + ASSERT_FALSE(manager.textureContainsPoint(texture, { 0, 1 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 1 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 1.4, 1.25 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 2, 1 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 1 })); + + ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 2 })); + ASSERT_FALSE(manager.textureContainsPoint(texture, { 2, 2 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 2 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 3.5, 2.1 })); + + ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 3 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 2, 3 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 3 })); + ASSERT_TRUE(manager.textureContainsPoint(texture, { 3.3, 3.5 })); + + // Cleanup + context.doneCurrent(); +} From 934d23a8f97a0b5d26f48c86467f8868cf85920d Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Sat, 24 Aug 2024 23:59:55 +0200 Subject: [PATCH 2/2] Use CPU texture in contains methods --- src/renderedtarget.cpp | 15 +------------ test/renderedtarget/renderedtarget_test.cpp | 24 ++++++++++----------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/renderedtarget.cpp b/src/renderedtarget.cpp index f9454fd..1f20b54 100644 --- a/src/renderedtarget.cpp +++ b/src/renderedtarget.cpp @@ -814,20 +814,7 @@ void RenderedTarget::updateHullPoints() bool RenderedTarget::containsLocalPoint(const QPointF &point) const { - if (!boundingRect().contains(point)) - return false; - - const std::vector &points = hullPoints(); - QPoint intPoint = point.toPoint(); - auto it = std::lower_bound(points.begin(), points.end(), intPoint, [](const QPointF &lhs, const QPointF &rhs) { return (lhs.y() < rhs.y()) || (lhs.y() == rhs.y() && lhs.x() < rhs.x()); }); - - if (it == points.end()) { - // The point is beyond the last point in the convex hull - return false; - } - - // Check if the point is equal to the one found - return *it == intPoint; + return textureManager()->textureContainsPoint(m_cpuTexture, point); } QPointF RenderedTarget::transformPoint(double scratchX, double scratchY, double originX, double originY, double rot) const diff --git a/test/renderedtarget/renderedtarget_test.cpp b/test/renderedtarget/renderedtarget_test.cpp index 044a81d..4e3c2e6 100644 --- a/test/renderedtarget/renderedtarget_test.cpp +++ b/test/renderedtarget/renderedtarget_test.cpp @@ -394,12 +394,12 @@ TEST_F(RenderedTargetTest, CpuRendering) ASSERT_TRUE(target.contains({ 1, 2 })); ASSERT_FALSE(target.contains({ 2, 2 })); ASSERT_TRUE(target.contains({ 3, 2 })); - ASSERT_FALSE(target.contains({ 3.5, 2.1 })); + ASSERT_TRUE(target.contains({ 3.5, 2.1 })); ASSERT_TRUE(target.contains({ 1, 3 })); ASSERT_TRUE(target.contains({ 2, 3 })); ASSERT_TRUE(target.contains({ 3, 3 })); - ASSERT_FALSE(target.contains({ 3.3, 3.5 })); + ASSERT_TRUE(target.contains({ 3.3, 3.5 })); // Test contains() with horizontal mirroring target.updateRotationStyle(Sprite::RotationStyle::LeftRight); @@ -408,9 +408,9 @@ TEST_F(RenderedTargetTest, CpuRendering) ASSERT_TRUE(target.contains({ -1, 1 })); ASSERT_FALSE(target.contains({ -2, 2 })); ASSERT_TRUE(target.contains({ -3, 2 })); - ASSERT_FALSE(target.contains({ -3.5, 2.1 })); + ASSERT_TRUE(target.contains({ -3.5, 2.1 })); ASSERT_TRUE(target.contains({ -2, 3 })); - ASSERT_FALSE(target.contains({ -3.3, 3.5 })); + ASSERT_TRUE(target.contains({ -3.3, 3.5 })); // Test containsScratchPoint() target.updateDirection(0); @@ -425,15 +425,15 @@ TEST_F(RenderedTargetTest, CpuRendering) ASSERT_TRUE(target.containsScratchPoint(-226, 164)); // [2, 1] ASSERT_TRUE(target.containsScratchPoint(-225, 164)); // [3, 1] - ASSERT_TRUE(target.containsScratchPoint(-227, 163)); // [1, 2] - ASSERT_FALSE(target.containsScratchPoint(-226, 163)); // [2, 2] - ASSERT_TRUE(target.containsScratchPoint(-225, 163)); // [3, 2] - ASSERT_FALSE(target.containsScratchPoint(-224.5, 162.9)); // [3.5, 2.1] + ASSERT_TRUE(target.containsScratchPoint(-227, 163)); // [1, 2] + ASSERT_FALSE(target.containsScratchPoint(-226, 163)); // [2, 2] + ASSERT_TRUE(target.containsScratchPoint(-225, 163)); // [3, 2] + ASSERT_TRUE(target.containsScratchPoint(-224.5, 162.9)); // [3.5, 2.1] - ASSERT_TRUE(target.containsScratchPoint(-227, 162)); // [1, 3] - ASSERT_TRUE(target.containsScratchPoint(-226, 162)); // [2, 3] - ASSERT_TRUE(target.containsScratchPoint(-225, 162)); // [3, 3] - ASSERT_FALSE(target.containsScratchPoint(-224.7, 161.5)); // [3.3, 3.5] + ASSERT_TRUE(target.containsScratchPoint(-227, 162)); // [1, 3] + ASSERT_TRUE(target.containsScratchPoint(-226, 162)); // [2, 3] + ASSERT_TRUE(target.containsScratchPoint(-225, 162)); // [3, 3] + ASSERT_TRUE(target.containsScratchPoint(-224.7, 161.5)); // [3.3, 3.5] // Test colorAtScratchPoint() ASSERT_EQ(target.colorAtScratchPoint(-228, 165), 0); // [0, 0]