Skip to content

Commit fc93a54

Browse files
author
Thomas Gorisse
committed
fix: working Filament demo
1 parent a76dc41 commit fc93a54

1 file changed

Lines changed: 101 additions & 16 deletions

File tree

sceneview-demo.html

Lines changed: 101 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ <h1>SceneView Web</h1>
4444

4545
<div class="badge">Powered by SceneView + Filament.js</div>
4646

47+
<script src="https://cdn.jsdelivr.net/npm/filament@1.52.3/filament.js"></script>
4748
<script src="js/sceneview.js"></script>
4849
<script>
4950
const MODELS = {
@@ -56,27 +57,111 @@ <h1>SceneView Web</h1>
5657
const status = document.getElementById('status');
5758
let viewer = null;
5859

59-
// One liner!
60-
SceneView.modelViewer('viewer', MODELS['DamagedHelmet']).then(v => {
61-
viewer = v;
62-
status.textContent = 'Drag to rotate · Scroll to zoom';
63-
status.style.color = '#34a853';
64-
}).catch(e => {
65-
status.textContent = 'Error: ' + e.message;
66-
status.style.color = '#ea4335';
60+
// Wait for Filament WASM to be ready, then use one-liner
61+
const DEFAULT_MODEL = MODELS['DamagedHelmet'];
62+
Filament.init([DEFAULT_MODEL], function() {
63+
status.textContent = 'Creating viewer...';
64+
try {
65+
const canvas = document.getElementById('viewer');
66+
canvas.width = canvas.clientWidth * devicePixelRatio;
67+
canvas.height = canvas.clientHeight * devicePixelRatio;
68+
69+
const engine = Filament.Engine.create(canvas);
70+
const scene = engine.createScene();
71+
const renderer = engine.createRenderer();
72+
const cam = engine.createCamera(Filament.EntityManager.get().create());
73+
const view = engine.createView();
74+
const sc = engine.createSwapChain();
75+
76+
view.setCamera(cam);
77+
view.setScene(scene);
78+
view.setViewport([0, 0, canvas.width, canvas.height]);
79+
renderer.setClearOptions({ clearColor: [0.05, 0.06, 0.1, 1.0], clear: true });
80+
cam.setProjectionFov(45, canvas.width / canvas.height, 0.1, 100, Filament.Camera$Fov.VERTICAL);
81+
82+
// Lights
83+
const sun = Filament.EntityManager.get().create();
84+
Filament.LightManager.Builder(Filament.LightManager$Type.SUN)
85+
.color([0.98, 0.92, 0.89]).intensity(110000).direction([0.6, -1, -0.8])
86+
.sunAngularRadius(1.9).sunHaloSize(10).sunHaloFalloff(80)
87+
.build(engine, sun);
88+
scene.addEntity(sun);
89+
90+
const fill = Filament.EntityManager.get().create();
91+
Filament.LightManager.Builder(Filament.LightManager$Type.DIRECTIONAL)
92+
.color([0.6, 0.65, 0.8]).intensity(30000).direction([-0.5, 0.5, 1])
93+
.build(engine, fill);
94+
scene.addEntity(fill);
95+
96+
// Load default model
97+
const loader = engine.createAssetLoader();
98+
let currentAsset = null;
99+
100+
function loadModel(url) {
101+
if (Filament.assets[url]) {
102+
showModel(url);
103+
} else {
104+
status.textContent = 'Downloading model...';
105+
status.style.color = '#8ab4f8';
106+
Filament.init([url], function() { showModel(url); });
107+
}
108+
}
109+
110+
function showModel(url) {
111+
// Remove old
112+
if (currentAsset) {
113+
scene.remove(currentAsset.getRoot());
114+
currentAsset.getRenderableEntities().forEach(e => scene.remove(e));
115+
}
116+
const asset = loader.createAsset(Filament.assets[url]);
117+
if (asset) {
118+
asset.loadResources();
119+
scene.addEntity(asset.getRoot());
120+
scene.addEntities(asset.getRenderableEntities());
121+
currentAsset = asset;
122+
status.textContent = 'Drag to rotate · Scroll to zoom';
123+
status.style.color = '#34a853';
124+
}
125+
}
126+
127+
showModel(DEFAULT_MODEL);
128+
129+
// Orbit controls
130+
let angle = 0, orbitR = 3.5, orbitH = 0.8, dragging = false, lastX = 0, lastY = 0, autoRotate = true;
131+
132+
canvas.addEventListener('mousedown', e => { dragging = true; lastX = e.clientX; lastY = e.clientY; autoRotate = false; });
133+
canvas.addEventListener('mousemove', e => { if (!dragging) return; angle += (e.clientX - lastX) * 0.005; orbitH += (e.clientY - lastY) * 0.01; lastX = e.clientX; lastY = e.clientY; });
134+
canvas.addEventListener('mouseup', () => dragging = false);
135+
canvas.addEventListener('mouseleave', () => dragging = false);
136+
canvas.addEventListener('wheel', e => { e.preventDefault(); orbitR *= (1 + e.deltaY * 0.001); orbitR = Math.max(0.5, Math.min(20, orbitR)); }, { passive: false });
137+
canvas.addEventListener('touchstart', e => { if (e.touches.length === 1) { dragging = true; lastX = e.touches[0].clientX; lastY = e.touches[0].clientY; autoRotate = false; } });
138+
canvas.addEventListener('touchmove', e => { if (!dragging) return; e.preventDefault(); angle += (e.touches[0].clientX - lastX) * 0.005; orbitH += (e.touches[0].clientY - lastY) * 0.01; lastX = e.touches[0].clientX; lastY = e.touches[0].clientY; }, { passive: false });
139+
canvas.addEventListener('touchend', () => dragging = false);
140+
141+
// Render loop
142+
function render() {
143+
if (autoRotate) angle += 0.006;
144+
cam.lookAt([Math.sin(angle) * orbitR, orbitH, Math.cos(angle) * orbitR], [0, 0, 0], [0, 1, 0]);
145+
if (renderer.beginFrame(sc)) { renderer.render(sc, view); renderer.endFrame(); }
146+
engine.execute();
147+
requestAnimationFrame(render);
148+
}
149+
render();
150+
151+
// Expose for model switching buttons
152+
window.loadModel = loadModel;
153+
154+
} catch(e) {
155+
status.textContent = 'Error: ' + e.message;
156+
status.style.color = '#ea4335';
157+
console.error(e);
158+
}
67159
});
68160

69161
function load(btn, name) {
70162
document.querySelectorAll('.models button').forEach(b => b.classList.remove('active'));
71163
btn.classList.add('active');
72-
if (viewer) {
73-
status.textContent = 'Loading ' + name + '...';
74-
status.style.color = '#8ab4f8';
75-
viewer.loadModel(MODELS[name]).then(() => {
76-
status.textContent = 'Drag to rotate · Scroll to zoom';
77-
status.style.color = '#34a853';
78-
});
79-
}
164+
if (window.loadModel) window.loadModel(MODELS[name]);
80165
}
81166
</script>
82167
</body>

0 commit comments

Comments
 (0)