fogón

← CiudadObjeto 3Dfogon/tarp-cargo

Carga con lona

de fogonCC07150 bloques
Carga con lonaArrastrá para girarlo
// «Carga con lona» · propio
// A lumpy pile of cargo covered by an olive green tarp with soft folds, tied down with tan ropes, a corner of a wooden crate showing underneath.

// Cargo under an olive tarp: the cloth hangs from whatever is below it, in folds, tied down with ropes. At the front
// left corner it has been pulled up and the wooden crate underneath shows.
const OLIVE = ["#3d4430", "#4d573a", "#5e6946", "#707c54", "#838f64"]; // dark → light
const ROPE = "#d4b77e", ROPE_DARK = "#a98d58";
const WOOD = { plank: ["#b9803f", "#c68d49", "#d29a55"], groove: "#8a5a28", frame: "#9c6730", frameDark: "#744a20", nail: "#2e2a26" };
const G = 48;

// How high the cargo is at each place (0: nothing there): a tall crate, lower boxes beside it, a drum, some sacks.
function cargo(x, y) {
  let h = 0;
  if (x >= 9 && x <= 25 && y >= 9 && y <= 38) h = 21;
  if (x >= 26 && x <= 40 && y >= 12 && y <= 30) h = Math.max(h, 14);
  if (x >= 26 && x <= 37 && y >= 31 && y <= 38) h = Math.max(h, 9);
  const drum = Math.hypot(x - 33, y - 21);
  if (drum < 6) h = Math.max(h, 14 + Math.sqrt(36 - drum * drum) * 0.9);
  const sacks = Math.pow((x - 17) / 7, 2) + Math.pow((y - 28) / 8, 2);
  if (sacks < 1) h = Math.max(h, 21 + 4 * Math.sqrt(1 - sacks));
  return h;
}
const raw = [], top = [];
for (let x = 0; x < G; x++) {
  raw.push([]);
  for (let y = 0; y < G; y++) raw[x].push(cargo(x, y));
}
// The cloth: over the cargo it lies on it; around it, it falls steeply to the ground, waving a little (the folds).
const fold = (x, y) => Math.sin(x * 1.1) + Math.sin(y * 1.1);
for (let x = 0; x < G; x++) {
  top.push([]);
  for (let y = 0; y < G; y++) {
    let best = -1;
    for (let i = Math.max(0, x - 6); i <= Math.min(G - 1, x + 6); i++)
      for (let j = Math.max(0, y - 6); j <= Math.min(G - 1, y + 6); j++)
        if (raw[i][j] > 0) best = Math.max(best, raw[i][j] - 4 * Math.hypot(i - x, j - y));
    if (raw[x][y] === 0 && best > 0) best += fold(x, y) * 0.7;
    top[x].push(best > 0.3 ? Math.round(best) : -1);
  }
}
const at = (x, y) => (x < 0 || y < 0 || x >= G || y >= G ? -1 : top[x][y]);
const pulledUp = (x, y, z) => x + y + 0.9 * z < 31;

// The crate that shows: boards, a frame, nails.
for (let x = 9; x <= 25; x++)
  for (let y = 9; y <= 38; y++)
    for (let z = 0; z <= 20; z++) {
      if (x > 10 && y > 10 && z < 19) continue;
      const a = x <= 10 ? y - 9 : x - 9, A = x <= 10 ? 30 : 17;
      let c = a % 4 === 0 ? WOOD.groove : WOOD.plank[(Math.floor(a / 4) * 5) % 3];
      if (a < 2 || a >= A - 2 || z < 2 || z > 18) c = z === 0 || a === 0 ? WOOD.frameDark : WOOD.frame;
      if ((a === 1 || a === A - 2) && (z === 1 || z === 19)) c = WOOD.nail;
      set(x, y, z, c);
    }

for (let x = 0; x < G; x++)
  for (let y = 0; y < G; y++) {
    const t = top[x][y];
    if (t < 0) continue;
    const low = Math.min(at(x - 1, y), at(x + 1, y), at(x, y - 1), at(x, y + 1));
    const flat = raw[x][y] > 0, f = fold(x, y);
    for (let z = Math.max(0, low - 1); z <= t; z++) {
      if (pulledUp(x, y, z)) continue;
      let k = flat && z === t ? (t >= 23 ? 4 : 3) : f > 0.6 ? 3 : f < -0.6 ? 1 : 2;
      if (!flat && z < 3) k -= 1;
      if (flat && z < t) k = 2;
      if (rand() < 0.08) k -= 1;
      if (pulledUp(x, y, z - 2.3)) k = 4; // the hem of the lifted corner
      set(x, y, z, OLIVE[Math.max(0, Math.min(4, k))]);
    }
  }

// The ropes: over the top and down both sides, one block above the cloth.
function rope(cells) {
  for (let n = 0; n < cells.length; n++) {
    const [x, y] = cells[n], t = top[x][y];
    if (t < 0) continue;
    let low = t;
    for (const m of [n - 1, n + 1]) if (cells[m] && at(cells[m][0], cells[m][1]) >= 0) low = Math.min(low, at(cells[m][0], cells[m][1]));
    for (let z = low + 1; z <= t + 1; z++) if (!pulledUp(x, y, z - 1)) set(x, y, z, (x + y + z) % 3 === 0 ? ROPE_DARK : ROPE);
  }
}
const along = (fixed, isX) => Array.from({ length: G }, (_, i) => (isX ? [fixed, i] : [i, fixed]));
rope(along(16, true));
rope(along(33, true));
rope(along(17, false));
rope(along(32, false));