fogón

← NaturalezaObjeto 3Dfogon/roca-grande

Peñasco

de fogonCC027081 bloques
PeñascoArrastrá para girarlo
// «Peñasco» · gpt-6-sol (medium)
// A large rocky outcrop: several big angular grey boulders piled together, the tallest in the back, with moss on the upper surfaces and small pebbles around the base. Uses most of the grid.

// A pile of broad, faceted boulders. The tallest stone rises at the back.
const stones = [
  { x: 24, y: 33, z: 19, rx: 12, ry: 10, rz: 20, seed: 1 },
  { x: 11, y: 31, z: 13, rx: 9,  ry: 10, rz: 14, seed: 2 },
  { x: 38, y: 32, z: 12, rx: 8,  ry: 9,  rz: 13, seed: 3 },
  { x: 23, y: 23, z: 10, rx: 13, ry: 10, rz: 11, seed: 4 },
  { x: 12, y: 16, z: 9,  rx: 9,  ry: 9,  rz: 10, seed: 5 },
  { x: 36, y: 18, z: 10, rx: 9,  ry: 9,  rz: 11, seed: 6 },
  { x: 25, y: 12, z: 7,  rx: 9,  ry: 8,  rz: 8,  seed: 7 }
];

const grey = ["#818c8b", "#959f9e", "#aab3b1", "#bec6c2", "#d0d4cc"];

for (const b of stones) {
  for (let z = Math.max(0, b.z - b.rz); z <= b.z + b.rz; z++) {
    for (let y = b.y - b.ry - 1; y <= b.y + b.ry + 1; y++) {
      for (let x = b.x - b.rx - 1; x <= b.x + b.rx + 1; x++) {
        const u = (x - b.x) / b.rx;
        const v = (y - b.y) / b.ry;
        const w = (z - b.z) / b.rz;
        const a = Math.abs(u), d = Math.abs(v), c = Math.abs(w);

        // Intersect several broad planes to give each rock angular, cut faces.
        if (a + .35*d + .27*c > 1.04 ||
            .35*a + d + .28*c > 1.05 ||
            .42*a + .40*d + c > 1.06 ||
            .49*Math.abs(u+v) + .29*c > 1.01 ||
            .49*Math.abs(u-v) + .26*c > 1.04) continue;

        let shade = 1;
        if (w > .12) shade++;
        if (w > .62) shade++;
        if (u < -.30 && v < .25) shade++;
        if (v > .35 || w < -.40) shade--;
        if (rand() < .075) shade += rand() < .5 ? -1 : 1;
        shade = Math.max(0, Math.min(4, shade));
        set(x, y, z, grey[shade]);
      }
    }
  }
}

// Moss gathers in irregular, connected patches on the sunlit upper faces.
for (let x = 2; x <= 45; x++) {
  for (let y = 3; y <= 44; y++) {
    for (let z = 5; z <= 40; z++) {
      if (!get(x, y, z) || get(x, y, z + 1)) continue;
      const patch =
        .65 * Math.sin(x*.43 + y*.13) +
        .48 * Math.cos(y*.53 - x*.18) +
        .29 * Math.sin(x*.93 - y*.71);
      if (patch < .57) continue;

      const moss = rand();
      set(x, y, z, moss < .15 ? "#48884c" :
                   moss < .55 ? "#62a959" :
                   moss < .88 ? "#79be61" : "#98d174");

      // A few little moss fringes spill down exposed edges.
      if (z > 6 && !get(x, y - 1, z) && rand() < .25) {
        set(x, y, z - 1, rand() < .5 ? "#518f4d" : "#69ae59");
      }
    }
  }
}

// Short, broken seams on the visible front faces.
const cracks = [
  [[10, 13], [11, 12], [11, 11], [12, 10], [12, 9]],
  [[19, 13], [20, 12], [20, 11], [21, 10]],
  [[35, 15], [35, 14], [36, 13], [36, 12], [37, 11]]
];
for (const crack of cracks) {
  for (const [x, z] of crack) {
    for (let y = 3; y <= 40; y++) {
      const color = get(x, y, z);
      if (color) {
        if (color[1] !== "4" && color[1] !== "6" && color[1] !== "7") {
          set(x, y, z, "#788482");
        }
        break;
      }
    }
  }
}

// Loose, rounded chips around the foot of the outcrop.
const pebbleColors = ["#a1aaa6", "#bac2b9", "#929d99", "#c9cdc2"];
for (let i = 0; i < 90; i++) {
  const x = 3 + Math.floor(rand() * 42);
  const y = 3 + Math.floor(rand() * 42);
  if (get(x, y, 0) || get(x, y, 1)) continue;
  // Keep chips near the pile rather than scattering them across empty corners.
  if (Math.abs(x - 24) + Math.abs(y - 24) > 34) continue;
  const color = pebbleColors[Math.floor(rand() * pebbleColors.length)];
  set(x, y, 0, color);
  if (rand() < .45) set(x + 1, y, 0, color);
  if (rand() < .16) set(x, y, 1, "#d0d3c9");
}