source: GTP/trunk/Lib/Geom/OgreStuff/include/OgreBitwise.h @ 1809

Revision 1809, 10.1 KB checked in by gumbau, 18 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#ifndef _Bitwise_H__
26#define _Bitwise_H__
27
28#include "OgrePrerequisites.h"
29
30namespace Ogre {
31
32    /** Class for manipulating bit patterns.
33    */
34    class Bitwise {
35    public:
36        /** Returns the most significant bit set in a value.
37        */
38        static FORCEINLINE unsigned int mostSignificantBitSet(unsigned int value)
39        {
40            unsigned int result = 0;
41            while (value != 0) {
42                ++result;
43                value >>= 1;
44            }
45            return result-1;
46        }
47        /** Returns the closest power-of-two number greater or equal to value.
48            @note 0 and 1 are powers of two, so
49                firstPO2From(0)==0 and firstPO2From(1)==1.
50        */
51        static FORCEINLINE uint32 firstPO2From(uint32 n)
52        {
53            --n;           
54            n |= n >> 16;
55            n |= n >> 8;
56            n |= n >> 4;
57            n |= n >> 2;
58            n |= n >> 1;
59            ++n;
60            return n;
61        }
62        /** Returns the number of bits a pattern must be shifted right by to
63            remove right-hand zeroes.
64        */
65                template<typename T>
66        static FORCEINLINE unsigned int getBitShift(T mask)
67                {
68                        if (mask == 0)
69                                return 0;
70
71                        unsigned int result = 0;
72                        while ((mask & 1) == 0) {
73                                ++result;
74                                mask >>= 1;
75                        }
76                        return result;
77                }
78
79        /** Takes a value with a given src bit mask, and produces another
80            value with a desired bit mask.
81            @remarks
82                This routine is useful for colour conversion.
83        */
84                template<typename SrcT, typename DestT>
85        static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
86                {
87                        // Mask off irrelevant source value bits (if any)
88                        srcValue = srcValue & srcBitMask;
89
90                        // Shift source down to bottom of DWORD
91                        const unsigned int srcBitShift = getBitShift(srcBitMask);
92                        srcValue >>= srcBitShift;
93
94                        // Get max value possible in source from srcMask
95                        const SrcT srcMax = srcBitMask >> srcBitShift;
96
97                        // Get max avaiable in dest
98                        const unsigned int destBitShift = getBitShift(destBitMask);
99                        const DestT destMax = destBitMask >> destBitShift;
100
101                        // Scale source value into destination, and shift back
102                        DestT destValue = (srcValue * destMax) / srcMax;
103                        return (destValue << destBitShift);
104                }
105
106        /**
107         * Convert N bit colour channel value to P bits. It fills P bits with the
108         * bit pattern repeated. (this is /((1<<n)-1) in fixed point)
109         */
110        static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p)
111        {
112            if(n > p)
113            {
114                // Less bits required than available; this is easy
115                value >>= n-p;
116            }
117            else if(n < p)
118            {
119                // More bits required than are there, do the fill
120                // Use old fashioned division, probably better than a loop
121                if(value == 0)
122                        value = 0;
123                else if(value == (static_cast<unsigned int>(1)<<n)-1)
124                        value = (1<<p)-1;
125                else    value = value*(1<<p)/((1<<n)-1);
126            }
127            return value;   
128        }
129
130        /**
131         * Convert floating point colour channel value between 0.0 and 1.0 (otherwise clamped)
132         * to integer of a certain number of bits. Works for any value of bits between 0 and 31.
133         */
134        static inline unsigned int floatToFixed(const float value, const unsigned int bits)
135        {
136            if(value <= 0.0f) return 0;
137            else if (value >= 1.0f) return (1<<bits)-1;
138            else return (unsigned int)(value * (1<<bits));     
139        }
140
141        /**
142         * Fixed point to float
143         */
144        static inline float fixedToFloat(unsigned value, unsigned int bits)
145        {
146            return (float)value/(float)((1<<bits)-1);
147        }
148
149        /**
150         * Write a n*8 bits integer value to memory in native endian.
151         */
152        static inline void intWrite(const void *dest, const int n, const unsigned int value)
153        {
154            switch(n) {
155                case 1:
156                    ((uint8*)dest)[0] = (uint8)value;
157                    break;
158                case 2:
159                    ((uint16*)dest)[0] = (uint16)value;
160                    break;
161                case 3:
162#if OGRE_ENDIAN == OGRE_ENDIAN_BIG     
163                    ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
164                    ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
165                    ((uint8*)dest)[2] = (uint8)(value & 0xFF);
166#else
167                    ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
168                    ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
169                    ((uint8*)dest)[0] = (uint8)(value & 0xFF);
170#endif
171                    break;
172                case 4:
173                    ((uint32*)dest)[0] = (uint32)value;               
174                    break;               
175            }       
176        }
177        /**
178         * Read a n*8 bits integer value to memory in native endian.
179         */
180        static inline unsigned int intRead(const void *src, int n) {
181            switch(n) {
182                case 1:
183                    return ((uint8*)src)[0];
184                case 2:
185                    return ((uint16*)src)[0];
186                case 3:
187#if OGRE_ENDIAN == OGRE_ENDIAN_BIG     
188                    return ((uint32)((uint8*)src)[0]<<16)|
189                            ((uint32)((uint8*)src)[1]<<8)|
190                            ((uint32)((uint8*)src)[2]);
191#else
192                    return ((uint32)((uint8*)src)[0])|
193                            ((uint32)((uint8*)src)[1]<<8)|
194                            ((uint32)((uint8*)src)[2]<<16);
195#endif
196                case 4:
197                    return ((uint32*)src)[0];
198            }
199            return 0; // ?
200        }
201
202        /** Convert a float32 to a float16 (NV_half_float)
203                Courtesy of OpenEXR
204        */
205        static inline uint16 floatToHalf(float i)
206        {
207            union { float f; uint32 i; } v;
208            v.f = i;
209            return floatToHalfI(v.i);
210        }
211                /** Converts float in uint32 format to a a half in uint16 format
212                */
213        static inline uint16 floatToHalfI(uint32 i)
214        {
215            register int s =  (i >> 16) & 0x00008000;
216            register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
217            register int m =   i        & 0x007fffff;
218       
219            if (e <= 0)
220            {
221                if (e < -10)
222                {
223                    return 0;
224                }
225                m = (m | 0x00800000) >> (1 - e);
226       
227                return s | (m >> 13);
228            }
229            else if (e == 0xff - (127 - 15))
230            {
231                if (m == 0) // Inf
232                {
233                    return s | 0x7c00;
234                }
235                else    // NAN
236                {
237                    m >>= 13;
238                    return s | 0x7c00 | m | (m == 0);
239                }
240            }
241            else
242            {
243                if (e > 30) // Overflow
244                {
245                    return s | 0x7c00;
246                }
247       
248                return s | (e << 10) | (m >> 13);
249            }
250        }
251       
252        /**
253         * Convert a float16 (NV_half_float) to a float32
254         * Courtesy of OpenEXR
255         */
256        static inline float halfToFloat(uint16 y)
257        {
258            union { float f; uint32 i; } v;
259            v.i = halfToFloatI(y);
260            return v.f;
261        }
262                /** Converts a half in uint16 format to a float
263                        in uint32 format
264                 */
265        static inline uint32 halfToFloatI(uint16 y)
266        {
267            register int s = (y >> 15) & 0x00000001;
268            register int e = (y >> 10) & 0x0000001f;
269            register int m =  y        & 0x000003ff;
270       
271            if (e == 0)
272            {
273                if (m == 0) // Plus or minus zero
274                {
275                    return s << 31;
276                }
277                else // Denormalized number -- renormalize it
278                {
279                    while (!(m & 0x00000400))
280                    {
281                        m <<= 1;
282                        e -=  1;
283                    }
284       
285                    e += 1;
286                    m &= ~0x00000400;
287                }
288            }
289            else if (e == 31)
290            {
291                if (m == 0) // Inf
292                {
293                    return (s << 31) | 0x7f800000;
294                }
295                else // NaN
296                {
297                    return (s << 31) | 0x7f800000 | (m << 13);
298                }
299            }
300       
301            e = e + (127 - 15);
302            m = m << 13;
303       
304            return (s << 31) | (e << 23) | m;
305        }
306         
307
308    };
309}
310
311#endif
Note: See TracBrowser for help on using the repository browser.