Skip to content

Instantly share code, notes, and snippets.

@tkokof
Created October 29, 2018 08:56
Show Gist options
  • Save tkokof/b05a8e794a5200abbba9ff13e1b4f98d to your computer and use it in GitHub Desktop.
Save tkokof/b05a8e794a5200abbba9ff13e1b4f98d to your computer and use it in GitHub Desktop.
public static class Sample
{
static int gsN = 127; // N(N+1)/2 = 8128 < 2^{13}
static float gsB = 2 * gsN + 1;
static float gsB2 = gsB * gsB;
static float gsFactor = (gsN - 1) * Mathf.Sqrt(0.5f);
static float gsInvFactor = 1.0f / gsFactor;
public static ushort CompressNormal(Vector3 normal)
{
var x = normal.x;
var y = normal.y;
var z = normal.z;
Debug.Assert(MathUtil.IsSame(x * x + y * y + z * z, 1));
// Determine octant.
ushort index = 0;
if (x < 0.0)
{
index |= 0x8000;
x = -x;
}
if (y < 0.0)
{
index |= 0x4000;
y = -y;
}
if (z < 0.0)
{
index |= 0x2000;
z = -z;
}
// Determine mantissa.
ushort usX = (ushort)Mathf.Floor(gsFactor * x);
ushort usY = (ushort)Mathf.Floor(gsFactor * y);
ushort mantissa = (ushort)(usX + ((usY * (255 - usY)) >> 1));
index |= mantissa;
return index;
}
public static Vector3 DecompressNormal(ushort index)
{
ushort mantissa = (ushort)(index & 0x1FFF);
// Extract triangular indices.
float temp = gsB2 - 8 * mantissa;
ushort usY = (ushort)Mathf.Floor(0.5f * (gsB - Mathf.Sqrt(Mathf.Abs(temp))));
ushort usX = (ushort)(mantissa - ((usY * (255 - usY)) >> 1));
var normal = Vector3.zero;
// Build approximate normal.
normal.x = usX * gsInvFactor;
normal.y = usY * gsInvFactor;
temp = 1.0f - normal.x * normal.x - normal.y * normal.y;
normal.z = Mathf.Sqrt(Mathf.Abs(temp));
// Determine octant.
if ((index & 0x8000) != 0)
{
normal.x = -normal.x;
}
if ((index & 0x4000) != 0)
{
normal.y = -normal.y;
}
if ((index & 0x2000) != 0)
{
normal.z = -normal.z;
}
return normal;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment