Line data Source code
1 :
2 : /* Copyright (c) 2006-2017, Stefan Eilemann <eile@equalizergraphics.com>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 : #ifndef EQFABRIC_VIEWPORT_H
19 : #define EQFABRIC_VIEWPORT_H
20 :
21 : #include <eq/fabric/api.h>
22 : #include <eq/fabric/types.h>
23 : #include <eq/fabric/vmmlib.h>
24 : #include <iostream>
25 : #include <lunchbox/debug.h>
26 :
27 : namespace eq
28 : {
29 : namespace fabric
30 : {
31 : std::ostream& operator<<(std::ostream& os, const Viewport& vp);
32 :
33 : /** A fractional viewport with methods for manipulation. */
34 : class Viewport
35 : {
36 : public:
37 : /** @name Constructors */
38 : //@{
39 : /** Construct a full fractional viewport. @version 1.0 */
40 31038 : Viewport()
41 31038 : : x(0.0f)
42 : , y(0.0f)
43 : , w(1.0f)
44 31038 : , h(1.0f)
45 : {
46 31038 : }
47 :
48 : /** Construct a fractional viewport with default values. @version 1.0 */
49 4580 : Viewport(const float x_, const float y_, const float w_, const float h_)
50 4580 : : x(x_)
51 : , y(y_)
52 : , w(w_)
53 4580 : , h(h_)
54 : {
55 4580 : }
56 :
57 : /** Construct a fractional viewport from a Vector4f. @version 1.3.0 */
58 : explicit Viewport(const Vector4f& from)
59 : : x(from[0])
60 : , y(from[1])
61 : , w(from[2])
62 : , h(from[3])
63 : {
64 : }
65 : //@}
66 :
67 : /** Make the viewport invalid. @internal */
68 736 : void invalidate()
69 : {
70 736 : x = 0.0f;
71 736 : y = 0.0f;
72 736 : w = -1.0f;
73 736 : h = -1.0f;
74 736 : }
75 :
76 : /** Apply (accumulate) another viewport. @internal */
77 1806 : void apply(const Viewport& rhs)
78 : {
79 1806 : LBASSERTINFO(isValid(), *this);
80 1806 : LBASSERTINFO(rhs.isValid(), rhs);
81 1806 : x += rhs.x * w;
82 1806 : y += rhs.y * h;
83 1806 : w *= rhs.w;
84 1806 : h *= rhs.h;
85 1806 : }
86 :
87 : /** Transform this viewport into the rhs viewport space. @internal */
88 1354 : void transform(const Viewport& rhs)
89 : {
90 1354 : w = w / rhs.w;
91 1354 : h = h / rhs.h;
92 1354 : x = (x - rhs.x) / rhs.w;
93 1354 : y = (y - rhs.y) / rhs.h;
94 1354 : }
95 :
96 : /**
97 : * @return true if the two viewports are identical.
98 : * @version 1.0
99 : */
100 4823 : bool operator==(const Viewport& rhs) const
101 : {
102 4823 : return (x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h);
103 : }
104 :
105 : /**
106 : * @return true if the two viewports are not identical.
107 : * @version 1.0
108 : */
109 6734 : bool operator!=(const Viewport& rhs) const
110 : {
111 6734 : return (x != rhs.x || y != rhs.y || w != rhs.w || h != rhs.h);
112 : }
113 :
114 : /**
115 : * @return true if the viewport has a non-negative, but potentially
116 : * empty, size.
117 : * @version 1.0
118 : */
119 11710 : bool isValid() const
120 : {
121 11710 : return (x >= 0.0f && y >= 0.0f && w >= 0.0f && h >= 0.0f);
122 : }
123 :
124 : /**
125 : * @return true if the viewport has a non-zero area, i.e, it is
126 : * not empty.
127 : * @version 1.0
128 : */
129 8740 : bool hasArea() const { return (w > 0.0f && h > 0.0f); }
130 : /** @return the area of this viewport. @version 1.0 */
131 : float getArea() const { return w * h; }
132 : /** @return the X end position. @version 1.0 */
133 18 : float getXEnd() const { return x + w; }
134 : /** @return the Y end position. @version 1.0 */
135 4 : float getYEnd() const { return y + h; }
136 : /** Create the intersection of the two viewports. @version 1.0 */
137 1798 : void intersect(const Viewport& rhs)
138 : {
139 1798 : if (*this == rhs)
140 774 : return;
141 :
142 1024 : if (!rhs.isValid() || !isValid())
143 : {
144 0 : invalidate();
145 0 : return;
146 : }
147 :
148 1024 : if (!rhs.hasArea() || !hasArea())
149 : {
150 0 : x = 0;
151 0 : y = 0;
152 0 : w = 0;
153 0 : h = 0;
154 0 : return;
155 : }
156 :
157 1024 : const float sEx = static_cast<float>(x + w);
158 1024 : const float sEy = static_cast<float>(y + h);
159 1024 : const float dEx = static_cast<float>(rhs.x + rhs.w);
160 1024 : const float dEy = static_cast<float>(rhs.y + rhs.h);
161 :
162 1024 : x = LB_MAX(x, rhs.x);
163 1024 : y = LB_MAX(y, rhs.y);
164 1024 : w = LB_MIN(sEx, dEx) - x;
165 1024 : h = LB_MIN(sEy, dEy) - y;
166 : }
167 :
168 : /** Create the union of the two viewports. @version 1.0 */
169 0 : void unite(const Viewport& rhs)
170 : {
171 0 : const float xEnd = LB_MAX(getXEnd(), rhs.getXEnd());
172 0 : const float yEnd = LB_MAX(getYEnd(), rhs.getYEnd());
173 0 : x = LB_MIN(x, rhs.x);
174 0 : y = LB_MIN(y, rhs.y);
175 0 : w = xEnd - x;
176 0 : h = yEnd - y;
177 0 : }
178 :
179 : /**
180 : * Compute the coverage of another viewport on this viewport.
181 : * @internal
182 : */
183 118 : Viewport getCoverage(const Viewport& with) const
184 : {
185 118 : Viewport coverage(with);
186 118 : coverage.intersect(*this); // intersection
187 118 : coverage.transform(*this); // in our coordinate system
188 :
189 118 : return coverage;
190 : }
191 :
192 : /** Apply the view coverage to this viewport. @internal */
193 : EQFABRIC_API void applyView(const Viewport& segmentVP,
194 : const Viewport& viewVP,
195 : const PixelViewport& pvp,
196 : const Vector4i& overdraw);
197 :
198 : float x; //!< The X coordinate
199 : float y; //!< The Y coordinate
200 : float w; //!< The width
201 : float h; //!< The height
202 :
203 : EQFABRIC_API static const Viewport FULL; //!< A full viewport.
204 : };
205 :
206 2396 : inline std::ostream& operator<<(std::ostream& os, const Viewport& vp)
207 : {
208 2396 : os << "[ " << vp.x << " " << vp.y << " " << vp.w << " " << vp.h << " ]";
209 2396 : return os;
210 : }
211 : }
212 : }
213 :
214 : #endif // EQFABRIC_VIEWPORT_H
|