Wege, Ebenen, Stufen und ein Sprung
Deploy App / deploy (push) Successful in 28s

Rueckmeldung Punkt fuer Punkt:

Weg rund ums Haus
- Der Ostweg ist jetzt durchgehend gepflastert von der Verbundstein-
  Anpassung (x 2.86) bis zur Grenze (x 4.45) - vorher 0.83 m breit mit
  Rasenstreifen daneben. Der Weg an der Suedgrenze reicht von der Grenze
  bis an die Nachbarmauer (z 4.49 bis 5.97).
- Winkelelemente Ost auf die Grenzlinie x 4.45; die Linie bei z 4.96 im
  Sueden war keine eigene Stuetzwand, das ist die Nachbarmauer selbst.

Hoehen und Gefaelle
- LEVELS koennen jetzt auch eine geneigte Ebene vorgeben. Die Wege sind
  Rampen: Ostweg rund 12%, Suedweg rund 3%, Feuerwehrzufahrt 13.6% aus
  den Plankoten -2.08 und -1.08. Der Architekturplan nennt an denselben
  Stellen "Steigung 9.9%" und "Steigung 13.0%".
- Ausserhalb der Zonen wird die Interpolation der naechsten Zone
  fortgesetzt statt ihres konstanten Ersatzwerts - die Feuerwehrzufahrt
  stand vorher als schwebende Platte ueber einer Gelaendekante.
- Gelaende oestlich der Grenze korrigiert: dort lag ein Huegel ueber dem
  Weg, obwohl der Plan -0.72 und -1.57 angibt.

Obere Ebene
- Der Rasen ist eben auf -0.02. Die Koten 0.09 bis 0.26 liegen schon im
  angehobenen Kiesbett des Sichtschutzes, nicht mehr im Rasen; ohne feste
  Vorgabe zog die Interpolation den Rasen huegelig hoch.

Stufen
- Beim gedeckten Sitzplatz stimmen jetzt beide schwebenden Platten: der
  Plan zeichnet zwei versetzte Rechtecke mit den Koten -0.02 und -0.17,
  bisher lagen sie auf -0.17 und -0.31 - die untere verschwand im Belag.
- Das Gartentor steht auf dem oberen Niveau (-0.13), von dort zwei Stufen
  hinunter auf den Hauptsitzplatz.
- Westtreppe ueber den ganzen Treppenblock (5 Stufen statt 4), die
  Gelaenderpfosten reichen bis ins Gelaende statt in der Luft zu enden.

Rundgang
- Treppen und schwebende Stufen sind begehbar: ihre Trittflaechen gehen in
  die Hoehenabfrage ein, die Stufen sind kein Hindernis mehr.
- Springen mit der Leertaste, rund 55 cm.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-10 19:49:46 +02:00
co-authored by Claude Opus 5
parent ce40d6275b
commit fad23a34c3
10 changed files with 215 additions and 51 deletions
+33 -3
View File
@@ -13,7 +13,7 @@ import './style.css';
import { loadSite, makeHeightSampler, type SiteData } from './site';
import { buildTerrain } from './scene/terrain';
import { buildSurfaces } from './scene/surfaces';
import { buildStelen, buildProps, buildLamps, buildLinear } from './scene/structures';
import { buildStelen, buildProps, buildLamps, buildLinear, treppeTritte } from './scene/structures';
import { buildWalls } from './scene/walls';
import { buildVegetation } from './scene/vegetation';
import { buildBuilding, buildNeighbourBuildings } from './scene/building';
@@ -80,6 +80,35 @@ async function main() {
});
scene.add(env.group);
// -- Begehbare Bauteile --------------------------------------------------
// Stufen und Treppen stecken nicht im Hoehenraster, sondern sind eigene
// Koerper. Damit man sie wirklich begehen kann, wird ihre Trittflaeche in
// die Hoehenabfrage des Rundgangs eingerechnet - sonst blieben sie blosse
// Hindernisse, um die man herumlaufen muss.
interface Tritt { cx: number; cz: number; hw: number; hd: number; rot: number; top: number }
const tritte: Tritt[] = [];
for (const p of site.props) {
if (p.type !== 'stufe' || p.top === undefined) continue;
tritte.push({
cx: p.x, cz: p.z, hw: p.w / 2, hd: p.d / 2,
rot: (p.rot * Math.PI) / 180, top: p.top,
});
}
for (const f of site.linear) {
if (f.kind === 'treppe') tritte.push(...treppeTritte(f));
}
const onTritt = (t: Tritt, x: number, z: number) => {
const dx = x - t.cx, dz = z - t.cz;
const c = Math.cos(-t.rot), s = Math.sin(-t.rot);
return Math.abs(dx * c - dz * s) <= t.hw && Math.abs(dx * s + dz * c) <= t.hd;
};
/** Hoehe unter den Fuessen: Gelaende oder die hoechste Trittflaeche darauf. */
const walkHeight = (x: number, z: number) => {
let y = height(x, z);
for (const t of tritte) if (onTritt(t, x, z) && t.top > y) y = t.top;
return y;
};
// -- Hindernisse fuer den Rundgang --------------------------------------
const obstacles: Obstacle[] = [];
const b = site.building;
@@ -113,7 +142,8 @@ async function main() {
}
}
for (const p of site.props) {
if (p.type === 'schacht' || p.type === 'wasserhahn') continue;
// Stufen sind begehbar, kein Hindernis - sie stehen in `tritte`.
if (p.type === 'schacht' || p.type === 'wasserhahn' || p.type === 'stufe') continue;
obstacles.push({ cx: p.x, cz: p.z, hw: p.w / 2, hd: p.d / 2, rot: (p.rot * Math.PI) / 180 });
}
for (const pl of site.plants) {
@@ -137,7 +167,7 @@ async function main() {
obstacles.push({ cx: p.x, cz: p.z, hw: 0.26, hd: 0.26, rot: 0 });
}
const walker = new Walker(camera, { height, obstacles, bounds: BOUNDS });
const walker = new Walker(camera, { height: walkHeight, obstacles, bounds: BOUNDS });
walker.attach(canvas);
const start = site.startViews[0];
walker.teleport(start.x, start.z, start.yaw);