From 1de49b66dc38b6cb3d11cd25ef42fd621fc2a50b Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Sat, 13 Mar 2021 16:45:56 +1100 Subject: [PATCH] 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 --- api/src/docker/openscad/runScad.js | 3 +- web/src/components/IdeViewer/IdeViewer.js | 65 +++++++++++-------- .../helpers/cadPackages/openScadController.js | 64 +++++++++++------- 3 files changed, 79 insertions(+), 53 deletions(-) diff --git a/api/src/docker/openscad/runScad.js b/api/src/docker/openscad/runScad.js index c313277..a7e8929 100644 --- a/api/src/docker/openscad/runScad.js +++ b/api/src/docker/openscad/runScad.js @@ -10,13 +10,14 @@ module.exports.runScad = async ({ camera: { position = { x: 40, y: 40, z: 40 }, rotation = { x: 55, y: 0, z: 25 }, + dist = 200, } = {}, } = {}, // TODO add view settings } = {}) => { const tempFile = await makeFile(file) const { x: rx, y: ry, z: rz } = rotation 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` console.log('command', command) diff --git a/web/src/components/IdeViewer/IdeViewer.js b/web/src/components/IdeViewer/IdeViewer.js index b97d8e0..ea71afb 100644 --- a/web/src/components/IdeViewer/IdeViewer.js +++ b/web/src/components/IdeViewer/IdeViewer.js @@ -2,17 +2,19 @@ import { IdeContext } from 'src/components/IdeToolbarNew' import { useRef, useState, useEffect, useContext } from 'react' import { Canvas, extend, useFrame, useThree } from 'react-three-fiber' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' +import { Vector3 } from 'three' extend({ OrbitControls }) let debounceTimeoutId function Controls({ onCameraChange, onDragStart }) { const controls = useRef() - const { scene, camera, gl } = useThree() + const { camera, gl } = useThree() useEffect(() => { // init camera position - camera.position.x = 16 - camera.position.y = 12 + camera.position.x = 200 + camera.position.y = 140 + camera.position.z = 20 camera.fov = 22.5 // matches default openscad fov // Order matters with Euler rotations @@ -28,22 +30,42 @@ function Controls({ onCameraChange, onDragStart }) { return [scadX, scadY, scadZ] } const getPositions = () => { - const { x: scadX, y: scadZ, z: negScadY } = camera.position - const scale = 10 - const scadY = -negScadY - return [scadX * scale, scadY * scale, scadZ * scale] + // Difficult to make this clean since I'm not sure why it works + // The OpenSCAD camera seems hard to work with but maybe it's just me + + // 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) { const dragCallback = () => { clearTimeout(debounceTimeoutId) debounceTimeoutId = setTimeout(() => { - const [rx, ry, rz] = getRotations() - const [x, y, z] = getPositions() + const [x, y, z] = getRotations() + const { position, dist } = getPositions() onCameraChange({ - position: { x, y, z }, - rotation: { x: rx, y: ry, z: rz }, + position, + rotation: { x, y, z }, + dist, }) }, 400) } @@ -124,32 +146,21 @@ const IdeViewer = () => { setIsDragging(true)} - onCameraChange={({ position, rotation }) => { + onCameraChange={(camera) => { dispatch({ type: 'render', payload: { code: currentCode, - camera: { - position, - rotation, - }, + camera, }, }) }} /> - - - + + + diff --git a/web/src/helpers/cadPackages/openScadController.js b/web/src/helpers/cadPackages/openScadController.js index 5fc69dc..d363cf0 100644 --- a/web/src/helpers/cadPackages/openScadController.js +++ b/web/src/helpers/cadPackages/openScadController.js @@ -13,38 +13,52 @@ export const render = async ({ code, settings }) => { }, file: code, }) - const response = await fetch(openScadBaseURL + '/render', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body, - }) - if (response.status === 400) { - const { error } = await response.json() - const cleanedErrorMessage = error.replace( - /["|']\/tmp\/.+\/main.scad["|']/g, - "'main.scad'" - ) + try { + const response = await fetch(openScadBaseURL + '/render', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body, + }) + if (response.status === 400) { + const { error } = await response.json() + const cleanedErrorMessage = error.replace( + /["|']\/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 { isError: true, message: { 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 = { -- 2.39.5