Skip to content

Instantly share code, notes, and snippets.

View usefulslug's full-sized avatar

Vegard Myklebust usefulslug

View GitHub Profile
@usefulslug
usefulslug / CIEDE2000.cs
Created April 22, 2021 19:09
CIEDE2000
// Implementation of "The CIEDE2000 Color-Difference Formula: Implementation Notes, Supplementary Test Data, and Mathematical Observations".
public static float CIEDE2000(Lab lab1, Lab lab2)
{
float Pi = Mathf.PI;
float Pi2 = 2.0f * Mathf.PI;
float kL = 1.0f, kC = 1.0f, kH = 1.0f;
var mCs = (Mathf.Sqrt( lab1.a * lab1.a + lab1.b * lab1.b) + Mathf.Sqrt(lab2.a * lab2.a + lab2.b * lab2.b)) / 2.0f;
var G = 0.5f * (1.0f - Mathf.Sqrt(Mathf.Pow(mCs, 7) / (Mathf.Pow(mCs, 7) + Mathf.Pow(25.0f, 7))));
@usefulslug
usefulslug / LabDeltaE.cs
Created April 22, 2021 19:04
Lab Delta E
public static float LabDeltaE(Lab labA, Lab labB)
{
var deltaL = labA.L - labB.L;
var deltaA = labA.a - labB.a;
var deltaB = labA.b - labB.b;
var c1 = Mathf.Sqrt(labA.a * labA.a + labA.b * labA.b);
var c2 = Mathf.Sqrt(labB.a * labB.a + labB.b * labB.b);
var deltaC = c1 - c2;
var deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
deltaH = deltaH < 0 ? 0 : Mathf.Sqrt(deltaH);
// Returns a smooth approximation between q1 and q2 using t1 and t2 as 'tangents'
def SQUAD(q1 as Quaternion, t1 as Quaternion, t2 as Quaternion, q2 as Quaternion, t as single):
slerpT as single = 2.0 * t * (1.0 - t)
slerp1 as Quaternion = QuaternionExtensions.SlerpNoInvert(q1, q2, t)
slerp2 as Quaternion = QuaternionExtensions.SlerpNoInvert(t1, t2, t)
return QuaternionExtensions.SlerpNoInvert(slerp1, slerp2, slerpT)
// Tries to compute sensible tangent values for the quaternion
def Intermediate(q0 as Quaternion, q1 as Quaternion, q2 as Quaternion):
q1inv as Quaternion = Quaternion.Inverse(q1)
c1 as Quaternion = q1inv * q2
c2 as Quaternion = q1inv * q0
c1.Log()
c2.Log()
c3 as Quaternion = c2 + c1
c3.Scale(-0.25)
c3.Exp()
// Returns a quaternion between q1 and q2 as part of a smooth SQUAD segment
def SplineSegment(q0 as Quaternion, q1 as Quaternion, q2 as Quaternion, q3 as Quaternion, t as single):
qa as Quaternion = Intermediate(q0,q1,q2)
qb as Quaternion = Intermediate(q1,q2,q3)
return SQUAD(q1, qa, qb, q2, t)
// Returns a smoothed quaternion along the set of quaternions making up the spline, each quaternion is along an equidistant value in t
def Spline(quaternions as (Quaternion), t as single):
section as int = (quaternions.Length-1) * t
alongLine as single = (quaternions.Length-1) * t - section
if section == 0:
return SplineSegment(quaternions[section], quaternions[section], quaternions[section+1], quaternions[section+2], alongLine)
elif section == quaternions.Length - 2 and section > 0:
return SplineSegment(quaternions[section-1], quaternions[section], quaternions[section+1], quaternions[section+1], alongLine)
elif section >= 1 and section < quaternions.Length - 2:
return SplineSegment(quaternions[section-1], quaternions[section], quaternions[section+1], quaternions[section+2], alongLine)
// Quaternion extensions for Unity by Vegard Myklebust.
// Made available under Creative Commons license CC0. License details can be found here:
// https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt
[Extension]
public def Log(ref a as Quaternion):
a0 as single = a.w
a.w = 0.0
if(Mathf.Abs(a0) < 1.0):
angle as single = Mathf.Acos(a0)
sinAngle as single = Mathf.Sin(angle)
// SQUAD (Spherical Spline Quaternions, [Shomake 1987]) implementation for Unity by Vegard Myklebust.
// Made available under Creative Commons license CC0. License details can be found here:
// https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt
import UnityEngine
static class SQUAD ():
// Returns a smoothed quaternion along the set of quaternions making up the spline, each quaternion is along an equidistant value in t
def Spline(quaternions as (Quaternion), t as single):
section as int = (quaternions.Length-1) * t
alongLine as single = (quaternions.Length-1) * t - section
if section == 0: