fogón

← Antiguo y prehistoriaObjeto 3Dfogon/domed-house

Casa con cúpula

de fogonCC010411 bloques
Casa con cúpulaArrastrá para girarlo
// «Casa con cúpula» · propio
// A whitewashed desert house with a parapet and a big white dome on its flat roof topped by a small dark iron ball, an arched red door and a striped cloth awning over it on two poles.

// A whitewashed desert house with a parapet and a big white dome on its flat roof topped by a dark iron ball, an
// arched red door and a striped cloth awning over it on two poles.
const white = ["#cfc4aa", "#ddd3bb", "#e8dfca", "#f1ead9", "#f9f4e8"];
const foot = ["#9c8a66", "#ab9973", "#b9a781"];
const red = ["#7d2a1c", "#96372a", "#ad4634", "#c25742"];
const yellow = ["#b98626", "#cf9a35", "#e0ad45", "#edc05e"];
const cream = ["#cbb68c", "#dcc9a0", "#ead9b6", "#f5e8cb"];
const pole = ["#3b2718", "#4a321f", "#5a3e27"];
const iron = ["#232221", "#33312f", "#4a4744"];
const dark = "#1a120c";
const clampi = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
const X0 = 6, X1 = 41, Y0 = 16, Y1 = 42, ROOF = 21;
const hash = (a, b, c = 0) => {
  const s = Math.sin(a * 12.9898 + b * 78.233 + c * 37.719) * 43758.5453;
  return s - Math.floor(s);
};
function wash(x, y, z) {
  let tone = 2 + (hash(Math.floor((x + y) / 6), Math.floor(z / 5)) > 0.6 ? 1 : 0) - (hash(Math.floor((x + y) / 4), Math.floor(z / 3), 2) > 0.84 ? 1 : 0);
  if (z > 15) tone++;
  if (z < 6) tone--;
  if (rand() < 0.06) tone--;
  return white[clampi(tone, 0, 4)];
}
// Walls (hollow), roof and parapet.
for (let x = X0; x <= X1; x++)
  for (let y = Y0; y <= Y1; y++)
    for (let z = 0; z <= ROOF + 3; z++) {
      const wall = x <= X0 + 1 || x >= X1 - 1 || y <= Y0 + 1 || y >= Y1 - 1;
      if (z > ROOF) {
        if (wall) set(x, y, z, z === ROOF + 3 ? white[clampi(4 - (rand() < 0.15 ? 1 : 0), 0, 4)] : wash(x, y, z + 4));
      } else if (wall) set(x, y, z, wash(x, y, z));
      else if (z >= ROOF - 1) set(x, y, z, hash(x >> 2, y >> 2) > 0.5 ? "#d8cdb4" : "#cdc2a8");
    }
// A sand-coloured foot.
for (let x = X0 - 1; x <= X1 + 1; x++)
  for (let y = Y0 - 1; y <= Y1 + 1; y++) {
    if (x > X0 && x < X1 && y > Y0 && y < Y1) continue;
    for (let z = 0; z <= 3; z++) set(x, y, z, z === 3 ? foot[2] : foot[clampi(1 - (rand() < 0.2 ? 1 : 0) + ((x + y) % 7 === 0 ? -1 : 0), 0, 2)]);
  }
// The dome: a shell on the roof, with a ring at its base and the iron ball on a stem.
const CX = 23.5, CY = 29, RX = 11.5, RZ = 10.5;
for (let x = 10; x <= 37; x++)
  for (let y = 16; y <= 42; y++)
    for (let z = ROOF + 1; z <= ROOF + 12; z++) {
      const nx = (x - CX) / RX, ny = (y - CY) / RX, nz = (z - ROOF - 1) / RZ;
      const d = Math.hypot(nx, ny, nz);
      if (d > 1 || d < 0.8) continue;
      let tone = 2 + (nz > 0.55 ? 1 : 0) + (-nx - ny > 0.5 ? 1 : 0) - (nx + ny > 0.7 ? 1 : 0) - (nz < 0.12 ? 1 : 0);
      if (rand() < 0.05) tone--;
      set(x, y, z, white[clampi(tone, 0, 4)]);
    }
