Files
cadSet/text-to-cad/models/implicits/thickened-mobius-strip.implicit.js
T
2026-07-22 19:38:36 +08:00

69 lines
2.6 KiB
JavaScript

const GLSL = `
const float IMPLICIT_MOBIUS_TAU = 6.283185307179586;
float sdf(vec3 p) {
float u = atan(p.y, p.x);
vec2 section = vec2(length(p.xy) - radius, p.z);
vec2 twistAxis = vec2(cos(0.5 * u), sin(0.5 * u));
vec2 closest = twistAxis * clamp(dot(section, twistAxis), -(width * 0.5), (width * 0.5));
return length(section - closest) - thickness;
}
vec3 implicit_palette(float t) {
float waveA = 0.5 + 0.5 * cos(6.283185307179586 * (t + 0.1));
float waveB = 0.5 + 0.5 * cos(6.283185307179586 * (t + 0.56));
return mix(mix(baseColor, midColor, waveA), accentColor, waveB * 0.74);
}
vec3 color(vec3 p, vec3 normal) {
vec2 ring = vec2(p.x, p.y);
float angle = atan(ring.y, ring.x) / 6.283185307179586;
vec3 bandColor = implicit_palette(angle + p.z * 0.035);
return mix(bandColor, edgeColor, smoothstep(0.25, 0.95, abs(normal.z)) * 0.28);
}
`;
export default {
schema: "implicit.js/0.1.0",
name: "thickened Mobius strip",
description: "A manufacturable one-half-twist Mobius strip with rounded boundary and finite shell thickness.",
units: "mm",
params: {
radius: { type: "number", label: "Radius", min: 14, max: 34, step: 0.25, default: 24, unit: "mm" },
width: { type: "number", label: "Band width", min: 4, max: 22, step: 0.25, default: 13.6, unit: "mm" },
thickness: { type: "number", label: "Thickness", min: 0.25, max: 2.5, step: 0.05, default: 0.82, unit: "mm" },
baseColor: { type: "color", label: "Rose color", default: "#ff4fa3" },
midColor: { type: "color", label: "Lagoon color", default: "#7c5cff" },
accentColor: { type: "color", label: "Iris color", default: "#35e6c9" },
edgeColor: { type: "color", label: "Edge color", default: "#ffd166" }
},
animations: {
bandBreath: {
label: "Band breath",
duration: 4.8,
loop: true,
update({ progress, set }) {
const wave = Math.sin(progress * Math.PI * 2);
set("width", 13.6 + wave * 5.5);
set("thickness", 0.82 + wave * 0.35);
set("radius", 24 + wave * 4);
}
}
},
bounds: ({ params }) => {
const halfWidth = params.width * 0.5;
const radialExtent = params.radius + halfWidth + params.thickness + 6;
const heightExtent = halfWidth + params.thickness + 6;
return [[-radialExtent, -radialExtent, -heightExtent], [radialExtent, radialExtent, heightExtent]];
},
render: ({ params }) => ({
steps: 192,
stepScale: 0.72,
maxStep: Math.max(params.thickness * 3.8, 1.4),
epsilon: Math.max(params.thickness * 0.012, 0.006),
normalEpsilon: Math.max(params.thickness * 0.075, 0.04)
}),
glsl: GLSL
};