fogón

← Basics3D assetfogon/mesa-tronco

Mesa tronco

by fogonCC016056 blocks
Mesa troncoDrag to turn it
// «Mesa tronco» · gpt-6-sol (medium)
// Stump table («Mesa tronco»).

const cx = 24, cy = 24;
const bark = ["#643b24", "#754429", "#87512d", "#995d32", "#ad6c3a"];
const grain = ["#f7cc80", "#f9d38a", "#f3c477", "#edb76a", "#ffdc96"];

function hash(x, y, z = 0) {
  const n = Math.sin(x * 127.1 + y * 311.7 + z * 74.7) * 43758.5453;
  return n - Math.floor(n);
}

// Uneven, solid trunk with long vertical bark grain.
for (let z = 2; z <= 30; z++) {
  for (let x = 10; x <= 38; x++) for (let y = 10; y <= 38; y++) {
    const dx = x - cx, dy = y - cy;
    const a = Math.atan2(dy, dx);
    const r = Math.hypot(dx, dy);
    const flare = z < 7 ? (7 - z) * 0.36 : 0;
    const edge = 9.5 + flare
      + 0.65 * Math.sin(a * 11 + 0.4)
      + 0.42 * Math.sin(a * 19 - 1.1)
      + 0.23 * Math.sin(z * 0.43 + a * 7);
    if (r > edge) continue;

    const stripe = Math.sin(a * 29 + 0.45 * Math.sin(z * 0.23 + a * 8));
    const fleck = hash(x, y, Math.floor(z / 3));
    let shade = stripe > 0.52 ? 3 : stripe < -0.55 ? 0 : 2;
    if (r > edge - 2.2) {
      shade += stripe > 0.75 ? 1 : 0;
      if (fleck < 0.10) shade--;
      if (fleck > 0.91) shade++;
    }
    set(x, y, z, bark[Math.max(0, Math.min(4, shade))]);
  }
}

// Raised bark strips, staggered breaks and dark fissures.
for (let i = 0; i < 46; i++) {
  const a = i * Math.PI * 2 / 46;
  const rr = 9.7 + 0.55 * Math.sin(a * 11 + 0.4);
  const x = Math.round(cx + Math.cos(a) * rr);
  const y = Math.round(cy + Math.sin(a) * rr);
  for (let z = 6 + Math.floor(hash(i, 3) * 5); z < 29; z++) {
    if (hash(i, Math.floor(z / 5)) < 0.14) continue;
    const c = i % 5 === 0 ? "#56341f" :
              i % 4 === 0 ? "#ae6e3b" :
              i % 3 === 0 ? "#85502c" : "#996035";
    set(x, y, z, hash(i, z) < 0.09 ? "#b3753e" : c);
  }
}

// Splayed, knobby roots at the foot.
for (let i = 0; i < 19; i++) {
  const a = i * Math.PI * 2 / 19 + 0.15 * Math.sin(i * 4);
  const reach = 12.0 + hash(i, 41) * 3.0;
  const start = 7.0;
  const c = bark[1 + (i % 4)];
  line(cx + Math.cos(a) * start, cy + Math.sin(a) * start, 5,
       cx + Math.cos(a) * reach, cy + Math.sin(a) * reach, 1, 2.1, c);
  for (let t = 7; t <= reach; t += 1.5) {
    const x = Math.round(cx + Math.cos(a) * t);
    const y = Math.round(cy + Math.sin(a) * t);
    const h = Math.max(1, Math.round(5 - (t - 7) * 0.75));
    box(x, y, 0, x + 1, y + 1, h,
        bark[Math.min(4, 1 + Math.floor(hash(i, t) * 4))]);
    if (hash(i, t, 7) > 0.43)
      set(x, y, h + 1, "#ae7040");
  }
}

// Rough overhanging tabletop: a thick slice of the same tree.
function radius(a) {
  return 18.25
    + 0.38 * Math.sin(9 * a + 0.5)
    + 0.27 * Math.sin(17 * a - 0.8)
    + 0.16 * Math.sin(31 * a);
}
for (let z = 29; z <= 33; z++) {
  for (let x = 4; x <= 44; x++) for (let y = 4; y <= 44; y++) {
    const dx = x - cx, dy = y - cy;
    const r = Math.hypot(dx, dy);
    const a = Math.atan2(dy, dx);
    const lip = radius(a) - (z === 29 ? 0.7 : 0);
    if (r > lip) continue;
    const h = hash(x, y, Math.floor(z / 2));
    let color;
    if (r < lip - 2.3) {
      color = z === 33 ? "#c88949" : "#794825";
    } else {
      color = z === 33 ? (h < 0.5 ? "#ab6834" : "#bd773b")
            : h < 0.18 ? "#59351f"
            : h < 0.52 ? "#754326"
            : h < 0.82 ? "#8f522b" : "#a66432";
    }
    set(x, y, z, color);
  }
}

// Irregular vertical notches around the bark rim.
for (let i = 0; i < 94; i++) {
  const a = i * Math.PI * 2 / 94;
  const r = radius(a);
  const x = Math.round(cx + Math.cos(a) * (r - 0.3));
  const y = Math.round(cy + Math.sin(a) * (r - 0.3));
  const bottom = 29 + Math.floor(hash(i, 12) * 3);
  for (let z = bottom; z <= 32; z++)
    set(x, y, z, hash(i, z) < 0.22 ? "#5b361f" :
        hash(i, 8) > 0.57 ? "#a46232" : "#754326");
}

// Fresh-cut golden top, with a thin darker live edge.
for (let x = 4; x <= 44; x++) for (let y = 4; y <= 44; y++) {
  const dx = x - cx, dy = y - cy;
  const r = Math.hypot(dx, dy);
  const a = Math.atan2(dy, dx);
  const edge = radius(a);
  if (r > edge) continue;

  const h = hash(x, y, 13);
  let color;
  if (r > edge - 0.72)
    color = h < 0.28 ? "#825029" : h < 0.72 ? "#a46532" : "#c48846";
  else if (r > edge - 1.55)
    color = h < 0.35 ? "#dfa458" : "#f4c778";
  else {
    color = grain[Math.floor(h * grain.length)];
    // Broken, gently wandering growth rings rather than perfect circles.
    const warped = r + 0.43 * Math.sin(a * 6 + r * 0.55)
                     + 0.22 * Math.sin(a * 13);
    const rings = [3.8, 6.7, 9.5, 12.1, 14.6, 16.2];
    for (const ring of rings) {
      if (Math.abs(warped - ring) < 0.48 && hash(x, y, 29) > 0.38) {
        color = h > 0.64 ? "#e3a651" : "#eab361";
        break;
      }
    }
    if (r < 2.5 && h > 0.40) color = "#edb665";
    if (h > 0.965) color = "#e6aa58";
  }
  set(x, y, 34, color);
}

// Small dark knot near the outer edge of the cut face.
for (let x = 35; x <= 39; x++) for (let y = 20; y <= 24; y++) {
  const d = Math.hypot((x - 37) * 1.2, y - 22);
  if (d < 1.65 && get(x, y, 34))
    set(x, y, 34, hash(x, y) > 0.35 ? "#9e6335" : "#b87a3e");
}