Main light can now be moved, intensity can be regulated and update environment image for model viewer

This commit is contained in:
Yeicor
2025-07-19 16:52:15 +02:00
parent 4af4315984
commit a2275f2897
7 changed files with 83 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ import type {Renderer} from "@google/model-viewer/lib/three-components/Renderer"
import type {Vector3} from "three";
import {BufferGeometry, Mesh} from "three";
import {acceleratedRaycast, computeBoundsTree, disposeBoundsTree} from 'three-mesh-bvh';
import {setupLighting} from "./lighting.ts";
ModelViewerElement.modelCacheSize = 0; // Also needed to avoid tree shaking
//@ts-ignore
@@ -67,6 +68,7 @@ onUpdated(() => {
});
elem.value.addEventListener('camera-change', onCameraChange);
elem.value.addEventListener('progress', (ev) => onProgress((ev as any).detail.totalProgress));
setupLighting(elem.value);
});
function onCameraChange() {
@@ -213,11 +215,11 @@ watch(disableTap, (newDisableTap) => {
<template>
<!-- The main 3D model viewer -->
<model-viewer ref="elem" v-if="sett != null" :ar="sett.arModes.length > 0" :ar-modes="sett.arModes"
:environment-image="sett.background" :exposure="sett.exposure" :autoplay="sett.autoplay"
:environment-image="sett.environment" :exposure="sett.exposure" :autoplay="sett.autoplay"
:orbit-sensitivity="sett.orbitSensitivity" :pan-sensitivity="sett.panSensitivity"
:poster="poster" :shadow-intensity="sett.shadowIntensity" :skybox-image="sett.skybox"
:src="props.src" :zoom-sensitivity="sett.zoomSensitivity" alt="The 3D model(s)" camera-controls
camera-orbit="30deg 75deg auto" interaction-prompt="none" max-camera-orbit="Infinity 180deg auto"
camera-orbit="45deg 45deg auto" interaction-prompt="none" max-camera-orbit="Infinity 180deg auto"
min-camera-orbit="-Infinity 0deg 5%" style="width: 100%; height: 100%">
<slot></slot>
<!-- Add a progress bar to the top of the model viewer -->

View File

@@ -0,0 +1,75 @@
import {ModelViewerElement} from '@google/model-viewer';
import {$scene} from "@google/model-viewer/lib/model-viewer-base";
import {settings} from "../misc/settings.ts";
export async function setupLighting(modelViewer: ModelViewerElement) {
modelViewer[$scene].environmentIntensity = (await settings()).environmentIntensity;
// Code is mostly copied from the example at: https://modelviewer.dev/examples/stagingandcameras/#turnSkybox
let lastX: number;
let panning = false;
let skyboxAngle = 0;
let radiansPerPixel: number;
const startPan = () => {
const orbit = modelViewer.getCameraOrbit();
const {radius} = orbit;
radiansPerPixel = -1 * radius / modelViewer.getBoundingClientRect().height;
modelViewer.interactionPrompt = 'none';
};
const updatePan = (thisX: number) => {
const delta = (thisX - lastX) * radiansPerPixel;
lastX = thisX;
skyboxAngle += delta;
const orbit = modelViewer.getCameraOrbit();
orbit.theta += delta;
modelViewer.cameraOrbit = orbit.toString();
modelViewer.resetTurntableRotation(skyboxAngle);
modelViewer.jumpCameraToGoal();
}
modelViewer.addEventListener('mousedown', (event) => {
panning = event.metaKey || event.shiftKey;
if (!panning)
return;
lastX = event.clientX;
startPan();
event.stopPropagation();
}, true);
modelViewer.addEventListener('touchstart', (event) => {
const {targetTouches, touches} = event;
panning = targetTouches.length === 2 && targetTouches.length === touches.length;
if (!panning)
return;
lastX = 0.5 * (targetTouches[0].clientX + targetTouches[1].clientX);
startPan();
}, true);
self.addEventListener('mousemove', (event) => {
if (!panning)
return;
updatePan(event.clientX);
event.stopPropagation();
}, true);
modelViewer.addEventListener('touchmove', (event) => {
if (!panning || event.targetTouches.length !== 2)
return;
const {targetTouches} = event;
const thisX = 0.5 * (targetTouches[0].clientX + targetTouches[1].clientX);
updatePan(thisX);
}, true);
self.addEventListener('mouseup', (event) => {
panning = false;
}, true);
modelViewer.addEventListener('touchend', (event) => {
panning = false;
}, true);
}