FastEngine 0.9.3
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
C_rect.inl
1/*
2 * Copyright 2024 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17namespace fge
18{
19
20template<class T>
21Rect<T>::Rect() :
22 _x(0),
23 _y(0),
24 _width(0),
25 _height(0)
26{}
27
28template<class T>
29Rect<T>::Rect(Vector2<T> const& position, Vector2<T> const& size) :
30 _x(position.x),
31 _y(position.y),
32 _width(size.x),
33 _height(size.y)
34{}
35
36template<class T>
37template<class U>
38Rect<T>::Rect(Rect<U> const& rectangle) :
39 _x(static_cast<T>(rectangle._x)),
40 _y(static_cast<T>(rectangle._y)),
41 _width(static_cast<T>(rectangle._width)),
42 _height(static_cast<T>(rectangle._height))
43{}
44
45template<class T>
46bool Rect<T>::operator==(Rect<T> const& right) const
47{
48 return (this->_x == right._x) && (this->_width == right._width) && (this->_y == right._y) &&
49 (this->_height == right._height);
50}
51
52template<class T>
53bool Rect<T>::operator!=(Rect<T> const& right) const
54{
55 return !this->operator==(right);
56}
57
58template<class T>
59bool Rect<T>::contains(Vector2<T> const& point) const
60{
61 // Rectangles with negative dimensions are allowed, so we must handle them correctly
62 T const farX = static_cast<T>(this->_x + this->_width);
63 T const farY = static_cast<T>(this->_y + this->_height);
64
65 // Compute the real min and max of the rectangle on both axes
66 T const minX = (this->_x < farX) ? this->_x : farX;
67 T const maxX = (this->_x > farX) ? this->_x : farX;
68 T const minY = (this->_y < farY) ? this->_y : farY;
69 T const maxY = (this->_y > farY) ? this->_y : farY;
70
71 return (point.x >= minX) && (point.x < maxX) && (point.y >= minY) && (point.y < maxY);
72}
73
74template<class T>
75std::optional<Rect<T>> Rect<T>::findIntersection(Rect<T> const& rectangle) const
76{
77 // Rectangles with negative dimensions are allowed, so we must handle them correctly
78 T const r1FarX = static_cast<T>(this->_x + this->_width);
79 T const r1FarY = static_cast<T>(this->_y + this->_height);
80
81 T const r2FarX = static_cast<T>(rectangle._x + rectangle._width);
82 T const r2FarY = static_cast<T>(rectangle._y + rectangle._height);
83
84 // Compute the min and max of the first rectangle on both axes
85 T const r1MinX = (this->_x < r1FarX) ? this->_x : r1FarX;
86 T const r1MaxX = (this->_x > r1FarX) ? this->_x : r1FarX;
87 T const r1MinY = (this->_y < r1FarY) ? this->_y : r1FarY;
88 T const r1MaxY = (this->_y > r1FarY) ? this->_y : r1FarY;
89
90 // Compute the min and max of the second rectangle on both axes
91 T const r2MinX = (rectangle._x < r2FarX) ? rectangle._x : r2FarX;
92 T const r2MaxX = (rectangle._x > r2FarX) ? rectangle._x : r2FarX;
93 T const r2MinY = (rectangle._y < r2FarY) ? rectangle._y : r2FarY;
94 T const r2MaxY = (rectangle._y > r2FarY) ? rectangle._y : r2FarY;
95
96 // Compute the intersection boundaries
97 T const interLeft = (r1MinX > r2MinX) ? r1MinX : r2MinX;
98 T const interTop = (r1MinY > r2MinY) ? r1MinY : r2MinY;
99 T const interRight = (r1MaxX < r2MaxX) ? r1MaxX : r2MaxX;
100 T const interBottom = (r1MaxY < r2MaxY) ? r1MaxY : r2MaxY;
101
102 // If the intersection is valid (positive non-zero area), then there is an intersection
103 if ((interLeft < interRight) && (interTop < interBottom))
104 {
105 return Rect<T>({interLeft, interTop}, {interRight - interLeft, interBottom - interTop});
106 }
107 return std::nullopt;
108}
109
110template<class T>
111Vector2<T> Rect<T>::getPosition() const
112{
113 return Vector2<T>(this->_x, this->_y);
114}
115
116template<class T>
117Vector2<T> Rect<T>::getSize() const
118{
119 return Vector2<T>(this->_width, this->_height);
120}
121
122inline fge::RectFloat operator*(glm::mat4 const& left, fge::RectFloat const& right)
123{
124 // Transform the 4 corners of the rectangle
125 fge::Vector2f const points[] = {left * glm::vec4(right._x, right._y, 0.0f, 1.0f),
126 left * glm::vec4(right._x, right._y + right._height, 0.0f, 1.0f),
127 left * glm::vec4(right._x + right._width, right._y, 0.0f, 1.0f),
128 left * glm::vec4(right._x + right._width, right._y + right._height, 0.0f, 1.0f)};
129
130 // Compute the bounding rectangle of the transformed points
131 float posLeft = points[0].x;
132 float posTop = points[0].y;
133 float posRight = points[0].x;
134 float posBottom = points[0].y;
135 for (int i = 1; i < 4; ++i)
136 {
137 if (points[i].x < posLeft)
138 {
139 posLeft = points[i].x;
140 }
141 else if (points[i].x > posRight)
142 {
143 posRight = points[i].x;
144 }
145 if (points[i].y < posTop)
146 {
147 posTop = points[i].y;
148 }
149 else if (points[i].y > posBottom)
150 {
151 posBottom = points[i].y;
152 }
153 }
154
155 return fge::RectFloat({posLeft, posTop}, {posRight - posLeft, posBottom - posTop});
156}
157
158} // namespace fge