소스 검색

Add util functions ThreeViewer.export, ThreeViewer.import, jsonToBlob, some refactor for those, Add example to convert HDR to EXR(export DataTexture as EXR)

master
Palash Bansal 3 년 전
부모
커밋
a9ab1460b6
No account linked to committer's email address

+ 2
- 2
examples/3dm-to-glb/script.ts 파일 보기



viewer.addPluginSync(Rhino3dmLoadPlugin) viewer.addPluginSync(Rhino3dmLoadPlugin)


// load obj + mtl
// load a 3dm file
const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/3dm/Rhino_Logo.3dm', { const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/3dm/Rhino_Logo.3dm', {
autoCenter: true, autoCenter: true,
autoScale: true, autoScale: true,
}) })


// export to glb // export to glb
const blob = await viewer.assetManager.exporter.exportObject(result)
const blob = await viewer.export(result)
// const blob = await viewer.exportScene(); // its possible to export the whole scene also // const blob = await viewer.exportScene(); // its possible to export the whole scene also


if (!blob || blob.ext !== 'glb') { if (!blob || blob.ext !== 'glb') {

+ 1
- 1
examples/exr-load/index.html 파일 보기

<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>HDR Load</title>
<title>EXR Load</title>
<!-- Import maps polyfill --> <!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported --> <!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

+ 3
- 3
examples/glb-export/script.ts 파일 보기

} }
const mesh = helmet.getObjectByName('node_damagedHelmet_-6514')! const mesh = helmet.getObjectByName('node_damagedHelmet_-6514')!


// const blob = await viewer.assetManager.exporter.exportObject(helmetObject, {exportExt: 'glb'})
// const blob = await viewer.export(helmetObject, {exportExt: 'glb'})
// const blob = await viewer.exportScene({viewerConfig: false}) // export scene without viewer config // const blob = await viewer.exportScene({viewerConfig: false}) // export scene without viewer config
// const blob = await viewer.exportScene() // export scene with viewer config and default settings. // const blob = await viewer.exportScene() // export scene with viewer config and default settings.


