@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/dist/GLTFDracoExportPlugin.d.ts +19 -3
- package/dist/GLTFDracoExportPlugin.d.ts.map +1 -1
- package/dist/GLTFDracoExporter.d.ts +1 -1
- package/dist/GLTFDracoExporter.d.ts.map +1 -1
- package/dist/dependencies.txt +0 -3
- package/dist/index.js +439 -665
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +440 -666
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -3
- package/src/GLTFDracoExportPlugin.ts +90 -49
- package/src/GLTFDracoExporter.ts +37 -30
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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',
|
package/src/GLTFDracoExporter.ts
CHANGED
|
@@ -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
|
-
|
|
89
|
+
try {
|
|
90
|
+
if (!uncompressed) throw new Error('GLTFDracoExporter: gltf is null')
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
let gltf = uncompressed
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
const bytes = (gltf as ArrayBuffer).byteLength || Infinity
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
// iDocument.createExtension(GLTFViewerConfigExtensionGP)
|
|
102
|
+
iDocument.createExtension(KHRDracoMeshCompression)
|
|
103
|
+
.setRequired(true)
|
|
104
|
+
.setEncoderOptions({...this._encoderOptions, ...dracoOptions ?? {}})
|
|
104
105
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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 {
|