Skip to content

Commit

Permalink
Updated meshoptimizer.
Browse files Browse the repository at this point in the history
  • Loading branch information
bkaradzic committed Sep 4, 2023
1 parent 525c89c commit e2ec438
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 49 deletions.
60 changes: 11 additions & 49 deletions 3rdparty/meshoptimizer/src/meshoptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ struct meshopt_Bounds
* For backface culling with orthographic projection, use the following formula to reject backfacing clusters:
* dot(view, cone_axis) >= cone_cutoff
*
* For perspective projection, you can the formula that needs cone apex in addition to axis & cutoff:
* For perspective projection, you can use the formula that needs cone apex in addition to axis & cutoff:
* dot(normalize(cone_apex - camera_position), cone_axis) >= cone_cutoff
*
* Alternatively, you can use the formula that doesn't need cone apex and uses bounding sphere instead:
Expand Down Expand Up @@ -577,19 +577,25 @@ inline int meshopt_quantizeUnorm(float v, int N);
inline int meshopt_quantizeSnorm(float v, int N);

/**
* Quantize a float into half-precision floating point value
* Quantize a float into half-precision (as defined by IEEE-754 fp16) floating point value
* Generates +-inf for overflow, preserves NaN, flushes denormals to zero, rounds to nearest
* Representable magnitude range: [6e-5; 65504]
* Maximum relative reconstruction error: 5e-4
*/
inline unsigned short meshopt_quantizeHalf(float v);
MESHOPTIMIZER_API unsigned short meshopt_quantizeHalf(float v);

/**
* Quantize a float into a floating point value with a limited number of significant mantissa bits
* Quantize a float into a floating point value with a limited number of significant mantissa bits, preserving the IEEE-754 fp32 binary representation
* Generates +-inf for overflow, preserves NaN, flushes denormals to zero, rounds to nearest
* Assumes N is in a valid mantissa precision range, which is 1..23
*/
inline float meshopt_quantizeFloat(float v, int N);
MESHOPTIMIZER_API float meshopt_quantizeFloat(float v, int N);

/**
* Reverse quantization of a half-precision (as defined by IEEE-754 fp16) floating point value
* Preserves Inf/NaN, flushes denormals to zero
*/
MESHOPTIMIZER_API float meshopt_dequantizeHalf(unsigned short h);
#endif

/**
Expand Down Expand Up @@ -684,50 +690,6 @@ inline int meshopt_quantizeSnorm(float v, int N)

return int(v * scale + round);
}

inline unsigned short meshopt_quantizeHalf(float v)
{
union { float f; unsigned int ui; } u = {v};
unsigned int ui = u.ui;

int s = (ui >> 16) & 0x8000;
int em = ui & 0x7fffffff;

/* bias exponent and round to nearest; 112 is relative exponent bias (127-15) */
int h = (em - (112 << 23) + (1 << 12)) >> 13;

/* underflow: flush to zero; 113 encodes exponent -14 */
h = (em < (113 << 23)) ? 0 : h;

/* overflow: infinity; 143 encodes exponent 16 */
h = (em >= (143 << 23)) ? 0x7c00 : h;

/* NaN; note that we convert all types of NaN to qNaN */
h = (em > (255 << 23)) ? 0x7e00 : h;

return (unsigned short)(s | h);
}

inline float meshopt_quantizeFloat(float v, int N)
{
union { float f; unsigned int ui; } u = {v};
unsigned int ui = u.ui;

const int mask = (1 << (23 - N)) - 1;
const int round = (1 << (23 - N)) >> 1;

int e = ui & 0x7f800000;
unsigned int rui = (ui + round) & ~mask;

/* round all numbers except inf/nan; this is important to make sure nan doesn't overflow into -0 */
ui = e == 0x7f800000 ? ui : rui;

/* flush denormals to zero */
ui = e == 0 ? 0 : ui;

u.ui = ui;
return u.f;
}
#endif

/* Internal implementation helpers */
Expand Down
70 changes: 70 additions & 0 deletions 3rdparty/meshoptimizer/src/quantization.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
#include "meshoptimizer.h"

#include <assert.h>

unsigned short meshopt_quantizeHalf(float v)
{
union { float f; unsigned int ui; } u = {v};
unsigned int ui = u.ui;

int s = (ui >> 16) & 0x8000;
int em = ui & 0x7fffffff;

// bias exponent and round to nearest; 112 is relative exponent bias (127-15)
int h = (em - (112 << 23) + (1 << 12)) >> 13;

// underflow: flush to zero; 113 encodes exponent -14
h = (em < (113 << 23)) ? 0 : h;

// overflow: infinity; 143 encodes exponent 16
h = (em >= (143 << 23)) ? 0x7c00 : h;

// NaN; note that we convert all types of NaN to qNaN
h = (em > (255 << 23)) ? 0x7e00 : h;

return (unsigned short)(s | h);
}

float meshopt_quantizeFloat(float v, int N)
{
assert(N >= 0 && N <= 23);

union { float f; unsigned int ui; } u = {v};
unsigned int ui = u.ui;

const int mask = (1 << (23 - N)) - 1;
const int round = (1 << (23 - N)) >> 1;

int e = ui & 0x7f800000;
unsigned int rui = (ui + round) & ~mask;

// round all numbers except inf/nan; this is important to make sure nan doesn't overflow into -0
ui = e == 0x7f800000 ? ui : rui;

// flush denormals to zero
ui = e == 0 ? 0 : ui;

u.ui = ui;
return u.f;
}

float meshopt_dequantizeHalf(unsigned short h)
{
unsigned int s = unsigned(h & 0x8000) << 16;
int em = h & 0x7fff;

// bias exponent and pad mantissa with 0; 112 is relative exponent bias (127-15)
int r = (em + (112 << 10)) << 13;

// denormal: flush to zero
r = (em < (1 << 10)) ? 0 : r;

// infinity/NaN; note that we preserve NaN payload as a byproduct of unifying inf/nan cases
// 112 is an exponent bias fixup; since we already applied it once, applying it twice converts 31 to 255
r += (em >= (31 << 10)) ? (112 << 23) : 0;

union { float f; unsigned int ui; } u;
u.ui = s | r;
return u.f;
}

0 comments on commit e2ec438

Please sign in to comment.