Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/forks/sandbox_light/src/external/ogremath/OgreBitwise.h @ 12373

Last change on this file since 12373 was 7908, checked in by rgrieder, 14 years ago

Stripped down trunk to form a new light sandbox.

  • Property svn:eol-style set to native
File size: 10.2 KB
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-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#ifndef _Bitwise_H__
30#define _Bitwise_H__
31
32#include "OgrePrerequisites.h"
33
34namespace Ogre {
35
36    /** Class for manipulating bit patterns.
37    */
38    class Bitwise {
39    public:
40        /** Returns the most significant bit set in a value.
41        */
42        static FORCEINLINE unsigned int mostSignificantBitSet(unsigned int value)
43        {
44            unsigned int result = 0;
45            while (value != 0) {
46                ++result;
47                value >>= 1;
48            }
49            return result-1;
50        }
51        /** Returns the closest power-of-two number greater or equal to value.
52            @note 0 and 1 are powers of two, so
53                firstPO2From(0)==0 and firstPO2From(1)==1.
54        */
55        static FORCEINLINE uint32 firstPO2From(uint32 n)
56        {
57            --n;           
58            n |= n >> 16;
59            n |= n >> 8;
60            n |= n >> 4;
61            n |= n >> 2;
62            n |= n >> 1;
63            ++n;
64            return n;
65        }
66        /** Determines whether the number is power-of-two or not.
67            @note 0 and 1 are tread as power of two.
68        */
69        template<typename T>
70        static FORCEINLINE bool isPO2(T n)
71        {
72            return (n & (n-1)) == 0;
73        }
74        /** Returns the number of bits a pattern must be shifted right by to
75            remove right-hand zeros.
76        */
77                template<typename T>
78        static FORCEINLINE unsigned int getBitShift(T mask)
79                {
80                        if (mask == 0)
81                                return 0;
82
83                        unsigned int result = 0;
84                        while ((mask & 1) == 0) {
85                                ++result;
86                                mask >>= 1;
87                        }
88                        return result;
89                }
90
91        /** Takes a value with a given src bit mask, and produces another
92            value with a desired bit mask.
93            @remarks
94                This routine is useful for colour conversion.
95        */
96                template<typename SrcT, typename DestT>
97        static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
98                {
99                        // Mask off irrelevant source value bits (if any)
100                        srcValue = srcValue & srcBitMask;
101
102                        // Shift source down to bottom of DWORD
103                        const unsigned int srcBitShift = getBitShift(srcBitMask);
104                        srcValue >>= srcBitShift;
105
106                        // Get max value possible in source from srcMask
107                        const SrcT srcMax = srcBitMask >> srcBitShift;
108
109                        // Get max available in dest
110                        const unsigned int destBitShift = getBitShift(destBitMask);
111                        const DestT destMax = destBitMask >> destBitShift;
112
113                        // Scale source value into destination, and shift back
114                        DestT destValue = (srcValue * destMax) / srcMax;
115                        return (destValue << destBitShift);
116                }
117
118        /**
119         * Convert N bit colour channel value to P bits. It fills P bits with the
120         * bit pattern repeated. (this is /((1<<n)-1) in fixed point)
121         */
122        static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p) 
123        {
124            if(n > p) 
125            {
126                // Less bits required than available; this is easy
127                value >>= n-p;
128            } 
129            else if(n < p)
130            {
131                // More bits required than are there, do the fill
132                // Use old fashioned division, probably better than a loop
133                if(value == 0)
134                        value = 0;
135                else if(value == (static_cast<unsigned int>(1)<<n)-1)
136                        value = (1<<p)-1;
137                else    value = value*(1<<p)/((1<<n)-1);
138            }
139            return value;   
140        }
141
142        /**
143         * Convert floating point colour channel value between 0.0 and 1.0 (otherwise clamped)
144         * to integer of a certain number of bits. Works for any value of bits between 0 and 31.
145         */
146        static inline unsigned int floatToFixed(const float value, const unsigned int bits)
147        {
148            if(value <= 0.0f) return 0;
149            else if (value >= 1.0f) return (1<<bits)-1;
150            else return (unsigned int)(value * (1<<bits));     
151        }
152
153        /**
154         * Fixed point to float
155         */
156        static inline float fixedToFloat(unsigned value, unsigned int bits)
157        {
158            return (float)value/(float)((1<<bits)-1);
159        }
160
161        /**
162         * Write a n*8 bits integer value to memory in native endian.
163         */
164        static inline void intWrite(void *dest, const int n, const unsigned int value)
165        {
166            switch(n) {
167                case 1:
168                    ((uint8*)dest)[0] = (uint8)value;
169                    break;
170                case 2:
171                    ((uint16*)dest)[0] = (uint16)value;
172                    break;
173                case 3:
174#if OGRE_ENDIAN == OGRE_ENDIAN_BIG     
175                    ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
176                    ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
177                    ((uint8*)dest)[2] = (uint8)(value & 0xFF);
178#else
179                    ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
180                    ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
181                    ((uint8*)dest)[0] = (uint8)(value & 0xFF);
182#endif
183                    break;
184                case 4:
185                    ((uint32*)dest)[0] = (uint32)value;               
186                    break;               
187            }       
188        }
189        /**
190         * Read a n*8 bits integer value to memory in native endian.
191         */
192        static inline unsigned int intRead(const void *src, int n) {
193            switch(n) {
194                case 1:
195                    return ((uint8*)src)[0];
196                case 2:
197                    return ((uint16*)src)[0];
198                case 3:
199#if OGRE_ENDIAN == OGRE_ENDIAN_BIG     
200                    return ((uint32)((uint8*)src)[0]<<16)|
201                            ((uint32)((uint8*)src)[1]<<8)|
202                            ((uint32)((uint8*)src)[2]);
203#else
204                    return ((uint32)((uint8*)src)[0])|
205                            ((uint32)((uint8*)src)[1]<<8)|
206                            ((uint32)((uint8*)src)[2]<<16);
207#endif
208                case 4:
209                    return ((uint32*)src)[0];
210            } 
211            return 0; // ?
212        }
213
214        /** Convert a float32 to a float16 (NV_half_float)
215                Courtesy of OpenEXR
216        */
217        static inline uint16 floatToHalf(float i)
218        {
219            union { float f; uint32 i; } v;
220            v.f = i;
221            return floatToHalfI(v.i);
222        }
223                /** Converts float in uint32 format to a a half in uint16 format
224                */
225        static inline uint16 floatToHalfI(uint32 i)
226        {
227            register int s =  (i >> 16) & 0x00008000;
228            register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
229            register int m =   i        & 0x007fffff;
230       
231            if (e <= 0)
232            {
233                if (e < -10)
234                {
235                    return 0;
236                }
237                m = (m | 0x00800000) >> (1 - e);
238       
239                return s | (m >> 13);
240            }
241            else if (e == 0xff - (127 - 15))
242            {
243                if (m == 0) // Inf
244                {
245                    return s | 0x7c00;
246                } 
247                else    // NAN
248                {
249                    m >>= 13;
250                    return s | 0x7c00 | m | (m == 0);
251                }
252            }
253            else
254            {
255                if (e > 30) // Overflow
256                {
257                    return s | 0x7c00;
258                }
259       
260                return s | (e << 10) | (m >> 13);
261            }
262        }
263       
264        /**
265         * Convert a float16 (NV_half_float) to a float32
266         * Courtesy of OpenEXR
267         */
268        static inline float halfToFloat(uint16 y)
269        {
270            union { float f; uint32 i; } v;
271            v.i = halfToFloatI(y);
272            return v.f;
273        }
274                /** Converts a half in uint16 format to a float
275                        in uint32 format
276                 */
277        static inline uint32 halfToFloatI(uint16 y)
278        {
279            register int s = (y >> 15) & 0x00000001;
280            register int e = (y >> 10) & 0x0000001f;
281            register int m =  y        & 0x000003ff;
282       
283            if (e == 0)
284            {
285                if (m == 0) // Plus or minus zero
286                {
287                    return s << 31;
288                }
289                else // Denormalized number -- renormalize it
290                {
291                    while (!(m & 0x00000400))
292                    {
293                        m <<= 1;
294                        e -=  1;
295                    }
296       
297                    e += 1;
298                    m &= ~0x00000400;
299                }
300            }
301            else if (e == 31)
302            {
303                if (m == 0) // Inf
304                {
305                    return (s << 31) | 0x7f800000;
306                }
307                else // NaN
308                {
309                    return (s << 31) | 0x7f800000 | (m << 13);
310                }
311            }
312       
313            e = e + (127 - 15);
314            m = m << 13;
315       
316            return (s << 31) | (e << 23) | m;
317        }
318         
319
320    };
321}
322
323#endif
Note: See TracBrowser for help on using the repository browser.