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:
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
Reference in New Issue
Block a user