createSimpleButtons({ createSimpleButtons({
['Download Helmet Object GLB']: async() => { ['Download Helmet Object GLB']: async() => {
const blob = await viewer.assetManager.exporter.exportObject(mesh, {
const blob = await viewer.export(mesh, {
exportExt: 'glb', exportExt: 'glb',
embedUrlImages: true, // embed images in glb even when url is available. embedUrlImages: true, // embed images in glb even when url is available.
}) })
downloadBlob(blob, 'helmet.' + blob.ext) downloadBlob(blob, 'helmet.' + blob.ext)
}, },
['Download Helmet Material']: async() => { ['Download Helmet Material']: async() => {
const blob = await viewer.assetManager.exporter.exportObject(<IMaterial>mesh.material)
const blob = await viewer.export(<IMaterial>mesh.material)
if (!blob) { if (!blob) {
alert('Unable to export helmet material') alert('Unable to export helmet material')
return return

+ 34
- 0
examples/hdr-to-exr/index.html 파일 보기

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HDR To EXR</title>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
{
"imports": {
"threepipe": "./../../dist/index.mjs"
}
}

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
</div>

</body>

+ 44
- 0
examples/hdr-to-exr/script.ts 파일 보기

import {_testFinish, downloadBlob, IAsset, ITexture, ThreeViewer} from 'threepipe'

const viewer = new ThreeViewer({canvas: document.getElementById('mcanvas') as HTMLCanvasElement})

async function init() {

// import a hdr file
const dataTexture = await viewer.import<ITexture>('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr')
if (!dataTexture) {
console.error('Unable to import texture')
return
}

// export as exr
const blob = await viewer.export(dataTexture, {exportExt: 'exr'})
if (!blob || blob.ext !== 'exr') {
console.error('Unable to export texture', blob)
return
}

// load the exr as environment map
const map = await viewer.setEnvironmentMap({
path: 'file.exr',
file: blob,
} as IAsset)
if (!map) {
console.error('Unable to load exr')
return
}
viewer.scene.background = map

// add download button
const downloadButton = document.createElement('button')
downloadButton.innerText = 'Download .exr'
downloadButton.style.position = 'absolute'
downloadButton.style.bottom = '3rem'
downloadButton.style.right = '3rem'
downloadButton.style.zIndex = '10000'
downloadButton.onclick = () => downloadBlob(blob, 'file.exr')
document.body.appendChild(downloadButton)

}

init().then(_testFinish)

+ 1
- 0
examples/index.html 파일 보기

<li><a href="./parallel-asset-import/">Parallel Asset Import </a></li> <li><a href="./parallel-asset-import/">Parallel Asset Import </a></li>
<li><a href="./obj-to-glb/">Convert OBJ to GLB </a></li> <li><a href="./obj-to-glb/">Convert OBJ to GLB </a></li>
<li><a href="./3dm-to-glb/">Convert 3DM to GLB </a></li> <li><a href="./3dm-to-glb/">Convert 3DM to GLB </a></li>
<li><a href="./hdr-to-exr/">Convert HDR to EXR </a></li>
</ul> </ul>
<h2 class="category">Tests</h2> <h2 class="category">Tests</h2>
<ul> <ul>

+ 1
- 1
examples/obj-to-glb/script.ts 파일 보기

// todo wait for images to load // todo wait for images to load


// export to glb // export to glb
const blob = await viewer.assetManager.exporter.exportObject(result)
const blob = await viewer.export(result)
// const blob = await viewer.exportScene(); // its possible to export the whole scene also // const blob = await viewer.exportScene(); // its possible to export the whole scene also


if (!blob || blob.ext !== 'glb') { if (!blob || blob.ext !== 'glb') {

+ 4
- 5
examples/pmat-material-export/script.ts 파일 보기

sphere.position.setX(2) sphere.position.setX(2)
await viewer.addSceneObject(sphere) await viewer.addSceneObject(sphere)


const matBlob = await viewer.assetManager.exporter.exportObject(material)
if (!matBlob) {
return
}
const matBlob = await viewer.export(material)
if (!matBlob) return

const material2 = await viewer.assetManager.importer.importSingle<IMaterial>({file: matBlob, path: 'mat.' + matBlob.ext}) const material2 = await viewer.assetManager.importer.importSingle<IMaterial>({file: matBlob, path: 'mat.' + matBlob.ext})
if (!material2) { if (!material2) {
return return


createSimpleButtons({ createSimpleButtons({
['Download PMAT']: async() => { ['Download PMAT']: async() => {
const blob = await viewer.assetManager.exporter.exportObject(material)
const blob = await viewer.export(material)
if (!blob) { if (!blob) {
alert('Unable to export material') alert('Unable to export material')
return return

+ 2
- 3
src/assetmanager/AssetExporter.ts 파일 보기

import {BaseEvent, EventDispatcher, WebGLRenderTarget} from 'three' import {BaseEvent, EventDispatcher, WebGLRenderTarget} from 'three'
import {IMaterial, IObject3D, ITexture} from '../core' import {IMaterial, IObject3D, ITexture} from '../core'
import {AnyOptions} from 'ts-browser-helpers'
import {BlobExt, ExportFileOptions, IAssetExporter, IExporter, IExportParser} from './IExporter' import {BlobExt, ExportFileOptions, IAssetExporter, IExporter, IExportParser} from './IExporter'
import {EXRExporter2, SimpleJSONExporter, SimpleTextExporter} from './export' import {EXRExporter2, SimpleJSONExporter, SimpleTextExporter} from './export'
import {IRenderTarget} from '../rendering' import {IRenderTarget} from '../rendering'
return this._cachedParsers.find(e => e.ext.includes(ext))?.parser ?? this._createParser(ext) return this._cachedParsers.find(e => e.ext.includes(ext))?.parser ?? this._createParser(ext)
} }


public async processBeforeExport(obj: IObject3D|IMaterial|ITexture|IRenderTarget, _: AnyOptions = {}): Promise<{obj:any, ext:string, typeExt?:string, blob?: BlobExt}|undefined> {
public async processBeforeExport(obj: IObject3D|IMaterial|ITexture|IRenderTarget, options: ExportFileOptions = {}): Promise<{obj:any, ext:string, typeExt?:string, blob?: BlobExt}|undefined> {
// if (obj.assetExporterProcessed && !options.forceExporterReprocess) return obj //todo;;; // if (obj.assetExporterProcessed && !options.forceExporterReprocess) return obj //todo;;;


switch (obj.assetType) { switch (obj.assetType) {
case 'material': case 'material':
return {obj: (obj as IMaterial).toJSON(), ext: (obj as IMaterial).constructor?.TypeSlug || 'json', typeExt: 'json'} return {obj: (obj as IMaterial).toJSON(), ext: (obj as IMaterial).constructor?.TypeSlug || 'json', typeExt: 'json'}
case 'texture': case 'texture':
return {obj: (obj as ITexture).toJSON(), ext: 'json'}
return options.exportExt ? {obj, ext: options.exportExt} : {obj: (obj as ITexture).toJSON(), ext: 'json'}
case 'renderTarget': case 'renderTarget':
if (obj.isWebGLMultipleRenderTargets) console.error('AssetExporter: WebGLMultipleRenderTargets export not supported') if (obj.isWebGLMultipleRenderTargets) console.error('AssetExporter: WebGLMultipleRenderTargets export not supported')
else if (!obj.renderManager) return {obj, ext: 'exr'} else if (!obj.renderManager) return {obj, ext: 'exr'}

+ 9
- 5
src/assetmanager/export/EXRExporter2.ts 파일 보기

import {WebGLRenderTarget} from 'three'
import {DataTexture, WebGLRenderTarget} from 'three'
import {EXRExporter, EXRExporterParseOptions} from 'three/examples/jsm/exporters/EXRExporter.js' import {EXRExporter, EXRExporterParseOptions} from 'three/examples/jsm/exporters/EXRExporter.js'
import {IExportParser} from '../IExporter' import {IExportParser} from '../IExporter'
import {IRenderTarget} from '../../rendering' import {IRenderTarget} from '../../rendering'


export class EXRExporter2 extends EXRExporter implements IExportParser { export class EXRExporter2 extends EXRExporter implements IExportParser {
async parseAsync(obj: IRenderTarget, options: EXRExporterParseOptions): Promise<Blob> {
if (!obj.renderManager) throw new Error('No renderManager on renderTarget')
if (obj.isWebGLMultipleRenderTargets) throw new Error('WebGLMultipleRenderTargets not supported')
const res = this.parse(obj.renderManager.webglRenderer, obj as any as WebGLRenderTarget, options)
async parseAsync(obj: IRenderTarget|DataTexture, options: EXRExporterParseOptions): Promise<Blob> {
const target = <IRenderTarget>obj
if (target.isWebGLRenderTarget && !target.renderManager) throw new Error('No renderManager on renderTarget')
if (!target.isWebGLRenderTarget && !(<DataTexture>obj).isDataTexture) throw new Error('Invalid object type')
if (target.isWebGLMultipleRenderTargets) throw new Error('WebGLMultipleRenderTargets not supported')
const res = target.isWebGLRenderTarget ?
this.parse(target.renderManager!.webglRenderer, <WebGLRenderTarget>target, options) :
this.parse(undefined, <DataTexture>obj, options)
return new Blob([res], {type: 'image/x-exr'}) return new Blob([res], {type: 'image/x-exr'})
} }
} }

+ 7
- 1
src/utils/serialization.ts 파일 보기

Vector4, Vector4,
} from 'three' } from 'three'
import type {AssetImporter, AssetManager, MaterialManager} from '../assetmanager' import type {AssetImporter, AssetManager, MaterialManager} from '../assetmanager'
import {IAssetImporter} from '../assetmanager'
import {BlobExt, IAssetImporter} from '../assetmanager'
import {ThreeViewer} from '../viewer' import {ThreeViewer} from '../viewer'
import {ITexture} from '../core' import {ITexture} from '../core'
import {IRenderTarget, RenderManager} from '../rendering' import {IRenderTarget, RenderManager} from '../rendering'
}, // clear context even if its present in resources }, // clear context even if its present in resources
} }
} }

export function jsonToBlob(json: any): BlobExt {
const b = new Blob([JSON.stringify(json)], {type: 'application/json'}) as BlobExt
b.ext = 'json'
return b
}

+ 27
- 0
src/viewer/ThreeViewer.ts 파일 보기

import { import {
AddObjectOptions, AddObjectOptions,
IAnimationLoopEvent, IAnimationLoopEvent,
IMaterial,
IObject3D, IObject3D,
IObjectProcessor, IObjectProcessor,
ITexture, ITexture,
import { import {
convertArrayBufferToStringsInMeta, convertArrayBufferToStringsInMeta,
getEmptyMeta, getEmptyMeta,
jsonToBlob,
metaFromResources, metaFromResources,
MetaImporter, MetaImporter,
metaToResources, metaToResources,
import {IViewerPlugin, IViewerPluginSync} from './IViewerPlugin' import {IViewerPlugin, IViewerPluginSync} from './IViewerPlugin'
import {DropzonePlugin, DropzonePluginOptions} from '../plugins/interaction/DropzonePlugin' import {DropzonePlugin, DropzonePluginOptions} from '../plugins/interaction/DropzonePlugin'
import {uiConfig, uiFolderContainer, UiObjectConfig} from 'uiconfig.js' import {uiConfig, uiFolderContainer, UiObjectConfig} from 'uiconfig.js'
import {IRenderTarget} from '../rendering'


export type IViewerEvent = BaseEvent & { export type IViewerEvent = BaseEvent & {
type: 'update'|'preRender'|'postRender'|'preFrame'|'postFrame'|'dispose'|'addPlugin'|'renderEnabled'|'renderDisabled' type: 'update'|'preRender'|'postRender'|'preFrame'|'postFrame'|'dispose'|'addPlugin'|'renderEnabled'|'renderDisabled'
return await this.assetManager.addAssetSingle<T>(obj, options) return await this.assetManager.addAssetSingle<T>(obj, options)
} }


/**
* Imports an object/model/material/texture/viewer-config/plugin-preset/... to the viewer scene from url or an {@link IAsset} object.
* Same as {@link AssetImporter.importSingle}
* @param obj
* @param options
*/
async import<T extends ImportResult = ImportResult>(obj: string | IAsset | null, options?: ImportAddOptions) {
if (!obj) return
return await this.assetManager.importer.importSingle<T>(obj, options)
}

/**
* Exports an object/mesh/material/texture/render-target/plugin-preset/viewer to a blob.
* If no object is given, a glb is exported with the current viewer state.
* @param obj
* @param options
*/
async export(obj?: IObject3D|IMaterial|ITexture|IRenderTarget|IViewerPlugin|(typeof this), options?: ExportFileOptions) {
if (!obj) obj = this._scene // this will export the glb with the scene and viewer config
if ((<typeof this>obj).type === this.type) return jsonToBlob((<typeof this>obj).exportConfig())
if ((<IViewerPlugin>obj).constructor?.PluginType) return jsonToBlob(this.exportPluginConfig(<IViewerPlugin>obj))
return await this.assetManager.exporter.exportObject(<IObject3D|IMaterial|ITexture|IRenderTarget>obj, options)
}

/** /**
* Set the environment map of the scene from url or an {@link IAsset} object. * Set the environment map of the scene from url or an {@link IAsset} object.
* @param map * @param map

Loading…
취소
저장