From a87255ef661593febfc948b0e6158d0b2aeae19a Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Wed, 9 Nov 2016 22:25:57 +0100 Subject: [PATCH] Fix texture clipping --- src/texture.cpp | 54 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/texture.cpp b/src/texture.cpp index aa0ba7a..cc8820f 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -30,6 +30,9 @@ #include #include #include +#if !defined(NDEBUG) +# include +#endif #define lengthof(a) (static_cast(sizeof(a) / sizeof(a[0]))) @@ -113,6 +116,15 @@ namespace cloonel { bool IsRectCompletelyInsideRect ( const RectFloat& parInner, const RectFloat& parOuter ) a_pure; #endif +#if !defined(NDEBUG) + bool areEqualRel (float parA, float parB, float parEpsilon) a_pure; + + //see: http://stackoverflow.com/questions/4548004/how-to-correctly-and-standardly-compare-floats + bool areEqualRel (float parA, float parB, float parEpsilon) { + return (std::fabs(parA - parB) <= parEpsilon * std::max(std::fabs(parA), std::fabs(parB))); + } +#endif + ///---------------------------------------------------------------------- ///---------------------------------------------------------------------- SDL_Surface* SurfaceFromPng (PixelFormat parPixelFormat, ushort2 parSize, const png_structp& parPngPtr, const png_infop& parInfoPtr, std::vector& parBuff) { @@ -260,6 +272,7 @@ namespace cloonel { ///got set to a valid value, otherwise false. ///---------------------------------------------------------------------- bool ClipRect (RectFloat& parSrc, RectFloat& parDest, const RectFloat& parClip) { + assert(areEqualRel(parSrc.Width(), parDest.Width(), 0.00001f)); assert(parSrc.IsValid()); assert(parDest.IsValid()); @@ -268,29 +281,34 @@ namespace cloonel { if (parDest.to <= parClip.from or parDest.from >= parClip.to) return false; - { - const RectFloat clip(float2(0.0f), float2(1.0f)); - const float2 srcWidthHeight(parSrc.WidthHeight()); - const float2 scaledOffs((parDest.from - parClip.from) / parClip.WidthHeight()); - parSrc.from -= float2(std::min(0.0f, scaledOffs.x() * srcWidthHeight.x()), std::min(0.0f, scaledOffs.y() * srcWidthHeight.y())); - const float2 scaledCrop((parClip.to - parDest.to) / parClip.WidthHeight()); - parSrc.to += float2(std::min(0.0f, scaledCrop.x() * srcWidthHeight.x()), std::min(0.0f, scaledCrop.y() * srcWidthHeight.y())); - assert(parSrc.IsValid()); - } - - RectFloat dst(parDest.from - parClip.from, parDest.to - parClip.from); - dst.from.x() = std::max(dst.from.x(), parClip.from.x()); - dst.from.y() = std::max(dst.from.y(), parClip.from.y()); - dst.to.x() = std::min(dst.to.x(), parClip.to.x()); - dst.to.y() = std::min(dst.to.y(), parClip.to.y()); + RectFloat dst; + dst.from.x() = std::max(parDest.from.x(), parClip.from.x()); + dst.from.y() = std::max(parDest.from.y(), parClip.from.y()); + dst.to.x() = std::min(parDest.to.x(), parClip.to.x()); + dst.to.y() = std::min(parDest.to.y(), parClip.to.y()); if (not dst.IsValid()) return false; - parDest.from += parClip.from; - parDest.to += parClip.from; + assert(parDest.from <= dst.from); + assert(parDest.to >= dst.to); - assert(parDest.IsValid()); + RectFloat src; + { + const float2 srcWidthHeight(parSrc.WidthHeight()); + const float2 scaledOffs((dst.from - parDest.from) / parDest.WidthHeight()); + src.from = parSrc.from + scaledOffs * srcWidthHeight; + const float2 scaledCrop((parDest.to - dst.to) / parDest.WidthHeight()); + src.to = parSrc.to - scaledCrop * srcWidthHeight; + assert(src.IsValid()); + + assert(dst.IsValid()); + assert(dst.from >= parClip.from); + assert(dst.to <= parClip.to); + assert(areEqualRel(src.Width(), dst.Width(), 0.00001f)); + } + parDest = dst; + parSrc = src; return true; }