Westpodest, Osttreppe, Gartenschrank, Start in der Uebersicht
Deploy App / deploy (push) Successful in 27s
Deploy App / deploy (push) Successful in 27s
- Weg um das Haus: der westliche Arm fehlte. Vor dem Gartentor liegt jetzt ein Podest auf -0.14 (Plan: dreimal -0.14 bis zur Suedwestecke), das an der Ecke in den Weg entlang der Suedgrenze uebergeht. Gegen die tiefer liegende Feuerwehrzufahrt schliesst ein Betonabschluss ab. - Westtreppe gedreht: die Trittlinien liegen im Plan parallel zur Rinne, die Treppe laeuft also laengs der Grenze nach Norden, vom Podest auf die Feuerwehrzufahrt (-0.14 auf -1.08). Die Zufahrt ist dort ausgespart. - Osttreppe war unter Rasen verschwunden. Unter Treppen wird das Gelaende jetzt unter die unterste Trittkante gelegt; die Treppe reicht vom Gelaender bis an die Winkelelemente. Der Belagstreifen, der sie zugedeckt hatte, ist weg. - Belaege und feste Ebenen legen das Gelaende auch ausserhalb der Zonen fest. Vorher stand am Fuss der Osttreppe ein Grashuegel ueber dem Podest. Podest und Stellplatte liegen gemeinsam auf -1.57. - Gartenschrank um 90 Grad gedreht: Rueckwand zum Beerenbeet, Doppeltueren zum Hauszugang. Dunkler gebeizt, damit er nicht mit der Fassade verschmilzt. - Schwebender Travertinblock an der Nordwestecke entfernt. - Die App oeffnet im Uebersichtsmodus. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -234,6 +234,8 @@ async function main() {
|
|||||||
onJoystick: (x, y, active) => walker.setJoystick(x, y, active),
|
onJoystick: (x, y, active) => walker.setJoystick(x, y, active),
|
||||||
});
|
});
|
||||||
walker.onPointerLockChange = (locked) => hud.setPointerLocked(locked);
|
walker.onPointerLockChange = (locked) => hud.setPointerLocked(locked);
|
||||||
|
// Die App oeffnet in der Uebersicht; der Rundgang ist einen Klick entfernt.
|
||||||
|
hud.setMode('overview');
|
||||||
|
|
||||||
// -- Renderschleife ------------------------------------------------------
|
// -- Renderschleife ------------------------------------------------------
|
||||||
function resize() {
|
function resize() {
|
||||||
|
|||||||
@@ -88,7 +88,8 @@ function schwebendeStufe(p: Prop, y: number): Group {
|
|||||||
*/
|
*/
|
||||||
function gartenhaus(p: Prop, y: number): Group {
|
function gartenhaus(p: Prop, y: number): Group {
|
||||||
const g = new Group();
|
const g = new Group();
|
||||||
const holz = material(tex.fassadeHolz(), { roughness: 0.8 });
|
// Dunkler gebeizt als die Fassade, damit der Schrank nicht mit dem Haus verschmilzt.
|
||||||
|
const holz = material(tex.fassadeHolz(), { color: 0x857868, roughness: 0.8 });
|
||||||
const dunkel = new MeshStandardMaterial({ color: 0x3b3934, roughness: 0.62 });
|
const dunkel = new MeshStandardMaterial({ color: 0x3b3934, roughness: 0.62 });
|
||||||
const metall = new MeshStandardMaterial({ color: 0x55565a, roughness: 0.45, metalness: 0.6 });
|
const metall = new MeshStandardMaterial({ color: 0x55565a, roughness: 0.45, metalness: 0.6 });
|
||||||
const a = (p.rot * Math.PI) / 180;
|
const a = (p.rot * Math.PI) / 180;
|
||||||
|
|||||||
+38
-21
@@ -84,6 +84,15 @@ export const TREES = [
|
|||||||
* bleibt die Ausgleichsebene aus den Koten stehen.
|
* bleibt die Ausgleichsebene aus den Koten stehen.
|
||||||
*/
|
*/
|
||||||
export const LEVELS = [
|
export const LEVELS = [
|
||||||
|
{
|
||||||
|
// Vor dem Gartentor liegt ein Podest auf -0.14 (Plan: dreimal -0.14 bis
|
||||||
|
// zur Suedwestecke). Es ist der westliche Arm des Wegs um das Haus und
|
||||||
|
// geht an der Ecke in den Weg entlang der Suedgrenze ueber. Erst von hier
|
||||||
|
// fuehrt die Treppe hinunter auf die Feuerwehrzufahrt.
|
||||||
|
id: 'weg-west', level: -0.14, types: ['tegula'],
|
||||||
|
note: 'Podest vor dem Gartentor',
|
||||||
|
polygon: [[-23.40, 2.15], [-21.70, 2.15], [-21.70, 6.05], [-23.40, 6.05]],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// Die Feuerwehrzufahrt ist eine Rampe: der Plan gibt -2.08 bei z -7.21
|
// Die Feuerwehrzufahrt ist eine Rampe: der Plan gibt -2.08 bei z -7.21
|
||||||
// und -1.08 bei z 0.12 an, also rund 13.6 % Steigung. Ohne feste Vorgabe
|
// und -1.08 bei z 0.12 an, also rund 13.6 % Steigung. Ohne feste Vorgabe
|
||||||
@@ -101,19 +110,19 @@ export const LEVELS = [
|
|||||||
polygon: [[2.05, -4.30], [4.55, -4.30], [4.55, 5.05], [2.05, 5.05]],
|
polygon: [[2.05, -4.30], [4.55, -4.30], [4.55, 5.05], [2.05, 5.05]],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'weg-ost-gelaender', level: -0.45, types: ['tegula'],
|
id: 'stellplatte-nordost', level: -1.57, types: ['tegula'],
|
||||||
note: 'Belagstreifen neben dem Gelaender der Osttreppe',
|
note: 'Stellplatte des Nachbarn auf der Hoehe des Treppenfusses',
|
||||||
polygon: [[2.05, -6.60], [2.92, -6.60], [2.92, -4.15], [2.05, -4.15]],
|
polygon: [[0.30, -11.30], [4.70, -11.30], [4.70, -7.25], [0.30, -7.25]],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'weg-ost-unten', level: -1.57, types: ['tegula'],
|
id: 'weg-ost-unten', level: -1.57, types: ['tegula'],
|
||||||
note: 'Podest am Fuss der Osttreppe',
|
note: 'Podest am Fuss der Osttreppe',
|
||||||
polygon: [[2.80, -7.70], [4.55, -7.70], [4.55, -6.45], [2.80, -6.45]],
|
polygon: [[2.10, -7.40], [4.55, -7.40], [4.55, -6.45], [2.10, -6.45]],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Der Weg an der Suedgrenze folgt dem Anstieg der Grenzkoten von -0.04
|
// Der Weg an der Suedgrenze folgt dem Anstieg der Grenzkoten von -0.04
|
||||||
// im Westen auf 0.63 im Osten.
|
// im Westen auf 0.63 im Osten.
|
||||||
id: 'weg-sued', plane: [0.0305, 0, 0.5634], types: ['tegula'],
|
id: 'weg-sued', plane: [0.0305, 0, 0.5231], types: ['tegula'],
|
||||||
note: 'Weg an der Suedgrenze als Rampe',
|
note: 'Weg an der Suedgrenze als Rampe',
|
||||||
polygon: [[-21.90, 4.45], [4.55, 4.45], [4.55, 6.05], [-21.90, 6.05]],
|
polygon: [[-21.90, 4.45], [4.55, 4.45], [4.55, 6.05], [-21.90, 6.05]],
|
||||||
},
|
},
|
||||||
@@ -210,9 +219,11 @@ export const WALLS = [
|
|||||||
path: [[-8.74, 4.18], [-7.24, 4.18]], t: 0.46, top: 2.28, base: 0.18,
|
path: [[-8.74, 4.18], [-7.24, 4.18]], t: 0.46, top: 2.28, base: 0.18,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'stufe-nordwest', type: 'travertin',
|
// Das Podest liegt bis 0.65 m ueber der Feuerwehrzufahrt. Ohne Abschluss
|
||||||
note: 'Stufe an der Nordwestecke, vom Sitzplatz auf die Schotterwiese',
|
// stuende dort eine Grasboeschung von einer Rasterzelle Breite.
|
||||||
path: [[-20.90, -7.29], [-20.10, -7.29]], t: 0.42, top: -0.33, base: -0.95,
|
id: 'abschluss-podest-west', type: 'beton',
|
||||||
|
note: 'Betonabschluss des Podests gegen die Feuerwehrzufahrt',
|
||||||
|
path: [[-23.42, 2.20], [-23.42, 6.00]], t: 0.16, top: -0.10, base: -1.00,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lamellenwand', type: 'lamellen',
|
id: 'lamellenwand', type: 'lamellen',
|
||||||
@@ -225,8 +236,8 @@ export const WALLS = [
|
|||||||
export const PROPS = [
|
export const PROPS = [
|
||||||
// Der Plan reserviert 1.8 x 1.8 m fuer das Gartenhaus. Gebaut wird dort ein
|
// Der Plan reserviert 1.8 x 1.8 m fuer das Gartenhaus. Gebaut wird dort ein
|
||||||
// schmaler Gartenschrank: 1.80 m breit, nur 0.50 m tief, rund 2.00 m hoch,
|
// schmaler Gartenschrank: 1.80 m breit, nur 0.50 m tief, rund 2.00 m hoch,
|
||||||
// mit dem Ruecken in der Ecke und den Tueren zum Garten.
|
// mit dem Ruecken zum Beerenbeet und den Tueren zum Hauszugang hin.
|
||||||
{ id: 'gartenschrank', type: 'gartenhaus', x: 1.87, z: -3.58, w: 0.50, d: 1.80, h: 2.00, rot: 0,
|
{ id: 'gartenschrank', type: 'gartenhaus', x: 1.215, z: -4.23, w: 0.50, d: 1.80, h: 2.00, rot: -90,
|
||||||
note: 'Gartenschrank 1.80 x 0.50 m, 2.00 m hoch' },
|
note: 'Gartenschrank 1.80 x 0.50 m, 2.00 m hoch' },
|
||||||
// Der Plan zeichnet zwei Rechtecke: das Podest 1.81 x 2.70 m (x -0.95 bis
|
// 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) und darauf die Huette 1.01 x 2.70 m an der Ostseite (x -0.15 bis
|
||||||
@@ -275,7 +286,12 @@ export const EXTRA_SURFACES = [
|
|||||||
{
|
{
|
||||||
type: 'tegula',
|
type: 'tegula',
|
||||||
note: 'Feuerwehrzufahrt und Zugangsweg westlich der Grenze, Tegula-Pflastersteine grau',
|
note: 'Feuerwehrzufahrt und Zugangsweg westlich der Grenze, Tegula-Pflastersteine grau',
|
||||||
polygon: [[-25.60, -13.50], [-22.10, -13.50], [-22.10, 6.40], [-25.60, 6.40]],
|
polygon: [[-25.60, -13.50], [-22.10, -13.50], [-22.10, 0.35], [-23.40, 0.35], [-23.40, 6.40], [-25.60, 6.40]],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'tegula',
|
||||||
|
note: 'Podest vor dem Gartentor, westlicher Arm des Wegs um das Haus',
|
||||||
|
polygon: [[-23.34, 2.20], [-21.74, 2.20], [-21.74, 5.97], [-23.34, 5.97]],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Der Plan zeigt oestlich der Grenze einen gepflasterten Weg, erst dahinter
|
// Der Plan zeigt oestlich der Grenze einen gepflasterten Weg, erst dahinter
|
||||||
@@ -284,15 +300,10 @@ export const EXTRA_SURFACES = [
|
|||||||
note: 'Weg an der Ostseite, Rampe oberhalb der Treppe (Steigung rund 12%)',
|
note: 'Weg an der Ostseite, Rampe oberhalb der Treppe (Steigung rund 12%)',
|
||||||
polygon: [[2.12, -4.18], [4.45, -4.18], [4.45, 4.96], [2.12, 4.96]],
|
polygon: [[2.12, -4.18], [4.45, -4.18], [4.45, 4.96], [2.12, 4.96]],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'tegula',
|
|
||||||
note: 'Belagstreifen neben dem Gelaender, bis an den Kopf der Osttreppe',
|
|
||||||
polygon: [[2.12, -6.55], [2.86, -6.55], [2.86, -4.18], [2.12, -4.18]],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'tegula',
|
type: 'tegula',
|
||||||
note: 'Weg an der Ostseite, Podest unterhalb der Treppe auf -1.57',
|
note: 'Weg an der Ostseite, Podest unterhalb der Treppe auf -1.57',
|
||||||
polygon: [[2.86, -7.60], [4.45, -7.60], [4.45, -6.52], [2.86, -6.52]],
|
polygon: [[2.17, -7.35], [4.45, -7.35], [4.45, -6.52], [2.17, -6.52]],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Schmaler gepflasterter Streifen jenseits der Suedgrenze, zwischen
|
// Schmaler gepflasterter Streifen jenseits der Suedgrenze, zwischen
|
||||||
@@ -329,7 +340,7 @@ export const LINEAR = [
|
|||||||
// Breite x 2.17 bis 3.78; die Koten daneben lauten -0.37 und -1.57.
|
// Breite x 2.17 bis 3.78; die Koten daneben lauten -0.37 und -1.57.
|
||||||
id: 'treppe-ost', kind: 'treppe',
|
id: 'treppe-ost', kind: 'treppe',
|
||||||
note: 'Treppe und Rampe hinunter zum Stellplatz des Nachbarn (-0.37 auf -1.57)',
|
note: 'Treppe und Rampe hinunter zum Stellplatz des Nachbarn (-0.37 auf -1.57)',
|
||||||
path: [[2.975, -4.18], [2.975, -6.52]], width: 1.61, fromY: -0.37, toY: -1.57, steps: 7,
|
path: [[3.31, -4.18], [3.31, -6.52]], width: 2.28, fromY: -0.37, toY: -1.57, steps: 7,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'gelaender-ost', kind: 'gelaender',
|
id: 'gelaender-ost', kind: 'gelaender',
|
||||||
@@ -340,13 +351,15 @@ export const LINEAR = [
|
|||||||
// Trittlinien bei x -21.94 bis -22.54 im Abstand von 20 cm, Block bis
|
// Trittlinien bei x -21.94 bis -22.54 im Abstand von 20 cm, Block bis
|
||||||
// x -23.34; Koten -0.28 oben und -1.08 auf der Feuerwehrzufahrt.
|
// x -23.34; Koten -0.28 oben und -1.08 auf der Feuerwehrzufahrt.
|
||||||
id: 'treppe-west', kind: 'treppe',
|
id: 'treppe-west', kind: 'treppe',
|
||||||
note: 'Treppe und Rampe von der Feuerwehrzufahrt zum Gartentor (-0.28 auf -1.08)',
|
// Die Trittlinien liegen im Plan parallel zur Rinne, die Treppe laeuft
|
||||||
path: [[-21.80, 1.37], [-23.34, 1.37]], width: 1.70, fromY: -0.28, toY: -1.08, steps: 5,
|
// also laengs der Grenze nach Norden - nicht quer von ihr weg.
|
||||||
|
note: 'Treppe und Rampe vom Podest vor dem Gartentor hinunter zur Feuerwehrzufahrt (-0.14 auf -1.08)',
|
||||||
|
path: [[-22.54, 2.20], [-22.54, 0.35]], width: 1.60, fromY: -0.14, toY: -1.08, steps: 6,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'gelaender-west', kind: 'gelaender',
|
id: 'gelaender-west', kind: 'gelaender',
|
||||||
note: 'Gelaender an der Treppe zur Feuerwehrzufahrt',
|
note: 'Gelaender an der Treppe zur Feuerwehrzufahrt',
|
||||||
path: [[-21.80, 0.52], [-23.34, 0.52]], fromY: -0.28, toY: -1.08, height: 0.95,
|
path: [[-23.38, 2.20], [-23.38, 0.35]], fromY: -0.14, toY: -1.08, height: 0.95,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'rinne-gartentor', kind: 'rinne',
|
id: 'rinne-gartentor', kind: 'rinne',
|
||||||
@@ -525,6 +538,10 @@ export const EXTRA_SPOTS = [
|
|||||||
{ x: 7.5, z: 0.0, y: 0.20, zone: 'ost' },
|
{ x: 7.5, z: 0.0, y: 0.20, zone: 'ost' },
|
||||||
{ x: 7.5, z: 5.0, y: 0.75, zone: 'ost' },
|
{ x: 7.5, z: 5.0, y: 0.75, zone: 'ost' },
|
||||||
{ x: 5.0, z: -6.4, y: -1.35, zone: 'ost' },
|
{ x: 5.0, z: -6.4, y: -1.35, zone: 'ost' },
|
||||||
|
// Fuss der Osttreppe: hier liegt das Gelaende auf Hoehe des Podests, sonst
|
||||||
|
// steht neben dem Treppenfuss ein Grashuegel.
|
||||||
|
{ x: 4.70, z: -6.55, y: -1.52, zone: 'ost' },
|
||||||
|
{ x: 4.70, z: -5.40, y: -0.95, zone: 'ost' },
|
||||||
{ x: 3.0, z: -8.5, y: -1.55, zone: 'zollet' },
|
{ x: 3.0, z: -8.5, y: -1.55, zone: 'zollet' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
+41
-14
@@ -389,25 +389,52 @@ for (let j = 0; j < nz; j++) {
|
|||||||
y = interpolate(x, z, best.id);
|
y = interpolate(x, z, best.id);
|
||||||
} else {
|
} else {
|
||||||
y = interpolate(x, z, zone);
|
y = interpolate(x, z, zone);
|
||||||
// Ausdruecklich flach vorgegebene Ebenen: der Rasen der oberen Ebene
|
}
|
||||||
// ist eben, ohne Vorgabe zieht ihn die Interpolation huegelig hoch.
|
// Feste Ebenen und Belaege gelten auch ausserhalb der Zonen. Vorher
|
||||||
for (const lv of LEVELS) {
|
// griffen sie nur innerhalb - das Podest am Fuss der Osttreppe liegt
|
||||||
if (!lv.flatten || !pointInPolygon(x, z, lv.polygon)) continue;
|
// aber zwischen den Zonen, und dort stand ein Grashuegel darueber.
|
||||||
y = lv.level;
|
for (const lv of LEVELS) {
|
||||||
locked[j * nx + i] = 1;
|
if (!lv.flatten || !pointInPolygon(x, z, lv.polygon)) continue;
|
||||||
break;
|
y = lv.level;
|
||||||
}
|
locked[j * nx + i] = 1;
|
||||||
for (const f of flatSurfaces) {
|
break;
|
||||||
if (!pointInPolygon(x, z, f.polygon)) continue;
|
}
|
||||||
y = Math.max(f.min, Math.min(f.max, f.plane.a * x + f.plane.b * z + f.plane.c));
|
for (const f of flatSurfaces) {
|
||||||
locked[j * nx + i] = 1;
|
if (!pointInPolygon(x, z, f.polygon)) continue;
|
||||||
break;
|
y = Math.max(f.min, Math.min(f.max, f.plane.a * x + f.plane.b * z + f.plane.c));
|
||||||
}
|
locked[j * nx + i] = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
height[j * nx + i] = y;
|
height[j * nx + i] = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unter den Treppen muss das Gelaende unter der untersten Trittkante liegen.
|
||||||
|
// Sonst waechst die Boeschung durch die Blockstufen hindurch und die Treppe
|
||||||
|
// verschwindet unter Rasen - genau das war an der Osttreppe passiert.
|
||||||
|
for (const f of LINEAR) {
|
||||||
|
if (f.kind !== 'treppe') continue;
|
||||||
|
const [ax, az] = f.path[0], [bx, bz] = f.path[f.path.length - 1];
|
||||||
|
const len = Math.hypot(bx - ax, bz - az) || 1;
|
||||||
|
const ux = (bx - ax) / len, uz = (bz - az) / len;
|
||||||
|
const riser = (f.fromY - f.toY) / f.steps;
|
||||||
|
const half = f.width / 2 + 0.08;
|
||||||
|
for (let j = 0; j < nz; j++) {
|
||||||
|
const z = GRID.z0 + j * CELL;
|
||||||
|
for (let i = 0; i < nx; i++) {
|
||||||
|
const x = GRID.x0 + i * CELL;
|
||||||
|
const s = (x - ax) * ux + (z - az) * uz;
|
||||||
|
const q = -(x - ax) * uz + (z - az) * ux;
|
||||||
|
if (s < -0.1 || s > len + 0.1 || Math.abs(q) > half) continue;
|
||||||
|
const t = Math.max(0, Math.min(1, s / len));
|
||||||
|
const unter = f.fromY + (f.toY - f.fromY) * t - riser - 0.03;
|
||||||
|
const k = j * nx + i;
|
||||||
|
height[k] = Math.min(height[k], unter);
|
||||||
|
locked[k] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Glaetten - aber nur die freien Felder. Die Belaege bleiben exakt eben.
|
// Glaetten - aber nur die freien Felder. Die Belaege bleiben exakt eben.
|
||||||
let smoothed = Float32Array.from(height);
|
let smoothed = Float32Array.from(height);
|
||||||
for (let pass = 0; pass < 3; pass++) {
|
for (let pass = 0; pass < 3; pass++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user