Home | History | Annotate | Download | only in gtc
      1 ///////////////////////////////////////////////////////////////////////////////////
      2 /// OpenGL Mathematics (glm.g-truc.net)
      3 ///
      4 /// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
      5 /// Permission is hereby granted, free of charge, to any person obtaining a copy
      6 /// of this software and associated documentation files (the "Software"), to deal
      7 /// in the Software without restriction, including without limitation the rights
      8 /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9 /// copies of the Software, and to permit persons to whom the Software is
     10 /// furnished to do so, subject to the following conditions:
     11 /// 
     12 /// The above copyright notice and this permission notice shall be included in
     13 /// all copies or substantial portions of the Software.
     14 /// 
     15 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     18 /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20 /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     21 /// THE SOFTWARE.
     22 ///
     23 /// @ref gtc_packing
     24 /// @file glm/gtc/packing.inl
     25 /// @date 2013-08-08 / 2013-08-08
     26 /// @author Christophe Riccio
     27 ///////////////////////////////////////////////////////////////////////////////////
     28 
     29 #include "../common.hpp"
     30 #include "../vec2.hpp"
     31 #include "../vec3.hpp"
     32 #include "../vec4.hpp"
     33 #include "../detail/type_half.hpp"
     34 
     35 namespace glm{
     36 namespace detail
     37 {
     38 	GLM_FUNC_QUALIFIER glm::uint16 float2half(glm::uint32 const & f)
     39 	{
     40 		// 10 bits    =>                         EE EEEFFFFF
     41 		// 11 bits    =>                        EEE EEFFFFFF
     42 		// Half bits  =>                   SEEEEEFF FFFFFFFF
     43 		// Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF
     44 
     45 		// 0x00007c00 => 00000000 00000000 01111100 00000000
     46 		// 0x000003ff => 00000000 00000000 00000011 11111111
     47 		// 0x38000000 => 00111000 00000000 00000000 00000000
     48 		// 0x7f800000 => 01111111 10000000 00000000 00000000
     49 		// 0x00008000 => 00000000 00000000 10000000 00000000
     50 		return
     51 			((f >> 16) & 0x8000) | // sign
     52 			((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | // exponential
     53 			((f >> 13) & 0x03ff); // Mantissa
     54 	}
     55 
     56 	GLM_FUNC_QUALIFIER glm::uint32 float2packed11(glm::uint32 const & f)
     57 	{
     58 		// 10 bits    =>                         EE EEEFFFFF
     59 		// 11 bits    =>                        EEE EEFFFFFF
     60 		// Half bits  =>                   SEEEEEFF FFFFFFFF
     61 		// Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF
     62 
     63 		// 0x000007c0 => 00000000 00000000 00000111 11000000
     64 		// 0x00007c00 => 00000000 00000000 01111100 00000000
     65 		// 0x000003ff => 00000000 00000000 00000011 11111111
     66 		// 0x38000000 => 00111000 00000000 00000000 00000000
     67 		// 0x7f800000 => 01111111 10000000 00000000 00000000
     68 		// 0x00008000 => 00000000 00000000 10000000 00000000
     69 		return
     70 			((((f & 0x7f800000) - 0x38000000) >> 17) & 0x07c0) | // exponential
     71 			((f >> 17) & 0x003f); // Mantissa
     72 	}
     73 
     74 	GLM_FUNC_QUALIFIER glm::uint32 packed11ToFloat(glm::uint32 const & p)
     75 	{
     76 		// 10 bits    =>                         EE EEEFFFFF
     77 		// 11 bits    =>                        EEE EEFFFFFF
     78 		// Half bits  =>                   SEEEEEFF FFFFFFFF
     79 		// Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF
     80 
     81 		// 0x000007c0 => 00000000 00000000 00000111 11000000
     82 		// 0x00007c00 => 00000000 00000000 01111100 00000000
     83 		// 0x000003ff => 00000000 00000000 00000011 11111111
     84 		// 0x38000000 => 00111000 00000000 00000000 00000000
     85 		// 0x7f800000 => 01111111 10000000 00000000 00000000
     86 		// 0x00008000 => 00000000 00000000 10000000 00000000
     87 		return
     88 			((((p & 0x07c0) << 17) + 0x38000000) & 0x7f800000) | // exponential
     89 			((p & 0x003f) << 17); // Mantissa
     90 	}
     91 
     92 	GLM_FUNC_QUALIFIER glm::uint32 float2packed10(glm::uint32 const & f)
     93 	{
     94 		// 10 bits    =>                         EE EEEFFFFF
     95 		// 11 bits    =>                        EEE EEFFFFFF
     96 		// Half bits  =>                   SEEEEEFF FFFFFFFF
     97 		// Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF
     98 
     99 		// 0x0000001F => 00000000 00000000 00000000 00011111
    100 		// 0x0000003F => 00000000 00000000 00000000 00111111
    101 		// 0x000003E0 => 00000000 00000000 00000011 11100000
    102 		// 0x000007C0 => 00000000 00000000 00000111 11000000
    103 		// 0x00007C00 => 00000000 00000000 01111100 00000000
    104 		// 0x000003FF => 00000000 00000000 00000011 11111111
    105 		// 0x38000000 => 00111000 00000000 00000000 00000000
    106 		// 0x7f800000 => 01111111 10000000 00000000 00000000
    107 		// 0x00008000 => 00000000 00000000 10000000 00000000
    108 		return
    109 			((((f & 0x7f800000) - 0x38000000) >> 18) & 0x03E0) | // exponential
    110 			((f >> 18) & 0x001f); // Mantissa
    111 	}
    112 
    113 	GLM_FUNC_QUALIFIER glm::uint32 packed10ToFloat(glm::uint32 const & p)
    114 	{
    115 		// 10 bits    =>                         EE EEEFFFFF
    116 		// 11 bits    =>                        EEE EEFFFFFF
    117 		// Half bits  =>                   SEEEEEFF FFFFFFFF
    118 		// Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF
    119 
    120 		// 0x0000001F => 00000000 00000000 00000000 00011111
    121 		// 0x0000003F => 00000000 00000000 00000000 00111111
    122 		// 0x000003E0 => 00000000 00000000 00000011 11100000
    123 		// 0x000007C0 => 00000000 00000000 00000111 11000000
    124 		// 0x00007C00 => 00000000 00000000 01111100 00000000
    125 		// 0x000003FF => 00000000 00000000 00000011 11111111
    126 		// 0x38000000 => 00111000 00000000 00000000 00000000
    127 		// 0x7f800000 => 01111111 10000000 00000000 00000000
    128 		// 0x00008000 => 00000000 00000000 10000000 00000000
    129 		return
    130 			((((p & 0x03E0) << 18) + 0x38000000) & 0x7f800000) | // exponential
    131 			((p & 0x001f) << 18); // Mantissa
    132 	}
    133 
    134 	GLM_FUNC_QUALIFIER glm::uint half2float(glm::uint const & h)
    135 	{
    136 		return ((h & 0x8000) << 16) | ((( h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13);
    137 	}
    138 
    139 	GLM_FUNC_QUALIFIER glm::uint floatTo11bit(float x)
    140 	{
    141 		if(x == 0.0f)
    142 			return 0;
    143 		else if(glm::isnan(x))
    144 			return ~0;
    145 		else if(glm::isinf(x))
    146 			return 0x1f << 6;
    147 
    148 		return float2packed11(reinterpret_cast<uint&>(x));
    149 	}
    150 
    151 	GLM_FUNC_QUALIFIER float packed11bitToFloat(glm::uint x)
    152 	{
    153 		if(x == 0)
    154 			return 0.0f;
    155 		else if(x == ((1 << 11) - 1))
    156 			return ~0;//NaN
    157 		else if(x == (0x1f << 6))
    158 			return ~0;//Inf
    159 
    160 		uint result = packed11ToFloat(x);
    161 		return reinterpret_cast<float&>(result);
    162 	}
    163 
    164 	GLM_FUNC_QUALIFIER glm::uint floatTo10bit(float x)
    165 	{
    166 		if(x == 0.0f)
    167 			return 0;
    168 		else if(glm::isnan(x))
    169 			return ~0;
    170 		else if(glm::isinf(x))
    171 			return 0x1f << 5;
    172 
    173 		return float2packed10(reinterpret_cast<uint&>(x));
    174 	}
    175 
    176 	GLM_FUNC_QUALIFIER float packed10bitToFloat(glm::uint x)
    177 	{
    178 		if(x == 0)
    179 			return 0.0f;
    180 		else if(x == ((1 << 10) - 1))
    181 			return ~0;//NaN
    182 		else if(x == (0x1f << 5))
    183 			return ~0;//Inf
    184 
    185 		uint result = packed10ToFloat(x);
    186 		return reinterpret_cast<float&>(result);
    187 	}
    188 
    189 //	GLM_FUNC_QUALIFIER glm::uint f11_f11_f10(float x, float y, float z)
    190 //	{
    191 //		return ((floatTo11bit(x) & ((1 << 11) - 1)) << 0) |  ((floatTo11bit(y) & ((1 << 11) - 1)) << 11) | ((floatTo10bit(z) & ((1 << 10) - 1)) << 22);
    192 //	}
    193 
    194 	union u10u10u10u2
    195 	{
    196 		struct
    197 		{
    198 			uint x : 10;
    199 			uint y : 10;
    200 			uint z : 10;
    201 			uint w : 2;
    202 		} data;
    203 		uint32 pack;
    204 	};
    205 
    206 	union i10i10i10i2
    207 	{
    208 		struct
    209 		{
    210 			int x : 10;
    211 			int y : 10;
    212 			int z : 10;
    213 			int w : 2;
    214 		} data;
    215 		uint32 pack;
    216 	};
    217 
    218 }//namespace detail
    219 
    220 	GLM_FUNC_QUALIFIER uint8 packUnorm1x8(float const & v)
    221 	{
    222 		return static_cast<uint8>(round(clamp(v, 0.0f, 1.0f) * 255.0f));
    223 	}
    224 	
    225 	GLM_FUNC_QUALIFIER float unpackUnorm1x8(uint8 const & p)
    226 	{
    227 		float Unpack(static_cast<float>(p));
    228 		return Unpack * static_cast<float>(0.0039215686274509803921568627451); // 1 / 255
    229 	}
    230 	
    231 	GLM_FUNC_QUALIFIER uint16 packUnorm2x8(vec2 const & v)
    232 	{
    233 		u8vec2 Topack(round(clamp(v, 0.0f, 1.0f) * 255.0f));
    234 		uint16* Packed = reinterpret_cast<uint16*>(&Topack);
    235 		return *Packed;
    236 	}
    237 	
    238 	GLM_FUNC_QUALIFIER vec2 unpackUnorm2x8(uint16 const & p)
    239 	{
    240 		u8vec2* Unpacked = reinterpret_cast<u8vec2*>(const_cast<uint16*>(&p));
    241 		return vec2(*Unpacked) * float(0.0039215686274509803921568627451); // 1 / 255
    242 	}
    243 
    244 	GLM_FUNC_QUALIFIER uint8 packSnorm1x8(float const & v)
    245 	{
    246 		int8 Topack(static_cast<int8>(round(clamp(v ,-1.0f, 1.0f) * 127.0f)));
    247 		uint8* Packed = reinterpret_cast<uint8*>(&Topack);
    248 		return *Packed;
    249 	}
    250 	
    251 	GLM_FUNC_QUALIFIER float unpackSnorm1x8(uint8 const & p)
    252 	{
    253 		float Unpack(static_cast<float>(*const_cast<uint8*>(&p)));
    254 		return clamp(
    255 			Unpack * 0.00787401574803149606299212598425f, // 1.0f / 127.0f
    256 			-1.0f, 1.0f);
    257 	}
    258 	
    259 	GLM_FUNC_QUALIFIER uint16 packSnorm2x8(vec2 const & v)
    260 	{
    261 		i8vec2 Topack(round(clamp(v ,-1.0f, 1.0f) * 127.0f));
    262 		uint16* Packed = reinterpret_cast<uint16*>(&Topack);
    263 		return *Packed;
    264 	}
    265 	
    266 	GLM_FUNC_QUALIFIER vec2 unpackSnorm2x8(uint16 const & p)
    267 	{
    268 		i8vec2* Unpack = reinterpret_cast<i8vec2*>(const_cast<uint16*>(&p));
    269 		return clamp(
    270 			vec2(*Unpack) * 0.00787401574803149606299212598425f, // 1.0f / 127.0f
    271 			-1.0f, 1.0f);
    272 	}
    273 	
    274 	GLM_FUNC_QUALIFIER uint16 packUnorm1x16(float const & s)
    275 	{
    276 		return static_cast<uint16>(round(clamp(s, 0.0f, 1.0f) * 65535.0f));
    277 	}
    278 
    279 	GLM_FUNC_QUALIFIER float unpackUnorm1x16(uint16 const & p)
    280 	{
    281 		float Unpack = static_cast<float>(*const_cast<uint16*>(&p));
    282 		return Unpack * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0
    283 	}
    284 
    285 	GLM_FUNC_QUALIFIER uint64 packUnorm4x16(vec4 const & v)
    286 	{
    287 		u16vec4 Topack(round(clamp(v , 0.0f, 1.0f) * 65535.0f));
    288 		uint64* Packed = reinterpret_cast<uint64*>(&Topack);
    289 		return *Packed;
    290 	}
    291 
    292 	GLM_FUNC_QUALIFIER vec4 unpackUnorm4x16(uint64 const & p)
    293 	{
    294 		u16vec4* Unpack = reinterpret_cast<u16vec4*>(const_cast<uint64*>(&p));
    295 		return vec4(*Unpack) * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0
    296 	}
    297 
    298 	GLM_FUNC_QUALIFIER uint16 packSnorm1x16(float const & v)
    299 	{
    300 		int16 Topack = static_cast<int16>(round(clamp(v ,-1.0f, 1.0f) * 32767.0f));
    301 		uint16* Packed = reinterpret_cast<uint16*>(&Topack);
    302 		return *Packed;
    303 	}
    304 
    305 	GLM_FUNC_QUALIFIER float unpackSnorm1x16(uint16 const & p)
    306 	{
    307 		float Unpack = static_cast<float>(*const_cast<uint16*>(&p));
    308 		return clamp(
    309 			Unpack * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, 
    310 			-1.0f, 1.0f);
    311 	}
    312 
    313 	GLM_FUNC_QUALIFIER uint64 packSnorm4x16(vec4 const & v)
    314 	{
    315 		i16vec4 Topack = static_cast<i16vec4>(round(clamp(v ,-1.0f, 1.0f) * 32767.0f));
    316 		uint64* Packed = reinterpret_cast<uint64*>(&Topack);
    317 		return *Packed;
    318 	}
    319 
    320 	GLM_FUNC_QUALIFIER vec4 unpackSnorm4x16(uint64 const & p)
    321 	{
    322 		i16vec4* Unpack(reinterpret_cast<i16vec4*>(const_cast<uint64*>(&p)));
    323 		return clamp(
    324 			vec4(*Unpack) * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f,
    325 			-1.0f, 1.0f);
    326 	}
    327 
    328 	GLM_FUNC_QUALIFIER uint16 packHalf1x16(float const & v)
    329 	{
    330 		int16 Topack = detail::toFloat16(v);
    331 		uint16* Packed = reinterpret_cast<uint16*>(&Topack);
    332 		return *Packed;
    333 	}
    334 
    335 	GLM_FUNC_QUALIFIER float unpackHalf1x16(uint16 const & v)
    336 	{
    337 		int16* Unpack = reinterpret_cast<int16*>(const_cast<uint16*>(&v));
    338 		return detail::toFloat32(*Unpack);
    339 	}
    340 
    341 	GLM_FUNC_QUALIFIER uint64 packHalf4x16(glm::vec4 const & v)
    342 	{
    343 		i16vec4 Unpack(
    344 			detail::toFloat16(v.x),
    345 			detail::toFloat16(v.y),
    346 			detail::toFloat16(v.z),
    347 			detail::toFloat16(v.w));
    348 
    349 		uint64* Packed = reinterpret_cast<uint64*>(&Unpack);
    350 		return *Packed;
    351 	}
    352 
    353 	GLM_FUNC_QUALIFIER glm::vec4 unpackHalf4x16(uint64 const & v)
    354 	{
    355 		i16vec4* p = reinterpret_cast<i16vec4*>(const_cast<uint64*>(&v));
    356 		i16vec4 Unpack(*p);
    357 	
    358 		return vec4(
    359 			detail::toFloat32(Unpack.x), 
    360 			detail::toFloat32(Unpack.y), 
    361 			detail::toFloat32(Unpack.z), 
    362 			detail::toFloat32(Unpack.w));
    363 	}
    364 
    365 	GLM_FUNC_QUALIFIER uint32 packI3x10_1x2(ivec4 const & v)
    366 	{
    367 		detail::i10i10i10i2 Result;
    368 		Result.data.x = v.x;
    369 		Result.data.y = v.y;
    370 		Result.data.z = v.z;
    371 		Result.data.w = v.w;
    372 		return Result.pack; 
    373 	}
    374 
    375 	GLM_FUNC_QUALIFIER ivec4 unpackI3x10_1x2(uint32 const & v)
    376 	{
    377 		detail::i10i10i10i2 Unpack;
    378 		Unpack.pack = v;
    379 		return ivec4(
    380 			Unpack.data.x,
    381 			Unpack.data.y,
    382 			Unpack.data.z,
    383 			Unpack.data.w);
    384 	}
    385 
    386 	GLM_FUNC_QUALIFIER uint32 packU3x10_1x2(uvec4 const & v)
    387 	{
    388 		detail::u10u10u10u2 Result;
    389 		Result.data.x = v.x;
    390 		Result.data.y = v.y;
    391 		Result.data.z = v.z;
    392 		Result.data.w = v.w;
    393 		return Result.pack; 
    394 	}
    395 
    396 	GLM_FUNC_QUALIFIER uvec4 unpackU3x10_1x2(uint32 const & v)
    397 	{
    398 		detail::u10u10u10u2 Unpack;
    399 		Unpack.pack = v;
    400 		return uvec4(
    401 			Unpack.data.x,
    402 			Unpack.data.y,
    403 			Unpack.data.z,
    404 			Unpack.data.w);
    405 	}
    406 
    407 	GLM_FUNC_QUALIFIER uint32 packSnorm3x10_1x2(vec4 const & v)
    408 	{
    409 		detail::i10i10i10i2 Result;
    410 		Result.data.x = int(round(clamp(v.x,-1.0f, 1.0f) * 511.f));
    411 		Result.data.y = int(round(clamp(v.y,-1.0f, 1.0f) * 511.f));
    412 		Result.data.z = int(round(clamp(v.z,-1.0f, 1.0f) * 511.f));
    413 		Result.data.w = int(round(clamp(v.w,-1.0f, 1.0f) *   1.f));
    414 		return Result.pack;
    415 	}
    416 
    417 	GLM_FUNC_QUALIFIER vec4 unpackSnorm3x10_1x2(uint32 const & v)
    418 	{
    419 		detail::i10i10i10i2 Unpack;
    420 		Unpack.pack = v;
    421 		vec4 Result;
    422 		Result.x = clamp(float(Unpack.data.x) / 511.f, -1.0f, 1.0f);
    423 		Result.y = clamp(float(Unpack.data.y) / 511.f, -1.0f, 1.0f);
    424 		Result.z = clamp(float(Unpack.data.z) / 511.f, -1.0f, 1.0f);
    425 		Result.w = clamp(float(Unpack.data.w) /   1.f, -1.0f, 1.0f);
    426 		return Result;
    427 	}
    428 
    429 	GLM_FUNC_QUALIFIER uint32 packUnorm3x10_1x2(vec4 const & v)
    430 	{
    431 		detail::i10i10i10i2 Result;
    432 		Result.data.x = int(round(clamp(v.x, 0.0f, 1.0f) * 1023.f));
    433 		Result.data.y = int(round(clamp(v.y, 0.0f, 1.0f) * 1023.f));
    434 		Result.data.z = int(round(clamp(v.z, 0.0f, 1.0f) * 1023.f));
    435 		Result.data.w = int(round(clamp(v.w, 0.0f, 1.0f) *    3.f));
    436 		return Result.pack;
    437 	}
    438 
    439 	GLM_FUNC_QUALIFIER vec4 unpackUnorm3x10_1x2(uint32 const & v)
    440 	{
    441 		detail::i10i10i10i2 Unpack;
    442 		Unpack.pack = v;
    443 		vec4 Result;
    444 		Result.x = float(Unpack.data.x) / 1023.f;
    445 		Result.y = float(Unpack.data.y) / 1023.f;
    446 		Result.z = float(Unpack.data.z) / 1023.f;
    447 		Result.w = float(Unpack.data.w) /   3.f;
    448 		return Result;
    449 	}
    450 
    451 	GLM_FUNC_QUALIFIER uint32 packF2x11_1x10(vec3 const & v)
    452 	{
    453 		return 
    454 			((detail::floatTo11bit(v.x) & ((1 << 11) - 1)) <<  0) |
    455 			((detail::floatTo11bit(v.y) & ((1 << 11) - 1)) << 11) |
    456 			((detail::floatTo10bit(v.z) & ((1 << 10) - 1)) << 22);
    457 	}
    458 
    459 	GLM_FUNC_QUALIFIER vec3 unpackF2x11_1x10(uint32 const & v)
    460 	{
    461 		return vec3(
    462 			detail::packed11bitToFloat(v >> 0), 
    463 			detail::packed11bitToFloat(v >> 11), 
    464 			detail::packed10bitToFloat(v >> 22));
    465 	}
    466 
    467 }//namespace glm
    468