← Whole house3D assetfogon/inodoro
Inodoro
Drag to turn it// «Inodoro» · gpt-6-sol (medium)
// A white toilet: a glossy white bowl with a seat and open lid (lid raised up against the tank), a rectangular tank at the back with a chrome flush button on top, and a roll of toilet paper on a holder beside it.
const white = "#f8f8f4";
const porcelain = "#f0f2f0";
const shadow = "#dce2e2";
const deepShadow = "#c8d1d3";
const chrome = "#aebdc5";
const chromeLight = "#e4edf0";
// Solid pedestal and gently rounded bowl.
box(20, 22, 0, 30, 30, 3, shadow);
ellipsoid(25, 25, 6, 7, 8, 6, porcelain);
for (let z = 7; z <= 23; z++) {
const t = (z - 7) / 16;
const rx = 7 + 3.2 * Math.sin(t * Math.PI / 2);
const ry = 8 + 4 * Math.sin(t * Math.PI / 2);
const cy = 24 - 1.2 * t;
for (let x = 14; x <= 36; x++) {
for (let y = 10; y <= 35; y++) {
const q = ((x - 25) / rx) ** 2 + ((y - cy) / ry) ** 2;
if (q > 1) continue;
let c = y < 19 ? white : porcelain;
if (x > 31 || y > 30 || z < 11) c = shadow;
if (z > 19 && rand() < 0.06) c = "#ffffff";
set(x, y, z, c);
}
}
}
// Recessed bowl, with a little clean sky-blue water visible inside.
for (let x = 15; x <= 35; x++) {
for (let y = 11; y <= 34; y++) {
const q = ((x - 25) / 10) ** 2 + ((y - 23) / 11.5) ** 2;
if (q > 1) continue;
set(x, y, 23, q < 0.43 ? "#bedce4" : q < 0.64 ? "#d8e7e9" : shadow);
if (q < 0.31) set(x, y, 24, rand() < 0.12 ? "#e3f2f3" : "#c8e5eb");
if (q >= 0.68) set(x, y, 24, q > 0.87 ? white : porcelain);
}
}
// Rectangular cistern, with softened toy-like corners.
for (let z = 23; z <= 36; z++) {
for (let x = 15; x <= 35; x++) {
for (let y = 33; y <= 41; y++) {
if ((x === 15 || x === 35) && (y === 33 || y === 41)) continue;
let c = porcelain;
if (y === 33) c = white;
if (x >= 34 || y >= 40 || z <= 25) c = shadow;
if (y === 33 && rand() < 0.035) c = "#ffffff";
set(x, y, z, c);
}
}
}
// Slightly overhanging cistern top and its chrome push button.
box(15, 33, 37, 35, 41, 38, white);
box(16, 34, 39, 34, 40, 39, porcelain);
box(21, 36, 39, 29, 39, 39, deepShadow);
box(22, 36, 40, 28, 38, 40, chrome);
box(23, 36, 41, 27, 37, 41, chromeLight);
// Raised lid: a broad white oval in front of the tank.
for (let x = 15; x <= 35; x++) {
for (let z = 25; z <= 41; z++) {
const q = ((x - 25) / 9.4) ** 2 + ((z - 33) / 8) ** 2;
if (q > 1) continue;
set(x, 32, z, shadow);
set(x, 31, z, q > 0.78 ? "#d8dfe0" : porcelain);
set(x, 30, z, q > 0.81 ? "#e4e9e8" : z > 35 ? "#ffffff" : white);
}
}
box(19, 29, 25, 21, 32, 27, deepShadow);
box(29, 29, 25, 31, 32, 27, deepShadow);
// Thick rounded seat, with an unmistakable opening.
for (let x = 14; x <= 36; x++) {
for (let y = 10; y <= 35; y++) {
const outer = ((x - 25) / 10.5) ** 2 + ((y - 22.7) / 11.7) ** 2;
const inner = ((x - 25) / 6.7) ** 2 + ((y - 22.5) / 7.5) ** 2;
if (outer > 1 || inner < 1) continue;
set(x, y, 25, outer > 0.85 ? shadow : porcelain);
set(x, y, 26, outer > 0.88 ? porcelain : "#ffffff");
}
}
// Small chrome wall bracket on the right, supporting a paper roll.
box(35, 27, 22, 39, 29, 24, chrome);
box(36, 27, 24, 38, 29, 25, chromeLight);
box(38, 25, 22, 40, 29, 23, deepShadow);
// Paper roll, axis pointing toward the viewer.
for (let y = 20; y <= 26; y++) {
for (let x = 35; x <= 45; x++) {
for (let z = 17; z <= 27; z++) {
const d = Math.hypot(x - 40, z - 22);
if (d > 4.7) continue;
let c = y === 20 ? "#fffdf5" : "#f4f2e9";
if (d > 4.05) c = y === 20 ? white : "#e6e6df";
if (z < 19) c = "#e6e6df";
if (rand() < 0.035) c = white;
set(x, y, z, c);
}
}
}
for (let x = 38; x <= 42; x++) {
for (let z = 20; z <= 24; z++) {
const d = Math.hypot(x - 40, z - 22);
if (d <= 1.65) set(x, 19, z, d < 0.8 ? "#c7bba8" : "#d8d2c5");
}
}
// A loose sheet hangs from the outer edge.
box(43, 18, 15, 44, 19, 20, "#fffdf5");
box(44, 18, 15, 44, 18, 19, "#e9e9e1");import { draw } from "./assets/voxel";
import { inodoro } from "./assets/inodoro";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, inodoro, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: its longest side, in px
// angle: turn on the floor, in radians
// t: seconds; if it moves, that animates it# In a terminal, in the game's folder
fogon assets add inodoro
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["inodoro"] })
# It lands in client/assets/inodoro.ts
# https://fogon.page/object/inodoro