Remove viewer debug line/state colours; app widget parity (chunking, near/far, occt-wasm)
This commit is contained in:
@@ -95,9 +95,8 @@ set the other labels, and set `publish=true` **last**.
|
|||||||
- **3D models** (`scripts/3d_model_viewer.js`): renders `.step`/`.stp`/`.stl` as file notes
|
- **3D models** (`scripts/3d_model_viewer.js`): renders `.step`/`.stp`/`.stl` as file notes
|
||||||
(title ends in the extension), inline attachment links, or links to published model file
|
(title ends in the extension), inline attachment links, or links to published model file
|
||||||
notes from text notes (resolved via `window.blogData`). The viewer is **full-bleed**
|
notes from text notes (resolved via `window.blogData`). The viewer is **full-bleed**
|
||||||
(`~100vw`, `height: min(70vh, 900px)`, ResizeObserver), with a loading progress bar, a
|
(`~100vw`, `height: min(70vh, 900px)`, ResizeObserver), with a loading progress bar and a
|
||||||
caption that shows `name · size · triangle count`, and a **debug line** under the box that
|
caption that shows `name · size · triangle count`. STEP is parsed
|
||||||
logs the step (`loading`/`parsing`/`done`/`error`) for on-device diagnosis. STEP is parsed
|
|
||||||
by **occt-wasm** (OpenCASCADE **V8**, MIT/Apache-2.0) in a **module worker**
|
by **occt-wasm** (OpenCASCADE **V8**, MIT/Apache-2.0) in a **module worker**
|
||||||
(`new Worker(url, {type:"module"})`, non-blocking) with
|
(`new Worker(url, {type:"module"})`, non-blocking) with
|
||||||
`linearDeflection: 0.4, angularDeflection: 0.2`. Libraries hosted as local notes via
|
`linearDeflection: 0.4, angularDeflection: 0.2`. Libraries hosted as local notes via
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ no external dependencies (except `highlight.js`, vendored in `lib/`).
|
|||||||
- **3D models**: `.step` / `.stp` / `.stl` files (as file notes, as inline attachments, or linked
|
- **3D models**: `.step` / `.stp` / `.stl` files (as file notes, as inline attachments, or linked
|
||||||
from text notes) render in an interactive three.js viewer (STEP via **occt-wasm**, OpenCASCADE
|
from text notes) render in an interactive three.js viewer (STEP via **occt-wasm**, OpenCASCADE
|
||||||
V8, parsed in a non-blocking **module worker**). The viewer is **full-bleed** (~`100vw`) with a
|
V8, parsed in a non-blocking **module worker**). The viewer is **full-bleed** (~`100vw`) with a
|
||||||
viewport-based height, drag to rotate / scroll to zoom, rounded 8px box, a loading progress bar,
|
viewport-based height, drag to rotate / scroll to zoom, rounded 8px box, a loading progress bar
|
||||||
a caption showing `name · size · triangle count`, and a small debug line. Large meshes are
|
and a caption showing `name · size · triangle count`. Large meshes are
|
||||||
split into `Uint16` chunks so mobile GPUs render them too (≈480k triangles for the demo
|
split into `Uint16` chunks so mobile GPUs render them too (≈480k triangles for the demo
|
||||||
battery module). See [docs/embed-3d-model.md](docs/embed-3d-model.md).
|
battery module). See [docs/embed-3d-model.md](docs/embed-3d-model.md).
|
||||||
- **3D viewer inside Trilium (app widget)**: the same viewer runs in the Trilium app itself
|
- **3D viewer inside Trilium (app widget)**: the same viewer runs in the Trilium app itself
|
||||||
|
|||||||
@@ -59,8 +59,7 @@ exists as its own (published) file note — the model stays in one place.
|
|||||||
- **Mobile compatibility**: the mesh is split into chunks of ≤65000 vertices
|
- **Mobile compatibility**: the mesh is split into chunks of ≤65000 vertices
|
||||||
(`chunkGeometry`, `Uint16` indices) so it renders on GPUs without
|
(`chunkGeometry`, `Uint16` indices) so it renders on GPUs without
|
||||||
`OES_element_index_uint`; the camera near/far is tightened after `fit()` for 16-bit
|
`OES_element_index_uint`; the camera near/far is tightened after `fit()` for 16-bit
|
||||||
depth buffers. The caption always shows a small **debug line** with the current step
|
depth buffers.
|
||||||
(`loading` / `parsing` / `done` / `error`) – useful while diagnosing.
|
|
||||||
- For **inline embedding from a file note (Option C)** the `blog_data` note must be
|
- For **inline embedding from a file note (Option C)** the `blog_data` note must be
|
||||||
present and the target model must be a published article (the viewer resolves
|
present and the target model must be a published article (the viewer resolves
|
||||||
`./<alias>` links against `window.blogData`).
|
`./<alias>` links against `window.blogData`).
|
||||||
|
|||||||
@@ -132,9 +132,6 @@
|
|||||||
cap.textContent = name;
|
cap.textContent = name;
|
||||||
box.appendChild(cap);
|
box.appendChild(cap);
|
||||||
}
|
}
|
||||||
var dbg = document.createElement("div");
|
|
||||||
dbg.className = "model-viewer-debug";
|
|
||||||
box.appendChild(dbg);
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,11 +175,6 @@
|
|||||||
var s = el.querySelector(".model-viewer-status");
|
var s = el.querySelector(".model-viewer-status");
|
||||||
if (s) s.textContent = text;
|
if (s) s.textContent = text;
|
||||||
}
|
}
|
||||||
function setStep(state, msg) {
|
|
||||||
el.className = "model-viewer model-" + state;
|
|
||||||
var dbg = el.querySelector(".model-viewer-debug");
|
|
||||||
if (dbg) dbg.textContent = new Date().toLocaleTimeString() + " [" + state + "] " + msg;
|
|
||||||
}
|
|
||||||
function setProgress(percent) {
|
function setProgress(percent) {
|
||||||
var bar = el.querySelector(".model-viewer-progress-fill");
|
var bar = el.querySelector(".model-viewer-progress-fill");
|
||||||
if (!bar) return;
|
if (!bar) return;
|
||||||
@@ -198,7 +190,6 @@
|
|||||||
var s = el.querySelector(".model-viewer-status");
|
var s = el.querySelector(".model-viewer-status");
|
||||||
if (s) { s.textContent = msg || "Could not load 3D model."; s.classList.add("error"); }
|
if (s) { s.textContent = msg || "Could not load 3D model."; s.classList.add("error"); }
|
||||||
setProgress(0);
|
setProgress(0);
|
||||||
setStep("error", msg || "Could not load 3D model.");
|
|
||||||
}
|
}
|
||||||
function showData(extra) {
|
function showData(extra) {
|
||||||
var d = el.querySelector(".model-viewer-data");
|
var d = el.querySelector(".model-viewer-data");
|
||||||
@@ -232,7 +223,6 @@
|
|||||||
|
|
||||||
setProgress(null);
|
setProgress(null);
|
||||||
setStatus("Loading 3D libraries\u2026");
|
setStatus("Loading 3D libraries\u2026");
|
||||||
setStep("loading", "Loading 3D libraries");
|
|
||||||
|
|
||||||
loadThree(function () {
|
loadThree(function () {
|
||||||
var wrap = el.querySelector(".model-viewer-canvas") || el;
|
var wrap = el.querySelector(".model-viewer-canvas") || el;
|
||||||
@@ -293,7 +283,6 @@
|
|||||||
fetchProgress(url, function (p) { setProgress(p); }).then(function (buf) {
|
fetchProgress(url, function (p) { setProgress(p); }).then(function (buf) {
|
||||||
fileSize = buf.byteLength;
|
fileSize = buf.byteLength;
|
||||||
showData();
|
showData();
|
||||||
setStep("loading", "Downloaded model " + formatBytes(fileSize));
|
|
||||||
var data = new Uint8Array(buf);
|
var data = new Uint8Array(buf);
|
||||||
if (isStep) {
|
if (isStep) {
|
||||||
setStatus("Downloading STEP parser\u2026");
|
setStatus("Downloading STEP parser\u2026");
|
||||||
@@ -301,12 +290,10 @@
|
|||||||
fetchProgress(OCCT_WASM_ABS, function () {}).then(function (wasmBuf) {
|
fetchProgress(OCCT_WASM_ABS, function () {}).then(function (wasmBuf) {
|
||||||
setStatus("Parsing STEP\u2026");
|
setStatus("Parsing STEP\u2026");
|
||||||
setProgress(null);
|
setProgress(null);
|
||||||
setStep("parsing", "STEP parser ready, parsing");
|
|
||||||
var t0 = Date.now();
|
var t0 = Date.now();
|
||||||
var parseTimer = setInterval(function () {
|
var parseTimer = setInterval(function () {
|
||||||
var el2 = Date.now() - t0;
|
var el2 = Date.now() - t0;
|
||||||
setStatus("Parsing STEP\u2026 (" + Math.round(el2 / 1000) + "s)");
|
setStatus("Parsing STEP\u2026 (" + Math.round(el2 / 1000) + "s)");
|
||||||
setStep("parsing", "Parsing STEP " + Math.round(el2 / 1000) + "s");
|
|
||||||
if (el2 > 240000 && !settled) { worker.terminate(); URL.revokeObjectURL(wurl); clearInterval(parseTimer); onError("STEP parse timed out."); }
|
if (el2 > 240000 && !settled) { worker.terminate(); URL.revokeObjectURL(wurl); clearInterval(parseTimer); onError("STEP parse timed out."); }
|
||||||
}, 1000);
|
}, 1000);
|
||||||
var blob = new Blob([WORKER_SRC], { type: "application/javascript" });
|
var blob = new Blob([WORKER_SRC], { type: "application/javascript" });
|
||||||
@@ -320,7 +307,6 @@
|
|||||||
var geo = new THREE.BufferGeometry();
|
var geo = new THREE.BufferGeometry();
|
||||||
geo.setAttribute("position", new THREE.Float32BufferAttribute(e.data.positions, 3));
|
geo.setAttribute("position", new THREE.Float32BufferAttribute(e.data.positions, 3));
|
||||||
if (e.data.indices) geo.setIndex(new THREE.BufferAttribute(e.data.indices, 1));
|
if (e.data.indices) geo.setIndex(new THREE.BufferAttribute(e.data.indices, 1));
|
||||||
var geoStats = "posV=" + geo.attributes.position.count + " idx=" + (geo.index ? geo.index.count : 0);
|
|
||||||
fixWinding(geo);
|
fixWinding(geo);
|
||||||
var mat = new THREE.MeshStandardMaterial({ color: 0xb8bb26, metalness: 0.2, roughness: 0.6, side: THREE.DoubleSide, flatShading: false });
|
var mat = new THREE.MeshStandardMaterial({ color: 0xb8bb26, metalness: 0.2, roughness: 0.6, side: THREE.DoubleSide, flatShading: false });
|
||||||
chunkGeometry(geo, group, mat);
|
chunkGeometry(geo, group, mat);
|
||||||
@@ -328,8 +314,6 @@
|
|||||||
fit();
|
fit();
|
||||||
showCanvas();
|
showCanvas();
|
||||||
showData(formatCount(tris) + " triangles");
|
showData(formatCount(tris) + " triangles");
|
||||||
var capGL = renderer.capabilities ? (renderer.capabilities.isWebGL2 ? "WebGL2" : "WebGL1") : "?";
|
|
||||||
setStep("done", "Rendered " + formatCount(tris) + " tris; meshes=" + group.children.length + " gl=" + capGL + " " + geoStats);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
onError("build: " + (err && err.message || err));
|
onError("build: " + (err && err.message || err));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -918,21 +918,6 @@ html.theme-light #content code {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.model-viewer.model-loading { background: #282828; }
|
|
||||||
.model-viewer.model-parsing { background: #504945; }
|
|
||||||
.model-viewer.model-done { background: #1d2021; }
|
|
||||||
.model-viewer.model-error { background: #3c3836; }
|
|
||||||
|
|
||||||
.model-viewer-debug {
|
|
||||||
font-family: "JetBrains Mono", Consolas, monospace;
|
|
||||||
font-size: 0.72em;
|
|
||||||
color: #928374;
|
|
||||||
text-align: center;
|
|
||||||
padding: 4px 12px;
|
|
||||||
background: #1d2021;
|
|
||||||
border-top: 1px solid var(--background-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- Bildunterschriften (Gruvbox) ---------- */
|
/* ---------- Bildunterschriften (Gruvbox) ---------- */
|
||||||
#content figcaption {
|
#content figcaption {
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
|
|||||||
Reference in New Issue
Block a user