fogón

← Fantasy3D assetfogon/mesa-de-alquimia

Mesa de alquimia

by fogonCC011135 blocks
Mesa de alquimiaDrag to turn it
// «Mesa de alquimia» · gpt-6-sol (medium)
// A heavy wooden alchemy table: a bubbling glass flask over a small flame, coiled glass tubes, a mortar with pestle, scattered herbs, an open scroll and a few colored potion bottles on top.

const wood = "#493028", woodDark = "#302321", woodMid = "#674331";
const woodLight = "#80563a", brass = "#bb8842", gold = "#e8b85d";
const glass = "#71c9bf", glassLight = "#b5f5db";

// Heavy legs, with broad feet and warm brass fittings.
for (const x of [8, 39]) {
  for (const y of [15, 35]) {
    box(x - 2, y - 2, 0, x + 2, y + 2, 17, woodDark);
    box(x - 1, y - 1, 2, x + 1, y + 1, 16, woodMid);
    box(x - 3, y - 3, 0, x + 3, y + 3, 2, wood);
    box(x - 2, y - 2, 5, x + 2, y + 2, 6, brass);
    box(x - 2, y - 2, 14, x + 2, y + 2, 15, brass);
  }
}

// Aprons and chunky tabletop.
box(7, 12, 12, 40, 15, 17, woodDark);
box(7, 35, 12, 40, 38, 17, woodDark);
box(5, 14, 13, 8, 36, 17, woodDark);
box(39, 14, 13, 42, 36, 17, woodDark);
box(4, 11, 17, 43, 39, 19, woodDark);
box(5, 12, 19, 42, 38, 20, woodMid);
for (let y = 12; y <= 38; y += 6) {
  box(5, y, 20, 42, Math.min(y + 4, 38), 20,
      [woodLight, "#765037", "#895d40", "#714b35", "#81563b"][Math.floor((y - 12) / 6)]);
  box(5, y + 5, 20, 42, y + 5, 20, woodDark);
}
box(4, 11, 18, 43, 11, 19, woodLight);
box(4, 39, 18, 43, 39, 19, woodLight);
for (let x = 7; x <= 40; x += 8) {
  box(x, 11, 18, x + 1, 11, 19, brass);
}

// Subtle grain on the broad top.
for (let i = 0; i < 125; i++) {
  const x = 6 + Math.floor(rand() * 35);
  const y = 13 + Math.floor(rand() * 24);
  if (get(x, y, 20) !== woodDark) {
    set(x, y, 20, rand() < 0.5 ? "#966645" : "#68432f");
    if (rand() < 0.45) set(x + 1, y, 20, "#966645");
  }
}

// Two inset drawers facing the viewer.
for (const x of [13, 32]) {
  box(x - 6, 11, 12, x + 6, 11, 16, brass);
  box(x - 5, 10, 13, x + 5, 10, 15, woodMid);
  box(x - 4, 9, 14, x + 4, 9, 14, woodLight);
  box(x - 1, 8, 13, x + 1, 9, 14, gold);
  set(x, 8, 14, "#fff0a3");
}

// Raised rear rail, carved with little golden studs.
box(5, 37, 21, 42, 39, 24, woodDark);
box(6, 37, 24, 41, 39, 24, woodLight);
for (let x = 8; x <= 40; x += 5) set(x, 36, 23, gold);

// Brass tripod and the little flame beneath the flask.
for (const [x, y] of [[15, 22], [23, 22], [19, 29]]) {
  line(x, y, 21, 19, 25, 25, 0, brass);
  set(x, y, 21, gold);
}
for (let a = 0; a < Math.PI * 2; a += 0.13) {
  set(19 + 4 * Math.cos(a), 25 + 4 * Math.sin(a), 25, brass);
}
box(17, 23, 21, 21, 27, 21, "#735043");
ellipsoid(19, 25, 23, 2, 2, 2, "#ffae38");
ellipsoid(19, 25, 24, 1, 1, 2, "#ffe779");
set(19, 24, 25, "#fffac0");
set(18, 24, 22, "#f36b4b");

// Round hollow glass flask.
for (let x = 13; x <= 25; x++) for (let y = 19; y <= 31; y++)
for (let z = 25; z <= 36; z++) {
  const d = Math.sqrt(((x - 19) / 5.2) ** 2 +
                      ((y - 25) / 5.2) ** 2 +
                      ((z - 30) / 5.2) ** 2);
  if (d > 0.78 && d <= 1.06) {
    set(x, y, z, y <= 22 ? "#a6ebd6" : glass);
  }
}
// Tall narrow neck and open-looking lip.
for (let z = 34; z <= 39; z++) {
  for (let x = 17; x <= 21; x++) for (let y = 23; y <= 27; y++) {
    if (x === 17 || x === 21 || y === 23 || y === 27)
      set(x, y, z, y === 23 ? glassLight : glass);
  }
}
box(16, 22, 39, 22, 22, 39, glassLight);
box(16, 28, 39, 22, 28, 39, glass);
for (let y = 23; y <= 27; y++) {
  set(16, y, 39, glassLight);
  set(22, y, 39, glassLight);
}

