Preview and stl mvp working

This commit is contained in:
Kurt Hutten
2021-11-21 17:49:22 +11:00
parent 8bdfec02d9
commit b1ff7796b9
8 changed files with 57 additions and 110 deletions

View File

@@ -1,9 +1,10 @@
{
"cSpell.words": [
"Cadhub",
"cadquery",
"curv",
"Customizer",
"Hutten",
"cadquery",
"jscad",
"openscad",
"sendmail"

View File

@@ -34,8 +34,12 @@ const makeRequest = (route, port) => [
app.post(...makeRequest('/openscad/preview', 5052))
app.post(...makeRequest('/openscad/stl', 5053))
app.post(...makeRequest('/cadquery/stl', 5060))
app.post(...makeRequest('/curv/preview', 5070))
app.post(...makeRequest('/curv/stl', 5071))
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})

View File

@@ -2,17 +2,27 @@ FROM public.ecr.aws/lts/ubuntu:20.04_stable
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update --fix-missing -qq
RUN apt-get -y -qq install git software-properties-common dirmngr apt-transport-https lsb-release ca-certificates xvfb unzip maim clang cmake git-core libboost-all-dev libopenexr-dev libtbb-dev libglm-dev libpng-dev libeigen3-dev dbus-x11 libxcursor-dev libxinerama-dev libxrandr-dev libglu1-mesa-dev libgles2-mesa-dev libgl1-mesa-dev libxi-dev
RUN git clone https://github.com/curv3d/curv.git
RUN cd curv
RUN git submodule init && git submodule update
RUN mkdir build
RUN cd build
RUN sed -i 's/set(LEAN_BUILD 0)/set(LEAN_BUILD 1)/' ../CMakeLists.txt
RUN cmake ..
RUN make
RUN make install
RUN apt-get update --fix-missing && apt-get -y -qq install software-properties-common dirmngr apt-transport-https lsb-release ca-certificates xvfb
RUN apt-get update -qq
RUN apt-get -y -qq install git
RUN apt-get update --fix-missing && apt-get -y --fix-broken install python-pycurl python-apt
RUN apt-get -y -qq --fix-broken install software-properties-common
RUN apt-get -y -qq install xvfb unzip maim clang cmake
RUN apt-get -y -qq install git-core libboost-all-dev
RUN apt-get -y -qq install libopenexr-dev libtbb-dev
RUN apt-get -y -qq install libglm-dev libpng-dev
RUN apt-get -y -qq install libeigen3-dev dbus-x11
RUN apt-get -y -qq install libxcursor-dev libxinerama-dev
RUN apt-get -y -qq install libxrandr-dev libglu1-mesa-dev
RUN apt-get -y -qq install libgles2-mesa-dev libgl1-mesa-dev
RUN apt-get -y -qq install libxi-dev
RUN git clone --recursive https://github.com/curv3d/curv; cd curv; make; make install
# install node14, see comment at the top of node14source_setup.sh
ADD src/docker/common/node14source_setup.sh /nodesource_setup.sh
@@ -46,7 +56,7 @@ RUN echo "cadhub-concat-split" > /var/task/cadhub-concat-split
# using built javascript from dist
# run `yarn rw build` before bulding this image
COPY dist/docker/openscad/* /var/task/js/
COPY dist/docker/curv/* /var/task/js/
COPY dist/docker/common/* /var/task/common/
COPY src/docker/common/entrypoint.sh /entrypoint.sh
RUN ["chmod", "+x", "/entrypoint.sh"]

View File

@@ -1,21 +1,5 @@
import { writeFiles, runCommand } from '../common/utils'
import { nanoid } from 'nanoid'
const { readFile } = require('fs/promises')
const fs = require('fs');
const { spawn } = require('child_process');
function* getXDisplayNumber() {
const startValue = 99;
let i = startValue;
while(true) {
i -= 1;
// Never hit zero since 0 is usually used by desktop users.
if (i <= 0) i = startValue;
yield ':' + i;
}
}
export const runCurv = async ({
file,
@@ -54,61 +38,23 @@ export const runCurv = async ({
const fullPath = `/tmp/${tempFile}/output.gz`
const imPath = `/tmp/${tempFile}/output.png`
const customizerPath = `/tmp/${tempFile}/customizer.param`
const summaryPath = `/tmp/${tempFile}/summary.json` // contains camera info
const code = file;
const DISPLAY = getXDisplayNumber().next().value;
const xvfbProcess = spawn(
'Xvfb',
[DISPLAY, '-ac', '-nocursor', '-screen', '0', '480x500x24'],
);
const curvProcess = spawn(
'curv',
['-' ],
{ env: Object.assign({}, process.env, { DISPLAY, PATH: '/usr/local/bin' }) }
);
curvProcess.stdin.write(code);
curvProcess.stdin.end();
let statusSet = false;
let contentTypeSet = false;
curvProcess.stderr.on('data', (buf) => {
const data = buf.toString('utf8');
if (data.indexOf('shape') >= 0) {
setTimeout(() => {
const screenshotProcess = spawn('maim', ['--hidecursor', imPath], { env: { DISPLAY } });
screenshotProcess.on('close', () => {
curvProcess.kill();
xvfbProcess.kill();
});
}, 1000);
}
if (data.indexOf('ERROR') < 0) { return; }
curvProcess.kill();
xvfbProcess.kill();
});
const command = [
'xvfb-run --auto-servernum --server-args "-screen 0 1024x768x24" curv',
`-o ${imPath}`,
`-O xsize=${x}`,
`-O ysize=${y}`,
`-O bg=webRGB[26,26,29]`, // #1A1A1D
`/tmp/${tempFile}/main.curv`,
].join(' ')
console.log('command', command)
try {
const files: string[] = await Promise.all(
[customizerPath, summaryPath].map((path) =>
readFile(path, { encoding: 'ascii' })
)
)
const [params, cameraInfo] = files.map((fileStr: string) =>
JSON.parse(fileStr)
)
const consoleMessage = await runCommand(command, 15000)
await writeFiles(
[
{
file: JSON.stringify({
cameraInfo: viewAll ? cameraInfo.camera : undefined,
customizerParams: params.parameters,
consoleMessage,
type: 'png',
}),
@@ -143,7 +89,6 @@ export const stlExport = async ({ file, settings: { parameters } } = {}) => {
)
const fullPath = `/tmp/${tempFile}/output.gz`
const stlPath = `/tmp/${tempFile}/output.stl`
const customizerPath = `/tmp/${tempFile}/customizer.param`
const command = [
'curv',
'-o', stlPath,
@@ -155,14 +100,10 @@ export const stlExport = async ({ file, settings: { parameters } } = {}) => {
try {
// lambda will time out before this, we might need to look at background jobs if we do git integration stl generation
const consoleMessage = await runCommand(command, 60000)
const params = JSON.parse(
await readFile(customizerPath, { encoding: 'ascii' })
).parameters
await writeFiles(
[
{
file: JSON.stringify({
customizerParams: params,
consoleMessage,
type: 'stl',
}),
@@ -175,7 +116,7 @@ export const stlExport = async ({ file, settings: { parameters } } = {}) => {
`cat ${stlPath} /var/task/cadhub-concat-split /tmp/${tempFile}/metadata.json | gzip > ${fullPath}`,
15000
)
return { consoleMessage, fullPath, customizerPath }
return { consoleMessage, fullPath }
} catch (error) {
return { error, fullPath }
}

View File

@@ -53,11 +53,20 @@ services:
command: js/curv.preview
# Adding volumes so that the containers can be restarted for js only changes in local dev
volumes:
- ../../dist/docker/openscad:/var/task/js/
- ../../dist/docker/curv:/var/task/js/
- ../../dist/docker/common:/var/task/common/
ports:
- "5052:8080"
environment:
AWS_SECRET_ACCESS_KEY: "${DEV_AWS_SECRET_ACCESS_KEY}"
AWS_ACCESS_KEY_ID: "${DEV_AWS_ACCESS_KEY_ID}"
BUCKET: "${DEV_BUCKET}"
- "5070:8080"
curv-stl:
build:
context: ../../
dockerfile: ./src/docker/curv/Dockerfile
image: curv
command: js/curv.stl
# Adding volumes so that the containers can be restarted for js only changes in local dev
volumes:
- ../../dist/docker/curv:/var/task/js/
- ../../dist/docker/common:/var/task/common/
ports:
- "5071:8080"

View File

@@ -6,7 +6,7 @@ module.exports = (config, { env }) => {
}
})
config.module.rules.push({
test: /\.(md|jscad\.js|py|scad)$/i,
test: /\.(md|jscad\.js|py|scad|curv)$/i,
use: 'raw-loader',
});
return config

View File

@@ -18,7 +18,7 @@ const IdeEditor = ({ Loading }) => {
cadquery: 'python',
openscad: 'cpp',
jscad: 'javascript',
curv: 'javascript',
curv: 'python',
INIT: '',
}
const monaco = useMonaco()

View File

@@ -7,8 +7,6 @@ import {
RenderArgs,
splitGziped,
} from '../common'
import { CurvToCadhubParams } from './openScadParams'
import type { XYZ, Camera } from 'src/helpers/hooks/useIdeState'
export const render = async ({ code, settings }: RenderArgs) => {
const pixelRatio = window.devicePixelRatio || 1
@@ -61,21 +59,8 @@ export const render = async ({ code, settings }: RenderArgs) => {
}
const blob = await response.blob()
const text = await new Response(blob).text()
const { consoleMessage, customizerParams, type, cameraInfo } =
const { consoleMessage, type } =
splitGziped(text)
const vecArray2Obj = (arr: number[]): XYZ => ({
x: arr[0],
y: arr[1],
z: arr[2],
})
const camera: Camera = cameraInfo
? {
dist: cameraInfo?.distance,
position: vecArray2Obj(cameraInfo?.translation),
rotation: vecArray2Obj(cameraInfo?.rotation),
isScadUpdate: true,
}
: undefined
return createHealthyResponse({
type: type !== 'stl' ? 'png' : 'geometry',
data:
@@ -83,9 +68,7 @@ export const render = async ({ code, settings }: RenderArgs) => {
? blob
: await stlToGeometry(window.URL.createObjectURL(blob)),
consoleMessage,
camera,
date: new Date(),
customizerParams: curvToCadhubParams(customizerParams || []),
})
} catch (e) {
return createUnhealthyResponse(new Date())
@@ -115,7 +98,7 @@ export const stl = async ({ code /*settings*/ }: RenderArgs) => {
}
const blob = await response.blob()
const text = await new Response(blob).text()
const { consoleMessage, customizerParams, type } = splitGziped(text)
const { consoleMessage, type } = splitGziped(text)
return createHealthyResponse({
type: type !== 'stl' ? 'png' : 'geometry',
data:
@@ -124,7 +107,6 @@ export const stl = async ({ code /*settings*/ }: RenderArgs) => {
: await stlToGeometry(window.URL.createObjectURL(blob)),
consoleMessage,
date: new Date(),
customizerParams: openScadToCadhubParams(customizerParams || []),
})
} catch (e) {
return createUnhealthyResponse(new Date())