v0.4.6: binnenspots per unit, omgeving als keuzemenu (Ontwerp/Dag/Nacht), lampen 15% zachter
- LightingModel.computeIndoor: plafondraster per unit (800-1500 h.o.h., 600 van wand/naad) - 3D, plattegrond, render, totalen en PDF - tegelvloer 20% groter; gras volledig verwijderd Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7ae76fe390
commit
5ecf3e0c2a
+27
-13
@@ -5,7 +5,7 @@
|
||||
* Zie LICENTIE.md.
|
||||
*/
|
||||
// ============================================================
|
||||
// core/skybox.js — omgeving voor de 3D-weergaven ("Lucht": geen/dag/nacht).
|
||||
// core/skybox.js — omgeving voor de 3D-weergaven (Ontwerp / Dag / Nacht).
|
||||
// Een panorama (assets/skybox.webp of skybox-night.webp) wordt op de grond
|
||||
// geprojecteerd, zodat het object op de grond staat; onder het object ligt
|
||||
// een ronde tegelvloer (assets/tiles.jpg) met een witte opstaande rand, groot
|
||||
@@ -28,6 +28,7 @@ window.Skybox = (() => {
|
||||
const RADIUS_M = 60; // straal van de omgevingsbol
|
||||
const TILE_M = 2.4; // één tegeltextuur (1024 px) beslaat zoveel meter
|
||||
const MARGIN_M = 1.5; // vrije rand tussen object en opstaande rand
|
||||
const SIZE_FACTOR = 1.2; // tegelvloer 20% ruimer dan object + marge
|
||||
const RIM_HEIGHT_M = 0.10, RIM_THICK_M = 0.025;
|
||||
const NIGHT_FACTOR = 0.15; // omgevingslicht 's nachts
|
||||
const SUN_OFFSET = { x: 8, y: 14, z: 6 };
|
||||
@@ -130,7 +131,7 @@ window.Skybox = (() => {
|
||||
if (box.isEmpty()) return;
|
||||
const c = box.getCenter(new THREE.Vector3());
|
||||
group.position.set(c.x, groundY, c.z);
|
||||
setTerrace(Math.hypot(box.max.x - box.min.x, box.max.z - box.min.z) / 2 + MARGIN_M);
|
||||
setTerrace((Math.hypot(box.max.x - box.min.x, box.max.z - box.min.z) / 2 + MARGIN_M) * SIZE_FACTOR);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -176,26 +177,39 @@ window.Skybox = (() => {
|
||||
if (o.shadowRoot) o.shadowRoot.traverse(obj => { if (obj.isMesh) obj.castShadow = on; });
|
||||
}
|
||||
|
||||
// Knop in een 3D-werkbalk die door geen -> dag -> nacht wisselt.
|
||||
const LABELS = { none: ['cloud', 'Lucht'], day: ['sun', 'Dag'], night: ['moon-stars', 'Nacht'] };
|
||||
// Keuzemenu in een 3D-werkbalk: Ontwerp (geen omgeving) / Dag / Nacht.
|
||||
const LABELS = { none: ['pencil-square', 'Ontwerp'], day: ['sun', 'Dag'], night: ['moon-stars', 'Nacht'] };
|
||||
function createToggle(toolbar, onChange) {
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.title = 'Omgeving: geen / dag / nacht';
|
||||
let m = getMode();
|
||||
const wrap = document.createElement('div');
|
||||
wrap.className = 'view-filter';
|
||||
wrap.innerHTML = `<button type="button" class="btn-3d-toggle vf-btn" title="Omgeving"></button>
|
||||
<div class="vf-menu">${MODES.map(k => `<div class="vf-item vf-option" data-mode="${k}"><i class="bi bi-${LABELS[k][0]}"></i>${LABELS[k][1]}</div>`).join('')}</div>`;
|
||||
toolbar.appendChild(wrap);
|
||||
const btn = wrap.querySelector('.vf-btn'), menu = wrap.querySelector('.vf-menu');
|
||||
const sync = () => {
|
||||
btn.className = 'btn-3d-toggle' + (m !== 'none' ? ' active' : '');
|
||||
btn.innerHTML = `<i class="bi bi-${LABELS[m][0]}"></i>${LABELS[m][1]}`;
|
||||
btn.innerHTML = `<i class="bi bi-${LABELS[m][0]}"></i>${LABELS[m][1]}<i class="bi bi-chevron-down"></i>`;
|
||||
menu.querySelectorAll('.vf-option').forEach(o => o.classList.toggle('active', o.dataset.mode === m));
|
||||
};
|
||||
btn.addEventListener('click', () => {
|
||||
m = MODES[(MODES.indexOf(m) + 1) % MODES.length];
|
||||
btn.addEventListener('click', (e) => { e.stopPropagation(); menu.classList.toggle('open'); });
|
||||
menu.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const opt = e.target.closest('.vf-option');
|
||||
if (!opt) return;
|
||||
menu.classList.remove('open');
|
||||
if (opt.dataset.mode === m) return;
|
||||
m = opt.dataset.mode;
|
||||
remember(m);
|
||||
sync();
|
||||
onChange(m);
|
||||
});
|
||||
const closeOnOutside = () => {
|
||||
if (!document.body.contains(wrap)) { document.removeEventListener('click', closeOnOutside); return; }
|
||||
menu.classList.remove('open');
|
||||
};
|
||||
document.addEventListener('click', closeOnOutside);
|
||||
sync();
|
||||
toolbar.appendChild(btn);
|
||||
return btn;
|
||||
return wrap;
|
||||
}
|
||||
|
||||
return { CAMERA_HEIGHT_M, NIGHT_FACTOR, createEnvironment, apply, getMode, lightFactor, createToggle };
|
||||
|
||||
Reference in New Issue
Block a user