From 2e1cc5905b0fd62e4085e83c46cd32cc7d4f7b77 Mon Sep 17 00:00:00 2001 From: pissang Date: Mon, 2 May 2022 15:54:00 +0800 Subject: [PATCH] wip(type): fix gltf loader --- src/Node.ts | 2 +- src/claygl.ts | 16 +++++++++++++- src/loader/GLTF.ts | 42 ++++++++++++++++++++++++++---------- src/plugin/FreeControl.ts | 7 +++++- src/plugin/GamepadControl.ts | 10 ++++++--- src/plugin/OrbitControl.ts | 10 ++++++++- src/plugin/Skydome.ts | 3 --- src/prePass/ShadowMap.ts | 2 +- src/util/texture.ts | 4 ++-- 9 files changed, 72 insertions(+), 24 deletions(-) delete mode 100644 src/plugin/Skydome.ts diff --git a/src/Node.ts b/src/Node.ts index 262cfb85..b43a46d8 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -597,7 +597,7 @@ class ClayNode extends Notifier { * @see http://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml * @function */ - lookAt(target: Vector3, up: Vector3) { + lookAt(target: Vector3, up?: Vector3) { tmpMat4.lookAt(this.position, target, up || this.localTransform.y).invert(); this.setLocalTransform(tmpMat4); diff --git a/src/claygl.ts b/src/claygl.ts index 1267be9a..c1cfb4ba 100644 --- a/src/claygl.ts +++ b/src/claygl.ts @@ -54,4 +54,18 @@ export { StandardMRShader } from './shader/index'; -export { load as loadGLTF } from './loader/GLTF'; +export { + load as loadGLTF, + loadAsync as loadGLTFAsync, + parse as parseGLTF, + parseBinary as parseGLB +} from './loader/GLTF'; + +export { default as ShadowMapPass } from './prePass/ShadowMap'; +export { default as EnvironmentMapPass } from './prePass/EnvironmentMap'; + +export { default as OrbitControl } from './plugin/OrbitControl'; +export { default as FreeControl } from './plugin/FreeControl'; +export { default as GamepadControl } from './plugin/GamepadControl'; + +export { default as Skybox } from './plugin/Skybox'; diff --git a/src/loader/GLTF.ts b/src/loader/GLTF.ts index ddacd611..dcea390c 100644 --- a/src/loader/GLTF.ts +++ b/src/loader/GLTF.ts @@ -244,6 +244,26 @@ interface GLTFLoadOpts { onprogress?: (percent: number, loaded: number, total: number) => void; } +// Load with promise +export function loadAsync( + url: string, + opts?: Omit +): Promise { + return new Promise((resolve, reject) => { + load( + url, + Object.assign({}, opts, { + onload(res: GLTFLoadResult) { + resolve(res); + }, + onerror(err: any) { + reject(err); + } + }) + ); + }); +} + export function load(url: string, opts?: GLTFLoadOpts) { opts = Object.assign( { @@ -382,7 +402,7 @@ export function parse(json: GLTFFormat, buffers: ArrayBuffer[] | undefined, opts afterLoadBuffer(true); } else { // Load buffers - json.buffers.forEach((bufferInfo: GLTFBuffer, idx: number) => { + (json.buffers || []).forEach((bufferInfo: GLTFBuffer, idx: number) => { loading++; const path = bufferInfo.uri; @@ -422,7 +442,7 @@ export function parse(json: GLTFFormat, buffers: ArrayBuffer[] | undefined, opts return; } - json.bufferViews.forEach((bufferViewInfo: GLTFBufferView, idx: number) => { + (json.bufferViews || []).forEach((bufferViewInfo: GLTFBufferView, idx: number) => { // PENDING Performance lib.bufferViews[idx] = lib.buffers[bufferViewInfo.buffer].slice( bufferViewInfo.byteOffset || 0, @@ -523,7 +543,7 @@ function loadBuffers( // https://github.com/KhronosGroup/glTF/issues/193 function parseSkins(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { // Create skeletons and joints - json.skins.forEach((skinInfo: GLTFSkin, idx: number) => { + (json.skins || []).forEach((skinInfo: GLTFSkin, idx: number) => { const skeleton = new Skeleton(skinInfo.name); for (let i = 0; i < skinInfo.joints.length; i++) { const nodeIdx = skinInfo.joints[i]; @@ -561,7 +581,7 @@ function parseSkins(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { return joint.index; } - json.nodes.forEach((nodeInfo: GLTFNode, nodeIdx: number) => { + (json.nodes || []).forEach((nodeInfo: GLTFNode, nodeIdx: number) => { if (nodeInfo.skin != null) { const skinIdx = nodeInfo.skin; const skeleton = lib.skeletons[skinIdx]; @@ -582,7 +602,7 @@ function parseSkins(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { } function parseTextures(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { - json.textures.forEach((textureInfo: GLTFTexture, idx: number) => { + (json.textures || []).forEach((textureInfo: GLTFTexture, idx: number) => { // samplers is optional const samplerInfo = (json.samplers && json.samplers[textureInfo.sampler]) || {}; const parameters: Partial = {}; @@ -945,7 +965,7 @@ function pbrSpecularGlossinessToStandard( } function parseMaterials(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { - json.materials.forEach((materialInfo: GLTFMaterial, idx: number) => { + (json.materials || []).forEach((materialInfo: GLTFMaterial, idx: number) => { /* eslint-disable-next-line */ if (materialInfo.extensions && materialInfo.extensions['KHR_materials_common']) { lib.materials[idx] = KHRCommonMaterialToStandard(materialInfo, lib, opts); @@ -973,7 +993,7 @@ function parseMaterials(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { } function parseMeshes(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { - json.meshes.forEach((meshInfo: GLTFMesh, idx: number) => { + (json.meshes || []).forEach((meshInfo: GLTFMesh, idx: number) => { lib.meshes[idx] = []; // Geometry for (let pp = 0; pp < meshInfo.primitives.length; pp++) { @@ -1154,7 +1174,7 @@ function parseNodes(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { }); } - json.nodes.forEach((nodeInfo: GLTFNode, idx: number) => { + (json.nodes || []).forEach((nodeInfo: GLTFNode, idx: number) => { let node: ClayNode; if (nodeInfo.camera != null && opts.includeCamera) { node = instanceCamera(json, nodeInfo); @@ -1201,7 +1221,7 @@ function parseNodes(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { }); // Build hierarchy - json.nodes.forEach((nodeInfo: GLTFNode, idx: number) => { + (json.nodes || []).forEach((nodeInfo: GLTFNode, idx: number) => { const node = lib.nodes[idx]; if (nodeInfo.children) { for (let i = 0; i < nodeInfo.children.length; i++) { @@ -1227,7 +1247,7 @@ function parseAnimations(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { } const timeAccessorMultiplied: Record = {}; - json.animations.forEach((animationInfo: GLTFAnimation, idx: number) => { + (json.animations || []).forEach((animationInfo: GLTFAnimation, idx: number) => { const channels = animationInfo.channels.filter(checkChannelPath); if (!channels.length) { @@ -1289,7 +1309,7 @@ function parseAnimations(json: GLTFFormat, lib: ParsedLib, opts: GLTFLoadOpts) { const maxLife = lib.animators.reduce(function (maxTime, animator) { return Math.max(maxTime, animator.getLife()); }, 0); - lib.animators.forEach(function (animator) { + (lib.animators || []).forEach(function (animator) { animator.setLife(maxLife); }); diff --git a/src/plugin/FreeControl.ts b/src/plugin/FreeControl.ts index 90a08e0a..86162fb3 100644 --- a/src/plugin/FreeControl.ts +++ b/src/plugin/FreeControl.ts @@ -70,8 +70,13 @@ class FreeControl extends Notifier { private _offsetPitch = 0; private _offsetRoll = 0; - constructor(opts?: Partial) { + constructor( + opts: Omit, 'domElement'> & { + domElement: HTMLElement; + } + ) { super(); + Object.assign( this, { diff --git a/src/plugin/GamepadControl.ts b/src/plugin/GamepadControl.ts index ffd5b869..e22e2868 100644 --- a/src/plugin/GamepadControl.ts +++ b/src/plugin/GamepadControl.ts @@ -37,12 +37,12 @@ interface GamepadControlOpts { /** * Function to be called when a standard gamepad is ready to use. */ - onStandardGamepadReady?: (gamepad) => void; + onStandardGamepadReady?: (gamepad: Gamepad) => void; /** * Function to be called when a gamepad is disconnected. */ - onGamepadDisconnected?: (gamepad) => void; + onGamepadDisconnected?: (gamepad: Gamepad) => void; } interface GamepadControl extends GamepadControlOpts {} @@ -75,7 +75,11 @@ class GamepadControl extends Notifier { private _standardGamepadAvailable = false; private _gamepadAxisThreshold = 0.3; - constructor(opts?: Partial) { + constructor( + opts: Omit, 'domElement'> & { + domElement: HTMLElement; + } + ) { super(); Object.assign( this, diff --git a/src/plugin/OrbitControl.ts b/src/plugin/OrbitControl.ts index 233f9372..54cb85ed 100644 --- a/src/plugin/OrbitControl.ts +++ b/src/plugin/OrbitControl.ts @@ -170,9 +170,15 @@ class OrbitControl extends Notifier { private _gestureMgr = new GestureMgr(); - constructor(opts?: Partial) { + constructor( + opts: Omit, 'domElement'> & { + domElement: HTMLElement; + } + ) { super(); + this.domElement = opts.domElement; + this.setOption( Object.assign( { @@ -200,6 +206,8 @@ class OrbitControl extends Notifier { opts ) ); + // Set target after option updated. + this._target = opts.target; // Each OrbitControl has it's own handler this._mouseDownHandler = this._mouseDownHandler.bind(this); diff --git a/src/plugin/Skydome.ts b/src/plugin/Skydome.ts deleted file mode 100644 index 5000ca19..00000000 --- a/src/plugin/Skydome.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Skybox from './Skybox'; - -export default Skybox; diff --git a/src/prePass/ShadowMap.ts b/src/prePass/ShadowMap.ts index 65efb29e..56dd28e0 100644 --- a/src/prePass/ShadowMap.ts +++ b/src/prePass/ShadowMap.ts @@ -142,7 +142,7 @@ class ShadowMapPass extends Notifier { /** * Render scene to shadow textures */ - render(renderer: Renderer, scene: Scene, sceneCamera: Camera, notUpdateScene?: boolean) { + render(renderer: Renderer, scene: Scene, sceneCamera?: Camera, notUpdateScene?: boolean) { if (!sceneCamera) { sceneCamera = scene.getMainCamera(); } diff --git a/src/util/texture.ts b/src/util/texture.ts index ed2402cf..c437fd77 100644 --- a/src/util/texture.ts +++ b/src/util/texture.ts @@ -3,7 +3,7 @@ import Texture2D from '../Texture2D'; import TextureCube from '../TextureCube'; import vendor from '../core/vendor'; import EnvironmentMapPass from '../prePass/EnvironmentMap'; -import Skydome from '../plugin/Skydome'; +import Skybox from '../plugin/Skybox'; import Scene from '../Scene'; import dds from './dds'; @@ -121,7 +121,7 @@ const textureUtil = { */ panoramaToCubeMap: function (renderer, panoramaMap, cubeMap, option) { const environmentMapPass = new EnvironmentMapPass(); - const skydome = new Skydome({ + const skydome = new Skybox({ scene: new Scene() }); skydome.setEnvironmentMap(panoramaMap);