v0.4.2: iconen gerepareerd, lucht-achtergrond (skybox) met toggle
- bootstrap-icons: @font-face correct ingebed (selector .bi::before was stuk) - core/skybox.js + assets/skybox-data.js (lazy), knop Lucht in alle 3D-weergaven - woning: met lucht aan raster en sandwichpanelen onzichtbaar Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3591fad220
commit
3a4b9608c0
@@ -159,6 +159,12 @@ assets/ logo (preloader) + bestemmingsmap voor toekomstige
|
|||||||
Koppeling, Dak). Labels: zelfstandig naamwoord, geen dubbele punt, uitleg
|
Koppeling, Dak). Labels: zelfstandig naamwoord, geen dubbele punt, uitleg
|
||||||
in een hint (i-icoon) i.p.v. tussen haakjes. Sneltoets T wisselt in drie
|
in een hint (i-icoon) i.p.v. tussen haakjes. Sneltoets T wisselt in drie
|
||||||
stappen: standaard -> 3D groot -> alleen de render -> standaard.
|
stappen: standaard -> 3D groot -> alleen de render -> standaard.
|
||||||
|
- **Lucht (v0.4.2).** Knop "Lucht" in elke 3D-werkbalk (core/skybox.js):
|
||||||
|
panorama uit assets/skybox.webp als achtergrond, keuze onthouden. Voor
|
||||||
|
file:// staat een verkleinde kopie als data-URI in assets/skybox-data.js
|
||||||
|
(pas geladen bij eerste gebruik; opnieuw genereren als skybox.webp
|
||||||
|
verandert). In de woning verdwijnen dan het raster en de sandwichpanelen
|
||||||
|
(die zitten in de grond); de volle render blijft een avondscène.
|
||||||
- **Mijlpaal v0.4 — gevelopbouw.** Samenvatting van de v0.3.11–0.3.19-iteraties:
|
- **Mijlpaal v0.4 — gevelopbouw.** Samenvatting van de v0.3.11–0.3.19-iteraties:
|
||||||
kruislat-latwerk op vochtdoek (richting gevelbekleding globaal), lampen op de
|
kruislat-latwerk op vochtdoek (richting gevelbekleding globaal), lampen op de
|
||||||
afgewerkte gevel (+52 mm), logo-watermerk op het doek, trasraam (cement-
|
afgewerkte gevel (+52 mm), logo-watermerk op het doek, trasraam (cement-
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 7.6 MiB |
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -118,6 +118,7 @@
|
|||||||
<script src="js/core/camera-memory.js"></script>
|
<script src="js/core/camera-memory.js"></script>
|
||||||
<script src="js/core/view-filter.js"></script>
|
<script src="js/core/view-filter.js"></script>
|
||||||
<script src="js/core/ui-kit.js"></script>
|
<script src="js/core/ui-kit.js"></script>
|
||||||
|
<script src="js/core/skybox.js"></script>
|
||||||
<script src="js/vendor/jspdf.umd.min.js"></script>
|
<script src="js/vendor/jspdf.umd.min.js"></script>
|
||||||
<script src="js/core/pdf-sheet.js"></script>
|
<script src="js/core/pdf-sheet.js"></script>
|
||||||
<script src="js/wall/wall-model.js"></script>
|
<script src="js/wall/wall-model.js"></script>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* Alle rechten voorbehouden. Gebruik uitsluitend met schriftelijke toestemming.
|
* Alle rechten voorbehouden. Gebruik uitsluitend met schriftelijke toestemming.
|
||||||
* Zie LICENTIE.md.
|
* Zie LICENTIE.md.
|
||||||
*/
|
*/
|
||||||
const APP_VERSION = '0.4.1';
|
const APP_VERSION = '0.4.2';
|
||||||
// 0.0.X per kleine iteratie, 0.X.0 per mijlpaal, X.0.0 bij live-gang.
|
// 0.0.X per kleine iteratie, 0.X.0 per mijlpaal, X.0.0 bij live-gang.
|
||||||
|
|
||||||
let tabs = [];
|
let tabs = [];
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*!
|
||||||
|
* Tectum
|
||||||
|
* Copyright © 2026 Machiel Heinen.
|
||||||
|
* Alle rechten voorbehouden. Gebruik uitsluitend met schriftelijke toestemming.
|
||||||
|
* Zie LICENTIE.md.
|
||||||
|
*/
|
||||||
|
// ============================================================
|
||||||
|
// core/skybox.js — lucht-achtergrond (equirectangulair panorama) voor de
|
||||||
|
// 3D-weergaven, met een "Lucht"-knop in de 3D-werkbalk. De afbeelding
|
||||||
|
// (assets/skybox-data.js, gegenereerd uit assets/skybox.webp) wordt pas bij
|
||||||
|
// de eerste keer aanzetten geladen en daarna gedeeld. De keuze aan/uit wordt
|
||||||
|
// onthouden (localStorage, alleen gemak).
|
||||||
|
// Plain script (geen ES-module).
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
window.Skybox = (() => {
|
||||||
|
const PREF_KEY = 'tectum.skybox';
|
||||||
|
let texturePromise = null;
|
||||||
|
|
||||||
|
function load() {
|
||||||
|
if (texturePromise) return texturePromise;
|
||||||
|
texturePromise = new Promise((resolve, reject) => {
|
||||||
|
const fromData = () => {
|
||||||
|
const img = new Image();
|
||||||
|
img.onload = () => {
|
||||||
|
const tex = new THREE.Texture(img);
|
||||||
|
tex.mapping = THREE.EquirectangularReflectionMapping;
|
||||||
|
tex.needsUpdate = true;
|
||||||
|
resolve(tex);
|
||||||
|
};
|
||||||
|
img.onerror = reject;
|
||||||
|
img.src = window.TECTUM_SKYBOX;
|
||||||
|
};
|
||||||
|
if (window.TECTUM_SKYBOX) return fromData();
|
||||||
|
const s = document.createElement('script');
|
||||||
|
s.src = 'assets/skybox-data.js';
|
||||||
|
s.onload = fromData;
|
||||||
|
s.onerror = reject;
|
||||||
|
document.head.appendChild(s);
|
||||||
|
});
|
||||||
|
texturePromise.catch(() => { texturePromise = null; });
|
||||||
|
return texturePromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isOn() {
|
||||||
|
try { return localStorage.getItem(PREF_KEY) === '1'; } catch (e) { return false; }
|
||||||
|
}
|
||||||
|
function remember(on) {
|
||||||
|
try { localStorage.setItem(PREF_KEY, on ? '1' : '0'); } catch (e) { /* geen opslag: alleen deze sessie */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zet de achtergrond van `scene`: lucht als on, anders fallbackColor (hex).
|
||||||
|
// wanted() wordt na het laden nog eens gevraagd (knop intussen uitgezet?).
|
||||||
|
function apply(scene, on, fallbackColor, wanted) {
|
||||||
|
if (!on) { scene.background = new THREE.Color(fallbackColor); return; }
|
||||||
|
load().then(tex => { if (!wanted || wanted()) scene.background = tex; })
|
||||||
|
.catch(() => { scene.background = new THREE.Color(fallbackColor); });
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Lucht"-knop in een 3D-werkbalk. onChange(on) bij elke klik (en niet bij
|
||||||
|
// aanmaken: de aanroeper leest de begintoestand met isOn()).
|
||||||
|
function createToggle(toolbar, onChange) {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.type = 'button';
|
||||||
|
btn.className = 'btn-3d-toggle' + (isOn() ? ' active' : '');
|
||||||
|
btn.title = 'Lucht als achtergrond';
|
||||||
|
btn.innerHTML = '<i class="bi bi-cloud-sun"></i>Lucht';
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const on = !btn.classList.contains('active');
|
||||||
|
btn.classList.toggle('active', on);
|
||||||
|
remember(on);
|
||||||
|
onChange(on);
|
||||||
|
});
|
||||||
|
toolbar.appendChild(btn);
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { load, isOn, apply, createToggle };
|
||||||
|
})();
|
||||||
+7
-1
@@ -706,7 +706,8 @@ function mountFloorEditor(container, callbacks) {
|
|||||||
dirLight.castShadow = true;
|
dirLight.castShadow = true;
|
||||||
scene.add(dirLight);
|
scene.add(dirLight);
|
||||||
|
|
||||||
scene.add(new THREE.GridHelper(10, 20, 0x444444, 0x222222));
|
const grid = new THREE.GridHelper(10, 20, 0x444444, 0x222222);
|
||||||
|
scene.add(grid);
|
||||||
|
|
||||||
const floorMaterials = roofMode ? RoofModel.createMaterials() : FloorModel.createMaterials();
|
const floorMaterials = roofMode ? RoofModel.createMaterials() : FloorModel.createMaterials();
|
||||||
|
|
||||||
@@ -726,6 +727,11 @@ function mountFloorEditor(container, callbacks) {
|
|||||||
isolatieVisible = v.isolatie;
|
isolatieVisible = v.isolatie;
|
||||||
update3DScene();
|
update3DScene();
|
||||||
});
|
});
|
||||||
|
// Lucht-achtergrond (core/skybox.js).
|
||||||
|
let skyOn = Skybox.isOn();
|
||||||
|
const applySky = () => { grid.visible = !skyOn; Skybox.apply(scene, skyOn, 0x1a1a1a, () => skyOn); };
|
||||||
|
Skybox.createToggle(document.getElementById('floor-toolbar-3d'), (on) => { skyOn = on; applySky(); });
|
||||||
|
applySky();
|
||||||
|
|
||||||
function update3DScene() {
|
function update3DScene() {
|
||||||
if (floorGroup3D) scene.remove(floorGroup3D);
|
if (floorGroup3D) scene.remove(floorGroup3D);
|
||||||
|
|||||||
+9
-2
@@ -301,6 +301,7 @@ function mountHouseEditor(container, callbacks) {
|
|||||||
let cameraFitted = CameraMemory.restore(overviewCamKey, camera, controls);
|
let cameraFitted = CameraMemory.restore(overviewCamKey, camera, controls);
|
||||||
let beplatingVisible = true, isolatieVisible = true, lampenVisible = true;
|
let beplatingVisible = true, isolatieVisible = true, lampenVisible = true;
|
||||||
let fullRender = false;
|
let fullRender = false;
|
||||||
|
let skyOn = Skybox.isOn();
|
||||||
|
|
||||||
// Weergave-filter (core/view-filter.js). Beplating = wandplaten, vloer-
|
// Weergave-filter (core/view-filter.js). Beplating = wandplaten, vloer-
|
||||||
// en plafondplaten, dakleer en boeideel/daktrim.
|
// en plafondplaten, dakleer en boeideel/daktrim.
|
||||||
@@ -319,12 +320,17 @@ function mountHouseEditor(container, callbacks) {
|
|||||||
|
|
||||||
// Volle render: avondscène, lampen en spots als echte lichtbronnen.
|
// Volle render: avondscène, lampen en spots als echte lichtbronnen.
|
||||||
let lightsGroup = null;
|
let lightsGroup = null;
|
||||||
|
// Lucht (core/skybox.js): alleen in de gewone weergave (de volle render is
|
||||||
|
// een avondscène). De sandwichpanelen zitten in de grond: met lucht aan
|
||||||
|
// zijn ze niet zichtbaar.
|
||||||
function applyRenderMode() {
|
function applyRenderMode() {
|
||||||
scene.background = new THREE.Color(fullRender ? 0x0b0f18 : 0x1a1a1a);
|
if (fullRender) scene.background = new THREE.Color(0x0b0f18);
|
||||||
|
else Skybox.apply(scene, skyOn, 0x1a1a1a, () => skyOn && !fullRender);
|
||||||
|
if (parts && parts.sandwichGroup) parts.sandwichGroup.visible = beplatingVisible && !(skyOn && !fullRender);
|
||||||
ambient.intensity = fullRender ? 0.1 : 0.6;
|
ambient.intensity = fullRender ? 0.1 : 0.6;
|
||||||
dirLight.intensity = fullRender ? 0.12 : 0.8;
|
dirLight.intensity = fullRender ? 0.12 : 0.8;
|
||||||
ground.visible = fullRender;
|
ground.visible = fullRender;
|
||||||
grid.visible = !fullRender;
|
grid.visible = !fullRender && !skyOn;
|
||||||
if (lightsGroup) { scene.remove(lightsGroup); lightsGroup = null; }
|
if (lightsGroup) { scene.remove(lightsGroup); lightsGroup = null; }
|
||||||
// De nep-lichtbundels (kegels) alleen in de snelle weergave; in de
|
// De nep-lichtbundels (kegels) alleen in de snelle weergave; in de
|
||||||
// volle render schijnt er echt licht.
|
// volle render schijnt er echt licht.
|
||||||
@@ -335,6 +341,7 @@ function mountHouseEditor(container, callbacks) {
|
|||||||
scene.add(lightsGroup);
|
scene.add(lightsGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Skybox.createToggle(document.getElementById('ho-toolbar-3d'), (on) => { skyOn = on; applyRenderMode(); });
|
||||||
document.getElementById('ho-btn-render').addEventListener('click', (e) => {
|
document.getElementById('ho-btn-render').addEventListener('click', (e) => {
|
||||||
fullRender = !fullRender;
|
fullRender = !fullRender;
|
||||||
e.currentTarget.classList.toggle('active', fullRender);
|
e.currentTarget.classList.toggle('active', fullRender);
|
||||||
|
|||||||
+7
-1
@@ -1203,7 +1203,8 @@ function mountWallEditor(container, callbacks) {
|
|||||||
dirLight.castShadow = true;
|
dirLight.castShadow = true;
|
||||||
scene.add(dirLight);
|
scene.add(dirLight);
|
||||||
|
|
||||||
scene.add(new THREE.GridHelper(10, 20, 0x444444, 0x222222));
|
const grid = new THREE.GridHelper(10, 20, 0x444444, 0x222222);
|
||||||
|
scene.add(grid);
|
||||||
|
|
||||||
const wallMaterials = WallModel.createMaterials();
|
const wallMaterials = WallModel.createMaterials();
|
||||||
|
|
||||||
@@ -1241,6 +1242,11 @@ function mountWallEditor(container, callbacks) {
|
|||||||
isolatieVisible = v.isolatie;
|
isolatieVisible = v.isolatie;
|
||||||
update3DScene();
|
update3DScene();
|
||||||
});
|
});
|
||||||
|
// Lucht-achtergrond (core/skybox.js).
|
||||||
|
let skyOn = Skybox.isOn();
|
||||||
|
const applySky = () => { grid.visible = !skyOn; Skybox.apply(scene, skyOn, 0x1a1a1a, () => skyOn); };
|
||||||
|
Skybox.createToggle(document.getElementById('wall-toolbar-3d'), (on) => { skyOn = on; applySky(); });
|
||||||
|
applySky();
|
||||||
|
|
||||||
// 3D-opbouw + volume-boekhouding komen uit WallModel.build3D (gedeeld
|
// 3D-opbouw + volume-boekhouding komen uit WallModel.build3D (gedeeld
|
||||||
// met de unit-editor).
|
// met de unit-editor).
|
||||||
|
|||||||
Reference in New Issue
Block a user