for (let x = 10; x <= 37; x++)
  for (let y = 16; y <= 42; y++) {
    const d = Math.hypot(x - CX, y - CY);
    if (d <= RX + 1.2 && d >= RX - 1.5) set(x, y, ROOF + 1, "#cfc4aa");
  }
box(23, 28, ROOF + 11, 24, 29, ROOF + 13, iron[1]);
sphere(23.5, 28.5, ROOF + 15, 1.6, iron[1]);
set(23, 28, ROOF + 16, iron[2]);
// The door: arched, red, in a sand-coloured frame.
const DX = 23.5, SPRING = 10, DR = 5;
for (let x = 15; x <= 32; x++)
  for (let z = 0; z <= 18; z++) {
    const e = z <= SPRING ? Math.abs(x - DX) - DR : Math.hypot(x - DX, z - SPRING) - DR;
    if (e <= 0) {
      const seam = x === 23 || x === 24;
      const fan = z > SPRING;
      let tone = 2 + (x < DX ? 1 : 0) - (Math.round(x - DX + 20.5) % 3 === 0 ? 1 : 0) - (z < 3 ? 1 : 0);
      if (fan) tone = Math.round(Math.atan2(z - SPRING, x - DX) * 3) % 2 === 0 ? 1 : 2;
      set(x, Y0 - 1, z, seam && !fan && z > 0 ? (x === 23 ? red[0] : red[1]) : red[clampi(tone, 0, 3)]);
      set(x, Y0, z, dark);
      if (z === SPRING) set(x, Y0 - 1, z, red[0]);
    } else if (e <= 2) {
      for (const y of [Y0 - 2, Y0 - 1]) set(x, y, z, foot[clampi(1 + (y === Y0 - 2 ? 1 : 0) - (z % 4 === 3 ? 1 : 0), 0, 2)]);
    }
  }
set(21, Y0 - 2, 7, "#c9a23a");
set(26, Y0 - 2, 7, "#c9a23a");
box(16, Y0 - 3, 0, 31, Y0 - 3, 0, foot[2]);
// Two small arched windows, one each side of the door, and one on the left wall.
for (const wx of [10, 36]) {
  box(wx, Y0, 9, wx + 2, Y0, 14, dark);
  set(wx + 1, Y0, 15, dark);
  box(wx - 1, Y0 - 1, 8, wx + 3, Y0 - 1, 8, foot[2]);
}
box(X0, 27, 9, X0, 30, 14, dark);
box(X0, 28, 15, X0, 29, 15, dark);
box(X0 - 1, 26, 8, X0 - 1, 31, 8, foot[2]);
// The awning: striped cloth from the wall down to two poles, with a hem.
const A0 = 13, A1 = 34;
for (let x = A0; x <= A1; x++) {
  const s = Math.floor((x - A0) / 3) % 2 === 0;
  const tones = s ? yellow : cream;
  const fold = (x - A0) % 3 === 0 ? 1 : 0;
  for (let y = 5; y <= Y0 - 1; y++) {
    const z = Math.round(15 + (y - 5) * 0.48 - 1.1 * Math.sin(((x - A0) / (A1 - A0)) * Math.PI));
    set(x, y, z, tones[clampi(3 - fold - (rand() < 0.1 ? 1 : 0), 0, 3)]);
    set(x, y, z - 1, tones[clampi(1 - fold, 0, 3)]);
  }
  const zf = Math.round(15 - 1.1 * Math.sin(((x - A0) / (A1 - A0)) * Math.PI));
  const hang = Math.abs(((x - A0) % 6) - 3) < 1.5 ? 3 : 2;
  for (let k = 1; k <= hang; k++) set(x, 5, zf - k, tones[clampi(2 - fold - (k === hang ? 1 : 0), 0, 3)]);
}
for (const px of [A0, A1 - 1]) {
  for (let z = 0; z <= 15; z++) for (let i = 0; i < 2; i++) for (let j = 0; j < 2; j++) set(px + i, 5 + j, z, pole[clampi(1 + (i === 0 && j === 0 ? 1 : 0) - (z < 2 ? 1 : 0), 0, 2)]);
}