fogón

← BásicoObjeto 3Dfogon/medio-coco

Medio coco

de fogonCC016644 bloques
Medio cocoArrastrá para girarlo
// «Medio coco» · gpt-6-sol (medium)
// Coconut half («Medio coco»).

// Half a coconut, cut side up.
const cx = 24, cy = 24;
const outerCenter = 20.7, outerRadius = 21.3;
const innerRadius = 17.1;
const TAU = Math.PI * 2;

function hash(a, b) {
  const n = Math.sin(a * 127.1 + b * 311.7) * 43758.5453;
  return n - Math.floor(n);
}

for (let z = 0; z <= 24; z++) {
  const roundRadius = Math.sqrt(Math.max(0,
    outerRadius * outerRadius - (z - outerCenter) ** 2));

  for (let x = 2; x <= 46; x++) {
    for (let y = 2; y <= 46; y++) {
      const dx = x - cx, dy = y - cy;
      const r = Math.hypot(dx, dy);
      const a = Math.atan2(dy, dx);
      const grain = hash(x, y);
      const edge = roundRadius
        + 0.32 * Math.sin(19 * a + 0.3)
        + 0.23 * Math.sin(43 * a + z * 0.12)
        + (grain - 0.5) * (z < 21 ? 0.85 : 0.35);

      if (r > edge) continue;

      let cavityFloor = 23.2;
      if (r < innerRadius) {
        cavityFloor = 23.2 - 14.1 *
          Math.sqrt(Math.max(0, 1 - (r / innerRadius) ** 2));
        if (z > cavityFloor + 0.35) continue;
      }

      const meat = (r < innerRadius && z >= cavityFloor - 2.2) ||
        (r >= 16.8 && r < 19.15 && z >= 22);
      const lip = z >= 22 && r >= 19.15;

      if (meat) {
        const depth = 24 - z;
        const light = hash(x + z * 7, y - z * 3);
        let color;
        if (depth < 2 || (r > 16.8 && z >= 23)) {
          color = light < 0.20 ? "#dad9cf" :
                  light < 0.73 ? "#f0eee5" : "#faf8ee";
        } else if (depth < 8) {
          color = light < 0.22 ? "#bcbdb5" :
                  light < 0.73 ? "#d8d8d0" : "#e9e9e1";
        } else {
          color = light < 0.35 ? "#aaa9a2" :
                  light < 0.83 ? "#c4c4ba" : "#d9d9d0";
        }
        set(x, y, z, color);
      } else {
        const streak = Math.sin(a * 94 + 0.55 * Math.sin(z * 0.65 + a * 17));
        const fleck = hash(x * 3 + z * 11, y * 5 - z * 7);
        const underside = z < 9;
        let color = streak < -0.52 ? "#62361e" :
                    streak > 0.65 ? "#a35c2d" : "#854821";
        if (underside && streak < 0.45) color = "#70391d";
        if (fleck < 0.10) color = "#61351d";
        if (fleck > 0.87) color = underside ? "#8b4924" : "#b16b36";
        if (lip) color = fleck < 0.27 ? "#70391e" :
                         fleck > 0.74 ? "#a55c2d" : "#874720";
        set(x, y, z, color);
      }
    }
  }
}

// Short, uneven fibers and raised grain on the outside of the husk.
for (let i = 0; i < 220; i++) {
  const angle = rand() * TAU;
  const start = 2 + Math.floor(rand() * 17);
  const length = 2 + Math.floor(rand() * 7);
  const shade = ["#62351c", "#774020", "#9b5328", "#ad6532"][Math.floor(rand() * 4)];
  for (let z = start; z < Math.min(22, start + length); z++) {
    const radius = Math.sqrt(Math.max(0,
      outerRadius * outerRadius - (z - outerCenter) ** 2));
    const twist = angle + 0.012 * Math.sin(z * 0.8 + i);
    const x = Math.round(cx + (radius + 0.18) * Math.cos(twist));
    const y = Math.round(cy + (radius + 0.18) * Math.sin(twist));
    if (get(x, y, z) === undefined ||
        !["#faf8ee", "#f0eee5", "#e9e9e1"].includes(get(x, y, z))) {
      set(x, y, z, shade);
    }
  }
}