import { IdeContext } from 'src/components/IdeToolbarNew' import { useRef, useState, useEffect, useContext, useMemo } from 'react' import { Canvas, extend, useFrame, useThree } from 'react-three-fiber' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' extend({ OrbitControls }) function Controls({ onCameraChange }) { const controls = useRef() const { scene, camera, gl } = useThree() useEffect(() => { // init camera position camera.position.x = 12 camera.position.y = 12 // Euler rotation can be problematic since order matters // We want it to rotate around the z or vertical axis first then the x axis // in Three Y is the vertical axis (Z for openscad) camera.rotation._order = 'YXZ' if (controls.current) { const callback = ({ target }) => { const getRotations = () => { const { x, y, z } = target.object.rotation const rad2Deg = 180 / Math.PI const scadX = (x + Math.PI / 2) * rad2Deg const scadZ = y * rad2Deg const scadY = z * rad2Deg return [scadX, scadY, scadZ] } const getPositions = () => { const { x: scadX, y: scadZ, z: negScadY } = target.object.position const scale = 10 // I'm not sure why this is exactly 10 const scadY = -negScadY return [scadX * scale, scadY * scale, scadZ * scale] } const [rx, ry, rz] = getRotations() const [x, y, z] = getPositions() onCameraChange({ position: { x, y, z }, rotation: { x: rx, y: ry, z: rz }, }) } controls.current.addEventListener('end', callback) const oldCurrent = controls.current return () => oldCurrent.removeEventListener('end', callback) } }, []) useFrame(() => controls.current.update()) return ( ) } function Box(props) { // This reference will give us direct access to the mesh const mesh = useRef() return ( ) } let currentCode // I have no idea why this works and using state.code is the dispatch doesn't but it was always stale const IdeViewer = () => { const { state, dispatch } = useContext(IdeContext) const [isDragging, setIsDragging] = useState(false) const image = useMemo( () => state.objectData?.type === 'png' && state.objectData?.data && window.URL.createObjectURL(state.objectData?.data), [state.objectData] ) currentCode = state.code return (
Rotating the Three.js Cube should than update the openscad camera to view the CAD object from the same angle. But having trouble translating between the two coordinate systems. OpenScad's camera only changes X and Z angles and Y is always 0. Where as rotation values from Three seem to change all x, y and z. I probably need to learn a bit more about 3d math.
{image && (
)}
setIsDragging(true)} onMouseUp={() => setIsDragging(false)} > { dispatch({ type: 'render', payload: { code: currentCode, camera: { position, rotation, }, }, }) }} />
) } export default IdeViewer