Fix rect clipping

This commit is contained in:
King_DuckZ 2016-11-08 20:15:19 +01:00
parent 89ac57eee7
commit 5d231206ef
4 changed files with 43 additions and 19 deletions

View file

@ -108,6 +108,7 @@ target_compile_features(${PROJECT_NAME}
target_compile_definitions(${PROJECT_NAME} target_compile_definitions(${PROJECT_NAME}
PRIVATE ${PNG_DEFINITIONS} PRIVATE ${PNG_DEFINITIONS}
PRIVATE VWR_WITH_IMPLICIT_CONVERSIONS=1
) )
configure_file(src/${PROJECT_NAME}Config.h.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.h) configure_file(src/${PROJECT_NAME}Config.h.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.h)

@ -1 +1 @@
Subproject commit 736e83893a645cce2cc0767237f538785cf8651d Subproject commit 2f4d31967541c9c4a87b2511fb0c6d3792c72c2d

View file

@ -8,9 +8,23 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <algorithm> #include <algorithm>
#include <ciso646> #include <ciso646>
#if !defined(NDEBUG)
# include "compatibility.h"
# include <cmath>
# include <limits>
#endif
namespace curry { namespace curry {
namespace { namespace {
#if !defined(NDEBUG)
bool are_equal_rel (float parA, float parB, float parEpsilon) a_pure;
//see: http://stackoverflow.com/questions/4548004/how-to-correctly-and-standardly-compare-floats
bool are_equal_rel (float parA, float parB, float parEpsilon) {
return (std::fabs(parA - parB) <= parEpsilon * std::max(std::fabs(parA), std::fabs(parB)));
}
#endif
///--------------------------------------------------------------------- ///---------------------------------------------------------------------
///--------------------------------------------------------------------- ///---------------------------------------------------------------------
bool DoEvents (cloonel::InputBag& parInput, cloonel::SDLMain* parSdlMain) { bool DoEvents (cloonel::InputBag& parInput, cloonel::SDLMain* parSdlMain) {
@ -52,6 +66,7 @@ namespace curry {
///---------------------------------------------------------------------- ///----------------------------------------------------------------------
bool clip_rect (Rect<float>& parSrc, Rect<float>& parDest, const Rect<float>& parClip) { bool clip_rect (Rect<float>& parSrc, Rect<float>& parDest, const Rect<float>& parClip) {
typedef Rect<float> RectFloat; typedef Rect<float> RectFloat;
assert(are_equal_rel(parSrc.width(), parDest.width(), std::numeric_limits<float>::epsilon()));
assert(parSrc.is_valid()); assert(parSrc.is_valid());
assert(parDest.is_valid()); assert(parDest.is_valid());
@ -60,29 +75,34 @@ namespace curry {
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(vec2f(0.0f), vec2f(1.0f)); dst.from.x() = std::max(parDest.from.x(), parClip.from.x());
const vec2f srcWidthHeight(parSrc.width_height()); dst.from.y() = std::max(parDest.from.y(), parClip.from.y());
const vec2f scaledOffs((parDest.from - parClip.from) / parClip.width_height()); dst.to.x() = std::min(parDest.to.x(), parClip.to.x());
parSrc.from -= vec2f(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 vec2f scaledCrop((parClip.to - parDest.to) / parClip.width_height());
parSrc.to += vec2f(std::min(0.0f, scaledCrop.x() * srcWidthHeight.x()), std::min(0.0f, scaledCrop.y() * srcWidthHeight.y()));
assert(parSrc.is_valid());
}
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.is_valid()) if (not dst.is_valid())
return false; return false;
parDest.from += parClip.from; assert(parDest.from <= dst.from);
parDest.to += parClip.from; assert(parDest.to >= dst.to);
assert(parDest.is_valid()); RectFloat src;
{
const vec2f srcWidthHeight(parSrc.width_height());
const vec2f scaledOffs((dst.from - parDest.from) / parDest.width_height());
src.from = parSrc.from + scaledOffs * srcWidthHeight;
const vec2f scaledCrop((parDest.to - dst.to) / parDest.width_height());
src.to = parSrc.to - scaledCrop * srcWidthHeight;
assert(src.is_valid());
assert(dst.is_valid());
assert(dst.from >= parClip.from);
assert(dst.to <= parClip.to);
assert(are_equal_rel(src.width(), dst.width(), std::numeric_limits<float>::epsilon()));
}
parDest = dst;
parSrc = src;
return true; return true;
} }
} //unnamed namespace } //unnamed namespace
@ -149,6 +169,8 @@ namespace curry {
auto src = make_sdlrect(parSrc); auto src = make_sdlrect(parSrc);
auto dst = make_sdlrect(parDest); auto dst = make_sdlrect(parDest);
assert(src.w == dst.w);
assert(src.h == dst.h);
SDL_RenderCopy(m_sdlmain->GetRenderer(), parTexture.texture(), &src, &dst); SDL_RenderCopy(m_sdlmain->GetRenderer(), parTexture.texture(), &src, &dst);
} }
} //namespace curry } //namespace curry

View file

@ -11,6 +11,7 @@ namespace curry {
public: public:
typedef vwr::Vec<std::array<T, 2>> VecType; typedef vwr::Vec<std::array<T, 2>> VecType;
Rect() = default;
Rect (T parLeft, T parTop, T parRight, T parBottom); Rect (T parLeft, T parTop, T parRight, T parBottom);
template <typename V1, typename V2> template <typename V1, typename V2>
Rect (const vwr::Vec<V1>& parLeftTop, const vwr::Vec<V2>& parBottomRight); Rect (const vwr::Vec<V1>& parLeftTop, const vwr::Vec<V2>& parBottomRight);