fogón

← Antiguo y prehistoriaObjeto 3Dfogon/coliseo

Coliseo

de fogonCC09552 bloques
ColiseoArrastrá para girarlo
// «Coliseo» · gpt-6-sol (medium)
// A compact Roman Colosseum: an oval ring of tan-cream stone with three stacked levels of arches, one side taller and the other partly broken down so the inside is visible, showing a sandy arena floor and tiers of seats.

const cx = 24, cy = 24;
const stone = ["#e8d4ae", "#f0dfbd", "#ddc49b", "#d4b88c"];
const trim = "#f6e9cc";
const shadow = "#b99870";

function oval(x, y, rx, ry) {
  return ((x - cx) / rx) ** 2 + ((y - cy) / ry) ** 2;
}

function stoneColor(z) {
  if (rand() < 0.08) return stone[3];
  if (rand() < 0.18) return stone[2];
  return z % 10 >= 8 ? stone[1] : stone[0];
}

// Broad, solid foundation.
for (let x = 3; x <= 45; x++)
for (let y = 7; y <= 41; y++) {
  const q = oval(x, y, 20.8, 16.7);
  if (q <= 1) set(x, y, 0, q > 0.87 ? shadow : "#cfb184");
  if (q <= 0.96) set(x, y, 1, q > 0.83 ? "#dec49b" : "#cbb087");
}

// Sandy arena, with a few broad patches of warmer sand.
for (let x = 12; x <= 36; x++)
for (let y = 16; y <= 32; y++) {
  if (oval(x, y, 11.2, 7.3) > 1) continue;
  const patch = Math.sin(x * 0.63 + y * 0.28) + Math.cos(y * 0.81 - x * 0.19);
  set(x, y, 2, rand() < 0.10 ? "#d7ae72" :
    patch > 0.7 ? "#f0d29a" : "#e7c58e");
}

// Low retaining lip around the sand.
for (let x = 11; x <= 37; x++)
for (let y = 15; y <= 33; y++) {
  if (oval(x, y, 12.0, 8.1) <= 1 &&
      oval(x, y, 11.25, 7.35) > 1) {
    set(x, y, 2, "#a97858");
    set(x, y, 3, "#dfc4a0");
  }
}

// Six rising, chunky rings of spectator seating.
for (let row = 0; row < 6; row++) {
  const rx = 12.35 + row * 0.91;
  const ry = 8.35 + row * 0.82;
  const innerX = rx - 0.94, innerY = ry - 0.84;
  const top = 4 + row;
  for (let x = 6; x <= 42; x++)
  for (let y = 10; y <= 38; y++) {
    if (oval(x, y, rx, ry) > 1 || oval(x, y, innerX, innerY) <= 1) continue;
    const a = Math.atan2((y - cy) / ry, (x - cx) / rx);
    const aisle = Math.abs(Math.sin(4 * a)) < 0.055 && row > 1;
    for (let z = 2; z <= top; z++) {
      set(x, y, z, z === top
        ? (aisle ? "#ae896e" : rand() < 0.15 ? "#f8e7c8" : "#ebd5b0")
        : "#bea17d");
    }
    if (!aisle && row > 0 && rand() < 0.65)
      set(x, y, top + 1, "#f4e1bf");
  }
}

// A stepped central aisle climbs the far seating.
for (let y = 31; y <= 37; y++)
for (let x = 23; x <= 25; x++) {
  const z = Math.min(10, 4 + Math.floor((y - 30) * 0.85));
  set(x, y, z, (y & 1) ? "#b39576" : "#d5b997");
}

// Elliptical arcade: twenty broad arch bays on each of three levels.
const bays = 20;
const step = 2 * Math.PI / bays;
function archFraction(x, y) {
  let a = Math.atan2((y - cy) / 16.2, (x - cx) / 20.1);
  a = ((a + Math.PI * 2) % (Math.PI * 2));
  let t = ((a / step) % 1 + 1) % 1;
  return Math.abs(t - 0.5) * 2; // 0 at arch center, 1 at its pillar
}
function wallHeight(x, y) {
  if (y >= 22) return 30;
  if (y >= 17 && (x <= 12 || x >= 36)) return 29;
  if (x <= 13) return 21;
  if (x >= 35) return 21;
  if (x <= 17 || x >= 31) return 12;
  if (x <= 20 || x >= 28) return 7;
  return 3; // collapsed front center exposes the arena
}

for (let x = 3; x <= 45; x++)
for (let y = 7; y <= 41; y++) {
  const q = Math.sqrt(oval(x, y, 20.0, 16.0));
  if (q < 0.865 || q > 1.045) continue;
  const f = archFraction(x, y);
  let height = wallHeight(x, y);
  if (height < 29) {
    height += Math.sin(x * 2.4 + y * 1.8) > 0.5 ? 1 : 0;
    if (Math.sin(x * 1.7 - y * 2.2) < -0.75) height--;
  }

  for (let z = 2; z <= height; z++) {
    const level = Math.floor((z - 2) / 10);
    const within = (z - 2) % 10;
    const archedTop = 6 - Math.floor(3 * (f / 0.76) ** 2);
    const opening = level < 3 && f < 0.76 &&
      within >= 1 && within <= archedTop;
    if (opening) continue;

    let color = stoneColor(z);
    if (z === 10 || z === 11 || z === 20 || z === 21 || z === 29)
      color = z % 10 === 0 ? "#d4b995" : trim;
    else if (f > 0.78 && within >= 1 && within <= 7)
      color = rand() < 0.12 ? "#d3b991" : "#edd9b5";
    else if (within === 7 && f < 0.76)
      color = "#f3dfbc"; // bright voussoirs above each arch
    if (z === height && height < 29) color = "#f0ddbb";
    set(x, y, z, color);
  }

  // Engaged columns project beyond the wall, making every bay legible.
  if (q > 0.975 && f > 0.81) {
    for (let base of [2, 12, 22]) {
      if (height < base + 2) continue;
      for (let z = base + 1; z <= Math.min(base + 7, height); z++) {
        set(x, y, z, z === base + 1 || z === base + 7
          ? trim : "#e9d4ae");
      }
    }
  }
}

// Strong horizontal cornices on the surviving upper walls.
for (let x = 3; x <= 45; x++)
for (let y = 7; y <= 41; y++) {
  const q = Math.sqrt(oval(x, y, 20.45, 16.4));
  if (q < 0.97 || q > 1.055) continue;
  const h = wallHeight(x, y);
  for (const z of [11, 21, 30]) {
    if (h >= z) set(x, y, z, z === 30 ? "#f7e9cc" : "#e9d1aa");
  }
}

// Irregular broken stones scattered just inside the missing front wall.
for (let i = 0; i < 35; i++) {
  const x = 16 + Math.floor(rand() * 17);
  const y = 10 + Math.floor(rand() * 5);
  if (oval(x, y, 19.4, 15.4) > 1) continue;
  const z = get(x, y, 2) ? 3 : 2;
  set(x, y, z, rand() < 0.5 ? "#efdcba" : "#c8a77d");
}

// Two small crimson standards hang against the tall, far inner wall.
for (const bx of [17, 30]) {
  box(bx, 36, 17, bx + 2, 36, 20, "#9f3d3d");
  box(bx, 36, 20, bx + 2, 36, 20, "#d9a750");
  set(bx + 1, 35, 18, "#e9bb64");
  set(bx, 36, 16, "#d9a750");
  set(bx + 2, 36, 16, "#d9a750");
}