| @@ -40,18 +40,10 @@ async function init() { | |||
| converting = true | |||
| // export to glb | |||
| const blob = await viewer.export(result, { | |||
| fbxBlob = await assimp.exportModel('fbx', result, { | |||
| embedUrlImages: true, | |||
| }) | |||
| // const blob = await viewer.exportScene(); // its possible to export the whole scene also | |||
| if (!blob || blob.ext !== 'glb') { | |||
| alert('Unable to export scene') | |||
| converting = false | |||
| return | |||
| } | |||
| fbxBlob = assimp.convertFiles({['file.glb']: await blob.arrayBuffer()}, 'fbx') | |||
| if (!fbxBlob) { | |||
| alert('Failed to convert glb to fbx') | |||
| converting = false | |||
| @@ -74,6 +74,7 @@ import { | |||
| EnvironmentControlsPlugin, | |||
| GlobeControlsPlugin, | |||
| } from '@threepipe/plugin-3d-tiles-renderer' | |||
| import {AssimpJsPlugin} from '@threepipe/plugin-assimpjs' | |||
| // @ts-expect-error todo fix import | |||
| import {BloomPlugin, DepthOfFieldPlugin, SSContactShadowsPlugin, SSReflectionPlugin, TemporalAAPlugin, VelocityBufferPlugin, OutlinePlugin, SSGIPlugin, AnisotropyPlugin} from '@threepipe/webgi-plugins' | |||
| @@ -138,6 +139,7 @@ export class ThreeEditor extends ThreeViewer { | |||
| EnvironmentControlsPlugin, GlobeControlsPlugin, | |||
| B3DMLoadPlugin, I3DMLoadPlugin, PNTSLoadPlugin, CMPTLoadPlugin, | |||
| TilesRendererPlugin, DeepZoomImageLoadPlugin, /* SlippyMapTilesLoadPlugin,*/ | |||
| new AssimpJsPlugin(false), | |||
| ] | |||
| editorModes: Record<string, Class<IViewerPlugin<any>>[]> = { | |||
| @@ -146,7 +148,7 @@ export class ThreeEditor extends ThreeViewer { | |||
| ['Interaction']: [HierarchyUiPlugin, TransformControlsPlugin, PickingPlugin, OutlinePlugin, Object3DGeneratorPlugin, GeometryGeneratorPlugin, EditorViewWidgetPlugin, Object3DWidgetsPlugin, MeshOptSimplifyModifierPlugin], | |||
| ['GBuffer']: [GBufferPlugin, DepthBufferPlugin, NormalBufferPlugin], | |||
| ['Post-processing']: [TonemapPlugin, ProgressivePlugin, SSAOPlugin, SSReflectionPlugin, BloomPlugin, DepthOfFieldPlugin, SSGIPlugin, FrameFadePlugin, VignettePlugin, ChromaticAberrationPlugin, FilmicGrainPlugin, TemporalAAPlugin, VelocityBufferPlugin, SSContactShadowsPlugin], | |||
| ['Export']: [AssetExporterPlugin, CanvasSnapshotPlugin, AWSClientPlugin, TransfrSharePlugin], | |||
| ['Export']: [AssetExporterPlugin, CanvasSnapshotPlugin, AWSClientPlugin, TransfrSharePlugin, AssimpJsPlugin], | |||
| ['Configurator']: [MaterialConfiguratorPlugin, SwitchNodePlugin, GLTFKHRMaterialVariantsPlugin], | |||
| ['Animation']: [GLTFAnimationPlugin, CameraViewPlugin], | |||
| ['Extras']: [HDRiGroundPlugin, Rhino3dmLoadPlugin, ClearcoatTintPlugin, FragmentClippingExtensionPlugin, NoiseBumpMaterialPlugin, AnisotropyPlugin, CustomBumpMapPlugin, VirtualCamerasPlugin, TilesRendererPlugin], | |||
| @@ -27,6 +27,7 @@ | |||
| "@threepipe/plugin-gltf-transform": "./../../plugins/gltf-transform/dist/index.mjs", | |||
| "@threepipe/plugin-gaussian-splatting": "./../../plugins/gaussian-splatting/dist/index.mjs", | |||
| "@threepipe/plugin-3d-tiles-renderer": "./../../plugins/3d-tiles-renderer/dist/index.mjs", | |||
| "@threepipe/plugin-assimpjs": "./../../plugins/assimpjs/dist/index.mjs", | |||
| "@threepipe/webgi-plugins": "https://unpkg.com/@threepipe/webgi-plugins@0.4.1/dist/index.mjs" | |||
| } | |||
| } | |||
| @@ -1,12 +1,12 @@ | |||
| { | |||
| "name": "@threepipe/plugin-assimpjs", | |||
| "version": "0.1.0", | |||
| "version": "0.2.0", | |||
| "lockfileVersion": 3, | |||
| "requires": true, | |||
| "packages": { | |||
| "": { | |||
| "name": "@threepipe/plugin-assimpjs", | |||
| "version": "0.1.0", | |||
| "version": "0.2.0", | |||
| "license": "Apache-2.0", | |||
| "dependencies": { | |||
| "assimpjs": "^0.0.10", | |||
| @@ -1,7 +1,7 @@ | |||
| { | |||
| "name": "@threepipe/plugin-assimpjs", | |||
| "description": "Assimp.js Plugin for ThreePipe", | |||
| "version": "0.1.0", | |||
| "version": "0.2.0", | |||
| "devDependencies": { | |||
| }, | |||
| "dependencies": { | |||
| @@ -51,7 +51,7 @@ | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git://github.com/repalash/threepipe.git", | |||
| "directory": "plugins/plugin-template-vite" | |||
| "directory": "plugins/assimpjs" | |||
| }, | |||
| "clean-package": { | |||
| "remove": [ | |||
| @@ -1,4 +1,11 @@ | |||
| import {AViewerPluginSync, ThreeViewer, getUrlQueryParam, createScriptFromURL} from 'threepipe' | |||
| import { | |||
| AViewerPluginSync, | |||
| ThreeViewer, | |||
| getUrlQueryParam, | |||
| createScriptFromURL, | |||
| IObject3D, | |||
| ExportFileOptions, uiButton, uiToggle, PickingPlugin, uiFolderContainer, | |||
| } from 'threepipe' | |||
| interface AssimpJsInterface{ | |||
| [key: string]: any | |||
| @@ -12,18 +19,23 @@ interface AssimpJsInterface{ | |||
| * Assimpjs - https://github.com/kovacsv/assimpjs | |||
| * Fork with a custom build to support fbx export - https://github.com/repalash/assimpjs | |||
| */ | |||
| @uiFolderContainer('Assimp') | |||
| export class AssimpJsPlugin extends AViewerPluginSync { | |||
| public static readonly PluginType: string = 'SamplePlugin' | |||
| enabled = true | |||
| dependencies = [] | |||
| initOnAdd: boolean | |||
| // public static LIBRARY_PATH = `https://cdn.jsdelivr.net/npm/assimpjs@${getUrlQueryParam('assimpjs', '0.0.10')}/` | |||
| // adds fbx export support | |||
| public static LIBRARY_PATH = `https://cdn.jsdelivr.net/gh/repalash/assimpjs@${getUrlQueryParam('assimpjs', 'main')}/` | |||
| constructor() { | |||
| constructor(initOnAdd = true) { | |||
| super() | |||
| this.initOnAdd = initOnAdd | |||
| } | |||
| protected _scriptElement?: HTMLScriptElement | |||
| private _initing: Promise<void>|undefined | |||
| @@ -57,8 +69,6 @@ export class AssimpJsPlugin extends AViewerPluginSync { | |||
| } | |||
| ajs?: AssimpJsInterface | |||
| initOnAdd = true | |||
| onAdded(viewer: ThreeViewer) { | |||
| super.onAdded(viewer) | |||
| if (this.initOnAdd) this.init() | |||
| @@ -93,4 +103,49 @@ export class AssimpJsPlugin extends AViewerPluginSync { | |||
| const blob = new Blob([resultFile.GetContent()], {type: 'application/octet-stream'}) | |||
| return blob | |||
| } | |||
| async exportModel(format: 'fbx'|'gltf2'|'glb2'|'assjson' = 'glb2', object?: IObject3D, options: ExportFileOptions = {embedUrlImages: true}) { | |||
| if (!this._viewer) { | |||
| console.error('AssimpJsPlugin - No viewer attached, please add the plugin to a viewer instance.') | |||
| return | |||
| } | |||
| const initing = this.init() | |||
| const selected = this.exportSelected ? this._viewer.getPlugin(PickingPlugin)?.getSelectedObject() : undefined | |||
| object = object || selected || this._viewer.scene.modelRoot | |||
| // export to glb | |||
| const blob = await this._viewer.export(object, options) | |||
| if (!blob || blob.ext !== 'glb') { | |||
| console.error('AssimpJsPlugin - Unable to export model, no blob returned.') | |||
| return | |||
| } | |||
| await initing // wait for assimp.js to be initialized | |||
| const blob2 = this.convertFiles({['file.glb']: await blob.arrayBuffer()}, format) | |||
| if (!blob2) { | |||
| console.error('AssimpJsPlugin - Unable to convert model to format:', format) | |||
| return | |||
| } | |||
| // convert to ArrayBuffer | |||
| return new File([blob2], 'model.' + format.replace(/2$/, ''), {type: 'application/octet-stream'}) | |||
| } | |||
| @uiToggle('Export Selected') | |||
| exportSelected = true | |||
| @uiButton('Download FBX') | |||
| async exportAsFbx(object?: IObject3D) { | |||
| if (!object?.isObject3D) object = undefined | |||
| const blob = await this.exportModel('fbx', object) | |||
| if (blob) { | |||
| await this._viewer?.exportBlob(blob, blob.name) | |||
| } | |||
| } | |||
| @uiButton('Download Assimp JSON') | |||
| async exportAsGlb(object?: IObject3D) { | |||
| if (!object?.isObject3D) object = undefined | |||
| const blob = await this.exportModel('assjson', object) | |||
| if (blob) { | |||
| await this._viewer?.exportBlob(blob, blob.name) | |||
| } | |||
| } | |||
| } | |||
| @@ -16,6 +16,8 @@ This package exports [AssimpJsPlugin](https://threepipe.org/plugins/assimpjs/doc | |||
| [](https://www.npmjs.com/package/@threepipe/plugin-assimpjs) | |||
| This package uses a custom fork of [assimpjs](https://github.com/kovacsv/assimpjs) with custom build to support fbx export etc - https://github.com/repalash/assimpjs | |||
| ```bash | |||
| npm install @threepipe/plugin-assimpjs | |||
| ``` | |||
| @@ -72,17 +74,10 @@ await assimp.init() // load the assimpjs library and wait for it to be ready. It | |||
| // load some models | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf') | |||
| // export to glb | |||
| const blob = await viewer.export(result, { | |||
| const fbxBlob = await assimp.exportModel('fbx', result, { | |||
| embedUrlImages: true, | |||
| }) | |||
| fbxBlob = assimp.convertFiles({['file.glb']: await blob.arrayBuffer()}, 'fbx') | |||
| if (!fbxBlob) { | |||
| console.error('Failed to convert files to fbx') | |||
| return | |||
| } | |||
| // download the fbx file | |||
| downloadBlob(fbxBlob, 'model.fbx') | |||
| ``` | |||