Implement clipping for DrawableLine.
This commit is contained in:
parent
634503bf00
commit
488c31c57e
11 changed files with 309 additions and 8 deletions
|
@ -40,7 +40,7 @@ namespace cloonel {
|
||||||
m_bounceCallback(&DoNothing),
|
m_bounceCallback(&DoNothing),
|
||||||
m_texture(new Texture(parPath, parMain, false))
|
m_texture(new Texture(parPath, parMain, false))
|
||||||
#if defined(WITH_DEBUG_VISUALS)
|
#if defined(WITH_DEBUG_VISUALS)
|
||||||
, m_bottomBarDrawable(parMain, Colour(250, 5, 1), static_cast<ushort2>(m_bottomBar.From()), static_cast<ushort2>(m_bottomBar.To()))
|
, m_bottomBarDrawable(parMain, Colour(250, 5, 1), static_cast<short2>(m_bottomBar.From()), static_cast<short2>(m_bottomBar.To()))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
assert(parMain);
|
assert(parMain);
|
||||||
|
@ -57,7 +57,7 @@ namespace cloonel {
|
||||||
m_bounceCallback(&DoNothing),
|
m_bounceCallback(&DoNothing),
|
||||||
m_texture(new Texture(parPath, parMain, false))
|
m_texture(new Texture(parPath, parMain, false))
|
||||||
#if defined(WITH_DEBUG_VISUALS)
|
#if defined(WITH_DEBUG_VISUALS)
|
||||||
, m_bottomBarDrawable(parMain, Colour(250, 5, 1), static_cast<ushort2>(m_bottomBar.From()), static_cast<ushort2>(m_bottomBar.To()))
|
, m_bottomBarDrawable(parMain, Colour(250, 5, 1), static_cast<short2>(m_bottomBar.From()), static_cast<short2>(m_bottomBar.To()))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
assert(parMain);
|
assert(parMain);
|
||||||
|
|
|
@ -20,15 +20,68 @@
|
||||||
|
|
||||||
#include "drawableline.hpp"
|
#include "drawableline.hpp"
|
||||||
#include "sdlmain.hpp"
|
#include "sdlmain.hpp"
|
||||||
|
#include "geometry_2d.hpp"
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
# include "line_helpers.hpp"
|
||||||
|
#endif
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#if defined(WITH_DEBUG_VISUALS)
|
#if defined(WITH_DEBUG_VISUALS)
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
namespace {
|
namespace {
|
||||||
///----------------------------------------------------------------------
|
///----------------------------------------------------------------------
|
||||||
///----------------------------------------------------------------------
|
///----------------------------------------------------------------------
|
||||||
void ClipLine (const SDL_Rect& /*parArea*/, Line<uint16_t, 2>& /*parLine*/) {
|
void ClipLine (const SDL_Rect& parArea, Line<int16_t, 2>& parLine) {
|
||||||
|
Line<float, 2> line(static_cast<float2>(parLine[0]), static_cast<float2>(parLine[1]));
|
||||||
|
const float al = static_cast<float>(parArea.x);
|
||||||
|
const float at = static_cast<float>(parArea.y);
|
||||||
|
const float ar = static_cast<float>(parArea.x + parArea.w);
|
||||||
|
const float ab = static_cast<float>(parArea.y + parArea.h);
|
||||||
|
|
||||||
|
{
|
||||||
|
const Line<float, 2> leftLine(al, at, al, ab);
|
||||||
|
const auto intersection(Intersection(line, leftLine));
|
||||||
|
if (intersection.first) {
|
||||||
|
if (line[0] < leftLine)
|
||||||
|
line[0] = intersection.second;
|
||||||
|
if (line[1] < leftLine)
|
||||||
|
line[1] = intersection.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const Line<float, 2> rightLine(ar, at, ar, ab);
|
||||||
|
const auto intersection(Intersection(line, rightLine));
|
||||||
|
if (intersection.first) {
|
||||||
|
if (line[0] > rightLine)
|
||||||
|
line[0] = intersection.second;
|
||||||
|
if (line[1] > rightLine)
|
||||||
|
line[1] = intersection.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const Line<float, 2> topLine(al, at, ar, at);
|
||||||
|
const auto intersection(Intersection(line, topLine));
|
||||||
|
if (intersection.first) {
|
||||||
|
if (line[0] < topLine)
|
||||||
|
line[0] = intersection.second;
|
||||||
|
if (line[1] < topLine)
|
||||||
|
line[1] = intersection.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const Line<float, 2> bottomLine(al, ab, ar, ab);
|
||||||
|
const auto intersection(Intersection(line, bottomLine));
|
||||||
|
if (intersection.first) {
|
||||||
|
if (line[0] > bottomLine)
|
||||||
|
line[0] = intersection.second;
|
||||||
|
if (line[1] > bottomLine)
|
||||||
|
line[1] = intersection.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parLine[0] = static_cast<short2>(line[0]);
|
||||||
|
parLine[1] = static_cast<short2>(line[1]);
|
||||||
}
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
|
@ -56,18 +109,18 @@ namespace cloonel {
|
||||||
SDL_SetRenderDrawColor(m_sdlmain->GetRenderer(), m_colour.r, m_colour.g, m_colour.b, m_colour.a);
|
SDL_SetRenderDrawColor(m_sdlmain->GetRenderer(), m_colour.r, m_colour.g, m_colour.b, m_colour.a);
|
||||||
|
|
||||||
LineBase scaledLine(*this);
|
LineBase scaledLine(*this);
|
||||||
scaledLine += static_cast<ushort2>(parPos);
|
scaledLine += static_cast<short2>(parPos);
|
||||||
scaledLine *= parScaling;
|
scaledLine *= parScaling;
|
||||||
{
|
{
|
||||||
SDL_Rect screen;
|
SDL_Rect screen;
|
||||||
screen.x = screen.y = 0;
|
screen.x = screen.y = 0;
|
||||||
const ushort2 wh(m_sdlmain->WidthHeight());
|
const short2 wh(static_cast<short2>(m_sdlmain->WidthHeight()));
|
||||||
screen.w = wh.x();
|
screen.w = wh.x();
|
||||||
screen.h = wh.y();
|
screen.h = wh.y();
|
||||||
|
|
||||||
ClipLine(screen, scaledLine);
|
ClipLine(screen, scaledLine);
|
||||||
}
|
}
|
||||||
const uint16_t h = m_sdlmain->WidthHeight().y();
|
const int16_t h = static_cast<int16_t>(m_sdlmain->WidthHeight().y());
|
||||||
if (scaledLine[0] != scaledLine[1]) {
|
if (scaledLine[0] != scaledLine[1]) {
|
||||||
SDL_RenderDrawLine(
|
SDL_RenderDrawLine(
|
||||||
m_sdlmain->GetRenderer(),
|
m_sdlmain->GetRenderer(),
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
class SDLMain;
|
class SDLMain;
|
||||||
|
|
||||||
class DrawableLine : public Line<uint16_t, 2> {
|
class DrawableLine : public Line<int16_t, 2> {
|
||||||
typedef Line<uint16_t, 2> LineBase;
|
typedef Line<int16_t, 2> LineBase;
|
||||||
public:
|
public:
|
||||||
explicit DrawableLine ( SDLMain* parMain );
|
explicit DrawableLine ( SDLMain* parMain );
|
||||||
explicit DrawableLine ( SDLMain* parMain, Colour parColour );
|
explicit DrawableLine ( SDLMain* parMain, Colour parColour );
|
||||||
|
|
25
src/geometry.cpp
Normal file
25
src/geometry.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||||
|
|
||||||
|
This file is part of CloonelJump.
|
||||||
|
|
||||||
|
CloonelJump is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
CloonelJump is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "geometry.hpp"
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
} //namespace cloonel
|
34
src/geometry.hpp
Normal file
34
src/geometry.hpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||||
|
|
||||||
|
This file is part of CloonelJump.
|
||||||
|
|
||||||
|
CloonelJump is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
CloonelJump is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef id3E40B29606D048569E18083DB682280F
|
||||||
|
#define id3E40B29606D048569E18083DB682280F
|
||||||
|
|
||||||
|
#include "vector.hpp"
|
||||||
|
#include <ciso646>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
template <typename T, uint32_t S>
|
||||||
|
bool IsPointOnSegment ( const Vector<T, S>& parPoint, const Vector<T, S>& parSegA, const Vector<T, S>& parSegB ) __attribute__((pure));
|
||||||
|
} //namespace cloonel
|
||||||
|
|
||||||
|
#include "geometry.inl"
|
||||||
|
|
||||||
|
#endif
|
31
src/geometry.inl
Normal file
31
src/geometry.inl
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||||
|
|
||||||
|
This file is part of CloonelJump.
|
||||||
|
|
||||||
|
CloonelJump is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
CloonelJump is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
template <typename T, uint32_t S>
|
||||||
|
bool IsPointOnSegment (const Vector<T, S>& parPoint, const Vector<T, S>& parSegA, const Vector<T, S>& parSegB) {
|
||||||
|
for (uint32_t z = 0; z < S; ++z) {
|
||||||
|
if (parPoint[z] <= std::max(parSegA[z], parSegB[z]) and parPoint[z] >= std::min(parSegA[z], parSegB[z]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} //namespace cloonel
|
23
src/geometry_2d.cpp
Normal file
23
src/geometry_2d.cpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||||
|
|
||||||
|
This file is part of CloonelJump.
|
||||||
|
|
||||||
|
CloonelJump is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
CloonelJump is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "geometry_2d.hpp"
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
} //namespace cloonel
|
43
src/geometry_2d.hpp
Normal file
43
src/geometry_2d.hpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||||
|
|
||||||
|
This file is part of CloonelJump.
|
||||||
|
|
||||||
|
CloonelJump is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
CloonelJump is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "vector.hpp"
|
||||||
|
#include "line.hpp"
|
||||||
|
#include "geometry.hpp"
|
||||||
|
#include <ciso646>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#ifndef id2B404E7CFDD3470680E572779CB819F6
|
||||||
|
#define id2B404E7CFDD3470680E572779CB819F6
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
template <typename T>
|
||||||
|
int GetOrientation ( const Vector<T, 2>& parPointA, const Vector<T, 2>& parPointB, const Vector<T, 2>& parPointC ) __attribute__((pure));
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool Intersection2D ( const Vector<T, 2>& parSegA1, const Vector<T, 2>& parSegA2, const Vector<T, 2>& parSegB1, const Vector<T, 2>& parSegB2 ) __attribute__((pure));
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::pair<bool, Vector<T, 2>> Intersection ( const Line<T, 2>& parSegA, const Line<T, 2>& parSegB ) __attribute__((pure));
|
||||||
|
} //namespace cloonel
|
||||||
|
|
||||||
|
#include "geometry_2d.inl"
|
||||||
|
|
||||||
|
#endif
|
88
src/geometry_2d.inl
Normal file
88
src/geometry_2d.inl
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||||
|
|
||||||
|
This file is part of CloonelJump.
|
||||||
|
|
||||||
|
CloonelJump is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
CloonelJump is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
|
int GetOrientation (const Vector<T, 2>& parPointA, const Vector<T, 2>& parPointB, const Vector<T, 2>& parPointC) {
|
||||||
|
const auto ret =
|
||||||
|
(parPointB.y() - parPointA.y()) * (parPointC.x() - parPointB.x()) -
|
||||||
|
(parPointB.x() - parPointA.x()) * (parPointC.y() - parPointB.y());
|
||||||
|
const T zero(0);
|
||||||
|
if (ret == zero)
|
||||||
|
return 0;
|
||||||
|
else if (ret < zero)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
|
bool Intersection2D (const Vector<T, 2>& parSegA1, const Vector<T, 2>& parSegA2, const Vector<T, 2>& parSegB1, const Vector<T, 2>& parSegB2) {
|
||||||
|
const int o1 = GetOrientation(parSegA1, parSegA2, parSegB1);
|
||||||
|
const int o2 = GetOrientation(parSegA1, parSegA2, parSegB2);
|
||||||
|
const int o3 = GetOrientation(parSegB1, parSegB2, parSegA1);
|
||||||
|
const int o4 = GetOrientation(parSegB1, parSegB2, parSegA2);
|
||||||
|
|
||||||
|
if (o1 != o2 and o3 != o4)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (0 == o1 and IsPointOnSegment(parSegA1, parSegB1, parSegA2))
|
||||||
|
return true;
|
||||||
|
if (0 == o2 and IsPointOnSegment(parSegA1, parSegB2, parSegA2))
|
||||||
|
return true;
|
||||||
|
if (0 == o3 and IsPointOnSegment(parSegB1, parSegA1, parSegB2))
|
||||||
|
return true;
|
||||||
|
if (0 == o4 and IsPointOnSegment(parSegB1, parSegA2, parSegB2))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///http://www.gidforums.com/t-20866.html
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
|
std::pair<bool, Vector<T, 2>> Intersection (const Line<T, 2>& parSegA, const Line<T, 2>& parSegB) {
|
||||||
|
typedef Line<T, 2> LineType;
|
||||||
|
|
||||||
|
const typename LineType::Point& startA = parSegA[0];
|
||||||
|
const typename LineType::Point& endA = parSegA[1];
|
||||||
|
const typename LineType::Point& startB = parSegB[0];
|
||||||
|
const typename LineType::Point& endB = parSegB[1];
|
||||||
|
|
||||||
|
const T A1(endA.y() - startA.y());
|
||||||
|
const T A2(endB.y() - startB.y());
|
||||||
|
const T B1(startA.x() - endA.x());
|
||||||
|
const T B2(startB.x() - endB.x());
|
||||||
|
const T det(A1 * B2 - A2 * B1);
|
||||||
|
|
||||||
|
if (det == 0) {
|
||||||
|
return std::make_pair(false, typename LineType::Point(0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const T C1(A1 * startA.x() + B1 * startA.y());
|
||||||
|
const T C2(A2 * startB.x() + B2 * startB.y());
|
||||||
|
return std::make_pair(true, typename LineType::Point((B2 * C1 - B1 * C2) / det, (A1 * C2 - A2 * C1) / det));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //namespace cloonel
|
|
@ -44,6 +44,7 @@ namespace cloonel {
|
||||||
void MoverSine::ApplyMotion (float parDelta) {
|
void MoverSine::ApplyMotion (float parDelta) {
|
||||||
const float pitwo = static_cast<float>(M_PI) * 2.0f;
|
const float pitwo = static_cast<float>(M_PI) * 2.0f;
|
||||||
m_alpha += parDelta * 2.6f;
|
m_alpha += parDelta * 2.6f;
|
||||||
|
//TODO: optimize - see https://groups.google.com/forum/#!topic/comp.graphics.api.opengl/FFl3djAYERs
|
||||||
while (m_alpha >= pitwo)
|
while (m_alpha >= pitwo)
|
||||||
m_alpha -= pitwo;
|
m_alpha -= pitwo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,9 @@ namespace cloonel {
|
||||||
|
|
||||||
typedef Vector<float, 2> float2;
|
typedef Vector<float, 2> float2;
|
||||||
typedef Vector<uint16_t, 2> ushort2;
|
typedef Vector<uint16_t, 2> ushort2;
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
typedef Vector<int16_t, 2> short2;
|
||||||
|
#endif
|
||||||
typedef Vector<int32_t, 2> int2;
|
typedef Vector<int32_t, 2> int2;
|
||||||
|
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
|
|
Loading…
Add table
Reference in a new issue