set up local development for openscad lamdas

and make a start on combining with Three.js IdeViewer
Resolves #227

related #231
This commit is contained in:
Kurt Hutten
2021-03-10 08:14:32 +11:00
parent 384d8231e8
commit 10062513fd
13 changed files with 4613 additions and 3490 deletions

View File

@@ -1,25 +1,133 @@
import { useContext } from 'react'
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'
import { Vector3 } from 'three'
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
if (controls.current) {
const callback = ({ target }) => {
// TODO figure out Three's rotations to make it match openscad's camera
const vector = new Vector3()
camera.getWorldDirection(vector)
console.log(Object.values(vector).map((val) => (val * 180) / Math.PI))
const { _x, _y, _z } = target.object.rotation
const rad2Deg = 180 / Math.PI
const [x, y, z] = [_x * rad2Deg, -_y * rad2Deg, _z * rad2Deg]
console.log({ y, z, x })
console.log(target, 'target')
onCameraChange({
position: target.object.position,
rotation: { x, y, z },
})
}
controls.current.addEventListener('end', callback)
return () => controls.current.removeEventListener('end', callback)
}
}, [])
useFrame(() => controls.current.update())
return (
<orbitControls
ref={controls}
args={[camera, gl.domElement]}
enableDamping
dampingFactor={0.1}
rotateSpeed={0.5}
/>
)
}
function Box(props) {
// This reference will give us direct access to the mesh
const mesh = useRef()
// Set up state for the hovered and active state
const [hovered, setHover] = useState(false)
const [active, setActive] = useState(false)
return (
<mesh
{...props}
ref={mesh}
scale={[1, 1, 1]}
onClick={(event) => setActive(!active)}
onPointerOver={(event) => setHover(true)}
onPointerOut={(event) => setHover(false)}
>
<boxBufferGeometry args={[10, 10, 10]} />
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
const IdeViewer = () => {
const { state } = useContext(IdeContext)
const image =
state.objectData?.type === 'png' &&
state.objectData?.data &&
window.URL.createObjectURL(state.objectData?.data)
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]
)
return (
<div className="p-8 border-2 m-2">
<div className="pb-4">hi I'm viewer</div>
<div>
I should be showing an{' '}
<span className="font-mono uppercase">{state.objectData?.type}</span>{' '}
right now with the data{' '}
<div className="pb-4">
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.
</div>
{image && (
<div>
<img src={image} className="" />
<div className="relative" style={{ height: '500px', width: '500px' }}>
{image && (
<div
className="absolute inset-0"
style={{ opacity: isDragging ? '0%' : '100%' }}
>
<img src={image} className="" />
</div>
)}
<div
className={`opacity-0 absolute inset-0 ${
isDragging ? 'opacity-100' : 'hover:opacity-50'
}`}
onMouseDown={() => setIsDragging(true)}
onMouseUp={() => setIsDragging(false)}
>
<Canvas>
<Controls
onCameraChange={({ position, rotation }) => {
dispatch({
type: 'render',
payload: {
code: state.code,
camera: {
position,
rotation,
},
},
})
}}
/>
<ambientLight />
<pointLight position={[15, 5, 10]} />
<Box position={[0, 0, 0]} />
</Canvas>
</div>
)}
</div>
</div>
)
}

View File

@@ -1,19 +1,24 @@
// const openScadBaseURL = 'http://localhost:8080' // for local development
const openScadBaseURL =
'https://x2wvhihk56.execute-api.us-east-1.amazonaws.com/dev'
export const render = async ({ code, settings }) => {
const body = JSON.stringify({
settings: {
size: {
x: 500,
y: 500,
},
camera: settings.camera,
},
file: code,
})
const response = await fetch(openScadBaseURL + '/render', {
method: 'POST',
headers: new Headers().append('Content-Type', 'application/json'),
body: JSON.stringify({
settings: {
size: {
x: 700,
y: 300,
},
},
file: code,
}),
headers: {
'Content-Type': 'application/json',
},
body,
})
if (response.status === 400) {
const { error } = await response.json()

View File

@@ -22,7 +22,7 @@ export const useIdeState = () => {
second: 'Console',
splitPercentage: 70,
},
}
},
}
const reducer = (state, { type, payload }) => {
switch (type) {
@@ -56,6 +56,8 @@ export const useIdeState = () => {
...state,
layout: payload.message,
}
default:
return state
}
}
@@ -64,7 +66,10 @@ export const useIdeState = () => {
switch (type) {
case 'render':
cadPackages[state.ideType]
.render({ code: payload.code })
.render({
code: payload.code,
settings: { camera: payload.camera },
})
.then(({ objectData, message, isError }) => {
if (isError) {
dispatch({