threepipe
Version:
A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.
77 lines (65 loc) • 3.41 kB
text/typescript
import type {GLTF, GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader.js'
import type {Object3D} from 'three'
import type {GLTFExporterPlugin, GLTFWriter} from 'three/examples/jsm/exporters/GLTFExporter.js'
export class GLTFObject3DExtrasExtension {
static readonly WebGiObject3DExtrasExtension = 'WEBGI_object3d_extras'
/**
* Also {@link Export}
* @param _
*/
static Import = (_: GLTFParser): GLTFLoaderPlugin =>({
name: '__' + this.WebGiObject3DExtrasExtension, // __ is prefix so that the extension is added to userdata, and we can process later in afterRoot
afterRoot: async(result: GLTF) => {
const scenes = result.scenes || (result.scene ? [result.scene] : [])
scenes.forEach(s=>{
s.traverse((o: any)=>{
if (!o || !o.isObject3D) return
const ext = o.userData?.gltfExtensions?.[this.WebGiObject3DExtrasExtension]
if (!ext) {
if (o.isLight && !o.isAmbientLight) o.castShadow = true
return
}
// if this extension is set, we use default (false) if not seet in ext. see the Export func.
const hasShadowDef = true
o.castShadow = ext.castShadow ?? false
o.receiveShadow = ext.receiveShadow ?? false
if (ext.visible !== undefined) o.visible = ext.visible
if (ext.frustumCulled !== undefined) o.frustumCulled = ext.frustumCulled
if (ext.renderOrder !== undefined) o.renderOrder = ext.renderOrder
// if (ext.userData !== undefined) o.userData = ext.userData
if (ext.layers !== undefined) o.layers.mask = ext.layers
if (hasShadowDef) {
o.userData.__keepShadowDef = true
}
delete o.userData.gltfExtensions[this.WebGiObject3DExtrasExtension]
})
})
},
})
/**
* Also {@link Import}
* @param w
* @constructor
*/
static Export = (w: GLTFWriter): GLTFExporterPlugin => ({
writeNode: (object: Object3D, nodeDef: any)=>{
if (!object?.isObject3D) return
if (!nodeDef.extensions) nodeDef.extensions = {}
const dat: any = {}
// non-default stuff from ObjectLoader.js
if (object.castShadow !== undefined && object.castShadow) dat.castShadow = object.castShadow
if (object.receiveShadow !== undefined && object.receiveShadow) dat.receiveShadow = object.receiveShadow
if (object.visible === false) dat.visible = false
if (object.frustumCulled === false) dat.frustumCulled = false
if (object.renderOrder !== 0) dat.renderOrder = object.renderOrder
if (object.layers.mask !== 1) dat.layers = object.layers.mask
if (object.matrixAutoUpdate === false) dat.matrixAutoUpdate = false
if (Object.keys(dat).length > 0) {
nodeDef.extensions[this.WebGiObject3DExtrasExtension] = dat
w.extensionsUsed[this.WebGiObject3DExtrasExtension] = true
}
},
})
// see GLTFDracoExportPlugin
static Textures: Record<string, string|number>|undefined = undefined
}