Add axes w/ rotation sync w/ main model viewer

This commit is contained in:
ochafik 2024-12-23 12:07:36 +00:00 committed by Olivier Chafik
commit 7a9e3f927f
3 changed files with 109 additions and 22 deletions

View file

@ -1,10 +1,7 @@
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
import { CSSProperties, useContext, useRef } from 'react';
import { CSSProperties, useContext, useEffect, useRef, useState } from 'react';
import { ModelContext } from './contexts';
import { StlViewer} from "react-stl-viewer";
import { ColorPicker } from 'primereact/colorpicker';
import { defaultModelColor } from '../state/initial-state';
declare global {
namespace JSX {
@ -19,34 +16,78 @@ export default function ViewerPanel({className, style}: {className?: string, sty
if (!model) throw new Error('No model');
const state = model.state;
const modelRef = useRef();
const modelViewerRef = useRef<any>();
const axesViewerRef = useRef<any>();
for (const ref of [modelViewerRef, axesViewerRef]) {
const otherRef = ref === modelViewerRef ? axesViewerRef : modelViewerRef;
useEffect(() => {
function handleCameraChange(e: any) {
if (e.detail.source === 'user-interaction') {
const cameraOrbit = ref.current.getCameraOrbit();
cameraOrbit.radius = otherRef.current.getCameraOrbit().radius;
otherRef.current.cameraOrbit = cameraOrbit.toString();
}
}
ref.current.addEventListener('camera-change', handleCameraChange);
return () => ref.current.removeEventListener('camera-change', handleCameraChange);
}, [ref.current, otherRef.current]);
}
return (
<div className={className}
style={{
display: 'flex',
flexDirection: 'column',
position: 'relative',
flex: 1,
width: '100%',
...(style ?? {})
}}>
{(state.output?.displayFileURL || state.output?.outFile && state.output.outFile.name.endsWith('.glb') && state.output?.outFileURL) && (
<model-viewer
orientation="0deg -90deg 0deg"
src={state.output?.displayFileURL ?? state.output?.outFileURL ?? ''}
style={{
width: '100%',
height: '100%',
}}
environment-image="./skybox-lights.jpg"
max-camera-orbit="auto 180deg auto"
min-camera-orbit="auto 0deg auto"
camera-controls
ar
ref={(ref: any) => {
modelRef.current = ref;
}}
/>
<model-viewer
orientation="0deg -90deg 0deg"
src={state.output?.displayFileURL ?? state.output?.outFileURL ?? ''}
style={{
width: '100%',
height: '100%',
}}
environment-image="./skybox-lights.jpg"
max-camera-orbit="auto 180deg auto"
min-camera-orbit="auto 0deg auto"
camera-controls
ar
ref={modelViewerRef}
>
<span slot="progress-bar"></span>
</model-viewer>
{state.view.showAxes && (
<model-viewer
orientation="0deg -90deg 0deg"
src="./axes.glb"
style={{
position: 'absolute',
bottom: 0,
right: 0,
zIndex: 10,
height: '200px',
width: '200px',
}}
loading="eager"
interpolation-decay="0"
environment-image="./skybox-lights.jpg"
max-camera-orbit="auto 180deg auto"
min-camera-orbit="auto 0deg auto"
orbit-sensitivity="5"
interaction-prompt="none"
disable-zoom
camera-controls="false"
disable-tap
disable-pan
ref={axesViewerRef}
>
<span slot="progress-bar"></span>
</model-viewer>
)}
</div>
)