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

Improve glTF material export code #13229

Merged
merged 4 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
import type { ITextureInfo, IKHRTextureTransform } from "babylonjs-gltf2interface";
import { Tools } from "core/Misc/tools";
import type { Texture } from "core/Materials/Textures/texture";
import { ProceduralTexture } from "core/Materials/Textures/Procedurals/proceduralTexture";
import type { Scene } from "core/scene";

import type { Nullable } from "core/types";
import type { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
import { _Exporter } from "../glTFExporter";

const NAME = "KHR_texture_transform";

import "../shaders/textureTransform.fragment";

/**
* @internal
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
private _recordedTextures: ProceduralTexture[] = [];

/** Name of this extension */
public readonly name = NAME;

Expand All @@ -32,11 +26,7 @@ export class KHR_texture_transform implements IGLTFExporterExtensionV2 {

constructor() {}

public dispose() {
for (const texture of this._recordedTextures) {
texture.dispose();
}
}
public dispose() {}

/** @internal */
public get wasUsed() {
Expand Down Expand Up @@ -85,76 +75,26 @@ export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
}
}

public preExportTextureAsync(context: string, babylonTexture: Texture): Promise<Texture> {
public preExportTextureAsync(context: string, babylonTexture: Texture): Promise<Nullable<Texture>> {
return new Promise((resolve, reject) => {
const scene = babylonTexture.getScene();
if (!scene) {
reject(`${context}: "scene" is not defined for Babylon texture ${babylonTexture.name}!`);
return;
}

let bakeTextureTransform = false;

/*
* The KHR_texture_transform schema only supports rotation around the origin.
* the texture must be baked to preserve appearance.
* see: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#gltf-schema-updates
* See https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#gltf-schema-updates.
*/
if (
(babylonTexture.uAng !== 0 || babylonTexture.wAng !== 0 || babylonTexture.vAng !== 0) &&
(babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0)
) {
bakeTextureTransform = true;
}

if (!bakeTextureTransform) {
resolve(babylonTexture);
return;
}

return this._textureTransformTextureAsync(babylonTexture, scene)
.then((proceduralTexture) => {
resolve(proceduralTexture);
})
.catch((e) => {
reject(e);
});
});
}

/**
* Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
* @param babylonTexture
* @param scene
*/
private _textureTransformTextureAsync(babylonTexture: Texture, scene: Scene): Promise<Texture> {
return new Promise((resolve) => {
const proceduralTexture = new ProceduralTexture(`${babylonTexture.name}`, babylonTexture.getSize(), "textureTransform", scene);
if (!proceduralTexture) {
Tools.Log(`Cannot create procedural texture for ${babylonTexture.name}!`);
resolve(babylonTexture);
}

proceduralTexture.reservedDataStore = {
hidden: true,
source: babylonTexture,
};

this._recordedTextures.push(proceduralTexture);

proceduralTexture.coordinatesIndex = babylonTexture.coordinatesIndex;
proceduralTexture.setTexture("textureSampler", babylonTexture);
proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());

// isReady trigger creation of effect if it doesnt exist yet
if (proceduralTexture.isReady()) {
proceduralTexture.render();
resolve(proceduralTexture);
Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation not centered at the origin cannot be exported with ${NAME}`);
resolve(null);
} else {
proceduralTexture.getEffect().executeWhenCompiled(() => {
proceduralTexture.render();
resolve(proceduralTexture);
});
resolve(babylonTexture);
}
});
}
Expand Down
12 changes: 6 additions & 6 deletions packages/dev/serializers/src/glTF/2.0/glTFExporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ export class _Exporter {
* Stores a map of the image data, where the key is the file name and the value
* is the image data
*/
public _imageData: { [fileName: string]: { data: Uint8Array; mimeType: ImageMimeType } };
public _imageData: { [fileName: string]: { data: ArrayBuffer; mimeType: ImageMimeType } };

protected _orderedImageData: Array<{ data: Uint8Array; mimeType: ImageMimeType }>;
protected _orderedImageData: Array<{ data: ArrayBuffer; mimeType: ImageMimeType }>;

/**
* Stores a map of the unique id of a node to its index in the node array
Expand Down Expand Up @@ -1054,7 +1054,7 @@ export class _Exporter {
private _generateJSON(shouldUseGlb: boolean, glTFPrefix?: string, prettyPrint?: boolean): string {
const buffer: IBuffer = { byteLength: this._totalByteLength };
let imageName: string;
let imageData: { data: Uint8Array; mimeType: ImageMimeType };
let imageData: { data: ArrayBuffer; mimeType: ImageMimeType };
let bufferView: IBufferView;
let byteOffset: number = this._totalByteLength;

Expand Down Expand Up @@ -1106,8 +1106,8 @@ export class _Exporter {
imageData = this._imageData[image.uri];
this._orderedImageData.push(imageData);
imageName = image.uri.split(".")[0] + " image";
bufferView = _GLTFUtilities._CreateBufferView(0, byteOffset, imageData.data.length, undefined, imageName);
byteOffset += imageData.data.buffer.byteLength;
bufferView = _GLTFUtilities._CreateBufferView(0, byteOffset, imageData.data.byteLength, undefined, imageName);
byteOffset += imageData.data.byteLength;
this._bufferViews.push(bufferView);
image.bufferView = this._bufferViews.length - 1;
image.name = imageName;
Expand Down Expand Up @@ -1281,7 +1281,7 @@ export class _Exporter {

// binary data
for (let i = 0; i < this._orderedImageData.length; ++i) {
glbData.push(this._orderedImageData[i].data.buffer);
glbData.push(this._orderedImageData[i].data);
}

glbData.push(binPaddingBuffer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface IGLTFExporterExtensionV2 extends IGLTFExporterExtension, IDispo
* @param mimeType The mime-type of the generated image
* @returns A promise that resolves with the exported texture
*/
preExportTextureAsync?(context: string, babylonTexture: Nullable<Texture>, mimeType: ImageMimeType): Promise<Texture>;
preExportTextureAsync?(context: string, babylonTexture: Nullable<Texture>, mimeType: ImageMimeType): Promise<Nullable<Texture>>;

/**
* Define this method to get notified when a texture info is created
Expand Down
Loading