Line data Source code
1 :
2 : /* Copyright (c) 2006-2010, 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 <lunchbox/debug.h>
24 :
25 : #include <iostream>
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 18014 : Viewport() : x(0.0f), y(0.0f), w(1.0f), h(1.0f) {}
41 :
42 : /** Construct a fractional viewport with default values. @version 1.0 */
43 2414 : explicit Viewport( const float x_, const float y_,
44 : const float w_, const float h_ )
45 2414 : : x(x_), y(y_), w(w_), h(h_) {}
46 :
47 : /** Construct a fractional viewport from a Vector4f. @version 1.3.0 */
48 : explicit Viewport( const Vector4f& from )
49 : : x( from[0] ), y( from[1] ), w( from[2] ), h( from[3] ) {}
50 : //@}
51 :
52 : /** Make the viewport invalid. @internal */
53 334 : void invalidate() { x=0.0f; y=0.0f; w=-1.0f; h=-1.0f; }
54 :
55 : /** Apply (accumulate) another viewport. @internal */
56 1794 : void apply( const Viewport& rhs )
57 : {
58 1794 : LBASSERTINFO( isValid(), *this);
59 1794 : LBASSERTINFO( rhs.isValid(), rhs );
60 1794 : x += rhs.x * w;
61 1794 : y += rhs.y * h;
62 1794 : w *= rhs.w;
63 1794 : h *= rhs.h;
64 1794 : }
65 :
66 : /** Transform this viewport into the rhs viewport space. @internal */
67 1017 : void transform( const Viewport& rhs )
68 : {
69 1017 : w = w / rhs.w;
70 1017 : h = h / rhs.h;
71 1017 : x = ( x - rhs.x ) / rhs.w;
72 1017 : y = ( y - rhs.y ) / rhs.h;
73 1017 : }
74 :
75 : /**
76 : * @return true if the two viewports are identical.
77 : * @version 1.0
78 : */
79 2754 : bool operator == ( const Viewport& rhs ) const
80 : {
81 2754 : return ( x==rhs.x && y==rhs.y && w==rhs.w && h==rhs.h);
82 : }
83 :
84 : /**
85 : * @return true if the two viewports are not identical.
86 : * @version 1.0
87 : */
88 4625 : bool operator != ( const Viewport& rhs ) const
89 : {
90 4625 : return ( x!=rhs.x || y!=rhs.y || w!=rhs.w || h!=rhs.h);
91 : }
92 :
93 : /**
94 : * @return true if the viewport has a non-negative, but potentially
95 : * empty, size.
96 : * @version 1.0
97 : */
98 10152 : bool isValid() const
99 10152 : { return ( x>=0.0f && y>=0.0f && w>=0.0f && h>=0.0f ); }
100 :
101 : /**
102 : * @return true if the viewport has a non-zero area, i.e, it is
103 : * not empty.
104 : * @version 1.0
105 : */
106 3525 : bool hasArea() const { return (w>0.0f && h>0.0f); }
107 :
108 : /** @return the area of this viewport. @version 1.0 */
109 : float getArea() const { return w*h; }
110 :
111 : /** @return the X end position. @version 1.0 */
112 0 : float getXEnd() const { return x+w; }
113 :
114 : /** @return the Y end position. @version 1.0 */
115 0 : float getYEnd() const { return y+h; }
116 :
117 : /** Create the intersection of the two viewports. @version 1.0 */
118 1233 : void intersect( const Viewport& rhs )
119 : {
120 1233 : if( *this == rhs )
121 759 : return;
122 :
123 474 : if( !rhs.isValid() || !isValid() )
124 : {
125 0 : invalidate();
126 0 : return;
127 : }
128 :
129 474 : if( !rhs.hasArea() || !hasArea() )
130 : {
131 0 : x = 0;
132 0 : y = 0;
133 0 : w = 0;
134 0 : h = 0;
135 0 : return;
136 : }
137 :
138 474 : const float sEx = static_cast< float >( x + w );
139 474 : const float sEy = static_cast< float >( y + h );
140 474 : const float dEx = static_cast< float >( rhs.x + rhs.w );
141 474 : const float dEy = static_cast< float >( rhs.y + rhs.h );
142 :
143 474 : x = LB_MAX( x, rhs.x );
144 474 : y = LB_MAX( y, rhs.y );
145 474 : w = LB_MIN( sEx, dEx ) - x;
146 474 : h = LB_MIN( sEy, dEy ) - y;
147 : }
148 :
149 : /** Create the union of the two viewports. @version 1.0 */
150 : void unite( const Viewport& rhs )
151 : {
152 : const float xEnd = LB_MAX( getXEnd(), rhs.getXEnd( ));
153 : const float yEnd = LB_MAX( getYEnd(), rhs.getYEnd( ));
154 : x = LB_MIN( x, rhs.x );
155 : y = LB_MIN( y, rhs.y );
156 : w = xEnd - x;
157 : h = yEnd - y;
158 : }
159 :
160 : /**
161 : * Compute the coverage of another viewport on this viewport.
162 : * @internal
163 : */
164 368 : Viewport getCoverage( const Viewport& with ) const
165 : {
166 368 : Viewport coverage( with );
167 368 : coverage.intersect( *this ); // intersection
168 368 : coverage.transform( *this ); // in our coordinate system
169 :
170 368 : return coverage;
171 : }
172 :
173 : /** Apply the view coverage to this viewport. @internal */
174 : EQFABRIC_API void applyView( const Viewport& segmentVP,
175 : const Viewport& viewVP,
176 : const PixelViewport& pvp,
177 : const Vector4i& overdraw );
178 :
179 : float x; //!< The X coordinate
180 : float y; //!< The Y coordinate
181 : float w; //!< The width
182 : float h; //!< The height
183 :
184 : EQFABRIC_API static const Viewport FULL; //!< A full viewport.
185 : };
186 :
187 1408 : inline std::ostream& operator << ( std::ostream& os, const Viewport& vp )
188 : {
189 1408 : os << "[ " << vp.x << " " << vp.y << " " << vp.w << " " << vp.h << " ]";
190 1408 : return os;
191 : }
192 : }
193 : }
194 :
195 : namespace lunchbox
196 : {
197 0 : template<> inline void byteswap( eq::fabric::Viewport& value )
198 : {
199 0 : byteswap( value.x );
200 0 : byteswap( value.y );
201 0 : byteswap( value.w );
202 0 : byteswap( value.h );
203 0 : }
204 : }
205 : #endif // EQFABRIC_VIEWPORT_H
|