fogón

← Animals3D assetfogon/pulpo

Pulpo

by fogonCC011734 blocks
PulpoDrag to turn it
// «Pulpo» · gpt-6-sol (medium)
// A cute cartoon purple octopus facing front (-y): a big round head with big white eyes with black pupils and pink cheeks, and eight curly tentacles spreading out on the floor around it with lighter pink sucker dots underneath.

const purple = ["#9650c5", "#a65bd4", "#b56be0"];
const pink = "#f4a2d2";
const palePink = "#ffd0e9";
const cx = 24, cy = 24;

// Eight thick, curling tentacles. Four wave independently.
for (let i = 0; i < 8; i++) {
  const angle = (-157.5 + i * 45) * Math.PI / 180;
  const dx = Math.sin(angle), dy = -Math.cos(angle);
  const sx = -dy, sy = dx;
  const curl = i < 4 ? -1 : 1;

  const moving = i >= 2 && i <= 5;
  if (moving) {
    const name = `tentacle${i}`;
    part(name, [cx + dx * 6, cy + dy * 6, 9]);
    animate(name, {
      type: "swing",
      axis: i % 2 ? "x" : "y",
      speed: i % 2 ? 3 : -3,
      amplitude: 0.3
    });
  } else {
    part("body");
  }

  const distance = [6, 8.5, 11, 13.5, 16, 18.5, 20, 20, 18.5];
  const sideways = [0, 0.2, 0.6, 1.1, 1.6, 1.8, 1.2, -0.2, -1.4];
  const height = [10, 8, 6, 4.5, 2.7, 2.5, 3.5, 6.5, 8];
  const radius = [3.6, 3.4, 3.1, 2.9, 2.7, 2.5, 2.2, 1.9, 1.5];

  function point(j) {
    return {
      x: cx + dx * distance[j] + sx * sideways[j] * curl,
      y: cy + dy * distance[j] + sy * sideways[j] * curl,
      z: height[j]
    };
  }

  // Overlapping round segments make a smooth, chunky arm.
  for (let j = 0; j < distance.length - 1; j++) {
    const a = point(j), b = point(j + 1);
    for (let step = 0; step < 4; step++) {
      const t = step / 4;
      const x = a.x + (b.x - a.x) * t;
      const y = a.y + (b.y - a.y) * t;
      const z = a.z + (b.z - a.z) * t;
      const r = radius[j] + (radius[j + 1] - radius[j]) * t;
      sphere(x, y, z, r, purple[j < 3 ? 0 : j < 6 ? 1 : 2]);
      sphere(x - 0.35, y - 0.35, z + r * 0.48, r * 0.58, "#bd76e4");
    }
  }

  const tip = point(8);
  sphere(tip.x, tip.y, tip.z, radius[8], "#bb74e1");

  // Flattened undersides visibly rest on the floor at z = 0.
  for (const j of [4, 5]) {
    const p = point(j);
    ellipsoid(p.x, p.y, 1, 2.2, 2.2, 1.2, "#8743b8");
    set(Math.round(p.x), Math.round(p.y), 0, "#8743b8");
  }

  // Paired pink suckers remain visible from above.
  for (let j = 2; j <= 7; j++) {
    const p = point(j), r = radius[j];
    for (const side of [-1, 1]) {
      const x = p.x + sx * side * 0.85;
      const y = p.y + sy * side * 0.85 - 0.35;
      const z = p.z + r * 0.76;
      sphere(x, y, z, 1.05, pink);
      sphere(x, y - 0.12, z + 0.3, 0.62, palePink);
    }
  }
}

// The whole head gently bobs above the grounded tentacles.
part("head", [24, 24, 18]);
animate("head", { type: "bob", axis: "z", speed: 2, amplitude: 1 });

ellipsoid(24, 24, 15, 7.8, 7.5, 8, "#8743b8");
ellipsoid(24, 24, 25, 11, 10.5, 13, "#a65bd4");

// Soft top-to-bottom shading with slight surface variation.
forEach((x, y, z, color) => {
  if (color !== "#a65bd4" || z < 14) return;
  let shade = z > 31 ? "#bd75e5" : z > 23 ? "#ae63dc" : "#9d52cc";
  if (rand() < 0.035) shade = z > 26 ? "#c480e9" : "#b86cdf";
  set(x, y, z, shade);
});

// Oversized white eyes, black pupils, and tiny highlights.
for (const x of [19, 29]) {
  ellipsoid(x, 14.1, 28, 3.1, 2.2, 3.8, "#f8f2ff");
  ellipsoid(x, 11.9, 27.7, 1.45, 1.1, 2, "#21152d");
  sphere(x - 0.5, 10.9, 29, 0.65, "#ffffff");
}

// Rosy cheeks and a small curved smile.
ellipsoid(15.8, 16.1, 23, 2.1, 1.15, 1.5, "#f3a0cf");
ellipsoid(32.2, 16.1, 23, 2.1, 1.15, 1.5, "#f3a0cf");
set(21, 14, 21, "#693478");
set(22, 13, 20, "#693478");
set(23, 13, 19, "#693478");
set(24, 13, 19, "#693478");
set(25, 13, 19, "#693478");
set(26, 13, 20, "#693478");
set(27, 14, 21, "#693478");

part("body");