← Gear3D assetfogon/yelmo-con-pluma
Yelmo con pluma
Drag to turn it// «Yelmo con pluma» · gpt-6-sol (medium)
// A rounded steel helmet with a hinged visor with slits at the front (-y), gold trims, and a tall bushy red plume rising from the top and curving toward the back. It stands upright on the floor (z=0), facing front (-y), centered, chunky and readable.
const steel = ["#53616b", "#64737d", "#788893", "#9aabb4"];
const gold = ["#9b672b", "#c58d38", "#e4b852", "#f7d778"];
const red = ["#861f29", "#aa2930", "#cb3b3c", "#e65a50", "#f37761"];
// Rounded helmet bowl: straight lower walls and a broad domed crown.
for (let z = 0; z <= 30; z++) {
const dome = z <= 15 ? 1 : Math.sqrt(Math.max(0, 1 - ((z - 15) / 16) ** 2));
const rx = 17 * dome;
const ry = 15.5 * dome;
for (let x = 6; x <= 42; x++) for (let y = 8; y <= 40; y++) {
const d = ((x - 24) / rx) ** 2 + ((y - 24) / ry) ** 2;
if (d > 1) continue;
let color;
if (z <= 2 && d > 0.69) {
color = gold[d > 0.87 ? 2 : 1];
} else if (z >= 20 && z <= 22 && d > 0.75) {
color = gold[z === 22 ? 2 : 1];
} else {
const shade = z > 23 || y < 19 ? 2 : z < 8 ? 0 : 1;
color = steel[Math.min(3, Math.max(0, shade + (rand() < 0.10 ? 1 : 0)))];
}
set(x, y, z, color);
}
}
// Substantial rolled lower edge.
for (let z = 0; z <= 3; z++) for (let x = 7; x <= 41; x++)
for (let y = 9; y <= 39; y++) {
const d = ((x - 24) / 17) ** 2 + ((y - 24) / 15.5) ** 2;
if (d > 0.76 && d <= 1) set(x, y, z, gold[z === 3 ? 3 : 1]);
}
// Side plates connect the visor to its hinges.
box(9, 8, 10, 13, 15, 20, "#58646d");
box(35, 8, 10, 39, 15, 20, "#58646d");
box(10, 7, 18, 13, 13, 21, "#b5a6a1");
box(35, 7, 18, 38, 13, 21, "#b5a6a1");
// Thick, gently tapered faceplate.
for (let z = 5; z <= 21; z++) {
const inset = z <= 7 ? 3 : z >= 20 ? 2 : 0;
for (let x = 10 + inset; x <= 38 - inset; x++) {
for (let y = 4; y <= 9; y++) {
let c = z > 17 ? "#8999a2" : z < 9 ? "#596873" : "#74838d";
if (y === 4 && (x < 15 || z >= 19)) c = "#a5b4ba";
if (rand() < 0.035) c = "#8d9da6";
set(x, y, z, c);
}
}
}
// Bright frame and a pronounced brow.
box(12, 3, 20, 36, 6, 21, "#c58d38");
box(14, 3, 21, 34, 5, 21, "#f2cd69");
box(10, 3, 9, 12, 6, 19, "#b98739");
box(36, 3, 9, 38, 6, 19, "#b98739");
box(13, 3, 5, 35, 6, 6, "#a87331");
box(15, 3, 6, 33, 4, 6, "#e5b951");
// Two deep eye slits, separated by a stout central bridge.
for (const [a, b] of [[14, 21], [27, 34]]) {
box(a, 2, 13, b, 4, 16, "#263038");
box(a, 2, 16, b, 2, 16, "#172229");
box(a, 2, 17, b, 3, 17, "#c2ced0");
box(a, 2, 12, b, 3, 12, "#46555e");
set(a, 2, 14, "#657780");
}
box(23, 2, 8, 25, 5, 19, "#b38035");
box(24, 1, 10, 24, 2, 18, "#f1c45b");
// Lower breathing openings.
for (const x of [17, 20, 28, 31]) {
box(x, 2, 8, x + 1, 3, 10, "#273138");
box(x, 2, 11, x + 1, 2, 11, "#a8b6b8");
}
// Round brass visor pivots, visible at either side of the brow.
for (const cx of [10, 38]) for (let x = cx - 4; x <= cx + 4; x++)
for (let z = 15; z <= 23; z++) {
const d = (x - cx) ** 2 + (z - 19) ** 2;
if (d <= 16) for (let y = 7; y <= 9; y++)
set(x, y, z, d > 10 ? "#8d5b29" : "#dfad48");
if (d <= 4) set(x, 6, z, "#78402e");
if (d <= 1) set(x, 5, z, "#c94b38");
}
// Raised gilded crest grips the base of the plume.
box(21, 20, 27, 27, 28, 31, "#ae7930");
box(22, 19, 28, 26, 25, 32, "#edbf56");
box(23, 19, 29, 25, 21, 31, "#f6db79");
// A thick, sweeping horsehair plume. Overlapping lobes form a single bushy mass.
const lobes = [
[24, 25, 32, 4, 4, 5],
[24, 25, 36, 4, 4, 6],
[24, 28, 41, 5, 5, 4],
[24, 33, 40, 5, 5, 4],
[24, 37, 36, 5, 5, 4],
[24, 39, 33, 4, 4, 3]
];
for (let z = 29; z <= 45; z++) for (let y = 20; y <= 43; y++)
for (let x = 18; x <= 30; x++) {
let inside = false, edge = false;
for (const [cx, cy, cz, rx, ry, rz] of lobes) {
const d = ((x - cx) / rx) ** 2 +
((y - cy) / ry) ** 2 +
((z - cz) / rz) ** 2;
if (d <= 1) {
inside = true;
if (d > 0.77) edge = true;
}
}
if (!inside || (edge && rand() < 0.055)) continue;
let shade = y < 29 ? 3 : y > 37 ? 1 : 2;
if (x > 26) shade--;
if (z > 41 && y < 32) shade++;
if (rand() < 0.18) shade += rand() < 0.5 ? -1 : 1;
set(x, y, z, red[Math.max(0, Math.min(4, shade))]);
}
// Chunky locks and warm highlights give the plume a combed texture.
line(21, 22, 33, 21, 26, 42, 1, "#ee6857");
line(25, 21, 34, 25, 27, 44, 1, "#ed6454");
line(28, 27, 41, 28, 35, 40, 1, "#a92930");
line(21, 32, 42, 21, 39, 35, 1, "#e35748");
line(25, 35, 41, 26, 41, 33, 1, "#9c2630");import { draw } from "./assets/voxel";
import { yelmoConPluma } from "./assets/yelmo-con-pluma";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, yelmoConPluma, 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 yelmo-con-pluma
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["yelmo-con-pluma"] })
# It lands in client/assets/yelmo-con-pluma.ts
# https://fogon.page/object/yelmo-con-pluma