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 35namespace glm{ 36namespace 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