58 lines
2.5 KiB
JavaScript
58 lines
2.5 KiB
JavaScript
const GLSL = `
|
|
float sdf(vec3 p) {
|
|
float d = implicit_sphere(p, vec3(0.0), coreRadius);
|
|
d = implicit_union_round(d, implicit_sphere(p, vec3(spacing, 0.0, 0.0), satelliteRadius), blend);
|
|
d = implicit_union_round(d, implicit_sphere(p, vec3(-spacing, 0.0, 0.0), satelliteRadius), blend);
|
|
d = implicit_union_round(d, implicit_sphere(p, vec3(0.0, spacing, 0.0), satelliteRadius), blend);
|
|
d = implicit_union_round(d, implicit_sphere(p, vec3(0.0, -spacing, 0.0), satelliteRadius), blend);
|
|
d = implicit_union_round(d, implicit_sphere(p, vec3(0.0, 0.0, spacing), satelliteRadius), blend);
|
|
d = implicit_union_round(d, implicit_sphere(p, vec3(0.0, 0.0, -spacing), satelliteRadius), blend);
|
|
return d;
|
|
}
|
|
|
|
|
|
vec3 color(vec3 p, vec3 normal) {
|
|
vec3 directionTint = normalize(abs(p) + vec3(0.001));
|
|
return xColor * directionTint.x + yColor * directionTint.y + zColor * directionTint.z;
|
|
}
|
|
`;
|
|
|
|
export default {
|
|
schema: "implicit.js/0.1.0",
|
|
name: "metaball molecule cluster",
|
|
description: "Seven overlapping spheres blended into one smooth organic implicit solid.",
|
|
units: "mm",
|
|
params: {
|
|
coreRadius: { type: "number", label: "Core radius", min: 5, max: 14, step: 0.1, default: 9.5, unit: "mm" },
|
|
satelliteRadius: { type: "number", label: "Satellite radius", min: 3.5, max: 10, step: 0.1, default: 7.2, unit: "mm" },
|
|
spacing: { type: "number", label: "Spacing", min: 7, max: 20, step: 0.25, default: 13, unit: "mm" },
|
|
blend: { type: "number", label: "Blend", min: 0.5, max: 8, step: 0.1, default: 5, unit: "mm" },
|
|
xColor: { type: "color", label: "X lobes", default: "#4f8cff" },
|
|
yColor: { type: "color", label: "Y lobes", default: "#5cff89" },
|
|
zColor: { type: "color", label: "Z lobes", default: "#ff66d8" }
|
|
},
|
|
animations: {
|
|
clusterPulse: {
|
|
label: "Cluster pulse",
|
|
duration: 4.6,
|
|
loop: true,
|
|
update({ progress, set }) {
|
|
const wave = Math.sin(progress * Math.PI * 2);
|
|
set("spacing", 13 + wave * 4);
|
|
set("blend", 5 + wave * 2.2);
|
|
set("satelliteRadius", 7.2 + wave * 1.6);
|
|
}
|
|
}
|
|
},
|
|
bounds: ({ params }) => {
|
|
const extent = params.spacing + Math.max(params.coreRadius, params.satelliteRadius) + params.blend + 5;
|
|
return [[-extent, -extent, -extent], [extent, extent, extent]];
|
|
},
|
|
render: ({ params }) => ({
|
|
steps: 240,
|
|
epsilon: Math.max(0.004, Math.min(params.coreRadius, params.satelliteRadius) * 0.0007),
|
|
normalEpsilon: Math.max(0.035, params.blend * 0.009)
|
|
}),
|
|
glsl: GLSL
|
|
};
|