fogón

← NaturalezaObjeto 3Dfogon/baobab

Baobab

de fogonCC013067 bloques
BaobabArrastrá para girarlo
// «Baobab» · gpt-6-sol (medium)
// A baobab tree: an enormously thick bottle-shaped grey-brown trunk with a short flat crown of stubby bare branches ending in small tufts of green leaves.

// A squat, bottle-trunked baobab with a sparse, flat crown.
const cx = 24, cy = 24;

const bark = ["#776d60", "#897a68", "#988773", "#a8957d"];
const groove = "#5e584f";
const leafDark = "#398b49";
const leafMid = "#55ac51";
const leafLight = "#78c966";
const leafSun = "#9cdd76";

function trunkRadius(z) {
  const profile = [
    [0, 10.5], [3, 11.7], [10, 12.3], [17, 11.4],
    [23, 9.4], [28, 7.1], [32, 5.6], [35, 5.1]
  ];
  for (let i = 1; i < profile.length; i++) {
    if (z <= profile[i][0]) {
      const a = profile[i - 1], b = profile[i];
      return a[1] + (b[1] - a[1]) * (z - a[0]) / (b[0] - a[0]);
    }
  }
  return 5.1;
}

// Solid, gently uneven bottle-shaped trunk.
for (let z = 0; z <= 35; z++) {
  const rx = trunkRadius(z);
  const ry = rx * 0.89;
  for (let x = Math.floor(cx - rx - 1); x <= Math.ceil(cx + rx + 1); x++) {
    for (let y = Math.floor(cy - ry - 1); y <= Math.ceil(cy + ry + 1); y++) {
      const dx = x - cx, dy = y - cy;
      const angle = Math.atan2(dy, dx);
      const edge = 0.17 * Math.sin(angle * 7 + z * 0.18)
                 + 0.13 * Math.sin(angle * 11 - z * 0.11);
      if ((dx * dx) / (rx * rx) + (dy * dy) / (ry * ry) <= 1 + edge / rx) {
        const shade = rand();
        const color = z < 5 ? bark[0]
          : shade < 0.12 ? bark[0]
          : shade < 0.69 ? bark[1]
          : shade < 0.94 ? bark[2] : bark[3];
        set(x, y, z, color);
      }
    }
  }
}

// Chunky roots flowing out from the foot of the trunk.
for (let i = 0; i < 9; i++) {
  const a = i * Math.PI * 2 / 9 + 0.12;
  const reach = 12.5 + (i % 3);
  const ux = Math.cos(a), uy = Math.sin(a);
  line(cx + ux * 7, cy + uy * 6, 5,
       cx + ux * reach, cy + uy * reach * 0.88, 0, 2.1, "#796d5d");
  line(cx + ux * 9, cy + uy * 8, 3,
       cx + ux * reach, cy + uy * reach * 0.88, 0, 1.2, "#998772");
}

// Broken, wandering vertical bark furrows around the trunk.
for (let i = 0; i < 17; i++) {
  const angle = i * Math.PI * 2 / 17;
  const bottom = 2 + i % 5;
  const top = 22 + i % 9;
  for (let z = bottom; z <= top; z++) {
    if ((z + 3 * i) % 13 === 0 || (z + i) % 17 === 0) continue;
    const a = angle + 0.045 * Math.sin(z * 0.35 + i);
    const rx = trunkRadius(z), ry = rx * 0.89;
    const x = Math.round(cx + (rx - 0.3) * Math.cos(a));
    const y = Math.round(cy + (ry - 0.3) * Math.sin(a));
    if (get(x, y, z)) set(x, y, z, groove);
    if (z % 3 !== 0) {
      const hx = Math.round(cx + (rx - 0.5) * Math.cos(a + 0.075));
      const hy = Math.round(cy + (ry - 0.5) * Math.sin(a + 0.075));
      if (get(hx, hy, z)) set(hx, hy, z, "#ab9880");
    }
  }
}

function tuft(x, y, z) {
  // Several small overlapping pom-poms, rather than a continuous canopy.
  ellipsoid(x, y, z, 2.8, 2.5, 2.1, leafDark);
  ellipsoid(x - 0.8, y - 0.5, z + 0.7, 2.2, 2.1, 1.8, leafMid);
  ellipsoid(x + 0.7, y + 0.3, z + 0.9, 1.8, 1.8, 1.4, leafLight);
  ellipsoid(x - 0.6, y - 0.8, z + 1.6, 1.3, 1.1, 0.8, leafSun);
}

const branches = [
  [18,  0, 36], [-18,  0, 36],
  [ 0, 17, 36], [  0,-17, 36],
  [14, 13, 36], [-15,-12, 36],
  [15,-13, 35], [-14, 14, 35]
];

branches.forEach(([dx, dy, height], i) => {
  const sx = cx + dx * 0.23, sy = cy + dy * 0.23;
  const mx = cx + dx * 0.65, my = cy + dy * 0.65;
  line(sx, sy, 31, mx, my, 34, 2.5, "#837360");
  line(mx, my, 34, cx + dx, cy + dy, height, 1.65, "#766856");

  // Exposed little fork at each leafy tip.
  line(cx + dx * 0.81, cy + dy * 0.81, 35,
       cx + dx * 0.92 - dy * 0.1,
       cy + dy * 0.92 + dx * 0.1, height + 1, 0.8, "#897761");
  tuft(cx + dx, cy + dy, height + 1);
});

// A few short upright shoots fill out the center without hiding the bare limbs.
line(22, 23, 34, 19, 21, 38, 1.3, "#837360");
tuft(19, 21, 38);
line(26, 25, 34, 29, 27, 38, 1.3, "#837360");
tuft(29, 27, 38);