Преглед изворни кода

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 Прегледај датотеку

@@ -6,14 +6,14 @@ async function init() {

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', {
autoCenter: true,
autoScale: true,
})

// 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

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

+ 1
- 1
examples/exr-load/index.html Прегледај датотеку

@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HDR Load</title>
<title>EXR Load</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>

+ 3
- 3
examples/glb-export/script.ts Прегледај датотеку

@@ -17,13 +17,13 @@ async function init() {
}
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() // export scene with viewer config and default settings.

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

+ 34
- 0
examples/hdr-to-exr/index.html Прегледај датотеку

@@ -0,0 +1,34 @@
<!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 Прегледај датотеку

@@ -0,0 +1,44 @@
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 Прегледај датотеку

@@ -249,6 +249,7 @@
<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="./3dm-to-glb/">Convert 3DM to GLB </a></li>
<li><a href="./hdr-to-exr/">Convert HDR to EXR </a></li>
</ul>
<h2 class="category">Tests</h2>
<ul>

+ 1
- 1
examples/obj-to-glb/script.ts Прегледај датотеку

@@ -13,7 +13,7 @@ async function init() {
// todo wait for images to load

// 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

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

+ 4
- 5
examples/pmat-material-export/script.ts Прегледај датотеку

@@ -22,10 +22,9 @@ async function init() {
sphere.position.setX(2)
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})
if (!material2) {
return
@@ -39,7 +38,7 @@ async function init() {

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

+ 2
- 3
src/assetmanager/AssetExporter.ts Прегледај датотеку

@@ -1,6 +1,5 @@
import {BaseEvent, EventDispatcher, WebGLRenderTarget} from 'three'
import {IMaterial, IObject3D, ITexture} from '../core'
import {AnyOptions} from 'ts-browser-helpers'
import {BlobExt, ExportFileOptions, IAssetExporter, IExporter, IExportParser} from './IExporter'
import {EXRExporter2, SimpleJSONExporter, SimpleTextExporter} from './export'
import {IRenderTarget} from '../rendering'
@@ -111,7 +110,7 @@ export class AssetExporter extends EventDispatcher<BaseEvent, 'exporterCreate' |
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;;;

switch (obj.assetType) {
@@ -124,7 +123,7 @@ export class AssetExporter extends EventDispatcher<BaseEvent, 'exporterCreate' |
case 'material':
return {obj: (obj as IMaterial).toJSON(), ext: (obj as IMaterial).constructor?.TypeSlug || 'json', typeExt: 'json'}
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':
if (obj.isWebGLMultipleRenderTargets) console.error('AssetExporter: WebGLMultipleRenderTargets export not supported')
else if (!obj.renderManager) return {obj, ext: 'exr'}

+ 9
- 5
src/assetmanager/export/EXRExporter2.ts Прегледај датотеку

@@ -1,13 +1,17 @@
import {WebGLRenderTarget} from 'three'
import {DataTexture, WebGLRenderTarget} from 'three'
import {EXRExporter, EXRExporterParseOptions} from 'three/examples/jsm/exporters/EXRExporter.js'
import {IExportParser} from '../IExporter'
import {IRenderTarget} from '../../rendering'

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'})
}
}

+ 7
- 1
src/utils/serialization.ts Прегледај датотеку

@@ -14,7 +14,7 @@ import {
Vector4,
} from 'three'
import type {AssetImporter, AssetManager, MaterialManager} from '../assetmanager'
import {IAssetImporter} from '../assetmanager'
import {BlobExt, IAssetImporter} from '../assetmanager'
import {ThreeViewer} from '../viewer'
import {ITexture} from '../core'
import {IRenderTarget, RenderManager} from '../rendering'
@@ -771,3 +771,9 @@ export function metaFromResources(resources?: Partial<SerializationResourcesType
}, // 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 Прегледај датотеку

@@ -4,6 +4,7 @@ import {TViewerScreenShader} from '../postprocessing'
import {
AddObjectOptions,
IAnimationLoopEvent,
IMaterial,
IObject3D,
IObjectProcessor,
ITexture,
@@ -14,6 +15,7 @@ import {ViewerRenderManager} from './ViewerRenderManager'
import {
convertArrayBufferToStringsInMeta,
getEmptyMeta,
jsonToBlob,
metaFromResources,
MetaImporter,
metaToResources,
@@ -36,6 +38,7 @@ import {GLStatsJS, IDialogWrapper, windowDialogWrapper} from '../utils'
import {IViewerPlugin, IViewerPluginSync} from './IViewerPlugin'
import {DropzonePlugin, DropzonePluginOptions} from '../plugins/interaction/DropzonePlugin'
import {uiConfig, uiFolderContainer, UiObjectConfig} from 'uiconfig.js'
import {IRenderTarget} from '../rendering'

export type IViewerEvent = BaseEvent & {
type: 'update'|'preRender'|'postRender'|'preFrame'|'postFrame'|'dispose'|'addPlugin'|'renderEnabled'|'renderDisabled'
@@ -372,6 +375,30 @@ export class ThreeViewer extends EventDispatcher<IViewerEvent, IViewerEventTypes
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.
* @param map

Loading…
Откажи
Сачувај