Fix texture clipping
This commit is contained in:
parent
68d179975e
commit
a87255ef66
1 changed files with 36 additions and 18 deletions
|
@ -30,6 +30,9 @@
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
# include <cmath>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define lengthof(a) (static_cast<int32_t>(sizeof(a) / sizeof(a[0])))
|
#define lengthof(a) (static_cast<int32_t>(sizeof(a) / sizeof(a[0])))
|
||||||
|
|
||||||
|
@ -113,6 +116,15 @@ namespace cloonel {
|
||||||
bool IsRectCompletelyInsideRect ( const RectFloat& parInner, const RectFloat& parOuter ) a_pure;
|
bool IsRectCompletelyInsideRect ( const RectFloat& parInner, const RectFloat& parOuter ) a_pure;
|
||||||
#endif
|
#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<uint8_t>& parBuff) {
|
SDL_Surface* SurfaceFromPng (PixelFormat parPixelFormat, ushort2 parSize, const png_structp& parPngPtr, const png_infop& parInfoPtr, std::vector<uint8_t>& parBuff) {
|
||||||
|
@ -260,6 +272,7 @@ namespace cloonel {
|
||||||
///got set to a valid value, otherwise false.
|
///got set to a valid value, otherwise false.
|
||||||
///----------------------------------------------------------------------
|
///----------------------------------------------------------------------
|
||||||
bool ClipRect (RectFloat& parSrc, RectFloat& parDest, const RectFloat& parClip) {
|
bool ClipRect (RectFloat& parSrc, RectFloat& parDest, const RectFloat& parClip) {
|
||||||
|
assert(areEqualRel(parSrc.Width(), parDest.Width(), 0.00001f));
|
||||||
assert(parSrc.IsValid());
|
assert(parSrc.IsValid());
|
||||||
assert(parDest.IsValid());
|
assert(parDest.IsValid());
|
||||||
|
|
||||||
|
@ -268,29 +281,34 @@ namespace cloonel {
|
||||||
if (parDest.to <= parClip.from or parDest.from >= parClip.to)
|
if (parDest.to <= parClip.from or parDest.from >= parClip.to)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
{
|
RectFloat dst;
|
||||||
const RectFloat clip(float2(0.0f), float2(1.0f));
|
dst.from.x() = std::max(parDest.from.x(), parClip.from.x());
|
||||||
const float2 srcWidthHeight(parSrc.WidthHeight());
|
dst.from.y() = std::max(parDest.from.y(), parClip.from.y());
|
||||||
const float2 scaledOffs((parDest.from - parClip.from) / parClip.WidthHeight());
|
dst.to.x() = std::min(parDest.to.x(), parClip.to.x());
|
||||||
parSrc.from -= float2(std::min(0.0f, scaledOffs.x() * srcWidthHeight.x()), std::min(0.0f, scaledOffs.y() * srcWidthHeight.y()));
|
dst.to.y() = std::min(parDest.to.y(), parClip.to.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());
|
|
||||||
|
|
||||||
if (not dst.IsValid())
|
if (not dst.IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
parDest.from += parClip.from;
|
assert(parDest.from <= dst.from);
|
||||||
parDest.to += parClip.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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue