Skip to content

Commit

Permalink
Add "input_generation" and "image_generation" scripts.
Browse files Browse the repository at this point in the history
  • Loading branch information
mattc committed Dec 30, 2020
1 parent a11a4dc commit 1561f93
Show file tree
Hide file tree
Showing 11 changed files with 770 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Hypar ML utilities

Tools for training and deploying models on [Hypar](https://hypar.io).
24 changes: 24 additions & 0 deletions image_generation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Image generation

Renders a directory of .glb files into .png files using [Hypar's](https://hypar.io) renderer.

This spins up a local static file server on port 8000 to expose the .glb files to the rendering sandbox. It then renders each .glb through the Hypar renderer in a headless Chromium context and saves a screenshot locally.

## Setup

Requirements:
* [NodeJS](https://nodejs.org/)
* Python 2

Run `npm install` inside this directory to fetch all remaining dependencies.

## Usage

Run the following command:
```
npm run ts-node generateImages.ts [INPUT_DIRECTORY] [OUTPUT_DIRECTORY]
```

Where:
* `[INPUT_DIRECTORY]` is the path to a directory containing .glb files
* `[OUTPUT_DIRECTORY]` is the path where output .png files will be written.
11 changes: 11 additions & 0 deletions image_generation/cors_simple_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#! /usr/bin/env python

from SimpleHTTPServer import SimpleHTTPRequestHandler, test

class CORSHTTPRequestHandler(SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header('Access-Control-Allow-Origin', '*')
SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
test(HandlerClass=CORSHTTPRequestHandler)
107 changes: 107 additions & 0 deletions image_generation/generateImages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
const { exec, execSync } = require('child_process')
const fs = require('fs')
const path = require('path')
const puppeteer = require('puppeteer')

const args = process.argv.slice(2)
if (args.length != 2) {
console.error('Must provide a directory of .glb files and an output directory')
process.exit()
}

const inputDirectory = path.resolve(args[0])
if (!fs.existsSync(inputDirectory)) {
console.error('Input directory does not exist: ', inputDirectory)
process.exit()
}
const outputDirectory = path.resolve(args[1])
if (!fs.existsSync(outputDirectory)){
fs.mkdirSync(outputDirectory, { recursive: true })
}

// Start a file server for the GLBs so that the web context can fetch them.
const serverPath = path.resolve('cors_simple_server.py')
process.chdir(inputDirectory)
const glbServerPort = 8000
exec(`python ${serverPath} ${glbServerPort}`, (err, stdout, stderr) => {
if (err) {
console.error(err)
return
}

// the *entire* stdout and stderr (buffered)
console.log(`stdout: ${stdout}`)
console.log(`stderr: ${stderr}`)
})
console.log(`GLB server listening on port ${glbServerPort}`)

// Use a headless web browser to render each GLB through Hypar's rendering engine and take a screenshot.
const width = 256
const height = 256
let browser = null
const screenshotGltf = async (glbName: string, targetName: string) => {
return new Promise(async (resolve, reject) => {
if (!browser) {
browser = await puppeteer.launch({
ignoreHTTPSErrors: true,
args: [
"--disable-dev-shm-usage",
"--no-zygote",
"--use-gl=swiftshader",
"--enable-webgl",
"--hide-scrollbars",
"--mute-audio",
"--no-sandbox",
"--single-process",
"--disable-breakpad",
"--ignore-gpu-blacklist",
"--headless"
],
})
}
const page = await browser.newPage()
await page.setViewport({ width: width, height: height })
await page.exposeFunction('onModelLoaded', e => {
console.log('Capturing screenshot.')
page.screenshot({ path: targetName }).then(async () => {
await page.close()
resolve()
})
.catch(async () => {
await page.close()
reject()
})
})
await page.evaluateOnNewDocument(() => {
document.addEventListener('model-loaded', () => {
(window as any).onModelLoaded()
})
})

await page.goto(`https://hypar.io/render?url=http://localhost:${glbServerPort}/${glbName}`)
})
}


// Iterate over all .glb files and take a screenshot.
const processFile = (filePath: string) => {
return new Promise((resolve, reject) => {
console.log('Processing', filePath)
const inPath = path.basename(filePath)
const outPath = path.join(outputDirectory, path.basename(filePath, '.glb') + '.png')
if (fs.existsSync(outPath)) {
console.log('Screenshot already exists. Skipping.')
resolve()
} else {
screenshotGltf(inPath, outPath).then(resolve).catch(resolve)
}
})
}

async function processAllFiles(files) {
for (const file of files) {
await processFile(file)
}
}
const files = fs.readdirSync(inputDirectory).filter((fileInDir) => path.extname(fileInDir) == '.glb')
processAllFiles(files)
Loading

0 comments on commit 1561f93

Please sign in to comment.