fogón

← NaturalezaObjeto 3Dfogon/planta-tropical

Planta tropical

de fogonCC05254 bloques
Planta tropicalArrastrá para girarlo
// «Planta tropical» · gpt-6-sol (medium)
// A big tropical plant with very large broad glossy green leaves (monstera style with splits), fanning out from the ground.

// A ground-level crown of glossy, split tropical leaves.
const C = {
  soil: "#805533",
  soilLight: "#a77342",
  soilDark: "#65432e",
  stem: "#318b39",
  stemLight: "#57b94a",
  underside: "#247b35",
  shade: "#29953b",
  green: "#39aa42",
  bright: "#4fc651",
  sunlit: "#69d55a",
  rim: "#81df68",
  vein: "#a6e874"
};

cylinder(24, 24, 0, 5, 2, C.soil);
ellipsoid(24, 24, 2, 4, 4, 2, C.soilLight);
for (let i = 0; i < 35; i++) {
  const a = rand() * Math.PI * 2;
  const r = 2 + rand() * 3;
  set(24 + Math.cos(a) * r, 24 + Math.sin(a) * r, 1,
      rand() < 0.6 ? C.soilDark : "#679c3d");
}
cylinder(24, 24, 2, 2, 9, C.stem);
cylinder(24, 24, 7, 1, 7, C.stemLight);

function growLeaf(angle, reach, baseZ, tipZ, width, phase) {
  const dx = Math.cos(angle), dy = Math.sin(angle);
  const sx = -dy, sy = dx;
  const rootR = 4.2;

  function point(t, u) {
    const r = rootR + (reach - rootR) * t;
    const drift = 1.1 * Math.sin(Math.PI * t + phase) * Math.sin(Math.PI * t);
    const x = 24 + dx * r + sx * (u + drift);
    const y = 24 + dy * r + sy * (u + drift);
    const z = baseZ + (tipZ - baseZ) * t
      + 2.3 * Math.sin(Math.PI * t)
      - 0.065 * Math.abs(u) ** 1.45
      + 0.55 * Math.sin(5 * Math.PI * t + phase) * Math.abs(u) / width;
    return [Math.round(x), Math.round(y), Math.round(z)];
  }

  // Curved, sturdy petiole underneath the blade.
  const jointX = 24 + dx * 1.5, jointY = 24 + dy * 1.5;
  const midX = 24 + dx * 3.1, midY = 24 + dy * 3.1;
  const rootX = 24 + dx * rootR, rootY = 24 + dy * rootR;
  line(24, 24, 4, jointX, jointY, 8, 1, C.stem);
  line(jointX, jointY, 8, midX, midY, baseZ - 4, 1, C.stemLight);
  line(midX, midY, baseZ - 4, rootX, rootY, baseZ, 1, C.stem);

  function halfWidth(t) {
    return Math.max(0.18, width * Math.pow(Math.sin(Math.PI * t), 0.72));
  }

  function isCut(t, fraction, side) {
    // Three deep, tapered cuts from each edge.
    for (let i = 0; i < 3; i++) {
      const center = [0.34, 0.57, 0.78][i]
        + (side < 0 ? 0.035 : 0);
      const depth = Math.max(0, (fraction - 0.46) / 0.54);
      if (Math.abs(t - center) < 0.078 * Math.pow(depth, 0.8))
        return true;
    }
    // Open oval fenestrations inside the leaf.
    const holes = [
      [0.27,  0.51, 0.057, 0.18],
      [0.46, -0.50, 0.068, 0.18],
      [0.66,  0.49, 0.065, 0.17]
    ];
    for (const [ht, hu, tr, ur] of holes) {
      if (((t - ht) / tr) ** 2 + ((side * fraction - hu) / ur) ** 2 < 1)
        return true;
    }
    return false;
  }

  // Sample densely so the sloping voxel leaf stays continuous.
  for (let t = 0; t <= 1.001; t += 0.013) {
    const w = halfWidth(t);
    for (let u = -w; u <= w + 0.01; u += 0.29) {
      const f = Math.abs(u) / w;
      if (f > 1 || isCut(t, f, Math.sign(u) || 1)) continue;
      const [x, y, z] = point(t, u);
      set(x, y, z - 1, C.underside);
      let color = C.green;
      if (f > 0.8) color = C.bright;
      if (f < 0.28 || y < 24) color = C.bright;
      if (f < 0.17 && rand() < 0.55) color = C.sunlit;
      if (f > 0.82 && rand() < 0.35) color = C.rim;
      if (rand() < 0.055) color = C.shade;
      set(x, y, z, color);
    }
  }

  // Raised central rib, with short diagonal veins that stop before the cuts.
  for (let t = 0.06; t < 0.94; t += 0.022) {
    const [x, y, z] = point(t, 0);
    set(x, y, z + 1, t < 0.75 ? C.vein : C.sunlit);
  }
  for (const t0 of [0.18, 0.37, 0.55, 0.72]) {
    for (const side of [-1, 1]) {
      for (let k = 0; k <= 11; k++) {
        const f = 0.09 + k * 0.055;
        const t = t0 + k * 0.006;
        if (isCut(t, f, side)) continue;
        const [x, y, z] = point(t, side * halfWidth(t) * f);
        if (get(x, y, z)) set(x, y, z + 1, C.sunlit);
      }
    }
  }
}

// Back leaves first, then the broad leaves fanning toward the viewer.
growLeaf( 2.38, 20, 15, 38, 8.0, 0.2);
growLeaf( 1.53, 19, 14, 36, 7.8, 1.1);
growLeaf( 0.76, 20, 15, 39, 8.5, 2.0);
growLeaf( Math.PI, 19, 13, 31, 8.2, 0.7);
growLeaf( 0.03, 19, 13, 32, 8.2, 1.7);
growLeaf(-2.34, 20, 14, 36, 8.7, 0.5);
growLeaf(-0.78, 20, 14, 37, 8.7, 1.5);
growLeaf(-Math.PI / 2, 21, 12, 31, 9.0, 2.3);

// A fresh, narrower leaf emerging through the middle of the crown.
line(24, 24, 7, 25, 23, 27, 1, C.stemLight);
ellipsoid(25, 23, 29, 2, 2, 8, C.bright);
line(25, 22, 23, 25, 22, 36, 0, C.vein);

// Small leaves hide the junction of the stalks at ground level.
for (let i = 0; i < 7; i++) {
  const a = i * Math.PI * 2 / 7;
  const x = 24 + Math.cos(a) * 4;
  const y = 24 + Math.sin(a) * 4;
  line(24, 24, 3, x, y, 5, 1, C.stem);
  ellipsoid(x, y, 5, 2, 2, 2, i % 2 ? C.bright : C.green);
  set(x, y, 7, C.sunlit);
}