Files
cadSet/text-to-cad/models/implicits/koch-snowflake-extrusion.implicit.js
T
2026-07-22 19:38:36 +08:00

76 lines
2.5 KiB
JavaScript

const GLSL = `
float sdBox(vec3 p, vec3 b) {
vec3 q = abs(p) - b;
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}
float snowflakeRadius(float a) {
float r = radius * (0.72 + 0.12 * cos(3.0 * a));
if (depth > 1.5) {
r += radius * 0.105 * cos(12.0 * a);
}
if (depth > 2.5) {
r += radius * 0.055 * cos(48.0 * a);
}
if (depth > 3.5) {
r += radius * 0.026 * cos(96.0 * a);
}
return r;
}
float sdf(vec3 p) {
float a = atan(p.y, p.x);
float radial = length(p.xy) - snowflakeRadius(a);
float sideBevel = radial - edgeRound;
float slab = abs(p.z) - thickness * 0.5 + edgeRound;
return min(max(sideBevel, slab), 0.0) + length(max(vec2(sideBevel, slab), 0.0)) - edgeRound;
}
vec3 color(vec3 p, vec3 normal) {
float a = atan(p.y, p.x);
float ice = 0.5 + 0.5 * cos(a * 12.0 + length(p.xy) * 0.11);
vec3 c = mix(baseColor, accentColor, ice);
return c * (0.62 + 0.38 * smoothstep(-0.3, 0.95, normal.z));
}
`;
export default {
schema: "implicit.js/0.1.0",
name: "Koch snowflake extrusion",
description: "A rounded extruded Koch-snowflake approximation with controllable recursive edge detail.",
units: "mm",
params: {
radius: { type: "number", label: "Radius", min: 14, max: 42, step: 0.5, default: 28, unit: "mm" },
depth: { type: "number", label: "Recursion depth", min: 1, max: 4, step: 1, default: 4 },
thickness: { type: "number", label: "Thickness", min: 1.5, max: 9, step: 0.1, default: 4.2, unit: "mm" },
edgeRound: { type: "number", label: "Edge round", min: 0.05, max: 1.6, step: 0.05, default: 0.55, unit: "mm" },
baseColor: { type: "color", label: "Ice color", default: "#e0fbff" },
accentColor: { type: "color", label: "Edge color", default: "#00a6ff" }
},
animations: {
frostBloom: {
label: "Frost bloom",
duration: 5.0,
loop: true,
update({ progress, set }) {
const wave = Math.sin(progress * Math.PI * 2);
set("edgeRound", 0.55 + (wave * 0.5 + 0.5) * 0.75);
set("thickness", 4.2 + wave * 1.2);
}
}
},
bounds: ({ params }) => {
const extent = params.radius + params.edgeRound + 7;
const z = params.thickness + params.edgeRound + 4;
return [[-extent, -extent, -z], [extent, extent, z]];
},
render: ({ params }) => ({
steps: 180,
stepScale: 0.72,
maxStep: Math.max(params.edgeRound * 4.5, 1.0),
epsilon: Math.max(params.edgeRound * 0.012, 0.004),
normalEpsilon: Math.max(params.edgeRound * 0.09, 0.035)
}),
glsl: GLSL
};