by adom
0402 SMD Red LED · 2.1 V drop · 25 mA max
← Commit history
Enable shadows for everything in the 3D viewer: every content mesh (LED, board, footprint, carrier tape and reel, nozzle, pocket LEDs, cover) now casts AND receives shadows; the ground receives only; translucent ghosts use transparencyShadow for soft alpha-weighted shadows. Updates both the characterization-page hero viewer (IN-S42ATR-viewer.html) and the README landing embed (README.html srcdoc).
2 files changed
+32−10
IN-S42ATR-viewer.html+16−5@@ -127,14 +127,24 @@ // older, so we do it here — same effect, no change to his code.) refreshRate=1 keeps the // cast shadow updating as the LED animates. const sg = viewer.getShadowGenerator && viewer.getShadowGenerator();- if (sg) {+ // Shadows for EVERYTHING: every content mesh casts AND receives; the ground only receives;+ // skybox / view-cube / axes are environment helpers (neither). Called once after ALL geometry+ // (model + tape/reel + ghosts) is built so nothing is missed. transparencyShadow lets the+ // translucent ghosts (nozzle, cover tape) cast alpha-weighted shadows instead of hard ones.+ const shadowed = new Set();+ const registerShadows = () => {+ if (!sg) return;+ if (sg.setTransparencyShadow) sg.setTransparencyShadow(true); else sg.transparencyShadow = true; scene.meshes.forEach(m => {- if (m.getTotalVertices && m.getTotalVertices() > 0 && !/skyBox|shadowGround|^ground$|viewCube|axis/i.test(m.name)) {- m.receiveShadows = true; sg.addShadowCaster(m);+ if (!m.getTotalVertices || m.getTotalVertices() === 0) return;+ if (/skyBox|viewCube|axis|gizmo/i.test(m.name)) return;+ m.receiveShadows = true; // everything receives (incl. ground)+ if (!/shadowGround|^ground$/i.test(m.name) && !shadowed.has(m)) { // ground receives but doesn't cast+ sg.addShadowCaster(m, true); shadowed.add(m); // (Set guard avoids duplicate casters) } }); const smap = sg.getShadowMap(); if (smap) smap.refreshRate = 1;- }+ }; // 3) Translucent ghosts (nozzle + carrier tape + component-in-tape), built with HIS Babylon. const PX = 0.0065, LED_TOP = 0.00045;@@ -216,6 +226,7 @@ }); const cover = B.MeshBuilder.CreateBox('cover_tape', { width:tLen, height:TW*0.6, depth:0.00003 }, scene); // clear cover tape cover.position = new B.Vector3(tCx, PKY + TBo*0.2, 0.00004); cover.material = coverMat; cover.parent = tape;+ registerShadows(); // now that ALL geometry exists (model + tape/reel + nozzle + pocket LEDs + cover), enable shadows on everything // 4) Motion — manual per-frame interpolation (no baked groups); positions in the model's space. const LIFT=0.00135, NHI=0.0032, NLO=0.00047, CARRY=0.0027;@@ -302,7 +313,7 @@ applyFrame(m); statusEl.textContent = 'STATIC · LED insertion (up/down) · toggle Light & FOV in Layers'; } else {- setNodeEnabled(ghostRoot, true); viewer.addContentRoot(ghostRoot, { castShadows:false, receiveShadows:false });+ setNodeEnabled(ghostRoot, true); viewer.addContentRoot(ghostRoot, { castShadows:true, receiveShadows:true }); if (ledLit) setNodeEnabled(ledLit, false); if (fovCone) setNodeEnabled(fovCone, false); if (ptLight) ptLight.setEnabled(false); lockLayer('light',true); lockLayer('fov',true); if (led) setNodeEnabled(led, true);
README.html+16−5@@ -161,14 +161,24 @@ // older, so we do it here — same effect, no change to his code.) refreshRate=1 keeps the // cast shadow updating as the LED animates. const sg = viewer.getShadowGenerator && viewer.getShadowGenerator();- if (sg) {+ // Shadows for EVERYTHING: every content mesh casts AND receives; the ground only receives;+ // skybox / view-cube / axes are environment helpers (neither). Called once after ALL geometry+ // (model + tape/reel + ghosts) is built so nothing is missed. transparencyShadow lets the+ // translucent ghosts (nozzle, cover tape) cast alpha-weighted shadows instead of hard ones.+ const shadowed = new Set();+ const registerShadows = () => {+ if (!sg) return;+ if (sg.setTransparencyShadow) sg.setTransparencyShadow(true); else sg.transparencyShadow = true; scene.meshes.forEach(m => {- if (m.getTotalVertices && m.getTotalVertices() > 0 && !/skyBox|shadowGround|^ground$|viewCube|axis/i.test(m.name)) {- m.receiveShadows = true; sg.addShadowCaster(m);+ if (!m.getTotalVertices || m.getTotalVertices() === 0) return;+ if (/skyBox|viewCube|axis|gizmo/i.test(m.name)) return;+ m.receiveShadows = true; // everything receives (incl. ground)+ if (!/shadowGround|^ground$/i.test(m.name) && !shadowed.has(m)) { // ground receives but doesn't cast+ sg.addShadowCaster(m, true); shadowed.add(m); // (Set guard avoids duplicate casters) } }); const smap = sg.getShadowMap(); if (smap) smap.refreshRate = 1;- }+ }; // 3) Translucent ghosts (nozzle + carrier tape + component-in-tape), built with HIS Babylon. const PX = 0.0065, LED_TOP = 0.00045;@@ -250,6 +260,7 @@ }); const cover = B.MeshBuilder.CreateBox('cover_tape', { width:tLen, height:TW*0.6, depth:0.00003 }, scene); // clear cover tape cover.position = new B.Vector3(tCx, PKY + TBo*0.2, 0.00004); cover.material = coverMat; cover.parent = tape;+ registerShadows(); // now that ALL geometry exists (model + tape/reel + nozzle + pocket LEDs + cover), enable shadows on everything // 4) Motion — manual per-frame interpolation (no baked groups); positions in the model's space. const LIFT=0.00135, NHI=0.0032, NLO=0.00047, CARRY=0.0027;@@ -336,7 +347,7 @@ applyFrame(m); statusEl.textContent = 'STATIC · LED insertion (up/down) · toggle Light & FOV in Layers'; } else {- setNodeEnabled(ghostRoot, true); viewer.addContentRoot(ghostRoot, { castShadows:false, receiveShadows:false });+ setNodeEnabled(ghostRoot, true); viewer.addContentRoot(ghostRoot, { castShadows:true, receiveShadows:true }); if (ledLit) setNodeEnabled(ledLit, false); if (fovCone) setNodeEnabled(fovCone, false); if (ptLight) ptLight.setEnabled(false); lockLayer('light',true); lockLayer('fov',true); if (led) setNodeEnabled(led, true);