Etappe E: Spielhaus als Stelzenhaus nach Plan
Deploy App / deploy (push) Successful in 27s

Der Plan zeichnet zwei Rechtecke uebereinander: Podest 1.81 x 2.70 m mit
der Kote 1.47 und darauf an der Ostseite die Huette 1.01 x 2.70 m. Bisher
stand hier ein geschlossener Kasten auf der Podestflaeche. Jetzt Stuetzen,
Podestboden auf 1.47, offene Plattform mit Bruestung im Westen, Huette mit
Pultdach im Osten und eine Leiter an der Westseite.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-10 18:06:32 +02:00
co-authored by Claude Opus 5
parent 5d5bc50b38
commit ce40d6275b
4 changed files with 76 additions and 17 deletions
+4
View File
@@ -136,6 +136,10 @@ aus (`src/scene/walls.ts`):
des Gefälles, Entwässerungsrinnen mit bündigem Rost.
- **Gartentor** – Stabgitterflügel von 100 cm mit zwei Pfosten und senkrechten
Stäben, nicht als geschlossenes Blatt.
- **Spielhaus** – ein Stelzenhaus. Der Plan zeichnet zwei Rechtecke: das Podest
1.81 × 2.70 m mit der Kote 1.47 (rund 0.9 m über dem Gelände) und darauf an
der Ostseite die Hütte 1.01 × 2.70 m. Der westliche Teil bleibt offene
Plattform mit Brüstung und Leiter.
Die **Eibengruppen** entstehen nicht aus Einzelkugeln: die Pflanzstandorte des
Plans werden gruppenweise verkettet, begradigt, an scharfen Knicken getrennt und
File diff suppressed because one or more lines are too long
+65 -14
View File
@@ -103,31 +103,82 @@ function gartenhaus(p: Prop, y: number): Group {
}
/** Spielhaus durch Zimmermann: Podest, Bretterwaende, Gelaender, Pultdach. */
/**
* Spielhaus des Zimmermanns: ein Stelzenhaus. Der Plan zeigt ein Podest von
* 1.81 x 2.70 m mit der Kote 1.47 - also rund 0.9 m ueber dem Gelaende - und
* darauf an der Ostseite eine Huette von 1.01 x 2.70 m. Der westliche Teil
* des Podests bleibt offene Plattform mit Bruestung und Leiter.
*/
function spielhaus(p: Prop, y: number): Group {
const g = new Group();
const holz = material(tex.fassadeHolz(), { color: 0xd8b98c, roughness: 0.85 });
const dunkel = material(tex.fassadeHolz(), { color: 0xa8895f, roughness: 0.88 });
const podestTop = y + 0.55;
const dach = material(tex.fassadeHolz(), { color: 0x7d6549, roughness: 0.9 });
const podest = new Mesh(boxGeometry(p.x, p.z, p.w, p.d, y - 0.1, podestTop, p.rot, 1.2), dunkel);
const deck = p.top ?? y + 0.9; // Oberkante Podestboden
const hw = p.w / 2, hd = p.d / 2;
const hutW = 1.01; // Huette an der Ostseite
const hutX = p.x + hw - hutW / 2;
const plattW = p.w - hutW; // offene Plattform im Westen
const plattX = p.x - hw + plattW / 2;
const trag: BufferGeometry[] = [];
// Vier Stuetzen, etwas eingerueckt
for (const dx of [-hw + 0.14, hw - 0.14]) {
for (const dz of [-hd + 0.14, hd - 0.14]) {
trag.push(boxGeometry(p.x + dx, p.z + dz, 0.11, 0.11, y - 0.35, deck - 0.06, 0, 1));
}
}
// Podestboden
trag.push(boxGeometry(p.x, p.z, p.w, p.d, deck - 0.06, deck, p.rot, 1.2));
const podest = new Mesh(mergeGeometries(trag), dunkel);
podest.castShadow = true; podest.receiveShadow = true;
g.add(podest);
const hw = p.w / 2, hd = p.d / 2;
// Rueckwand und zwei Seitenwaende, Vorderseite offen
const back = new Mesh(boxGeometry(p.x, p.z + hd - 0.05, p.w, 0.09, podestTop, y + p.h, p.rot, 1.2), holz);
const left = new Mesh(boxGeometry(p.x - hw + 0.05, p.z, 0.09, p.d, podestTop, y + p.h, p.rot, 1.2), holz);
const right = new Mesh(boxGeometry(p.x + hw - 0.05, p.z - hd / 3, 0.09, p.d / 3, podestTop, y + p.h, p.rot, 1.2), holz);
for (const m of [back, left, right]) { m.castShadow = true; m.receiveShadow = true; g.add(m); }
// Huette: Rueckwand, zwei Seitenwaende, Vorderseite offen
const wand: BufferGeometry[] = [];
wand.push(boxGeometry(hutX, p.z + hd - 0.05, hutW, 0.09, deck, deck + p.h, p.rot, 1.2));
wand.push(boxGeometry(hutX, p.z - hd + 0.05, hutW, 0.09, deck, deck + p.h, p.rot, 1.2));
wand.push(boxGeometry(hutX + hutW / 2 - 0.05, p.z, 0.09, p.d, deck, deck + p.h, p.rot, 1.2));
// Halbe Wand zur Plattform hin, damit ein Durchgang bleibt
wand.push(boxGeometry(hutX - hutW / 2 + 0.05, p.z + hd / 2, 0.09, p.d / 2, deck, deck + p.h, p.rot, 1.2));
const huette = new Mesh(mergeGeometries(wand), holz);
huette.castShadow = true; huette.receiveShadow = true;
g.add(huette);
// Bruestung an der offenen Seite
const rail = new Mesh(boxGeometry(p.x, p.z - hd + 0.05, p.w, 0.07, podestTop + 0.32, podestTop + 0.45, p.rot, 1.2), holz);
rail.castShadow = true;
g.add(rail);
// Bruestung um die offene Plattform, Pfosten und Handlauf
const gel: BufferGeometry[] = [];
const gy0 = deck + 0.62, gy1 = deck + 0.72;
gel.push(boxGeometry(plattX, p.z + hd - 0.04, plattW, 0.06, gy0, gy1, p.rot, 1));
gel.push(boxGeometry(plattX, p.z - hd + 0.04, plattW, 0.06, gy0, gy1, p.rot, 1));
gel.push(boxGeometry(p.x - hw + 0.04, p.z, 0.06, p.d, gy0, gy1, p.rot, 1));
for (let i = 0; i <= 5; i++) {
const zz = p.z - hd + 0.1 + (i * (p.d - 0.2)) / 5;
gel.push(boxGeometry(p.x - hw + 0.04, zz, 0.05, 0.05, deck, gy1, 0, 1));
}
const bruestung = new Mesh(mergeGeometries(gel), holz);
bruestung.castShadow = true;
g.add(bruestung);
// Leiter an der Westseite
const leiter: BufferGeometry[] = [];
const lx = p.x - hw - 0.16;
for (const dz of [-0.24, 0.24]) {
leiter.push(boxGeometry(lx, p.z + dz, 0.07, 0.07, y, deck + 0.28, 0, 1));
}
const stufen = Math.max(3, Math.round((deck - y) / 0.26));
for (let i = 1; i <= stufen; i++) {
leiter.push(boxGeometry(lx, p.z, 0.05, 0.55, y + (i * (deck - y)) / stufen - 0.03,
y + (i * (deck - y)) / stufen, 0, 1));
}
const l = new Mesh(mergeGeometries(leiter), dunkel);
l.castShadow = true;
g.add(l);
// Pultdach ueber der Huette
const roof = new Mesh(
boxGeometry(p.x, p.z, p.w + 0.26, p.d + 0.26, y + p.h, y + p.h + 0.09, p.rot, 2),
material(tex.fassadeHolz(), { color: 0x7d6549, roughness: 0.9 }),
boxGeometry(hutX, p.z, hutW + 0.3, p.d + 0.26, deck + p.h, deck + p.h + 0.09, p.rot, 2),
dach,
);
roof.castShadow = true;
g.add(roof);
+6 -2
View File
@@ -192,8 +192,12 @@ export const WALLS = [
export const PROPS = [
{ id: 'gartenhaus', type: 'gartenhaus', x: 1.20, z: -3.60, w: 1.8, d: 1.8, h: 2.15, rot: 0,
note: 'Standort Gartenhaus 1,8 x 1,8 m' },
{ id: 'spielhaus', type: 'spielhaus', x: 0.0, z: 3.15, w: 1.8, d: 2.7, h: 2.30, rot: 0,
note: 'Spielhaus durch Zimmermann, Podest auf 1.47' },
// Der Plan zeichnet zwei Rechtecke: das Podest 1.81 x 2.70 m (x -0.95 bis
// 0.86) und darauf die Huette 1.01 x 2.70 m an der Ostseite (x -0.15 bis
// 0.86). Die Kote 1.47 im Podest ist die Hoehe des Bodens - ein Stelzenhaus,
// rund 0.9 m ueber dem Gelaende.
{ id: 'spielhaus', type: 'spielhaus', x: -0.045, z: 3.15, w: 1.81, d: 2.70, h: 1.90, rot: 0,
top: 1.47, note: 'Spielhaus durch Zimmermann, Podest auf 1.47' },
{ id: 'flammengrill', type: 'flammengrill', x: -6.95, z: 2.45, w: 0.7, d: 0.7, h: 0.85, rot: 0,
note: 'Flammengrill im Dekorkiesfeld' },
{ id: 'baenkli', type: 'bank', x: -20.62, z: 1.42, w: 0.50, d: 1.50, h: 0.45, rot: 90,