fogón

← AsiáticoObjeto 3Dfogon/daruma

Daruma

de fogonCC027854 bloques
DarumaArrastrá para girarlo
// «Daruma» · gpt-6-sol (medium)
// A round red Daruma doll standing on the ground: an egg-shaped body painted bright red with gold patterns on the sides, a white face area with a big black mustache and eyebrows, ONE eye painted black and the other left blank white.

part("doll", [24, 24, 0]);

const profile = [
  [0, 8], [2, 11], [5, 14], [10, 17], [17, 18],
  [23, 17.5], [29, 15], [34, 11], [38, 6], [39, 3]
];

function radius(z) {
  for (let i = 1; i < profile.length; i++) {
    if (z <= profile[i][0]) {
      const [z0, r0] = profile[i - 1];
      const [z1, r1] = profile[i];
      return r0 + (r1 - r0) * (z - z0) / (z1 - z0);
    }
  }
  return 0;
}

const front = Array.from({ length: 40 }, () => ({}));

// Solid, rounded lacquer body.
for (let z = 0; z <= 39; z++) {
  const r = radius(z);
  for (let x = Math.ceil(24 - r); x <= Math.floor(24 + r); x++) {
    const reach = r * Math.sqrt(Math.max(0, 1 - ((x - 24) / r) ** 2));
    for (let y = Math.ceil(24 - reach); y <= Math.floor(24 + reach); y++) {
      if (front[z][x] === undefined) front[z][x] = y;
      let color = "#d92524";
      if (z < 4) color = "#9d171b";
      else if (y > 29 || z < 9) color = "#b91c20";
      else if (z > 23 && x < 29) color = "#ed3430";
      if (rand() < 0.035) color = z < 9 ? "#a71b1d" : "#e43b32";
      set(x, y, z, color);
    }
  }
}

function paint(x, z, color) {
  x = Math.round(x);
  z = Math.round(z);
  const y = front[z]?.[x];
  if (y === undefined) return;
  set(x, y - 1, z, color);
  set(x, y, z, color);
}

function dot(cx, cz, r, color) {
  for (let x = Math.floor(cx - r); x <= Math.ceil(cx + r); x++)
    for (let z = Math.floor(cz - r); z <= Math.ceil(cz + r); z++)
      if ((x - cx) ** 2 + (z - cz) ** 2 <= r * r)
        paint(x, z, color);
}

function stroke(x0, z0, x1, z1, width, color) {
  const steps = Math.ceil(Math.hypot(x1 - x0, z1 - z0) * 3);
  for (let i = 0; i <= steps; i++) {
    const t = i / steps;
    dot(x0 + (x1 - x0) * t, z0 + (z1 - z0) * t, width, color);
  }
}

function curve(points, width, color) {
  for (let i = 1; i < points.length; i++)
    stroke(...points[i - 1], ...points[i], width, color);
}

// Gold foot rim and small lacquer highlights.
for (let x = 11; x <= 37; x++) {
  paint(x, 3, "#d7a346");
  if (x % 3 !== 0) paint(x, 4, "#f2c966");
}
curve([[12, 8], [15, 7], [19, 6], [24, 6], [29, 6], [33, 7], [36, 8]],
      0.55, "#e9b954");

// Raised gold frame around the face.
for (let a = 0; a < Math.PI * 2; a += 0.018) {
  const x = 24 + 11.8 * Math.cos(a);
  const z = 26.2 + 8.7 * Math.sin(a);
  dot(x, z, 0.65, "#e7ac43");
}

// Cream-white painted face.
for (let z = 18; z <= 35; z++) {
  for (let x = 12; x <= 36; x++) {
    const u = (x - 24) / 10.9;
    const v = (z - 26.2) / 7.8;
    if (u * u + v * v <= 1) {
      paint(x, z, z > 29 ? "#fff8e9" : x > 30 ? "#eee6d7" : "#fff4e4");
    }
  }
}

// Dark, expressive eyebrows.
curve([[16, 30], [18, 32], [20, 32], [22, 30.5]], 1.05, "#211b1c");
curve([[26, 30.5], [28, 32], [30, 32], [32, 30]], 1.05, "#211b1c");
stroke(17, 32.5, 20, 33, 0.35, "#44302a");
stroke(28, 33, 31, 32.5, 0.35, "#44302a");

// Only the viewer-left eye is painted; the right eye remains white.
for (let z = 24; z <= 29; z++)
  for (let x = 16; x <= 22; x++)
    if (((x - 19) / 2.1) ** 2 + ((z - 26.5) / 2.6) ** 2 <= 1)
      paint(x, z, "#17191a");
paint(18, 28, "#fffdf1");

// Heavy, sweeping black mustache.
dot(24, 23, 1.35, "#211819");
curve([[24, 22], [21, 23], [19, 23], [17, 21], [16, 20]],
      1.15, "#211819");
curve([[24, 22], [27, 23], [29, 23], [31, 21], [32, 20]],
      1.15, "#211819");
dot(20, 22, 1.15, "#211819");
dot(28, 22, 1.15, "#211819");

// Mirrored gold cloud-scrolls and lotus petals on the red sides.
for (const s of [-1, 1]) {
  const X = d => 24 + s * d;
  curve([[X(13), 29], [X(16), 27], [X(17), 24], [X(15), 22],
         [X(13), 23], [X(13), 25]], 0.8, "#f4cb68");
  dot(X(13), 25, 0.8, "#ffe092");

  curve([[X(11), 18], [X(15), 17], [X(17), 14], [X(16), 12],
         [X(13), 12]], 0.8, "#e7ad43");
  curve([[X(11), 18], [X(12), 14], [X(11), 11]], 0.65, "#ffd778");
  curve([[X(11), 18], [X(9), 15], [X(9), 12]], 0.65, "#ffd778");
  dot(X(11), 18, 1.05, "#f7ce68");
  dot(X(15), 12, 0.8, "#ffe092");

  for (const [d, z] of [[15, 30], [18, 19], [14, 9], [10, 11]])
    dot(X(d), z, 0.8, "#f3c463");
}

// Little gold crest below the face.
curve([[20, 13], [22, 15], [24, 16], [26, 15], [28, 13]],
      0.8, "#f4c766");
curve([[20, 13], [23, 12], [24, 10], [25, 12], [28, 13]],
      0.65, "#e9af49");
dot(24, 14, 0.9, "#ffe299");

animate("doll", { type: "swing", axis: "y", speed: 2, amplitude: 0.2 });