source: OGRE/trunk/ogrenew/OgreMain/include/OgreBitwise.h @ 692

Revision 692, 10.0 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

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            return floatToHalfI(*reinterpret_cast<uint32*>(&i));
208        }
209                /** Converts float in uint32 format to a a half in uint16 format
210                */
211        static inline uint16 floatToHalfI(uint32 i)
212        {
213            register int s =  (i >> 16) & 0x00008000;
214            register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
215            register int m =   i        & 0x007fffff;
216       
217            if (e <= 0)
218            {
219                if (e < -10)
220                {
221                    return 0;
222                }
223                m = (m | 0x00800000) >> (1 - e);
224       
225                return s | (m >> 13);
226            }
227            else if (e == 0xff - (127 - 15))
228            {
229                if (m == 0) // Inf
230                {
231                    return s | 0x7c00;
232                }
233                else    // NAN
234                {
235                    m >>= 13;
236                    return s | 0x7c00 | m | (m == 0);
237                }
238            }
239            else
240            {
241                if (e > 30) // Overflow
242                {
243                    return s | 0x7c00;
244                }
245       
246                return s | (e << 10) | (m >> 13);
247            }
248        }
249       
250        /**
251         * Convert a float16 (NV_half_float) to a float32
252         * Courtesy of OpenEXR
253         */
254        static inline float halfToFloat(uint16 y)
255        {
256            uint32 r = halfToFloatI(y);
257            return *reinterpret_cast<float*>(&r);
258        }
259                /** Converts a half in uint16 format to a float
260                        in uint32 format
261                 */
262        static inline uint32 halfToFloatI(uint16 y)
263        {
264            register int s = (y >> 15) & 0x00000001;
265            register int e = (y >> 10) & 0x0000001f;
266            register int m =  y        & 0x000003ff;
267       
268            if (e == 0)
269            {
270                if (m == 0) // Plus or minus zero
271                {
272                    return s << 31;
273                }
274                else // Denormalized number -- renormalize it
275                {
276                    while (!(m & 0x00000400))
277                    {
278                        m <<= 1;
279                        e -=  1;
280                    }
281       
282                    e += 1;
283                    m &= ~0x00000400;
284                }
285            }
286            else if (e == 31)
287            {
288                if (m == 0) // Inf
289                {
290                    return (s << 31) | 0x7f800000;
291                }
292                else // NaN
293                {
294                    return (s << 31) | 0x7f800000 | (m << 13);
295                }
296            }
297       
298            e = e + (127 - 15);
299            m = m << 13;
300       
301            return (s << 31) | (e << 23) | m;
302        }
303         
304
305    };
306}
307
308#endif
Note: See TracBrowser for help on using the repository browser.