source: GTP/trunk/App/Demos/Geom/OgreStuff/include/OgreBitwise.h @ 1092

Revision 1092, 9.2 KB checked in by gumbau, 18 years ago (diff)

LodStrips? and LODTrees demos

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 number of bits a pattern must be shifted right by to
37            remove right-hand zeroes.
38        */
39                template<typename T>
40        static FORCEINLINE unsigned int getBitShift(T mask)
41                {
42                        if (mask == 0)
43                                return 0;
44
45                        unsigned int result = 0;
46                        while ((mask & 1) == 0) {
47                                ++result;
48                                mask >>= 1;
49                        }
50                        return result;
51                }
52
53        /** Takes a value with a given src bit mask, and produces another
54            value with a desired bit mask.
55            @remarks
56                This routine is useful for colour conversion.
57        */
58                template<typename SrcT, typename DestT>
59        static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
60                {
61                        // Mask off irrelevant source value bits (if any)
62                        srcValue = srcValue & srcBitMask;
63
64                        // Shift source down to bottom of DWORD
65                        const unsigned int srcBitShift = getBitShift(srcBitMask);
66                        srcValue >>= srcBitShift;
67
68                        // Get max value possible in source from srcMask
69                        const SrcT srcMax = srcBitMask >> srcBitShift;
70
71                        // Get max avaiable in dest
72                        const unsigned int destBitShift = getBitShift(destBitMask);
73                        const DestT destMax = destBitMask >> destBitShift;
74
75                        // Scale source value into destination, and shift back
76                        DestT destValue = (srcValue * destMax) / srcMax;
77                        return (destValue << destBitShift);
78                }
79
80        /**
81         * Convert N bit colour channel value to P bits. It fills P bits with the
82         * bit pattern repeated. (this is /((1<<n)-1) in fixed point)
83         */
84        static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p)
85        {
86            if(n > p)
87            {
88                // Less bits required than available; this is easy
89                value >>= n-p;
90            }
91            else if(n < p)
92            {
93                // More bits required than are there, do the fill
94                // Use old fashioned division, probably better than a loop
95                if(value == 0)
96                        value = 0;
97                else if(value == (static_cast<unsigned int>(1)<<n)-1)
98                        value = (1<<p)-1;
99                else    value = value*(1<<p)/((1<<n)-1);
100            }
101            return value;   
102        }
103
104        /**
105         * Convert floating point colour channel value between 0.0 and 1.0 (otherwise clamped)
106         * to integer of a certain number of bits. Works for any value of bits between 0 and 31.
107         */
108        static inline unsigned int floatToFixed(const float value, const unsigned int bits)
109        {
110            if(value <= 0.0f) return 0;
111            else if (value >= 1.0f) return (1<<bits)-1;
112            else return (unsigned int)(value * (1<<bits));     
113        }
114
115        /**
116         * Fixed point to float
117         */
118        static inline float fixedToFloat(unsigned value, unsigned int bits)
119        {
120            return (float)value/(float)((1<<bits)-1);
121        }
122
123        /**
124         * Write a n*8 bits integer value to memory in native endian.
125         */
126        static inline void intWrite(const void *dest, const int n, const unsigned int value)
127        {
128            switch(n) {
129                case 1:
130                    ((uint8*)dest)[0] = (uint8)value;
131                    break;
132                case 2:
133                    ((uint16*)dest)[0] = (uint16)value;
134                    break;
135                case 3:
136#if OGRE_ENDIAN == OGRE_ENDIAN_BIG     
137                    ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
138                    ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
139                    ((uint8*)dest)[2] = (uint8)(value & 0xFF);
140#else
141                    ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
142                    ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
143                    ((uint8*)dest)[0] = (uint8)(value & 0xFF);
144#endif
145                    break;
146                case 4:
147                    ((uint32*)dest)[0] = (uint32)value;               
148                    break;               
149            }       
150        }
151        /**
152         * Read a n*8 bits integer value to memory in native endian.
153         */
154        static inline unsigned int intRead(const void *src, int n) {
155            switch(n) {
156                case 1:
157                    return ((uint8*)src)[0];
158                case 2:
159                    return ((uint16*)src)[0];
160                case 3:
161#if OGRE_ENDIAN == OGRE_ENDIAN_BIG     
162                    return ((uint32)((uint8*)src)[0]<<16)|
163                            ((uint32)((uint8*)src)[1]<<8)|
164                            ((uint32)((uint8*)src)[2]);
165#else
166                    return ((uint32)((uint8*)src)[0])|
167                            ((uint32)((uint8*)src)[1]<<8)|
168                            ((uint32)((uint8*)src)[2]<<16);
169#endif
170                case 4:
171                    return ((uint32*)src)[0];
172            }
173            return 0; // ?
174        }
175
176        /** Convert a float32 to a float16 (NV_half_float)
177                Courtesy of OpenEXR
178        */
179        static inline uint16 floatToHalf(float i)
180        {
181            return floatToHalfI(*reinterpret_cast<uint32*>(&i));
182        }
183                /** Converts float in uint32 format to a a half in uint16 format
184                */
185        static inline uint16 floatToHalfI(uint32 i)
186        {
187            register int s =  (i >> 16) & 0x00008000;
188            register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
189            register int m =   i        & 0x007fffff;
190       
191            if (e <= 0)
192            {
193                if (e < -10)
194                {
195                    return 0;
196                }
197                m = (m | 0x00800000) >> (1 - e);
198       
199                return s | (m >> 13);
200            }
201            else if (e == 0xff - (127 - 15))
202            {
203                if (m == 0) // Inf
204                {
205                    return s | 0x7c00;
206                }
207                else    // NAN
208                {
209                    m >>= 13;
210                    return s | 0x7c00 | m | (m == 0);
211                }
212            }
213            else
214            {
215                if (e > 30) // Overflow
216                {
217                    return s | 0x7c00;
218                }
219       
220                return s | (e << 10) | (m >> 13);
221            }
222        }
223       
224        /**
225         * Convert a float16 (NV_half_float) to a float32
226         * Courtesy of OpenEXR
227         */
228        static inline float halfToFloat(uint16 y)
229        {
230            uint32 r = halfToFloatI(y);
231            return *reinterpret_cast<float*>(&r);
232        }
233                /** Converts a half in uint16 format to a float
234                        in uint32 format
235                 */
236        static inline uint32 halfToFloatI(uint16 y)
237        {
238            register int s = (y >> 15) & 0x00000001;
239            register int e = (y >> 10) & 0x0000001f;
240            register int m =  y        & 0x000003ff;
241       
242            if (e == 0)
243            {
244                if (m == 0) // Plus or minus zero
245                {
246                    return s << 31;
247                }
248                else // Denormalized number -- renormalize it
249                {
250                    while (!(m & 0x00000400))
251                    {
252                        m <<= 1;
253                        e -=  1;
254                    }
255       
256                    e += 1;
257                    m &= ~0x00000400;
258                }
259            }
260            else if (e == 31)
261            {
262                if (m == 0) // Inf
263                {
264                    return (s << 31) | 0x7f800000;
265                }
266                else // NaN
267                {
268                    return (s << 31) | 0x7f800000 | (m << 13);
269                }
270            }
271       
272            e = e + (127 - 15);
273            m = m << 13;
274       
275            return (s << 31) | (e << 23) | m;
276        }
277         
278
279    };
280}
281
282#endif
Note: See TracBrowser for help on using the repository browser.