Skip to content

Commit

Permalink
Merge fe2d17b into a3f82c3
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Sep 26, 2019
2 parents a3f82c3 + fe2d17b commit 1bd8af6
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 95 deletions.
5 changes: 5 additions & 0 deletions modules/gltf/docs/api-reference/gltf-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ loaders.gl aims to provide support for glTF extensions that can be handled compl

Note that many glTF extensions affect aspects that are firmly outside of the scope of loaders.gl (e.g. rendering), and no attempt is made to process those extensions in loaders.gl.

| Extension | Description |
| -------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| [KHR_draco_mesh_compression](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression) | |
| [KHR_lights_punctual](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual) | |

## Official Extensions

### KHR_draco_mesh_compression
Expand Down
56 changes: 27 additions & 29 deletions modules/gltf/src/lib/extensions/KHR_draco_mesh_compression.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,39 @@ import GLTFScenegraph from '../gltf-scenegraph';
import {KHR_DRACO_MESH_COMPRESSION} from '../gltf-constants';
import {getGLTFAccessors, getGLTFAccessor} from '../gltf-utils/gltf-attribute-utils';

export default class KHR_draco_mesh_compression {
static get name() {
return KHR_DRACO_MESH_COMPRESSION;
// Note: We have a "soft dependency" on Draco to avoid bundling it when not needed
export async function decode(gltfData, options, context) {
if (!options.gltf.decompressMeshes) {
return;
}

// Note: We have a "soft dependency" on Draco to avoid bundling it when not needed
static async decode(gltfData, options, context) {
if (!options.gltf.decompress) {
return;
}

const scenegraph = new GLTFScenegraph(gltfData);
const promises = [];
for (const primitive of meshPrimitiveIterator(scenegraph)) {
if (scenegraph.getObjectExtension(primitive, KHR_DRACO_MESH_COMPRESSION)) {
promises.push(decompressPrimitive(primitive, scenegraph, options, context));
}
const scenegraph = new GLTFScenegraph(gltfData);
const promises = [];
for (const primitive of meshPrimitiveIterator(scenegraph)) {
if (scenegraph.getObjectExtension(primitive, KHR_DRACO_MESH_COMPRESSION)) {
promises.push(decompressPrimitive(primitive, scenegraph, options, context));
}
}

// Decompress meshes in parallel
await Promise.all(promises);
// Decompress meshes in parallel
await Promise.all(promises);

// We have now decompressed all primitives, so remove the top-level extensions
scenegraph.removeExtension(KHR_DRACO_MESH_COMPRESSION);
}
// We have now decompressed all primitives, so remove the top-level extensions
scenegraph.removeExtension(KHR_DRACO_MESH_COMPRESSION);
}

static encode(gltfData, options = {}) {
const scenegraph = new GLTFScenegraph(gltfData);
export function encode(gltfData, options = {}) {
const scenegraph = new GLTFScenegraph(gltfData);

for (const mesh of scenegraph.json.meshes || []) {
// eslint-disable-next-line camelcase
compressMesh(mesh, options);
// NOTE: Only add the extension if something was actually compressed
scenegraph.addRequiredExtension(KHR_DRACO_MESH_COMPRESSION);
}
for (const mesh of scenegraph.json.meshes || []) {
// eslint-disable-next-line camelcase
compressMesh(mesh, options);
// NOTE: Only add the extension if something was actually compressed
scenegraph.addRequiredExtension(KHR_DRACO_MESH_COMPRESSION);
}
}

// PRIVATE
// DECODE

// Unpacks one mesh primitive and removes the extension from the primitive
// DracoDecoder needs to be imported and registered by app
Expand Down Expand Up @@ -75,6 +69,8 @@ async function decompressPrimitive(primitive, scenegraph, options, context) {
checkPrimitive(primitive);
}

// ENCODE

// eslint-disable-next-line max-len
// Only TRIANGLES: 0x0004 and TRIANGLE_STRIP: 0x0005 are supported
function compressMesh(attributes, indices, mode = 4, options, context) {
Expand Down Expand Up @@ -114,6 +110,8 @@ function compressMesh(attributes, indices, mode = 4, options, context) {
return glTFMesh;
}

// UTILS

function checkPrimitive(primitive) {
if (!primitive.attributes && Object.keys(primitive.attributes).length > 0) {
throw new Error('Empty glTF primitive detected: Draco decompression failure?');
Expand Down
79 changes: 37 additions & 42 deletions modules/gltf/src/lib/extensions/KHR_lights_punctual.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,51 @@
// GLTF EXTENSION: KHR_lights_punctual
// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual

import assert from '../utils/assert';
import GLTFScenegraph from '../gltf-scenegraph';
import {KHR_LIGHTS_PUNCTUAL} from '../gltf-constants';

// GLTF EXTENSION: KHR_lights_punctual
// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
// eslint-disable-next-line camelcase
export default class KHR_lights_punctual {
static get name() {
return KHR_LIGHTS_PUNCTUAL;
}

static decode(gltfData, options) {
const gltfScenegraph = new GLTFScenegraph(gltfData);
export function decode(gltfData, options) {
const gltfScenegraph = new GLTFScenegraph(gltfData);
const {json} = gltfScenegraph;

// Move the light array out of the extension and remove the extension
const extension = gltfScenegraph.getExtension(KHR_LIGHTS_PUNCTUAL);
if (extension) {
gltfScenegraph.json.lights = extension.lights;
gltfScenegraph.removeExtension(KHR_LIGHTS_PUNCTUAL);
}
// Move the light array out of the extension and remove the extension
const extension = gltfScenegraph.getExtension(KHR_LIGHTS_PUNCTUAL);
if (extension) {
gltfScenegraph.json.lights = extension.lights;
gltfScenegraph.removeExtension(KHR_LIGHTS_PUNCTUAL);
}

// Any nodes that have the extension, add lights field pointing to light object
// and remove the extension
for (const node of gltfScenegraph.nodes || []) {
const nodeExtension = node.extensions && node.extensions.KHR_lights_punctual;
if (nodeExtension) {
node.light = gltfScenegraph._get('lights', nodeExtension.light);
delete node.extensions.KHR_lights_punctual;
}
// Any nodes that have the extension, add lights field pointing to light object
// and remove the extension
for (const node of json.nodes || []) {
const nodeExtension = gltfScenegraph.getObjectExtension(node, KHR_LIGHTS_PUNCTUAL);
if (nodeExtension) {
node.light = nodeExtension.light;
}
gltfScenegraph.removeObjectExtension(node, KHR_LIGHTS_PUNCTUAL);
}
}

// Move the light ar ray out of the extension and remove the extension
static encode(gltfData, options) {
const gltfScenegraph = new GLTFScenegraph(gltfData);
const {json} = gltfScenegraph;
// Move the light ar ray out of the extension and remove the extension
export function encode(gltfData, options) {
const gltfScenegraph = new GLTFScenegraph(gltfData);
const {json} = gltfScenegraph;

if (json.lights) {
const extension = gltfScenegraph.addExtensions(KHR_LIGHTS_PUNCTUAL);
assert(!extension.lights);
extension.lights = json.lights;
delete json.lights;
}
if (json.lights) {
const extension = gltfScenegraph.addExtensions(KHR_LIGHTS_PUNCTUAL);
assert(!extension.lights);
extension.lights = json.lights;
delete json.lights;
}

// Any nodes that have lights field pointing to light object
// add the extension
if (gltfScenegraph.json.lights) {
for (const light of gltfScenegraph.json.lights) {
const node = light.node;
gltfScenegraph.addObjectExtension(node, KHR_LIGHTS_PUNCTUAL, light);
}
delete gltfScenegraph.json.lights;
// Any nodes that have lights field pointing to light object
// add the extension
if (gltfScenegraph.json.lights) {
for (const light of gltfScenegraph.json.lights) {
const node = light.node;
gltfScenegraph.addObjectExtension(node, KHR_LIGHTS_PUNCTUAL, light);
}
delete gltfScenegraph.json.lights;
}
}
17 changes: 9 additions & 8 deletions modules/gltf/src/lib/extensions/gltf-extensions.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
/* eslint-disable camelcase */
import KHR_draco_mesh_compression from './KHR_draco_mesh_compression';
import KHR_lights_punctual from './KHR_lights_punctual';
import * as KHR_draco_mesh_compression from './KHR_draco_mesh_compression';
import * as KHR_lights_punctual from './KHR_lights_punctual';
// import UBER_POINT_CLOUD_COMPRESSION from './KHR_draco_mesh_compression';

export const EXTENSIONS = {
KHR_draco_mesh_compression,
KHR_lights_punctual
};

export async function decodeExtensions(gltf, options, context) {
export async function decodeExtensions(gltf, options = {}, context) {
options.gltf = options.gltf || {};
for (const extensionName in EXTENSIONS) {
const disableExtension = extensionName in options && !options[extensionName];
if (!disableExtension) {
const excludes = options.gltf.excludeExtensions || {};
const exclude = extensionName in excludes && !excludes[extensionName];
if (!exclude) {
const extension = EXTENSIONS[extensionName];
// Note: We decode extensions sequentially, this might not be necessary
// Currently we only have glTF, but when we add Basis we may revisit
// Note: We decode async extensions sequentially, this might not be necessary
// Currently we only have Draco, but when we add Basis we may revisit
await extension.decode(gltf, options, context);
// TODO - warn if extension cannot be decoded synchronously?
}
}
}
1 change: 1 addition & 0 deletions modules/gltf/src/lib/gltf-constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
export const KHR_DRACO_MESH_COMPRESSION = 'KHR_draco_mesh_compression';
export const UBER_POINT_CLOUD_EXTENSION = 'UBER_draco_point_cloud_compression';
export const KHR_LIGHTS_PUNCTUAL = 'KHR_lights_punctual';
export const KHR_MATERIALS_UNLIT = 'KHR_materials_unlit';

const COMPONENTS = {
SCALAR: 1,
Expand Down
15 changes: 15 additions & 0 deletions modules/gltf/src/lib/gltf-scenegraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,21 @@ export default class GLTFScenegraph {
return this;
}

addObjectExtension(object, extensionName, data) {
assert(data);
object.extensions = object.extensions || {};
// TODO - clobber or merge?
object.extensions[extensionName] = data;
this.registerUsedExtension(extensionName);
return this;
}

removeObjectExtension(object, extensionName) {
const extensions = object.extensions || {};
delete extensions[extensionName];
return this;
}

// Add to standard GLTF top level extension object, mark as used
addExtension(extensionName, data) {
assert(data);
Expand Down
30 changes: 14 additions & 16 deletions modules/gltf/test/lib/extensions/KHR_lights_punctual.spec.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
/* eslint-disable max-len */
// import test from 'tape-promise/tape';
/* eslint-disable camelcase */
import test from 'tape-promise/tape';

// TBA
import {decodeExtensions} from '@loaders.gl/gltf/lib/extensions/gltf-extensions.js';

/* eslint-disable max-len, camelcase */
/*
import test from 'tape-promise/tape';
const TEST_CASES = [
{
name: 'KHR_lights_punctual',
Expand Down Expand Up @@ -39,23 +36,24 @@ const TEST_CASES = [
nodes: [
{
extensions: {},
id: 'node-0',
children: [],
light: {
color: [1.0, 1.0, 1.0],
type: 'directional'
}
light: 0
}
],
lights: [
{
color: [1.0, 1.0, 1.0],
type: 'directional'
}
]
}
}
];

test('gltf#KHR_lights_punctuals', t => {
test('gltf#KHR_lights_punctuals', async t => {
for (const testCase of TEST_CASES) {
const json = getResolvedJson(testCase.input);
t.deepEqual(json, testCase.output, testCase.name);
await decodeExtensions(testCase.input);
// Modifies input
t.deepEqual(testCase.input.json, testCase.output, testCase.name);
}
t.end();
});
*/

0 comments on commit 1bd8af6

Please sign in to comment.