pixelViewport.h

00001 
00002 /* Copyright (c) 2006-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #ifndef EQ_PIXELVIEWPORT_H
00019 #define EQ_PIXELVIEWPORT_H
00020 
00021 #include <eq/client/viewport.h> // used in inline method
00022 #include <eq/client/pixel.h>    // used in inline method
00023 #include <eq/client/zoom.h>     // used in inline method
00024 #include <eq/client/types.h>
00025 
00026 #include <eq/base/base.h>
00027 #include <eq/base/debug.h>
00028 
00029 
00030 #include <limits>
00031 
00032 namespace eq
00033 {
00037     class PixelViewport 
00038     {
00039     public:
00044         PixelViewport() : x(0), y(0), w(-1), h(-1)  {}
00045 
00046         PixelViewport( const int32_t x_, const int32_t y_, 
00047                        const int32_t w_, const int32_t h_ )
00048                 : x(x_), y(y_), w(w_), h(h_)  {}
00050 
00054         void invalidate() { x = 0; y = 0; w = -1; h = -1; }
00055 
00060         bool isValid() const { return (w>=0 && h>=0); }
00061         
00066         bool hasArea() const { return (w>0 && h>0); }
00067 
00069         uint32_t getArea() const { return w * h; }
00070 
00075         void apply( const Viewport& rhs )
00076             {
00077                 // honor position over size to avoid rounding artifacts
00078                 const int32_t xEnd = x + static_cast<int32_t>((rhs.x+rhs.w)*w);
00079                 const int32_t yEnd = y + static_cast<int32_t>((rhs.y+rhs.h)*h);
00080 
00081                 x += static_cast<int32_t>( w * rhs.x );
00082                 y += static_cast<int32_t>( h * rhs.y );
00083                 w = xEnd - x;
00084                 h = yEnd - y;
00085             }
00086 
00087         void apply( const Pixel& pixel )
00088             {
00089                 if( pixel.w > 1 )
00090                 {
00091                     int32_t newWidth = w / pixel.w;
00092                     // This would be the correct thing to do, but it would
00093                     // require frustum adaptations in CUV::_computeFrustum:
00094                     //if( w - ( newWidth * pixel.w ) > pixel.x )
00095                     if( w - ( newWidth * pixel.w ) != 0 )
00096                         ++newWidth;
00097 
00098                     w = newWidth;
00099                 }
00100                 if( pixel.h > 1 )
00101                 {
00102                     int32_t newHeight = h / pixel.h;
00103                     // This would be the correct thing to do, but it would
00104                     // require frustum adaptations in CUV::_computeFrustum:
00105                     // if( w - ( newWidth * pixel.h ) > pixel.y )
00106                     if( h - ( newHeight * pixel.h ) != 0 )
00107                         ++newHeight;
00108 
00109                     h = newHeight;
00110                 }
00111         }
00112 
00113         void apply( const Zoom& zoom )
00114             {
00115                 if( zoom == Zoom::NONE )
00116                     return;
00117 
00118                 x = static_cast< int32_t >( x * zoom.x() + .5f );
00119                 y = static_cast< int32_t >( y * zoom.y() + .5f );
00120                 w = static_cast< int32_t >( w * zoom.x() + .5f );
00121                 h = static_cast< int32_t >( h * zoom.y() + .5f );
00122             }
00123 
00124         const PixelViewport getSubPVP( const Viewport& rhs ) const
00125             {
00126                 if( rhs == Viewport::FULL )
00127                     return *this;
00128 
00129                 PixelViewport result;
00130 
00131                 // honor position over size to avoid rounding artifacts
00132                 const int32_t xEnd = x + static_cast<int32_t>((rhs.x+rhs.w)*w);
00133                 const int32_t yEnd = y + static_cast<int32_t>((rhs.y+rhs.h)*h);
00134 
00135                 result.x = x + static_cast<int32_t>( w * rhs.x );
00136                 result.y = y + static_cast<int32_t>( h * rhs.y );
00137                 result.w = xEnd - result.x;
00138                 result.h = yEnd - result.y;
00139 
00140                 return result;
00141             }
00142 
00143         const Viewport getSubVP( const PixelViewport& rhs ) const
00144             {
00145                 if( *this == rhs )
00146                     return Viewport::FULL;
00147 
00148                 if( !rhs.hasArea( ))
00149                     return Viewport( static_cast<float>( x ), 
00150                                      static_cast<float>( y ), 0.f, 0.f );
00151 
00152                 return Viewport(  ( x - rhs.x )/ static_cast<float>( rhs.w ),
00153                                   ( y - rhs.y )/ static_cast<float>( rhs.h ),
00154                                   ( w )/ static_cast<float>( rhs.w ),
00155                                   ( h )/ static_cast<float>( rhs.h ));
00156             }
00157 
00158         const Zoom getZoom( const PixelViewport& rhs ) const
00159             {
00160                 if( *this == rhs )
00161                     return Zoom::NONE;
00162 
00163                 if( !rhs.hasArea( ))
00164                     return Zoom( std::numeric_limits< float >::max(), 
00165                                  std::numeric_limits< float >::max( ));
00166 
00167                 return Zoom( w / static_cast<float>( rhs.w ),
00168                              h / static_cast<float>( rhs.h ));
00169             }
00170 
00172         int32_t getXEnd() const { return x+w; }
00173 
00175         int32_t getYEnd() const { return y+h; }
00176 
00177         const PixelViewport operator + ( const Vector2i& offset ) const
00178             {
00179                 return PixelViewport( x+offset.x(), y+offset.y(), w, h );
00180             }
00181 
00182         const PixelViewport operator * ( const eq::Pixel& pixel ) const
00183             {
00184                 return PixelViewport( x, y, w * pixel.w, h * pixel.h );
00185             }
00186         PixelViewport& operator *= ( const eq::Pixel& pixel )
00187             {
00188                 w *= pixel.w;
00189                 h *= pixel.h;
00190                 x += pixel.x;
00191                 y += pixel.y;
00192                 return *this;
00193             }
00194 
00195         bool operator == ( const PixelViewport& rhs ) const 
00196             { 
00197                 return ( x==rhs.x && y==rhs.y && w==rhs.w && h==rhs.h );
00198             }
00199         bool operator != ( const PixelViewport& rhs ) const 
00200             { 
00201                 return ( x!=rhs.x || y!=rhs.y || w!=rhs.w || h!=rhs.h );
00202             }
00203 
00205         void merge( const PixelViewport& rhs )
00206             {
00207                 if( *this == rhs || !rhs.hasArea() )
00208                     return;
00209 
00210                 if( !hasArea() )
00211                 {
00212                     *this = rhs;
00213                     return;
00214                 }
00215 
00216                 const int32_t sEx =     x +     w;
00217                 const int32_t sEy =     y +     h;
00218                 const int32_t dEx = rhs.x + rhs.w;
00219                 const int32_t dEy = rhs.y + rhs.h;
00220                 
00221                 x = EQ_MIN( x, rhs.x );
00222                 y = EQ_MIN( y, rhs.y );
00223                 w = EQ_MAX( sEx, dEx ) - x;
00224                 h = EQ_MAX( sEy, dEy ) - y;
00225             }
00226 
00228         void intersect( const PixelViewport& rhs )
00229             {
00230                 if( *this == rhs )
00231                     return;
00232 
00233                 if( !rhs.isValid() || !isValid() )
00234                 {
00235                     invalidate();
00236                     return;
00237                 }
00238                 
00239                 if( !rhs.hasArea() || !hasArea() )
00240                 {
00241                     x = 0;
00242                     y = 0;
00243                     w = 0;
00244                     h = 0;
00245                     return;
00246                 }
00247                 
00248                 const int32_t sEx =     x +     w;
00249                 const int32_t sEy =     y +     h;
00250                 const int32_t dEx = rhs.x + rhs.w;
00251                 const int32_t dEy = rhs.y + rhs.h;
00252                     
00253                 x = EQ_MAX( x, rhs.x );
00254                 y = EQ_MAX( y, rhs.y );
00255                 w = EQ_MIN( sEx, dEx ) - x;
00256                 h = EQ_MIN( sEy, dEy ) - y;
00257             }
00258 
00260 
00266         bool isPointInside( const int32_t pX, const int32_t pY ) const
00267             {
00268                 if( pX < x || pY < y || pX > (x+w) || pY > (y+h) )
00269                     return false;
00270                 return true;
00271             }
00272 
00273         int32_t x;
00274         int32_t y;
00275         int32_t w;
00276         int32_t h;
00277     };
00278 
00279     inline std::ostream& operator << ( std::ostream& os, 
00280                                        const PixelViewport& pvp )
00281     {
00282         os << "[ " << pvp.x << " " << pvp.y << " " << pvp.w << " " << pvp.h
00283            <<" ]";
00284         return os;
00285     }
00286 }
00287 
00288 #endif // EQ_PIXELVIEWPORT_H
Generated on Mon Aug 10 18:58:40 2009 for Equalizer 0.9 by  doxygen 1.5.8