Files
XCEngine/MVS/3DGS-Unity/Runtime/GaussianUtils.cs
2026-03-29 01:36:53 +08:00

108 lines
3.2 KiB
C#

// SPDX-License-Identifier: MIT
using Unity.Mathematics;
namespace GaussianSplatting.Runtime
{
public static class GaussianUtils
{
public static float Sigmoid(float v)
{
return math.rcp(1.0f + math.exp(-v));
}
public static float3 SH0ToColor(float3 dc0)
{
const float kSH_C0 = 0.2820948f;
return dc0 * kSH_C0 + 0.5f;
}
public static float3 LinearScale(float3 logScale)
{
return math.abs(math.exp(logScale));
}
public static float SquareCentered01(float x)
{
x -= 0.5f;
x *= x * math.sign(x);
return x * 2.0f + 0.5f;
}
public static float InvSquareCentered01(float x)
{
x -= 0.5f;
x *= 0.5f;
x = math.sqrt(math.abs(x)) * math.sign(x);
return x + 0.5f;
}
public static float4 NormalizeSwizzleRotation(float4 wxyz)
{
return math.normalize(wxyz).yzwx;
}
// Returns three smallest quaternion components in xyz (normalized to 0..1 range), and index/3 of the largest one in w
public static float4 PackSmallest3Rotation(float4 q)
{
// find biggest component
float4 absQ = math.abs(q);
int index = 0;
float maxV = absQ.x;
if (absQ.y > maxV)
{
index = 1;
maxV = absQ.y;
}
if (absQ.z > maxV)
{
index = 2;
maxV = absQ.z;
}
if (absQ.w > maxV)
{
index = 3;
maxV = absQ.w;
}
if (index == 0) q = q.yzwx;
if (index == 1) q = q.xzwy;
if (index == 2) q = q.xywz;
float3 three = q.xyz * (q.w >= 0 ? 1 : -1); // -1/sqrt2..+1/sqrt2 range
three = (three * math.SQRT2) * 0.5f + 0.5f; // 0..1 range
return new float4(three, index / 3.0f);
}
// Based on https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
// Insert two 0 bits after each of the 21 low bits of x
static ulong MortonPart1By2(ulong x)
{
x &= 0x1fffff;
x = (x ^ (x << 32)) & 0x1f00000000ffffUL;
x = (x ^ (x << 16)) & 0x1f0000ff0000ffUL;
x = (x ^ (x << 8)) & 0x100f00f00f00f00fUL;
x = (x ^ (x << 4)) & 0x10c30c30c30c30c3UL;
x = (x ^ (x << 2)) & 0x1249249249249249UL;
return x;
}
// Encode three 21-bit integers into 3D Morton order
public static ulong MortonEncode3(uint3 v)
{
return (MortonPart1By2(v.z) << 2) | (MortonPart1By2(v.y) << 1) | MortonPart1By2(v.x);
}
// See GaussianSplatting.hlsl
public static uint2 DecodeMorton2D_16x16(uint t)
{
t = (t & 0xFF) | ((t & 0xFE) << 7); // -EAFBGCHEAFBGCHD
t &= 0x5555; // -E-F-G-H-A-B-C-D
t = (t ^ (t >> 1)) & 0x3333; // --EF--GH--AB--CD
t = (t ^ (t >> 2)) & 0x0f0f; // ----EFGH----ABCD
return new uint2(t & 0xF, t >> 8); // --------EFGHABCD
}
}
}