// The magical liquid is its own animated part.
part("liquid", [19, 25, 29]);
for (let x = 15; x <= 23; x++) for (let y = 21; y <= 29; y++)
for (let z = 26; z <= 30; z++) {
  const d = Math.sqrt(((x - 19) / 5.2) ** 2 +
                      ((y - 25) / 5.2) ** 2 +
                      ((z - 30) / 5.2) ** 2);
  if (d < 0.73 && z <= 29 + (x % 3 === 0 ? 1 : 0))
    set(x, y, z, "#a8f44b");
}
animate("liquid", {
  type: "colors", palette: ["#b8ff46", "#49df6f", "#f5ef55"],
  pattern: "wave", glow: 0.8
});
part("body");

// Glass reflections and a few bubbles seen through the front.
line(16, 21, 29, 17, 20, 32, 0, "#e5fff0");
set(18, 20, 34, "#e5fff0");
set(18, 20, 35, "#e5fff0");
for (const [x, y, z] of [[17, 21, 30], [20, 21, 31], [19, 21, 28]]) {
  set(x, y, z, "#efffd2");
}

// Curled glass condenser: a tube winding behind the flask toward the bottles.
function tube(x0, y0, z0, x1, y1, z1) {
  line(x0, y0, z0, x1, y1, z1, 0, "#55bcb7");
}
tube(22, 26, 37, 25, 30, 37);
let prev = null;
for (let i = 0; i <= 46; i++) {
  const t = i / 46 * Math.PI * 3.5;
  const p = [27 + 3.2 * Math.cos(t), 32 + i * 0.045,
             35 + 3.2 * Math.sin(t)];
  if (prev) tube(...prev, ...p);
  if (i % 7 === 0) set(...p, "#d4fff0");
  prev = p;
}
tube(...prev, 32, 33, 31);
tube(32, 33, 31, 33, 33, 29);

// Stone mortar, dark inside, with a chunky slanted pestle.
ellipsoid(11, 26, 23, 5, 5, 3, "#777c75");
ellipsoid(11, 26, 24, 4, 4, 2, "#9da298");
for (let x = 6; x <= 16; x++) for (let y = 21; y <= 31; y++) {
  const d = Math.hypot(x - 11, y - 26);
  if (d < 3.2) set(x, y, 26, "#3d5047");
  else if (d <= 5) set(x, y, 26, d > 4.3 ? "#c3bdae" : "#90968b");
}
for (const [x, y] of [[9, 24], [12, 25], [11, 28], [13, 27]])
  set(x, y, 26, "#8fcb59");
line(10, 25, 25, 7, 23, 32, 1, "#b8aa8c");
sphere(7, 23, 32, 1, "#ded2a8");

// An unfurled parchment on the right front, complete with rolled edges.
box(28, 14, 21, 40, 24, 21, "#b9966b");
box(29, 15, 22, 39, 23, 22, "#f5dda1");
for (let y = 14; y <= 24; y++) {
  sphere(28, y, 22, 1, "#e2bf80");
  sphere(40, y, 22, 1, "#e2bf80");
}
for (const [y, a, b] of [[17, 31, 37], [19, 30, 35], [21, 31, 38]]) {
  for (let x = a; x <= b; x++) {
    if ((x + y) % 4 !== 0) set(x, y, 23, "#8d604d");
  }
}
set(37, 20, 23, "#a9498b");
set(38, 20, 23, "#a9498b");

// Three little jewel-toned potions along the back.
function bottle(cx, cy, c, hi) {
  box(cx - 2, cy - 2, 21, cx + 2, cy + 2, 26, c);
  box(cx - 1, cy - 1, 27, cx + 1, cy + 1, 29, hi);
  box(cx - 2, cy - 2, 26, cx + 2, cy + 2, 26, glassLight);
  box(cx - 1, cy - 1, 30, cx + 1, cy + 1, 30, brass);
  box(cx, cy, 31, cx, cy, 31, gold);
  box(cx - 2, cy - 2, 23, cx - 2, cy - 2, 25, "#ddffef");
  set(cx - 1, cy - 2, 25, "#ffffff");
}
bottle(33, 32, "#ad49b6", "#e488ea");
bottle(39, 32, "#278f99", "#67e6dc");
bottle(39, 26, "#bb555f", "#ff9a85");

// Herbs strewn around the work, with bright leaves and a tiny mushroom.
function herb(x, y) {
  line(x - 2, y + 1, 21, x + 2, y - 1, 21, 0, "#546c3b");
  for (const [dx, dy] of [[-2, 0], [-1, -1], [1, 1], [2, -2]]) {
    set(x + dx, y + dy, 21, "#75a84c");
    set(x + dx, y + dy, 22, rand() < 0.5 ? "#a6ca61" : "#648d46");
  }
}
herb(11, 16);
herb(22, 15);
herb(25, 20);
box(8, 17, 21, 8, 17, 22, "#ead9ae");
sphere(8, 17, 23, 2, "#d0717d");
set(7, 15, 23, "#fff2c9");
set(9, 15, 23, "#fff2c9");

// Loose brass tools and a few sparkling flecks.
line(16, 16, 21, 20, 17, 21, 0, brass);
sphere(16, 16, 21, 1, gold);
for (const [x, y] of [[25, 14], [26, 27], [35, 27]]) {
  set(x, y, 21, "#e9ba62");
  set(x + 1, y, 21, "#c18c4c");
}