export interface GenerateSettings {
seed: number;
ssGuidanceStrength: number;
ssSamplingSteps: number;
slatGuidanceStrength: number;
slatSamplingSteps: number;
multiimageAlgo: "multidiffusion" | "stochastic";
meshSimplify: number;
textureSize: 512 | 1024 | 2048;
}
export const DEFAULT_GENERATE_SETTINGS: GenerateSettings = {
seed: -1,
ssGuidanceStrength: 7.5,
ssSamplingSteps: 30,
slatGuidanceStrength: 3,
slatSamplingSteps: 12,
multiimageAlgo: "multidiffusion",
meshSimplify: 0.95,
textureSize: 1024,
};(function patchFetch() {
if (typeof window === "undefined") return;
const prev = window.fetch as typeof fetch & { __gradio_patched?: boolean };
if (prev.__gradio_patched) return;
const orig = window.fetch.bind(window);
const next = function (input: RequestInfo | URL, init?: RequestInit) {
const url =
typeof input === "string"
? input
: input instanceof URL
? input.toString()
: (input as Request).url;
if (url.includes(".hf.space") || url.includes(".gradio.live")) {
return orig(input, { ...init, credentials: "omit" });
}
return orig(input, init);
} as typeof fetch & { __gradio_patched?: boolean };
next.__gradio_patched = true;
window.fetch = next;
})();function decodeSseEvents(text: string) {
const chunks = text
.split(/\n\s*\n/)
.map((chunk) => chunk.trim())
.filter(Boolean);
return chunks.map((chunk) => {
const lines = chunk.split("\n");
const eventLine = lines.find((line) => line.startsWith("event:"));
const dataLines = lines
.filter((line) => line.startsWith("data:"))
.map((line) => line.slice(5).trim())
.join("\n");
return {
event: eventLine ? eventLine.slice(6).trim() : "message",
data: dataLines ? JSON.parse(dataLines) : null,
};
});
}async function collectSseEvents(response: Response, onEvent: (event: any) => void) {
if (!response.body) {
const events = decodeSseEvents(await response.text());
events.forEach(onEvent);
return events;
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { done, value } = await reader.read();
buffer += decoder.decode(value ?? new Uint8Array(), { stream: !done });
const chunks = buffer.split(/\n\s*\n/);
buffer = chunks.pop() ?? "";
for (const chunk of chunks) {
decodeSseEvents(chunk).forEach(onEvent);
}
if (done) break;
}
}function svgToPng(svgFile: File, size = 1024): Promise<File> {
return new Promise((resolve, reject) => {
const url = URL.createObjectURL(svgFile);
const img = new Image();
img.onload = () => {
const canvas = document.createElement("canvas");
canvas.width = img.naturalWidth || size;
canvas.height = img.naturalHeight || size;
const ctx = canvas.getContext("2d");
if (!ctx) return reject(new Error("No 2d context"));
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
URL.revokeObjectURL(url);
canvas.toBlob((blob) => {
if (!blob) return reject(new Error("Canvas toBlob failed"));
resolve(new File([blob], svgFile.name.replace(/\.svg$/i, ".png"), {
type: "image/png",
}));
}, "image/png");
};
img.onerror = () => reject(new Error("SVG load failed"));
img.src = url;
});
}function loadModel(url: string): Promise<void> {
return new Promise((resolve, reject) => {
const loader = new GLTFLoader();
loader.load(
url,
(gltf) => {
removeLoadedModels();
const model = gltf.scene;
model.userData.isLoadedModel = true;
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
const size = box.getSize(new THREE.Vector3());
const maxDim = Math.max(size.x, size.y, size.z);
model.position.sub(center);
scene.add(model);
const dist = maxDim * 2.5;
camera.position.set(dist, dist * 0.7, dist);
controls.target.set(0, 0, 0);
controls.update();
resolve();
},
undefined,
reject,
);
});
}const styleConfig = {
normal: { background: 0x111113, ambient: 0xffffff, key: 0xffffff },
clay: { background: 0x16181d, ambient: 0xf7efe4, key: 0xffffff, clay: 0xc9c1b6 },
blue: { background: 0x0f172a, ambient: 0xdbeafe, key: 0x93c5fd },
};
function applyClayMaterial(mesh: THREE.Mesh) {
mesh.material = new THREE.MeshStandardMaterial({
color: 0xc9c1b6,
roughness: 0.82,
metalness: 0.02,
});
}