fogón

← Nature3D assetfogon/lavanda

Lavanda

by fogonCC09519 blocks
LavandaDrag to turn it
// «Lavanda» · gpt-6-sol (medium)
// A round clump of lavender: many thin upright grey-green stems topped with spikes of purple flowers.

// Low, leafy base
ellipsoid(24, 24, 2, 10, 9, 3, "#758e69");
ellipsoid(24, 24, 4, 8, 7, 3, "#93a781");

const greens = ["#6f886e", "#819a79", "#9bab87", "#b0bd98"];
const purples = ["#8654bd", "#9d63d2", "#b47ce3", "#cd9af0", "#ddaef6"];
const goldenAngle = 2.399963;

// Pointed, grey-green leaves spreading from the crown
for (let i = 0; i < 100; i++) {
  const a = i * goldenAngle;
  const reach = 5 + rand() * 10;
  const start = 1 + rand() * 5;
  const z = 1 + Math.floor(rand() * 4);
  const color = greens[Math.floor(rand() * greens.length)];
  line(
    24 + Math.cos(a) * start, 24 + Math.sin(a) * start, z,
    24 + Math.cos(a) * reach, 24 + Math.sin(a) * reach, z + 2 + rand() * 4,
    0, color
  );
}

// Upright, gently fanning stems with distinct lavender flower spikes
const count = 76;
for (let i = 0; i < count; i++) {
  const a = i * goldenAngle;
  const spread = Math.sqrt((i + 0.5) / count);
  const r = spread * (13.8 + rand() * 1.7);
  const tipX = 24 + Math.cos(a) * r;
  const tipY = 24 + Math.sin(a) * r;
  const footX = 24 + Math.cos(a) * r * 0.55;
  const footY = 24 + Math.sin(a) * r * 0.55;

  const top = Math.round(39 - spread * 7 + (rand() - 0.5) * 8);
  const length = 8 + Math.floor(rand() * 4);
  const bottom = top - length;
  const stemColor = greens[Math.floor(rand() * 3)];

  line(footX, footY, 4, tipX, tipY, bottom + 1, 0, stemColor);

  // A few narrow leaves along each stalk
  if (rand() < 0.8) {
    const leafZ = 8 + Math.floor(rand() * 9);
    const t = (leafZ - 4) / (bottom - 3);
    const sx = footX + (tipX - footX) * t;
    const sy = footY + (tipY - footY) * t;
    const side = rand() < 0.5 ? -1 : 1;
    line(sx, sy, leafZ, sx + Math.cos(a + side) * 4,
         sy + Math.sin(a + side) * 4, leafZ + 3, 0,
         greens[1 + Math.floor(rand() * 3)]);
  }

  // Each spike is plump near its base and tapers to a bright pointed tip.
  for (let z = bottom; z <= top; z++) {
    const t = (z - bottom) / length;
    const radius = t < 0.24 ? 1.45 + t * 3.2 : 2.2 * Math.pow((1 - t) / 0.76, 0.7) + 0.25;
    const cx = Math.round(tipX + Math.sin(i * 2.1 + z * 0.4) * 0.25);
    const cy = Math.round(tipY);

    for (let dx = -2; dx <= 2; dx++) {
      for (let dy = -2; dy <= 2; dy++) {
        const distance = Math.hypot(dx, dy);
        if (distance > radius || (distance > radius - 0.3 && rand() < 0.25)) continue;
        let shade = 1 + Math.floor(rand() * 3);
        if (dy < 0 || t > 0.7) shade = Math.min(4, shade + 1);
        if (dy > 0 && rand() < 0.45) shade = Math.max(0, shade - 1);
        set(cx + dx, cy + dy, z, purples[shade]);
      }
    }

    // Tiny projecting florets break up the outline of each spike.
    if (t > 0.12 && t < 0.85 && rand() < 0.45) {
      const angle = a + z * 2.4;
      set(cx + Math.round(Math.cos(angle) * (radius + 0.4)),
          cy + Math.round(Math.sin(angle) * (radius + 0.4)),
          z, purples[2 + Math.floor(rand() * 3)]);
    }
  }
}