Skip to content

Commit

Permalink
Add an ugly flag to glTF draco loader extension (#14325)
Browse files Browse the repository at this point in the history
  • Loading branch information
bghgary committed Sep 20, 2023
1 parent 9469727 commit 33ae7ca
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 7 deletions.
64 changes: 61 additions & 3 deletions packages/dev/core/src/Meshes/Compression/dracoCompression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { VertexData } from "../mesh.vertexData";
import type { ThinEngine } from "../../Engines/thinEngine";
import { DracoDecoderModule } from "draco3dgltf";
import type { DecoderModule, DecoderBuffer, Decoder, Mesh, PointCloud, Status } from "draco3dgltf";
import { Logger } from "../../Misc/logger";

declare let DracoDecoderModule: DracoDecoderModule;

Expand Down Expand Up @@ -441,9 +442,28 @@ export class DracoCompression implements IDisposable {
return Promise.resolve();
}

private _decodeMeshAsync(engine: Nullable<ThinEngine>, data: ArrayBuffer | ArrayBufferView, attributes?: { [kind: string]: number }): Promise<MeshData> {
private _decodeMeshAsync(
engine: Nullable<ThinEngine>,
data: ArrayBuffer | ArrayBufferView,
attributes?: { [kind: string]: number },
gltfNormalizedOverride?: { [kind: string]: boolean }
): Promise<MeshData> {
const dataView = data instanceof ArrayBuffer ? new Int8Array(data) : new Int8Array(data.buffer, data.byteOffset, data.byteLength);

const applyGltfNormalizedOverride = (kind: string, normalized: boolean): boolean => {
if (gltfNormalizedOverride && gltfNormalizedOverride[kind] !== undefined) {
if (normalized !== gltfNormalizedOverride[kind]) {
Logger.Warn(
`Normalized flag from Draco data (${normalized}) does not match normalized flag from glTF accessor (${gltfNormalizedOverride[kind]}). Using flag from glTF accessor.`
);
}

return gltfNormalizedOverride[kind];
} else {
return normalized;
}
};

if (this._workerPoolPromise) {
return this._workerPoolPromise.then((workerPool) => {
return new Promise<MeshData>((resolve, reject) => {
Expand Down Expand Up @@ -485,7 +505,7 @@ export class DracoCompression implements IDisposable {
message.offset,
undefined,
undefined,
message.normalized,
applyGltfNormalizedOverride(message.kind, message.normalized),
true
)
);
Expand Down Expand Up @@ -517,7 +537,22 @@ export class DracoCompression implements IDisposable {
resultIndices = indices;
},
(kind, data, offset, stride, normalized) => {
resultAttributes.push(new VertexBuffer(null, data, kind, false, undefined, stride, undefined, offset, undefined, undefined, normalized, true));
resultAttributes.push(
new VertexBuffer(
null,
data,
kind,
false,
undefined,
stride,
undefined,
offset,
undefined,
undefined,
applyGltfNormalizedOverride(kind, normalized),
true
)
);
}
);

Expand Down Expand Up @@ -552,6 +587,29 @@ export class DracoCompression implements IDisposable {
});
}

/** @internal */
public _decodeMeshToGeometryForGltfAsync(
name: string,
scene: Scene,
data: ArrayBuffer | ArrayBufferView,
attributes: { [kind: string]: number },
gltfNormalizedOverride: { [kind: string]: boolean }
): Promise<Geometry> {
return this._decodeMeshAsync(scene.getEngine(), data, attributes, gltfNormalizedOverride).then((meshData) => {
const geometry = new Geometry(name, scene);

if (meshData.indices) {
geometry.setIndices(meshData.indices);
}

for (const attribute of meshData.attributes) {
geometry.setVerticesBuffer(attribute);
}

return geometry;
});
}

/**
* Decode Draco compressed mesh data to Babylon vertex data.
* @param data The ArrayBuffer or ArrayBufferView for the Draco compression data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
*/
public enabled: boolean;

/**
* Defines whether to use the normalized flag from the glTF accessor instead of the Draco data. Defaults to true.
*/
public useNormalizedFlagFromAccessor = true;

private _loader: GLTFLoader;

/**
Expand Down Expand Up @@ -69,6 +74,7 @@ export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
}

const attributes: { [kind: string]: number } = {};
const normalized: { [kind: string]: boolean } = {};
const loadAttribute = (name: string, kind: string) => {
const uniqueId = extension.attributes[name];
if (uniqueId == undefined) {
Expand All @@ -81,6 +87,13 @@ export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
}

attributes[kind] = uniqueId;

if (this.useNormalizedFlagFromAccessor) {
const accessor = ArrayItem.TryGet(this._loader.gltf.accessors, primitive.attributes[name]);
if (accessor) {
normalized[kind] = accessor.normalized || false;
}
}
};

loadAttribute("POSITION", VertexBuffer.PositionKind);
Expand All @@ -100,7 +113,7 @@ export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
if (!bufferView._dracoBabylonGeometry) {
bufferView._dracoBabylonGeometry = this._loader.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {
const dracoCompression = this.dracoCompression || DracoCompression.Default;
return dracoCompression.decodeMeshToGeometryAsync(babylonMesh.name, this._loader.babylonScene, data, attributes).catch((error) => {
return dracoCompression._decodeMeshToGeometryForGltfAsync(babylonMesh.name, this._loader.babylonScene, data, attributes, normalized).catch((error) => {
throw new Error(`${context}: ${error.message}`);
});
});
Expand Down
20 changes: 17 additions & 3 deletions packages/dev/loaders/src/glTF/2.0/glTFLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,20 @@ export class ArrayItem {
return array[index];
}

/**
* Gets an item from the given array or returns null if not available.
* @param array The array to get the item from
* @param index The index to the array
* @returns The array item or null
*/
public static TryGet<T>(array: ArrayLike<T> | undefined, index: number | undefined): Nullable<T> {
if (!array || index == undefined || !array[index]) {
return null;
}

return array[index];
}

/**
* Assign an `index` field to each item of the given array.
* @param array The array of items
Expand Down Expand Up @@ -1050,8 +1064,8 @@ export class GLTFLoader implements IGLTFLoader {
);
}

const loadAttribute = (attribute: string, kind: string, callback?: (accessor: IAccessor) => void) => {
if (attributes[attribute] == undefined) {
const loadAttribute = (name: string, kind: string, callback?: (accessor: IAccessor) => void) => {
if (attributes[name] == undefined) {
return;
}

Expand All @@ -1060,7 +1074,7 @@ export class GLTFLoader implements IGLTFLoader {
babylonMesh._delayInfo.push(kind);
}

const accessor = ArrayItem.Get(`${context}/attributes/${attribute}`, this._gltf.accessors, attributes[attribute]);
const accessor = ArrayItem.Get(`${context}/attributes/${name}`, this._gltf.accessors, attributes[name]);
promises.push(
this._loadVertexAccessorAsync(`/accessors/${accessor.index}`, accessor, kind).then((babylonVertexBuffer) => {
if (babylonVertexBuffer.getKind() === VertexBuffer.PositionKind && !this.parent.alwaysComputeBoundingBox && !babylonMesh.skeleton) {
Expand Down

0 comments on commit 33ae7ca

Please sign in to comment.