Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

OgreBitwise.h

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright (c) 2000-2005 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #ifndef _Bitwise_H__
00026 #define _Bitwise_H__
00027 
00028 #include "OgrePrerequisites.h"
00029 
00030 namespace Ogre {
00031 
00034     class Bitwise {
00035     public:
00039         template<typename T>
00040         static FORCEINLINE unsigned int getBitShift(T mask)
00041         {
00042             if (mask == 0)
00043                 return 0;
00044 
00045             unsigned int result = 0;
00046             while ((mask & 1) == 0) {
00047                 ++result;
00048                 mask >>= 1;
00049             }
00050             return result;
00051         }
00052 
00058         template<typename SrcT, typename DestT>
00059         static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
00060         {
00061             // Mask off irrelevant source value bits (if any)
00062             srcValue = srcValue & srcBitMask;
00063 
00064             // Shift source down to bottom of DWORD
00065             const unsigned int srcBitShift = getBitShift(srcBitMask);
00066             srcValue >>= srcBitShift;
00067 
00068             // Get max value possible in source from srcMask
00069             const SrcT srcMax = srcBitMask >> srcBitShift;
00070 
00071             // Get max avaiable in dest
00072             const unsigned int destBitShift = getBitShift(destBitMask);
00073             const DestT destMax = destBitMask >> destBitShift;
00074 
00075             // Scale source value into destination, and shift back
00076             DestT destValue = (srcValue * destMax) / srcMax;
00077             return (destValue << destBitShift);
00078         }
00079 
00084         static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p) 
00085         {
00086             if(n > p) 
00087             {
00088                 // Less bits required than available; this is easy
00089                 value >>= n-p;
00090             } 
00091             else if(n < p)
00092             {
00093                 // More bits required than are there, do the fill
00094                 // Use old fashioned division, probably better than a loop
00095                 if(value == 0)
00096                         value = 0;
00097                 else if(value == (static_cast<unsigned int>(1)<<n)-1)
00098                         value = (1<<p)-1;
00099                 else    value = value*(1<<p)/((1<<n)-1);
00100             }
00101             return value;    
00102         }
00103 
00108         static inline unsigned int floatToFixed(const float value, const unsigned int bits)
00109         {
00110             if(value <= 0.0f) return 0;
00111             else if (value >= 1.0f) return (1<<bits)-1;
00112             else return (unsigned int)(value * (1<<bits));     
00113         }
00114 
00118         static inline float fixedToFloat(unsigned value, unsigned int bits)
00119         {
00120             return (float)value/(float)((1<<bits)-1);
00121         }
00122 
00126         static inline void intWrite(const void *dest, const int n, const unsigned int value)
00127         {
00128             switch(n) {
00129                 case 1:
00130                     ((uint8*)dest)[0] = (uint8)value;
00131                     break;
00132                 case 2:
00133                     ((uint16*)dest)[0] = (uint16)value;
00134                     break;
00135                 case 3:
00136 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG      
00137                     ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
00138                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
00139                     ((uint8*)dest)[2] = (uint8)(value & 0xFF);
00140 #else
00141                     ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
00142                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
00143                     ((uint8*)dest)[0] = (uint8)(value & 0xFF);
00144 #endif
00145                     break;
00146                 case 4:
00147                     ((uint32*)dest)[0] = (uint32)value;                
00148                     break;                
00149             }        
00150         }
00154         static inline unsigned int intRead(const void *src, int n) {
00155             switch(n) {
00156                 case 1:
00157                     return ((uint8*)src)[0];
00158                 case 2:
00159                     return ((uint16*)src)[0];
00160                 case 3:
00161 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG      
00162                     return ((uint32)((uint8*)src)[0]<<16)|
00163                             ((uint32)((uint8*)src)[1]<<8)|
00164                             ((uint32)((uint8*)src)[2]);
00165 #else
00166                     return ((uint32)((uint8*)src)[0])|
00167                             ((uint32)((uint8*)src)[1]<<8)|
00168                             ((uint32)((uint8*)src)[2]<<16);
00169 #endif
00170                 case 4:
00171                     return ((uint32*)src)[0];
00172             } 
00173             return 0; // ?
00174         }
00175 
00179         static inline uint16 floatToHalf(float i)
00180         {
00181             return floatToHalfI(*reinterpret_cast<uint32*>(&i));
00182         }
00185         static inline uint16 floatToHalfI(uint32 i)
00186         {
00187             register int s =  (i >> 16) & 0x00008000;
00188             register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
00189             register int m =   i        & 0x007fffff;
00190         
00191             if (e <= 0)
00192             {
00193                 if (e < -10)
00194                 {
00195                     return 0;
00196                 }
00197                 m = (m | 0x00800000) >> (1 - e);
00198         
00199                 return s | (m >> 13);
00200             }
00201             else if (e == 0xff - (127 - 15))
00202             {
00203                 if (m == 0) // Inf
00204                 {
00205                     return s | 0x7c00;
00206                 } 
00207                 else    // NAN
00208                 {
00209                     m >>= 13;
00210                     return s | 0x7c00 | m | (m == 0);
00211                 }
00212             }
00213             else
00214             {
00215                 if (e > 30) // Overflow
00216                 {
00217                     return s | 0x7c00;
00218                 }
00219         
00220                 return s | (e << 10) | (m >> 13);
00221             }
00222         }
00223         
00228         static inline float halfToFloat(uint16 y)
00229         {
00230             uint32 r = halfToFloatI(y);
00231             return *reinterpret_cast<float*>(&r);
00232         }
00236         static inline uint32 halfToFloatI(uint16 y)
00237         {
00238             register int s = (y >> 15) & 0x00000001;
00239             register int e = (y >> 10) & 0x0000001f;
00240             register int m =  y        & 0x000003ff;
00241         
00242             if (e == 0)
00243             {
00244                 if (m == 0) // Plus or minus zero
00245                 {
00246                     return s << 31;
00247                 }
00248                 else // Denormalized number -- renormalize it
00249                 {
00250                     while (!(m & 0x00000400))
00251                     {
00252                         m <<= 1;
00253                         e -=  1;
00254                     }
00255         
00256                     e += 1;
00257                     m &= ~0x00000400;
00258                 }
00259             }
00260             else if (e == 31)
00261             {
00262                 if (m == 0) // Inf
00263                 {
00264                     return (s << 31) | 0x7f800000;
00265                 }
00266                 else // NaN
00267                 {
00268                     return (s << 31) | 0x7f800000 | (m << 13);
00269                 }
00270             }
00271         
00272             e = e + (127 - 15);
00273             m = m << 13;
00274         
00275             return (s << 31) | (e << 23) | m;
00276         }
00277          
00278 
00279     };
00280 }
00281 
00282 #endif

Copyright © 2000-2005 by The OGRE Team
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Feb 12 12:59:41 2006