From 0fcb02a95bb125209cf84d76fa08a43fd3fdbbe1 Mon Sep 17 00:00:00 2001 From: zhuxudong Date: Thu, 31 Aug 2023 15:23:33 +0800 Subject: [PATCH] fix: glTF parser error and test case --- .../src/gltf/parser/GLTFEntityParser.ts | 4 +- .../loader/src/gltf/parser/GLTFSceneParser.ts | 4 +- tests/src/loader/GLTFLoader.test.ts | 528 +++++++++--------- 3 files changed, 275 insertions(+), 261 deletions(-) diff --git a/packages/loader/src/gltf/parser/GLTFEntityParser.ts b/packages/loader/src/gltf/parser/GLTFEntityParser.ts index c667c3130a..b722a27b20 100644 --- a/packages/loader/src/gltf/parser/GLTFEntityParser.ts +++ b/packages/loader/src/gltf/parser/GLTFEntityParser.ts @@ -8,7 +8,7 @@ export class GLTFEntityParser extends GLTFParser { parse(context: GLTFParserContext, index: number): Entity { const entityInfo = context.glTF.nodes[index]; const engine = context.glTFResource.engine; - const { matrix, translation, rotation, scale } = entityInfo; + const { matrix, translation, rotation, scale, extensions } = entityInfo; const entity = new Entity(engine, entityInfo.name || `_GLTF_ENTITY_${index}`); const { transform } = entity; @@ -37,6 +37,8 @@ export class GLTFEntityParser extends GLTFParser { } } + GLTFParser.executeExtensionsAdditiveAndParse(extensions, context, entity, entityInfo); + return entity; } } diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts index 641c5bde65..7620c33613 100644 --- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts +++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts @@ -79,7 +79,7 @@ export class GLTFSceneParser extends GLTFParser { private _parseEntityComponent(context: GLTFParserContext, index: number): Promise { const { glTF, glTFResource } = context; const entityInfo = glTF.nodes[index]; - const { camera: cameraID, mesh: meshID, extensions } = entityInfo; + const { camera: cameraID, mesh: meshID } = entityInfo; const entity = context.get(GLTFParserType.Entity, index); let promise: Promise; @@ -101,8 +101,6 @@ export class GLTFSceneParser extends GLTFParser { } } - GLTFParser.executeExtensionsAdditiveAndParse(extensions, context, entity, entityInfo); - return Promise.all(promises); }); } diff --git a/tests/src/loader/GLTFLoader.test.ts b/tests/src/loader/GLTFLoader.test.ts index 8279169d6d..3247a3a52d 100644 --- a/tests/src/loader/GLTFLoader.test.ts +++ b/tests/src/loader/GLTFLoader.test.ts @@ -21,6 +21,7 @@ import { GLTFParser, GLTFParserContext, GLTFParserType, + GLTFSchemaParser, registerGLTFExtension, registerGLTFParser } from "@galacean/engine-loader"; @@ -34,294 +35,307 @@ before(async () => { canvasDOM.width = 1024; canvasDOM.height = 1024; engine = await WebGLEngine.create({ canvas: canvasDOM }); -}); -@registerGLTFParser(GLTFParserType.Schema) -class GLTFCustomJSONParser extends GLTFParser { - parse(context: GLTFParserContext) { - const glTF = { - bufferViews: [ - { - buffer: 0, - byteLength: 1000 - } - ], - accessors: [ - { - bufferView: 0, - byteOffset: 0, - componentType: 5126, - count: 3, - max: [2.0], - min: [0.0], - type: "SCALAR", - normalized: true + @registerGLTFParser(GLTFParserType.Schema) + class GLTFCustomJSONParser extends GLTFParser { + parse(context: GLTFParserContext) { + const glTF = { + buffers: [ + { + byteLength: 1000 + } + ], + bufferViews: [ + { + buffer: 0, + byteLength: 1000 + } + ], + accessors: [ + { + bufferView: 0, + byteOffset: 0, + componentType: 5126, + count: 3, + max: [2.0], + min: [0.0], + type: "SCALAR", + normalized: true + }, + { + bufferView: 0, + componentType: 5126, + count: 3, + type: "VEC3" + } + ], + images: [ + { + bufferView: 0, + mimeType: "image/jpeg" + } + ], + textures: [ + { + sampler: 0, + source: 0, + name: "test" + } + ], + samplers: [ + { + magFilter: 9729, + minFilter: 9986, + wrapS: 10497, + wrapT: 33648 + } + ], + asset: { + version: "2.0" }, - { - bufferView: 0, - componentType: 5126, - count: 3, - type: "VEC3" - } - ], - images: [ - { - bufferView: 0, - mimeType: "image/jpeg" - } - ], - textures: [ - { - sampler: 0, - source: 0, - name: "test" - } - ], - samplers: [ - { - magFilter: 9729, - minFilter: 9986, - wrapS: 10497, - wrapT: 33648 - } - ], - asset: { - version: "2.0" - }, - extensionsUsed: [ - "KHR_materials_unlit", - "KHR_materials_pbrSpecularGlossiness", - "KHR_materials_clearcoat", - "KHR_lights_punctual", - "Custom_Material", - "Custom_Light" - ], - extensionsRequired: [ - "KHR_materials_unlit", - "KHR_materials_pbrSpecularGlossiness", - "Custom_Material", - "Custom_Light" - ], - extensions: { - KHR_lights_punctual: { - lights: [ - { - color: [1, 0, 0], - intensity: 0.5, - type: "spot", - range: 20, - spot: { - innerConeAngle: Math.PI / 3, - outerConeAngle: Math.PI / 2 + extensionsUsed: [ + "KHR_materials_unlit", + "KHR_materials_pbrSpecularGlossiness", + "KHR_materials_clearcoat", + "KHR_lights_punctual", + "Custom_Material", + "Custom_Light" + ], + extensionsRequired: [ + "KHR_materials_unlit", + "KHR_materials_pbrSpecularGlossiness", + "Custom_Material", + "Custom_Light" + ], + extensions: { + KHR_lights_punctual: { + lights: [ + { + color: [1, 0, 0], + intensity: 0.5, + type: "spot", + range: 20, + spot: { + innerConeAngle: Math.PI / 3, + outerConeAngle: Math.PI / 2 + } } - } - ] - } - }, - nodes: [ - { - name: "entity1", - translation: [1, 0, 0], - rotation: [Math.PI, 0, 0, 0], - scale: [2, 2, 2], - extensions: { - KHR_lights_punctual: { - light: 0 - } + ] } }, - { - name: "entity2", - translation: [1, 0, 0], - rotation: [Math.PI, 0, 0, 0], - scale: [2, 2, 2], - mesh: 0, - extensions: { - Custom_Light: {} + nodes: [ + { + name: "entity1", + translation: [1, 0, 0], + rotation: [Math.PI, 0, 0, 0], + scale: [2, 2, 2], + extensions: { + KHR_lights_punctual: { + light: 0 + } + } + }, + { + name: "entity2", + translation: [1, 0, 0], + rotation: [Math.PI, 0, 0, 0], + scale: [2, 2, 2], + mesh: 0, + extensions: { + Custom_Light: {} + } } - } - ], - scene: 0, - scenes: [{ name: "scene", nodes: [0] }], - materials: [ - { - name: "pbr", - pbrMetallicRoughness: { - baseColorFactor: [1, 0, 0, 1], - baseColorTexture: { - index: 0, - extensions: { - KHR_texture_transform: { - offset: [0.5, 0.5], - scale: [2, 2], - rotation: Math.PI / 2, - texCoord: 1 + ], + scene: 0, + scenes: [{ name: "scene", nodes: [0] }], + materials: [ + { + name: "pbr", + pbrMetallicRoughness: { + baseColorFactor: [1, 0, 0, 1], + baseColorTexture: { + index: 0, + extensions: { + KHR_texture_transform: { + offset: [0.5, 0.5], + scale: [2, 2], + rotation: Math.PI / 2, + texCoord: 1 + } } + }, + metallicRoughnessTexture: { + index: 0 } }, - metallicRoughnessTexture: { + emissiveTexture: { index: 0 + }, + normalTexture: { + index: 0, + scale: 2 + }, + occlusionTexture: { + index: 0, + strength: 2, + texCoord: 1 + }, + emissiveFactor: [1, 1, 1, 1], + doubleSided: true, + alphaMode: "BLEND", + extensions: { + KHR_materials_clearcoat: { + clearcoatFactor: 0.5, + clearcoatRoughnessFactor: 0.5, + clearcoatTexture: { + index: 0 + }, + clearcoatRoughnessTexture: { + index: 0 + }, + clearcoatNormalTexture: { + index: 0 + } + } } }, - emissiveTexture: { - index: 0 - }, - normalTexture: { - index: 0, - scale: 2 - }, - occlusionTexture: { - index: 0, - strength: 2, - texCoord: 1 + { + name: "unlit", + alphaMode: "OPAQUE", + pbrMetallicRoughness: { + baseColorFactor: [0, 1, 0, 1] + }, + extensions: { + KHR_materials_unlit: {} + } }, - emissiveFactor: [1, 1, 1, 1], - doubleSided: true, - alphaMode: "BLEND", - extensions: { - KHR_materials_clearcoat: { - clearcoatFactor: 0.5, - clearcoatRoughnessFactor: 0.5, - clearcoatTexture: { - index: 0 - }, - clearcoatRoughnessTexture: { - index: 0 - }, - clearcoatNormalTexture: { - index: 0 + { + name: "specular", + alphaMode: "MASK", + alphaCutoff: 0.8, + extensions: { + KHR_materials_pbrSpecularGlossiness: { + diffuseFactor: [0, 0, 1, 1], + specularFactor: [1, 0, 0, 1], + glossinessFactor: 0.5, + diffuseTexture: { + index: 0 + }, + specularGlossinessTexture: { + index: 0 + } } } - } - }, - { - name: "unlit", - alphaMode: "OPAQUE", - pbrMetallicRoughness: { - baseColorFactor: [0, 1, 0, 1] }, - extensions: { - KHR_materials_unlit: {} - } - }, - { - name: "specular", - alphaMode: "MASK", - alphaCutoff: 0.8, - extensions: { - KHR_materials_pbrSpecularGlossiness: { - diffuseFactor: [0, 0, 1, 1], - specularFactor: [1, 0, 0, 1], - glossinessFactor: 0.5, - diffuseTexture: { - index: 0 - }, - specularGlossinessTexture: { - index: 0 - } + { + name: "custom blinn-phong", + extensions: { + Custom_Material: { baseColorFactor: [1, 1, 0, 1] } } } - }, - { - name: "custom blinn-phong", - extensions: { - Custom_Material: { baseColorFactor: [1, 1, 0, 1] } - } - } - ], - animations: [ - { - channels: [ - { - sampler: 0, - target: { - node: 0, - path: "rotation" + ], + animations: [ + { + channels: [ + { + sampler: 0, + target: { + node: 0, + path: "rotation" + } } - } - ], - name: "animation", - samplers: [ - { - input: 0, - interpolation: "LINEAR", - output: 1 - } - ] - } - ], - meshes: [ - { - name: "mesh", - primitives: [ - { - attributes: { - NORMAL: 1, - POSITION: 1, - TANGENT: 1, - TEXCOORD_0: 1 - }, - indices: 1, - material: 0, - mode: 4, - targets: [ - { + ], + name: "animation", + samplers: [ + { + input: 0, + interpolation: "LINEAR", + output: 1 + } + ] + } + ], + meshes: [ + { + name: "mesh", + primitives: [ + { + attributes: { + NORMAL: 1, POSITION: 1, TANGENT: 1, - NORMAL: 1 + TEXCOORD_0: 1 }, - { - POSITION: 1, - TANGENT: 1, - NORMAL: 1 - } - ], - extensions: {} + indices: 1, + material: 0, + mode: 4, + targets: [ + { + POSITION: 1, + TANGENT: 1, + NORMAL: 1 + }, + { + POSITION: 1, + TANGENT: 1, + NORMAL: 1 + } + ], + extensions: {} + } + ], + weights: [1, 1], + extras: { + targetNames: ["bs0", "bs1"] } - ], - weights: [1, 1], - extras: { - targetNames: ["bs0", "bs1"] } - } - ] - }; + ] + }; - const buffer = new ArrayBuffer(1000); - const dataView = new Uint8Array(buffer); - dataView.set([ - 255, 216, 255, 219, 0, 67, 0, 3, 2, 2, 3, 2, 2, 3, 3, 3, 3, 4, 3, 3, 4, 5, 8, 5, 5, 4, 4, 5, 10, 7, 7, 6, 8, 12, - 10, 12, 12, 11, 10, 11, 11, 13, 14, 18, 16, 13, 14, 17, 14, 11, 11, 16, 22, 16, 17, 19, 20, 21, 21, 21, 12, 15, - 23, 24, 22, 20, 24, 18, 20, 21, 20, 255, 219, 0, 67, 1, 3, 4, 4, 5, 4, 5, 9, 5, 5, 9, 20, 13, 11, 13, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 255, 192, 0, 17, 8, 0, 1, 0, 1, 3, 1, - 34, 0, 2, 17, 1, 3, 17, 1, 255, 196, 0, 21, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 255, 196, 0, - 20, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 196, 0, 21, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 9, 255, 196, 0, 20, 17, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 218, 0, 12, 3, 1, - 0, 2, 17, 3, 17, 0, 63, 0, 157, 0, 6, 42, 155, 255, 217 - ]); - context.buffers = [buffer]; + const buffer = new ArrayBuffer(1000); + const dataView = new Uint8Array(buffer); + dataView.set([ + 255, 216, 255, 219, 0, 67, 0, 3, 2, 2, 3, 2, 2, 3, 3, 3, 3, 4, 3, 3, 4, 5, 8, 5, 5, 4, 4, 5, 10, 7, 7, 6, 8, 12, + 10, 12, 12, 11, 10, 11, 11, 13, 14, 18, 16, 13, 14, 17, 14, 11, 11, 16, 22, 16, 17, 19, 20, 21, 21, 21, 12, 15, + 23, 24, 22, 20, 24, 18, 20, 21, 20, 255, 219, 0, 67, 1, 3, 4, 4, 5, 4, 5, 9, 5, 5, 9, 20, 13, 11, 13, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 255, 192, 0, 17, 8, 0, 1, 0, 1, + 3, 1, 34, 0, 2, 17, 1, 3, 17, 1, 255, 196, 0, 21, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 255, + 196, 0, 20, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 196, 0, 21, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 255, 196, 0, 20, 17, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 218, + 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0, 157, 0, 6, 42, 155, 255, 217 + ]); + context.buffers = [buffer]; - return Promise.resolve(glTF); + return Promise.resolve(glTF); + } } -} -@registerGLTFExtension("Custom_Material", GLTFExtensionMode.CreateAndParse) -class CustomMaterial extends GLTFExtensionParser { - createAndParse(context: GLTFParserContext, extensionSchema: { baseColorFactor: Array }): BlinnPhongMaterial { - const material = new BlinnPhongMaterial(engine); - const baseColorFactor = extensionSchema.baseColorFactor; - material.baseColor.set(baseColorFactor[0], baseColorFactor[1], baseColorFactor[2], baseColorFactor[3]); - return material; + @registerGLTFExtension("Custom_Material", GLTFExtensionMode.CreateAndParse) + class CustomMaterial extends GLTFExtensionParser { + createAndParse( + context: GLTFParserContext, + extensionSchema: { baseColorFactor: Array } + ): BlinnPhongMaterial { + const material = new BlinnPhongMaterial(engine); + const baseColorFactor = extensionSchema.baseColorFactor; + material.baseColor.set(baseColorFactor[0], baseColorFactor[1], baseColorFactor[2], baseColorFactor[3]); + return material; + } } -} -@registerGLTFExtension("Custom_Light", GLTFExtensionMode.AdditiveParse) -class CustomLight extends GLTFExtensionParser { - additiveParse(context: GLTFParserContext, parseResource: Entity, extensionSchema: GLTFExtensionSchema): void { - parseResource.addComponent(PointLight); + @registerGLTFExtension("Custom_Light", GLTFExtensionMode.AdditiveParse) + class CustomLight extends GLTFExtensionParser { + additiveParse(context: GLTFParserContext, parseResource: Entity, extensionSchema: GLTFExtensionSchema): void { + parseResource.addComponent(PointLight); + } } -} +}); + +after(() => { + @registerGLTFParser(GLTFParserType.Schema) + class test extends GLTFSchemaParser {} +}); describe("glTF Loader test", function () { it("Pipeline Parser", async () => {