• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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