@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
108 lines (102 loc) • 3.02 kB
text/typescript
import {Vector2} from 'three';
import {absV2, vector2MaxScalar, vector2Dot} from './_VectorUtils';
import {_sizzleVec2} from './_Sizzle';
import {NamedFunction2, NamedFunction3, NamedFunction4, NamedFunction5} from './_Base';
const _q = new Vector2();
const _q2 = new Vector2();
const _b = new Vector2();
const _w = new Vector2();
export class SDF2DBox extends NamedFunction3<[Vector2, Vector2, Vector2]> {
static override type() {
return 'SDF2DBox';
}
func(p: Vector2, center: Vector2, size: Vector2): number {
p.sub(center);
absV2(p, p);
p.sub(size);
return vector2MaxScalar(p, 0, _q2).length() + Math.min(Math.max(p.x, p.y), 0.0);
}
}
export class SDF2DCircle extends NamedFunction3<[Vector2, Vector2, number]> {
static override type() {
return 'SDF2DCircle';
}
func(p: Vector2, center: Vector2, radius: number): number {
p.sub(center);
return p.length() - radius;
}
}
export class SDF2DCross extends NamedFunction5<[Vector2, Vector2, number, number, number]> {
static override type() {
return 'SDF2DCross';
}
func(p: Vector2, center: Vector2, length: number, width: number, radius: number): number {
// p = abs(p)
p.sub(center);
absV2(p, p);
// p = (p.y>p.x) ? p.yx : p.xy;
if (p.y > p.x) {
_sizzleVec2(p, _q2);
p.copy(_q2);
}
// vec2 q = p - b;
_b.x = length;
_b.y = width;
_q.copy(p).sub(_b);
// float k = max(q.y,q.x);
const k = Math.max(_q.y, _q.x);
// vec2 w = (k>0.0) ? q : vec2(b.y-p.x,-k);
if (k > 0) {
_w.copy(_q);
} else {
_w.x = _b.y - p.x;
_w.y = -k;
}
// return sign(k)*length(max(w,0.0)) + r;
return Math.sign(k) * vector2MaxScalar(_w, 0, _w).length() + radius;
}
}
// float sdHeart( in vec2 p )
// {
// p.x = abs(p.x);
// if( p.y+p.x>1.0 )
// return sqrt(dot2(p-vec2(0.25,0.75))) - sqrt(2.0)/4.0;
// return sqrt(min(dot2(p-vec2(0.00,1.00)),
// dot2(p-0.5*max(p.x+p.y,0.0)))) * sign(p.x-p.y);
// }
const SQRT_2_BY_4 = Math.sqrt(2.0) / 4.0;
export class SDF2DHeart extends NamedFunction2<[Vector2, Vector2]> {
static override type() {
return 'SDF2DHeart';
}
func(p: Vector2, center: Vector2): number {
p.sub(center);
// p.x = abs(p.x)
p.x = Math.abs(p.x);
if (p.y + p.x > 1.0) {
_q2.set(0.25, 0.75);
// return sqrt(dot2(p-vec2(0.25,0.75))) - sqrt(2.0)/4.0;
return Math.sqrt(vector2Dot(p.sub(_q2))) - SQRT_2_BY_4;
}
// return sqrt(min(dot2(p-vec2(0.00,1.00)),
// dot2(p-0.5*max(p.x+p.y,0.0)))) * sign(p.x-p.y);
_q2.set(0.25, 0.75);
const a = vector2Dot(p.sub(_q2));
const b = vector2Dot(p.subScalar(0.5 * Math.max(p.x + p.y, 0.0)));
const c = Math.sqrt(Math.min(a, b));
const d = Math.sign(p.x - p.y);
return c * d;
}
}
export class SDF2DRoundedX extends NamedFunction4<[Vector2, Vector2, number, number]> {
static override type() {
return 'SDF2DRoundedX';
}
func(p: Vector2, center: Vector2, w: number, r: number): number {
p.sub(center);
absV2(p, _q);
const min = Math.min(_q.x + _q.y, w) * 0.5;
_q.subScalar(min);
return _q.length() - r;
}
}