Skip to content

Commit

Permalink
Merge pull request #154 from CesiumGS/dequantize-web3d-quantized-attr…
Browse files Browse the repository at this point in the history
…ibutes

Dequantize `WEB3D_quantized_attributes`
  • Loading branch information
lilleyse authored Jan 6, 2025
2 parents 8440bdb + 0af80b9 commit eff511a
Show file tree
Hide file tree
Showing 8 changed files with 446 additions and 9 deletions.
16 changes: 11 additions & 5 deletions demos/tools/TilesetUpgraderDemos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,22 @@ async function upgradeTileset(
}

async function tilesetUpgraderDemos() {
await upgradeTilesetJson(
await upgradeTileset(
SPECS_DATA_BASE_DIRECTORY +
"/upgradeTileset/tilesetWithContentUrls/tileset.json",
"./output/upgradeTileset/tilesetWithContentUrls-upgraded/tileset.json"
"/upgradeTileset/tilesetWithB3dmWithGltf1/tileset.json",
"./output/upgradeTileset/tilesetWithB3dmWithGltf1-upgraded/tileset.json"
);

await upgradeTileset(
SPECS_DATA_BASE_DIRECTORY +
"/upgradeTileset/tilesetWithB3dmWithGltf1/tileset.json",
"./output/upgradeTileset/tilesetWithB3dmWithGltf1-upgraded/tileset.json"
"/upgradeTileset/tilesetWithB3dmWithGltf1WithWeb3dQuantizedAttributes/tileset.json",
"./output/upgradeTileset/tilesetWithB3dmWithGltf1WithWeb3dQuantizedAttributes-upgraded/tileset.json"
);

await upgradeTilesetJson(
SPECS_DATA_BASE_DIRECTORY +
"/upgradeTileset/tilesetWithContentUrls/tileset.json",
"./output/upgradeTileset/tilesetWithContentUrls-upgraded/tileset.json"
);

await upgradeTileset(
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"asset" : {
"version" : "1.1"
},
"geometricError" : 1024.0,
"root" : {
"boundingVolume" : {
"box" : [ 0.5, 0.00625, 0.5, 0.5, 0.0, 0.0, 0.00625, 0.0, 0.0, 0.0, 0.0, 0.5 ]
},
"geometricError" : 32.0,
"refine" : "ADD",
"content" : {
"uri" : "b3dmWithGltf1WithWeb3dQuantizedAttributes.b3dm"
}
}
}
44 changes: 44 additions & 0 deletions src/tilesets/tilesets/Extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,30 @@ export class Extensions {
Extensions.removeFrom(extensible, "extensionsRequired", extension);
}

/**
* Returns whether the given extensible object declares the given
* extension in its `extensionsUsed` array.
*
* @param extensible - The object that may declare the used extension
* @param extension - The extension (i.e. its name as a string)
* @returns Whether the object declares the extension to be used
*/
static usesExtension(extensible: Extensible, extension: string) {
return Extensions.contains(extensible, "extensionsUsed", extension);
}

/**
* Returns whether the given extensible object declares the given
* extension in its `extensionsRequired` array.
*
* @param extensible - The object that may declare the required extension
* @param extension - The extension (i.e. its name as a string)
* @returns Whether the object declares the extension to be required
*/
static requiresExtension(extensible: Extensible, extension: string) {
return Extensions.contains(extensible, "extensionsRequired", extension);
}

/**
* Adds the given element to the specified array if it was not
* contained yet, creating a new array if it did not exist yet.
Expand Down Expand Up @@ -153,4 +177,24 @@ export class Extensions {
delete object[key];
}
}

/**
* Returns whether the specified array property is defined and
* includes the given element
*
* @param object - The object containing the array
* @param key - The name of the array property
* @param element - The element
*/
private static contains<T>(
object: { [key: string]: T[] | undefined },
key: string,
element: T
): boolean {
const array = object[key];
if (!array) {
return false;
}
return array.includes(element);
}
}
2 changes: 1 addition & 1 deletion src/tools/contentProcessing/GltfTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { StructuralMetadataMerger } from "../gltfExtensionsUtils/StructuralMetad
*/
export class GltfTransform {
/**
* The `gltf-transform` IO handler, intialized lazily and cached
* The `gltf-transform` IO handler, initialized lazily and cached
* in `getIO`.
*/
private static io: NodeIO | undefined;
Expand Down
61 changes: 61 additions & 0 deletions src/tools/contentProcessing/GltfUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { TileFormatError } from "../../tilesets";
import { Extensions } from "../../tilesets";

import { GltfPipelineLegacy } from "./GltfPipelineLegacy";
import { GltfWeb3dQuantizedAttributes } from "./GltfWeb3dQuantizedAttributes";

/**
* Internal utility methods related to glTF/GLB data.
Expand Down Expand Up @@ -320,4 +321,64 @@ export class GltfUtilities {
Extensions.removeExtensionUsed(gltf, "CESIUM_RTC");
Extensions.removeExtension(gltf, "CESIUM_RTC");
}

/**
* Given an input buffer containing a binary glTF 2.0 asset, remove
* its use of the `WEB3D_quantized_attributes` extension.
*
* See `GltfWeb3dQuantizedAttributes` for further notes about
* the context where this is used.
*
* @param glbBuffer - The buffer containing the binary glTF.
* @returns A promise that resolves to the resulting binary glTF.
*/
static async replaceWeb3dQuantizedAttributesExtension(
glbBuffer: Buffer
): Promise<Buffer> {
// Process the GLB data with a custom gltf-pipeline stage that removes
// the WEB3D_quantized_attributes from the extensionsUsed/Required
// arrays, and collects the 'decodeMatrix' arrays from the extension
// objects in the accessors.
const extensionName = "WEB3D_quantized_attributes";
let usedExtension = false;
const decodeMatrices: (number[] | undefined)[] = [];

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const customStage = (gltf: any, options: any) => {
usedExtension = Extensions.usesExtension(gltf, extensionName);
if (usedExtension) {
Extensions.removeExtensionUsed(gltf, extensionName);

// Collect the 'decodeMatrix' arrays, one for each accessor
// (or 'undefined' if the accessor did not use the extension)
const accessors = gltf.accessors || [];
for (let i = 0; i < accessors.length; i++) {
const accessor = accessors[i];
const extensions = accessor.extensions || {};
const extension = extensions[extensionName] || {};
const decodeMatrix = extension.decodeMatrix;
decodeMatrices.push(decodeMatrix);
}
}
return gltf;
};
const options = {
customStages: [customStage],
keepUnusedElements: true,
};
const result = await GltfPipeline.processGlb(glbBuffer, options);
const preprocessedGlb = result.glb;

// If the glTF did not use the extension, then just return the result
if (!usedExtension) {
return preprocessedGlb;
}

// Otherwise, post-process the glTF to dequantize the accessors
// using the decode matrices that have been found for them.
return GltfWeb3dQuantizedAttributes.replaceWeb3dQuantizedAttributesExtension(
preprocessedGlb,
decodeMatrices
);
}
}
Loading

0 comments on commit eff511a

Please sign in to comment.