fogón

← Fiestas y NavidadObjeto 3Dfogon/pan-dulce

Pan dulce

de fogonCC022809 bloques
Pan dulceArrastrá para girarlo
// «Pan dulce» · gpt-6-sol (medium)
// A round Argentinian pan dulce on a wooden board: a tall domed golden-brown loaf with a cracked top dusted with a few nuts, its sides studded with bits of red and green candied fruit and dark raisins, with one slice cut out showing the yellow crumb inside.

// Rounded wooden serving board
for (let x = 3; x <= 43; x++) {
  for (let y = 3; y <= 44; y++) {
    const dx = Math.max(7 - x, 0, x - 39);
    const dy = Math.max(7 - y, 0, y - 40);
    if (dx * dx + dy * dy > 16) continue;

    for (let z = 0; z <= 2; z++) {
      let color = z === 0 ? "#8d4b28" : z === 1 ? "#b66b36" : "#d8934d";
      if (z === 2) {
        if (y === 12 || y === 21 || y === 30 || y === 39) color = "#ad6636";
        else if (rand() < 0.09) color = "#e2a65f";
      }
      set(x, y, z, color);
    }
  }
}

// Small handle with a hanging hole
for (let x = 42; x <= 46; x++) {
  for (let y = 21; y <= 27; y++) {
    if ((x === 46 && (y === 21 || y === 27)) ||
        (x === 42 && (y === 21 || y === 27))) continue;
    for (let z = 0; z <= 2; z++)
      set(x, y, z, z === 2 ? "#d8934d" : z === 1 ? "#b66b36" : "#8d4b28");
  }
}
for (let z = 0; z <= 2; z++) set(44, 24, z, null);

// Soft shadow beneath the loaf
for (let x = 7; x <= 39; x++) {
  for (let y = 9; y <= 41; y++) {
    const d = ((x - 23) / 17) ** 2 + ((y - 25) / 16) ** 2;
    if (d < 1 && get(x, y, 2))
      set(x, y, 2, d > 0.83 ? "#b87740" : "#94522c");
  }
}

function loafTop(x, y) {
  const r2 = ((x - 23) / 15.5) ** 2 + ((y - 25) / 15) ** 2;
  return r2 <= 1 ? 16 + 19 * Math.sqrt(1 - r2) : -1;
}

// The loaf has a generous slice removed from its front.
for (let x = 7; x <= 39; x++) {
  for (let y = 10; y <= 40; y++) {
    const top = loafTop(x, y);
    if (top < 5) continue;

    for (let z = 4; z <= Math.floor(top); z++) {
      if (y < 20 && x >= 18 && x <= 29) continue;

      const cutFace = (y === 20 && x >= 18 && x <= 29) ||
        (x === 17 && y < 20) || (x === 30 && y < 20);

      let color;
      if (cutFace) {
        color = rand() < 0.13 ? "#edbd62" :
          rand() < 0.27 ? "#fff0b1" : "#ffdf83";
      } else if (z < 8) {
        color = rand() < 0.12 ? "#af632e" : "#bd7032";
      } else if (z >= top - 2) {
        color = rand() < 0.23 ? "#f5b55f" : "#dc8e42";
      } else {
        color = rand() < 0.13 ? "#e8a253" : "#c57a37";
      }
      set(x, y, z, color);
    }
  }
}

// Speckles and fruit in the exposed, buttery crumb
for (let x = 18; x <= 29; x++) {
  for (let z = 7; z <= 30; z++) {
    if (!get(x, 20, z) || rand() > 0.075) continue;
    const fruit = ["#bd3539", "#287d4b", "#69412d", "#f39b45"];
    set(x, 20, z, fruit[Math.floor(rand() * fruit.length)]);
    if (rand() < 0.35 && get(x + 1, 20, z))
      set(x + 1, 20, z, fruit[Math.floor(rand() * fruit.length)]);
  }
}

// Bright candied fruit and raisins studding the outer crust
for (let x = 8; x <= 38; x++) {
  for (let y = 11; y <= 39; y++) {
    for (let z = 8; z <= 27; z++) {
      if (!get(x, y, z) || rand() > 0.031) continue;
      const exposed = !get(x, y - 1, z) ||
        !get(x - 1, y, z) || !get(x + 1, y, z);
      if (!exposed) continue;
      if ((y === 20 && x >= 18 && x <= 29) ||
          (x === 17 && y < 20) || (x === 30 && y < 20)) continue;

      const bits = ["#dc353a", "#f04a46", "#32955a", "#267847", "#61402d"];
      set(x, y, z, bits[Math.floor(rand() * bits.length)]);
    }
  }
}

// An irregular, dark baked crack across the crown, with pale torn edges
for (let y = 17; y <= 34; y++) {
  const x = 23 + Math.round(1.5 * Math.sin(y * 0.72));
  const top = Math.floor(loafTop(x, y));
  if (top < 27) continue;
  set(x, y, top, "#925025");
  if (get(x + 1, y, top)) set(x + 1, y, top, "#ffe0a0");
  if (y % 4 === 0 && get(x - 1, y, top))
    set(x - 1, y, top, "#ad602c");
}

// A few chunky toasted nuts nestled into the top
const nuts = [
  [17, 25], [19, 31], [27, 29], [29, 22], [24, 18], [32, 27]
];
for (const [x, y] of nuts) {
  const z = Math.floor(loafTop(x, y));
  if (z < 23) continue;
  ellipsoid(x, y, z + 1, 1.5, 1, 0.8, "#f4d18b");
  set(x, y, z + 2, "#fff0bc");
}

// The removed slice stands in front, showing its golden crumb.
for (let x = 25; x <= 40; x++) {
  const u = (x - 32.5) / 8;
  if (Math.abs(u) >= 1) continue;
  const top = Math.floor(18 + 8 * Math.sqrt(1 - u * u));

  for (let y = 6; y <= 11; y++) {
    for (let z = 4; z <= top; z++) {
      const crust = z >= top - 2 || z <= 5 ||
        x <= 26 || x >= 39;
      let color;
      if (crust)
        color = z >= top - 1 ? "#e7a052" : "#b96d32";
      else if (y <= 8)
        color = rand() < 0.16 ? "#fff0b0" : "#ffdd7d";
      else
        color = "#e9b765";
      set(x, y, z, color);
    }
  }
}

// Fruit clearly visible on the slice's cut face
const sliceFruit = [
  [29, 11, "#d83d42"], [35, 10, "#338b51"],
  [32, 16, "#65402c"], [37, 17, "#d93c42"],
  [28, 18, "#329653"], [34, 21, "#62412e"]
];
for (const [x, z, color] of sliceFruit) {
  if (get(x, 6, z)) set(x, 6, z, color);
}

// A little shine along the board's front edge
for (let x = 9; x <= 40; x++) {
  if (get(x, 3, 2) && x % 5 !== 0) set(x, 3, 2, "#edb36b");
}