use crate::prelude::*;
use theframework::prelude::*;
#[inline(always)]
pub fn hash21(p: Vec2<f32>) -> f32 {
let mut p3 = Vec3::new(
(p.x * 0.1031).fract(),
(p.y * 0.1031).fract(),
(p.x * 0.1031).fract(),
);
let dot = p3.dot(Vec3::new(p3.y + 33.333, p3.z + 33.333, p3.x + 33.333));
p3.x += dot;
p3.y += dot;
p3.z += dot;
((p3.x + p3.y) * p3.z).fract()
}
pub fn noise2d(p: &Vec2<f32>, scale: Vec2<f32>, octaves: i32) -> f32 {
fn hash(p: Vec2<f32>) -> f32 {
let mut p3 = Vec3::new(p.x, p.y, p.x).map(|v| (v * 0.13).fract());
p3 += p3.dot(Vec3::new(p3.y, p3.z, p3.x) + 3.333);
((p3.x + p3.y) * p3.z).fract()
}
fn noise(x: Vec2<f32>) -> f32 {
let i = x.map(|v| v.floor());
let f = x.map(|v| v.fract());
let a = hash(i);
let b = hash(i + Vec2::new(1.0, 0.0));
let c = hash(i + Vec2::new(0.0, 1.0));
let d = hash(i + Vec2::new(1.0, 1.0));
let u = f * f * f.map(|v| 3.0 - 2.0 * v);
f32::lerp(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y
}
let mut x = *p * 8.0 * scale;
if octaves == 0 {
return noise(x);
}
let mut v = 0.0;
let mut a = 0.5;
let shift = Vec2::new(100.0, 100.0);
let rot = Mat2::new(0.5f32.cos(), 0.5f32.sin(), -0.5f32.sin(), 0.5f32.cos());
for _ in 0..octaves {
v += a * noise(x);
x = rot * x * 2.0 + shift;
a *= 0.5;
}
v
}
pub fn noise3d(coll: &TheCollection, p: &Vec3<f32>) -> f32 {
fn hash(mut p: f32) -> f32 {
p = (p * 0.011).fract();
p *= p + 7.5;
p *= p + p;
p.fract()
}
fn noise(x: Vec3<f32>) -> f32 {
let step = Vec3::new(110.0, 241.0, 171.0);
let i = x.map(|v| v.floor());
let f = x.map(|v| v.fract());
let n = i.dot(step);
let u = f * f * f.map(|v| 3.0 - 2.0 * v);
f32::lerp(
f32::lerp(
f32::lerp(
hash(n + step.dot(Vec3::new(0.0, 0.0, 0.0))),
hash(n + step.dot(Vec3::new(1.0, 0.0, 0.0))),
u.x,
),
f32::lerp(
hash(n + step.dot(Vec3::new(0.0, 1.0, 0.0))),
hash(n + step.dot(Vec3::new(1.0, 1.0, 0.0))),
u.x,
),
u.y,
),
f32::lerp(
f32::lerp(
hash(n + step.dot(Vec3::new(0.0, 0.0, 1.0))),
hash(n + step.dot(Vec3::new(1.0, 0.0, 1.0))),
u.x,
),
f32::lerp(
hash(n + step.dot(Vec3::new(0.0, 1.0, 1.0))),
hash(n + step.dot(Vec3::new(1.0, 1.0, 1.0))),
u.x,
),
u.y,
),
u.z,
)
}
let scale = Vec3::new(
coll.get_f32_default("UV Scale X", 1.0),
coll.get_f32_default("UV Scale Y", 1.0),
coll.get_f32_default("UV Scale Z", 1.0),
);
let octaves = coll.get_i32_default("Octaves", 5);
let mut x = Vec3::new(1240.0, 1240.0, 1240.0) + *p * 8.0 * scale;
if octaves == 0 {
return noise(x);
}
let mut v = 0.0;
let mut a = 0.5;
let shift = Vec3::new(100.0, 100.0, 100.0);
for _ in 0..octaves {
v += a * noise(x);
x = x * 2.0 + shift;
a *= 0.5;
}
v
}
fn rot(a: f32) -> Mat2<f32> {
Mat2::new(a.cos(), -a.sin(), a.sin(), a.cos())
}
pub fn box_divide(p: Vec2<f32>, gap: f32, rotation: f32, rounding: f32) -> (f32, f32) {
fn s_box(p: Vec2<f32>, b: Vec2<f32>, r: f32) -> f32 {
let d = p.map(|v| v.abs()) - b + Vec2::new(r, r);
d.x.max(d.y).min(0.0) + (d.map(|v| v.max(0.0))).magnitude() - r
}
let mut p = p;
let ip = p.map(|v| v.floor());
p -= ip;
let mut l = Vec2::new(1.0, 1.0);
let mut last_l;
let mut r = hash21(ip);
for _ in 0..6 {
r = (l + Vec2::new(r, r)).dot(Vec2::new(123.71, 439.43)).fract() * 0.4 + (1.0 - 0.4) / 2.0;
last_l = l;
if l.x > l.y {
p = Vec2::new(p.y, p.x);
l = Vec2::new(l.y, l.x);
}
if p.x < r {
l.x /= r;
p.x /= r;
} else {
l.x /= 1.0 - r;
p.x = (p.x - r) / (1.0 - r);
}
if last_l.x > last_l.y {
p = Vec2::new(p.y, p.x);
l = Vec2::new(l.y, l.x);
}
}
p -= 0.5;
let id = hash21(ip + l);
p = rot((id - 0.5) * rotation) * p;
let th = l * 0.02 * gap;
let c = s_box(p, Vec2::new(0.5, 0.5) - th, rounding);
(c, id)
}
pub fn bricks(uv: Vec2<f32>, hit: &mut Hit, params: &[f32]) -> f32 {
fn s_box(p: Vec2<f32>, b: Vec2<f32>, r: f32) -> f32 {
let d = p.map(|v| v.abs()) - b + Vec2::new(r, r);
d.x.max(d.y).min(0.0) + (d.map(|v| v.max(0.0))).magnitude() - r
}
let ratio = params[0];
let round = params[1];
let rotation = params[2];
let gap = params[3];
let cell = params[4];
let mode = params[5] as i32;
let mut u = uv;
let w = Vec2::new(ratio, 1.0);
u *= Vec2::new(cell, cell) / w;
if mode == 0 {
u.x += 0.5 * (u.y.floor() % 2.0);
}
let id = hash21(u.map(|v| v.floor()));
let mut p = u.map(|v| v.fract());
p = rot((id - 0.5) * rotation) * (p - 0.5);
hit.hash = id;
hit.uv = p;
s_box(p, Vec2::new(0.5, 0.5) - gap, round)
}