Torque3D Documentation / _generateds / rectClipper.cpp

rectClipper.cpp

Engine/source/util/rectClipper.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "util/rectClipper.h"
 25
 26namespace {
 27
 28inline void
 29swap(F32& in_one, F32& in_two)
 30{
 31   F32 temp = in_one;
 32   in_one   = in_two;
 33   in_two   = temp;
 34}
 35
 36}
 37
 38bool
 39RectClipper::clipLine(const Point2I& in_rStart,
 40                      const Point2I& in_rEnd,
 41                      Point2I&       out_rStart,
 42                      Point2I&       out_rEnd) const
 43{
 44   // Check for trivial rejection
 45   if ((in_rStart.x < m_clipRect.point.x && in_rEnd.x < m_clipRect.point.x) ||
 46       (in_rStart.x >= m_clipRect.point.x + m_clipRect.extent.x &&
 47         in_rEnd.x >= m_clipRect.point.x + m_clipRect.extent.x))
 48      return false;
 49   if ((in_rStart.y < m_clipRect.point.y && in_rEnd.y < m_clipRect.point.y) ||
 50       (in_rStart.y >= m_clipRect.point.y + m_clipRect.extent.y &&
 51         in_rEnd.y >= m_clipRect.point.y + m_clipRect.extent.y))
 52      return false;
 53
 54   F32 x1 = F32(in_rStart.x);
 55   F32 y1 = F32(in_rStart.y);
 56   F32 x2 = F32(in_rEnd.x);
 57   F32 y2 = F32(in_rEnd.y);
 58
 59   // I'm using essentially what's in the Phoenix libs, Liang-Biarsky based, but
 60   //  converted to FP math for greater precision on the back end...
 61   //
 62   bool flipped = false;
 63   if (x1 > x2) 
 64   {
 65      swap(x1, x2);
 66      swap(y1, y2);
 67      flipped = !flipped;
 68   }
 69
 70   F32 dx = x2 - x1;
 71   F32 dy = y2 - y1;
 72
 73   // Clip x coord
 74   F32 t;
 75   if (x1 < F32(m_clipRect.point.x)) 
 76   {
 77      t   = (F32(m_clipRect.point.x) - x1) / F32(dx);
 78      x1  = F32(m_clipRect.point.x);
 79      y1 += t * dy;
 80      dx  = x2 - x1;
 81      dy  = y2 - y1;
 82   }
 83   if (x2 >= F32(m_clipRect.point.x + m_clipRect.extent.x))
 84   {
 85      t   = (F32(m_clipRect.point.x + m_clipRect.extent.x - 1) - x1) / F32(dx);
 86      x2  = F32(m_clipRect.point.x + m_clipRect.extent.x - 1);
 87      y2  = y1 + (t * dy);
 88      dx  = x2 - x1;
 89      dy  = y2 - y1;
 90   }
 91
 92   // Recheck trivial rejection condition...
 93   if((y1 > F32(m_clipRect.point.y + m_clipRect.extent.y - 1) &&
 94         y2 > F32(m_clipRect.point.y + m_clipRect.extent.y - 1)) ||
 95         (y1 < F32(m_clipRect.point.y) && y2 < F32(m_clipRect.point.y)))
 96      return false;
 97
 98   if (y1 > y2) 
 99   {
100      swap(x1, x2);
101      swap(y1, y2);
102      flipped = !flipped;
103   }
104
105   if (y1 < F32(m_clipRect.point.y)) 
106   {
107      t   = (F32(m_clipRect.point.y) - y1) / F32(dy);
108      y1  = F32(m_clipRect.point.y);
109      x1 += t * dx;
110      dx  = x2 - x1;
111      dy  = y2 - y1;
112   }
113   if (y2 > F32(m_clipRect.point.y + m_clipRect.extent.y - 1))
114   {
115      t   = (F32(m_clipRect.point.y + m_clipRect.extent.y - 1) - y1) / F32(dy);
116      y2  = F32(m_clipRect.point.y + m_clipRect.extent.y - 1);
117      x2  = x1 + (t * dx);
118   }
119
120   if (flipped == true) 
121   {
122      out_rEnd.x   = S32(x1 + 0.5f);
123      out_rEnd.y   = S32(y1 + 0.5f);
124      out_rStart.x = S32(x2 + 0.5f);
125      out_rStart.y = S32(y2 + 0.5f);
126   } 
127   else 
128   {
129      out_rStart.x = S32(x1 + 0.5f);
130      out_rStart.y = S32(y1 + 0.5f);
131      out_rEnd.x   = S32(x2 + 0.5f);
132      out_rEnd.y   = S32(y2 + 0.5f);
133   }
134
135   return true;
136}
137
138
139bool
140RectClipper::clipRect(const RectI& in_rRect,
141                      RectI&       out_rRect) const
142{
143   AssertFatal(in_rRect.isValidRect(), "Inappropriate min/max coords for rectangle");
144
145   if (in_rRect.point.x + in_rRect.extent.x - 1 < m_clipRect.point.x ||
146       in_rRect.point.x > m_clipRect.point.x + m_clipRect.extent.x - 1)
147      return false;
148   if (in_rRect.point.y + in_rRect.extent.y - 1 < m_clipRect.point.y ||
149       in_rRect.point.y > m_clipRect.point.y + m_clipRect.extent.y - 1)
150      return false;
151
152   if (in_rRect.point.x < m_clipRect.point.x) out_rRect.point.x = m_clipRect.point.x;
153   else                                       out_rRect.point.x = in_rRect.point.x;
154
155   if (in_rRect.point.y < m_clipRect.point.y) out_rRect.point.y = m_clipRect.point.y;
156   else                                       out_rRect.point.y = in_rRect.point.y;
157
158   Point2I bottomR;
159   bottomR.x = getMin(in_rRect.point.x + in_rRect.extent.x - 1,
160                     m_clipRect.point.x + m_clipRect.extent.x - 1);
161   bottomR.y = getMin(in_rRect.point.y + in_rRect.extent.y - 1,
162                     m_clipRect.point.y + m_clipRect.extent.y - 1);
163
164   out_rRect.extent.x = bottomR.x - out_rRect.point.x + 1;
165   out_rRect.extent.x = bottomR.y - out_rRect.point.y + 1;
166
167   return true;
168}
169