@threepipe/plugin-gltf-transform 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,8 +1,19 @@
1
1
  {
2
2
  "name": "@threepipe/plugin-gltf-transform",
3
3
  "description": "Utility plugins for threepipe using gltf-transform to optimize/compress glTF files.",
4
- "version": "0.1.0",
4
+ "version": "0.1.3",
5
5
  "dependencies": {},
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.mjs",
10
+ "require": "./dist/index.js"
11
+ },
12
+ "./dist/": {
13
+ "import": "./dist/",
14
+ "require": "./dist/"
15
+ }
16
+ },
6
17
  "type": "module",
7
18
  "main": "dist/index.js",
8
19
  "module": "dist/index.mjs",
@@ -26,9 +37,10 @@
26
37
  "homepage": "https://github.com/repalash/threepipe#readme",
27
38
  "repository": {
28
39
  "type": "git",
29
- "url": "git://github.com/repalash/threepipe.git"
40
+ "url": "git://github.com/repalash/threepipe.git",
41
+ "directory": "plugins/gltf-transform"
30
42
  },
31
43
  "peerDependencies": {
32
- "threepipe": "^0.0.32"
44
+ "threepipe": "^0.0.39"
33
45
  }
34
46
  }
@@ -1,8 +1,6 @@
1
1
  import {
2
2
  AssetExporterPlugin,
3
3
  AViewerPluginSync,
4
- ClearcoatTintPlugin,
5
- CustomBumpMapPlugin,
6
4
  DRACOLoader2,
7
5
  generateUUID,
8
6
  GLTFLightExtrasExtension,
@@ -12,8 +10,12 @@ import {
12
10
  GLTFMaterialsDisplacementMapExtension,
13
11
  GLTFMaterialsLightMapExtension,
14
12
  GLTFObject3DExtrasExtension,
15
- NoiseBumpMaterialPlugin,
13
+ IExporter,
16
14
  ThreeViewer,
15
+ clearCoatTintGLTFExtension,
16
+ customBumpMapGLTFExtension,
17
+ noiseBumpMaterialGLTFExtension,
18
+ fragmentClippingGLTFExtension,
17
19
  } from 'threepipe'
18
20
  import {GLTFDracoExporter} from './GLTFDracoExporter'
19
21
  import {UiObjectConfig} from 'uiconfig.js'
@@ -32,62 +34,92 @@ export enum EncoderMethod {
32
34
  *
33
35
  * @category Plugins
34
36
  */
35
- export class GLTFDracoExportPlugin extends AViewerPluginSync<''> {
37
+ export class GLTFDracoExportPlugin extends AViewerPluginSync {
36
38
  public static readonly PluginType = 'GLTFDracoExportPlugin'
37
39
  enabled = true
38
40
 
41
+ /**
42
+ * These are added here, but also added as plugins. Added here by default so that the data is not lost if some plugin is not added in an app.
43
+ * To explicitly remove the data, use `removeExtension` with the name of the extension
44
+ */
45
+ extraExtensions = [
46
+ [GLTFMaterialsBumpMapExtension.WebGiMaterialsBumpMapExtension, GLTFMaterialsBumpMapExtension.Textures],
47
+ [GLTFMaterialsLightMapExtension.WebGiMaterialsLightMapExtension, GLTFMaterialsLightMapExtension.Textures],
48
+ [GLTFMaterialsAlphaMapExtension.WebGiMaterialsAlphaMapExtension, GLTFMaterialsAlphaMapExtension.Textures],
49
+ [GLTFMaterialsDisplacementMapExtension.WebGiMaterialsDisplacementMapExtension, GLTFMaterialsDisplacementMapExtension.Textures],
50
+ [customBumpMapGLTFExtension.name, customBumpMapGLTFExtension.textures],
51
+ [GLTFLightExtrasExtension.WebGiLightExtrasExtension, GLTFLightExtrasExtension.Textures],
52
+ [GLTFObject3DExtrasExtension.WebGiObject3DExtrasExtension, GLTFObject3DExtrasExtension.Textures],
53
+ [GLTFMaterialExtrasExtension.WebGiMaterialExtrasExtension, GLTFMaterialExtrasExtension.Textures],
54
+ [clearCoatTintGLTFExtension.name, clearCoatTintGLTFExtension.textures],
55
+ [noiseBumpMaterialGLTFExtension.name, noiseBumpMaterialGLTFExtension.textures],
56
+ [fragmentClippingGLTFExtension.name, fragmentClippingGLTFExtension.textures],
57
+
58
+ // extenal plugins
59
+
60
+ // AnisotropyMaterialExtension
61
+ ['WEBGI_materials_anisotropy', {
62
+ anisotropyDirection: 'RGB',
63
+ }],
64
+ // todo port
65
+ // DiamondMaterialExtension
66
+ // AnimationMarkersExtension
67
+ // ThinFilmLayerMaterialExtension
68
+ // TriplanarMappingMaterialExtension
69
+ // SSBevelMaterialExtension
70
+ ] as [string, Record<string, string|number>|undefined][]
71
+
72
+ addExtension(name: string, textures?: Record<string, string|number>) {
73
+ const ext = this.extraExtensions.findIndex(e => e[0] === name)
74
+ if (ext >= 0) this.extraExtensions[ext] = [name, textures]
75
+ else this.extraExtensions.push([name, textures])
76
+ }
77
+
78
+ /**
79
+ * Note - don't remove an extension when removing a plugin.
80
+ *
81
+ * extensions can be removed if you don't want to save the data of some plugin when transforming glb. But since this is not desirable in most cases, it is not recommended.
82
+ * @param name
83
+ */
84
+ removeExtension(name: string) {
85
+ const ext = this.extraExtensions.findIndex(e => e[0] === name)
86
+ if (ext >= 0) this.extraExtensions.splice(ext, 1)
87
+ }
88
+
89
+ private _lastExporter?: IExporter['ctor'] = undefined
90
+
91
+ protected _ctor: IExporter['ctor'] = (_, _exporter) => {
92
+ if (!this._viewer) throw new Error('Viewer not set')
93
+ const tempFile = generateUUID() + '.drc' // dummy
94
+ const ex = new GLTFDracoExporter({},
95
+ // todo unregister on dispose
96
+ this._viewer.assetManager.importer.registerFile(tempFile) as DRACOLoader2)
97
+ ex.setup(this._viewer, _exporter.extensions)
98
+ for (const [ext, config] of this.extraExtensions) {
99
+ ex.createAndAddExtension(ext, config)
100
+ }
101
+ return ex
102
+ }
103
+
39
104
  onAdded(viewer: ThreeViewer): void {
40
105
  super.onAdded(viewer)
41
- const importer = viewer.assetManager.importer
42
106
  const exporter = viewer.assetManager.exporter
43
107
 
44
- const glbExporter = exporter.getExporter('glb')
45
- if (glbExporter) exporter.removeExporter(glbExporter)
46
-
47
- // todo remove exporter and add back the old one on plugin remove.
48
- exporter.addExporter({
49
- ...glbExporter || {
108
+ let glbExporter = exporter.getExporter('glb')
109
+ this._lastExporter = glbExporter?.ctor
110
+ if (!glbExporter) {
111
+ console.error('GLTFDracoExportPlugin: GLB exporter not found in AssetManager.exporter, creating a new one.')
112
+ glbExporter = {
50
113
  ext: ['glb', 'gltf'],
51
114
  extensions: [],
52
- }, // for extensions
53
- ctor: (_, _exporter) => {
54
- const tempFile = generateUUID() + '.drc' // dummy
55
- const ex = new GLTFDracoExporter({},
56
- // todo unregister on dispose
57
- importer.registerFile(tempFile) as DRACOLoader2)
58
- ex.setup(viewer, _exporter.extensions)
59
- ex.createAndAddExtension(GLTFMaterialsBumpMapExtension.WebGiMaterialsBumpMapExtension, {
60
- bumpTexture: 'R',
61
- })
62
- ex.createAndAddExtension(GLTFMaterialsLightMapExtension.WebGiMaterialsLightMapExtension, {
63
- lightMapTexture: 'RGB',
64
- })
65
- ex.createAndAddExtension(GLTFMaterialsAlphaMapExtension.WebGiMaterialsAlphaMapExtension, {
66
- alphaTexture: 'G',
67
- })
68
- ex.createAndAddExtension(GLTFMaterialsDisplacementMapExtension.WebGiMaterialsDisplacementMapExtension, {
69
- displacementTexture: 'R',
70
- })
71
- ex.createAndAddExtension(CustomBumpMapPlugin.CUSTOM_BUMP_MAP_GLTF_EXTENSION, {
72
- customBumpMap: 'RGB',
73
- })
74
- ex.createAndAddExtension(GLTFLightExtrasExtension.WebGiLightExtrasExtension)
75
- ex.createAndAddExtension(GLTFObject3DExtrasExtension.WebGiObject3DExtrasExtension)
76
- ex.createAndAddExtension(GLTFMaterialExtrasExtension.WebGiMaterialExtrasExtension)
77
- ex.createAndAddExtension(ClearcoatTintPlugin.CLEARCOAT_TINT_GLTF_EXTENSION)
78
- ex.createAndAddExtension(NoiseBumpMaterialPlugin.NOISE_BUMP_MATERIAL_GLTF_EXTENSION)
79
- // todo port
80
- // DiamondMaterialExtension
81
- // AnimationMarkersExtension
82
- // AnisotropyMaterialExtension
83
- // ThinFilmLayerMaterialExtension
84
- // TriplanarMappingMaterialExtension
85
- // SSBevelMaterialExtension
86
- return ex
87
- },
88
- })
115
+ ctor: this._ctor,
116
+ }
117
+ exporter.addExporter(glbExporter)
118
+ } else {
119
+ glbExporter.ctor = this._ctor
120
+ }
89
121
 
90
- // for ui
122
+ // for ui. todo use viewer.forPlugin
91
123
  const exportPlugin = viewer.getPlugin(AssetExporterPlugin)
92
124
  if (exportPlugin) {
93
125
  Object.assign(exportPlugin.exportOptions, {
@@ -114,6 +146,15 @@ export class GLTFDracoExportPlugin extends AViewerPluginSync<''> {
114
146
  }
115
147
  }
116
148
 
149
+ onRemove(viewer: ThreeViewer) {
150
+ const exporter = viewer.assetManager.exporter
151
+ const glbExporter = exporter.getExporter('glb')
152
+ if (glbExporter && this._lastExporter) {
153
+ glbExporter.ctor = this._lastExporter
154
+ }
155
+ super.onRemove(viewer)
156
+ }
157
+
117
158
  protected _makeUi = (exporter: AssetExporterPlugin)=>[
118
159
  {
119
160
  type: 'checkbox',
@@ -67,7 +67,7 @@ export class GLTFDracoExporter extends GLTFExporter2 implements IExportParser {
67
67
 
68
68
  }
69
69
 
70
- async parseAsync(obj: any, {compress = false, dracoOptions, ...options}: {compress: boolean, dracoOptions?: EncoderOptions} & GLTFExporter2Options): Promise<Blob> {
70
+ async parseAsync(obj: any, {compress = false, dracoOptions, ...options}: {compress: boolean, dracoOptions?: EncoderOptions} & GLTFExporter2Options, throwOnError = false): Promise<Blob> {
71
71
  if (!this.loader) {
72
72
  console.error('GLTFDracoExporter: No DRACOLoader2 instance provided')
73
73
  return super.parseAsync(obj, options)
@@ -86,42 +86,49 @@ export class GLTFDracoExporter extends GLTFExporter2 implements IExportParser {
86
86
  const uncompressedBlob = await super.parseAsync(uncompressed, ops)
87
87
  if (!compress) return uncompressedBlob
88
88
 
89
- if (!uncompressed) throw new Error('GLTFDracoExporter: gltf is null')
89
+ try {
90
+ if (!uncompressed) throw new Error('GLTFDracoExporter: gltf is null')
90
91
 
91
- let gltf = uncompressed
92
+ let gltf = uncompressed
92
93
 
93
- const bytes = (gltf as ArrayBuffer).byteLength || Infinity
94
+ const bytes = (gltf as ArrayBuffer).byteLength || Infinity
94
95
 
95
- const iDocument = await (typeof gltf === 'object' && !(gltf as any).byteLength ? this._io.readJSON({
96
- json: gltf as GLTF.IGLTF,
97
- resources: {},
98
- }) : this._io.readBinary(new Uint8Array(gltf as ArrayBuffer)))
96
+ const iDocument = await (typeof gltf === 'object' && !(gltf as any).byteLength ? this._io.readJSON({
97
+ json: gltf as GLTF.IGLTF,
98
+ resources: {},
99
+ }) : this._io.readBinary(new Uint8Array(gltf as ArrayBuffer)))
99
100
 
100
- // iDocument.createExtension(GLTFViewerConfigExtensionGP)
101
- iDocument.createExtension(KHRDracoMeshCompression)
102
- .setRequired(true)
103
- .setEncoderOptions({...this._encoderOptions, ...dracoOptions ?? {}})
101
+ // iDocument.createExtension(GLTFViewerConfigExtensionGP)
102
+ iDocument.createExtension(KHRDracoMeshCompression)
103
+ .setRequired(true)
104
+ .setEncoderOptions({...this._encoderOptions, ...dracoOptions ?? {}})
104
105
 
105
- if (ops.exportExt === 'glb') {
106
- gltf = await this._io.writeBinary(iDocument)
107
- if (isFinite(bytes)) {
108
- console.log('DRACO Compression ratio: ' + ((gltf as ArrayBuffer).byteLength / bytes).toFixed(5))
109
- }
110
- } else {
111
- const jDoc = await this._io.writeJSON(iDocument)
112
- gltf = jDoc.json
113
- if (Object.values(jDoc.resources).filter(v => v).length > 0) {
114
- console.warn('DRACOExporter: extra resources in resources not supported properly')
115
- ;(gltf as any).resources = jDoc.resources
106
+ if (ops.exportExt === 'glb') {
107
+ gltf = await this._io.writeBinary(iDocument)
108
+ if (isFinite(bytes)) {
109
+ console.log('DRACO Compression ratio: ' + ((gltf as ArrayBuffer).byteLength / bytes).toFixed(5))
110
+ }
111
+ } else {
112
+ const jDoc = await this._io.writeJSON(iDocument)
113
+ gltf = jDoc.json
114
+ if (Object.values(jDoc.resources).filter(v => v).length > 0) {
115
+ console.warn('DRACOExporter: extra resources in resources not supported properly')
116
+ ;(gltf as any).resources = jDoc.resources
117
+ }
116
118
  }
117
- }
118
119
 
119
- gltf.__isGLTFOutput = true
120
- const blob = await super.parseAsync(gltf, ops) as any // this will just convert it to blob because __isGLTFOutput is set (checked in GLTFExporter2)
121
- if (!blob) throw new Error('GLTFDracoExporter: blob is null')
122
- blob.ext = 'glb'
123
- ;(blob as any).__uncompressed = uncompressedBlob
124
- return blob
120
+ gltf.__isGLTFOutput = true
121
+ const blob = await super.parseAsync(gltf, ops) as any // this will just convert it to blob because __isGLTFOutput is set (checked in GLTFExporter2)
122
+ if (!blob) throw new Error('GLTFDracoExporter: blob is null')
123
+ blob.ext = 'glb'
124
+ ;(blob as any).__uncompressed = uncompressedBlob
125
+ return blob
126
+ } catch (e) {
127
+ if (throwOnError) throw e
128
+ console.error('Unable to compress glb with DRACO extension, fallback to uncompressed')
129
+ console.error(e)
130
+ return uncompressedBlob
131
+ }
125
132
  }
126
133
 
127
134
  addExtension(extension: typeof Extension): this {