fogón

← Parties and Christmas3D assetfogon/rosca-de-reyes

Rosca de Reyes

by fogonCC014525 blocks
Rosca de ReyesDrag to turn it
// «Rosca de Reyes» · gpt-6-sol (medium)
// A ring-shaped sweet bread on a round plate: a golden-brown glazed ring decorated on top with stripes of pastry cream, strips of red and green candied fruit and a sprinkle of sugar, with a small crown of gold paper resting on it.

const cx = 24, cy = 24;

// A round, pastel plate with a raised white rim.
for (let x = 2; x <= 46; x++) {
  for (let y = 2; y <= 46; y++) {
    const r = Math.hypot(x - cx, y - cy);
    if (r <= 20.8) set(x, y, 0, "#badbd5");
    if (r <= 21.5) {
      set(x, y, 1, r > 20 ? "#d8e9e5" : "#c8f0e9");
      set(x, y, 2, r > 19.7 ? "#fff9ed" : "#e6fffa");
    }
    if (r <= 19.4) set(x, y, 3, "#effff9");
    if (r >= 19.4 && r <= 21.2) {
      set(x, y, 3, r > 20.5 ? "#e1e9e3" : "#ffffff");
    }
    if (r >= 20 && r <= 21.1) set(x, y, 4, "#fffdf4");
    if (r >= 19.45 && r < 19.9) set(x, y, 4, "#f5cc68");
  }
}

// Solid sweet-bread ring, with a shiny upper crust.
const ringRadius = 13.35;
const tubeRadius = 5.7;
const centerZ = 9;
const tubeHeight = 5.3;

function breadTop(r) {
  const t = (r - ringRadius) / tubeRadius;
  return Math.abs(t) < 1
    ? centerZ + tubeHeight * Math.sqrt(1 - t * t)
    : 0;
}

for (let x = 4; x <= 44; x++) {
  for (let y = 4; y <= 44; y++) {
    const r = Math.hypot(x - cx, y - cy);
    const radial = (r - ringRadius) / tubeRadius;
    if (Math.abs(radial) > 1) continue;
    const top = breadTop(r);

    for (let z = 4; z <= 15; z++) {
      const shape = radial * radial +
        Math.pow((z - centerZ) / tubeHeight, 2);
      if (shape > 1) continue;

      let color;
      if (z >= top - 1.15 && z >= 10) {
        color = rand() < 0.17 ? "#ffdf82" : "#e9a83d";
        if (rand() < 0.12) color = "#f5bd54";
      } else if (z <= 6) {
        color = rand() < 0.2 ? "#a85b28" : "#bc712e";
      } else {
        color = rand() < 0.16 ? "#dc933b" : "#ca7c2e";
      }
      set(x, y, z, color);
    }
  }
}

// Thick, gently wavy stripes of pastry cream across the top.
for (let i = 0; i < 12; i++) {
  const angle = i * Math.PI / 6;
  let previous = null;
  for (let j = 0; j <= 16; j++) {
    const r = 9.3 + j * 0.5;
    const a = angle + 0.022 * Math.sin(j * 0.7 + i);
    const point = [
      cx + r * Math.cos(a),
      cy + r * Math.sin(a),
      breadTop(r) + 0.9
    ];
    if (previous) {
      line(...previous, ...point, 0.7,
        j % 4 === 0 ? "#fff9df" : "#f7e7bb");
    }
    previous = point;
  }
}

// Glossy red and green candied-fruit strips between the cream stripes.
for (let i = 0; i < 12; i++) {
  const angle = (i + 0.5) * Math.PI / 6;
  const r = i % 3 === 0 ? 14.6 : 12.1;
  const x = cx + r * Math.cos(angle);
  const y = cy + r * Math.sin(angle);
  const z = breadTop(r) + 1.35;
  const tx = -Math.sin(angle);
  const ty = Math.cos(angle);
  const green = i % 2 === 0;

  line(x - tx * 1.9, y - ty * 1.9, z,
       x + tx * 1.9, y + ty * 1.9, z,
       0.85, green ? "#278a45" : "#bd2538");
  line(x - tx * 1.5, y - ty * 1.5, z + 0.65,
       x + tx * 1.5, y + ty * 1.5, z + 0.65,
       0.45, green ? "#67d56d" : "#ff6670");
}

// Sparkling sugar crystals, scattered over exposed glaze.
for (let i = 0; i < 135; i++) {
  const angle = rand() * Math.PI * 2;
  const r = 9 + rand() * 8.3;
  const x = Math.round(cx + r * Math.cos(angle));
  const y = Math.round(cy + r * Math.sin(angle));
  const z = Math.round(breadTop(r) + 0.7);
  if (z >= 11 && rand() < 0.78) {
    set(x, y, z, rand() < 0.3 ? "#fff1c9" : "#ffffff");
  }
}

// A little hollow gold-paper crown resting on the back of the bread.
const crownX = 24, crownY = 35;
for (let x = 19; x <= 29; x++) {
  for (let y = 30; y <= 40; y++) {
    const dx = x - crownX, dy = y - crownY;
    const r = Math.hypot(dx, dy);
    if (r < 3.35 || r > 4.8) continue;

    const a = Math.atan2(dy, dx);
    let nearestPoint = Math.PI;
    for (let k = 0; k < 5; k++) {
      const pointAngle = -Math.PI / 2 + k * Math.PI * 2 / 5;
      const difference = Math.atan2(
        Math.sin(a - pointAngle), Math.cos(a - pointAngle)
      );
      nearestPoint = Math.min(nearestPoint, Math.abs(difference));
    }
    const pointedTop = 18.2 + 4.5 *
      Math.max(0, 1 - nearestPoint / (Math.PI / 5));

    for (let z = 14; z <= 23; z++) {
      if (z > pointedTop) continue;
      let color = dy < 0 ? "#f9c747" : "#d99422";
      if (z === 14 || z === 17) color = "#ffe477";
      else if (z > 18 && rand() < 0.3) color = "#ffe076";
      set(x, y, z, color);
    }
  }
}

// Rounded golden tips and bright jewels on the crown's front band.
for (let k = 0; k < 5; k++) {
  const a = -Math.PI / 2 + k * Math.PI * 2 / 5;
  sphere(
    crownX + 4.1 * Math.cos(a),
    crownY + 4.1 * Math.sin(a),
    22,
    0.8,
    "#ffe67a"
  );
}
sphere(24, 30.6, 16, 1, "#e94455");
set(24, 30, 17, "#ffb1a3");
sphere(21, 32, 16, 0.8, "#47c993");
sphere(27, 32, 16, 0.8, "#62d7e4");