fogón

← Basics3D assetfogon/trompeta

Trompeta

by fogonCC04536 blocks
TrompetaDrag to turn it
// «Trompeta» · gpt-6-sol (medium)
// Trumpet («Trompeta»).

// Move the entire trumpet down ten blocks so its lowest blocks rest at z = 0.
function buildTrumpet(rawSet, rawSphere, rawCylinder, rawLine, rawBox) {
  const set = (x, y, z, color) => rawSet(x, y, z - 10, color);
  const sphere = (x, y, z, r, color) => rawSphere(x, y, z - 10, r, color);
  const cylinder = (x, y, z, r, h, color, axis) =>
    rawCylinder(x, y, z - 10, r, h, color, axis);
  const line = (x0, y0, z0, x1, y1, z1, r, color) =>
    rawLine(x0, y0, z0 - 10, x1, y1, z1 - 10, r, color);
  const box = (x0, y0, z0, x1, y1, z1, color) =>
    rawBox(x0, y0, z0 - 10, x1, y1, z1 - 10, color);

  const gold = "#d9a43a";
  const light = "#f3c95f";
  const bright = "#ffe18a";
  const shadow = "#a97224";
  const dark = "#78501d";

  function pipeX(x0, x1, y, z, r = 1.6) {
    for (let x = x0; x <= x1; x++) {
      for (let yy = Math.floor(y - r); yy <= Math.ceil(y + r); yy++) {
        for (let zz = Math.floor(z - r); zz <= Math.ceil(z + r); zz++) {
          if ((yy - y) ** 2 + (zz - z) ** 2 > r * r + 0.4) continue;
          let c = yy < y ? light : gold;
          if (zz > z) c = bright;
          if (zz < z - 0.5 || yy > y + 0.5) c = shadow;
          if (rand() < 0.055) c = light;
          set(x, yy, zz, c);
        }
      }
    }
  }

  function pipeY(x, y0, y1, z, r = 1.5) {
    line(x, y0, z, x, y1, z, r, gold);
    line(x, y0, z + 1, x, y1, z + 1, 0, light);
  }

  // Long, parallel runs of tubing and the curved return at the narrow end.
  pipeX(9, 36, 17, 25, 1.65);
  pipeX(10, 34, 29, 21, 1.65);
  pipeX(13, 35, 25, 27, 1.45);
  pipeX(9, 32, 20, 20, 1.2);

  for (let i = 0; i <= 12; i++) {
    const t = Math.PI * i / 12;
    const y = 17 + 12 * (i / 12);
    const x = 8 - 2.7 * Math.sin(t);
    const z = 23 - 2 * (i / 12);
    sphere(x, y, z, 1.65, i < 5 ? light : gold);
    set(Math.round(x), Math.round(y), Math.round(z + 1), bright);
  }

  // Silvery mouthpiece.
  pipeX(5, 10, 29, 21, 1.15);
  cylinder(4, 29, 21, 2, 2, "#d7d9c9", "x");
  cylinder(5, 29, 21, 1, 3, "#a5aaa1", "x");
  set(4, 28, 22, "#f3f0dc");

  // Three upright piston-valve casings.
  for (const x of [18, 24, 30]) {
    cylinder(x, 22, 11, 2.5, 17, shadow);
    cylinder(x, 21, 12, 2.15, 17, gold);
    box(x - 1, 19, 13, x, 19, 27, light);
    box(x + 2, 21, 13, x + 2, 23, 26, dark);
    cylinder(x, 22, 10, 3, 2, gold);
    cylinder(x, 21, 10, 2, 1, bright);
    cylinder(x, 22, 27, 3, 2, light);
    cylinder(x, 22, 29, 1, 4, shadow);

    cylinder(x, 22, 33, 3, 2, gold);
    cylinder(x, 21, 35, 2.5, 1, "#f7df9e");
    box(x - 2, 19, 34, x + 1, 19, 34, bright);

    for (const z of [15, 25]) {
      cylinder(x, 22, z, 3, 1, light);
      set(x + 2, 23, z, shadow);
    }
  }

  // Connecting bends between and below the pistons.
  for (const x of [15, 21, 27, 33]) {
    pipeY(x, 23, 29, 18, 1.1);
    line(x, 28, 18, x + 2, 29, 20, 1.1, light);
  }
  for (const x of [19, 25, 31]) {
    line(x, 19, 25, x + 2, 17, 25, 1, bright);
  }
  pipeX(12, 35, 16, 23, 1.2);

  // Rising bell throat.
  for (let x = 31; x <= 36; x++) {
    const z = 26 + (x - 31) * 0.25;
    pipeX(x, x, 24, z, 2.6 + (x - 31) * 0.38);
  }

  // Wide, hollow, faceted brass bell.
  const profile = [4.4, 5.0, 5.8, 6.7, 7.5, 8.3, 9.0, 9.6, 10.0, 10.2, 10.1, 9.8];
  const cy = 24, cz = 28;
  for (let i = 0; i < profile.length; i++) {
    const x = 33 + i;
    const outer = profile[i];
    const inner = Math.max(2, outer - (i < 7 ? 2.7 : 2.1));
    for (let y = Math.floor(cy - outer); y <= Math.ceil(cy + outer); y++) {
      for (let z = Math.floor(cz - outer); z <= Math.ceil(cz + outer); z++) {
        const d = Math.hypot(y - cy, z - cz);
        if (d > outer + 0.25 || d < inner) continue;
        let c = gold;
        if (z > cz + 2 || y < cy - 3) c = light;
        if (z > cz + 6 && y < cy) c = bright;
        if (z < cz - 3 || y > cy + 3) c = shadow;
        if (i % 3 === 0 && d > outer - 1.1) c = z >= cz ? bright : gold;
        if (rand() < 0.075) c = z >= cz ? "#f8d978" : "#bb842c";
        set(x, y, z, c);
      }
    }
  }

  // Recessed interior and bright rolled lip.
  for (let y = 16; y <= 32; y++) {
    for (let z = 20; z <= 36; z++) {
      const d = Math.hypot(y - cy, z - cz);
      if (d < 7.7) {
        set(42, y, z, d < 4.5 ? "#946321" : "#b78330");
        if (z > cz && rand() < 0.3) set(42, y, z, "#cb9b43");
      }
    }
  }
  for (let y = 14; y <= 34; y++) {
    for (let z = 18; z <= 38; z++) {
      const d = Math.hypot(y - cy, z - cz);
      if (d >= 8.0 && d <= 10.25) {
        set(44, y, z, z >= cz || y < cy ? bright : gold);
        if (d >= 9.35) set(43, y, z, z < cz ? shadow : light);
      }
    }
  }
}

buildTrumpet(set, sphere, cylinder, line, box);