Skip to content

Commit

Permalink
Cherry pick glTF parse support custom extsnions and parser (#1534)
Browse files Browse the repository at this point in the history
* glTF parse support custom extsnions and parser (#1008)

* feat: glTF parse support custom extsnions and parser

Co-authored-by: ChenMo <gl3336563@163.com>
Co-authored-by: zhuxudong <callzhuxudong@163.com>
  • Loading branch information
GuoLei1990 and zhuxudong authored May 9, 2023
1 parent 2155a84 commit 6553494
Show file tree
Hide file tree
Showing 37 changed files with 964 additions and 784 deletions.
17 changes: 10 additions & 7 deletions packages/loader/src/GLTFLoader.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { AssetPromise, AssetType, Loader, LoadItem, resourceLoader, ResourceManager } from "@galacean/engine-core";
import { GLTFParser } from "./gltf/GLTFParser";
import { GLTFPipeline } from "./gltf/GLTFPipeline";
import { GLTFResource } from "./gltf/GLTFResource";
import { ParserContext } from "./gltf/parser/ParserContext";
import { GLTFParserContext } from "./gltf/parser/GLTFParserContext";

@resourceLoader(AssetType.Prefab, ["gltf", "glb"])
export class GLTFLoader extends Loader<GLTFResource> {
load(item: LoadItem, resourceManager: ResourceManager): Record<string, AssetPromise<any>> {
const url = item.url;
const context = new ParserContext(url);
const { url } = item;
const params = <GLTFParams>item.params;
const context = new GLTFParserContext(url);
const glTFResource = new GLTFResource(resourceManager.engine, url);
const masterPromiseInfo = context.masterPromiseInfo;

context.glTFResource = glTFResource;
context.keepMeshData = item.params?.keepMeshData ?? false;
context.keepMeshData = params?.keepMeshData ?? false;

masterPromiseInfo.onCancel(() => {
const { chainPromises } = context;
Expand All @@ -21,8 +22,8 @@ export class GLTFLoader extends Loader<GLTFResource> {
}
});

GLTFParser.defaultPipeline
.parse(context)
(params?.pipeline || GLTFPipeline.defaultPipeline)
._parse(context)
.then(masterPromiseInfo.resolve)
.catch((e) => {
console.error(e);
Expand All @@ -42,4 +43,6 @@ export interface GLTFParams {
* Keep raw mesh data for glTF parser, default is false.
*/
keepMeshData: boolean;
/** Custom glTF pipeline. */
pipeline: GLTFPipeline;
}
63 changes: 0 additions & 63 deletions packages/loader/src/gltf/GLTFParser.ts

This file was deleted.

76 changes: 76 additions & 0 deletions packages/loader/src/gltf/GLTFPipeline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { AssetPromise } from "@galacean/engine-core";
import { GLTFResource } from "./GLTFResource";
import { GLTFAnimationParser } from "./parser/GLTFAnimationParser";
import { GLTFBufferParser } from "./parser/GLTFBufferParser";
import { GLTFEntityParser } from "./parser/GLTFEntityParser";
import { GLTFMaterialParser } from "./parser/GLTFMaterialParser";
import { GLTFMeshParser } from "./parser/GLTFMeshParser";
import { GLTFParser } from "./parser/GLTFParser";
import { GLTFParserContext } from "./parser/GLTFParserContext";
import { GLTFSceneParser } from "./parser/GLTFSceneParser";
import { GLTFSkinParser } from "./parser/GLTFSkinParser";
import { GLTFTextureParser } from "./parser/GLTFTextureParser";
import { GLTFValidator } from "./parser/GLTFValidator";

/**
* GLTF pipeline.
*/
export class GLTFPipeline {
/**
* Default pipeline.
*/
static defaultPipeline = new GLTFPipeline(
GLTFBufferParser,
GLTFValidator,
GLTFTextureParser,
GLTFMaterialParser,
GLTFMeshParser,
GLTFEntityParser,
GLTFSkinParser,
GLTFAnimationParser,
GLTFSceneParser
);

private _parsers: GLTFParser[] = [];

/**
* Constructor of GLTFPipeline.
* @param parsers - Parsers to be executed in order
*/
constructor(...parsers: (new () => GLTFParser)[]) {
parsers.forEach((pipe: new () => GLTFParser, index: number) => {
this._parsers[index] = new pipe();
});
}

/**
* @internal
*/
_parse(context: GLTFParserContext): AssetPromise<GLTFResource> {
const glTFResource = context.glTFResource;
let lastParser;

return new AssetPromise<GLTFResource>((resolve, reject) => {
this._parsers.forEach((parser: GLTFParser) => {
if (lastParser) {
lastParser = lastParser.then(() => {
return parser.parse(context);
});
if (lastParser.cancel) {
context.chainPromises.push(lastParser);
}
} else {
lastParser = parser.parse(context);
}
});

if (lastParser) {
lastParser
.then(() => {
resolve(glTFResource);
})
.catch(reject);
}
});
}
}
7 changes: 3 additions & 4 deletions packages/loader/src/gltf/GLTFResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
Light,
Material,
ModelMesh,
Renderer,
Skin,
Texture2D
} from "@galacean/engine-core";
Expand Down Expand Up @@ -38,8 +37,8 @@ export class GLTFResource extends EngineObject {
sceneRoots: Entity[];
/** RootEntity after SceneParser. */
defaultSceneRoot: Entity;
/** Renderer can replace material by `renderer.setMaterial` if gltf use plugin-in KHR_materials_variants. */
variants?: { renderer: Renderer; material: Material; variants: string[] }[];
/** Extensions data. */
extensionsData: Record<string, any>;

constructor(engine: Engine, url: string) {
super(engine);
Expand All @@ -66,6 +65,6 @@ export class GLTFResource extends EngineObject {
this.cameras = null;
this.lights = null;
this.sceneRoots = null;
this.variants = null;
this.extensionsData = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -853,3 +853,6 @@ export interface IGLTF extends IProperty {
*/
textures?: ITexture[];
}

/** glTF extensible owner schema. */
export type GLTFExtensionOwnerSchema = IMeshPrimitive | IMaterial | ITextureInfo | INode;
9 changes: 6 additions & 3 deletions packages/loader/src/gltf/GLTFUtil.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IndexFormat, TypedArray, VertexElementFormat } from "@galacean/engine-core";
import { Color, Vector2, Vector3, Vector4 } from "@galacean/engine-math";
import { BufferInfo, ParserContext } from "./parser/ParserContext";
import { AccessorComponentType, AccessorType, IAccessor, IBufferView, IGLTF } from "./Schema";
import { AccessorComponentType, AccessorType, IAccessor, IBufferView, IGLTF } from "./GLTFSchema";
import { BufferInfo, GLTFParserContext } from "./parser/GLTFParserContext";

const charCodeOfDot = ".".charCodeAt(0);
const reEscapeChar = /\\(\\)?/g;
Expand All @@ -23,6 +23,9 @@ const rePropName = RegExp(
"g"
);




/**
* @internal
*/
Expand Down Expand Up @@ -147,7 +150,7 @@ export class GLTFUtil {
}
}

static getAccessorBuffer(context: ParserContext, gltf: IGLTF, accessor: IAccessor): BufferInfo {
static getAccessorBuffer(context: GLTFParserContext, gltf: IGLTF, accessor: IAccessor): BufferInfo {
const { buffers } = context;
const bufferViews = gltf.bufferViews;

Expand Down
22 changes: 0 additions & 22 deletions packages/loader/src/gltf/extensions/ExtensionParser.ts

This file was deleted.

17 changes: 10 additions & 7 deletions packages/loader/src/gltf/extensions/GALACEAN_materials_remap.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Material } from "@galacean/engine-core";
import { registerExtension } from "../parser/Parser";
import { ParserContext } from "../parser/ParserContext";
import { ExtensionParser } from "./ExtensionParser";
import { IGalaceanMaterialRemap } from "./Schema";
import { registerGLTFExtension } from "../parser/GLTFParser";
import { GLTFParserContext } from "../parser/GLTFParserContext";
import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
import { IGalaceanMaterialRemap } from "./GLTFExtensionSchema";

@registerExtension("OASIS_materials_remap")
class GalaceanMaterialsRemap extends ExtensionParser {
createEngineResource(schema: IGalaceanMaterialRemap, context: ParserContext): Promise<Material> {
@registerGLTFExtension("OASIS_materials_remap", GLTFExtensionMode.CreateAndParse)
class OasisMaterialsRemap extends GLTFExtensionParser {
/**
* @override
*/
createAndParse(context: GLTFParserContext, schema: IGalaceanMaterialRemap): Promise<Material> {
const { engine } = context.glTFResource;
// @ts-ignore
return engine.resourceManager.getResourceByRef<Material>(schema);
Expand Down
73 changes: 73 additions & 0 deletions packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { EngineObject } from "@galacean/engine-core";
import { GLTFExtensionOwnerSchema } from "../GLTFSchema";
import { GLTFParserContext } from "../parser/GLTFParserContext";
import { GLTFExtensionSchema } from "./GLTFExtensionSchema";

/**
* Base class of glTF extension parser.
*/
export abstract class GLTFExtensionParser {
/**
* @internal
* The extension mode.
*/
_mode: GLTFExtensionMode;

/**
* Initialize the parser.
* @remarks Some plugins require initialization.
* @returns The void or promise
*/
initialize(): void | Promise<void> {}

/**
* Create and parse the resource.
* @remarks This method overrides the default resource creation.
* @param context - The parser context
* @param extensionSchema - The extension schema
* @param extensionOwnerSchema - The extension owner schema
* @returns The resource or promise
*/
createAndParse(
context: GLTFParserContext,
extensionSchema: GLTFExtensionSchema,
extensionOwnerSchema: GLTFExtensionOwnerSchema,
...extra
): EngineObject | Promise<EngineObject> {
throw "Not implemented.";
}

/**
* Additive parse to the resource.
* @param context - The parser context
* @param parseResource - The parsed resource
* @param extensionSchema - The extension schema
* @param extensionOwnerSchema - The extension owner schema
* @returns The void or promise
*/
additiveParse(
context: GLTFParserContext,
parseResource: EngineObject,
extensionSchema: GLTFExtensionSchema,
extensionOwnerSchema: GLTFExtensionOwnerSchema,
...extra
): void | Promise<void> {
throw "Not implemented.";
}
}

/**
* glTF Extension mode.
*/
export enum GLTFExtensionMode {
/**
* Cerate instance and parse mode.
* @remarks
* If the glTF property has multiple extensions of `CreateAndParse` mode, only execute the last one.
* If this method is registered, the default pipeline processing will be ignored.
*/
CreateAndParse,

/** Additive parse mode. */
AdditiveParse
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IMaterialNormalTextureInfo, ITextureInfo } from "../Schema";
import { IMaterialNormalTextureInfo, ITextureInfo } from "../GLTFSchema";

/**
* Interfaces from the KHR_lights_punctual extension
Expand Down Expand Up @@ -159,7 +159,7 @@ export interface IGalaceanMaterialRemap {
isClone?: boolean;
}

export type ExtensionSchema =
export type GLTFExtensionSchema =
| IKHRLightsPunctual_Light
| IKHRDracoMeshCompression
| IKHRMaterialsClearcoat
Expand All @@ -175,4 +175,5 @@ export type ExtensionSchema =
| IKHRTextureBasisU
| IKHRTextureTransform
| IKHRXmp
| IKHRXmp_Node;
| IKHRXmp_Node
| Object;
Loading

0 comments on commit 6553494

Please sign in to comment.