/******************************************************************************
* This file includes a number of functions related to signed distance field
* operations.
******************************************************************************/
// SDF combination operators
[docs]/**
* Inverts a signed distance field. (Logical NOT)
*
* :param a: the sdf to invert.
* :returns: the new sdf.
*/
float op_not(float a) {
return -a;
}
[docs]/**
* Computes the union between two distance fields. (logical OR)
*
* :param a: the first sdf.
* :param b: the second sdf.
* :returns: the combined sdf.
*/
float op_union(float a, float b) {
return min(a, b);
}
[docs]/**
* Computes the intersection between two distance fields. (logical AND)
*
* :param a: the first sdf.
* :param b: the second sdf.
* :returns: the combined sdf.
*/
float op_intersect(float a, float b) {
return max(a, b);
}
[docs]/**
* Computes the difference between two distance fields. (logical SUBTRACT)
*
* :param a: the first sdf.
* :param b: the second sdf.
* :returns: the combined sdf.
*/
float op_subtract(float a, float b) {
return op_intersect(a, op_not(b));
}
[docs]/**
* Computes the exclusive OR between two distance fields. (logical XOR)
*
* :param a: the first sdf.
* :param b: the second sdf.
* :returns: the combined sdf.
*/
float op_xor(float a, float b) {
return op_intersect(op_union(a, b), -op_intersect(a, b));
}
// polynomial smooth min
// https://iquilezles.org/articles/smin/
[docs]float op_sminCubic(float a, float b, float k)
{
float h = max(k - abs(a - b), 0.0)/k;
return min(a, b) - h*h*h*k*(1.0/6.0);
}
[docs]float op_smaxCubic(float a, float b, float k)
{
float h = max(k - abs(a - b), 0.0)/k;
return max(a, b) + h*h*h*k*(1.0/6.0);
}
[docs]/**
* Computes the union between two distance fields with a soft intersection. (logical OR)
*
* :param a: the first sdf.
* :param b: the second sdf.
* :param k: the amount of smoothing to apply to the intersection.
* :returns: the combined sdf.
*/
float op_smoothUnion(float a, float b, float k) {
return op_sminCubic(a, b, k);
}
[docs]/**
* Computes the intersection between two distance fields with a soft intersection. (logical AND)
*
* :param a: the first sdf.
* :param b: the second sdf.
* :param k: the amount of smoothing to apply to the intersection.
* :returns: the combined sdf.
*/
float op_smoothIntersect(float a, float b, float k) {
return op_smaxCubic(a, b, k);
}
[docs]/**
* Computes the difference between two distance fields with a soft intersection. (logical SUBTRACT)
*
* :param a: the first sdf.
* :param b: the second sdf.
* :param k: the amount of smoothing to apply to the intersection.
* :returns: the combined sdf.
*/
float op_smoothSubtract(float a, float b, float k) {
return op_smoothIntersect(a, op_not(b), k);
}
[docs]/**
* Computes the exclusive OR between two distance fields with a soft intersection. (logical XOR)
*
* :param a: the first sdf.
* :param b: the second sdf.
* :param k: the amount of smoothing to apply to the intersection.
* :returns: the combined sdf.
*/
float op_smoothXor(float a, float b, float k) {
return op_smoothIntersect(op_smoothUnion(a, b, k), -op_smoothIntersect(a, b, k), k);
}