Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

glTF parse support custom extsnions and parser #1008

Merged
merged 26 commits into from
Mar 1, 2023
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4376181
refactor: export gltf parsers for users
zhuxudong Sep 6, 2022
9b23f8f
Merge branch 'dev/1.0' into refactor/export-parser
zhuxudong Feb 21, 2023
62d4416
refactor: export relative variable
zhuxudong Feb 21, 2023
3ec1b17
refactor: support custom material parser
zhuxudong Feb 21, 2023
f47f002
refactor: export pipeline
zhuxudong Feb 21, 2023
e9a5c8b
refactor: rename
zhuxudong Feb 27, 2023
d5a892d
refactor: add warning
zhuxudong Feb 27, 2023
d825f22
refactor: rename
zhuxudong Feb 27, 2023
ef8e1dd
refactor: rename
zhuxudong Feb 27, 2023
0b36e5d
refactor: add resourceIndex to use customization
zhuxudong Feb 27, 2023
a9b9f86
refactor: extend resource
zhuxudong Feb 27, 2023
a7d1ad7
refactor: extension mode
zhuxudong Feb 28, 2023
ea1deea
refactor: use decorator
zhuxudong Feb 28, 2023
74d2a02
refactor: param
zhuxudong Feb 28, 2023
f1e60eb
refactor: add extension common parser
zhuxudong Mar 1, 2023
9043190
refactor: opt GLTFLoader code (#6)
GuoLei1990 Mar 1, 2023
be6b1d4
refactor: draco
zhuxudong Mar 1, 2023
80d30c8
refactor: opt code (#7)
GuoLei1990 Mar 1, 2023
55a3865
refactor: primitive additive parser
zhuxudong Mar 1, 2023
e363823
refactor: add extension data
zhuxudong Mar 1, 2023
43ee74f
refactor: private
zhuxudong Mar 1, 2023
a9d4648
refactor: add comments
zhuxudong Mar 1, 2023
583a4de
refactor: perf code
zhuxudong Mar 1, 2023
f390b7b
refactor: add comment
zhuxudong Mar 1, 2023
46b6b41
refactor: rename
zhuxudong Mar 1, 2023
ecab3fe
refactor: export type
zhuxudong Mar 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 "@oasis-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;
@@ -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);
@@ -39,4 +40,6 @@ export class GLTFLoader extends Loader<GLTFResource> {
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 "@oasis-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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add type


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
@@ -7,7 +7,6 @@ import {
Light,
Material,
ModelMesh,
Renderer,
Skin,
Texture2D
} from "@oasis-engine/core";
@@ -38,8 +37,8 @@ export class GLTFResource extends EngineObject {
sceneRoots: Entity[];
/** Oasis 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);
@@ -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
@@ -853,3 +853,6 @@ export interface IGLTF extends IProperty {
*/
textures?: ITexture[];
}

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

const charCodeOfDot = ".".charCodeAt(0);
const reEscapeChar = /\\(\\)?/g;
const rePropName = RegExp(
// Match anything that isn't a dot or bracket.
"[^.[\\]]+" +
"|" +
// Or match property names within brackets.
"\\[(?:" +
// Match a non-string expression.
"([^\"'][^[]*)" +
"|" +
// Or match strings (supports escaping characters).
"([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2" +
")\\]" +
"|" +
// Or match "" as the space between consecutive dots or empty brackets.
"(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))",
"g"
);
import { BufferInfo, GLTFParserContext } from "./parser/GLTFParserContext";
import { AccessorComponentType, AccessorType, IAccessor, IBufferView, IGLTF } from "./GLTFSchema";

/**
* @internal
@@ -147,7 +127,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;

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

This file was deleted.

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 "@oasis-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
@@ -159,7 +159,7 @@ export interface IOasisMaterialRemap {
isClone?: boolean;
}

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