fogón

← City3D assetfogon/tire-stack

Pila de neumáticos

by fogonCC010163 blocks
Pila de neumáticosDrag to turn it
// «Pila de neumáticos» · propio
// A stack of five black rubber tires with visible tread and round holes in the middle, one more tire leaning against the stack.

// Five tires in a stack and one more leaning against it.
const RUBBER = { side: "#28292d", sideTop: "#3e4046", ring: "#5a5d64", bead: "#33353a", treadA: "#17181a", treadB: "#474a50", rib: "#2c2e32", hole: "#141517" };
const HALF = 3, OUTER = 11.2, INNER = 5.1;

// What a tire has at a point: `axial` along its axle (0 in the middle), `radial` from the axle, `angle` around it.
// `up`: +1 or -1, the side that faces the light.
function tireAt(axial, radial, angle, up) {
  if (Math.abs(axial) > HALF) return null;
  const shoulder = Math.abs(axial) > 2;
  const outer = shoulder ? OUTER - 1 : OUTER, inner = shoulder ? INNER + 0.8 : INNER;
  if (radial > outer || radial < inner) return null;
  if (radial > outer - 1.3) {
    // The tread: dark shoulders (they part one tire from the next), a rib round the middle and lugs on either side.
    if (shoulder) return RUBBER.treadA;
    if (Math.abs(axial) < 1) return RUBBER.rib;
    const seg = Math.floor(((angle + Math.PI) / (2 * Math.PI)) * 24 + (axial > 0 ? 0.5 : 0));
    return seg % 2 ? RUBBER.treadA : RUBBER.treadB;
  }
  if (radial < inner + 1.1) return axial * up > 2 ? RUBBER.bead : RUBBER.hole;
  const lit = axial * up > 2;
  if (radial > 7.6 && radial < 8.8) return lit ? RUBBER.ring : RUBBER.sideTop;
  return lit ? RUBBER.sideTop : RUBBER.side;
}

// The one that leans: its axle points towards the stack and a little down.
const t = (22 * Math.PI) / 180;
const ax = Math.cos(t), az = -Math.sin(t); // the axle
const ux = Math.sin(t), uz = Math.cos(t); // "up" within the tire
const CX = 12.5, CY = 24, CZ = 11.6;
for (let x = 0; x <= 30; x++)
  for (let y = 10; y <= 38; y++)
    for (let z = 0; z <= 27; z++) {
      const dx = x - CX, dy = y - CY, dz = z - CZ;
      const axial = dx * ax + dz * az;
      const rx = dx - axial * ax, rz = dz - axial * az;
      const radial = Math.hypot(rx, dy, rz);
      const c = tireAt(axial, radial, Math.atan2(dy, rx * ux + rz * uz), -1);
      if (c) set(x, y, z, c);
    }

// The stack: each tire a little off the one below.
const offsets = [[0, 0], [1, -1], [-1, 0], [0, 1], [1, 0]];
offsets.forEach(([ox, oy], i) => {
  const cx = 31 + ox, cy = 24 + oy;
  for (let x = cx - 12; x <= cx + 12; x++)
    for (let y = cy - 12; y <= cy + 12; y++)
      for (let k = 0; k < 6; k++) {
        const c = tireAt(k - 2.5, Math.hypot(x - cx, y - cy), Math.atan2(y - cy, x - cx) + i * 0.4, 1);
        if (c) set(x, y, i * 6 + k, c);
      }
});