Fix OpenSCAD move sync

Hard to capture in a title. when you move the object with right-click drag, that axis move away from the shape.

resolves #241
This commit is contained in:
Kurt Hutten
2021-03-13 16:45:56 +11:00
parent ba45e3ea57
commit 1de49b66dc
3 changed files with 79 additions and 53 deletions

View File

@@ -10,13 +10,14 @@ module.exports.runScad = async ({
camera: { camera: {
position = { x: 40, y: 40, z: 40 }, position = { x: 40, y: 40, z: 40 },
rotation = { x: 55, y: 0, z: 25 }, rotation = { x: 55, y: 0, z: 25 },
dist = 200,
} = {}, } = {},
} = {}, // TODO add view settings } = {}, // TODO add view settings
} = {}) => { } = {}) => {
const tempFile = await makeFile(file) const tempFile = await makeFile(file)
const { x: rx, y: ry, z: rz } = rotation const { x: rx, y: ry, z: rz } = rotation
const { x: px, y: py, z: pz } = position const { x: px, y: py, z: pz } = position
const cameraArg = `--camera=${px},${py},${pz},${rx},${ry},${rz},300` const cameraArg = `--camera=${px},${py},${pz},${rx},${ry},${rz},${dist}`
const command = `xvfb-run --auto-servernum --server-args "-screen 0 1024x768x24" openscad -o /tmp/${tempFile}/output.png ${cameraArg} --imgsize=${x},${y} --colorscheme DeepOcean /tmp/${tempFile}/main.scad` const command = `xvfb-run --auto-servernum --server-args "-screen 0 1024x768x24" openscad -o /tmp/${tempFile}/output.png ${cameraArg} --imgsize=${x},${y} --colorscheme DeepOcean /tmp/${tempFile}/main.scad`
console.log('command', command) console.log('command', command)

View File

@@ -2,17 +2,19 @@ import { IdeContext } from 'src/components/IdeToolbarNew'
import { useRef, useState, useEffect, useContext } from 'react' import { useRef, useState, useEffect, useContext } from 'react'
import { Canvas, extend, useFrame, useThree } from 'react-three-fiber' import { Canvas, extend, useFrame, useThree } from 'react-three-fiber'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { Vector3 } from 'three'
extend({ OrbitControls }) extend({ OrbitControls })
let debounceTimeoutId let debounceTimeoutId
function Controls({ onCameraChange, onDragStart }) { function Controls({ onCameraChange, onDragStart }) {
const controls = useRef() const controls = useRef()
const { scene, camera, gl } = useThree() const { camera, gl } = useThree()
useEffect(() => { useEffect(() => {
// init camera position // init camera position
camera.position.x = 16 camera.position.x = 200
camera.position.y = 12 camera.position.y = 140
camera.position.z = 20
camera.fov = 22.5 // matches default openscad fov camera.fov = 22.5 // matches default openscad fov
// Order matters with Euler rotations // Order matters with Euler rotations
@@ -28,22 +30,42 @@ function Controls({ onCameraChange, onDragStart }) {
return [scadX, scadY, scadZ] return [scadX, scadY, scadZ]
} }
const getPositions = () => { const getPositions = () => {
const { x: scadX, y: scadZ, z: negScadY } = camera.position // Difficult to make this clean since I'm not sure why it works
const scale = 10 // The OpenSCAD camera seems hard to work with but maybe it's just me
const scadY = -negScadY
return [scadX * scale, scadY * scale, scadZ * scale] // this gives us a vector the same length as the camera.position
const cameraViewVector = new Vector3(0, 0, 1)
.applyQuaternion(camera.quaternion) // make unit vector of the camera
.multiplyScalar(camera.position.length()) // make it the same length as the position vector
// make a vector from the position vector to the cameraView vector
const head2Head = new Vector3().subVectors(
camera.position,
cameraViewVector
)
return {
// I can't seem to get normal vector addition to work
// but this works
position: {
x: camera.position.x + head2Head.x,
y: -camera.position.z - head2Head.z,
z: camera.position.y + head2Head.y,
},
dist: camera.position.length(),
}
} }
if (controls.current) { if (controls.current) {
const dragCallback = () => { const dragCallback = () => {
clearTimeout(debounceTimeoutId) clearTimeout(debounceTimeoutId)
debounceTimeoutId = setTimeout(() => { debounceTimeoutId = setTimeout(() => {
const [rx, ry, rz] = getRotations() const [x, y, z] = getRotations()
const [x, y, z] = getPositions() const { position, dist } = getPositions()
onCameraChange({ onCameraChange({
position: { x, y, z }, position,
rotation: { x: rx, y: ry, z: rz }, rotation: { x, y, z },
dist,
}) })
}, 400) }, 400)
} }
@@ -124,32 +146,21 @@ const IdeViewer = () => {
<Canvas> <Canvas>
<Controls <Controls
onDragStart={() => setIsDragging(true)} onDragStart={() => setIsDragging(true)}
onCameraChange={({ position, rotation }) => { onCameraChange={(camera) => {
dispatch({ dispatch({
type: 'render', type: 'render',
payload: { payload: {
code: currentCode, code: currentCode,
camera: { camera,
position,
rotation,
},
}, },
}) })
}} }}
/> />
<ambientLight /> <ambientLight />
<pointLight position={[15, 5, 10]} /> <pointLight position={[15, 5, 10]} />
<Box position={[0, 4.95, 0]} size={[0.1, 10, 0.1]} color="cyan" /> <Box position={[0, 49.5, 0]} size={[1, 100, 1]} color="cyan" />
<Box <Box position={[0, 0, -50.5]} size={[1, 1, 100]} color="orange" />
position={[0, 0, -5.05]} <Box position={[50.5, 0, 0]} size={[100, 1, 1]} color="hotpink" />
size={[0.1, 0.1, 10]}
color="orange"
/>
<Box
position={[5.05, 0, 0]}
size={[10, 0.1, 0.1]}
color="hotpink"
/>
</Canvas> </Canvas>
</div> </div>
</div> </div>

View File

@@ -13,38 +13,52 @@ export const render = async ({ code, settings }) => {
}, },
file: code, file: code,
}) })
const response = await fetch(openScadBaseURL + '/render', { try {
method: 'POST', const response = await fetch(openScadBaseURL + '/render', {
headers: { method: 'POST',
'Content-Type': 'application/json', headers: {
}, 'Content-Type': 'application/json',
body, },
}) body,
if (response.status === 400) { })
const { error } = await response.json() if (response.status === 400) {
const cleanedErrorMessage = error.replace( const { error } = await response.json()
/["|']\/tmp\/.+\/main.scad["|']/g, const cleanedErrorMessage = error.replace(
"'main.scad'" /["|']\/tmp\/.+\/main.scad["|']/g,
) "'main.scad'"
)
return {
isError: true,
message: {
type: 'error',
message: cleanedErrorMessage,
},
}
}
const data = await response.blob()
return {
objectData: {
type: 'png',
data,
},
message: {
type: 'message',
message: 'successful render',
},
}
} catch (e) {
// TODO handle errors better
// I think we should display something overlayed on the viewer window something like "network issue try again"
// and in future I think we need timeouts differently as they maybe from a user trying to render something too complex
// or something with minkowski in it :/ either way something like "render timed out, try again or here are tips to reduce part complexity" with a link talking about $fn and minkowski etc
return { return {
isError: true, isError: true,
message: { message: {
type: 'error', type: 'error',
message: cleanedErrorMessage, message: 'network issue',
}, },
} }
} }
const data = await response.blob()
return {
objectData: {
type: 'png',
data,
},
message: {
type: 'message',
message: 'successful render',
},
}
} }
const openScad = { const openScad = {