diff --git a/axes.scad b/axes.scad new file mode 100644 index 0000000..9dbd839 --- /dev/null +++ b/axes.scad @@ -0,0 +1,46 @@ +module arrow(length=30, shaft_radius=1, head_radius=2, head_length=5) { + cylinder(h=length-head_length, r=shaft_radius, center=false); + + translate([0, 0, length-head_length]) + cylinder(h=head_length, r1=head_radius, r2=0, center=false); +} + +color("red") + rotate([0, 90, 0]) + arrow(); + +color("green") + rotate([-90, 0, 0]) + arrow(); + +color("blue") + rotate([0, 0, 90]) + arrow(); + +module letter(text) + linear_extrude(1) text(text, halign="center", valign="center"); + +letter_dist = 38; +union() { + color("red") + translate([letter_dist, 0, 0]) + rotate([45, 0, 45]) + letter("X"); + color("green") + rotate([0, 0, 90]) + translate([letter_dist, 0, 0]) + rotate([45, 0, -45]) + letter("Y"); + color("blue") + rotate([0, -90, 0]) + translate([letter_dist, 0, 0]) + rotate([90+45, 0, 0]) + rotate([0, 0, -90]) + letter("Z"); +} + +color("grey") + cube(10, center=true); + +color([0, 0, 0, $preview ? 0.05 : 0]) + sphere(r=43); diff --git a/public/axes.glb b/public/axes.glb new file mode 100644 index 0000000..821f204 Binary files /dev/null and b/public/axes.glb differ diff --git a/src/components/ViewerPanel.tsx b/src/components/ViewerPanel.tsx index 544064c..2003c95 100644 --- a/src/components/ViewerPanel.tsx +++ b/src/components/ViewerPanel.tsx @@ -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(); + const axesViewerRef = useRef(); + 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 (
- {(state.output?.displayFileURL || state.output?.outFile && state.output.outFile.name.endsWith('.glb') && state.output?.outFileURL) && ( - { - modelRef.current = ref; - }} - /> + + + + {state.view.showAxes && ( + + + )}
)