From a5f1ad831eb946b226fb3beeea6b55cafaf88d97 Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Mon, 5 Dec 2016 17:09:52 -0500 Subject: [PATCH 01/47] Added updateVersion stage as well as some refactoring --- CHANGES.md | 4 + index.js | 1 + lib/Pipeline.js | 4 + lib/addDefaults.js | 83 +------- lib/getUniqueId.js | 55 ++--- lib/loadGltfUris.js | 10 +- lib/updateVersion.js | 355 +++++++++++++++++++++++++++++++++ specs/lib/addDefaultsSpec.js | 78 +------- specs/lib/updateVersionSpec.js | 265 ++++++++++++++++++++++++ 9 files changed, 651 insertions(+), 204 deletions(-) create mode 100644 lib/updateVersion.js create mode 100644 specs/lib/updateVersionSpec.js diff --git a/CHANGES.md b/CHANGES.md index 218b30bc..8f551313 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,10 @@ Change Log ========== +### Next Release + +* Added `updateVersion` stage for transitioning assets between glTF version and migrated any glTF 0.8 code out of `addDefaults` + ### 0.1.0-alpha6 - 2016-11-18 * Fixed `combinePrimitives` stage and re-added it to the pipeline. [#108](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/issues/108) diff --git a/index.js b/index.js index 8f5b79f2..87b64184 100644 --- a/index.js +++ b/index.js @@ -37,6 +37,7 @@ module.exports = { RemoveUnusedProperties : require('./lib/RemoveUnusedProperties'), removeUnusedVertices : require('./lib/removeUnusedVertices'), uninterleaveAndPackBuffers : require('./lib/uninterleaveAndPackBuffers'), + updateVersion : require('./lib/updateVersion'), writeAccessor : require('./lib/writeAccessor'), writeBinaryGltf : require('./lib/writeBinaryGltf'), writeBufferComponent : require('./lib/writeBufferComponent'), diff --git a/lib/Pipeline.js b/lib/Pipeline.js index 8a3fe5ea..1e7dc33f 100644 --- a/lib/Pipeline.js +++ b/lib/Pipeline.js @@ -25,6 +25,7 @@ var removeDuplicatePrimitives = require('./removeDuplicatePrimitives'); var removeNormals = require('./removeNormals'); var removePipelineExtras = require('./removePipelineExtras'); var quantizeAttributes = require('./quantizeAttributes'); +var updateVersion = require('./updateVersion'); var writeGltf = require('./writeGltf'); var writeBinaryGltf = require('./writeBinaryGltf'); var writeSource = require('./writeSource'); @@ -83,6 +84,9 @@ Pipeline.processJSONWithExtras = function(gltfWithExtras, options) { if (options.removeNormals) { removeNormals(gltfWithExtras); } + updateVersion(gltfWithExtras, { + targetVersion: '1.0' + }); addDefaults(gltfWithExtras, options); RemoveUnusedProperties.removeAll(gltfWithExtras); generateNormals(gltfWithExtras, options); diff --git a/lib/addDefaults.js b/lib/addDefaults.js index 33bf6626..d368be64 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -1,14 +1,11 @@ 'use strict'; var Cesium = require('cesium'); -var Cartesian3 = Cesium.Cartesian3; var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; -var Quaternion = Cesium.Quaternion; var WebGLConstants = Cesium.WebGLConstants; var addExtensionsUsed = require('./addExtensionsUsed'); -var findAccessorMinMax = require('./findAccessorMinMax'); var modelMaterialsCommon = require('./modelMaterialsCommon'); module.exports = addDefaults; @@ -23,11 +20,6 @@ function accessorDefaults(gltf) { if (accessors.hasOwnProperty(name)) { var accessor = accessors[name]; accessor.byteStride = defaultValue(accessor.byteStride, 0); - if (!defined(accessor.min) || !defined(accessor.max)) { - var minMax = findAccessorMinMax(gltf, accessor); - accessor.min = defaultValue(accessor.min, minMax.min); - accessor.max = defaultValue(accessor.max, minMax.max); - } } } } @@ -71,25 +63,13 @@ function assetDefaults(gltf) { gltf.asset = {}; } var asset = gltf.asset; - - // Backwards compatibility for glTF 0.8. profile was a string. - if (!defined(asset.profile) || (typeof asset.profile === 'string')) { + if (!defined(asset.profile)) { asset.profile = {}; } var profile = asset.profile; - asset.premultipliedAlpha = defaultValue(asset.premultipliedAlpha, false); profile.api = defaultValue(profile.api, 'WebGL'); - profile.version = defaultValue(profile.version, '1.0.2'); - - // glTF 0.8 backward compatibility - if (defined(gltf.version)) { - asset.version = defaultValue(asset.version, gltf.version); - delete gltf.version; - } - if (typeof asset.version === 'number') { - asset.version = asset.version.toFixed(1).toString(); - } + profile.version = defaultValue(profile.version, '1.0'); } function bufferDefaults(gltf) { @@ -201,15 +181,6 @@ function materialDefaults(gltf, options) { for (var name in materials) { if (materials.hasOwnProperty(name)) { var material = materials[name]; - var instanceTechnique = material.instanceTechnique; - if (defined(instanceTechnique)) { - // glTF 0.8 backward compatibility - material.technique = instanceTechnique.technique; - material.values = instanceTechnique.values; - - delete material.instanceTechnique; - } - if (!defined(material.technique)) { if (!defined(material.extensions) || Object.keys(material.extensions).length === 0) { guessExtensionTechnique(gltf, material, options); @@ -269,7 +240,6 @@ function meshDefaults(gltf) { for (var name in meshes) { if (meshes.hasOwnProperty(name)) { var mesh = meshes[name]; - if (!defined(mesh.primitives)) { mesh.primitives = []; } @@ -278,14 +248,11 @@ function meshDefaults(gltf) { var length = primitives.length; for (var i = 0; i < length; ++i) { var primitive = primitives[i]; - if (!defined(primitive.attributes)) { primitive.attributes = {}; } + primitive.mode = defaultValue(primitive.mode, WebGLConstants.TRIANGLES); - // Backwards compatibility for glTF 0.8. primitive was renamed to mode. - var defaultMode = defaultValue(primitive.primitive, WebGLConstants.TRIANGLES); - primitive.mode = defaultValue(primitive.mode, defaultMode); } } } @@ -296,10 +263,6 @@ function nodeDefaults(gltf) { gltf.nodes = {}; } var nodes = gltf.nodes; - var hasAxisAngle = (parseFloat(gltf.asset.version) < 1.0); - - var axis = new Cartesian3(); - var quat = new Quaternion(); for (var name in nodes) { if (nodes.hasOwnProperty(name)) { var node = nodes[name]; @@ -308,14 +271,6 @@ function nodeDefaults(gltf) { node.children = []; } - if (hasAxisAngle && defined(node.rotation)) { - // glTF 0.8 backward compatibility - var rotation = node.rotation; - Cartesian3.fromArray(rotation, 0, axis); - Quaternion.fromAxisAngle(axis, rotation[3], quat); - node.rotation = [quat.x, quat.y, quat.z, quat.w]; - } - if (!defined(node.matrix)) { // Add default identity matrix if there is no matrix property and no TRS properties if (!defined(node.translation) && !defined(node.rotation) && !defined(node.scale)) { @@ -339,14 +294,6 @@ function nodeDefaults(gltf) { } } } - - var instanceSkin = node.instanceSkin; - if (defined(instanceSkin)) { - node.skeletons = instanceSkin.skeletons; - node.skin = instanceSkin.skin; - node.meshes = instanceSkin.meshes; - delete node.instanceSkin; - } } } } @@ -459,25 +406,6 @@ function techniqueDefaults(gltf, options) { parameters.diffuse.semantic = '_3DTILESDIFFUSE'; } - var passes = technique.passes; - if (defined(passes)) { - // glTF 0.8 backward compatibility - var passName = defaultValue(technique.pass, 'defaultPass'); - if (passes.hasOwnProperty(passName)) { - var pass = passes[passName]; - var instanceProgram = pass.instanceProgram; - - technique.attributes = defaultValue(technique.attributes, instanceProgram.attributes); - technique.program = defaultValue(technique.program, instanceProgram.program); - technique.uniforms = defaultValue(technique.uniforms, instanceProgram.uniforms); - - technique.states = defaultValue(technique.states, pass.states); - } - - technique.passes = undefined; - technique.pass = undefined; - } - if (!defined(technique.attributes)) { technique.attributes = {}; } @@ -527,11 +455,6 @@ function textureDefaults(gltf) { */ function addDefaults(gltf, options) { options = defaultValue(options, {}); - - if (defined(gltf.allExtensions)) { - gltf.extensionsUsed = gltf.allExtensions; - gltf.allExtensions = undefined; - } gltf.extensionsUsed = defaultValue(gltf.extensionsUsed, []); accessorDefaults(gltf); diff --git a/lib/getUniqueId.js b/lib/getUniqueId.js index 1230faec..3ff93adf 100644 --- a/lib/getUniqueId.js +++ b/lib/getUniqueId.js @@ -12,49 +12,18 @@ module.exports = getUniqueId; * @returns {String} A unique id beginning with prefix. */ function getUniqueId(gltf, prefix) { - var prefixMatches = {}; - - // Check top level objects with ids for instances of the prefix - checkForPrefix(gltf.nodes, prefixMatches, prefix); - checkForPrefix(gltf.skins, prefixMatches, prefix); - checkForPrefix(gltf.cameras, prefixMatches, prefix); - checkForPrefix(gltf.meshes, prefixMatches, prefix); - checkForPrefix(gltf.accessors, prefixMatches, prefix); - checkForPrefix(gltf.materials, prefixMatches, prefix); - checkForPrefix(gltf.bufferViews, prefixMatches, prefix); - checkForPrefix(gltf.techniques, prefixMatches, prefix); - checkForPrefix(gltf.textures, prefixMatches, prefix); - checkForPrefix(gltf.buffers, prefixMatches, prefix); - checkForPrefix(gltf.programs, prefixMatches, prefix); - checkForPrefix(gltf.images, prefixMatches, prefix); - checkForPrefix(gltf.samplers, prefixMatches, prefix); - checkForPrefix(gltf.shaders, prefixMatches, prefix); - - // Generate a new ID based on the prefix and any occurrences of the prefix throughout the json - // Case where the prefix is already unique - if (!prefixMatches[prefix]) { - return prefix; - } - - // Impossible for prefixMatches to contain all strings of form 'prefix_X', 0 <= X < count, and 'prefix' - var prefixMatchCount = Object.keys(prefixMatches).length; - for (var i = 0; i < prefixMatchCount; i++) { - var newID = prefix + '_' + i; - if (!prefixMatches[newID]) { - return newID; - } - } -} - -function checkForPrefix(topLevelObject, prefixMatches, prefix) { - if (defined(topLevelObject)) { - var objectIds = Object.keys(topLevelObject); - var objectIdCount = objectIds.length; - for (var j = 0; j < objectIdCount; j++) { - var idString = objectIds[j]; - if (idString.startsWith(prefix)) { - prefixMatches[idString] = true; + var id = prefix; + var appendIndex = 0; + for (var topLevelGroupId in gltf) { + if (gltf.hasOwnProperty(topLevelGroupId)) { + var topLevelGroup = gltf[topLevelGroupId]; + var match = topLevelGroup[id]; + while (defined(match)) { + id = prefix + '_' + appendIndex; + match = topLevelGroup[id]; + appendIndex++; } } } -} + return id; +} \ No newline at end of file diff --git a/lib/loadGltfUris.js b/lib/loadGltfUris.js index e0ef60a6..3aa86715 100644 --- a/lib/loadGltfUris.js +++ b/lib/loadGltfUris.js @@ -22,15 +22,15 @@ module.exports = loadGltfUris; * glTF must be initialized for the pipeline. * * @param {Object} gltf A javascript object containing a glTF asset. - * @param {Object} options Options for loading uris. - * @param {String} options.basePath The path to look in when loading external files. + * @param {Object} [options] Options for loading uris. + * @param {String} [options.basePath] The path to look in when loading external files. * @returns {Promise} A promise that resolves to the glTF asset when all uris are loaded. * * @see addPipelineExtras */ function loadGltfUris(gltf, options) { options = defaultValue(options, {}); - var basePath = options.basePath; + var basePath = defaultValue(options.basePath, ''); var loadURIs = [ loadURI(gltf, basePath, 'buffers'), loadURI(gltf, basePath, 'images'), @@ -53,7 +53,9 @@ function loadURI(gltf, basePath, name) { var object = objects[id]; var uri = object.uri; object.extras = defaultValue(object.extras, {}); - object.extras._pipeline = defaultValue(object.extras._pipeline, {}); + object.extras._pipeline = defaultValue(object.extras._pipeline, { + deleteExtras: true + }); //Load the uri into the extras object based on the uri type if (isDataUri(uri)) { if (!defined(object.extras._pipeline.source)) { diff --git a/lib/updateVersion.js b/lib/updateVersion.js new file mode 100644 index 00000000..7fbaf7ca --- /dev/null +++ b/lib/updateVersion.js @@ -0,0 +1,355 @@ +'use strict'; +var Cesium = require('cesium'); + +var getUniqueId = require('./getUniqueId'); +var findAccessorMinMax = require('./findAccessorMinMax'); +var loadGltfUris = require('./loadGltfUris'); + +var Cartesian3 = Cesium.Cartesian3; +var DeveloperError = Cesium.DeveloperError; +var Quaternion = Cesium.Quaternion; +var WebGLConstants = Cesium.WebGLConstants; +var defaultValue = Cesium.defaultValue; +var defined = Cesium.defined; + +module.exports = updateVersion; + +var updateFunctions = { + '0.8' : glTF_0_8_to_glTF_1_0, + '1.0' : glTF_1_0_to_glTF_1_1 +}; + +/** + * Update the glTF version to the latest (1.1), or targetVersion if specified. + * Applies changes made to the glTF spec between revisions so that the core library + * only has to handle the latest version. + * + * @param {Object} gltf A javascript object containing a glTF asset. + * @param {Object} [options] Options for updating the glTF. + * @param {String} [options.targetVersion] The glTF will be upgraded until it hits the specified version. + * @returns {Object} The updated glTF asset. + */ +function updateVersion(gltf, options) { + options = defaultValue(options, {}); + var targetVersion = options.targetVersion; + var version = gltf.version; + if (defined(gltf.asset)) { + version = defaultValue(version, gltf.asset.version); + } + if (!defined(version)) { + throw new DeveloperError('glTF must have a defined version'); + } + var updateFunction = updateFunctions[version]; + while (defined(updateFunction)) { + updateFunction(gltf); + version = gltf.asset.version; + if (version === targetVersion) { + break; + } + updateFunction = updateFunctions[version]; + } + return gltf; +} + +function glTF_0_8_to_glTF_1_0(gltf) { + if (!defined(gltf.asset)) { + gltf.asset = {}; + } + var asset = gltf.asset; + asset.version = '1.0'; + // profile should be an object, not a string + if (!defined(asset.profile) || (typeof asset.profile === 'string')) { + asset.profile = {}; + } + // version property should be in asset, not on the root element + if (defined(gltf.version)) { + delete gltf.version; + } + // material.instanceTechnique properties should be directly on the material + var materials = gltf.materials; + for (var materialId in materials) { + if (materials.hasOwnProperty(materialId)) { + var material = materials[materialId]; + var instanceTechnique = material.instanceTechnique; + if (defined(instanceTechnique)) { + material.technique = instanceTechnique.technique; + material.values = instanceTechnique.values; + delete material.instanceTechnique; + } + } + } + // primitive.primitive should primitive.mode + var meshes = gltf.meshes; + for (var meshId in meshes) { + if (meshes.hasOwnProperty(meshId)) { + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + if (defined(primitives)) { + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + var primitive = primitives[i]; + var defaultMode = defaultValue(primitive.primitive, WebGLConstants.TRIANGLES); + primitive.mode = defaultValue(primitive.mode, defaultMode); + delete primitive.primitive; + } + } + } + } + // node rotation should be quaternion, not axis-angle + // node.instanceSkin is deprecated + var nodes = gltf.nodes; + var axis = new Cartesian3(); + var quat = new Quaternion(); + for (var nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + var node = nodes[nodeId]; + if (defined(node.rotation)) { + var rotation = node.rotation; + Cartesian3.fromArray(rotation, 0, axis); + Quaternion.fromAxisAngle(axis, rotation[3], quat); + node.rotation = [quat.x, quat.y, quat.z, quat.w]; + } + var instanceSkin = node.instanceSkin; + if (defined(instanceSkin)) { + node.skeletons = instanceSkin.skeletons; + node.skin = instanceSkin.skin; + node.meshes = instanceSkin.meshes; + delete node.instanceSkin; + } + } + } + // technique.pass and techniques.passes are deprecated + var techniques = gltf.techniques; + for (var techniqueId in techniques) { + if (techniques.hasOwnProperty(techniqueId)) { + var technique = techniques[techniqueId]; + var passes = technique.passes; + if (defined(passes)) { + var passName = defaultValue(technique.pass, 'defaultPass'); + if (passes.hasOwnProperty(passName)) { + var pass = passes[passName]; + var instanceProgram = pass.instanceProgram; + technique.attributes = defaultValue(technique.attributes, instanceProgram.attributes); + technique.program = defaultValue(technique.program, instanceProgram.program); + technique.uniforms = defaultValue(technique.uniforms, instanceProgram.uniforms); + technique.states = defaultValue(technique.states, pass.states); + } + delete technique.passes; + delete technique.pass; + } + } + } + // gltf.allExtensions -> extensionsUsed + if (defined(gltf.allExtensions)) { + gltf.extensionsUsed = gltf.allExtensions; + gltf.allExtensions = undefined; + } +} + +function glTF_1_0_to_glTF_1_1(gltf) { + if (!defined(gltf.asset)) { + gltf.asset = {}; + } + var asset = gltf.asset; + asset.version = '1.1'; + // profile.version does not include revision number ("1.0.3" -> "1.0") + var profile = asset.profile; + if (defined(profile)) { + var version = profile.version; + if (defined(version)) { + profile.version = version[0] + '.' + version[2]; + } + } + // animation.samplers now refers directly to accessors and animation.parameters should be removed + var animations = gltf.animations; + for (var animationId in animations) { + if (animations.hasOwnProperty(animationId)) { + var animation = animations[animationId]; + var parameters = animation.parameters; + var samplers = animation.samplers; + for (var samplerId in samplers) { + if (samplers.hasOwnProperty(samplerId)) { + var sampler = samplers[samplerId]; + sampler.input = parameters[sampler.input]; + sampler.output = parameters[sampler.output]; + } + } + delete animation.parameters; + } + } + // material.values should be arrays + var materials = gltf.materials; + for (var materialId in materials) { + if (materials.hasOwnProperty(materialId)) { + var material = materials[materialId]; + var materialValues = material.values; + for (var materialValueId in materialValues) { + if (materialValues.hasOwnProperty(materialValueId)) { + var materialValue = materialValues[materialValueId]; + if (!Array.isArray(materialValue)) { + materialValues[materialValueId] = [materialValue]; + } + } + } + } + } + // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#) + var meshes = gltf.meshes; + var i; + for (var meshId in meshes) { + if (meshes.hasOwnProperty(meshId)) { + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + if (defined(primitives)) { + var primitivesLength = primitives.length; + for (i = 0; i < primitivesLength; i++) { + var primitive = primitives[i]; + var attributes = primitive.attributes; + var semantics = Object.keys(attributes); + var semanticsLength = semantics.length; + for (var j = 0; j < semanticsLength; j++) { + var semantic = semantics[j]; + if (semantic === 'TEXCOORD') { + attributes.TEXCOORD_0 = attributes[semantic]; + delete attributes[semantic]; + } + if (semantic === 'COLOR') { + attributes.COLOR_0 = attributes[semantic]; + delete attributes[semantic]; + } + } + } + } + } + } + // technique.parameters.value should be arrays + // TEXCOORD and COLOR semantics must be written with a set index (TEXCOORD_#) + var techniques = gltf.techniques; + for (var techniqueId in techniques) { + if (techniques.hasOwnProperty(techniqueId)) { + var technique = techniques[techniqueId]; + var techniqueParameters = technique.parameters; + for (var techniqueParameterId in techniqueParameters) { + if (techniqueParameters.hasOwnProperty(techniqueParameterId)) { + var techniqueParameter = techniqueParameters[techniqueParameterId]; + var techniqueParameterValue = techniqueParameter.value; + if (defined(techniqueParameterValue) && !Array.isArray(techniqueParameterValue)) { + techniqueParameter.value = [techniqueParameterValue]; + } + var techniqueParameterSemantic = techniqueParameter.semantic; + if (defined(techniqueParameterSemantic)) { + if (techniqueParameterSemantic === 'TEXCOORD') { + techniqueParameter.semantic = 'TEXCOORD_0'; + } else if (techniqueParameterSemantic === 'COLOR') { + techniqueParameter.semantic = 'COLOR_0'; + } + } + } + } + } + } + // accessor.min and accessor.max must be defined + var accessors = gltf.accessors; + var bufferViews = gltf.bufferViews; + var buffers = gltf.buffers; + for (var accessorId in accessors) { + if (accessors.hasOwnProperty(accessorId)) { + var accessor = accessors[accessorId]; + if (!defined(accessor.min) || !defined(accessor.max)) { + var bufferViewId = accessor.bufferView; + var bufferView = bufferViews[bufferViewId]; + var bufferId = bufferView.buffer; + var buffer = buffers[bufferId]; + if (!defined(buffer.extras) || !defined(buffer.extras._pipeline) || !defined(buffer.extras._pipeline.source)) { + // glTF uris need to be loaded into extras for findAccessorMinMax + loadGltfUris(gltf); + } + var minMax = findAccessorMinMax(gltf, accessor); + accessor.min = minMax.min; + accessor.max = minMax.max; + } + } + } + // skeleton hierarchy must be separate from the node hierarchy (a node with jointName cannot contain camera, skeletons, skins, or meshes) + var nodes = gltf.nodes; + var node; + var nodeId; + var nodeStack = []; + var mappedSkeletonNodes = {}; + var parentNodes = {}; + for (nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + nodeStack.push(nodeId); + node = nodes[nodeId]; + var children = node.children; + if (defined(children)) { + var childrenLength = children.length; + for (i = 0; i < childrenLength; i++) { + var childNodeId = children[i]; + parentNodes[childNodeId] = nodeId; + } + } + } + } + while (nodeStack.length > 0) { + nodeId = nodeStack.pop(); + node = nodes[nodeId]; + var jointName = node.jointName; + if (defined(jointName)) { + // this node is a joint; clone the hierarchy + if (!defined(node.camera) && !defined(node.skeletons) && !defined(node.skins) && !defined(node.meshes) && !defined(node.children)) { + // the original node can be removed since it is only a skeleton node + var parentId = parentNodes[nodeId]; + if (defined(parentId)) { + var parentChildren = nodes[parentId].children; + parentChildren.splice(parentChildren.indexOf(nodeId), 1); + } + delete nodes[nodeId]; + } + var lastNodeId; + var skeletonNode; + var end = false; + while (defined(nodeId)) { + var skeletonNodeId = mappedSkeletonNodes[nodeId]; + if (!defined(skeletonNodeId)) { + skeletonNodeId = getUniqueId(gltf, nodeId + '-skeleton'); + skeletonNode = { + jointName: jointName + }; + if (defined(node.translation) || defined(node.rotation) || defined(node.scale)) { + skeletonNode.translation = defaultValue(node.translation, [0.0, 0.0, 0.0]); + skeletonNode.rotation = defaultValue(node.rotation, [0.0, 0.0, 0.0, 1.0]); + skeletonNode.scale = defaultValue(node.scale, [1.0, 1.0, 1.0]); + } else { + skeletonNode.matrix = defaultValue(node.matrix, [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0]); + } + delete node.jointName; + nodes[skeletonNodeId] = skeletonNode; + mappedSkeletonNodes[nodeId] = skeletonNodeId; + } else { + end = true; + } + if (defined(lastNodeId)) { + skeletonNode = nodes[skeletonNodeId]; + var skeletonChildren = skeletonNode.children; + if (!defined(skeletonChildren)) { + skeletonNode.children = [lastNodeId]; + } else { + skeletonChildren.push(lastNodeId); + } + } + if (end) { + break; + } + lastNodeId = skeletonNodeId; + nodeId = parentNodes[nodeId]; + node = nodes[nodeId]; + } + } + } +} + diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index 102bf179..a7cef733 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -34,8 +34,6 @@ describe('addDefaults', function() { addDefaults(gltf); var accessor = gltf.accessors.accessorId; expect(accessor.byteStride).toEqual(0); - expect(accessor.min).toBeDefined(); - expect(accessor.max).toBeDefined(); }); it('Adds animation properties', function() { @@ -91,17 +89,9 @@ describe('addDefaults', function() { expect(gltf.asset.premultipliedAlpha).toEqual(false); expect(gltf.asset.profile).toBeDefined(); expect(gltf.asset.profile.api).toEqual('WebGL'); - expect(gltf.asset.profile.version).toEqual('1.0.2'); + expect(gltf.asset.profile.version).toEqual('1.0'); }); - it('Updates version property from glTF 0.8', function() { - var gltf = { - "version" : 0.8 - }; - - addDefaults(gltf); - expect(gltf.asset.version).toEqual('0.8'); - }); it('Adds buffer properties', function() { var gltf = { @@ -663,25 +653,6 @@ describe('addDefaults', function() { expect(gltf.meshes.meshId.primitives[0].mode).toEqual(WebGLConstants.TRIANGLES); }); - it('glTF 0.8 to 1.0, primitive.primitive -> primitive.mode', function() { - var gltf = { - "meshes": { - "meshId": { - "primitives": [ - { - "indices": "accessorId", - "material": "materialId", - "primitive": 5 - } - ] - } - } - }; - - addDefaults(gltf); - expect(gltf.meshes.meshId.primitives[0].mode).toEqual(WebGLConstants.TRIANGLE_STRIP); - }); - it('Adds node properties', function() { var gltf = { "nodes": { @@ -719,40 +690,6 @@ describe('addDefaults', function() { expect(gltf.nodes.nodeId.rotation).toEqual([0.0, 0.0, 0.0, 1.0]); }); - it('glTF 0.8 to 1.0, node.instanceSkin -> node', function() { - var gltf = { - "nodes": { - "nodeId": { - "instanceSkin": { - "skeletons": {}, - "skin": {}, - "meshes": {} - } - } - } - }; - - addDefaults(gltf); - expect(gltf.nodes.nodeId.skeletons).toBeDefined(); - expect(gltf.nodes.nodeId.skin).toBeDefined(); - expect(gltf.nodes.nodeId.meshes).toBeDefined(); - expect(gltf.nodes.nodeId.instanceSkin).not.toBeDefined(); - }); - - it('glTF 0.8 to 1.0, axis angle -> quaternion', function() { - var gltf = { - "version": 0.8, - "nodes": { - "nodeId": { - "rotation": [1.0, 0.0, 0.0, 0.0] - } - } - }; - - addDefaults(gltf); - expect(gltf.nodes.nodeId.rotation).toEqual([0.0, 0.0, 0.0, 1.0]); - }); - it('Adds program properties', function() { var gltf = { "programs": { @@ -831,19 +768,6 @@ describe('addDefaults', function() { expect(gltf.textures.textureId.type).toEqual(WebGLConstants.UNSIGNED_BYTE); }); - - it('glTF 0.8 to 1.0, allExtensions -> extensionsUsed', function() { - var gltf = { - "allExtensions": [ - "KHR_materials_common" - ] - }; - - addDefaults(gltf); - expect(gltf.allExtensions).not.toBeDefined(); - expect(gltf.extensionsUsed).toBeDefined(); - }); - it('Adds empty top-level properties', function() { var gltf = {}; diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js new file mode 100644 index 00000000..800ebbed --- /dev/null +++ b/specs/lib/updateVersionSpec.js @@ -0,0 +1,265 @@ +'use strict'; +var Cesium = require('cesium'); + +var updateVersion = require('../../lib/updateVersion'); + +var WebGLConstants = Cesium.WebGLConstants; + +describe('updateVersion', function() { + it('throws an error if gltf has no version', function() { + var gltf = {}; + expect(function() { + updateVersion(gltf); + }).toThrowDeveloperError(); + }); + + it('updates empty glTF with version from 0.8 to 1.1', function() { + var gltf = { + version: '0.8' + }; + updateVersion(gltf); + expect(gltf.version).not.toBeDefined(); + expect(gltf.asset.version).toBe('1.1'); + }); + + it('updates empty glTF with version 1.0 to 1.1', function() { + var gltf = { + asset : { + version: '1.0' + } + }; + updateVersion(gltf); + expect(gltf.asset.version).toBe('1.1'); + }); + + it('updates glTF from 0.8 to 1.0', function() { + var gltf = { + version: '0.8', + asset: { + profile: 'WebGL 1.0' + }, + allExtensions: [ + 'extension' + ], + materials: { + material: { + instanceTechnique: { + technique: 'technique', + values: { + ambient: [0.0, 0.0, 0.0, 1.0] + } + } + } + }, + meshes: { + mesh: { + primitives: [ + { + primitive: WebGLConstants.TRIANGLES + } + ] + } + }, + nodes: { + node: { + rotation: [0.0, 0.0, 1.0, 0.0], + instanceSkin: { + skeletons: ['skeleton'], + skin: 'skin', + meshes: ['mesh'] + } + } + }, + techniques: { + technique: { + pass: 'pass', + passes: { + pass: { + instanceProgram: { + attributes: { + attribute: 'TEST_ATTRIBUTE' + }, + program: 'program', + uniforms: { + uniform: 'TEST_UNIFORM' + } + }, + states: ['TEST_STATE'] + } + } + } + } + }; + updateVersion(gltf, { + targetVersion: '1.0' + }); + expect(gltf.asset.version).toBe('1.0'); + expect(gltf.asset.profile).toEqual({}); + expect(gltf.version).not.toBeDefined(); + expect(gltf.extensionsUsed).toEqual(['extension']); + var material = gltf.materials.material; + expect(material.technique).toBe('technique'); + expect(material.values).toEqual({ + 'ambient': [0.0, 0.0, 0.0, 1.0] + }); + var primitive = gltf.meshes.mesh.primitives[0]; + expect(primitive.primitive).not.toBeDefined(); + expect(primitive.mode).toBe(WebGLConstants.TRIANGLES); + var node = gltf.nodes.node; + expect(node.rotation).toEqual([0.0, 0.0, 0.0, 1.0]); + expect(node.skeletons).toEqual(['skeleton']); + expect(node.skin).toBe('skin'); + expect(node.meshes).toEqual(['mesh']); + var technique = gltf.techniques.technique; + expect(technique.pass).not.toBeDefined(); + expect(technique.passes).not.toBeDefined(); + expect(technique.attributes).toEqual({ + attribute: 'TEST_ATTRIBUTE' + }); + expect(technique.program).toBe('program'); + expect(technique.uniforms).toEqual({ + uniform: 'TEST_UNIFORM' + }); + expect(technique.states).toEqual(['TEST_STATE']); + }); + + it('updates glTF from 1.0 to 1.1', function() { + var buffer = new Buffer(new Int16Array([-2.0, 1.0, 0.0, 1.0, 2.0, 3.0]).buffer); + var gltf = { + asset: { + profile: { + version: '1.0.3' + }, + version: '1.0' + }, + animations: { + animation: { + samplers: { + sampler: { + input: 'INPUT', + output: 'OUTPUT' + } + }, + parameters: { + INPUT: 'accessor_input', + OUTPUT: 'accessor_output' + } + } + }, + meshes: { + mesh: { + primitives: [ + { + attributes: { + TEXCOORD: 'accessor_texcoord', + COLOR: 'accessor_color' + } + } + ] + } + }, + materials: { + material: { + values: { + shininess: 1.0 + } + } + }, + techniques: { + technique: { + parameters: { + lightAttenuation: { + value: 1.0 + }, + texcoord: { + semantic: 'TEXCOORD' + }, + color: { + semantic: 'COLOR' + } + } + } + }, + accessors: { + accessor: { + byteOffset: 0, + byteStride: 0, + bufferView: 'bufferView', + componentType: WebGLConstants.SHORT, + count: 6, + type: 'SCALAR' + } + }, + bufferViews: { + bufferView: { + buffer: 'buffer', + byteLength: buffer.length, + byteOffset: 0 + } + }, + buffers: { + buffer: { + byteLength: buffer.length, + extras: { + _pipeline: { + source: buffer + } + } + } + }, + nodes: { + meshNode: { + meshes: ['mesh'] + }, + rootNode: { + children: ['jointNodeOne', 'jointNodeTwo', 'meshNode'] + }, + jointNodeOne: { + jointName: 'jointOne', + meshes: ['mesh'] + }, + jointNodeTwo: { + jointName: 'jointTwo', + translation: [1.0, 0.0, 0.0] + } + } + }; + updateVersion(gltf, { + targetVersion: '1.1' + }); + expect(gltf.asset.profile.version).toEqual('1.0'); + var animation = gltf.animations.animation; + var sampler = animation.samplers.sampler; + expect(sampler.input).toBe('accessor_input'); + expect(sampler.output).toBe('accessor_output'); + expect(animation.parameters).not.toBeDefined(); + var material = gltf.materials.material; + expect(material.values.shininess).toEqual([1.0]); + var technique = gltf.techniques.technique; + expect(technique.parameters.lightAttenuation.value).toEqual([1.0]); + expect(technique.parameters.texcoord.semantic).toBe('TEXCOORD_0'); + expect(technique.parameters.color.semantic).toBe('COLOR_0'); + var accessor = gltf.accessors.accessor; + expect(accessor.min).toEqual([-2.0]); + expect(accessor.max).toEqual([3.0]); + var primitive = gltf.meshes.mesh.primitives[0]; + expect(primitive.attributes.TEXCOORD).not.toBeDefined(); + expect(primitive.attributes.TEXCOORD_0).toBe('accessor_texcoord'); + expect(primitive.attributes.COLOR).not.toBeDefined(); + expect(primitive.attributes.COLOR_0).toBe('accessor_color'); + var nodes = gltf.nodes; + var rootNode = nodes.rootNode; + expect(rootNode.children).toEqual(['jointNodeOne', 'meshNode']); + var rootNodeSkeleton = nodes['rootNode-skeleton']; + expect(rootNodeSkeleton.matrix).toBeDefined(); + expect(rootNodeSkeleton.children).toEqual(['jointNodeTwo-skeleton', 'jointNodeOne-skeleton']); + var jointNodeOneSkeleton = nodes['jointNodeOne-skeleton']; + expect(jointNodeOneSkeleton.meshes).not.toBeDefined(); + var jointNodeOne = nodes.jointNodeOne; + expect(jointNodeOne.meshes).toEqual(['mesh']); + expect(jointNodeOne.jointName).not.toBeDefined(); + var jointNodeTwoSkeleton = nodes['jointNodeTwo-skeleton']; + expect(jointNodeTwoSkeleton.translation).toEqual([1.0, 0.0, 0.0]); + expect(nodes.jointNodeTwo).not.toBeDefined(); + }); +}); \ No newline at end of file From b4ff28165491e03cb7312a27a218f8b1a2630cf8 Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Wed, 14 Dec 2016 15:40:39 -0500 Subject: [PATCH 02/47] Split out into multiple functions --- lib/updateVersion.js | 313 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 261 insertions(+), 52 deletions(-) diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 7fbaf7ca..1acb13d1 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -6,6 +6,7 @@ var findAccessorMinMax = require('./findAccessorMinMax'); var loadGltfUris = require('./loadGltfUris'); var Cartesian3 = Cesium.Cartesian3; +var CesiumMath = Cesium.CesiumMath; var DeveloperError = Cesium.DeveloperError; var Quaternion = Cesium.Quaternion; var WebGLConstants = Cesium.WebGLConstants; @@ -15,8 +16,8 @@ var defined = Cesium.defined; module.exports = updateVersion; var updateFunctions = { - '0.8' : glTF_0_8_to_glTF_1_0, - '1.0' : glTF_1_0_to_glTF_1_1 + '0.8' : glTF08to10, + '1.0' : glTF10to11 }; /** @@ -37,7 +38,7 @@ function updateVersion(gltf, options) { version = defaultValue(version, gltf.asset.version); } if (!defined(version)) { - throw new DeveloperError('glTF must have a defined version'); + version = '1.0'; } var updateFunction = updateFunctions[version]; while (defined(updateFunction)) { @@ -51,21 +52,7 @@ function updateVersion(gltf, options) { return gltf; } -function glTF_0_8_to_glTF_1_0(gltf) { - if (!defined(gltf.asset)) { - gltf.asset = {}; - } - var asset = gltf.asset; - asset.version = '1.0'; - // profile should be an object, not a string - if (!defined(asset.profile) || (typeof asset.profile === 'string')) { - asset.profile = {}; - } - // version property should be in asset, not on the root element - if (defined(gltf.version)) { - delete gltf.version; - } - // material.instanceTechnique properties should be directly on the material +function updateInstanceTechniques(gltf) { var materials = gltf.materials; for (var materialId in materials) { if (materials.hasOwnProperty(materialId)) { @@ -78,7 +65,9 @@ function glTF_0_8_to_glTF_1_0(gltf) { } } } - // primitive.primitive should primitive.mode +} + +function setPrimitiveModes(gltf) { var meshes = gltf.meshes; for (var meshId in meshes) { if (meshes.hasOwnProperty(meshId)) { @@ -95,8 +84,9 @@ function glTF_0_8_to_glTF_1_0(gltf) { } } } - // node rotation should be quaternion, not axis-angle - // node.instanceSkin is deprecated +} + +function updateNodes(gltf) { var nodes = gltf.nodes; var axis = new Cartesian3(); var quat = new Quaternion(); @@ -118,7 +108,9 @@ function glTF_0_8_to_glTF_1_0(gltf) { } } } - // technique.pass and techniques.passes are deprecated +} + +function removeTechniquePasses(gltf) { var techniques = gltf.techniques; for (var techniqueId in techniques) { if (techniques.hasOwnProperty(techniqueId)) { @@ -139,6 +131,31 @@ function glTF_0_8_to_glTF_1_0(gltf) { } } } +} + +function glTF08to10(gltf) { + if (!defined(gltf.asset)) { + gltf.asset = {}; + } + var asset = gltf.asset; + asset.version = '1.0'; + // profile should be an object, not a string + if (!defined(asset.profile) || (typeof asset.profile === 'string')) { + asset.profile = {}; + } + // version property should be in asset, not on the root element + if (defined(gltf.version)) { + delete gltf.version; + } + // material.instanceTechnique properties should be directly on the material + updateInstanceTechniques(gltf); + // primitive.primitive should be primitive.mode + setPrimitiveModes(gltf); + // node rotation should be quaternion, not axis-angle + // node.instanceSkin is deprecated + updateNodes(gltf); + // technique.pass and techniques.passes are deprecated + removeTechniquePasses(gltf); // gltf.allExtensions -> extensionsUsed if (defined(gltf.allExtensions)) { gltf.extensionsUsed = gltf.allExtensions; @@ -146,13 +163,8 @@ function glTF_0_8_to_glTF_1_0(gltf) { } } -function glTF_1_0_to_glTF_1_1(gltf) { - if (!defined(gltf.asset)) { - gltf.asset = {}; - } +function stripWebGLRevisionNumber(gltf) { var asset = gltf.asset; - asset.version = '1.1'; - // profile.version does not include revision number ("1.0.3" -> "1.0") var profile = asset.profile; if (defined(profile)) { var version = profile.version; @@ -160,7 +172,56 @@ function glTF_1_0_to_glTF_1_1(gltf) { profile.version = version[0] + '.' + version[2]; } } - // animation.samplers now refers directly to accessors and animation.parameters should be removed +} + +var knownExtensions = { + CESIUM_RTC : true, + KHR_binary_glTF : true, + KHR_materials_common : true, + WEB3D_quantized_attributes : true +}; +function requireKnownExtensions(gltf) { + var extensionsUsed = gltf.extensionsUsed; + gltf.extensionsRequired = defaultValue(gltf.extensionsRequired, []); + if (defined(extensionsUsed)) { + var extensionsUsedLength = extensionsUsed.length; + for (var i = 0; i < extensionsUsedLength; i++) { + var extension = extensionsUsed[i]; + if (defined(knownExtensions[extension])) { + gltf.extensionsRequired.push(extension); + extensionsUsed.splice(i, 1); + i--; + } + } + } +} + +function addGlExtensionsUsed(gltf) { + var accessors = gltf.accessors; + var meshes = gltf.meshes; + for (var meshId in meshes) { + if (meshes.hasOwnProperty(meshId)) { + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + if (defined(primitives)) { + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + var primitive = primitives[i]; + var indicesAccessorId = primitive.indices; + if (defined(indicesAccessorId)) { + var indicesAccessor = accessors[indicesAccessorId]; + if (indicesAccessor.componentType === WebGLConstants.UNSIGNED_INT) { + gltf.glExtensionsUsed = ['OES_element_index_uint']; + return; + } + } + } + } + } + } +} + +function removeAnimationSamplersIndirection(gltf) { var animations = gltf.animations; for (var animationId in animations) { if (animations.hasOwnProperty(animationId)) { @@ -177,7 +238,19 @@ function glTF_1_0_to_glTF_1_1(gltf) { delete animation.parameters; } } - // material.values should be arrays +} + +function removeBufferType(gltf) { + var buffers = gltf.buffers; + for (var bufferId in buffers) { + if (buffers.hasOwnProperty(bufferId)) { + var buffer = buffers[bufferId]; + delete buffer.type; + } + } +} + +function makeMaterialValuesArray(gltf) { var materials = gltf.materials; for (var materialId in materials) { if (materials.hasOwnProperty(materialId)) { @@ -193,16 +266,17 @@ function glTF_1_0_to_glTF_1_1(gltf) { } } } - // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#) +} + +function requireAttributeSetIndex(gltf) { var meshes = gltf.meshes; - var i; for (var meshId in meshes) { if (meshes.hasOwnProperty(meshId)) { var mesh = meshes[meshId]; var primitives = mesh.primitives; if (defined(primitives)) { var primitivesLength = primitives.length; - for (i = 0; i < primitivesLength; i++) { + for (var i = 0; i < primitivesLength; i++) { var primitive = primitives[i]; var attributes = primitive.attributes; var semantics = Object.keys(attributes); @@ -222,8 +296,6 @@ function glTF_1_0_to_glTF_1_1(gltf) { } } } - // technique.parameters.value should be arrays - // TEXCOORD and COLOR semantics must be written with a set index (TEXCOORD_#) var techniques = gltf.techniques; for (var techniqueId in techniques) { if (techniques.hasOwnProperty(techniqueId)) { @@ -232,10 +304,6 @@ function glTF_1_0_to_glTF_1_1(gltf) { for (var techniqueParameterId in techniqueParameters) { if (techniqueParameters.hasOwnProperty(techniqueParameterId)) { var techniqueParameter = techniqueParameters[techniqueParameterId]; - var techniqueParameterValue = techniqueParameter.value; - if (defined(techniqueParameterValue) && !Array.isArray(techniqueParameterValue)) { - techniqueParameter.value = [techniqueParameterValue]; - } var techniqueParameterSemantic = techniqueParameter.semantic; if (defined(techniqueParameterSemantic)) { if (techniqueParameterSemantic === 'TEXCOORD') { @@ -248,29 +316,132 @@ function glTF_1_0_to_glTF_1_1(gltf) { } } } - // accessor.min and accessor.max must be defined - var accessors = gltf.accessors; - var bufferViews = gltf.bufferViews; +} + +function makeTechniqueValuesArrays(gltf) { + var techniques = gltf.techniques; + for (var techniqueId in techniques) { + if (techniques.hasOwnProperty(techniqueId)) { + var technique = techniques[techniqueId]; + var techniqueParameters = technique.parameters; + for (var techniqueParameterId in techniqueParameters) { + if (techniqueParameters.hasOwnProperty(techniqueParameterId)) { + var techniqueParameter = techniqueParameters[techniqueParameterId]; + var techniqueParameterValue = techniqueParameter.value; + if (defined(techniqueParameterValue) && !Array.isArray(techniqueParameterValue)) { + techniqueParameter.value = [techniqueParameterValue]; + } + } + } + } + } +} + +function removeScissorFromTechniques(gltf) { + var techniques = gltf.techniques; + for (var techniqueId in techniques) { + if (techniques.hasOwnProperty(techniqueId)) { + var technique = techniques[techniqueId]; + delete technique.states.functions.scissor; + var techniqueStates = technique.states; + if (defined(techniqueStates)) { + var enableStates = techniqueStates.enable; + if (defined(enableStates)) { + var scissorIndex = enableStates.indexOf(WebGLConstants.SCISSOR_TEST); + if (scissorIndex >= 0) { + enableStates.splice(scissorIndex, 1); + } + } + } + } + } +} + +function clampTechniqueFunctionStates(gltf) { + var i; + var techniques = gltf.techniques; + for (var techniqueId in techniques) { + if (techniques.hasOwnProperty(techniqueId)) { + var technique = techniques[techniqueId]; + var techniqueStates = technique.states; + if (defined(techniqueStates)) { + var functions = techniqueStates.functions; + if (defined(functions)) { + var blendColor = functions.blendColor; + if (defined(blendColor)) { + for (i = 0; i < 4; i++) { + blendColor[i] = CesiumMath.clamp(blendColor[i], 0.0, 1.0); + } + } + var depthRange = functions.depthRange; + if (defined(depthRange)) { + depthRange[1] = CesiumMath.clamp(depthRange[1], 0.0, 1.0); + depthRange[0] = CesiumMath.clamp(depthRange[0], 0.0, depthRange[1]); + } + } + } + } + } +} + +function clampCameraParameters(gltf) { + var cameras = gltf.cameras; + for (var cameraId in cameras) { + if (cameras.hasOwnProperty(cameraId)) { + var camera = cameras[cameraId]; + var perspective = camera.perspective; + if (defined(perspective)) { + var aspectRatio = perspective.aspectRatio; + if (defined(aspectRatio) && aspectRatio === 0.0) { + delete perspective.aspectRatio; + } + var yfov = perspective.yfov; + if (defined(yfov) && yfov === 0.0) { + perspective.yfov = 1.0; + } + } + } + } +} + +function requireByteLength(gltf) { var buffers = gltf.buffers; + for (var bufferId in buffers) { + if (buffers.hasOwnProperty(bufferId)) { + var buffer = buffers[bufferId]; + if (!defined(buffer.byteLength)) { + buffer.byteLength = buffer.extras._pipeline.source.length; + } + } + } + var bufferViews = gltf.bufferViews; + for (var bufferViewId in bufferViews) { + if (bufferViews.hasOwnProperty(bufferViewId)) { + var bufferView = bufferViews[bufferViewId]; + if (!defined(bufferView.byteLength)) { + var bufferViewBufferId = bufferView.buffer; + var bufferViewBuffer = buffers[bufferViewBufferId]; + bufferView.byteLength = bufferViewBuffer.byteLength; + } + } + } +} + +function requireAccessorMinMax(gltf) { + var accessors = gltf.accessors; for (var accessorId in accessors) { if (accessors.hasOwnProperty(accessorId)) { var accessor = accessors[accessorId]; if (!defined(accessor.min) || !defined(accessor.max)) { - var bufferViewId = accessor.bufferView; - var bufferView = bufferViews[bufferViewId]; - var bufferId = bufferView.buffer; - var buffer = buffers[bufferId]; - if (!defined(buffer.extras) || !defined(buffer.extras._pipeline) || !defined(buffer.extras._pipeline.source)) { - // glTF uris need to be loaded into extras for findAccessorMinMax - loadGltfUris(gltf); - } var minMax = findAccessorMinMax(gltf, accessor); accessor.min = minMax.min; accessor.max = minMax.max; } } } - // skeleton hierarchy must be separate from the node hierarchy (a node with jointName cannot contain camera, skeletons, skins, or meshes) +} + +function separateSkeletonHierarchy(gltf) { var nodes = gltf.nodes; var node; var nodeId; @@ -284,7 +455,7 @@ function glTF_1_0_to_glTF_1_1(gltf) { var children = node.children; if (defined(children)) { var childrenLength = children.length; - for (i = 0; i < childrenLength; i++) { + for (var i = 0; i < childrenLength; i++) { var childNodeId = children[i]; parentNodes[childNodeId] = nodeId; } @@ -353,3 +524,41 @@ function glTF_1_0_to_glTF_1_1(gltf) { } } +function glTF10to11(gltf) { + if (!defined(gltf.asset)) { + gltf.asset = {}; + } + var asset = gltf.asset; + asset.version = '1.1'; + // glTF uris need to be loaded if they haven't been + loadGltfUris(gltf); + // profile.version does not include revision number ("1.0.3" -> "1.0") + stripWebGLRevisionNumber(gltf); + // move known extensions from extensionsUsed to extensionsRequired + requireKnownExtensions(gltf); + // if any index accessors have UNSIGNED_INT componentType, add the WebGL extension OES_element_index_uint + addGlExtensionsUsed(gltf); + // animation.samplers now refers directly to accessors and animation.parameters should be removed + removeAnimationSamplersIndirection(gltf); + // bufferView.byteLength and buffer.byteLength are required + requireByteLength(gltf); + // accessor.min and accessor.max must be defined + requireAccessorMinMax(gltf); + // buffer.type is unnecessary and should be removed + removeBufferType(gltf); + // material.values should be arrays + makeMaterialValuesArray(gltf); + // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#) + requireAttributeSetIndex(gltf); + // technique.parameters.value should be arrays + makeTechniqueValuesArrays(gltf); + // remove scissor from techniques + removeScissorFromTechniques(gltf); + // clamp technique function states to min/max + clampTechniqueFunctionStates(gltf); + // clamp camera parameters + clampCameraParameters(gltf); + // skeleton hierarchy must be separate from the node hierarchy (a node with jointName cannot contain camera, skeletons, skins, or meshes) + separateSkeletonHierarchy(gltf); +} + From 318d2b861b47e8121dd8dbfe2e2b4ab64dacb37d Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Wed, 14 Dec 2016 15:54:29 -0500 Subject: [PATCH 03/47] Cleaned up a few failing tests --- lib/loadGltfUris.js | 7 ++++--- lib/updateVersion.js | 18 +++++++++--------- specs/lib/updateVersionSpec.js | 9 +++++---- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/loadGltfUris.js b/lib/loadGltfUris.js index f20ea606..34aeec3f 100644 --- a/lib/loadGltfUris.js +++ b/lib/loadGltfUris.js @@ -19,14 +19,11 @@ module.exports = loadGltfUris; /** * Load uris in the glTF into buffers. * The buffer data is placed into extras._pipeline.source for the corresponding object. - * glTF must be initialized for the pipeline. * * @param {Object} gltf A javascript object containing a glTF asset. * @param {Object} [options] Options for loading uris. * @param {String} [options.basePath] The path to look in when loading external files. * @returns {Promise} A promise that resolves to the glTF asset when all uris are loaded. - * - * @see addPipelineExtras */ function loadGltfUris(gltf, options) { options = defaultValue(options, {}); @@ -38,6 +35,10 @@ function loadGltfUris(gltf, options) { ]; return Promise.all(loadURIs) .then(function() { + gltf.extras = defaultValue(gltf.extras, {}); + gltf.extras._pipeline = defaultValue(gltf.extras._pipeline, { + deleteExtras: true + }); gltf.extras._pipeline.jimpScratch = new Jimp(1, 1); return gltf; }); diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 1acb13d1..9e9034b9 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -7,7 +7,6 @@ var loadGltfUris = require('./loadGltfUris'); var Cartesian3 = Cesium.Cartesian3; var CesiumMath = Cesium.CesiumMath; -var DeveloperError = Cesium.DeveloperError; var Quaternion = Cesium.Quaternion; var WebGLConstants = Cesium.WebGLConstants; var defaultValue = Cesium.defaultValue; @@ -34,19 +33,17 @@ function updateVersion(gltf, options) { options = defaultValue(options, {}); var targetVersion = options.targetVersion; var version = gltf.version; - if (defined(gltf.asset)) { - version = defaultValue(version, gltf.asset.version); - } - if (!defined(version)) { - version = '1.0'; - } + gltf.asset = defaultValue(gltf.asset, { + version: '1.0' + }); + version = defaultValue(version, gltf.asset.version); var updateFunction = updateFunctions[version]; while (defined(updateFunction)) { - updateFunction(gltf); version = gltf.asset.version; if (version === targetVersion) { break; } + updateFunction(gltf); updateFunction = updateFunctions[version]; } return gltf; @@ -342,9 +339,12 @@ function removeScissorFromTechniques(gltf) { for (var techniqueId in techniques) { if (techniques.hasOwnProperty(techniqueId)) { var technique = techniques[techniqueId]; - delete technique.states.functions.scissor; var techniqueStates = technique.states; if (defined(techniqueStates)) { + var techniqueFunctions = techniqueStates.functions; + if (defined(techniqueFunctions)) { + delete techniqueFunctions.scissor; + } var enableStates = techniqueStates.enable; if (defined(enableStates)) { var scissorIndex = enableStates.indexOf(WebGLConstants.SCISSOR_TEST); diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index 800ebbed..83ed01b9 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -6,11 +6,12 @@ var updateVersion = require('../../lib/updateVersion'); var WebGLConstants = Cesium.WebGLConstants; describe('updateVersion', function() { - it('throws an error if gltf has no version', function() { + it('defaults to 1.0 if gltf has no version', function() { var gltf = {}; - expect(function() { - updateVersion(gltf); - }).toThrowDeveloperError(); + updateVersion(gltf, { + targetVersion: '1.0' + }); + expect(gltf.asset.version).toEqual('1.0'); }); it('updates empty glTF with version from 0.8 to 1.1', function() { From 77cd99517670ee5d8c692efcb743c4d029deb9d9 Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Wed, 14 Dec 2016 17:09:55 -0500 Subject: [PATCH 04/47] Added new upgrades to specs --- lib/updateVersion.js | 26 ++++---- specs/lib/updateVersionSpec.js | 107 +++++++++++++++++++++++++++------ 2 files changed, 103 insertions(+), 30 deletions(-) diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 9e9034b9..f63dbe1c 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -6,7 +6,7 @@ var findAccessorMinMax = require('./findAccessorMinMax'); var loadGltfUris = require('./loadGltfUris'); var Cartesian3 = Cesium.Cartesian3; -var CesiumMath = Cesium.CesiumMath; +var CesiumMath = Cesium.Math; var Quaternion = Cesium.Quaternion; var WebGLConstants = Cesium.WebGLConstants; var defaultValue = Cesium.defaultValue; @@ -276,17 +276,19 @@ function requireAttributeSetIndex(gltf) { for (var i = 0; i < primitivesLength; i++) { var primitive = primitives[i]; var attributes = primitive.attributes; - var semantics = Object.keys(attributes); - var semanticsLength = semantics.length; - for (var j = 0; j < semanticsLength; j++) { - var semantic = semantics[j]; - if (semantic === 'TEXCOORD') { - attributes.TEXCOORD_0 = attributes[semantic]; - delete attributes[semantic]; - } - if (semantic === 'COLOR') { - attributes.COLOR_0 = attributes[semantic]; - delete attributes[semantic]; + if (defined(attributes)) { + var semantics = Object.keys(attributes); + var semanticsLength = semantics.length; + for (var j = 0; j < semanticsLength; j++) { + var semantic = semantics[j]; + if (semantic === 'TEXCOORD') { + attributes.TEXCOORD_0 = attributes[semantic]; + delete attributes[semantic]; + } + if (semantic === 'COLOR') { + attributes.COLOR_0 = attributes[semantic]; + delete attributes[semantic]; + } } } } diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index 83ed01b9..7748aba6 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -20,7 +20,7 @@ describe('updateVersion', function() { }; updateVersion(gltf); expect(gltf.version).not.toBeDefined(); - expect(gltf.asset.version).toBe('1.1'); + expect(gltf.asset.version).toEqual('1.1'); }); it('updates empty glTF with version 1.0 to 1.1', function() { @@ -30,7 +30,7 @@ describe('updateVersion', function() { } }; updateVersion(gltf); - expect(gltf.asset.version).toBe('1.1'); + expect(gltf.asset.version).toEqual('1.1'); }); it('updates glTF from 0.8 to 1.0', function() { @@ -94,22 +94,22 @@ describe('updateVersion', function() { updateVersion(gltf, { targetVersion: '1.0' }); - expect(gltf.asset.version).toBe('1.0'); + expect(gltf.asset.version).toEqual('1.0'); expect(gltf.asset.profile).toEqual({}); expect(gltf.version).not.toBeDefined(); expect(gltf.extensionsUsed).toEqual(['extension']); var material = gltf.materials.material; - expect(material.technique).toBe('technique'); + expect(material.technique).toEqual('technique'); expect(material.values).toEqual({ 'ambient': [0.0, 0.0, 0.0, 1.0] }); var primitive = gltf.meshes.mesh.primitives[0]; expect(primitive.primitive).not.toBeDefined(); - expect(primitive.mode).toBe(WebGLConstants.TRIANGLES); + expect(primitive.mode).toEqual(WebGLConstants.TRIANGLES); var node = gltf.nodes.node; expect(node.rotation).toEqual([0.0, 0.0, 0.0, 1.0]); expect(node.skeletons).toEqual(['skeleton']); - expect(node.skin).toBe('skin'); + expect(node.skin).toEqual('skin'); expect(node.meshes).toEqual(['mesh']); var technique = gltf.techniques.technique; expect(technique.pass).not.toBeDefined(); @@ -117,7 +117,7 @@ describe('updateVersion', function() { expect(technique.attributes).toEqual({ attribute: 'TEST_ATTRIBUTE' }); - expect(technique.program).toBe('program'); + expect(technique.program).toEqual('program'); expect(technique.uniforms).toEqual({ uniform: 'TEST_UNIFORM' }); @@ -125,7 +125,7 @@ describe('updateVersion', function() { }); it('updates glTF from 1.0 to 1.1', function() { - var buffer = new Buffer(new Int16Array([-2.0, 1.0, 0.0, 1.0, 2.0, 3.0]).buffer); + var arrayBuffer = new Buffer(new Int16Array([-2.0, 1.0, 0.0, 1.0, 2.0, 3.0]).buffer); var gltf = { asset: { profile: { @@ -147,6 +147,11 @@ describe('updateVersion', function() { } } }, + extensionsUsed: [ + 'KHR_materials_common', + 'WEB3D_quantized_attributes', + 'UNKOWN_EXTENSION' + ], meshes: { mesh: { primitives: [ @@ -154,7 +159,8 @@ describe('updateVersion', function() { attributes: { TEXCOORD: 'accessor_texcoord', COLOR: 'accessor_color' - } + }, + indices: 'accessor_indices' } ] } @@ -168,6 +174,14 @@ describe('updateVersion', function() { }, techniques: { technique: { + states: { + enable: [ WebGLConstants.SCISSOR_TEST ], + functions: { + blendColor: [-1.0, 0.0, 0.0, 2.0], + depthRange: [1.0, -1.0], + scissor: [0.0, 0.0, 0.0, 0.0] + } + }, parameters: { lightAttenuation: { value: 1.0 @@ -189,25 +203,35 @@ describe('updateVersion', function() { componentType: WebGLConstants.SHORT, count: 6, type: 'SCALAR' + }, + accessor_indices: { + componentType: WebGLConstants.UNSIGNED_INT } }, bufferViews: { bufferView: { buffer: 'buffer', - byteLength: buffer.length, byteOffset: 0 } }, buffers: { buffer: { - byteLength: buffer.length, + type: 'arraybuffer', extras: { _pipeline: { - source: buffer + source: arrayBuffer } } } }, + cameras: { + camera: { + perspective: { + aspectRatio : 0.0, + yfov : 0.0 + } + } + }, nodes: { meshNode: { meshes: ['mesh'] @@ -229,25 +253,39 @@ describe('updateVersion', function() { targetVersion: '1.1' }); expect(gltf.asset.profile.version).toEqual('1.0'); + var extensionsUsed = gltf.extensionsUsed; + expect(extensionsUsed).toEqual(['UNKOWN_EXTENSION']); + var extensionsRequired = gltf.extensionsRequired; + expect(extensionsRequired).toEqual([ + 'KHR_materials_common', + 'WEB3D_quantized_attributes' + ]); + var glExtensionsUsed = gltf.glExtensionsUsed; + expect(glExtensionsUsed).toEqual(['OES_element_index_uint']); var animation = gltf.animations.animation; var sampler = animation.samplers.sampler; - expect(sampler.input).toBe('accessor_input'); - expect(sampler.output).toBe('accessor_output'); + expect(sampler.input).toEqual('accessor_input'); + expect(sampler.output).toEqual('accessor_output'); expect(animation.parameters).not.toBeDefined(); var material = gltf.materials.material; expect(material.values.shininess).toEqual([1.0]); var technique = gltf.techniques.technique; expect(technique.parameters.lightAttenuation.value).toEqual([1.0]); - expect(technique.parameters.texcoord.semantic).toBe('TEXCOORD_0'); - expect(technique.parameters.color.semantic).toBe('COLOR_0'); + expect(technique.parameters.texcoord.semantic).toEqual('TEXCOORD_0'); + expect(technique.parameters.color.semantic).toEqual('COLOR_0'); + var states = technique.states; + expect(states.enable).toEqual([]); + expect(states.functions.scissor).not.toBeDefined(); + expect(states.functions.blendColor).toEqual([0.0, 0.0, 0.0, 1.0]); + expect(states.functions.depthRange).toEqual([0.0, 0.0]); var accessor = gltf.accessors.accessor; expect(accessor.min).toEqual([-2.0]); expect(accessor.max).toEqual([3.0]); var primitive = gltf.meshes.mesh.primitives[0]; expect(primitive.attributes.TEXCOORD).not.toBeDefined(); - expect(primitive.attributes.TEXCOORD_0).toBe('accessor_texcoord'); + expect(primitive.attributes.TEXCOORD_0).toEqual('accessor_texcoord'); expect(primitive.attributes.COLOR).not.toBeDefined(); - expect(primitive.attributes.COLOR_0).toBe('accessor_color'); + expect(primitive.attributes.COLOR_0).toEqual('accessor_color'); var nodes = gltf.nodes; var rootNode = nodes.rootNode; expect(rootNode.children).toEqual(['jointNodeOne', 'meshNode']); @@ -262,5 +300,38 @@ describe('updateVersion', function() { var jointNodeTwoSkeleton = nodes['jointNodeTwo-skeleton']; expect(jointNodeTwoSkeleton.translation).toEqual([1.0, 0.0, 0.0]); expect(nodes.jointNodeTwo).not.toBeDefined(); + var camera = gltf.cameras.camera; + expect(camera.perspective.aspectRatio).not.toBeDefined(); + expect(camera.perspective.yfov).toEqual(1.0); + var buffer = gltf.buffers.buffer; + expect(buffer.type).not.toBeDefined(); + expect(buffer.byteLength).toEqual(arrayBuffer.length); + var bufferView = gltf.bufferViews.bufferView; + expect(bufferView.byteLength).toEqual(arrayBuffer.length); + }); + + it('does not add glExtensionsUsed if primitive indices are not UNSIGNED_INT', function() { + var gltf = { + asset: { + version: '1.0' + }, + accessors: { + indices_accessor: { + componentType: WebGLConstants.UNSIGNED_SHORT + } + }, + meshes : { + mesh : { + primitives : [ + { + indices: 'indices_accessor' + } + ] + } + } + }; + updateVersion(gltf); + expect(gltf.asset.version).toEqual('1.1'); + expect(gltf.glExtensionsUsed).not.toBeDefined(); }); }); \ No newline at end of file From 6478c988f4c2739c0c6e680407c6c7352c038617 Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Wed, 14 Dec 2016 17:52:53 -0500 Subject: [PATCH 05/47] Application specific parameters are prefixed with underscores --- lib/updateVersion.js | 66 ++++++++++++++++++++++++++++++++++ specs/lib/updateVersionSpec.js | 11 +++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/lib/updateVersion.js b/lib/updateVersion.js index f63dbe1c..faac94c1 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -317,6 +317,70 @@ function requireAttributeSetIndex(gltf) { } } +var knownSemantics = { + POSITION: true, + NORMAL: true, + TEXCOORD: true, + COLOR: true, + JOINT: true, + WEIGHT: true, + BATCHID: true +}; +function underscoreApplicationSpecificSemantics(gltf) { + var mappedSemantics = {}; + var meshes = gltf.meshes; + var techniques = gltf.techniques; + for (var meshId in meshes) { + if (meshes.hasOwnProperty(meshId)) { + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + if (defined(primitives)) { + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + var primitive = primitives[i]; + var attributes = primitive.attributes; + if (defined(attributes)) { + var semantics = Object.keys(attributes); + var semanticsLength = semantics.length; + for (var j = 0; j < semanticsLength; j++) { + var semantic = semantics[j]; + if (semantic.charAt(0) !== '_') { + var setIndex = semantic.search(/_[0-9]+/g); + var strippedSemantic = semantic; + if (setIndex >= 0) { + strippedSemantic = semantic.substring(0, setIndex); + } + if (!defined(knownSemantics[strippedSemantic])) { + var attributeValue = attributes[semantic]; + delete attributes[semantic]; + var newSemantic = '_' + semantic; + attributes[newSemantic] = attributeValue; + mappedSemantics[semantic] = newSemantic; + } + } + } + } + } + } + } + } + for (var techniqueId in techniques) { + if (techniques.hasOwnProperty(techniqueId)) { + var technique = techniques[techniqueId]; + var techniqueParameters = technique.parameters; + for (var techniqueParameterId in techniqueParameters) { + if (techniqueParameters.hasOwnProperty(techniqueParameterId)) { + var techniqueParameter = techniqueParameters[techniqueParameterId]; + var mappedSemantic = mappedSemantics[techniqueParameter.semantic]; + if (defined(mappedSemantic)) { + techniqueParameter.semantic = mappedSemantic; + } + } + } + } + } +} + function makeTechniqueValuesArrays(gltf) { var techniques = gltf.techniques; for (var techniqueId in techniques) { @@ -552,6 +616,8 @@ function glTF10to11(gltf) { makeMaterialValuesArray(gltf); // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#) requireAttributeSetIndex(gltf); + // Add underscores to application-specific parameters + underscoreApplicationSpecificSemantics(gltf); // technique.parameters.value should be arrays makeTechniqueValuesArrays(gltf); // remove scissor from techniques diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index 7748aba6..8afddadb 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -158,7 +158,9 @@ describe('updateVersion', function() { { attributes: { TEXCOORD: 'accessor_texcoord', - COLOR: 'accessor_color' + COLOR: 'accessor_color', + APPLICATIONSPECIFIC: 'accessor', + _TEMPERATURE: 'accessor_temperature' }, indices: 'accessor_indices' } @@ -191,6 +193,9 @@ describe('updateVersion', function() { }, color: { semantic: 'COLOR' + }, + application: { + semantic: 'APPLICATIONSPECIFIC' } } } @@ -273,6 +278,7 @@ describe('updateVersion', function() { expect(technique.parameters.lightAttenuation.value).toEqual([1.0]); expect(technique.parameters.texcoord.semantic).toEqual('TEXCOORD_0'); expect(technique.parameters.color.semantic).toEqual('COLOR_0'); + expect(technique.parameters.application.semantic).toEqual('_APPLICATIONSPECIFIC'); var states = technique.states; expect(states.enable).toEqual([]); expect(states.functions.scissor).not.toBeDefined(); @@ -286,6 +292,9 @@ describe('updateVersion', function() { expect(primitive.attributes.TEXCOORD_0).toEqual('accessor_texcoord'); expect(primitive.attributes.COLOR).not.toBeDefined(); expect(primitive.attributes.COLOR_0).toEqual('accessor_color'); + expect(primitive.attributes.APPLICATIONSPECIFIC).not.toBeDefined(); + expect(primitive.attributes._APPLICATIONSPECIFIC).toEqual('accessor'); + expect(primitive.attributes._TEMPERATURE).toEqual('accessor_temperature'); var nodes = gltf.nodes; var rootNode = nodes.rootNode; expect(rootNode.children).toEqual(['jointNodeOne', 'meshNode']); From a6db84299ff0514f4605eee0595fdb2dfad9cbea Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 17 Jan 2017 12:00:19 -0500 Subject: [PATCH 06/47] Migrated changes back from cesium --- lib/updateVersion.js | 171 +++++++++++++++++++-------------- specs/lib/updateVersionSpec.js | 61 ++++++------ 2 files changed, 130 insertions(+), 102 deletions(-) diff --git a/lib/updateVersion.js b/lib/updateVersion.js index faac94c1..8a409c23 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -7,6 +7,7 @@ var loadGltfUris = require('./loadGltfUris'); var Cartesian3 = Cesium.Cartesian3; var CesiumMath = Cesium.Math; +var Matrix4 = Cesium.Matrix4; var Quaternion = Cesium.Quaternion; var WebGLConstants = Cesium.WebGLConstants; var defaultValue = Cesium.defaultValue; @@ -32,19 +33,21 @@ var updateFunctions = { function updateVersion(gltf, options) { options = defaultValue(options, {}); var targetVersion = options.targetVersion; - var version = gltf.version; - gltf.asset = defaultValue(gltf.asset, { - version: '1.0' - }); - version = defaultValue(version, gltf.asset.version); - var updateFunction = updateFunctions[version]; - while (defined(updateFunction)) { - version = gltf.asset.version; - if (version === targetVersion) { - break; + if (defined(gltf)) { + var version = gltf.version; + gltf.asset = defaultValue(gltf.asset, { + version : '1.0' + }); + version = defaultValue(version, gltf.asset.version); + var updateFunction = updateFunctions[version]; + while (defined(updateFunction)) { + if (version === targetVersion) { + break; + } + updateFunction(gltf); + version = gltf.asset.version; + updateFunction = updateFunctions[version]; } - updateFunction(gltf); - updateFunction = updateFunctions[version]; } return gltf; } @@ -507,84 +510,104 @@ function requireAccessorMinMax(gltf) { } } +var scratchTranslation = new Cartesian3(); +var scratchRotation = new Quaternion(); +var scratchScale = new Cartesian3(); +var defaultScale = new Cartesian3(1.0, 1.0, 1.0); +var scratchMatrix4 = new Matrix4(); +var scratchPreApplyTransform = new Matrix4(); +function getNodeTransform(node) { + if (defined(node.matrix)) { + return Matrix4.fromArray(node.matrix); + } else if (defined(node.translation) || defined(node.rotation) || defined(node.scale)) { + Cartesian3.ZERO.clone(scratchTranslation); + if (defined(node.translation)) { + Cartesian3.unpack(node.translation, scratchTranslation); + } + Quaternion.IDENTITY.clone(scratchRotation); + if (defined(node.rotation)) { + Quaternion.unpack(node.rotation, scratchRotation); + } + defaultScale.clone(scratchScale); + if (defined(node.scale)) { + Cartesian3.unpack(node.scale, scratchScale); + } + Matrix4.fromTranslationQuaternionRotationScale(scratchTranslation, scratchRotation, scratchScale, scratchMatrix4); + return scratchMatrix4; + } else { + return Matrix4.IDENTITY; + } +} + + function separateSkeletonHierarchy(gltf) { var nodes = gltf.nodes; - var node; - var nodeId; - var nodeStack = []; - var mappedSkeletonNodes = {}; + var scenes = gltf.scenes; + + var skinnedNodes = []; var parentNodes = {}; - for (nodeId in nodes) { + + var i; + var skeletonIds; + + for (var nodeId in nodes) { if (nodes.hasOwnProperty(nodeId)) { - nodeStack.push(nodeId); - node = nodes[nodeId]; + var node = nodes[nodeId]; var children = node.children; if (defined(children)) { var childrenLength = children.length; - for (var i = 0; i < childrenLength; i++) { + for (i = 0; i < childrenLength; i++) { var childNodeId = children[i]; parentNodes[childNodeId] = nodeId; } } + var skinId = node.skin; + skeletonIds = node.skeletons; + if (defined(skinId) && defined(skeletonIds)) { + skinnedNodes.push(nodeId); + } } } - while (nodeStack.length > 0) { - nodeId = nodeStack.pop(); - node = nodes[nodeId]; - var jointName = node.jointName; - if (defined(jointName)) { - // this node is a joint; clone the hierarchy - if (!defined(node.camera) && !defined(node.skeletons) && !defined(node.skins) && !defined(node.meshes) && !defined(node.children)) { - // the original node can be removed since it is only a skeleton node - var parentId = parentNodes[nodeId]; - if (defined(parentId)) { - var parentChildren = nodes[parentId].children; - parentChildren.splice(parentChildren.indexOf(nodeId), 1); - } - delete nodes[nodeId]; - } - var lastNodeId; - var skeletonNode; - var end = false; - while (defined(nodeId)) { - var skeletonNodeId = mappedSkeletonNodes[nodeId]; - if (!defined(skeletonNodeId)) { - skeletonNodeId = getUniqueId(gltf, nodeId + '-skeleton'); - skeletonNode = { - jointName: jointName - }; - if (defined(node.translation) || defined(node.rotation) || defined(node.scale)) { - skeletonNode.translation = defaultValue(node.translation, [0.0, 0.0, 0.0]); - skeletonNode.rotation = defaultValue(node.rotation, [0.0, 0.0, 0.0, 1.0]); - skeletonNode.scale = defaultValue(node.scale, [1.0, 1.0, 1.0]); - } else { - skeletonNode.matrix = defaultValue(node.matrix, [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0]); + + var sceneId = gltf.scene; + if (defined(sceneId)) { + var scene = scenes[sceneId]; + + var skinnedNodesLength = skinnedNodes.length; + for (i = 0; i < skinnedNodesLength; i++) { + var skinnedNodeId = skinnedNodes[i]; + var skinnedNode = nodes[skinnedNodeId]; + skeletonIds = skinnedNode.skeletons; + var skeletonIdsLength = skeletonIds.length; + for (var j = 0; j < skeletonIdsLength; j++) { + var skeletonId = skeletonIds[j]; + var parentNodeId = parentNodes[skeletonId]; + if (defined(parentNodeId)) { + var parentNode = nodes[parentNodeId]; + var parentChildren = parentNode.children; + var index = parentChildren.indexOf(skeletonId); + parentChildren.splice(index, 1); + parentNode.children = parentChildren; + Matrix4.IDENTITY.clone(scratchPreApplyTransform); + while (defined(parentNode)) { + var parentTransform = getNodeTransform(parentNode); + Matrix4.multiply(parentTransform, scratchPreApplyTransform, scratchPreApplyTransform); + parentNodeId = parentNodes[parentNodeId]; + parentNode = nodes[parentNodeId]; } - delete node.jointName; - nodes[skeletonNodeId] = skeletonNode; - mappedSkeletonNodes[nodeId] = skeletonNodeId; - } else { - end = true; - } - if (defined(lastNodeId)) { - skeletonNode = nodes[skeletonNodeId]; - var skeletonChildren = skeletonNode.children; - if (!defined(skeletonChildren)) { - skeletonNode.children = [lastNodeId]; - } else { - skeletonChildren.push(lastNodeId); + if (!Matrix4.equals(scratchPreApplyTransform, Matrix4.IDENTITY)) { + var newRootNodeId = getUniqueId(gltf, 'root-' + skeletonId); + var newRootNode = { + children: [], + matrix: Matrix4.pack(scratchPreApplyTransform, [], 0) + }; + newRootNode.children.push(skeletonId); + nodes[newRootNodeId] = newRootNode; + skeletonId = newRootNodeId; + skeletonIds[j] = newRootNodeId; } + scene.nodes.push(skeletonId); } - if (end) { - break; - } - lastNodeId = skeletonNodeId; - nodeId = parentNodes[nodeId]; - node = nodes[nodeId]; } } } diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index 8afddadb..b9b7d9ec 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -232,25 +232,38 @@ describe('updateVersion', function() { cameras: { camera: { perspective: { - aspectRatio : 0.0, - yfov : 0.0 + aspectRatio: 0.0, + yfov: 0.0 } } }, nodes: { - meshNode: { - meshes: ['mesh'] - }, - rootNode: { - children: ['jointNodeOne', 'jointNodeTwo', 'meshNode'] - }, - jointNodeOne: { - jointName: 'jointOne', - meshes: ['mesh'] + rootTransform: { + children: [ + 'skeletonNode', + 'meshNode' + ], + matrix: [ + 1, 0, 0, 0, + 0, 0, -1, 0, + 0, 1, 0, 0, + 0, 0, 0, 1 + ] }, - jointNodeTwo: { - jointName: 'jointTwo', - translation: [1.0, 0.0, 0.0] + skeletonNode: {}, + meshNode: { + skin: 'someSkin', + skeletons: [ + 'skeletonNode' + ] + } + }, + scene: 'defaultScene', + scenes: { + defaultScene: { + nodes: [ + 'rootTransform' + ] } } }; @@ -295,20 +308,12 @@ describe('updateVersion', function() { expect(primitive.attributes.APPLICATIONSPECIFIC).not.toBeDefined(); expect(primitive.attributes._APPLICATIONSPECIFIC).toEqual('accessor'); expect(primitive.attributes._TEMPERATURE).toEqual('accessor_temperature'); - var nodes = gltf.nodes; - var rootNode = nodes.rootNode; - expect(rootNode.children).toEqual(['jointNodeOne', 'meshNode']); - var rootNodeSkeleton = nodes['rootNode-skeleton']; - expect(rootNodeSkeleton.matrix).toBeDefined(); - expect(rootNodeSkeleton.children).toEqual(['jointNodeTwo-skeleton', 'jointNodeOne-skeleton']); - var jointNodeOneSkeleton = nodes['jointNodeOne-skeleton']; - expect(jointNodeOneSkeleton.meshes).not.toBeDefined(); - var jointNodeOne = nodes.jointNodeOne; - expect(jointNodeOne.meshes).toEqual(['mesh']); - expect(jointNodeOne.jointName).not.toBeDefined(); - var jointNodeTwoSkeleton = nodes['jointNodeTwo-skeleton']; - expect(jointNodeTwoSkeleton.translation).toEqual([1.0, 0.0, 0.0]); - expect(nodes.jointNodeTwo).not.toBeDefined(); + var rootTransform = gltf.nodes.rootTransform; + var rootSkeletonNode = gltf.nodes['root-skeletonNode']; + var scene = gltf.scenes.defaultScene; + expect(scene.nodes).toEqual(['rootTransform', 'root-skeletonNode']); + expect(rootTransform.children).toEqual(['meshNode']); + expect(rootSkeletonNode.matrix).toEqual(rootTransform.matrix); var camera = gltf.cameras.camera; expect(camera.perspective.aspectRatio).not.toBeDefined(); expect(camera.perspective.yfov).toEqual(1.0); From e882790e471d75c2d5bf72769c68e9ddf629497f Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 25 Jan 2017 13:43:10 -0500 Subject: [PATCH 07/47] Changed 1.1 to 2.0 --- lib/updateVersion.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/updateVersion.js b/lib/updateVersion.js index f37ce6a3..6692b775 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -17,18 +17,11 @@ module.exports = updateVersion; var updateFunctions = { '0.8' : glTF08to10, - '1.0' : glTF10to11 + '2.0' : glTF10to20 }; /** - * Update the glTF version to the latest (1.1), or targetVersion if specified. -======= - '0.8': glTF08to10 -}; - -/** - * Update the glTF version to the latest version (1.0), or targetVersion if specified. ->>>>>>> 232ca482dffd68340c8b06a537cfbd471a277ca4 + * Update the glTF version to the latest version (2.0), or targetVersion if specified. * Applies changes made to the glTF spec between revisions so that the core library * only has to handle the latest version. * @@ -628,12 +621,12 @@ function separateSkeletonHierarchy(gltf) { } } -function glTF10to11(gltf) { +function glTF10to20(gltf) { if (!defined(gltf.asset)) { gltf.asset = {}; } var asset = gltf.asset; - asset.version = '1.1'; + asset.version = '2.0'; // glTF uris need to be loaded if they haven't been loadGltfUris(gltf); // profile.version does not include revision number ("1.0.3" -> "1.0") From e88fd50ca87f25c977594c1bceace6d61d7c21ae Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 25 Jan 2017 15:28:02 -0500 Subject: [PATCH 08/47] Lots of 1.0->2.0 changes in pipeline stages --- lib/RemoveUnusedProperties.js | 41 +++++++++++-------- lib/addDefaults.js | 1 - lib/addExtensionsRequired.js | 26 ++++++++++++ lib/addPipelineExtras.js | 4 +- lib/generateModelMaterialsCommon.js | 4 +- lib/getBinaryGltf.js | 4 +- lib/updateVersion.js | 19 +++++---- .../CesiumTexturedBoxTestUnusedTree.gltf | 2 +- .../CesiumTexturedBoxTest_BinaryCheck.gltf | 1 + specs/lib/RemoveUnusedPropertiesSpec.js | 28 ++++++++----- specs/lib/addDefaultsSpec.js | 1 - specs/lib/getBinaryGltfSpec.js | 8 ++-- specs/lib/updateVersionSpec.js | 16 +++++++- 13 files changed, 107 insertions(+), 48 deletions(-) create mode 100644 lib/addExtensionsRequired.js diff --git a/lib/RemoveUnusedProperties.js b/lib/RemoveUnusedProperties.js index 8748a7e6..82793b1c 100644 --- a/lib/RemoveUnusedProperties.js +++ b/lib/RemoveUnusedProperties.js @@ -191,13 +191,13 @@ RemoveUnusedProperties.removeAccessors = function(gltf) { if (defined(animations)) { for (var animationId in animations) { if (animations.hasOwnProperty(animationId)) { - var parameters = animations[animationId].parameters; - if (defined(parameters)) { - for (var parameterId in parameters) { - if (parameters.hasOwnProperty(parameterId)) { - var animationAccessorId = parameters[parameterId]; - usedAccessorIds[animationAccessorId] = true; - } + var animation = animations[animationId]; + var samplers = animation.samplers; + for (var samplerId in samplers) { + if (samplers.hasOwnProperty(samplerId)) { + var sampler = samplers[samplerId]; + usedAccessorIds[sampler.input] = true; + usedAccessorIds[sampler.output] = true; } } } @@ -268,16 +268,23 @@ RemoveUnusedProperties.removeTextures = function(gltf) { var techniques = gltf.techniques; // Build hash of used textures by iterating through materials and techniques + var i; + var values; + var valueLength; + var value; if (defined(materials)) { for (var materialId in materials) { if (materials.hasOwnProperty(materialId)) { if (defined(materials[materialId].values)) { - var values = materials[materialId].values; + values = materials[materialId].values; for (var valueId in values) { if (values.hasOwnProperty(valueId)) { - if (typeof values[valueId] === 'string') { - var materialTextureId = values[valueId]; - usedTextureIds[materialTextureId] = true; + value = values[valueId]; + valueLength = value.length; + for (i = 0; i < valueLength; i++) { + if (typeof value[i] === 'string') { + usedTextureIds[value[i]] = true; + } } } } @@ -292,11 +299,13 @@ RemoveUnusedProperties.removeTextures = function(gltf) { var parameters = techniques[techniqueId].parameters; for (var parameterId in parameters) { if (parameters.hasOwnProperty(parameterId)) { - if (defined(parameters[parameterId].value)) { - var value = parameters[parameterId].value; - if (typeof value === 'string') { - var techniqueTextureId = value; - usedTextureIds[techniqueTextureId] = true; + value = parameters[parameterId].value; + if (defined(value)) { + valueLength = value.length; + for (i = 0; i < valueLength; i++) { + if (typeof value[i] === 'string') { + usedTextureIds[value[i]] = true; + } } } } diff --git a/lib/addDefaults.js b/lib/addDefaults.js index bc246a73..b622c130 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -18,7 +18,6 @@ var gltfTemplate = { animations : { '*' : { channels : [], - parameters : {}, samplers : { '*' : { interpolation : 'LINEAR' diff --git a/lib/addExtensionsRequired.js b/lib/addExtensionsRequired.js new file mode 100644 index 00000000..5b70c1bb --- /dev/null +++ b/lib/addExtensionsRequired.js @@ -0,0 +1,26 @@ +'use strict'; +var Cesium = require('cesium'); +var addExtensionsUsed = require('./addExtensionsUsed'); + +var defined = Cesium.defined; + +module.exports = addExtensionsRequired; + +/** + * Adds an extension to gltf.extensionsRequired if it does not already exist. + * Initializes extensionsRequired if it is not defined. + * + * @param {Object} gltf A javascript object containing a glTF asset. + * @param {String} extension The extension to add. + */ +function addExtensionsRequired(gltf, extension) { + var extensionsRequired = gltf.extensionsRequired; + if (!defined(extensionsRequired)) { + extensionsRequired = []; + gltf.extensionsRequired = extensionsRequired; + } + if (extensionsRequired.indexOf(extension) < 0) { + extensionsRequired.push(extension); + } + addExtensionsUsed(gltf, extension); +} \ No newline at end of file diff --git a/lib/addPipelineExtras.js b/lib/addPipelineExtras.js index f31d245a..a382a8af 100644 --- a/lib/addPipelineExtras.js +++ b/lib/addPipelineExtras.js @@ -10,8 +10,10 @@ module.exports = addPipelineExtras; var exceptions = { attributes: true, uniforms: true, - extensions: true + extensions: true, + values: true }; + /** * Adds extras._pipeline to each object that can have extras in the glTF asset. * diff --git a/lib/generateModelMaterialsCommon.js b/lib/generateModelMaterialsCommon.js index 1542f67b..a43062d2 100644 --- a/lib/generateModelMaterialsCommon.js +++ b/lib/generateModelMaterialsCommon.js @@ -1,6 +1,6 @@ 'use strict'; var Cesium = require('cesium'); -var addExtensionsUsed = require('./addExtensionsUsed'); +var addExtensionsRequired = require('./addExtensionsUsed'); var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; @@ -24,7 +24,7 @@ function generateModelMaterialsCommon(gltf, kmcOptions) { kmcOptions = defaultValue(kmcOptions, {}); kmcOptions.doubleSided = defaultValue(kmcOptions.doubleSided, false); kmcOptions.technique = defaultValue(kmcOptions.technique, 'PHONG'); - addExtensionsUsed(gltf, 'KHR_materials_common'); + addExtensionsRequired(gltf, 'KHR_materials_common'); var materialsCommon; var materials = gltf.materials; var nodes = gltf.nodes; diff --git a/lib/getBinaryGltf.js b/lib/getBinaryGltf.js index d1bf2461..57720895 100644 --- a/lib/getBinaryGltf.js +++ b/lib/getBinaryGltf.js @@ -6,7 +6,7 @@ var sizeOf = require('image-size'); var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; -var addExtensionsUsed = require('./addExtensionsUsed'); +var addExtensionsRequired = require('./addExtensionsRequired'); var mergeBuffers = require('./mergeBuffers'); var removePipelineExtras = require('./removePipelineExtras'); @@ -75,7 +75,7 @@ function updateBinaryObject(gltf, pipelineExtras, name, state) { * @see loadGltfUris */ function getBinaryGltf(gltf, embed, embedImage) { - addExtensionsUsed(gltf, 'KHR_binary_glTF'); + addExtensionsRequired(gltf, 'KHR_binary_glTF'); // Create the special binary buffer from the existing buffers gltf.bufferViews = defaultValue(gltf.bufferViews, {}); gltf.buffers = defaultValue(gltf.buffers, {}); diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 6692b775..facc6960 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -3,7 +3,6 @@ var Cesium = require('cesium'); var getUniqueId = require('./getUniqueId'); var findAccessorMinMax = require('./findAccessorMinMax'); -var loadGltfUris = require('./loadGltfUris'); var Cartesian3 = Cesium.Cartesian3; var CesiumMath = Cesium.Math; @@ -17,7 +16,8 @@ module.exports = updateVersion; var updateFunctions = { '0.8' : glTF08to10, - '2.0' : glTF10to20 + '1.0' : glTF10to20, + '2.0' : null }; /** @@ -34,10 +34,17 @@ function updateVersion(gltf, options) { options = defaultValue(options, {}); var targetVersion = options.targetVersion; var version = gltf.version; + gltf.asset = defaultValue(gltf.asset, { version: '1.0' }); + version = defaultValue(version, gltf.asset.version); + // invalid version, default to 1.0 + if (!updateFunctions.hasOwnProperty(version)) { + version = '1.0'; + } + var updateFunction = updateFunctions[version]; while (defined(updateFunction)) { version = gltf.asset.version; @@ -197,8 +204,6 @@ function requireKnownExtensions(gltf) { var extension = extensionsUsed[i]; if (defined(knownExtensions[extension])) { gltf.extensionsRequired.push(extension); - extensionsUsed.splice(i, 1); - i--; } } } @@ -295,8 +300,7 @@ function requireAttributeSetIndex(gltf) { if (semantic === 'TEXCOORD') { attributes.TEXCOORD_0 = attributes[semantic]; delete attributes[semantic]; - } - if (semantic === 'COLOR') { + } else if (semantic === 'COLOR') { attributes.COLOR_0 = attributes[semantic]; delete attributes[semantic]; } @@ -335,7 +339,6 @@ var knownSemantics = { COLOR: true, JOINT: true, WEIGHT: true, - BATCHID: true }; function underscoreApplicationSpecificSemantics(gltf) { var mappedSemantics = {}; @@ -627,8 +630,6 @@ function glTF10to20(gltf) { } var asset = gltf.asset; asset.version = '2.0'; - // glTF uris need to be loaded if they haven't been - loadGltfUris(gltf); // profile.version does not include revision number ("1.0.3" -> "1.0") stripWebGLRevisionNumber(gltf); // move known extensions from extensionsUsed to extensionsRequired diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestUnusedTree.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestUnusedTree.gltf index 584ba528..c804476a 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestUnusedTree.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestUnusedTree.gltf @@ -53,7 +53,7 @@ "Effect-Texture": { "technique": "technique0", "values": { - "diffuse": "texture_Image0001" + "diffuse": ["texture_Image0001"] } } }, diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf index cbd70bd7..0522fdca 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf @@ -108,6 +108,7 @@ } }, "extensionsUsed": ["KHR_binary_glTF"], + "extensionsRequired": ["KHR_binary_glTF"], "images": { "Image0001": { "name": "Image0001", diff --git a/specs/lib/RemoveUnusedPropertiesSpec.js b/specs/lib/RemoveUnusedPropertiesSpec.js index 83880975..b993d5dd 100644 --- a/specs/lib/RemoveUnusedPropertiesSpec.js +++ b/specs/lib/RemoveUnusedPropertiesSpec.js @@ -351,8 +351,10 @@ describe('RemoveUnusedProperties', function() { }, "animations": { "animation_0": { - "parameters": { - "TIME": "animAccessor_0" + "samplers": { + "sampler": { + "input": "animAccessor_0" + } } } }, @@ -415,8 +417,10 @@ describe('RemoveUnusedProperties', function() { }, "animations": { "animation_0": { - "parameters": { - "TIME": "animAccessor_0" + "samplers": { + "sampler": { + "input": "animAccessor_0" + } } } }, @@ -704,7 +708,7 @@ describe('RemoveUnusedProperties', function() { "name": "Texture", "technique": "technique0", "values": { - "diffuse": "texture_Image0001", + "diffuse": ["texture_Image0001"], "shininess": 256, "specular": [ 0.2, @@ -742,7 +746,7 @@ describe('RemoveUnusedProperties', function() { "parameters": { "diffuse": { "type": 35678, - "value": "texture_Image0001" + "value": ["texture_Image0001"] } }, "program": "program_0" @@ -775,8 +779,8 @@ describe('RemoveUnusedProperties', function() { "name": "Texture", "technique": "technique0", "values": { - "diffuse": "texture_Image0001", - "shininess": 256, + "diffuse": ["texture_Image0001"], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -809,7 +813,7 @@ describe('RemoveUnusedProperties', function() { "parameters": { "diffuse": { "type": 35678, - "value": "texture_Image0001" + "value": ["texture_Image0001"] } }, "program": "program_0" @@ -1271,7 +1275,11 @@ describe('RemoveUnusedProperties', function() { .then(function (data) { var gltf = JSON.parse(data); gltf.scenes.defaultScene.nodes[0] = 'node_3'; - gltf.animations.animation_0.parameters.TIME = 'animAccessor_0'; + gltf.animations.animation_0.samplers = { + sampler : { + input : 'animAccessor_0' + } + }; removeAll(gltf); expect(gltf.accessors.accessor_23).toBeDefined(); diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index 93113164..e43c06d2 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -77,7 +77,6 @@ describe('addDefaults', function() { addDefaults(gltf); expect(gltf.animations.animationId.channels).toEqual([]); - expect(gltf.animations.animationId.parameters).toEqual({}); expect(gltf.animations.animationId.samplers).toEqual({}); }); diff --git a/specs/lib/getBinaryGltfSpec.js b/specs/lib/getBinaryGltfSpec.js index e9f474d4..699c7f5f 100644 --- a/specs/lib/getBinaryGltfSpec.js +++ b/specs/lib/getBinaryGltfSpec.js @@ -58,8 +58,8 @@ describe('getBinaryGltf', function() { expect(header.toString('utf8', 0, 4)).toEqual('glTF'); expect(header.readUInt32LE(4)).toEqual(1); - expect(header.readUInt32LE(8)).toEqual(17742); - expect(header.readUInt32LE(12)).toEqual(3932); + expect(header.readUInt32LE(8)).toEqual(17782); + expect(header.readUInt32LE(12)).toEqual(3972); expect(header.readUInt32LE(16)).toEqual(0); }); @@ -70,8 +70,8 @@ describe('getBinaryGltf', function() { expect(header.toString('utf8', 0, 4)).toEqual('glTF'); expect(header.readUInt32LE(4)).toEqual(1); - expect(header.readUInt32LE(8)).toEqual(4372); - expect(header.readUInt32LE(12)).toEqual(3512); + expect(header.readUInt32LE(8)).toEqual(4412); + expect(header.readUInt32LE(12)).toEqual(3552); expect(header.readUInt32LE(16)).toEqual(0); }); diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index 78ffc508..4abdf8b6 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -33,6 +33,16 @@ describe('updateVersion', function() { expect(gltf.asset.version).toEqual('2.0'); }); + it('updates a glTF with non-standard version to 2.0', function() { + var gltf = { + asset : { + version: '1.0.1' + } + }; + updateVersion(gltf); + expect(gltf.asset.version).toEqual('2.0'); + }); + it('updates glTF from 0.8 to 1.0', function() { var gltf = { version: '0.8', @@ -278,7 +288,11 @@ describe('updateVersion', function() { }); expect(gltf.asset.profile.version).toEqual('1.0'); var extensionsUsed = gltf.extensionsUsed; - expect(extensionsUsed).toEqual(['UNKOWN_EXTENSION']); + expect(extensionsUsed).toEqual([ + 'KHR_materials_common', + 'WEB3D_quantized_attributes', + 'UNKOWN_EXTENSION' + ]); var extensionsRequired = gltf.extensionsRequired; expect(extensionsRequired).toEqual([ 'KHR_materials_common', From f2557af4f3c69abe1ec791922d2f6a79e2bb510e Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 25 Jan 2017 21:41:39 -0500 Subject: [PATCH 09/47] Tweaks from model generation --- index.js | 1 + lib/addDefaults.js | 4 +--- lib/addPipelineExtras.js | 47 +++++++++++++------------------------ lib/removePipelineExtras.js | 1 + lib/updateVersion.js | 5 +++- lib/writeSource.js | 6 +++++ 6 files changed, 29 insertions(+), 35 deletions(-) diff --git a/index.js b/index.js index fce35f2b..eff922c2 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ module.exports = { AccessorReader : require('./lib/AccessorReader'), addCesiumRTC : require('./lib/addCesiumRTC'), addDefaults : require('./lib/addDefaults'), + addExtensionsRequired : require('./lib/addExtensionsRequired'), addExtensionsUsed : require('./lib/addExtensionsUsed'), addPipelineExtras : require('./lib/addPipelineExtras'), bakeAmbientOcclusion : require('./lib/bakeAmbientOcclusion'), diff --git a/lib/addDefaults.js b/lib/addDefaults.js index b622c130..dfe0243f 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -157,9 +157,7 @@ var gltfTemplate = { attributes: {}, uniforms: {}, states: { - '*': { - enable: [] - } + enable: [] } } }, diff --git a/lib/addPipelineExtras.js b/lib/addPipelineExtras.js index a382a8af..764e51dc 100644 --- a/lib/addPipelineExtras.js +++ b/lib/addPipelineExtras.js @@ -11,7 +11,8 @@ var exceptions = { attributes: true, uniforms: true, extensions: true, - values: true + values: true, + samplers: true }; /** @@ -22,47 +23,31 @@ var exceptions = { */ function addPipelineExtras(gltf) { var objectStack = []; - gltf.extras = defaultValue(gltf.extras, {}); - gltf.extras._pipeline = defaultValue(gltf.extras._pipeline, {}); for (var rootObjectId in gltf) { if (gltf.hasOwnProperty(rootObjectId)) { var rootObject = gltf[rootObjectId]; - for (var topLevelObjectId in rootObject) { - if (rootObject.hasOwnProperty(topLevelObjectId)) { - var topLevelObject = rootObject[topLevelObjectId]; - if (defined(topLevelObject) && typeof topLevelObject === 'object') { - objectStack.push(topLevelObject); - } - } - } + objectStack.push(rootObject); } } - if (defined(gltf.asset)) { - objectStack.push(gltf.asset); - } while (objectStack.length > 0) { var object = objectStack.pop(); - if (Array.isArray(object)) { - var length = object.length; - for (var i = 0; i < length; i++) { - var item = object[i]; - if (defined(item) && typeof item === 'object') { - objectStack.push(item); - } - } - } else { - object.extras = defaultValue(object.extras, {}); - object.extras._pipeline = defaultValue(object.extras._pipeline, {}); - for (var propertyId in object) { - if (object.hasOwnProperty(propertyId)) { - var property = object[propertyId]; - if (defined(property) && typeof property === 'object' && propertyId !== 'extras' && !exceptions[propertyId]) { - objectStack.push(property); + for (var propertyId in object) { + if (object.hasOwnProperty(propertyId)) { + var property = object[propertyId]; + if (defined(property) && typeof property === 'object' && propertyId !== 'extras') { + objectStack.push(property); + if (!exceptions[propertyId] && !Array.isArray(property)) { + property.extras = defaultValue(property.extras, {}); + property.extras._pipeline = defaultValue(property.extras._pipeline, {}); } } } } } - + gltf.extras = defaultValue(gltf.extras, {}); + gltf.extras._pipeline = defaultValue(gltf.extras._pipeline, {}); + gltf.asset = defaultValue(gltf.asset, {}); + gltf.asset.extras = defaultValue(gltf.asset.extras, {}); + gltf.asset.extras._pipeline = defaultValue(gltf.asset.extras._pipeline, {}); return gltf; } \ No newline at end of file diff --git a/lib/removePipelineExtras.js b/lib/removePipelineExtras.js index 07fe7f3c..0cdda98d 100644 --- a/lib/removePipelineExtras.js +++ b/lib/removePipelineExtras.js @@ -4,6 +4,7 @@ var Cesium = require('cesium'); var defined = Cesium.defined; module.exports = removePipelineExtras; + /** * Iterate through the objects within each glTF object and delete their pipeline extras object. * diff --git a/lib/updateVersion.js b/lib/updateVersion.js index facc6960..587fc288 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -610,7 +610,10 @@ function separateSkeletonHierarchy(gltf) { var newRootNodeId = getUniqueId(gltf, 'root-' + skeletonId); var newRootNode = { children: [], - matrix: Matrix4.pack(scratchPreApplyTransform, [], 0) + matrix: Matrix4.pack(scratchPreApplyTransform, [], 0), + extras: { + _pipeline: {} + } }; newRootNode.children.push(skeletonId); nodes[newRootNodeId] = newRootNode; diff --git a/lib/writeSource.js b/lib/writeSource.js index f12b8ec1..9b645f10 100644 --- a/lib/writeSource.js +++ b/lib/writeSource.js @@ -4,6 +4,7 @@ var fsExtra = require('fs-extra'); var mime = require('mime'); var path = require('path'); var Promise = require('bluebird'); +var isDataUri = require('./isDataUri'); var defined = Cesium.defined; @@ -32,6 +33,11 @@ function writeSource(gltf, basePath, name, embed, embedImage) { } } else { var fileName = id + extension; + var uri = object.uri; + if (defined(uri) && !isDataUri(uri)) { + // Use the original filename if it was external + fileName = uri; + } object.uri = fileName; var outputPath = path.join(basePath, fileName); promises.push(fsOutputFile(outputPath, source)); From 3d35c2140fa85935ab7a91a524a587f105b1d5ca Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 25 Jan 2017 22:12:26 -0500 Subject: [PATCH 10/47] Generate default material --- lib/addDefaults.js | 33 ++++++++++++++++++++++++++ specs/lib/addDefaultsSpec.js | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/lib/addDefaults.js b/lib/addDefaults.js index dfe0243f..46322e08 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -218,6 +218,14 @@ function addDefaultsFromTemplate(object, template) { } } +var defaultMaterial = { + values : { + emission : [ + 0.5, 0.5, 0.5, 1.0 + ] + } +}; + var defaultTechnique = { attributes : { a_position : 'position' @@ -299,6 +307,30 @@ var defaultFragmentShader = { } }; +function addDefaultMaterial(gltf) { + var meshes = gltf.meshes; + + var defaultMaterialId; + + for (var meshId in meshes) { + if (meshes.hasOwnProperty(meshId)) { + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + var primitive = primitives[i]; + if (!defined(primitive.material)) { + if (!defined(defaultMaterialId)) { + defaultMaterialId = getUniqueId(gltf, 'defaultMaterial'); + gltf.materials[defaultMaterialId] = clone(defaultMaterial, true); + } + primitive.material = defaultMaterialId; + } + } + } + } +} + function addDefaultTechnique(gltf) { var materials = gltf.materials; var techniques = gltf.techniques; @@ -421,6 +453,7 @@ function optimizeForCesium(gltf) { function addDefaults(gltf, options) { options = defaultValue(options, {}); addDefaultsFromTemplate(gltf, gltfTemplate); + addDefaultMaterial(gltf); addDefaultTechnique(gltf); enableDiffuseTransparency(gltf); if (options.optimizeForCesium) { diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index e43c06d2..2c0287f4 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -428,4 +428,50 @@ describe('addDefaults', function() { expect(gltf.techniques).toBeDefined(); expect(gltf.textures).toBeDefined(); }); + + it('Adds the default material if a mesh has an undefined material', function() { + var gltf = { + meshes: { + mesh: { + primitives: [ + {}, + {} + ] + } + } + }; + addDefaults(gltf); + + var mesh = gltf.meshes.mesh; + var meshMaterial = mesh.primitives[0].material; + expect(meshMaterial).toBeDefined(); + expect(mesh.primitives[1].material).toEqual(meshMaterial); + + expect(gltf.materials[meshMaterial]).toBeDefined(); + }); + + it('Adds the default technique, program and shader if a material has an undefined technique', function() { + var gltf = { + materials: { + material0: {}, + material1: {} + } + }; + + addDefaults(gltf); + + var techniqueId = gltf.materials.material0.technique; + expect(gltf.materials.material1.technique).toEqual(techniqueId); + var technique = gltf.techniques[techniqueId]; + expect(technique).toBeDefined(); + var programId = technique.program; + var program = gltf.programs[programId]; + expect(program).toBeDefined(); + var vertexShaderId = program.vertexShader; + var fragmentShaderId = program.fragmentShader; + var vertexShader = gltf.shaders[vertexShaderId]; + var fragmentShader = gltf.shaders[fragmentShaderId]; + expect(vertexShader).toBeDefined(); + expect(fragmentShader).toBeDefined(); + }); }); From 7f8ad7c52b3b3186e267a90f981554c449bca402 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 25 Jan 2017 22:12:33 -0500 Subject: [PATCH 11/47] Add updateVersion to buildForCesium --- gulpfile.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index 35727deb..9773c3c4 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -196,7 +196,8 @@ gulp.task('build-cesium', function () { 'numberOfComponentsForType.js', 'parseBinaryGltf.js', 'processModelMaterialsCommon.js', - 'techniqueParameterForSemantic.js' + 'techniqueParameterForSemantic.js', + 'updateVersion.js' ]; var subDependencyMapping = { cesium : { From ed61ae7695319e7bd4923b4122309b2b9a42c15e Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 25 Jan 2017 22:20:55 -0500 Subject: [PATCH 12/47] Select default scene --- lib/addDefaults.js | 14 ++++++++++++++ specs/lib/addDefaultsSpec.js | 12 +++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/addDefaults.js b/lib/addDefaults.js index 46322e08..4f93865f 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -423,6 +423,19 @@ function enableDiffuseTransparency(gltf) { } } +function selectDefaultScene(gltf) { + var scenes = gltf.scenes; + + if (!defined(gltf.scene)) { + for (var sceneId in scenes) { + if (scenes.hasOwnProperty(sceneId)) { + gltf.scene = sceneId; + break; + } + } + } +} + function optimizeForCesium(gltf) { // Give the diffuse uniform a semantic to support color replacement in 3D Tiles var techniques = gltf.techniques; @@ -456,6 +469,7 @@ function addDefaults(gltf, options) { addDefaultMaterial(gltf); addDefaultTechnique(gltf); enableDiffuseTransparency(gltf); + selectDefaultScene(gltf); if (options.optimizeForCesium) { optimizeForCesium(gltf); } diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index 2c0287f4..53110d00 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -457,7 +457,6 @@ describe('addDefaults', function() { material1: {} } }; - addDefaults(gltf); var techniqueId = gltf.materials.material0.technique; @@ -474,4 +473,15 @@ describe('addDefaults', function() { expect(vertexShader).toBeDefined(); expect(fragmentShader).toBeDefined(); }); + + it('Selects a default scene if none is present', function() { + var gltf = { + scenes: { + scene: {} + } + }; + addDefaults(gltf); + + expect(gltf.scene).toEqual('scene'); + }); }); From 7ee3137088f9d3087376302cf6f37e54eaf15584 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Thu, 26 Jan 2017 07:22:03 -0500 Subject: [PATCH 13/47] A few more small changes --- gulpfile.js | 16 ++++++++++------ lib/RemoveUnusedProperties.js | 8 ++++++++ lib/addDefaults.js | 5 +++-- lib/updateVersion.js | 16 +++++++++------- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 9773c3c4..5fd1977f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -165,13 +165,17 @@ function amdify(source, subDependencyMapping) { paths.push(requireMapping[variable]); } } - var definePathsHeader = '\'' + paths.join('\',\n \'') + '\''; - var defineVariablesHeader = variables.join(',\n '); var defineHeader = '/*global define*/\n' + - 'define([\n' + - ' ' + definePathsHeader + '\n' + - ' ], function(\n' + - ' ' + defineVariablesHeader + ') {\n '; + 'define([], function() {\n '; + if (paths.length > 0) { + var definePathsHeader = '\'' + paths.join('\',\n \'') + '\''; + var defineVariablesHeader = variables.join(',\n '); + defineHeader = '/*global define*/\n' + + 'define([\n' + + ' ' + definePathsHeader + '\n' + + ' ], function(\n' + + ' ' + defineVariablesHeader + ') {\n '; + } var defineFooter = '\n});\n'; if (defined(returnValue)) { defineFooter = '\n return ' + returnValue + ';' + defineFooter; diff --git a/lib/RemoveUnusedProperties.js b/lib/RemoveUnusedProperties.js index 82793b1c..a6212247 100644 --- a/lib/RemoveUnusedProperties.js +++ b/lib/RemoveUnusedProperties.js @@ -74,6 +74,14 @@ RemoveUnusedProperties.removeNodes = function(gltf) { nodeStack.push(child); } } + var skeletons = nodes[node].skeletons; + if (defined(skeletons)) { + var skeletonsLength = skeletons.length; + for (var k = 0; k < skeletonsLength; k++) { + var skeleton = skeletons[k]; + nodeStack.push(skeleton); + } + } } } } diff --git a/lib/addDefaults.js b/lib/addDefaults.js index 4f93865f..d71fef44 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -29,7 +29,7 @@ var gltfTemplate = { premultipliedAlpha : false, profile : { api : 'WebGL', - version : '1.0.3' + version : '1.0' } }, buffers : { @@ -169,7 +169,8 @@ var gltfTemplate = { type: WebGLConstants.UNSIGNED_BYTE } }, - extensionsUsed : [] + extensionsUsed : [], + extensionsRequired : [] }; function addDefaultsFromTemplate(object, template) { diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 587fc288..76c31939 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -240,15 +240,17 @@ function removeAnimationSamplersIndirection(gltf) { if (animations.hasOwnProperty(animationId)) { var animation = animations[animationId]; var parameters = animation.parameters; - var samplers = animation.samplers; - for (var samplerId in samplers) { - if (samplers.hasOwnProperty(samplerId)) { - var sampler = samplers[samplerId]; - sampler.input = parameters[sampler.input]; - sampler.output = parameters[sampler.output]; + if (defined(parameters)) { + var samplers = animation.samplers; + for (var samplerId in samplers) { + if (samplers.hasOwnProperty(samplerId)) { + var sampler = samplers[samplerId]; + sampler.input = parameters[sampler.input]; + sampler.output = parameters[sampler.output]; + } } + delete animation.parameters; } - delete animation.parameters; } } } From 7b63d220148d5d126c278be5452b68b8560521a1 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Thu, 26 Jan 2017 07:34:16 -0500 Subject: [PATCH 14/47] Add removePipelineExtras to cesium build --- gulpfile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/gulpfile.js b/gulpfile.js index 5fd1977f..090553eb 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -200,6 +200,7 @@ gulp.task('build-cesium', function () { 'numberOfComponentsForType.js', 'parseBinaryGltf.js', 'processModelMaterialsCommon.js', + 'removePipelineExtras.js', 'techniqueParameterForSemantic.js', 'updateVersion.js' ]; From a76c50383b50cd2071e29a3fce23c70924d32331 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Thu, 26 Jan 2017 11:53:01 -0500 Subject: [PATCH 15/47] kmc fixes --- lib/generateModelMaterialsCommon.js | 2 +- lib/processModelMaterialsCommon.js | 24 +++++++++++++++--------- lib/quantizeAttributes.js | 4 ++-- specs/lib/addDefaultsSpec.js | 2 +- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/generateModelMaterialsCommon.js b/lib/generateModelMaterialsCommon.js index a43062d2..a61eb81f 100644 --- a/lib/generateModelMaterialsCommon.js +++ b/lib/generateModelMaterialsCommon.js @@ -1,6 +1,6 @@ 'use strict'; var Cesium = require('cesium'); -var addExtensionsRequired = require('./addExtensionsUsed'); +var addExtensionsRequired = require('./addExtensionsRequired'); var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; diff --git a/lib/processModelMaterialsCommon.js b/lib/processModelMaterialsCommon.js index 736b1675..f38d9666 100644 --- a/lib/processModelMaterialsCommon.js +++ b/lib/processModelMaterialsCommon.js @@ -6,7 +6,7 @@ var defaultValue = Cesium.defaultValue; var techniqueParameterForSemantic = require('./techniqueParameterForSemantic'); -module.exports = modelMaterialsCommon; +module.exports = processModelMaterialsCommon; function webGLConstantToGlslType(webGLValue) { switch (webGLValue) { @@ -168,7 +168,7 @@ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeFo lights = gltf.extensions.KHR_materials_common.lights; } var parameterValues = khrMaterialsCommon.values; - var jointCount = defaultValue(parameterValues.jointCount, 0); + var jointCount = defaultValue(khrMaterialsCommon.jointCount, 0); var hasSkinning = (jointCount > 0); var vertexShader = 'precision highp float;\n'; @@ -570,6 +570,7 @@ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeFo // Add shaders shaders[vertexShaderId] = { type: WebGLConstants.VERTEX_SHADER, + uri: 'data:\'\';', extras: { _pipeline: { source: vertexShader, @@ -579,6 +580,7 @@ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeFo }; shaders[fragmentShaderId] = { type: WebGLConstants.FRAGMENT_SHADER, + uri: 'data:\'\';', extras: { _pipeline: { source: fragmentShader, @@ -789,7 +791,7 @@ function ensureSemanticExistence(gltf) { /** * @private */ -function modelMaterialsCommon(gltf, options) { +function processModelMaterialsCommon(gltf, options) { options = defaultValue(options, {}); if (!defined(gltf)) { @@ -797,14 +799,18 @@ function modelMaterialsCommon(gltf, options) { } var hasExtension = false; + var extensionsRequired = gltf.extensionsRequired; var extensionsUsed = gltf.extensionsUsed; if (defined(extensionsUsed)) { - var extensionsUsedCount = extensionsUsed.length; - for (var i = 0; i < extensionsUsedCount; ++i) { - if (extensionsUsed[i] === 'KHR_materials_common') { - hasExtension = true; - extensionsUsed.splice(i, 1); - break; + var index = extensionsUsed.indexOf('KHR_materials_common'); + if (index >= 0) { + extensionsUsed.splice(index, 1); + hasExtension = true; + } + if (defined(extensionsRequired)) { + index = extensionsRequired.indexOf('KHR_materials_common'); + if (index >= 0) { + extensionsRequired.splice(index, 1); } } } diff --git a/lib/quantizeAttributes.js b/lib/quantizeAttributes.js index a3967f4a..5596a49d 100644 --- a/lib/quantizeAttributes.js +++ b/lib/quantizeAttributes.js @@ -6,7 +6,7 @@ var defined = Cesium.defined; var AccessorReader = require('./AccessorReader'); -var addExtensionsUsed = require('./addExtensionsUsed'); +var addExtensionsRequired = require('./addExtensionsRequired'); var findAccessorMinMax = require('./findAccessorMinMax'); var numberOfComponentsForType = require('./numberOfComponentsForType'); var uninterleaveAndPackBuffers = require('./uninterleaveAndPackBuffers'); @@ -145,7 +145,7 @@ function quantizeAttributes(gltf, options) { // Repack the buffers uninterleaveAndPackBuffers(gltf); // Finalize - addExtensionsUsed(gltf, 'WEB3D_quantized_attributes'); + addExtensionsRequired(gltf, 'WEB3D_quantized_attributes'); } } diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index 53110d00..584194d9 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -88,7 +88,7 @@ describe('addDefaults', function() { expect(gltf.asset.premultipliedAlpha).toEqual(false); expect(gltf.asset.profile).toBeDefined(); expect(gltf.asset.profile.api).toEqual('WebGL'); - expect(gltf.asset.profile.version).toEqual('1.0.3'); + expect(gltf.asset.profile.version).toEqual('1.0'); }); it('Adds buffer properties', function() { From d8337e15d6b2193f5c58d658daa70f54452cf7c5 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Thu, 26 Jan 2017 11:53:08 -0500 Subject: [PATCH 16/47] Build global cesium include --- gulpfile.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index 090553eb..a11bae5c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -218,5 +218,25 @@ gulp.task('build-cesium', function () { var outputPath = path.join(outputDir, fileName); return fsExtraOutputFile(outputPath, source); }); - }); + }) + .then(function() { + var definePathsHeader = '\'' + files.join('\',\n \'') + '\''; + var variables = []; + var filesLength = files.length; + var body = ' var GltfPipeline = {};\n'; + for (var i = 0; i < filesLength; i++) { + var strippedName = files[i].replace('.js', ''); + variables.push(strippedName); + body += ' GltfPipeline.' + strippedName + ' = ' + strippedName + ';\n'; + } + var defineVariablesHeader = variables.join(',\n '); + var defineHeader = '/*global define*/\n' + + 'define([\n' + + ' ' + definePathsHeader + '\n' + + ' ], function(\n' + + ' ' + defineVariablesHeader + ') {\n\n'; + var defineFooter = ' return GltfPipeline;\n});\n'; + var outputPath = path.join(outputDir, 'GltfPipeline.js'); + return fsExtraOutputFile(outputPath, defineHeader + body + defineFooter); + }); }); From 9bb2d3cd7ac3d91d316d102ba611d5c88d993d13 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Thu, 26 Jan 2017 12:51:14 -0500 Subject: [PATCH 17/47] Update --- gulpfile.js | 22 +--------------------- lib/processModelMaterialsCommon.js | 2 -- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index a11bae5c..090553eb 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -218,25 +218,5 @@ gulp.task('build-cesium', function () { var outputPath = path.join(outputDir, fileName); return fsExtraOutputFile(outputPath, source); }); - }) - .then(function() { - var definePathsHeader = '\'' + files.join('\',\n \'') + '\''; - var variables = []; - var filesLength = files.length; - var body = ' var GltfPipeline = {};\n'; - for (var i = 0; i < filesLength; i++) { - var strippedName = files[i].replace('.js', ''); - variables.push(strippedName); - body += ' GltfPipeline.' + strippedName + ' = ' + strippedName + ';\n'; - } - var defineVariablesHeader = variables.join(',\n '); - var defineHeader = '/*global define*/\n' + - 'define([\n' + - ' ' + definePathsHeader + '\n' + - ' ], function(\n' + - ' ' + defineVariablesHeader + ') {\n\n'; - var defineFooter = ' return GltfPipeline;\n});\n'; - var outputPath = path.join(outputDir, 'GltfPipeline.js'); - return fsExtraOutputFile(outputPath, defineHeader + body + defineFooter); - }); + }); }); diff --git a/lib/processModelMaterialsCommon.js b/lib/processModelMaterialsCommon.js index f38d9666..b3d2643b 100644 --- a/lib/processModelMaterialsCommon.js +++ b/lib/processModelMaterialsCommon.js @@ -570,7 +570,6 @@ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeFo // Add shaders shaders[vertexShaderId] = { type: WebGLConstants.VERTEX_SHADER, - uri: 'data:\'\';', extras: { _pipeline: { source: vertexShader, @@ -580,7 +579,6 @@ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeFo }; shaders[fragmentShaderId] = { type: WebGLConstants.FRAGMENT_SHADER, - uri: 'data:\'\';', extras: { _pipeline: { source: fragmentShader, From 01b31409d6972ca8371e6f9d99bba0934fe31648 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Thu, 26 Jan 2017 12:52:59 -0500 Subject: [PATCH 18/47] Update CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index ce055af0..a3d43be0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,7 +6,7 @@ Change Log * Fixed a bug in `addPipelineExtras` that made it try to add extras to null objects. * Expose `triangleAxisAlignedBoundingBoxOverlap`, an implementation of Tomas Akenine-Möller algorithm for determining if a triangle overlaps an axis aligned bounding box. * Merged [gltf-statistics](https://github.com/AnalyticalGraphicsInc/gltf-statistics) as a stage in the pipeline. -* Added `updateVersion` stage for patching glTF `0.8` -> `1.0` changes; `addDefaults` no longer calls `processModelMaterialsCommon`. [#223](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/223) +* Added glTF `1.0` -> `2.0` into `updateVersion` and pipeline stages now follow the `2.0` specification. [#223](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/223) ### 0.1.0-alpha10 - 2017-01-10 * Added `tangentsBitangents` generation option From 3bc06ba01f76e1ba58fd0345ef8cd7ec574499a9 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Thu, 26 Jan 2017 13:11:21 -0500 Subject: [PATCH 19/47] Added two more update functions --- lib/addDefaults.js | 3 ++- lib/updateVersion.js | 45 ++++++++++++++++++++++++++++++++++ specs/lib/updateVersionSpec.js | 22 ++++++++++++++++- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/lib/addDefaults.js b/lib/addDefaults.js index d71fef44..e8549922 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -274,6 +274,7 @@ var defaultVertexShader = { type : WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { + extension : '.vert', source : '' + 'precision highp float;\n' + '\n' + @@ -294,7 +295,7 @@ var defaultFragmentShader = { type : WebGLConstants.FRAGMENT_SHADER, extras : { _pipeline : { - extension : '.vert', + extension: '.frag', source : '' + 'precision highp float;\n' + '\n' + diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 76c31939..9a5402eb 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -629,6 +629,47 @@ function separateSkeletonHierarchy(gltf) { } } +function stripTechniqueAttributeValues(gltf) { + var techniques = gltf.techniques; + for (var techniqueId in techniques) { + if (techniques.hasOwnProperty(techniqueId)) { + var technique = techniques[techniqueId]; + var attributes = technique.attributes; + var parameters = technique.parameters; + for (var attributeName in attributes) { + if (attributes.hasOwnProperty(attributeName)) { + var parameterId = attributes[attributeName]; + var parameter = parameters[parameterId]; + if (defined(parameter.value)) { + delete parameter.value; + } + } + } + } + } +} + +function stripTechniqueParameterCount(gltf) { + var techniques = gltf.techniques; + for (var techniqueId in techniques) { + if (techniques.hasOwnProperty(techniqueId)) { + var technique = techniques[techniqueId]; + var parameters = technique.parameters; + for (var parameterId in parameters) { + if (parameters.hasOwnProperty(parameterId)) { + var parameter = parameters[parameterId]; + if (defined(parameter.count)) { + var semantic = parameter.semantic; + if (!defined(semantic) || (semantic !== 'JOINTMATRIX' && semantic.indexOf('_') !== 0)) { + delete parameter.count; + } + } + } + } + } + } +} + function glTF10to20(gltf) { if (!defined(gltf.asset)) { gltf.asset = {}; @@ -665,4 +706,8 @@ function glTF10to20(gltf) { clampCameraParameters(gltf); // skeleton hierarchy must be separate from the node hierarchy (a node with jointName cannot contain camera, skeletons, skins, or meshes) separateSkeletonHierarchy(gltf); + // a technique parameter specified as an attribute cannot have a value + stripTechniqueAttributeValues(gltf); + // only techniques with a JOINTMATRIX or application specific semantic may have a defined count property + stripTechniqueParameterCount(gltf); } diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index 4abdf8b6..ad39094a 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -200,6 +200,9 @@ describe('updateVersion', function() { scissor: [0.0, 0.0, 0.0, 0.0] } }, + attributes: { + a_application: 'application' + }, parameters: { lightAttenuation: { value: 1.0 @@ -211,7 +214,19 @@ describe('updateVersion', function() { semantic: 'COLOR' }, application: { - semantic: 'APPLICATIONSPECIFIC' + semantic: 'APPLICATIONSPECIFIC', + count: 1, + value: 2 + }, + jointMatrix: { + semantic: 'JOINTMATRIX', + count: 2 + }, + notJointMatrix: { + count: 3 + }, + notJointMatrixWithSemantic: { + count: 4 } } } @@ -309,6 +324,7 @@ describe('updateVersion', function() { expect(material.values.shininess).toEqual([1.0]); var technique = gltf.techniques.technique; expect(technique.parameters.lightAttenuation.value).toEqual([1.0]); + expect(technique.parameters.application.value).not.toBeDefined(); expect(technique.parameters.texcoord.semantic).toEqual('TEXCOORD_0'); expect(technique.parameters.color.semantic).toEqual('COLOR_0'); expect(technique.parameters.application.semantic).toEqual('_APPLICATIONSPECIFIC'); @@ -342,6 +358,10 @@ describe('updateVersion', function() { expect(buffer.byteLength).toEqual(arrayBuffer.length); var bufferView = gltf.bufferViews.bufferView; expect(bufferView.byteLength).toEqual(arrayBuffer.length); + expect(technique.parameters.application.count).toEqual(1); + expect(technique.parameters.jointMatrix.count).toEqual(2); + expect(technique.parameters.notJointMatrix.count).not.toBeDefined(); + expect(technique.parameters.notJointMatrixWithSemantic.count).not.toBeDefined(); }); it('does not add glExtensionsUsed if primitive indices are not UNSIGNED_INT', function() { From 6d584075eef0590f7dc86e9ac43b429230ec2f16 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 26 Jan 2017 16:36:48 -0500 Subject: [PATCH 20/47] Update CHANGES.md --- CHANGES.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a3d43be0..8a261390 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,11 +6,12 @@ Change Log * Fixed a bug in `addPipelineExtras` that made it try to add extras to null objects. * Expose `triangleAxisAlignedBoundingBoxOverlap`, an implementation of Tomas Akenine-Möller algorithm for determining if a triangle overlaps an axis aligned bounding box. * Merged [gltf-statistics](https://github.com/AnalyticalGraphicsInc/gltf-statistics) as a stage in the pipeline. -* Added glTF `1.0` -> `2.0` into `updateVersion` and pipeline stages now follow the `2.0` specification. [#223](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/223) +* Added `updateVersion` stage for upgrading the glTF version of an asset, including upgrading from `1.0` to `2.0`. [#223](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/223) + * All pipeline stages now operator on glTF `2.0` assets. + * `addDefaults` no longer automatically upgrades glTF `0.8` to `1.0`. ### 0.1.0-alpha10 - 2017-01-10 * Added `tangentsBitangents` generation option -* Added `updateVersion` stage for transitioning assets between glTF version and migrated any glTF 0.8 code out of `addDefaults` ### 0.1.0-alpha9 - 2017-01-03 * Fixed issue with embedding base64 encoded shader strings for assets using the KHR_materials_common extension From 0d6e895f865d87bd35b9d05a79d8856ceaffae20 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Thu, 26 Jan 2017 22:44:39 -0500 Subject: [PATCH 21/47] Strip version numbers when guessing if invalid --- lib/updateVersion.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 9a5402eb..79dcb41a 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -17,7 +17,7 @@ module.exports = updateVersion; var updateFunctions = { '0.8' : glTF08to10, '1.0' : glTF10to20, - '2.0' : null + '2.0' : undefined }; /** @@ -40,12 +40,20 @@ function updateVersion(gltf, options) { }); version = defaultValue(version, gltf.asset.version); - // invalid version, default to 1.0 + // invalid version if (!updateFunctions.hasOwnProperty(version)) { - version = '1.0'; + // try truncating trailing version numbers, could be a number as well if it is 0.8 + if (defined(version)) { + version = ('' + version).substring(0, 3); + } + // default to 1.0 if it cannot be determined + if (!updateFunctions.hasOwnProperty(version)) { + version = '1.0'; + } } var updateFunction = updateFunctions[version]; + while (defined(updateFunction)) { version = gltf.asset.version; if (version === targetVersion) { @@ -552,7 +560,6 @@ function getNodeTransform(node) { } } - function separateSkeletonHierarchy(gltf) { var nodes = gltf.nodes; var scenes = gltf.scenes; From 843a48029ac33aa78427d53d57bf39069a6926d6 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Mon, 13 Feb 2017 19:30:53 -0500 Subject: [PATCH 22/47] WIP Array-based Traversal --- lib/NodeHelpers.js | 94 +++-- lib/addCesiumRTC.js | 2 + lib/addDefaults.js | 256 +++++++------- lib/addPipelineExtras.js | 19 +- lib/addToArray.js | 14 + lib/bakeAmbientOcclusion.js | 54 ++- lib/cesiumGeometryToGltfPrimitive.js | 10 +- lib/combineNodes.js | 1 - lib/createAccessor.js | 53 ++- lib/getAvailableArraySlot.js | 16 + lib/removeDuplicatePrimitives.js | 58 ++- .../ambientOcclusion/cube_over_ground.gltf | 261 +++++++------- .../CesiumTexturedBoxTest.gltf | 147 ++++---- .../CesiumTexturedBoxTestAddExtras.gltf | 147 ++++---- .../CesiumTexturedBoxTestTransparent.gltf | 147 ++++---- specs/lib/NodeHelpersSpec.js | 60 ++-- specs/lib/addDefaultsSpec.js | 329 ++++++++---------- specs/lib/addPipelineExtrasSpec.js | 69 ++-- specs/lib/bakeAmbientOcclusionSpec.js | 91 +++-- specs/lib/removeDuplicatePrimitivesSpec.js | 24 +- 20 files changed, 905 insertions(+), 947 deletions(-) create mode 100644 lib/addToArray.js create mode 100644 lib/getAvailableArraySlot.js diff --git a/lib/NodeHelpers.js b/lib/NodeHelpers.js index fb0bf8af..657317c6 100644 --- a/lib/NodeHelpers.js +++ b/lib/NodeHelpers.js @@ -48,15 +48,15 @@ function flattenTransform(parameters, node, parent) { * @private */ NodeHelpers.computeFlatTransformScene = function(scene, nodes) { - var rootNodeIDs = scene.nodes; + var nodeIds = scene.nodes; var parameters = { matrix4Scratch: matrix4Scratch }; - for (var id in rootNodeIDs) { - if (rootNodeIDs.hasOwnProperty(id)) { - var rootNode = nodes[rootNodeIDs[id]]; - NodeHelpers.depthFirstTraversal(rootNode, nodes, flattenTransform, parameters); - } + var nodeIdsLength = nodeIds.length; + for (var i = 0; i < nodeIdsLength; i++) { + var nodeId = nodeIds[i]; + var node = nodes[nodeId]; + NodeHelpers.depthFirstTraversal(node, nodes, flattenTransform, parameters); } }; @@ -77,18 +77,18 @@ function addNodeToArray(parameters, node) { * @private */ NodeHelpers.getAllNodesInScene = function(scene, nodes, resultArray) { - var rootNodeIDs = scene.nodes; + var nodeIds = scene.nodes; if (!defined(resultArray)) { resultArray = []; } var parameters = { nodeArray: resultArray }; - for (var id in rootNodeIDs) { - if (rootNodeIDs.hasOwnProperty(id)) { - var rootNode = nodes[rootNodeIDs[id]]; - NodeHelpers.depthFirstTraversal(rootNode, nodes, addNodeToArray, parameters); - } + var nodeIdsLength = nodeIds.length; + for (var i = 0; i < nodeIdsLength; i++) { + var nodeId = nodeIds[i]; + var node = nodes[nodeId]; + NodeHelpers.depthFirstTraversal(node, nodes, addNodeToArray, parameters); } return resultArray; }; @@ -118,14 +118,13 @@ NodeHelpers.depthFirstTraversal = function(rootNode, allNodes, functionChildPare if (!defined(currentNode.children)) { continue; } - var childrenIDs = currentNode.children; - for (var id in childrenIDs) { - if (childrenIDs.hasOwnProperty(id)) { - var childID = childrenIDs[id]; - var childNode = allNodes[childID]; - functionChildParent(parameters, childNode, currentNode); - nodeStack.push(childNode); - } + var children = currentNode.children; + var childrenLength = children.length; + for (var i = 0; i < childrenLength; i++) { + var childId = children[i]; + var childNode = allNodes[childId]; + functionChildParent(parameters, childNode, currentNode); + nodeStack.push(childNode); } } }; @@ -190,16 +189,15 @@ var packedParametersScratch = { * @private */ NodeHelpers.forEachPrimitiveInScene = function(gltf, scene, primitiveFunction, parameters) { - var rootNodeNames = scene.nodes; - var allNodes = gltf.nodes; + var nodeIds = scene.nodes; + var nodes = gltf.nodes; packedParametersScratch.meshes = gltf.meshes; packedParametersScratch.parameters = parameters; packedParametersScratch.primitiveFunction = primitiveFunction; - for (var nodeID in rootNodeNames) { - if (rootNodeNames.hasOwnProperty(nodeID)) { - var rootNodeName = rootNodeNames[nodeID]; - NodeHelpers.depthFirstTraversal(allNodes[rootNodeName], allNodes, forEachPrimitiveInNode, packedParametersScratch); - } + var nodeIdsLength = nodeIds.length; + for (var i = 0; i < nodeIdsLength; i++) { + var nodeId = nodeIds[i]; + NodeHelpers.depthFirstTraversal(nodes[nodeId], nodes, forEachPrimitiveInNode, packedParametersScratch); } }; @@ -208,18 +206,17 @@ function forEachPrimitiveInNode(packedParameters, node) { var parameters = packedParameters.parameters; var primitiveFunction = packedParameters.primitiveFunction; - var meshIDs = node.meshes; - if (!defined(meshIDs)) { + var meshId = node.mesh; + if (!defined(meshId)) { return; } - var meshIdsLength = meshIDs.length; - for (var i = 0; i < meshIdsLength; i++) { - var meshID = meshIDs[i]; - var meshData = meshes[meshID]; - var primitives = meshData.primitives; - var primitiveIdsLength = primitives.length; - for (var j = 0; j < primitiveIdsLength; j++) { - primitiveFunction(primitives[j], meshID + '_' + j, parameters, node); + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + if (defined(primitives)) { + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + var primitive = primitives[i]; + primitiveFunction(primitive, meshId + '_' + i, parameters, node); } } } @@ -235,21 +232,18 @@ function forEachPrimitiveInNode(packedParameters, node) { NodeHelpers.mapMeshesToNodes = function(gltf) { var meshesToNodes = {}; var nodes = gltf.nodes; - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { + if (defined(nodes)) { + var nodesLength = nodes.length; + for (var nodeId = 0; nodeId < nodesLength; nodeId++) { var node = nodes[nodeId]; - var meshes = node.meshes; - if (defined(meshes)) { - var meshesLength = meshes.length; - for (var i = 0; i < meshesLength; i++) { - var mesh = meshes[i]; - var nodeMapping = meshesToNodes[mesh]; - if (!defined(nodeMapping)) { - nodeMapping = []; - meshesToNodes[mesh] = nodeMapping; - } - nodeMapping.push(nodeId); + var meshId = node.mesh; + if (defined(meshId)) { + var nodeMapping = meshesToNodes[meshId]; + if (!defined(nodeMapping)) { + nodeMapping = []; + meshesToNodes[meshId] = nodeMapping; } + nodeMapping.push(nodeId); } } } diff --git a/lib/addCesiumRTC.js b/lib/addCesiumRTC.js index e9dbf7fa..b9d196b4 100644 --- a/lib/addCesiumRTC.js +++ b/lib/addCesiumRTC.js @@ -6,6 +6,7 @@ var Ellipsoid = Cesium.Ellipsoid; var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; +var addExtensionsRequired = require('./addExtensionsRequired'); var addExtensionsUsed = require('./addExtensionsUsed'); module.exports = addCesiumRTC; @@ -44,6 +45,7 @@ function addCesiumRTC(gltf, options) { extensions.CESIUM_RTC = { center : positionArray }; + addExtensionsRequired(gltf, 'CEISUM_RTC'); addExtensionsUsed(gltf, 'CESIUM_RTC'); var techniques = gltf.techniques; for (var techniqueId in techniques) { diff --git a/lib/addDefaults.js b/lib/addDefaults.js index e8549922..018bc9bb 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -1,6 +1,6 @@ 'use strict'; var Cesium = require('cesium'); -var getUniqueId = require('./getUniqueId'); +var addToArray = require('./addToArray'); var clone = Cesium.clone; var defaultValue = Cesium.defaultValue; @@ -10,21 +10,21 @@ var WebGLConstants = Cesium.WebGLConstants; module.exports = addDefaults; var gltfTemplate = { - accessors : { - '*' : { + accessors : [ + { byteStride : 0 } - }, - animations : { - '*' : { + ], + animations : [ + { channels : [], - samplers : { - '*' : { + samplers : [ + { interpolation : 'LINEAR' } - } + ] } - }, + ], asset : { premultipliedAlpha : false, profile : { @@ -32,21 +32,21 @@ var gltfTemplate = { version : '1.0' } }, - buffers : { - '*': { + buffers : [ + { byteLength: 0, type: 'arraybuffer' } - }, - bufferViews: { - '*': { + ], + bufferViews: [ + { byteLength: 0 } - }, - cameras: {}, - images: {}, - materials: { - '*': { + ], + cameras: [], + images: [], + materials: [ + { values: function(material) { var extensions = defaultValue(material.extensions, {}); var materialsCommon = extensions.KHR_materials_common; @@ -81,9 +81,9 @@ var gltfTemplate = { } } } - }, - meshes : { - '*' : { + ], + meshes : [ + { primitives : [ { attributes : {}, @@ -91,9 +91,9 @@ var gltfTemplate = { } ] } - }, - nodes : { - '*' : { + ], + nodes : [ + { children : [], matrix : function(node) { if (!defined(node.translation) && !defined(node.rotation) && !defined(node.scale)) { @@ -121,28 +121,28 @@ var gltfTemplate = { } } } - }, - programs : { - '*' : { + ], + programs : [ + { attributes : [] } - }, - samplers : { - '*' : { + ], + samplers : [ + { magFilter: WebGLConstants.LINEAR, minFilter : WebGLConstants.NEAREST_MIPMAP_LINEAR, wrapS : WebGLConstants.REPEAT, wrapT : WebGLConstants.REPEAT } - }, - scenes : { - '*' : { + ], + scenes : [ + { nodes : [] } - }, - shaders : {}, - skins : { - '*' : { + ], + shaders : [], + skins : [ + { bindShapeMatrix : [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, @@ -150,9 +150,9 @@ var gltfTemplate = { 0.0, 0.0, 0.0, 1.0 ] } - }, - techniques : { - '*' : { + ], + techniques : [ + { parameters: {}, attributes: {}, uniforms: {}, @@ -160,15 +160,15 @@ var gltfTemplate = { enable: [] } } - }, - textures : { - '*' : { + ], + textures : [ + { format: WebGLConstants.RGBA, internalFormat: WebGLConstants.RGBA, target: WebGLConstants.TEXTURE_2D, type: WebGLConstants.UNSIGNED_BYTE } - }, + ], extensionsUsed : [], extensionsRequired : [] }; @@ -310,24 +310,23 @@ var defaultFragmentShader = { }; function addDefaultMaterial(gltf) { + var materials = gltf.materials; var meshes = gltf.meshes; var defaultMaterialId; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - if (!defined(primitive.material)) { - if (!defined(defaultMaterialId)) { - defaultMaterialId = getUniqueId(gltf, 'defaultMaterial'); - gltf.materials[defaultMaterialId] = clone(defaultMaterial, true); - } - primitive.material = defaultMaterialId; + var meshesLength = meshes.length; + for (var meshId = 0; meshId < meshesLength; meshId++) { + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + var primitivesLength = primitives.length; + for (var j = 0; j < primitivesLength; j++) { + var primitive = primitives[j]; + if (!defined(primitive.material)) { + if (!defined(defaultMaterialId)) { + defaultMaterialId = addToArray(materials, clone(defaultMaterial, true)); } + primitive.material = defaultMaterialId; } } } @@ -340,41 +339,30 @@ function addDefaultTechnique(gltf) { var shaders = gltf.shaders; var defaultTechniqueId; - var defaultProgramId; - var defaultVertexShaderId; - var defaultFragmentShaderId; - for (var materialId in materials) { - if (materials.hasOwnProperty(materialId)) { - var material = materials[materialId]; - var techniqueId = material.technique; - var extensions = defaultValue(material.extensions, {}); - var materialsCommon = extensions.KHR_materials_common; - if (!defined(techniqueId)) { - if (!defined(defaultTechniqueId) && !defined(materialsCommon)) { - defaultTechniqueId = getUniqueId(gltf, 'defaultTechnique'); - defaultProgramId = getUniqueId(gltf, 'defaultProgram'); - defaultVertexShaderId = getUniqueId(gltf, 'defaultVertexShader'); - defaultFragmentShaderId = getUniqueId(gltf, 'defaultFragmentShader'); + var materialsLength = materials.length; + for (var materialId = 0; materialId < materialsLength; materialId++) { + var material = materials[materialId]; + var techniqueId = material.technique; + var extensions = defaultValue(material.extensions, {}); + var materialsCommon = extensions.KHR_materials_common; + if (!defined(techniqueId)) { + if (!defined(defaultTechniqueId) && !defined(materialsCommon)) { + var technique = clone(defaultTechnique, true); + defaultTechniqueId = addToArray(techniques, technique); - var technique = clone(defaultTechnique, true); - techniques[defaultTechniqueId] = technique; - technique.program = defaultProgramId; + var program = clone(defaultProgram, true); + technique.program = addToArray(programs, program); - var program = clone(defaultProgram, true); - programs[defaultProgramId] = program; - program.vertexShader = defaultVertexShaderId; - program.fragmentShader = defaultFragmentShaderId; + var vertexShader = clone(defaultVertexShader, true); + program.vertexShader = addToArray(shaders, vertexShader); - var vertexShader = clone(defaultVertexShader, true); - shaders[defaultVertexShaderId] = vertexShader; - - var fragmentShader = clone(defaultFragmentShader, true); - shaders[defaultFragmentShaderId] = fragmentShader; - } - material.technique = defaultTechniqueId; + var fragmentShader = clone(defaultFragmentShader, true); + program.fragmentShader = addToArray(shaders, fragmentShader); } + material.technique = defaultTechniqueId; } + } } @@ -382,45 +370,45 @@ function enableDiffuseTransparency(gltf) { var materials = gltf.materials; var techniques = gltf.techniques; - for (var materialId in materials) { - if (materials.hasOwnProperty(materialId)) { - var material = materials[materialId]; - if (defined(material.values) && defined(material.values.diffuse)) { - // Check if the diffuse texture/color is transparent - var diffuse = material.values.diffuse; - var diffuseTransparent = false; - if (typeof diffuse === 'string') { - diffuseTransparent = gltf.images[gltf.textures[diffuse].source].extras._pipeline.transparent; - } else { - diffuseTransparent = diffuse[3] < 1.0; - } + var materialsLength = materials.length; + for (var materialId = 0; materialId < materialsLength; materialId++) { + var material = materials[materialId]; + if (defined(material.values) && defined(material.values.diffuse)) { + // Check if the diffuse texture/color is transparent + var diffuse = material.values.diffuse; + var diffuseTransparent = false; + if (diffuse.length === 1) { + diffuseTransparent = gltf.images[gltf.textures[diffuse[0]].source].extras._pipeline.transparent; + } else { + diffuseTransparent = diffuse[3] < 1.0; + } - var technique = techniques[material.technique]; - var blendingEnabled = technique.states.enable.indexOf(WebGLConstants.BLEND) > -1; + var technique = techniques[material.technique]; + var blendingEnabled = technique.states.enable.indexOf(WebGLConstants.BLEND) > -1; - // Override the technique's states if blending isn't already enabled - if (diffuseTransparent && !blendingEnabled) { - technique.states = { - enable: [ - WebGLConstants.DEPTH_TEST, - WebGLConstants.BLEND + // Override the technique's states if blending isn't already enabled + if (diffuseTransparent && !blendingEnabled) { + technique.states = { + enable: [ + WebGLConstants.DEPTH_TEST, + WebGLConstants.BLEND + ], + depthMask: false, + functions: { + blendEquationSeparate: [ + WebGLConstants.FUNC_ADD, + WebGLConstants.FUNC_ADD ], - depthMask: false, - functions: { - blendEquationSeparate: [ - WebGLConstants.FUNC_ADD, - WebGLConstants.FUNC_ADD - ], - blendFuncSeparate: [ - WebGLConstants.ONE, - WebGLConstants.ONE_MINUS_SRC_ALPHA, - WebGLConstants.ONE, - WebGLConstants.ONE_MINUS_SRC_ALPHA - ] - } - }; - } + blendFuncSeparate: [ + WebGLConstants.ONE, + WebGLConstants.ONE_MINUS_SRC_ALPHA, + WebGLConstants.ONE, + WebGLConstants.ONE_MINUS_SRC_ALPHA + ] + } + }; } + } } } @@ -429,11 +417,10 @@ function selectDefaultScene(gltf) { var scenes = gltf.scenes; if (!defined(gltf.scene)) { - for (var sceneId in scenes) { - if (scenes.hasOwnProperty(sceneId)) { - gltf.scene = sceneId; - break; - } + var scenesLength = scenes.length; + for (var sceneId = 0; sceneId < scenesLength; sceneId++) { + gltf.scene = sceneId; + break; } } } @@ -441,13 +428,12 @@ function selectDefaultScene(gltf) { function optimizeForCesium(gltf) { // Give the diffuse uniform a semantic to support color replacement in 3D Tiles var techniques = gltf.techniques; - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = techniques[techniqueId]; - var parameters = technique.parameters; - if (defined(parameters.diffuse)) { - parameters.diffuse.semantic = '_3DTILESDIFFUSE'; - } + var techniquesLength = techniques.length; + for (var techniqueId = 0; techniqueId < techniquesLength; techniqueId++) { + var technique = techniques[techniqueId]; + var parameters = technique.parameters; + if (defined(parameters.diffuse)) { + parameters.diffuse.semantic = '_3DTILESDIFFUSE'; } } } diff --git a/lib/addPipelineExtras.js b/lib/addPipelineExtras.js index 764e51dc..35fc5f4b 100644 --- a/lib/addPipelineExtras.js +++ b/lib/addPipelineExtras.js @@ -23,10 +23,18 @@ var exceptions = { */ function addPipelineExtras(gltf) { var objectStack = []; - for (var rootObjectId in gltf) { - if (gltf.hasOwnProperty(rootObjectId)) { - var rootObject = gltf[rootObjectId]; - objectStack.push(rootObject); + for (var rootArrayId in gltf) { + if (gltf.hasOwnProperty(rootArrayId)) { + var rootArray = gltf[rootArrayId]; + var rootArrayLength = rootArray.length; + for (var i = 0; i < rootArrayLength; i++) { + var rootObject = rootArray[i]; + if (defined(rootObject) && typeof rootObject === 'object') { + rootObject.extras = defaultValue(rootObject.extras, {}); + rootObject.extras._pipeline = defaultValue(rootObject.extras._pipeline, {}); + objectStack.push(rootObject); + } + } } } while (objectStack.length > 0) { @@ -49,5 +57,8 @@ function addPipelineExtras(gltf) { gltf.asset = defaultValue(gltf.asset, {}); gltf.asset.extras = defaultValue(gltf.asset.extras, {}); gltf.asset.extras._pipeline = defaultValue(gltf.asset.extras._pipeline, {}); + gltf.asset.profile = defaultValue(gltf.asset.profile, {}); + gltf.asset.profile.extras = defaultValue(gltf.asset.profile.extras, {}); + gltf.asset.profile.extras._pipeline = defaultValue(gltf.asset.profile.extras_pipeline, {}); return gltf; } \ No newline at end of file diff --git a/lib/addToArray.js b/lib/addToArray.js new file mode 100644 index 00000000..ef53949e --- /dev/null +++ b/lib/addToArray.js @@ -0,0 +1,14 @@ +'use strict'; +var getAvailableArraySlot = require('./getAvailableArraySlot'); + +module.exports = addToArray; + +function addToArray(array, element) { + var index = getAvailableArraySlot(array); + if (index >= array.length) { + array.push(element); + return array.length - 1; + } + array[index] = element; + return index; +} \ No newline at end of file diff --git a/lib/bakeAmbientOcclusion.js b/lib/bakeAmbientOcclusion.js index c1bd8bd3..09dc3e77 100644 --- a/lib/bakeAmbientOcclusion.js +++ b/lib/bakeAmbientOcclusion.js @@ -1,11 +1,17 @@ 'use strict'; var Cesium = require('cesium'); -var clone = require('clone'); +var Jimp = require('jimp'); +var addToArray = require('./addToArray'); +var GeometryMath = require('./GeometryMath'); +var NodeHelpers = require('./NodeHelpers'); +var readAccessor = require('./readAccessor'); +var StaticUniformGrid = require('./StaticUniformGrid'); var baryCentricCoordinates = Cesium.barycentricCoordinates; var Cartesian2 = Cesium.Cartesian2; var Cartesian3 = Cesium.Cartesian3; var CesiumMath = Cesium.Math; +var clone = Cesium.clone; var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; var DeveloperError = Cesium.DeveloperError; @@ -17,13 +23,6 @@ var ShaderSource = Cesium.ShaderSource; var WebGLConstants = Cesium.WebGLConstants; var IntersectionTests = Cesium.IntersectionTests; -var GeometryMath = require('./GeometryMath'); -var getUniqueId = require('./getUniqueId'); -var Jimp = require('jimp'); -var NodeHelpers = require('./NodeHelpers'); -var readAccessor = require('./readAccessor'); -var StaticUniformGrid = require('./StaticUniformGrid'); - var scratchRay = new Ray(); var barycentricCoordinateScratch = new Cartesian3(); var worldPositionScratch = new Cartesian3(); @@ -323,9 +322,7 @@ function addVertexData(gltf, options) { var allAOData = parameters.allAOData; var allAODataLength = allAOData.length; - var aoBufferId = getUniqueId(gltf, 'aoBuffer'); - - gltf.buffers[aoBufferId] = { + var aoBuffer = { type: 'arraybuffer', extras: { _pipeline: { @@ -334,16 +331,16 @@ function addVertexData(gltf, options) { } } }; + var aoBufferId = addToArray(gltf.buffers, aoBuffer); // add buffer view - var aoBufferViewId = getUniqueId(gltf, 'aoBufferView'); - - gltf.bufferViews[aoBufferViewId] = { + var aoBufferView = { buffer: aoBufferId, byteOffset: 0, byteLength: allAODataLength * 4, target: WebGLConstants.ARRAY_BUFFER }; + var aoBufferViewId = addToArray(gltf.bufferViews, aoBufferView); // add accessor for each primitive var primitiveCount = primitiveOrder.length; @@ -351,15 +348,14 @@ function addVertexData(gltf, options) { for (var i = 0; i < primitiveCount; i++) { var primitive = primitiveOrder[i]; var primitiveVertexCount = parameters.primitiveVertexCounts[i]; - var name = 'accessor_' + parameters.primitiveNames[i] + '_AO'; - primitive.attributes._OCCLUSION = name; - gltf.accessors[name] = { + var aoAccessor = { bufferView: aoBufferViewId, byteOffset: byteOffset, componentType: WebGLConstants.FLOAT, count: primitiveVertexCount, type: 'SCALAR' }; + primitive.attributes._OCCLUSION = addToArray(gltf.accessors, aoAccessor); byteOffset += primitiveVertexCount * 4; } } @@ -573,16 +569,15 @@ function bakeToTexture(gltf, options) { var exampleTextureID; var exampleImageID; - for (var materialID in materials) { - if (materials.hasOwnProperty(materialID)) { - var material = materials[materialID]; - if (defined(material.values) && defined(material.values.diffuse)) { - if (typeof material.values.diffuse === 'string') { - exampleMaterialID = materialID; - exampleTextureID = material.values.diffuse; - exampleImageID = textures[exampleTextureID].source; - break; - } + var materialsLength = materials.length; + for (var materialId = 0; materialId < materialsLength; materialId++) { + var material = materials[materialId]; + if (defined(material.values) && defined(material.values.diffuse)) { + if (typeof material.values.diffuse === 'string') { + exampleMaterialID = materialId; + exampleTextureID = material.values.diffuse; + exampleImageID = textures[exampleTextureID].source; + break; } } } @@ -719,8 +714,7 @@ function ensureImageUniqueness(gltf, options) { var newImageID = meshPrimitiveID + '_AO_image'; // Grab the existing material - var materialID = primitive.material; - var material = allMaterials[materialID]; + var material = allMaterials[primitive.material]; var values = material.values; var diffuse = values.diffuse; @@ -728,7 +722,7 @@ function ensureImageUniqueness(gltf, options) { // - clone the example material // - clone the example texture // - clone the example image. resize to resolution and set to diffuse color, if any - if (!defined(diffuse) || typeof diffuse !== 'string') { + if (!defined(diffuse) || diffuse.length > 1) { cloneAndSetupMaterialTextureImage({ newMaterialID : newMaterialID, newTextureID : newTextureID, diff --git a/lib/cesiumGeometryToGltfPrimitive.js b/lib/cesiumGeometryToGltfPrimitive.js index 7ba950d5..e721c3f8 100644 --- a/lib/cesiumGeometryToGltfPrimitive.js +++ b/lib/cesiumGeometryToGltfPrimitive.js @@ -27,16 +27,8 @@ function getFirstAttributeSemantic(gltf, primitive, semantic, packedLength) { throw new DeveloperError('Unsupported attribute semantic: ' + semantic); } if (semantics.length <= 0) { - - var id; - - // all attributes but texcoords may occur only once - if (semantic !== 'TEXCOORD') { - id = 'accessor_' + semantic.toLowerCase(); - } - primitive.attributes[semantic] = createAccessor(gltf, packedLength, type, - WebGLConstants.FLOAT, WebGLConstants.ARRAY_BUFFER, id); + WebGLConstants.FLOAT, WebGLConstants.ARRAY_BUFFER); return semantic; } return semantics[0]; diff --git a/lib/combineNodes.js b/lib/combineNodes.js index c6b128f0..2894d016 100644 --- a/lib/combineNodes.js +++ b/lib/combineNodes.js @@ -42,7 +42,6 @@ function combineNodes(gltf) { var rootNodeId = getUniqueId(gltf, rootNodePrefix); var rootNode = { children : sceneNodes, - meshes : [], matrix : [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, diff --git a/lib/createAccessor.js b/lib/createAccessor.js index f2187335..d81a8742 100644 --- a/lib/createAccessor.js +++ b/lib/createAccessor.js @@ -1,9 +1,9 @@ 'use strict'; var Cesium = require('cesium'); +var addToArray = require('./addToArray'); var byteLengthForComponentType = require('./byteLengthForComponentType'); var findAccessorMinMax = require('./findAccessorMinMax'); -var getUniqueId = require('./getUniqueId'); var numberOfComponentsForType = require('./numberOfComponentsForType'); var writeBufferComponent = require('./writeBufferComponent'); @@ -20,11 +20,10 @@ module.exports = createAccessor; * @param {String} type glTF type (e.g. 'scalar', 'vec3') * @param {Number} componentType glTF component type (e.g. 5126 (float)) * @param {Number} target glTF bufferView target (e.g. 34962 (ARRAY_BUFFER), 34963 (ELEMENT_ARRAY_BUFFER) - * @param {String} [id] The id to use when assigning the accessor to the glTF asset. If undefined, a unique id is generated. * * @returns {String} The accessor's id. */ -function createAccessor(gltf, dataOrLength, type, componentType, target, id) { +function createAccessor(gltf, dataOrLength, type, componentType, target) { var numberOfComponents = numberOfComponentsForType(type); var data; var dataLength; @@ -38,29 +37,24 @@ function createAccessor(gltf, dataOrLength, type, componentType, target, id) { throw new DeveloperError('Length of data written must be a multiple of the number of accessor components.'); } var componentByteLength = byteLengthForComponentType(componentType); - if (!defined(id)) { - id = getUniqueId(gltf, 'accessor'); - } - var bufferViewId = getUniqueId(gltf, 'bufferView'); - var bufferId = getUniqueId(gltf, 'buffer'); var bufferData = new Buffer(dataLength * componentByteLength); if (defined(data)) { for (var i = 0; i < data.length; i++) { writeBufferComponent(bufferData, componentType, data[i], i * componentByteLength); } } - var accessor = { - bufferView : bufferViewId, - byteOffset : 0, - byteStride : 0, - componentType : componentType, - count : dataLength / numberOfComponents, + + var buffer = { + type : "arraybuffer", + byteLength : bufferData.length, extras : { - _pipeline : {} - }, - type : type + _pipeline : { + extension : '.bin', + source : bufferData + } + } }; - gltf.accessors[id] = accessor; + var bufferId = addToArray(gltf.buffers, buffer); var bufferView = { buffer : bufferId, @@ -71,22 +65,23 @@ function createAccessor(gltf, dataOrLength, type, componentType, target, id) { }, target : target }; - gltf.bufferViews[bufferViewId] = bufferView; + var bufferViewId = addToArray(gltf.bufferViews, bufferView); - var buffer = { - type : "arraybuffer", - byteLength : bufferData.length, + var accessor = { + bufferView : bufferViewId, + byteOffset : 0, + byteStride : 0, + componentType : componentType, + count : dataLength / numberOfComponents, extras : { - _pipeline : { - extension : '.bin', - source : bufferData - } - } + _pipeline : {} + }, + type : type }; - gltf.buffers[bufferId] = buffer; + var accessorId = addToArray(gltf.accessors, accessor); var minMax = findAccessorMinMax(gltf, accessor); accessor.min = minMax.min; accessor.max = minMax.max; - return id; + return accessorId; } \ No newline at end of file diff --git a/lib/getAvailableArraySlot.js b/lib/getAvailableArraySlot.js new file mode 100644 index 00000000..9e912ac2 --- /dev/null +++ b/lib/getAvailableArraySlot.js @@ -0,0 +1,16 @@ +'use strict'; +var Cesium = require('cesium'); + +var defined = Cesium.defined; + +module.exports = getAvailableArraySlot; + +function getAvailableArraySlot(array) { + var arrayLength = array.length; + for (var i = 0; i < arrayLength; i++) { + if (!defined(array[i])) { + return i; + } + } + return arrayLength; +} \ No newline at end of file diff --git a/lib/removeDuplicatePrimitives.js b/lib/removeDuplicatePrimitives.js index 17b0ce8f..86ccd951 100644 --- a/lib/removeDuplicatePrimitives.js +++ b/lib/removeDuplicatePrimitives.js @@ -1,11 +1,10 @@ 'use strict'; var Cesium = require('cesium'); - -var defined = Cesium.defined; - +var addToArray = require('./addToArray'); var NodeHelpers = require('./NodeHelpers'); var PrimitiveHelpers = require('./PrimitiveHelpers'); -var getUniqueId = require('./getUniqueId'); + +var defined = Cesium.defined; module.exports = removeDuplicatePrimitives; @@ -22,30 +21,29 @@ function removeDuplicatePrimitives(gltf) { var primitivesCount = []; var primitivesToMeshes = []; var meshIndex; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - var index = findObject(seenPrimitives, primitive, PrimitiveHelpers.primitiveEquals); - if (index < 0) { + var meshesLength = meshes.length; + for (var meshId = 0; meshId < meshesLength; meshId++) { + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + var primitive = primitives[i]; + var index = findObject(seenPrimitives, primitive, PrimitiveHelpers.primitiveEquals); + if (index < 0) { + meshIndex = {}; + meshIndex[meshId] = {}; + meshIndex[meshId][i] = true; + primitivesToMeshes.push(meshIndex); + primitivesCount.push(1); + seenPrimitives.push(primitive); + } else { + meshIndex = primitivesToMeshes[index][meshId]; + if (!defined(meshIndex)) { meshIndex = {}; - meshIndex[meshId] = {}; - meshIndex[meshId][i] = true; - primitivesToMeshes.push(meshIndex); - primitivesCount.push(1); - seenPrimitives.push(primitive); - } else { - meshIndex = primitivesToMeshes[index][meshId]; - if (!defined(meshIndex)) { - meshIndex = {}; - primitivesToMeshes[index][meshId] = meshIndex; - } - meshIndex[i] = true; - primitivesCount[index]++; + primitivesToMeshes[index][meshId] = meshIndex; } + meshIndex[i] = true; + primitivesCount[index]++; } } } @@ -54,7 +52,6 @@ function removeDuplicatePrimitives(gltf) { return gltf; } -var splitMeshPrefix = 'mesh-split'; function removeDuplicatesFromTraversal(gltf, seenPrimitives, primitivesCount, primitivesToMeshes) { var meshes = gltf.meshes; var nodes = gltf.nodes; @@ -73,12 +70,12 @@ function removeDuplicatesFromTraversal(gltf, seenPrimitives, primitivesCount, pr indices = Object.keys(meshInstances[meshId]); removePrimitivesFromMesh(gltf, meshId, indices, 1); } else { - var splitMeshId = getUniqueId(gltf, splitMeshPrefix); - meshes[splitMeshId] = { + var splitMesh = { primitives : [ primitive ] }; + var splitMeshId = addToArray(meshes, splitMesh); for (var j = 0; j < meshIdsLength; j++) { meshId = meshIds[j]; indices = Object.keys(meshInstances[meshId]); @@ -110,7 +107,8 @@ function removePrimitivesFromMesh(gltf, meshId, indices, startIndex) { function finalizeRemoval(gltf) { var meshes = gltf.meshes; var removeMeshes = []; - for (var meshId in meshes) { + var meshesLength = meshes.length; + for (var meshId = 0; meshId < meshesLength; meshId++) { if (meshes.hasOwnProperty(meshId)) { var mesh = meshes[meshId]; var primitives = mesh.primitives; diff --git a/specs/data/ambientOcclusion/cube_over_ground.gltf b/specs/data/ambientOcclusion/cube_over_ground.gltf index a59f7742..7c277cf8 100644 --- a/specs/data/ambientOcclusion/cube_over_ground.gltf +++ b/specs/data/ambientOcclusion/cube_over_ground.gltf @@ -1,15 +1,15 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_56", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, "type": "SCALAR" }, - "accessor_23": { - "bufferView": "bufferView_57", + { + "bufferView": 1, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -26,8 +26,8 @@ ], "type": "VEC3" }, - "accessor_25": { - "bufferView": "bufferView_57", + { + "bufferView": 1, "byteOffset": 432, "byteStride": 12, "componentType": 5126, @@ -44,8 +44,8 @@ ], "type": "VEC3" }, - "accessor_27": { - "bufferView": "bufferView_57", + { + "bufferView": 1, "byteOffset": 864, "byteStride": 8, "componentType": 5126, @@ -60,16 +60,16 @@ ], "type": "VEC2" }, - "accessor_48": { - "bufferView": "bufferView_56", + { + "bufferView": 0, "byteOffset": 72, "byteStride": 0, "componentType": 5123, "count": 36, "type": "SCALAR" }, - "accessor_50": { - "bufferView": "bufferView_57", + { + "bufferView": 1, "byteOffset": 1152, "byteStride": 12, "componentType": 5126, @@ -86,8 +86,8 @@ ], "type": "VEC3" }, - "accessor_52": { - "bufferView": "bufferView_57", + { + "bufferView": 1, "byteOffset": 1584, "byteStride": 12, "componentType": 5126, @@ -104,8 +104,8 @@ ], "type": "VEC3" }, - "accessor_54": { - "bufferView": "bufferView_57", + { + "bufferView": 1, "byteOffset": 2016, "byteStride": 8, "componentType": 5126, @@ -120,55 +120,54 @@ ], "type": "VEC2" } - }, - "animations": {}, + ], + "animations": [], "asset": { - "generator": "collada2gltf@", "premultipliedAlpha": true, "profile": { "api": "WebGL", - "version": "1.0.2" + "version": "1.0" }, - "version": "1.0" + "version": "2.0" }, - "bufferViews": { - "bufferView_56": { - "buffer": "cube_over_ground", + "bufferViews": [ + { + "buffer": 0, "byteLength": 144, "byteOffset": 0, "target": 34963 }, - "bufferView_57": { - "buffer": "cube_over_ground", + { + "buffer": 0, "byteLength": 2304, "byteOffset": 144, "target": 34962 } - }, - "buffers": { - "cube_over_ground": { + ], + "buffers": [ + { "byteLength": 2448, "type": "arraybuffer", "uri": "data:application/octet-stream;base64,AAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAAACAPwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/7/9/PwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/7/9/PwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAPwAAgD8AAIC/AACAvwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/7/9/PwAAgL8AAIA/AACAPwAAgD8AAIA/7/9/PwAAgL8AAIA/AACAPwAAgL8AAIC/7/9/PwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAPAIC0AACAPwAAAAAPAIC0AACAPwAAAAAPAIC0AAAAAAAAgL/6//+0AAAAAAAAgL/6//+0AAAAAAAAgL/6//+0AACAvw8AgDQbACC0AACAvw8AgDQbACC0AACAvw8AgDQbACC0AwCQNAAAgD8PAIA0AwCQNAAAgD8PAIA0AwCQNAAAgD8PAIA0AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAP/j/H7Xt/680AACAP/j/H7Xt/680AACAP/j/H7Xt/680+v//tAAAgL8AAAAA+v//tAAAgL8AAAAA+v//tAAAgL8AAAAAAACAvw8AgDTX//+zAACAvw8AgDTX//+zAACAvw8AgDTX//+z7v9fNAAAgD8AAAAA7v9fNAAAgD8AAAAA7v9fNAAAgD8AAAAAAAAAAKCqqj6fqqo+AAAAAAAAAAAAAAAAn6qqPqCqqj4AAAAAoKoqP5+qqj6wqio/n6qqPrCqKj+wqio/AACAP7CqKj+wqio/AAAAAP7/fz+fqqo+sKoqPwAAAACwqio/AACAP7CqKj+wqio/AACAPwAAgD8AAIA/sKoqP7CqKj+fqqo+oKqqPp+qqj6wqio/AAAAAKCqqj6fqqo+oKqqPp+qqj4AAAAAn6qqPqCqqj4AAAAAoKqqPgAAAACgqio/n6qqPrCqKj+fqqo+AACAP7CqKj8AAIA/AAAAAP7/fz+fqqo+AACAP5+qqj6wqio/AACAP7CqKj+wqio/sKoqP7CqKj8AAIA/sKoqP7CqKj+wqio/oKqqPp+qqj6gqqo+AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAvwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIC/AACAPwAAgD8AAIA/AACAvwAAgL8AAIA/AACAPwAAgL8AAIC/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAPwAAgD8AAIA/AACAvwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/n6qqPgAAgD+wqio/sKoqP5+qqj6wqio/AAAAALCqKj+fqqo+oKqqPgAAAACgqqo+AAAAAAAAgD+fqqo+sKoqP4+qCjSwqio/sKoqP7CqKj+fqqo+oKqqPp+qqj6wqio/AACAP7CqKj+wqio/AACAPwAAgD8AAIA/n6qqPqCqqj4AAAAAAAAAAAAAAACgqqo+n6qqPgAAgD+wqio/AACAP7CqKj+wqio/AAAAALCqKj+fqqo+sKoqP5+qqj6gqqo+AAAAAAAAgD+fqqo+AACAP5+qqj6wqio/sKoqP7CqKj+wqio/oKqqPp+qqj6gqqo+AACAP7CqKj+wqio/sKoqP7CqKj8AAIA/n6qqPqCqqj6fqqo+AAAAAAAAAAAAAAAA" } - }, - "images": { - "Untitled": { + ], + "images": [ + { "name": "Untitled", "uri": "data:image/png;base64,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" }, - "Untitled_001": { + { "name": "Untitled_001", "uri": "data:image/png;base64,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" } - }, - "materials": { - "Material-effect": { + ], + "materials": [ + { "name": "Material-effect", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Untitled", - "shininess": 256, + "diffuse": [0], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -177,12 +176,12 @@ ] } }, - "Material_001-effect": { + { "name": "Material_001", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Untitled_001", - "shininess": 256, + "diffuse": [1], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -191,12 +190,12 @@ ] } }, - "useless-material": { + { "name": "useless", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Untitled_001", - "shininess": 256, + "diffuse": [1], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -205,86 +204,86 @@ ] } } - }, - "meshes": { - "Cube_mesh": { + ], + "meshes": [ + { "name": "Cube", "primitives": [ { "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" + "NORMAL": 2, + "POSITION": 1, + "TEXCOORD_0": 3 }, - "indices": "accessor_21", - "material": "Material-effect", + "indices": 0, + "material": 0, "mode": 4 } ] }, - "Cube_001_mesh": { + { "name": "Cube.001", "primitives": [ { "attributes": { - "NORMAL": "accessor_52", - "POSITION": "accessor_50", - "TEXCOORD_0": "accessor_54" + "NORMAL": 6, + "POSITION": 5, + "TEXCOORD_0": 7 }, - "indices": "accessor_48", - "material": "Material_001-effect", + "indices": 4, + "material": 1, "mode": 4 } ] }, - "useless_mesh": { + { "name": "Cube.001", "primitives": [ { "attributes": { - "NORMAL": "accessor_52", - "POSITION": "accessor_50", - "TEXCOORD_0": "accessor_54" + "NORMAL": 6, + "POSITION": 5, + "TEXCOORD_0": 7 }, - "indices": "accessor_48", - "material": "Material_001-effect", + "indices": 4, + "material": 1, "mode": 4 }, { "attributes": { - "NORMAL": "accessor_52", - "POSITION": "accessor_50", - "TEXCOORD_0": "accessor_54" + "NORMAL": 6, + "POSITION": 5, + "TEXCOORD_0": 7 }, - "indices": "accessor_48", - "material": "Material_001-effect", + "indices": 4, + "material": 1, "mode": 4 }, { "attributes": { - "NORMAL": "accessor_52", - "POSITION": "accessor_50", - "TEXCOORD_0": "accessor_54" + "NORMAL": 6, + "POSITION": 5, + "TEXCOORD_0": 7 }, - "indices": "accessor_48", - "material": "useless-material", + "indices": 4, + "material": 2, "mode": 4 }, { "attributes": { - "NORMAL": "accessor_52", - "POSITION": "accessor_50", - "TEXCOORD_0": "accessor_54" + "NORMAL": 6, + "POSITION": 5, + "TEXCOORD_0": 7 }, - "indices": "accessor_48", - "material": "useless-material", + "indices": 4, + "material": 2, "mode": 4 } ] } - }, - "nodes": { - "Cube": { + ], + "nodes": [ + { "children": [], "matrix": [ 1, @@ -304,12 +303,10 @@ 0, 1 ], - "meshes": [ - "Cube_mesh" - ], + "mesh": 0, "name": "Cube" }, - "Cube_001": { + { "children": [], "matrix": [ 2, @@ -329,15 +326,13 @@ -1.3000000715255737, 1 ], - "meshes": [ - "Cube_001_mesh" - ], + "mesh": 1, "name": "Cube_001" }, - "node_2": { + { "children": [ - "Cube", - "Cube_001" + 0, + 1 ], "matrix": [ 1, @@ -359,7 +354,7 @@ ], "name": "Y_UP_Transform" }, - "useless_node": { + { "children": [], "matrix": [ 1, @@ -379,59 +374,57 @@ 0, 1 ], - "meshes": [ - "useless_mesh" - ], + "mesh": 2, "name": "useless Cube" } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position", "a_texcoord0" ], - "fragmentShader": "cube_over_ground0FS", - "vertexShader": "cube_over_ground0VS" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "samplers": { - "sampler_0": { + ], + "samplers": [ + { "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497 } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_2" + 2 ], "node": [] }, - "uselessScene": { + { "nodes": [ - "useless_node" + 3 ], "node": [] } - }, - "shaders": { - "cube_over_ground0FS": { + ], + "shaders": [ + { "type": 35632, "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0KdW5pZm9ybSBzYW1wbGVyMkQgdV9kaWZmdXNlOw0KdW5pZm9ybSB2ZWM0IHVfc3BlY3VsYXI7DQp1bmlmb3JtIGZsb2F0IHVfc2hpbmluZXNzOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzMgbm9ybWFsID0gbm9ybWFsaXplKHZfbm9ybWFsKTsNCnZlYzQgY29sb3IgPSB2ZWM0KDAuLCAwLiwgMC4sIDAuKTsNCnZlYzQgZGlmZnVzZSA9IHZlYzQoMC4sIDAuLCAwLiwgMS4pOw0KdmVjNCBzcGVjdWxhcjsNCmRpZmZ1c2UgPSB0ZXh0dXJlMkQodV9kaWZmdXNlLCB2X3RleGNvb3JkMCk7DQpzcGVjdWxhciA9IHVfc3BlY3VsYXI7DQpkaWZmdXNlLnh5eiAqPSBtYXgoZG90KG5vcm1hbCx2ZWMzKDAuLDAuLDEuKSksIDAuKTsNCmNvbG9yLnh5eiArPSBkaWZmdXNlLnh5ejsNCmNvbG9yID0gdmVjNChjb2xvci5yZ2IgKiBkaWZmdXNlLmEsIGRpZmZ1c2UuYSk7DQpnbF9GcmFnQ29sb3IgPSBjb2xvcjsNCn0NCg==" }, - "cube_over_ground0VS": { + { "type": 35633, "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsNCmF0dHJpYnV0ZSB2ZWMzIGFfbm9ybWFsOw0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdW5pZm9ybSBtYXQzIHVfbm9ybWFsTWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMyIGFfdGV4Y29vcmQwOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzQgcG9zID0gdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCnZfbm9ybWFsID0gdV9ub3JtYWxNYXRyaXggKiBhX25vcm1hbDsNCnZfdGV4Y29vcmQwID0gYV90ZXhjb29yZDA7DQpnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHBvczsNCn0NCg==" } - }, - "skins": {}, - "techniques": { - "technique0": { + ], + "skins": [], + "techniques": [ + { "attributes": { "a_normal": "normal", "a_position": "position", @@ -472,7 +465,7 @@ "type": 35664 } }, - "program": "program_0", + "program": 0, "states": { "enable": [ 2929, @@ -489,27 +482,27 @@ "u_specular": "specular" } } - }, - "textures": { - "texture_Untitled": { + ], + "textures": [ + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Untitled", + "sampler": 0, + "source": 0, "target": 3553, "type": 5121 }, - "texture_Untitled_001": { + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Untitled_001", + "sampler": 0, + "source": 1, "target": 3553, "type": 5121 } - }, + ], "extensionsUsed": [], - "cameras": {}, + "cameras": [], "extensions": { "KHR_materials_common": { "lights": {} diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf index 9073acdf..60f6005f 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf @@ -1,15 +1,15 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, "type": "SCALAR" }, - "accessor_23": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -26,8 +26,8 @@ ], "type": "VEC3" }, - "accessor_25": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 288, "byteStride": 12, "componentType": 5126, @@ -44,8 +44,8 @@ ], "type": "VEC3" }, - "accessor_27": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 576, "byteStride": 8, "componentType": 5126, @@ -60,51 +60,50 @@ ], "type": "VEC2" } - }, - "animations": {}, + ], + "animations": [], "asset": { - "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", "premultipliedAlpha": true, "profile": { "api": "WebGL", - "version": "1.0.2" + "version": "1.0" }, - "version": 1 + "version": "2.0" }, - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", + "bufferViews": [ + { + "buffer": 0, "byteLength": 72, "byteOffset": 0, "target": 34963 }, - "bufferView_30": { - "buffer": "CesiumTexturedBoxTest", + { + "buffer": 0, "byteLength": 768, "byteOffset": 72, "target": 34962 } - }, - "buffers": { - "CesiumTexturedBoxTest": { + ], + "buffers": [ + { "byteLength": 840, "type": "arraybuffer", "uri": "CesiumTexturedBoxTest.bin" } - }, - "images": { - "Image0001": { + ], + "images": [ + { "name": "Image0001", "uri": "Cesium_Logo_Flat.png" } - }, - "materials": { - "Effect-Texture": { + ], + "materials": [ + { "name": "Texture", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Image0001", - "shininess": 256, + "diffuse": [0], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -113,26 +112,26 @@ ] } } - }, - "meshes": { - "Geometry-mesh002": { + ], + "meshes": [ + { "name": "Mesh", "primitives": [ { "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" + "NORMAL": 2, + "POSITION": 1, + "TEXCOORD_0": 3 }, - "indices": "accessor_21", - "material": "Effect-Texture", + "indices": 0, + "material": 0, "mode": 4 } ] } - }, - "nodes": { - "Geometry-mesh002Node": { + ], + "nodes": [ + { "children": [], "matrix": [ 1, @@ -152,12 +151,10 @@ 0, 1 ], - "meshes": [ - "Geometry-mesh002" - ], + "mesh": 0, "name": "Mesh" }, - "groupLocator030Node": { + { "children": [ "txtrLocator026Node" ], @@ -181,7 +178,7 @@ ], "name": "Texture_Group" }, - "node_3": { + { "children": [ "Geometry-mesh002Node", "groupLocator030Node" @@ -206,7 +203,7 @@ ], "name": "Y_UP_Transform" }, - "txtrLocator026Node": { + { "children": [], "matrix": [ 1, @@ -228,47 +225,47 @@ ], "name": "Cesium_Logo_Flat__Image___Texture_" } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position", "a_texcoord0" ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "samplers": { - "sampler_0": { + ], + "samplers": [ + { "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497 } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_3" + 2 ] } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { + ], + "shaders": [ + { "type": 35632, "uri": "CesiumTexturedBoxTest0FS.glsl" }, - "CesiumTexturedBoxTest0VS": { + { "type": 35633, "uri": "CesiumTexturedBoxTest0VS.glsl" } - }, - "skins": {}, - "techniques": { - "technique0": { + ], + "skins": [], + "techniques": [ + { "attributes": { "a_normal": "normal", "a_position": "position", @@ -325,15 +322,15 @@ "u_specular": "specular" } } - }, - "textures": { - "texture_Image0001": { + ], + "textures": [ + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", + "sampler": 0, + "source": 0, "target": 3553, "type": 5121 } - } + ] } \ No newline at end of file diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestAddExtras.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestAddExtras.gltf index 113d39d9..67df8fcf 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestAddExtras.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestAddExtras.gltf @@ -1,59 +1,58 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "componentType": 5123, "count": 36, "type": "SCALAR" } - }, - "animations": { - "animation_0": { + ], + "animations": [ + { "channels": [ { - "sampler": "animation_0_scale_sampler", + "sampler": 0, "target": { - "id": "Bone", + "id": 0, "path": "scale" } } ], - "samplers": { - "sampler": { + "samplers": [ + { "input": "TIME", "interpolation": "LINEAR", "output": "rotation" } - } + ] } - }, + ], "asset": { - "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", "premultipliedAlpha": true, "profile": { "api": "WebGL", - "version": "1.0.2" + "version": "1.0" }, - "version": 1 + "version": "2.0" }, - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", + "bufferViews": [ + { + "buffer": 0, "byteLength": 72, "byteOffset": 0, "target": 34963 } - }, - "buffers": { - "CesiumTexturedBoxTest": { + ], + "buffers": [ + { "byteLength": 840, "type": "arraybuffer", "uri": "CesiumTexturedBoxTest.bin" } - }, - "cameras": { - "camera_0": { + ], + "cameras": [ + { "orthographic": { "xmag": 1.0, "ymag": 1.0, @@ -68,35 +67,35 @@ }, "type": "perspective" } - }, - "images": { - "Image0001": { + ], + "images": [ + { "uri": "Cesium_Logo_Flat.png" } - }, - "materials": { - "EffectTexture": { + ], + "materials": [ + { "name": "Texture", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Image0001", - "shininess": 256 + "diffuse": [0], + "shininess": [256] }, "extras": {} } - }, - "meshes": { - "mesh002": { + ], + "meshes": [ + { "name": "Mesh", "primitives": [ { "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" + "NORMAL": 2, + "POSITION": 1, + "TEXCOORD_0": 3 }, - "indices": "accessor_21", - "material": "Effect-Texture", + "indices": 0, + "material": 0, "mode": 4, "extras": {} } @@ -105,59 +104,59 @@ "_pipeline": {} } } - }, - "nodes": { - "mesh002Node": { + ], + "nodes": [ + { "children": [], "meshes": [ - "Geometry-mesh002" + 0 ], "name": "Mesh", "extras": {} } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position", "a_texcoord0" ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS", + "fragmentShader": 0, + "vertexShader": 1, "extras": {} } - }, - "samplers": { - "sampler_0": { + ], + "samplers": [ + { "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497, "extras": {} } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_3" + 0 ], "extras": {} } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { + ], + "shaders": [ + { "type": 35632, "uri": "CesiumTexturedBoxTest0FS.glsl", "extras": { "misc": {} } } - }, - "skins": { - "Armature_Cylinder_skin": { - "inverseBindMatrices": "IBM_Armature_Cylinder-skin", + ], + "skins": [ + { + "inverseBindMatrices": 0, "jointNames": [ "Bone", "Bone_001" @@ -167,9 +166,9 @@ "misc": {} } } - }, - "techniques": { - "technique0": { + ], + "techniques": [ + { "parameters": { "diffuse": { "type": 35678, @@ -198,18 +197,18 @@ "misc": {} } } - }, - "textures": { - "texture_Image0001": { + ], + "textures": [ + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", + "sampler": 0, + "source": 1, "target": 3553, "type": 5121, "extras": { "misc": {} } } - } + ] } \ No newline at end of file diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestTransparent.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestTransparent.gltf index 9efe2718..a819dae0 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestTransparent.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestTransparent.gltf @@ -1,15 +1,15 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, "type": "SCALAR" }, - "accessor_23": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -26,8 +26,8 @@ ], "type": "VEC3" }, - "accessor_25": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 288, "byteStride": 12, "componentType": 5126, @@ -44,8 +44,8 @@ ], "type": "VEC3" }, - "accessor_27": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 576, "byteStride": 8, "componentType": 5126, @@ -60,51 +60,50 @@ ], "type": "VEC2" } - }, - "animations": {}, + ], + "animations": [], "asset": { - "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", "premultipliedAlpha": true, "profile": { "api": "WebGL", - "version": "1.0.2" + "version": "1.0" }, - "version": 1 + "version": "2.0" }, - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", + "bufferViews": [ + { + "buffer": 0, "byteLength": 72, "byteOffset": 0, "target": 34963 }, - "bufferView_30": { - "buffer": "CesiumTexturedBoxTest", + { + "buffer": 0, "byteLength": 768, "byteOffset": 72, "target": 34962 } - }, - "buffers": { - "CesiumTexturedBoxTest": { + ], + "buffers": [ + { "byteLength": 840, "type": "arraybuffer", "uri": "CesiumTexturedBoxTest.bin" } - }, - "images": { - "Image0001": { + ], + "images": [ + { "name": "Image0001", "uri": "Cesium_Logo_Flat_Transparent.png" } - }, - "materials": { - "Effect-Texture": { + ], + "materials": [ + { "name": "Texture", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Image0001", - "shininess": 256, + "diffuse": [0], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -113,26 +112,26 @@ ] } } - }, - "meshes": { - "Geometry-mesh002": { + ], + "meshes": [ + { "name": "Mesh", "primitives": [ { "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" + "NORMAL": 2, + "POSITION": 1, + "TEXCOORD_0": 3 }, - "indices": "accessor_21", - "material": "Effect-Texture", + "indices": 0, + "material": 0, "mode": 4 } ] } - }, - "nodes": { - "Geometry-mesh002Node": { + ], + "nodes": [ + { "children": [], "matrix": [ 1, @@ -152,12 +151,10 @@ 0, 1 ], - "meshes": [ - "Geometry-mesh002" - ], + "mesh": 0, "name": "Mesh" }, - "groupLocator030Node": { + { "children": [ "txtrLocator026Node" ], @@ -181,7 +178,7 @@ ], "name": "Texture_Group" }, - "node_3": { + { "children": [ "Geometry-mesh002Node", "groupLocator030Node" @@ -206,7 +203,7 @@ ], "name": "Y_UP_Transform" }, - "txtrLocator026Node": { + { "children": [], "matrix": [ 1, @@ -228,47 +225,47 @@ ], "name": "Cesium_Logo_Flat__Image___Texture_" } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position", "a_texcoord0" ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "samplers": { - "sampler_0": { + ], + "samplers": [ + { "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497 } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_3" + 2 ] } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { + ], + "shaders": [ + { "type": 35632, "uri": "CesiumTexturedBoxTest0FS.glsl" }, - "CesiumTexturedBoxTest0VS": { + { "type": 35633, "uri": "CesiumTexturedBoxTest0VS.glsl" } - }, - "skins": {}, - "techniques": { - "technique0": { + ], + "skins": [], + "techniques": [ + { "attributes": { "a_normal": "normal", "a_position": "position", @@ -325,15 +322,15 @@ "u_specular": "specular" } } - }, - "textures": { - "texture_Image0001": { + ], + "textures": [ + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", + "sampler": 0, + "source": 0, "target": 3553, "type": 5121 } - } + ] } \ No newline at end of file diff --git a/specs/lib/NodeHelpersSpec.js b/specs/lib/NodeHelpersSpec.js index 8bde160e..a680c45e 100644 --- a/specs/lib/NodeHelpersSpec.js +++ b/specs/lib/NodeHelpersSpec.js @@ -15,14 +15,14 @@ var fiveBoxPath = './specs/data/combineObjects/fiveBox.gltf'; describe('NodeHelpers', function() { var testScene = { "nodes": [ - "leftElbow", - "rightWrist" + 1, + 5 ] }; - var testNodes = { - "leftShoulder": { + var testNodes = [ + { "children": [ - "leftElbow" + 1 ], "translation": [ 1, 0, 0 @@ -31,9 +31,9 @@ describe('NodeHelpers', function() { "_pipeline": {} } }, - "leftElbow": { + { "children": [ - "leftWrist" + 2 ], "translation": [ 1, 0, 0 @@ -42,10 +42,10 @@ describe('NodeHelpers', function() { "_pipeline": {} } }, - "leftWrist": { + { "children": [ - "leftPinkie", - "leftThumb" + 3, + 4 ], "translation": [ 1, 0, 0 @@ -54,7 +54,7 @@ describe('NodeHelpers', function() { "_pipeline": {} } }, - "leftPinkie": { + { "children": [ ], "translation": [ @@ -64,7 +64,7 @@ describe('NodeHelpers', function() { "_pipeline": {} } }, - "leftThumb": { + { "children": [ ], "translation": [ @@ -74,10 +74,10 @@ describe('NodeHelpers', function() { "_pipeline": {} } }, - "rightWrist": { + { "children": [ - "rightPinkie", - "rightThumb" + 6, + 7 ], "translation": [ -1, 0, 0 @@ -86,7 +86,7 @@ describe('NodeHelpers', function() { "_pipeline": {} } }, - "rightPinkie": { + { "children": [ ], "translation": [ @@ -96,7 +96,7 @@ describe('NodeHelpers', function() { "_pipeline": {} } }, - "rightThumb": { + { "children": [ ], "translation": [ @@ -106,7 +106,7 @@ describe('NodeHelpers', function() { "_pipeline": {} } } - }; + ]; it('correctly gets the local matrix of a node that has a local matrix', function() { var testNode = { @@ -170,8 +170,8 @@ describe('NodeHelpers', function() { 0, 0, 1, 0, -1, 0, 0, 1 ]); - var actualLeftPinkie = testNodesClone.leftPinkie.extras._pipeline.flatTransform; - var actualRightWrist = testNodesClone.rightWrist.extras._pipeline.flatTransform; + var actualLeftPinkie = testNodesClone[3].extras._pipeline.flatTransform; + var actualRightWrist = testNodesClone[5].extras._pipeline.flatTransform; expect(Matrix4.equalsEpsilon(actualLeftPinkie, expectLeftPinkie, CesiumMath.EPSILON7)).toEqual(true); expect(Matrix4.equalsEpsilon(actualRightWrist, expectRightWrist, CesiumMath.EPSILON7)).toEqual(true); }); @@ -211,19 +211,19 @@ describe('NodeHelpers', function() { it('maps meshes to nodes', function() { var gltf = { - meshes : { - mesh : {} - }, - nodes : { - nodeA : { - meshes : ['mesh'] + meshes : [ + {} + ], + nodes : [ + { + mesh : 0 }, - nodeB : { - meshes : ['mesh'] + { + mesh : 0 } - } + ] }; var meshesToNodes = NodeHelpers.mapMeshesToNodes(gltf); - expect(meshesToNodes.mesh).toEqual(['nodeA', 'nodeB']); + expect(meshesToNodes[0]).toEqual([0, 1]); }); }); diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index 584194d9..b57e350e 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -20,64 +20,53 @@ var gltfTransparentPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBox describe('addDefaults', function() { it('Adds accessor properties', function() { var gltf = { - "accessors": { - "accessorId": { - "bufferView": "bufferViewId", - "byteOffset": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR" - } - } + "accessors": [{ + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "type": "SCALAR" + }] }; addDefaults(gltf); - var accessor = gltf.accessors.accessorId; + var accessor = gltf.accessors[0]; expect(accessor.byteStride).toEqual(0); }); it('Adds animation properties', function() { var gltf = { - "animations": { - "animationId": { - "channels": [ - { - "sampler": "samplerId", - "target": { - "id": "jointId", - "path": "rotation" - } - } - ], - "parameters": { - "TIME": "timeAccessorId", - "rotation": "rotationAccessorId" - }, - "samplers": { - "samplerId": { - "input": "TIME", - "output": "rotation" + "animations": [{ + "channels": [ + { + "sampler": 0, + "target": { + "id": 0, + "path": "rotation" } } - } - } + ], + "samplers": [{ + "input": 0, + "output": 1 + }] + }] }; addDefaults(gltf); - expect(gltf.animations.animationId.samplers.samplerId.interpolation).toEqual('LINEAR'); + expect(gltf.animations[0].samplers[0].interpolation).toEqual('LINEAR'); }); it('Adds animation empty properties', function() { var gltf = { - "animations": { - "animationId" : { - } - } + "animations": [ + {} + ] }; addDefaults(gltf); - expect(gltf.animations.animationId.channels).toEqual([]); - expect(gltf.animations.animationId.samplers).toEqual({}); + expect(gltf.animations[0].channels).toEqual([]); + expect(gltf.animations[0].samplers).toEqual([]); }); it('Adds asset properties', function() { @@ -93,43 +82,37 @@ describe('addDefaults', function() { it('Adds buffer properties', function() { var gltf = { - "buffers": { - "bufferId": { - "byteLength": 840, - "uri": "buffer.bin" - } - } + "buffers": [{ + "byteLength": 840, + "uri": "buffer.bin" + }] }; addDefaults(gltf); - expect(gltf.buffers.bufferId.type).toEqual('arraybuffer'); + expect(gltf.buffers[0].type).toEqual('arraybuffer'); }); it('does not change the material if the material has a technique', function() { var gltf = { - "techniques": { - "technique1": { - "states": { - "enable": [ - 2929, - 2884 - ] - } - } - }, - "materials": { - "blinn-1": { - "technique": "technique1", - "values": { - "ambient": [0, 0, 0, 1], - "diffuse": [1, 0, 0, 1], - "emission": "texture_file2", - "shininess": 38.4, - "specular": [0, 0, 0, 1] - }, - "name": "blinn1" + "techniques": [{ + "states": { + "enable": [ + 2929, + 2884 + ] } - } + }], + "materials": [{ + "technique": 0, + "values": { + "ambient": [0, 0, 0, 1], + "diffuse": [1, 0, 0, 1], + "emission": [0], + "shininess": [38.4], + "specular": [0, 0, 0, 1] + }, + "name": "blinn1" + }] }; var materialsCopy = clone(gltf.materials); addDefaults(gltf); @@ -158,57 +141,51 @@ describe('addDefaults', function() { it('generates a material with alpha blending if the diffuse texture is transparent and no technique or extension values are given', function(done) { var gltf = { - "textures": { - "texture0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 - } - }, - "images": { - "Image0001": { - "name": "Image0001", - "uri": transparentImageUri + "textures": [{ + "format": 6408, + "internalFormat": 6408, + "sampler": 0, + "source": 0, + "target": 3553, + "type": 5121 + }], + "images": [{ + "name": "Image0001", + "uri": transparentImageUri + }], + "materials": [{ + "values": { + "ambient": [0, 0, 0, 1], + "diffuse": [0], + "emission": [1, 0, 0, 1] } - }, - "materials": { - "material1": { - "values": { - "ambient": [0, 0, 0, 1], - "diffuse": "texture0001", - "emission": [1, 0, 0, 1] - } - } - } + }] }; addPipelineExtras(gltf); expect(loadGltfUris(gltf) .then(function() { addDefaults(gltf); - var technique = gltf.techniques[Object.keys(gltf.techniques)[0]]; + var technique = gltf.techniques[0]; expect(technique.states).toEqual(alphaBlendState); }), done).toResolve(); }); it('generates a material with alpha blending if the diffuse color is transparent and no technique or extension values are given', function() { var gltf = { - "materials": { - "material1": { + "materials": [ + { "values": { "ambient": [0, 0, 0, 1], "diffuse": [1, 0, 0, 0.5], "emission": [1, 0, 0, 1] } } - } + ] }; addDefaults(gltf); - var technique = gltf.techniques[Object.keys(gltf.techniques)[0]]; + var technique = gltf.techniques[0]; expect(technique.states).toEqual(alphaBlendState); }); @@ -216,13 +193,13 @@ describe('addDefaults', function() { expect(fsReadFile(gltfTransparentPath) .then(function(data) { var gltf = JSON.parse(data); - var originalState = gltf.techniques[Object.keys(gltf.techniques)[0]].states; + var originalState = gltf.techniques[0].states; expect(originalState).not.toEqual(alphaBlendState); return readGltf(gltfTransparentPath); }) .then(function (gltf) { addDefaults(gltf); - var technique = gltf.techniques[Object.keys(gltf.techniques)[0]]; + var technique = gltf.techniques[0]; expect(technique.states).toEqual(alphaBlendState); }), done).toResolve(); }); @@ -231,15 +208,15 @@ describe('addDefaults', function() { expect(fsReadFile(gltfTransparentPath) .then(function(data) { var gltf = JSON.parse(data); - var originalState = gltf.techniques[Object.keys(gltf.techniques)[0]].states; + var originalState = gltf.techniques[0].states; expect(originalState).not.toEqual(alphaBlendState); return readGltf(gltfTransparentPath); }) .then(function (gltf) { - var material = gltf.materials[Object.keys(gltf.materials)[0]]; + var material = gltf.materials[0]; material.values.diffuse = [1, 0, 0, 0.5]; addDefaults(gltf); - var technique = gltf.techniques[Object.keys(gltf.techniques)[0]]; + var technique = gltf.techniques[0]; expect(technique.states).toEqual(alphaBlendState); }), done).toResolve(); }); @@ -250,25 +227,24 @@ describe('addDefaults', function() { addDefaults(gltf, { optimizeForCesium : true }); - var technique = gltf.techniques[Object.keys(gltf.techniques)[0]]; + var technique = gltf.techniques[0]; expect(technique.parameters.diffuse.semantic).toEqual('_3DTILESDIFFUSE'); }), done).toResolve(); }); it('Adds mesh properties', function() { var gltf = { - "meshes": { - "meshId": { - } - } + "meshes": [ + {} + ] }; addDefaults(gltf); - expect(gltf.meshes.meshId.primitives).toEqual([]); + expect(gltf.meshes[0].primitives).toEqual([]); gltf = { - "meshes": { - "meshId": { + "meshes": [ + { "primitives": [ { "indices": "accessorId", @@ -276,24 +252,23 @@ describe('addDefaults', function() { } ] } - } + ] }; addDefaults(gltf); - expect(gltf.meshes.meshId.primitives[0].attributes).toBeDefined(); - expect(gltf.meshes.meshId.primitives[0].mode).toEqual(WebGLConstants.TRIANGLES); + expect(gltf.meshes[0].primitives[0].attributes).toBeDefined(); + expect(gltf.meshes[0].primitives[0].mode).toEqual(WebGLConstants.TRIANGLES); }); it('Adds node properties', function() { var gltf = { - "nodes": { - "nodeId": { - } - } + "nodes": [ + {} + ] }; addDefaults(gltf); - var node = gltf.nodes.nodeId; + var node = gltf.nodes[0]; expect(node.children).toEqual([]); expect(node.matrix).toEqual([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); expect(node.translation).not.toBeDefined(); @@ -301,108 +276,106 @@ describe('addDefaults', function() { expect(node.scale).not.toBeDefined(); gltf = { - "nodes": { - "nodeId": { + "nodes": [ + { "translation": [0.0, 0.0, 0.0] } - } + ] }; addDefaults(gltf); - expect(gltf.nodes.nodeId.translation).toEqual([0.0, 0.0, 0.0]); - expect(gltf.nodes.nodeId.rotation).toEqual([0.0, 0.0, 0.0, 1.0]); - expect(gltf.nodes.nodeId.scale).toEqual([1.0, 1.0, 1.0]); - expect(gltf.nodes.nodeId.matrix).not.toBeDefined(); + expect(gltf.nodes[0].translation).toEqual([0.0, 0.0, 0.0]); + expect(gltf.nodes[0].rotation).toEqual([0.0, 0.0, 0.0, 1.0]); + expect(gltf.nodes[0].scale).toEqual([1.0, 1.0, 1.0]); + expect(gltf.nodes[0].matrix).not.toBeDefined(); gltf = { - "nodes": { - "nodeId": { + "nodes": [ + { "scale": [1.0, 1.0, 1.0] } - } + ] }; addDefaults(gltf); - expect(gltf.nodes.nodeId.translation).toEqual([0.0, 0.0, 0.0]); - expect(gltf.nodes.nodeId.rotation).toEqual([0.0, 0.0, 0.0, 1.0]); - expect(gltf.nodes.nodeId.scale).toEqual([1.0, 1.0, 1.0]); - expect(gltf.nodes.nodeId.matrix).not.toBeDefined(); + expect(gltf.nodes[0].translation).toEqual([0.0, 0.0, 0.0]); + expect(gltf.nodes[0].rotation).toEqual([0.0, 0.0, 0.0, 1.0]); + expect(gltf.nodes[0].scale).toEqual([1.0, 1.0, 1.0]); + expect(gltf.nodes[0].matrix).not.toBeDefined(); }); it('Adds program properties', function() { var gltf = { - "programs": { - "programId": { - "fragmentShader": "bufferId0FS", - "vertexShader": "bufferId0VS" + "programs": [ + { + "fragmentShader": 0, + "vertexShader": 1 } - } + ] }; addDefaults(gltf); - expect(gltf.programs.programId.attributes).toEqual([]); + expect(gltf.programs[0].attributes).toEqual([]); }); it('Adds sampler properties', function() { var gltf = { - "samplers": { - "samplerId": { - } - } + "samplers": [ + {} + ] }; addDefaults(gltf); - expect(gltf.samplers.samplerId.magFilter).toEqual(WebGLConstants.LINEAR); - expect(gltf.samplers.samplerId.minFilter).toEqual(WebGLConstants.NEAREST_MIPMAP_LINEAR); - expect(gltf.samplers.samplerId.wrapS).toEqual(WebGLConstants.REPEAT); - expect(gltf.samplers.samplerId.wrapT).toEqual(WebGLConstants.REPEAT); + expect(gltf.samplers[0].magFilter).toEqual(WebGLConstants.LINEAR); + expect(gltf.samplers[0].minFilter).toEqual(WebGLConstants.NEAREST_MIPMAP_LINEAR); + expect(gltf.samplers[0].wrapS).toEqual(WebGLConstants.REPEAT); + expect(gltf.samplers[0].wrapT).toEqual(WebGLConstants.REPEAT); }); it('Adds scene properties', function() { var gltf = { - "scenes": { - "defaultScene": { - } - } + "scenes": [ + {} + ] }; addDefaults(gltf); - expect(gltf.scenes.defaultScene.nodes).toEqual([]); + expect(gltf.scenes[0].nodes).toEqual([]); }); it('Adds skin properties', function() { var gltf = { - "skins": { - "skinId": { - "inverseBindMatrices": "accessorId", + "skins": [ + { + "inverseBindMatrices": 0, "jointNames": [ "jointId" ], "name": "Armature" } - } + ] }; addDefaults(gltf); - expect(gltf.skins.skinId.bindShapeMatrix).toEqual([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + expect(gltf.skins[0].bindShapeMatrix).toEqual([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); }); it('Adds texture properties', function() { var gltf = { - "textures": { - "textureId": { + "textures": [ + { "format": 6408, - "sampler": "samplerId", - "source": "Image0001" + "sampler": 0, + "source": 0 } - } + ] }; addDefaults(gltf); - expect(gltf.textures.textureId.format).toEqual(WebGLConstants.RGBA); - expect(gltf.textures.textureId.internalFormat).toEqual(6408); - expect(gltf.textures.textureId.target).toEqual(WebGLConstants.TEXTURE_2D); - expect(gltf.textures.textureId.type).toEqual(WebGLConstants.UNSIGNED_BYTE); + expect(gltf.textures[0].format).toEqual(WebGLConstants.RGBA); + expect(gltf.textures[0].internalFormat).toEqual(6408); + expect(gltf.textures[0].target).toEqual(WebGLConstants.TEXTURE_2D); + expect(gltf.textures[0].type).toEqual(WebGLConstants.UNSIGNED_BYTE); }); it('Adds empty top-level properties', function() { @@ -431,18 +404,18 @@ describe('addDefaults', function() { it('Adds the default material if a mesh has an undefined material', function() { var gltf = { - meshes: { - mesh: { + meshes: [ + { primitives: [ {}, {} ] } - } + ] }; addDefaults(gltf); - var mesh = gltf.meshes.mesh; + var mesh = gltf.meshes[0]; var meshMaterial = mesh.primitives[0].material; expect(meshMaterial).toBeDefined(); expect(mesh.primitives[1].material).toEqual(meshMaterial); @@ -452,15 +425,15 @@ describe('addDefaults', function() { it('Adds the default technique, program and shader if a material has an undefined technique', function() { var gltf = { - materials: { - material0: {}, - material1: {} - } + materials: [ + {}, + {} + ] }; addDefaults(gltf); - var techniqueId = gltf.materials.material0.technique; - expect(gltf.materials.material1.technique).toEqual(techniqueId); + var techniqueId = gltf.materials[0].technique; + expect(gltf.materials[1].technique).toEqual(techniqueId); var technique = gltf.techniques[techniqueId]; expect(technique).toBeDefined(); var programId = technique.program; @@ -476,12 +449,12 @@ describe('addDefaults', function() { it('Selects a default scene if none is present', function() { var gltf = { - scenes: { - scene: {} - } + scenes: [ + {} + ] }; addDefaults(gltf); - expect(gltf.scene).toEqual('scene'); + expect(gltf.scene).toEqual(0); }); }); diff --git a/specs/lib/addPipelineExtrasSpec.js b/specs/lib/addPipelineExtrasSpec.js index 4119a758..45dcda77 100644 --- a/specs/lib/addPipelineExtrasSpec.js +++ b/specs/lib/addPipelineExtrasSpec.js @@ -18,50 +18,50 @@ describe('addPipelineExtras', function() { }); it('added an extras object to objects without extras', function() { - expect(gltf.accessors.accessor_21.extras._pipeline).toBeDefined(); - expect(gltf.animations.animation_0.extras._pipeline).toBeDefined(); - expect(gltf.animations.animation_0.channels[0].extras._pipeline).toBeDefined(); - expect(gltf.animations.animation_0.channels[0].target.extras._pipeline).toBeDefined(); - expect(gltf.animations.animation_0.samplers.sampler.extras._pipeline).toBeDefined(); + expect(gltf.accessors[0].extras._pipeline).toBeDefined(); + expect(gltf.animations[0].extras._pipeline).toBeDefined(); + expect(gltf.animations[0].channels[0].extras._pipeline).toBeDefined(); + expect(gltf.animations[0].channels[0].target.extras._pipeline).toBeDefined(); + expect(gltf.animations[0].samplers[0].extras._pipeline).toBeDefined(); expect(gltf.asset.extras._pipeline).toBeDefined(); expect(gltf.asset.profile.extras._pipeline).toBeDefined(); expect(gltf.extras._pipeline).toBeDefined(); - expect(gltf.buffers.CesiumTexturedBoxTest.extras._pipeline).toBeDefined(); - expect(gltf.bufferViews.bufferView_29.extras._pipeline).toBeDefined(); - expect(gltf.cameras.camera_0.extras._pipeline).toBeDefined(); - expect(gltf.cameras.camera_0.orthographic.extras._pipeline).toBeDefined(); - expect(gltf.cameras.camera_0.perspective.extras._pipeline).toBeDefined(); - expect(gltf.images.Image0001.extras._pipeline).toBeDefined(); + expect(gltf.buffers[0].extras._pipeline).toBeDefined(); + expect(gltf.bufferViews[0].extras._pipeline).toBeDefined(); + expect(gltf.cameras[0].extras._pipeline).toBeDefined(); + expect(gltf.cameras[0].orthographic.extras._pipeline).toBeDefined(); + expect(gltf.cameras[0].perspective.extras._pipeline).toBeDefined(); + expect(gltf.images[0].extras._pipeline).toBeDefined(); }); it('added a _pipeline object to existing extras', function() { - expect(gltf.materials.EffectTexture.extras._pipeline).toBeDefined(); - expect(gltf.meshes.mesh002.extras._pipeline).toBeDefined(); - expect(gltf.meshes.mesh002.primitives[0].extras._pipeline).toBeDefined(); - expect(gltf.nodes.mesh002Node.extras._pipeline).toBeDefined(); - expect(gltf.programs.program_0.extras._pipeline).toBeDefined(); - expect(gltf.samplers.sampler_0.extras._pipeline).toBeDefined(); - expect(gltf.scenes.defaultScene.extras._pipeline).toBeDefined(); + expect(gltf.materials[0].extras._pipeline).toBeDefined(); + expect(gltf.meshes[0].extras._pipeline).toBeDefined(); + expect(gltf.meshes[0].primitives[0].extras._pipeline).toBeDefined(); + expect(gltf.nodes[0].extras._pipeline).toBeDefined(); + expect(gltf.programs[0].extras._pipeline).toBeDefined(); + expect(gltf.samplers[0].extras._pipeline).toBeDefined(); + expect(gltf.scenes[0].extras._pipeline).toBeDefined(); }); it('did not overwrite existing extras objects', function() { - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras._pipeline).toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras.misc).toBeDefined(); - expect(gltf.skins.Armature_Cylinder_skin.extras._pipeline).toBeDefined(); - expect(gltf.skins.Armature_Cylinder_skin.extras.misc).toBeDefined(); - expect(gltf.techniques.technique0.extras._pipeline).toBeDefined(); - expect(gltf.techniques.technique0.extras.misc).toBeDefined(); - expect(gltf.techniques.technique0.parameters.diffuse.extras.misc).toBeDefined(); - expect(gltf.techniques.technique0.states.extras._pipeline).toBeDefined(); - expect(gltf.techniques.technique0.states.extras.misc).toBeDefined(); - expect(gltf.techniques.technique0.states.functions.extras._pipeline).toBeDefined(); - expect(gltf.techniques.technique0.states.functions.extras.misc).toBeDefined(); - expect(gltf.textures.texture_Image0001.extras._pipeline).toBeDefined(); - expect(gltf.textures.texture_Image0001.extras.misc).toBeDefined(); + expect(gltf.shaders[0].extras._pipeline).toBeDefined(); + expect(gltf.shaders[0].extras.misc).toBeDefined(); + expect(gltf.skins[0].extras._pipeline).toBeDefined(); + expect(gltf.skins[0].extras.misc).toBeDefined(); + expect(gltf.techniques[0].extras._pipeline).toBeDefined(); + expect(gltf.techniques[0].extras.misc).toBeDefined(); + expect(gltf.techniques[0].parameters.diffuse.extras.misc).toBeDefined(); + expect(gltf.techniques[0].states.extras._pipeline).toBeDefined(); + expect(gltf.techniques[0].states.extras.misc).toBeDefined(); + expect(gltf.techniques[0].states.functions.extras._pipeline).toBeDefined(); + expect(gltf.techniques[0].states.functions.extras.misc).toBeDefined(); + expect(gltf.textures[0].extras._pipeline).toBeDefined(); + expect(gltf.textures[0].extras.misc).toBeDefined(); }); it('does not attempt to add extras to null objects', function() { - gltf.accessors.accessor_25 = { + gltf.accessors.push({ "bufferView": "bufferView_29", "byteOffset": 0, "componentType": 5123, @@ -77,8 +77,9 @@ describe('addPipelineExtras', function() { null, null ] - }; + }); + var accessorId = gltf.accessors.length - 1; addPipelineExtras(gltf); - expect(gltf.accessors.accessor_25).toBeDefined(); + expect(gltf.accessors[accessorId]).toBeDefined(); }); }); \ No newline at end of file diff --git a/specs/lib/bakeAmbientOcclusionSpec.js b/specs/lib/bakeAmbientOcclusionSpec.js index e5c89dea..038d9b0f 100644 --- a/specs/lib/bakeAmbientOcclusionSpec.js +++ b/specs/lib/bakeAmbientOcclusionSpec.js @@ -28,12 +28,11 @@ function cloneGltfWithJimps(gltf) { var originalJimp = gltf.extras._pipeline.jimpScratch; gltfClone.extras._pipeline.jimpScratch = originalJimp.clone(); var images = gltfClone.images; - for (var imageID in images) { - if (images.hasOwnProperty(imageID)) { - var image = images[imageID]; - originalJimp = gltf.images[imageID].extras._pipeline.jimpImage; - image.extras._pipeline.jimpImage = originalJimp.clone(); - } + var imagesLength = images.length; + for (var imageId = 0; imageId < imagesLength; imageId++) { + var image = images[imageId]; + originalJimp = gltf.images[imageId].extras._pipeline.jimpImage; + image.extras._pipeline.jimpImage = originalJimp.clone(); } return gltfClone; } @@ -84,64 +83,64 @@ describe('AmbientOcclusion', function() { var dataBuffer = Buffer.concat([indicesBuffer, positionsBuffer, normalsBuffer, uvsBuffer]); var testGltf = { - "accessors": { - "accessor_index": { - "bufferView": "index_view", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "componentType": 5123, "count": 6, "type": "SCALAR" }, - "accessor_position": { - "bufferView": "position_view", + { + "bufferView": 1, "byteOffset": 0, "componentType": 5126, "count": 4, "type": "VEC3" }, - "accessor_normal": { - "bufferView": "normal_view", + { + "bufferView": 2, "byteOffset": 0, "componentType": 5126, "count": 4, "type": "VEC3" }, - "accessor_uv": { - "bufferView": "uv_view", + { + "bufferView": 3, "byteOffset": 0, "componentType": 5126, "count": 4, "type": "VEC2" } - }, - "bufferViews": { - "index_view": { - "buffer": "buffer_0", + ], + "bufferViews": [ + { + "buffer": 0, "byteOffset": 0, "byteLength": 6 * 2, "target": 34963 }, - "position_view": { - "buffer": "buffer_0", + { + "buffer": 0, "byteOffset": 6 * 2, "byteLength": 4 * 3 * 4, "target": 34962 }, - "normal_view": { - "buffer": "buffer_0", + { + "buffer": 0, "byteOffset": 6 * 2 + (4 * 3 * 4), "byteLength": 4 * 3 * 4, "target": 34962 }, - "uv_view": { - "buffer": "buffer_0", + { + "buffer": 0, "byteOffset": 6 * 2 + (4 * 3 * 4) * 2, "byteLength": 4 * 2 * 4, "target": 34962 } - }, - "buffers": { - "buffer_0": { + ], + "buffers": [ + { "uri": "data:", "byteLength": indicesLength * 2 + (positionsLength + normalsLength + uvsLength) * 4, "extras": { @@ -150,17 +149,17 @@ describe('AmbientOcclusion', function() { } } } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "squareNode" + 0 ] } - }, - "nodes": { - "squareNode": { + ], + "nodes": [ + { "children": [], "matrix": [ 2, 0, 0, 0, @@ -168,33 +167,31 @@ describe('AmbientOcclusion', function() { 0, 0, 2, 0, 0, 0, 0, 1 ], - "meshes": [ - "mesh_square" - ], + "mesh": 0, "name": "square", "extras": { "_pipeline": {} } } - }, - "meshes": { - "mesh_square": { + ], + "meshes": [ + { "name": "square", "primitives": [ { "attributes": { - "POSITION": "accessor_position", - "NORMAL": "accessor_normal", - "TEXCOORD_0": "accessor_uv" + "POSITION": 1, + "NORMAL": 2, + "TEXCOORD_0": 3, }, - "indices": "accessor_index", + "indices": 0, "extras": { "_pipeline": {} } } ] } - } + ] }; beforeAll(function(done) { diff --git a/specs/lib/removeDuplicatePrimitivesSpec.js b/specs/lib/removeDuplicatePrimitivesSpec.js index c3b5522f..a383a42b 100644 --- a/specs/lib/removeDuplicatePrimitivesSpec.js +++ b/specs/lib/removeDuplicatePrimitivesSpec.js @@ -5,8 +5,8 @@ var removeDuplicatePrimitives = require('../../lib/removeDuplicatePrimitives'); describe('removeDuplicatePrimitives', function() { it('removes duplicate primitives', function() { var gltf = { - meshes : { - mesh : { + meshes : [ + { primitives : [ { attributes : { @@ -34,18 +34,18 @@ describe('removeDuplicatePrimitives', function() { } ] } - } + ] }; removeDuplicatePrimitives(gltf); - var primitives = gltf.meshes.mesh.primitives; + var primitives = gltf.meshes[0].primitives; expect(primitives.length).toEqual(2); expect(primitives[1].indices).toEqual(8); }); it('combines duplicate primitives across meshes', function() { var gltf = { - meshes : { - meshA : { + meshes : [ + { primitives : [ { attributes : { @@ -57,7 +57,7 @@ describe('removeDuplicatePrimitives', function() { } ] }, - meshB : { + { primitives : [ { attributes : { @@ -69,13 +69,13 @@ describe('removeDuplicatePrimitives', function() { } ] } - } + ] }; removeDuplicatePrimitives(gltf); var meshes = gltf.meshes; - expect(meshes['mesh-split']).toBeDefined(); - expect(meshes['mesh-split'].primitives.length).toEqual(1); - expect(meshes.meshA.primitives.length).toEqual(0); - expect(meshes.meshB.primitives.length).toEqual(0); + expect(meshes.length).toEqual(3); + expect(meshes[2].primitives.length).toEqual(1); + expect(meshes[0].primitives.length).toEqual(0); + expect(meshes[1].primitives.length).toEqual(0); }); }); \ No newline at end of file From 9f4b12b089c7a2be140e4df6d2b809b2392b9817 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 14 Feb 2017 13:45:46 -0500 Subject: [PATCH 23/47] More WIP changes --- lib/addDefaults.js | 8 +- lib/combineNodes.js | 72 ++++--- lib/processModelMaterialsCommon.js | 196 ++++++++----------- specs/lib/processModelMaterialsCommonSpec.js | 126 ++++++------ 4 files changed, 198 insertions(+), 204 deletions(-) diff --git a/lib/addDefaults.js b/lib/addDefaults.js index 018bc9bb..341c109f 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -61,20 +61,20 @@ var gltfTemplate = { var technique = materialsCommon.technique; var defaults = { ambient: [0.0, 0.0, 0.0, 1.0], - doubleSided: false, emission: [0.0, 0.0, 0.0, 1.0], - transparency: 1.0, - transparent: false + transparency: [1.0], }; if (technique !== 'CONSTANT') { defaults.diffuse = [0.0, 0.0, 0.0, 1.0]; if (technique !== 'LAMBERT') { defaults.specular = [0.0, 0.0, 0.0, 1.0]; - defaults.shininess = 0.0; + defaults.shininess = [0.0]; } } return { KHR_materials_common: { + doubleSided: false, + transparent: false, values: defaults } }; diff --git a/lib/combineNodes.js b/lib/combineNodes.js index 2894d016..d5c4e708 100644 --- a/lib/combineNodes.js +++ b/lib/combineNodes.js @@ -1,10 +1,9 @@ 'use strict'; var Cesium = require('cesium'); -var jp = require('jsonpath'); +var addToArray = require('./addToArray'); var NodeHelpers = require('./NodeHelpers'); var PrimitiveHelpers = require('./PrimitiveHelpers'); var RemoveUnusedProperties = require('./RemoveUnusedProperties'); -var getUniqueId = require('./getUniqueId'); var Matrix4 = Cesium.Matrix4; var defined = Cesium.defined; @@ -12,7 +11,6 @@ var removeNodes = RemoveUnusedProperties.removeNodes; module.exports = combineNodes; -var rootNodePrefix = 'rootNode'; var scratchTransform = new Matrix4(); /** @@ -33,26 +31,29 @@ var scratchTransform = new Matrix4(); */ function combineNodes(gltf) { var nodes = gltf.nodes; + var scenes = gltf.scenes; + var exclude = {}; getAnimationTargets(gltf, exclude); getTechniqueTargets(gltf, exclude); - jp.apply(gltf, '$.scenes[*]', function(scene) { + var scenesLength = scenes.length; + for (var sceneId = 0; sceneId < scenesLength; sceneId++) { + var scene = scenes[sceneId]; var sceneNodes = scene.nodes; if (defined(sceneNodes)) { - var rootNodeId = getUniqueId(gltf, rootNodePrefix); var rootNode = { - children : sceneNodes, - matrix : [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - ], - extras : { - _pipeline : {} - } + children : sceneNodes, + matrix : [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ], + extras : { + _pipeline : {} + } }; - nodes[rootNodeId] = rootNode; + var rootNodeId = addToArray(nodes, rootNode); mergeChildrenIntoNode(gltf, rootNodeId, NodeHelpers.mapMeshesToNodes(gltf), mapMeshesToMeshes(gltf), exclude); removeVestigialNodes(gltf, rootNodeId, exclude); if (rootNode.children.length > 0 && rootNode.meshes.length === 0) { @@ -62,24 +63,41 @@ function combineNodes(gltf) { } } return scene; - }); + } removeNodes(gltf); return gltf; } function getAnimationTargets(gltf, targets) { - jp.apply(gltf, '$.animations[*].channels[*].target.id', function(nodeId) { - targets[nodeId] = true; - return nodeId; - }); + var animations = gltf.animations; + var animationsLength = animations.length; + for (var animationId = 0; animationId < animationsLength; animationId++) { + var animation = animations[animationId]; + var channels = animation.channels; + var channelsLength = channels.length; + for (var channelId = 0; channelId < channelsLength; channelId++) { + var channel = channels[channelId]; + targets[channel.target.id] = true; + } + } return targets; } function getTechniqueTargets(gltf, targets) { - jp.apply(gltf, '$.techniques[*].parameters[?(@.node)]', function(techniqueParameters) { - targets[techniqueParameters.node] = true; - return techniqueParameters; - }); + var techniques = gltf.techniques; + var techniquesLength = techniques.length; + for (var techniqueId = 0; techniqueId < techniquesLength; techniqueId++) { + var technique = techniques[techniqueId]; + var parameters = technique.parameters; + for (var parameterName in parameters) { + if (parameters.hasOwnProperty(parameterName)) { + var parameter = parameters[parameterName]; + if (defined(parameter.node)) { + targets[parameter.node] = true; + } + } + } + } return targets; } @@ -175,7 +193,7 @@ function transformNodes(gltf, nodeIds, transform) { delete node.scale; var packedTransform = []; Matrix4.pack(nodeTransform, packedTransform); - node.matrix= packedTransform; + node.matrix = packedTransform; } } @@ -224,7 +242,7 @@ function canMergeToParent(gltf, nodeId, exclude) { function mapMeshesToMeshes(gltf) { var meshesToMeshes = {}; var meshes = gltf.meshes; - if (defined(meshes)) { + if (defined(meshes)) { var meshIds = Object.keys(meshes); while (meshIds.length > 0) { var meshId = meshIds.pop(); diff --git a/lib/processModelMaterialsCommon.js b/lib/processModelMaterialsCommon.js index b3d2643b..4f9a756e 100644 --- a/lib/processModelMaterialsCommon.js +++ b/lib/processModelMaterialsCommon.js @@ -1,10 +1,13 @@ 'use strict'; var Cesium = require('cesium'); +var addToArray = require('./addToArray'); +var techniqueParameterForSemantic = require('./techniqueParameterForSemantic'); + + var WebGLConstants = Cesium.WebGLConstants; var defined = Cesium.defined; var defaultValue = Cesium.defaultValue; -var techniqueParameterForSemantic = require('./techniqueParameterForSemantic'); module.exports = processModelMaterialsCommon; @@ -143,21 +146,6 @@ function generateLightParameters(gltf) { return result; } -function getNextId(dictionary, baseName, startingCount) { - var count = defaultValue(startingCount, 0); - var nextId; - do { - nextId = baseName + (count++).toString(); - } while (defined(dictionary[nextId])); - - return nextId; -} - -var techniqueCount = 0; -var vertexShaderCount = 0; -var fragmentShaderCount = 0; -var programCount = 0; - function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeForCesium) { var techniques = gltf.techniques; var shaders = gltf.shaders; @@ -174,12 +162,6 @@ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeFo var vertexShader = 'precision highp float;\n'; var fragmentShader = 'precision highp float;\n'; - // Generate IDs for our new objects - var techniqueId = getNextId(techniques, 'technique', techniqueCount); - var vertexShaderId = getNextId(shaders, 'vertexShader', vertexShaderCount); - var fragmentShaderId = getNextId(shaders, 'fragmentShader', fragmentShaderCount); - var programId = getNextId(programs, 'program', programCount); - var hasNormals = (lightingModel !== 'CONSTANT'); // Add techniques @@ -559,25 +541,19 @@ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeFo ] }; } - techniques[techniqueId] = { - attributes: techniqueAttributes, - parameters: techniqueParameters, - program: programId, - states: techniqueStates, - uniforms: techniqueUniforms - }; // Add shaders - shaders[vertexShaderId] = { + var vertexShaderId = addToArray(shaders, { type: WebGLConstants.VERTEX_SHADER, - extras: { - _pipeline: { - source: vertexShader, - extension: '.glsl' + extras: { + _pipeline: { + source: vertexShader, + extension: '.glsl' } } - }; - shaders[fragmentShaderId] = { + }); + + var fragmentShaderId = addToArray(shaders, { type: WebGLConstants.FRAGMENT_SHADER, extras: { _pipeline: { @@ -585,15 +561,23 @@ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, optimizeFo extension: '.glsl' } } - }; + }); // Add program var programAttributes = Object.keys(techniqueAttributes); - programs[programId] = { + var programId = addToArray(programs, { attributes: programAttributes, fragmentShader: fragmentShaderId, vertexShader: vertexShaderId - }; + }); + + var techniqueId = addToArray(techniques, { + attributes: techniqueAttributes, + parameters: techniqueParameters, + program: programId, + states: techniqueStates, + uniforms: techniqueUniforms + }); return techniqueId; } @@ -611,13 +595,13 @@ function getKHRMaterialsCommonValueType(paramName, paramValue) { switch (paramName) { case 'ambient': - return (value instanceof String || typeof value === 'string') ? WebGLConstants.SAMPLER_2D : WebGLConstants.FLOAT_VEC4; + return value.length === 1 ? WebGLConstants.SAMPLER_2D : WebGLConstants.FLOAT_VEC4; case 'diffuse': - return (value instanceof String || typeof value === 'string') ? WebGLConstants.SAMPLER_2D : WebGLConstants.FLOAT_VEC4; + return value.length === 1 ? WebGLConstants.SAMPLER_2D : WebGLConstants.FLOAT_VEC4; case 'emission': - return (value instanceof String || typeof value === 'string') ? WebGLConstants.SAMPLER_2D : WebGLConstants.FLOAT_VEC4; + return value.length === 1 ? WebGLConstants.SAMPLER_2D : WebGLConstants.FLOAT_VEC4; case 'specular': - return (value instanceof String || typeof value === 'string') ? WebGLConstants.SAMPLER_2D : WebGLConstants.FLOAT_VEC4; + return value.length === 1 ? WebGLConstants.SAMPLER_2D : WebGLConstants.FLOAT_VEC4; case 'shininess': return WebGLConstants.FLOAT; case 'transparency': @@ -641,9 +625,7 @@ function getTechniqueKey(khrMaterialsCommon) { var keysCount = keys.length; for (var i = 0; i < keysCount; ++i) { var name = keys[i]; - //generate first part of key using shader parameters for KHR_materials_common attributes - //(including a check, because some boolean flags should not be used as shader parameters) - if (values.hasOwnProperty(name) && (name !== 'transparent') && (name !== 'doubleSided')) { + if (values.hasOwnProperty(name)) { techniqueKey += name + ':' + getKHRMaterialsCommonValueType(name, values[name]); techniqueKey += ';'; } @@ -675,56 +657,55 @@ function lightDefaults(gltf) { } var lights = khrMaterialsCommon.lights; - for (var name in lights) { - if (lights.hasOwnProperty(name)) { - var light = lights[name]; - if (light.type === 'ambient') { - if (!defined(light.ambient)) { - light.ambient = {}; - } - var ambientLight = light.ambient; - - if (!defined(ambientLight.color)) { - ambientLight.color = [1.0, 1.0, 1.0]; - } - } else if (light.type === 'directional') { - if (!defined(light.directional)) { - light.directional = {}; - } - var directionalLight = light.directional; + var lightsLength = lights.length; + for (var lightId = 0; lightId < lightsLength; lightId++) { + var light = lights[lightId]; + if (light.type === 'ambient') { + if (!defined(light.ambient)) { + light.ambient = {}; + } + var ambientLight = light.ambient; - if (!defined(directionalLight.color)) { - directionalLight.color = [1.0, 1.0, 1.0]; - } - } else if (light.type === 'point') { - if (!defined(light.point)) { - light.point = {}; - } - var pointLight = light.point; + if (!defined(ambientLight.color)) { + ambientLight.color = [1.0, 1.0, 1.0]; + } + } else if (light.type === 'directional') { + if (!defined(light.directional)) { + light.directional = {}; + } + var directionalLight = light.directional; - if (!defined(pointLight.color)) { - pointLight.color = [1.0, 1.0, 1.0]; - } + if (!defined(directionalLight.color)) { + directionalLight.color = [1.0, 1.0, 1.0]; + } + } else if (light.type === 'point') { + if (!defined(light.point)) { + light.point = {}; + } + var pointLight = light.point; - pointLight.constantAttenuation = defaultValue(pointLight.constantAttenuation, 1.0); - pointLight.linearAttenuation = defaultValue(pointLight.linearAttenuation, 0.0); - pointLight.quadraticAttenuation = defaultValue(pointLight.quadraticAttenuation, 0.0); - } else if (light.type === 'spot') { - if (!defined(light.spot)) { - light.spot = {}; - } - var spotLight = light.spot; + if (!defined(pointLight.color)) { + pointLight.color = [1.0, 1.0, 1.0]; + } - if (!defined(spotLight.color)) { - spotLight.color = [1.0, 1.0, 1.0]; - } + pointLight.constantAttenuation = defaultValue(pointLight.constantAttenuation, 1.0); + pointLight.linearAttenuation = defaultValue(pointLight.linearAttenuation, 0.0); + pointLight.quadraticAttenuation = defaultValue(pointLight.quadraticAttenuation, 0.0); + } else if (light.type === 'spot') { + if (!defined(light.spot)) { + light.spot = {}; + } + var spotLight = light.spot; - spotLight.constantAttenuation = defaultValue(spotLight.constantAttenuation, 1.0); - spotLight.fallOffAngle = defaultValue(spotLight.fallOffAngle, 3.14159265); - spotLight.fallOffExponent = defaultValue(spotLight.fallOffExponent, 0.0); - spotLight.linearAttenuation = defaultValue(spotLight.linearAttenuation, 0.0); - spotLight.quadraticAttenuation = defaultValue(spotLight.quadraticAttenuation, 0.0); + if (!defined(spotLight.color)) { + spotLight.color = [1.0, 1.0, 1.0]; } + + spotLight.constantAttenuation = defaultValue(spotLight.constantAttenuation, 1.0); + spotLight.fallOffAngle = defaultValue(spotLight.fallOffAngle, 3.14159265); + spotLight.fallOffExponent = defaultValue(spotLight.fallOffExponent, 0.0); + spotLight.linearAttenuation = defaultValue(spotLight.linearAttenuation, 0.0); + spotLight.quadraticAttenuation = defaultValue(spotLight.quadraticAttenuation, 0.0); } } } @@ -756,6 +737,9 @@ function ensureSemanticExistenceForPrimitive(gltf, primitive) { var accessorId = attributes[semantic]; var accessor = accessors[accessorId]; var lowerCase = semantic.toLowerCase(); + if (lowerCase.charAt(0) === '_') { + lowerCase = lowerCase.slice(1); + } var attributeName = 'a_' + lowerCase; technique.parameters[lowerCase] = { semantic: semantic, @@ -774,14 +758,13 @@ function ensureSemanticExistenceForPrimitive(gltf, primitive) { function ensureSemanticExistence(gltf) { var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - ensureSemanticExistenceForPrimitive(gltf, primitives[i]); - } + var meshesLength = meshes.length; + for (var meshId = 0; meshId < meshesLength; meshId++) { + var mesh = meshes[meshId]; + var primitives = mesh.primitives; + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + ensureSemanticExistenceForPrimitive(gltf, primitives[i]); } } } @@ -816,13 +799,13 @@ function processModelMaterialsCommon(gltf, options) { if (hasExtension) { gltf.asset.premultipliedAlpha = true; if (!defined(gltf.programs)) { - gltf.programs = {}; + gltf.programs = []; } if (!defined(gltf.shaders)) { - gltf.shaders = {}; + gltf.shaders = []; } if (!defined(gltf.techniques)) { - gltf.techniques = {}; + gltf.techniques = []; } lightDefaults(gltf); @@ -847,16 +830,9 @@ function processModelMaterialsCommon(gltf, options) { material.values = {}; var values = khrMaterialsCommon.values; for (var valueName in values) { - if (values.hasOwnProperty(valueName) && (valueName !== 'transparent') && (valueName !== 'doubleSided')) { + if (values.hasOwnProperty(valueName)) { var value = values[valueName]; - - // Backwards compatibility for COLLADA2GLTF v1.0-draft when it encoding - // materials using KHR_materials_common with explicit type/value members - if (defined(value.value)) { - material.values[valueName] = value.value; - } else { - material.values[valueName] = value; - } + material.values[valueName] = value; } } diff --git a/specs/lib/processModelMaterialsCommonSpec.js b/specs/lib/processModelMaterialsCommonSpec.js index 5285dac6..cafc3203 100644 --- a/specs/lib/processModelMaterialsCommonSpec.js +++ b/specs/lib/processModelMaterialsCommonSpec.js @@ -8,17 +8,17 @@ var clone = Cesium.clone; describe('processModelMaterialsCommon', function() { it('generates techniques and nodes for KHR_materials_common lights', function() { var gltf = { - materials: { - material1: { + materials: [ + { extensions : { KHR_materials_common : { technique : 'BLINN' } } } - }, - nodes: { - node1: { + ], + nodes: [ + { children: [], extensions: { KHR_materials_common: { @@ -26,7 +26,7 @@ describe('processModelMaterialsCommon', function() { } } }, - node2: { + { children: [], extensions: { KHR_materials_common: { @@ -34,7 +34,7 @@ describe('processModelMaterialsCommon', function() { } } }, - node3: { + { children: [], extensions: { KHR_materials_common: { @@ -42,7 +42,7 @@ describe('processModelMaterialsCommon', function() { } } }, - node4: { + { children: [], extensions: { KHR_materials_common: { @@ -50,27 +50,26 @@ describe('processModelMaterialsCommon', function() { } } } - - }, + ], extensionsUsed: [ 'KHR_materials_common' ], extensions: { KHR_materials_common : { - lights: { - ambientLight: { + lights: [ + { ambient: { color: [1.0, 1.0, 1.0] }, type: 'ambient' }, - directionalLight: { + { directional: { color: [1.0, 1.0, 1.0] }, type: 'directional' }, - pointLight: { + { point: { color: [1.0, 1.0, 1.0] }, @@ -80,7 +79,7 @@ describe('processModelMaterialsCommon', function() { quadraticAttenuation: 1.0, type: 'point' }, - spotLight: { + { spot: { spot: [1.0, 1.0, 1.0] }, @@ -92,7 +91,7 @@ describe('processModelMaterialsCommon', function() { falloffExponent: 0.0, type: 'spot' } - } + ] } } }; @@ -101,35 +100,36 @@ describe('processModelMaterialsCommon', function() { diffuse: [0.0, 0.0, 0.0, 1.0], emission: [0.0, 0.0, 0.0, 1.0], specular: [0.0, 0.0, 0.0, 1.0], - shininess: 0.0, - transparency: 1.0 + shininess: [0.0], + transparency: [1.0] }; addDefaults(gltf); processModelMaterialsCommon(gltf); - expect(Object.keys(gltf.materials).length > 0).toEqual(true); - expect(Object.keys(gltf.techniques).length > 0).toEqual(true); - for (var materialID in gltf.materials) { - if (gltf.materials.hasOwnProperty(materialID)) { - expect(gltf.materials[materialID].values).toEqual(expectValues); - } + expect(gltf.materials.length).toBeGreaterThan(0) + expect(gltf.techniques.length).toBeGreaterThan(0); + var materialsLength = gltf.materials.length; + for (var materialId = 0; materialId < materialsLength; materialId++) { + expect(gltf.materials[materialId].values).toEqual(expectValues); } }); it('works with optimizeForCesium', function() { var gltf = { extensionsUsed: ['KHR_materials_common'], - materials: { - material1: { + materials: [ + { extensions: { KHR_materials_common: { technique: 'BLINN', - ambient: [0.0, 0.0, 0.0, 1.0], - diffuse: [1.0, 0.0, 0.0, 1.0], - emission: 'texture_file2' + values: { + ambient: [0.0, 0.0, 0.0, 1.0], + diffuse: [1.0, 0.0, 0.0, 1.0], + emission: [0] + } } } } - } + ] }; var gltfClone = clone(gltf, true); @@ -140,57 +140,57 @@ describe('processModelMaterialsCommon', function() { processModelMaterialsCommon(gltfClone, options); // Uses the Cesium sun as its default light source - var fragmentShaderSource = gltfClone.shaders.fragmentShader0.extras._pipeline.source; + var fragmentShaderSource = gltfClone.shaders[gltfClone.programs[0].fragmentShader].extras._pipeline.source; expect(fragmentShaderSource.indexOf('czm_sunDirectionEC') > -1).toBe(true); // Adds the _3DTILESDIFFUSE flag - var technique = gltfClone.techniques[Object.keys(gltfClone.techniques)[0]]; + var technique = gltfClone.techniques[0]; expect(technique.parameters.diffuse.semantic).toEqual('_3DTILESDIFFUSE'); gltfClone = clone(gltf, true); addDefaults(gltfClone); processModelMaterialsCommon(gltfClone); - fragmentShaderSource = gltfClone.shaders.fragmentShader0.extras._pipeline.source; + fragmentShaderSource = gltfClone.shaders[gltfClone.programs[0].fragmentShader].extras._pipeline.source; expect(fragmentShaderSource.indexOf('czm_sunDirectionEC') > -1).toBe(false); }); it('adds nonstandard semantic', function() { var gltf = { - 'accessors': { - 'accessor_3': { - 'componentType': 5123, - 'type': 'SCALAR' + accessors: [ + { + componentType: 5123, + type: 'SCALAR' } - }, - 'extensionsUsed': [ + ], + extensionsUsed: [ 'KHR_materials_common' ], - 'meshes': { - 'mesh1' : { - 'primitives': [ + meshes: [ + { + primitives: [ { - 'attributes': { - 'NORMAL': 'accessor_1', - 'POSITION': 'accessor_2', - 'BATCHID': 'accessor_3' + attributes: { + NORMAL: 1, + POSITION: 2, + _BATCHID: 0 }, - 'indices': 'accessor_4', - 'material': 'material1', - 'mode': 4 + indices: 3, + material: 0, + mode: 4 } ] } - }, - 'materials': { - 'material1': { - 'extensions': { - 'KHR_materials_common': { - 'doubleSided': false, - 'jointCount': 0, - 'technique': 'PHONG', - 'transparent': false, - 'values': { + ], + materials: [ + { + extensions: { + KHR_materials_common: { + doubleSided: false, + jointCount: 0, + technique: 'PHONG', + transparent: false, + values: { 'diffuse': [ 0.4, 0.4, @@ -200,19 +200,19 @@ describe('processModelMaterialsCommon', function() { } } }, - 'name': 'material1' + name: 'material1' } - } + ] }; var gltfClone = clone(gltf); addDefaults(gltfClone); processModelMaterialsCommon(gltfClone); - var material = gltfClone.materials.material1; + var material = gltfClone.materials[0]; var technique = gltfClone.techniques[material.technique]; expect(technique.attributes.a_batchid).toEqual('batchid'); - expect(technique.parameters.batchid.semantic).toEqual('BATCHID'); + expect(technique.parameters.batchid.semantic).toEqual('_BATCHID'); var program = gltfClone.programs[technique.program]; expect(program.attributes.indexOf('a_batchid') > -1).toBe(true); From dee100926b4b66d599900fa1706384333dbd3386 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 14 Feb 2017 14:01:56 -0500 Subject: [PATCH 24/47] Removed combineMeshes -> nodes only have a singular mesh now --- lib/Pipeline.js | 2 - lib/combineMeshes.js | 69 ----------------- specs/lib/combineMeshesSpec.js | 132 --------------------------------- 3 files changed, 203 deletions(-) delete mode 100644 lib/combineMeshes.js delete mode 100644 specs/lib/combineMeshesSpec.js diff --git a/lib/Pipeline.js b/lib/Pipeline.js index 4b638285..a80f5475 100644 --- a/lib/Pipeline.js +++ b/lib/Pipeline.js @@ -8,7 +8,6 @@ var RemoveUnusedProperties = require('./RemoveUnusedProperties'); var addDefaults = require('./addDefaults'); var addPipelineExtras = require('./addPipelineExtras'); var bakeAmbientOcclusion = require('./bakeAmbientOcclusion'); -var combineMeshes = require('./combineMeshes'); var combineNodes = require('./combineNodes'); var combinePrimitives = require('./combinePrimitives'); var compressIntegerAccessors = require('./compressIntegerAccessors'); @@ -112,7 +111,6 @@ Pipeline.processJSONWithExtras = function(gltfWithExtras, options) { combinePrimitives(gltfWithExtras); convertDagToTree(gltfWithExtras); combineNodes(gltfWithExtras); - combineMeshes(gltfWithExtras); combinePrimitives(gltfWithExtras); MergeDuplicateProperties.mergeAll(gltfWithExtras); removeDuplicatePrimitives(gltfWithExtras); diff --git a/lib/combineMeshes.js b/lib/combineMeshes.js deleted file mode 100644 index 5878f821..00000000 --- a/lib/combineMeshes.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; -var Cesium = require('cesium'); - -var defined = Cesium.defined; - -module.exports = combineMeshes; - -/** - * Combines meshes in a node. - * Should be run before the {@link combinePrimitives} stage to merge all primitives for a node into one mesh. - * - * The glTF asset must be initialized for the pipeline. - * - * @param {Object} gltf A javascript object containing a glTF asset. - * @returns {Object} The glTF asset with combined meshes. - * - * @see addPipelineExtras - * @see loadGltfUris - * @see combinePrimitives - */ -function combineMeshes(gltf) { - var nodes = gltf.nodes; - var meshes = gltf.meshes; - - if (defined(nodes)) { - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - var node = nodes[nodeId]; - var nodeMeshes = node.meshes; - - if (defined(nodeMeshes) && nodeMeshes.length > 1) { - //Find the next available id for the combined mesh. - var idCount = 0; - var newMeshId = nodeId + '_mesh_' + idCount; - var objectKeys = Object.keys(meshes); - while (objectKeys.indexOf(newMeshId) !== -1) { - idCount++; - newMeshId = newMeshId.slice(0, -1) + idCount; - } - - //Combine all the primitives from the meshes into one array. - var primitiveList = []; - for (var i = 0; i < nodeMeshes.length; i++) { - var primitives = meshes[nodeMeshes[i]].primitives; - if (defined(primitives)) { - for (var j = 0; j < primitives.length; j++) { - primitiveList.push(primitives[j]); - } - } - } - - //Create a new mesh with all the primitives and the node id. - var newMesh = { - "name": nodeId + '_mesh', - "primitives": primitiveList, - "extras": { - "_pipeline": {} - } - }; - - node.meshes = [newMeshId]; - meshes[newMeshId] = newMesh; - } - } - } - } - - return gltf; -} \ No newline at end of file diff --git a/specs/lib/combineMeshesSpec.js b/specs/lib/combineMeshesSpec.js deleted file mode 100644 index bd7fe414..00000000 --- a/specs/lib/combineMeshesSpec.js +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; -var clone = require('clone'); -var combineMeshes = require('../../lib/combineMeshes'); - -describe('combineMeshes', function() { - it('does not affect nodes with one mesh', function() { - var gltf = { - "meshes": { - "mesh_0": { - "primitives": [ - { - "material": "mat_0" - } - ] - }, - "mesh_1": { - "primitives": [ - { - "material": "mat_1" - } - ] - } - }, - "nodes": { - "node_0": { - "meshes": [ - "mesh_0" - ] - }, - "node_1": { - "meshes": [ - "mesh_1" - ] - } - } - }; - - expect(gltf).toEqual(combineMeshes(clone(gltf))); - }); - - it('combines both meshes', function() { - var gltf = { - "meshes": { - "mesh_0": { - "primitives": [ - { - "material": "mat_0" - } - ] - }, - "mesh_1": { - "primitives": [ - { - "material": "mat_1" - } - ] - } - }, - "nodes": { - "node_0": { - "meshes": [ - "mesh_0", - "mesh_1" - ] - } - } - }; - - combineMeshes(gltf); - - expect(gltf.nodes.node_0.meshes).toEqual(['node_0_mesh_0']); - expect(gltf.meshes.node_0_mesh_0).toBeDefined(); - expect(gltf.meshes.node_0_mesh_0.primitives).toEqual([ - { - "material": 'mat_0' - }, - { - "material": 'mat_1' - } - ]); - }); - - it('combines some meshes', function() { - var gltf = { - "meshes": { - "mesh_0": { - "primitives": [ - { - "material": "mat_0" - } - ] - }, - "mesh_1": { - "primitives": [ - { - "material": "mat_1" - } - ] - } - }, - "nodes": { - "node_0": { - "meshes": [ - "mesh_0", - "mesh_1" - ] - }, - "node_1": { - "meshes": [ - "mesh_0" - ] - } - } - }; - - var combinedGltf = combineMeshes(clone(gltf)); - - expect(combinedGltf.nodes.node_0.meshes).toEqual(['node_0_mesh_0']); - expect(combinedGltf.meshes.node_0_mesh_0).toBeDefined(); - expect(combinedGltf.meshes.node_0_mesh_0.primitives).toEqual([ - { - "material": 'mat_0' - }, - { - "material": 'mat_1' - } - ]); - expect(combinedGltf.nodes.node_1).toEqual(gltf.nodes.node_1); - expect(combinedGltf.meshes.mesh_0).toEqual(gltf.meshes.mesh_0); - expect(combinedGltf.meshes.mesh_1).toEqual(gltf.meshes.mesh_1); - }); -}); \ No newline at end of file From 2ac3bfdd3e97158259460cf4a42d7fcd8cd609b2 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 14 Feb 2017 19:04:35 -0500 Subject: [PATCH 25/47] Operator -> operate --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 84a3711a..24aa55f9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,7 +11,7 @@ Change Log * Added `build-cesium-combined` command to gulp file for generating simple files for other projects. [#231](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/231). * Change Cesium `Geometry`'s and `VertexFormat`'s `binormal` attribute to bitangent. * `updateVersion` stage for upgrades the glTF version of an asset from `1.0` to `2.0`. [#223](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/223) - * All pipeline stages now operat on glTF `2.0` assets. + * All pipeline stages now operate on glTF `2.0` assets. ### 0.1.0-alpha10 - 2017-01-10 * Added `tangentsBitangents` generation option From 2ec85450b161405c389a3c3a6a5946193e92a629 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 14 Feb 2017 19:05:00 -0500 Subject: [PATCH 26/47] combineNodes, removeUnused and dagToTree traversal changes --- .../dagToTree/DagTestSingleDuplicate.gltf | 39 +- specs/data/dagToTree/DagTestSingleNode.gltf | 16 +- .../dagToTree/DagTestSubgraphDuplicate.gltf | 62 +-- specs/data/dagToTree/DagTestTree.gltf | 29 +- specs/data/dagToTree/DagTestTwoRoots.gltf | 55 +-- specs/lib/RemoveUnusedPropertiesSpec.js | 291 +++++++------- specs/lib/combineNodesSpec.js | 365 +++++++++--------- specs/lib/convertDagToTreeSpec.js | 196 +++++++--- 8 files changed, 615 insertions(+), 438 deletions(-) diff --git a/specs/data/dagToTree/DagTestSingleDuplicate.gltf b/specs/data/dagToTree/DagTestSingleDuplicate.gltf index 5dc6766b..78cc867b 100644 --- a/specs/data/dagToTree/DagTestSingleDuplicate.gltf +++ b/specs/data/dagToTree/DagTestSingleDuplicate.gltf @@ -1,28 +1,33 @@ { - "nodes": { - "A": { + "nodes": [ + { "children": [ - "B", - "C" - ] + 1, + 2 + ], + "name": "A" }, - "B": { + { "children": [ - "D" - ] + 3 + ], + "name": "B" }, - "C": { + { "children": [ - "D" - ] + 3 + ], + "name": "C" }, - "D": {} - }, - "scenes": { - "defaultScene": { + { + "name": "D" + } + ], + "scenes": [ + { "nodes": [ - "A" + 0 ] } - } + ] } \ No newline at end of file diff --git a/specs/data/dagToTree/DagTestSingleNode.gltf b/specs/data/dagToTree/DagTestSingleNode.gltf index 2916c5d8..3e1dc002 100644 --- a/specs/data/dagToTree/DagTestSingleNode.gltf +++ b/specs/data/dagToTree/DagTestSingleNode.gltf @@ -1,12 +1,14 @@ { - "nodes": { - "A": {} - }, - "scenes": { - "defaultScene": { + "nodes": [ + { + "name": "A" + } + ], + "scenes": [ + { "nodes": [ - "A" + 0 ] } - } + ] } \ No newline at end of file diff --git a/specs/data/dagToTree/DagTestSubgraphDuplicate.gltf b/specs/data/dagToTree/DagTestSubgraphDuplicate.gltf index 7723d4fa..ec6350e1 100644 --- a/specs/data/dagToTree/DagTestSubgraphDuplicate.gltf +++ b/specs/data/dagToTree/DagTestSubgraphDuplicate.gltf @@ -1,44 +1,52 @@ { - "nodes": { - "A": { + "nodes": [ + { "children": [ - "B", - "C" - ] + 1, + 2 + ], + "name": "A" }, - "B": { + { "children": [ - "D" - ] + 3 + ], + "name": "B" }, - "C": { + { "children": [ - "D" - ] + 3 + ], + "name": "C" }, - "D": { + { "children": [ - "E", - "F" - ] + 4, + 5 + ], + "name": "D" }, - "E": { + { "children": [ - "G" - ] + 6 + ], + "name": "E" }, - "F": { + { "children": [ - "G" - ] + 6 + ], + "name": "F" }, - "G": {} - }, - "scenes": { - "defaultScene": { + { + "name": "G" + } + ], + "scenes": [ + { "nodes": [ - "A" + 0 ] } - } + ] } \ No newline at end of file diff --git a/specs/data/dagToTree/DagTestTree.gltf b/specs/data/dagToTree/DagTestTree.gltf index 86daa9dd..267fbe69 100644 --- a/specs/data/dagToTree/DagTestTree.gltf +++ b/specs/data/dagToTree/DagTestTree.gltf @@ -1,19 +1,24 @@ { - "nodes": { - "A": { + "nodes": [ + { "children": [ - "B", - "C" - ] + 1, + 2 + ], + "name": "A" + }, + { + "name": "B" }, - "B": {}, - "C": {} - }, - "scenes": { - "defaultScene": { + { + "name": "C" + } + ], + "scenes": [ + { "nodes": [ - "A" + 0 ] } - } + ] } \ No newline at end of file diff --git a/specs/data/dagToTree/DagTestTwoRoots.gltf b/specs/data/dagToTree/DagTestTwoRoots.gltf index 3bf9dceb..d8fb234c 100644 --- a/specs/data/dagToTree/DagTestTwoRoots.gltf +++ b/specs/data/dagToTree/DagTestTwoRoots.gltf @@ -1,39 +1,46 @@ { - "nodes": { - "B": { + "nodes": [ + { "children": [ - "D" - ] + 2 + ], + "name": "B" }, - "C": { + { "children": [ - "D" - ] + 2 + ], + "name": "C" }, - "D": { + { "children": [ - "E", - "F" - ] + 3, + 4 + ], + "name": "D" }, - "E": { + { "children": [ - "G" - ] + 5 + ], + "name": "E" }, - "F": { + { "children": [ - "G" - ] + 5 + ], + "name": "F" }, - "G": {} - }, - "scenes": { - "defaultScene": { + { + "name": "G" + } + ], + "scenes": [ + { "nodes": [ - "B", - "C" + 0, + 1 ] } - } + ] } \ No newline at end of file diff --git a/specs/lib/RemoveUnusedPropertiesSpec.js b/specs/lib/RemoveUnusedPropertiesSpec.js index b993d5dd..dfa1a19b 100644 --- a/specs/lib/RemoveUnusedPropertiesSpec.js +++ b/specs/lib/RemoveUnusedPropertiesSpec.js @@ -1,8 +1,6 @@ 'use strict'; - var Promise = require('bluebird'); var fs = require('fs-extra'); - var RemoveUnusedProperties = require('../../lib/RemoveUnusedProperties'); var fsReadFile = Promise.promisify(fs.readFile); @@ -14,142 +12,175 @@ describe('RemoveUnusedProperties', function() { describe('removeNodes', function () { it('removes an isolated node', function () { var gltf = { - "nodes": { - "node_3": { - "children": [ - "left_node", - "right_node" - ] + nodes: [ + { + children: [ + 1, + 2 + ], + name: 'node_3' }, - "left_node": {}, - "right_node": { - "children": [ - "txtrLocator026Node" - ] + { + name: 'left_node' }, - "txtrLocator026Node": {}, - "unusedNodeId": {} - }, - "scenes": { - "defaultScene": { - "nodes": [ - "node_3" + { + children: [ + 3 + ], + name: 'right_node' + }, + { + name: 'txtrLocator026Node' + }, + { + name: 'unusedNodeId' + } + ], + scenes: [ + { + nodes: [ + 0 ] } - } + ] }; removeNodes(gltf); - expect(gltf.nodes.unusedNodeId).not.toBeDefined(); - expect(Object.keys(gltf.nodes).length).toEqual(4); + var nodes = gltf.nodes; + expect(nodes.length).toEqual(4); + expect(nodes[0].name).toEqual('node_3'); + expect(nodes[1].name).toEqual('left_node'); + expect(nodes[2].name).toEqual('right_node'); + expect(nodes[3].name).toEqual('txtrLocator026Node'); }); it('removes an unused tree', function () { var gltf = { - "nodes": { - "node_3": { - "children": [ - "left_node", - "right_node" - ] + nodes: [ + { + children: [ + 1, + 2 + ], + name: 'node_3' }, - "left_node": {}, - "right_node": { - "children": [ - "txtrLocator026Node" - ] + { + name: 'left_node' }, - "txtrLocator026Node": {} - }, - "scenes": { - "defaultScene": {} - } + { + children: [ + 3 + ], + name: 'right_node' + }, + { + name: 'txtrLocator026Node' + } + ], + scenes: [ + {} + ] }; + removeNodes(gltf); - expect(gltf.nodes.node_3).not.toBeDefined(); - expect(gltf.nodes.left_node).not.toBeDefined(); - expect(gltf.nodes.right_node).not.toBeDefined(); - expect(gltf.nodes.txtrLocator026Node).not.toBeDefined(); - expect(Object.keys(gltf.nodes).length).toEqual(0); + expect(gltf.nodes.length).toEqual(0); }); it('removes an extra tree', function () { var gltf = { - "nodes": { - "node_3": { - "children": [ - "left_node", - "right_node" - ] + nodes: [ + { + children: [ + 1, + 2 + ], + name: 'node_3' }, - "left_node": {}, - "right_node": { - "children": [ - "txtrLocator026Node" - ] + { + name: 'left_node' }, - "txtrLocator026Node": {}, - "unusedRootId": { - "children": [ - "unusedLeftId", - "unusedRightId" - ] + { + children: [ + 3 + ], + name: 'right_node' }, - "unusedLeftId": {}, - "unusedRightId": { - "children": [ - "unusedChildId" - ] + { + name: 'txtrLocator026Node' }, - "unusedChildId": {} - }, - "scenes": { - "defaultScene": { - "nodes": [ - "node_3" + { + children: [ + 5, 6 + ], + name: 'unusedRootId' + }, + { + name: 'unusedLeftId' + }, + { + children: [ + 7 + ], + name: 'unusedRightId' + }, + { + name: 'unusedChildId' + } + ], + scenes: [ + { + nodes: [ + 0 ] } - } + ] }; removeNodes(gltf); - expect(gltf.nodes.unusedRootId).not.toBeDefined(); - expect(gltf.nodes.unusedLeftId).not.toBeDefined(); - expect(gltf.nodes.unusedRightId).not.toBeDefined(); - expect(gltf.nodes.unusedChildId).not.toBeDefined(); - expect(Object.keys(gltf.nodes).length).toEqual(4); + var nodes = gltf.nodes; + expect(nodes.length).toEqual(4); + expect(nodes[0].name).toEqual('node_3'); + expect(nodes[1].name).toEqual('left_node'); + expect(nodes[2].name).toEqual('right_node'); + expect(nodes[3].name).toEqual('txtrLocator026Node'); }); it('does not remove any nodes', function () { var gltf = { - "nodes": { - "node_3": { - "children": [ - "left_node", - "right_node" - ] + nodes: [ + { + children: [ + 1, + 2 + ], + name: 'node_3' }, - "left_node": {}, - "right_node": { - "children": [ - "txtrLocator026Node" - ] + { + name: 'left_node' }, - "txtrLocator026Node": {} - }, - "scenes": { - "defaultScene": { - "nodes": [ - "node_3" + { + children: [ + 3 + ], + name: 'right_node' + }, + { + name: 'txtrLocator026Node' + } + ], + scenes: [ + { + nodes: [ + 0 ] } - } + ] }; - removeNodes(gltf); - expect(gltf.nodes.node_3).toBeDefined(); - expect(gltf.nodes.left_node).toBeDefined(); - expect(gltf.nodes.right_node).toBeDefined(); - expect(gltf.nodes.txtrLocator026Node).toBeDefined(); - expect(Object.keys(gltf.nodes).length).toEqual(4); + var nodes = gltf.nodes; + expect(nodes.length).toEqual(4); + expect(nodes[0].name).toEqual('node_3'); + expect(nodes[1].name).toEqual('left_node'); + expect(nodes[2].name).toEqual('right_node'); + expect(nodes[3].name).toEqual('txtrLocator026Node'); }); }); @@ -268,43 +299,45 @@ describe('RemoveUnusedProperties', function() { describe('removeMeshes', function () { it('removes a mesh', function () { var gltf = { - "meshes": { - "Geometry-mesh002": { - primitives: [{}] + meshes: [ + { + primitives: [{}], + name: 'Geometry-mesh002' }, - "unusedMeshId": {} - }, - "nodes": { - "Geometry-mesh002Node": { - "meshes": [ - "Geometry-mesh002" - ] + { + name: 'unusedMeshId' } - } + ], + nodes: [ + { + mesh: 0, + name: 'Geometry-mesh002Node' + } + ] }; removeMeshes(gltf); - expect(gltf.meshes.unusedMeshId).not.toBeDefined(); - expect(Object.keys(gltf.meshes).length).toEqual(1); + expect(gltf.meshes.length).toEqual(1); + expect(gltf.meshes[0].name).toEqual('Geometry-mesh002'); }); it('does not remove any meshes', function () { var gltf = { - "meshes": { - "Geometry-mesh002": { - primitives: [{}] - } - }, - "nodes": { - "Geometry-mesh002Node": { - "meshes": [ - "Geometry-mesh002" - ] - } - } + meshes: [ + { + primitives: [{}], + name: 'Geometry-mesh002' + } + ], + nodes: [ + { + mesh: 0, + name: 'Geometry-mesh002Node' + } + ] }; removeMeshes(gltf); - expect(gltf.meshes["Geometry-mesh002"]).toBeDefined(); - expect(Object.keys(gltf.meshes).length).toEqual(1); + expect(gltf.meshes.length).toEqual(1); + expect(gltf.meshes[0].name).toEqual('Geometry-mesh002'); }); }); diff --git a/specs/lib/combineNodesSpec.js b/specs/lib/combineNodesSpec.js index aca6a160..908ae5b0 100644 --- a/specs/lib/combineNodesSpec.js +++ b/specs/lib/combineNodesSpec.js @@ -9,103 +9,108 @@ var readAccessor = require('../../lib/readAccessor'); describe('combineNodes', function() { it('reduces a scene with extra nodes to a single node', function() { var gltf = { - nodes : { - nodeA : {}, - nodeB : {}, - nodeC : {} - }, - scenes : { - scene : { + nodes : [ + {}, + {}, + {} + ], + scenes : [ + { nodes : [ - 'nodeA', - 'nodeB', - 'nodeC' + 0, + 1, + 2 ] } - } + ] }; combineNodes(gltf); - expect(Object.keys(gltf.nodes).length).toEqual(1); + expect(gltf.nodes.length).toEqual(1); }); it('preserves camera node', function() { var gltf = { - nodes : { - nodeA : { - children : ['nodeB'] + nodes : [ + { + children : [1] }, - nodeB : { - children : ['nodeC'] + { + children : [2] }, - nodeC : { - camera : 'camera' + { + camera : 0 } - }, - scenes : { - scene : { - nodes : ['nodeA'] + ], + scenes : [ + { + nodes : [0] } - } + ] }; combineNodes(gltf); var nodes = gltf.nodes; - expect(nodes.nodeC).toBeDefined(); + expect(nodes.length).toEqual(1); + expect(nodes[0].camera).toBeDefined(); }); - it('preserve joint node', function() { + it('preserves joint node', function() { var gltf = { - nodes : { - nodeA : { - children : ['nodeB'] + nodes : [ + { + children : [1] }, - nodeB : { - children : ['nodeC'] + { + children : [2] }, - nodeC : { + { jointName : 'joint' } - }, - scenes : { - scene : { - nodes : ['nodeA'] + ], + scenes : [ + { + nodes : [0] } - } + ] }; combineNodes(gltf); var nodes = gltf.nodes; - expect(nodes.nodeC).toBeDefined(); + expect(nodes.length).toEqual(1); + expect(nodes[0].jointName).toEqual('joint'); }); it('handles crossed mesh dependencies', function() { var gltf = { - meshes : { - mesh : {} - }, - nodes : { - nodeA : { - meshes : ['mesh'] + meshes : [ + { + primitives: [{}] + } + ], + nodes : [ + { + mesh: 0 }, - nodeB : { - meshes : ['mesh'] + { + mesh: 0 } - }, - scenes : { - scene : { - nodes : ['nodeA', 'nodeB'] + ], + scenes : [ + { + nodes : [0, 1] } - } + ] }; combineNodes(gltf); var nodes = gltf.nodes; - expect(nodes.nodeA).toBeDefined(); - expect(nodes.nodeB).toBeDefined(); + expect(nodes.length).toEqual(2); + expect(nodes[0].mesh).toEqual(0); + expect(nodes[1].mesh).toEqual(0); }); it('flattens out unnecessary node chains', function() { var gltf = { - nodes : { - nodeA : { - children : ['nodeB'], + nodes : [ + { + children : [1], matrix : [ 1.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, @@ -113,8 +118,8 @@ describe('combineNodes', function() { 1.0, 2.0, 3.0, 1.0 ] }, - nodeB : { - children : ['nodeC'], + { + children : [2], matrix : [ 4.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, @@ -122,20 +127,21 @@ describe('combineNodes', function() { 4.0, 5.0, 6.0, 1.0 ] }, - nodeC : { - camera : '' + { + camera : 0 } - }, - scenes : { - scene : { - nodes : ['nodeA'] + ], + scenes : [ + { + nodes : [0] } - } + ] }; combineNodes(gltf); var nodes = gltf.nodes; - var cameraNode = nodes.nodeC; - expect(cameraNode).toBeDefined(); + expect(nodes.length).toEqual(1); + var cameraNode = nodes[0]; + expect(cameraNode.camera).toEqual(0); expect(cameraNode.matrix).toEqual([ 4.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, @@ -146,52 +152,53 @@ describe('combineNodes', function() { it('doesn\'t modify nodes targeted for animation', function() { var gltf = { - animations : { - animation : { + animations : [ + { channels : [ { target: { - id: 'nodeA' + id: 0 } } ] } - }, - nodes : { - nodeA : {} - }, - scenes : { - scene : { - nodes : ['nodeA'] + ], + nodes : [ + {} + ], + scenes : [ + { + nodes : [0] } - } + ] }; combineNodes(gltf); - expect(gltf.nodes.nodeA).toBeDefined(); + var nodes = gltf.nodes; + expect(nodes.length).toEqual(1); }); it('doesn\'t modify nodes targeted from technique parameters', function() { var gltf = { - nodes : { - nodeA : {} - }, - scenes : { - scene : { - nodes : ['nodeA'] + nodes : [ + {} + ], + scenes : [ + { + nodes : [0] } - }, - techniques : { - technique : { + ], + techniques : [ + { parameters : { lightTransform : { - node : 'nodeA' + node : 0 } } } - } + ] }; combineNodes(gltf); - expect(gltf.nodes.nodeA).toBeDefined(); + expect(gltf.nodes.length).toEqual(1); }); it('transforms mesh primitives from a child node and passes it to the parent', function() { @@ -204,48 +211,48 @@ describe('combineNodes', function() { var indicesBuffer = new Buffer(indices.buffer); var buffer = Buffer.concat([attributesBuffer, indicesBuffer]); var gltf = { - accessors : { - positionAccessor : { - bufferView : 'attributesBufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.FLOAT, count : positions.length / 3, type : "VEC3" }, - normalAccessor : { - bufferView : 'attributesBufferView', + { + bufferView : 0, byteOffset : normalsBuffer.length, byteStride : 0, componentType : WebGLConstants.FLOAT, count : normals.length / 3, type : "VEC3" }, - indicesAccessor : { - bufferView : 'indicesBufferView', + { + bufferView : 1, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indices.length, type : "SCALAR" } - }, - bufferViews : { - attributesBufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : attributesBuffer.length, byteOffset : 0, target : WebGLConstants.ARRAY_BUFFER }, - indicesBufferView : { - buffer : 'buffer', + { + buffer : 0, byteLength : indicesBuffer.length, byteOffset : attributesBuffer.length, target : WebGLConstants.ELEMENT_ARRAY_BUFFER } - }, - buffers : { - buffer : { + ], + buffers : [ + { type : "arraybuffer", byteLength : buffer.length, extras : { @@ -254,49 +261,49 @@ describe('combineNodes', function() { } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - NORMAL : 'normalAccessor', - POSITION : 'positionAccessor' + NORMAL : 1, + POSITION : 0 }, - indices : 'indicesAccessor' + indices : 2 } ] } - }, - nodes : { - nodeA : { - children : ['nodeB'] + ], + nodes : [ + { + children : [1] }, - nodeB : { - meshes : ['mesh'], + { + mesh : 0, matrix : [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 3.0, 1.0] } - }, - scenes : { - scene : { - nodes : ['nodeA'] + ], + scenes : [ + { + nodes : [0] } - } + ] }; combineNodes(gltf); var accessors = gltf.accessors; var nodes = gltf.nodes; - var rootNodeId = Object.keys(nodes)[0]; + var rootNodeId = gltf.scenes[0].nodes[0]; var rootNode = nodes[rootNodeId]; - expect(rootNode.meshes[0]).toEqual('mesh'); + expect(rootNode.mesh).toEqual(0); var cartesianPositions = []; var cartesianNormals = []; - readAccessor(gltf, accessors.positionAccessor, cartesianPositions); - readAccessor(gltf, accessors.normalAccessor, cartesianNormals); + readAccessor(gltf, accessors[0], cartesianPositions); + readAccessor(gltf, accessors[1], cartesianNormals); expect(cartesianPositions.length).toEqual(cartesianNormals.length); var length = cartesianPositions.length; @@ -326,56 +333,56 @@ describe('combineNodes', function() { var allIndicesBuffer = Buffer.concat([indicesBuffer, overlappedIndicesBuffer]); var buffer = Buffer.concat([attributesBuffer, allIndicesBuffer]); var gltf = { - accessors : { - positionAccessor : { - bufferView : 'attributesBufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.FLOAT, count : positions.length / 3, type : "VEC3" }, - normalAccessor : { - bufferView : 'attributesBufferView', + { + bufferView : 0, byteOffset : normalsBuffer.length, byteStride : 0, componentType : WebGLConstants.FLOAT, count : normals.length / 3, type : "VEC3" }, - indicesAccessor : { - bufferView : 'indicesBufferView', + { + bufferView : 1, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indices.length, type : "SCALAR" }, - overlappedIndicesAccessor : { - bufferView : 'indicesBufferView', - byteOffset : indicesBuffer.length, - byteStride : 0, - componentType : WebGLConstants.UNSIGNED_SHORT, - count : overlappedIndices.length, - type : "SCALAR" + { + bufferView: 1, + byteOffset: indicesBuffer.length, + byteStride: 0, + componentType: WebGLConstants.UNSIGNED_SHORT, + count: overlappedIndices.length, + type: "SCALAR" } - }, - bufferViews : { - attributesBufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : attributesBuffer.length, byteOffset : 0, target : WebGLConstants.ARRAY_BUFFER }, - indicesBufferView : { - buffer : 'buffer', + { + buffer : 0, byteLength : allIndicesBuffer.length, byteOffset : attributesBuffer.length, target : WebGLConstants.ELEMENT_ARRAY_BUFFER } - }, - buffers : { - buffer : { + ], + buffers : [ + { type : "arraybuffer", byteLength : buffer.length, extras : { @@ -384,55 +391,59 @@ describe('combineNodes', function() { } } } - }, - meshes : { - meshA : { + ], + meshes : [ + { primitives : [ { attributes : { - NORMAL : 'normalAccessor', - POSITION : 'positionAccessor' + NORMAL : 1, + POSITION : 0 }, - indices : 'indicesAccessor' + indices : 2 } ] }, - meshB : { + { primitives : [ { attributes : { - NORMAL : 'normalAccessor', - POSITION : 'positionAccessor' + NORMAL : 1, + POSITION : 0 }, - indices : 'overlappedIndicesAccessor' + indices : 3 } ] } - }, - nodes : { - nodeA : { - children : ['nodeB', 'nodeC'] + ], + nodes : [ + { + children : [1, 2], + name : 'NodeA' }, - nodeB : { - meshes : ['meshA'], + { + mesh : 0, matrix : [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, - 1.0, 2.0, 3.0, 1.0] + 1.0, 2.0, 3.0, 1.0], + name : 'NodeB' }, - nodeC: { - meshes : ['meshB'] + { + mesh : 1, + name : 'NodeC' } - }, - scenes : { - scene : { - nodes : ['nodeA'] + ], + scenes : [ + { + nodes : [0] } - } + ] }; combineNodes(gltf); var nodes = gltf.nodes; - expect(nodes.nodeB).toBeDefined(); - expect(nodes.nodeC).toBeDefined(); + expect(nodes.length).toEqual(2); + expect(nodes[0].name).toEqual('NodeB'); + expect(nodes[1].name).toEqual('NodeC'); }); }); \ No newline at end of file diff --git a/specs/lib/convertDagToTreeSpec.js b/specs/lib/convertDagToTreeSpec.js index 24788d8b..91e7dbfe 100644 --- a/specs/lib/convertDagToTreeSpec.js +++ b/specs/lib/convertDagToTreeSpec.js @@ -44,9 +44,9 @@ describe('convertDagToTree', function() { convertDagToTree(dag); removePipelineExtras(dag); - expect(dag.nodes).toEqual({ - "A": {} - }); + expect(dag.nodes).toEqual([{ + name: "A" + }]); }); it('does not duplicate any nodes in the tree', function() { @@ -54,11 +54,18 @@ describe('convertDagToTree', function() { convertDagToTree(dag); removePipelineExtras(dag); - expect(dag.nodes).toEqual({ - "A": { "children": ["B", "C"] }, - "B": {}, - "C": {} - }); + expect(dag.nodes).toEqual([ + { + children: [1, 2], + name: 'A' + }, + { + name: 'B' + }, + { + name: 'C' + } + ]); }); it('duplicates one node', function() { @@ -66,11 +73,29 @@ describe('convertDagToTree', function() { convertDagToTree(dag); removePipelineExtras(dag); - expect(dag.nodes.D_1).toBeDefined(); - expect(dag.nodes.A.children).toEqual(["B", "C"]); - expect(dag.nodes.B.children).toEqual(["D"]); - expect(dag.nodes.C.children).toEqual(["D_1"]); - expect(dag.nodes.D.children).not.toBeDefined(); + expect(dag.nodes).toEqual([ + { + children: [ + 1, + 2 + ], + name: 'A' + }, { + children: [ + 3 + ], + name: 'B' + }, { + children: [ + 4 + ], + name: 'C' + }, { + name: 'D' + }, { + name: 'D' + } + ]); }); it('duplicates a subgraph', function() { @@ -78,23 +103,66 @@ describe('convertDagToTree', function() { convertDagToTree(dag); removePipelineExtras(dag); - - expect(dag.nodes.D_1).toBeDefined(); - expect(dag.nodes.E_1).toBeDefined(); - expect(dag.nodes.F_1).toBeDefined(); - expect(dag.nodes.G_1).toBeDefined(); - expect(dag.nodes.G_2).toBeDefined(); - expect(dag.nodes.G_3).toBeDefined(); - - expect(dag.nodes.A.children).toEqual(["B", "C"]); - expect(dag.nodes.B.children).toEqual(["D"]); - expect(dag.nodes.C.children).toEqual(["D_1"]); - expect(dag.nodes.D.children).toEqual(["E", "F"]); - expect(dag.nodes.D_1.children).toEqual(["E_1", "F_1"]); - expect(dag.nodes.E.children).toEqual(["G"]); - expect(dag.nodes.F.children).toEqual(["G_2"]); - expect(dag.nodes.E_1.children).toEqual(["G_1"]); - expect(dag.nodes.F_1.children).toEqual(["G_3"]); + + expect(dag.nodes).toEqual([ + { + children: [ + 1, + 2 + ], + name: 'A' + }, { + children: [ + 3 + ], + name: 'B' + }, { + children: [ + 7 + ], + name: 'C' + }, { + children: [ + 4, + 5 + ], + name: 'D' + }, { + children: [ + 6 + ], + name: 'E' + }, { + children: [ + 12 + ], + name: 'F' + }, { + name: 'G' + }, { + children: [ + 8, + 9 + ], + name: 'D' + }, { + children: [ + 10 + ], + name: 'E' + }, { + children: [ + 11 + ], + name: 'F' + }, { + name: 'G' + }, { + name: 'G' + }, { + name: 'G' + } + ]); }); it('converts a DAG with two roots', function() { @@ -103,20 +171,58 @@ describe('convertDagToTree', function() { convertDagToTree(dag); removePipelineExtras(dag); - expect(dag.nodes.D_1).toBeDefined(); - expect(dag.nodes.E_1).toBeDefined(); - expect(dag.nodes.F_1).toBeDefined(); - expect(dag.nodes.G_1).toBeDefined(); - expect(dag.nodes.G_2).toBeDefined(); - expect(dag.nodes.G_3).toBeDefined(); - - expect(dag.nodes.B.children).toEqual(["D"]); - expect(dag.nodes.C.children).toEqual(["D_1"]); - expect(dag.nodes.D.children).toEqual(["E", "F"]); - expect(dag.nodes.D_1.children).toEqual(["E_1", "F_1"]); - expect(dag.nodes.E.children).toEqual(["G"]); - expect(dag.nodes.F.children).toEqual(["G_1"]); - expect(dag.nodes.E_1.children).toEqual(["G_2"]); - expect(dag.nodes.F_1.children).toEqual(["G_3"]); + expect(dag.nodes).toEqual([ + { + children: [ + 2 + ], + name: 'B' + }, { + children: [ + 7 + ], + name: 'C' + }, { + children: [ + 3, + 4 + ], + name: 'D' + }, { + children: [ + 5 + ], + name: 'E' + }, { + children: [ + 6 + ], + name: 'F' + }, { + name: 'G' + }, { + name: 'G' + }, { + children: [ + 8, + 9 + ], + name: 'D' + }, { + children: [ + 10 + ], + name: 'E' + }, { + children: [ + 11 + ], + name: 'F' + }, { + name: 'G' + }, { + name: 'G' + } + ]); }); }); \ No newline at end of file From 29e21f20c7097216c7b05ae1182cccc1b0c22715 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 15 Feb 2017 16:00:56 -0500 Subject: [PATCH 27/47] More WIP --- lib/compressTextures.js | 82 +++++------ lib/loadGltfUris.js | 94 ++++++------ specs/data/combineObjects/fiveBox.gltf | 194 ++++++++++++------------- specs/lib/NodeHelpersSpec.js | 9 +- specs/lib/compressTexturesSpec.js | 15 +- 5 files changed, 198 insertions(+), 196 deletions(-) diff --git a/lib/compressTextures.js b/lib/compressTextures.js index 66a5335d..dc9f8db7 100644 --- a/lib/compressTextures.js +++ b/lib/compressTextures.js @@ -45,55 +45,53 @@ function compressTextures(gltf, options) { var promises = []; var images = gltf.images; - for (var imageId in images) { - if (images.hasOwnProperty(imageId)) { - var image = images[imageId]; - var pipelineExtras = image.extras._pipeline; - var compressedImages = {}; - var length = optionsArray.length; - for (var i = 0; i < length; ++i) { - var compressionOptions = optionsArray[i]; - var compressedType = compressionOptions.format; - if (compressedType.indexOf('crunch') >= 0) { - // crunch-dxt1, crunch-dxt5 require the s3tc extension and a crunch decoder - compressedType = 'crunch'; - } else if (compressedType.indexOf('dxt') >= 0) { - // dxt1, dxt3, dxt5 all require the s3tc extension - compressedType = 's3tc'; - } - var compressedImage = { - uri : undefined, - extras : { - _pipeline : { - source : undefined, - extension : undefined, - name : imageId + '-' + compressedType - } - } - }; - compressedImages[compressedType] = compressedImage; - promises.push(compressTexture(gltf, imageId, compressionOptions) - .then(replaceImage(compressedImage))); + var imagesLength = images.length; + for (var imageId = 0; imageId < imagesLength; imageId++) { + var image = images[imageId]; + var pipelineExtras = image.extras._pipeline; + var compressedImages = {}; + var length = optionsArray.length; + for (var i = 0; i < length; ++i) { + var compressionOptions = optionsArray[i]; + var compressedType = compressionOptions.format; + if (compressedType.indexOf('crunch') >= 0) { + // crunch-dxt1, crunch-dxt5 require the s3tc extension and a crunch decoder + compressedType = 'crunch'; + } else if (compressedType.indexOf('dxt') >= 0) { + // dxt1, dxt3, dxt5 all require the s3tc extension + compressedType = 's3tc'; } + var compressedImage = { + uri : undefined, + extras : { + _pipeline : { + source : undefined, + extension : undefined, + name : imageId + '-' + compressedType + } + } + }; + compressedImages[compressedType] = compressedImage; + promises.push(compressTexture(gltf, imageId, compressionOptions) + .then(replaceImage(compressedImage))); + } - image.extras.compressedImage3DTiles = compressedImages; + image.extras.compressedImage3DTiles = compressedImages; - // Set the default image to a 1x1 white png - image.uri = defaultImageUri; - pipelineExtras.source = Buffer.from(defaultImageUri.slice(22), 'base64'); - pipelineExtras.transparent = false; - pipelineExtras.extension = '.png'; - } + // Set the default image to a 1x1 white png + image.uri = defaultImageUri; + pipelineExtras.source = Buffer.from(defaultImageUri.slice(22), 'base64'); + pipelineExtras.transparent = false; + pipelineExtras.extension = '.png'; } // Edit samplers to disallow mip-mapping var samplers = gltf.samplers; - for (var samplerId in samplers) { - if (samplers.hasOwnProperty(samplerId)) { - var sampler = samplers[samplerId]; - if (sampler.minFilter !== WebGLConstants.NEAREST && sampler.minFilter !== WebGLConstants.LINEAR) { - sampler.minFilter = WebGLConstants.LINEAR; - } + var samplersLength = samplers.length; + for (var samplerId = 0; samplerId < samplersLength; samplerId++) { + var sampler = samplers[samplerId]; + if (sampler.minFilter !== WebGLConstants.NEAREST && sampler.minFilter !== WebGLConstants.LINEAR) { + sampler.minFilter = WebGLConstants.LINEAR; } } diff --git a/lib/loadGltfUris.js b/lib/loadGltfUris.js index 8a37b1db..5f50ce4b 100644 --- a/lib/loadGltfUris.js +++ b/lib/loadGltfUris.js @@ -36,13 +36,12 @@ function loadGltfUris(gltf, options) { // Read sources for compressed textures var images = gltf.images; - for (var imageId in images) { - if (images.hasOwnProperty(imageId)) { - var image = images[imageId]; - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - loadURIs.push(loadURI(compressedImages, 'images', basePath)); - } + var imagesLength = images.length; + for (var imageId = 0; imageId < imagesLength; imageId++) { + var image = images[imageId]; + if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { + var compressedImages = image.extras.compressedImage3DTiles; + loadURIs.push(loadURI(compressedImages, 'images', basePath)); } } @@ -61,51 +60,50 @@ function loadURI(objects, name, basePath) { //Iterate through each object and get a promise to load its uri var promises = []; if (defined(objects)) { - for (var id in objects) { - if (objects.hasOwnProperty(id)) { - var object = objects[id]; - object.extras = defaultValue(object.extras, {}); - object.extras._pipeline = defaultValue(object.extras._pipeline, {}); - if (defined(object.extras._pipeline.source) && !defined(object.uri)) { - object.uri = 'data:,'; - } - var uri = object.uri; - //Load the uri into the extras object based on the uri type - if (isDataUri(uri)) { - if (!defined(object.extras._pipeline.source)) { - var buffer = dataUriToBuffer(uri); - if (name === 'shaders') { - object.extras._pipeline.source = buffer.toString(); - } else { - object.extras._pipeline.source = buffer; - } - } - if (!defined(object.extras._pipeline.extension)) { - switch (name) { - case 'buffers': - object.extras._pipeline.extension = '.bin'; - break; - case 'images': - object.extras._pipeline.extension = getImageDataUriFormat(uri); - break; - case 'shaders': - object.extras._pipeline.extension = '.glsl'; - break; - } + var objectsLength = objects.length; + for (var i = 0; i < objectsLength; i++) { + var object = objects[i]; + object.extras = defaultValue(object.extras, {}); + object.extras._pipeline = defaultValue(object.extras._pipeline, {}); + if (defined(object.extras._pipeline.source) && !defined(object.uri)) { + object.uri = 'data:,'; + } + var uri = object.uri; + //Load the uri into the extras object based on the uri type + if (isDataUri(uri)) { + if (!defined(object.extras._pipeline.source)) { + var buffer = dataUriToBuffer(uri); + if (name === 'shaders') { + object.extras._pipeline.source = buffer.toString(); + } else { + object.extras._pipeline.source = buffer; } - if (name === 'images') { - promises.push(generateJimpImage(object)); + } + if (!defined(object.extras._pipeline.extension)) { + switch (name) { + case 'buffers': + object.extras._pipeline.extension = '.bin'; + break; + case 'images': + object.extras._pipeline.extension = getImageDataUriFormat(uri); + break; + case 'shaders': + object.extras._pipeline.extension = '.glsl'; + break; } - } else { - var uriPath = uri; - if (!path.isAbsolute(uriPath)) { - if (!defined(basePath)) { - throw new DeveloperError('glTF model references external files but no basePath is supplied'); - } - uriPath = path.join(basePath, uriPath); + } + if (name === 'images') { + promises.push(generateJimpImage(object)); + } + } else { + var uriPath = uri; + if (!path.isAbsolute(uriPath)) { + if (!defined(basePath)) { + throw new DeveloperError('glTF model references external files but no basePath is supplied'); } - promises.push(readFromFile(object, name, uriPath)); + uriPath = path.join(basePath, uriPath); } + promises.push(readFromFile(object, name, uriPath)); } } } diff --git a/specs/data/combineObjects/fiveBox.gltf b/specs/data/combineObjects/fiveBox.gltf index ee97716e..0c3c4f00 100644 --- a/specs/data/combineObjects/fiveBox.gltf +++ b/specs/data/combineObjects/fiveBox.gltf @@ -1,15 +1,15 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, "type": "SCALAR" }, - "accessor_23": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -26,16 +26,16 @@ ], "type": "VEC3" }, - "accessor_29": { - "bufferView": "bufferView_64", + { + "bufferView": 2, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 384, "type": "SCALAR" }, - "accessor_31": { - "bufferView": "bufferView_65", + { + "bufferView": 3, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -52,16 +52,16 @@ ], "type": "VEC3" }, - "accessor_56": { - "bufferView": "bufferView_64", + { + "bufferView": 2, "byteOffset": 768, "byteStride": 0, "componentType": 5123, "count": 132, "type": "SCALAR" }, - "accessor_58": { - "bufferView": "bufferView_65", + { + "bufferView": 3, "byteOffset": 7168, "byteStride": 12, "componentType": 5126, @@ -78,16 +78,16 @@ ], "type": "VEC3" }, - "accessor_29_1": { - "bufferView": "bufferView_64_1", + { + "bufferView": 4, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 384, "type": "SCALAR" }, - "accessor_31_1": { - "bufferView": "bufferView_65_1", + { + "bufferView": 5, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -104,16 +104,16 @@ ], "type": "VEC3" }, - "accessor_56_1": { - "bufferView": "bufferView_64_1", + { + "bufferView": 4, "byteOffset": 768, "byteStride": 0, "componentType": 5123, "count": 132, "type": "SCALAR" }, - "accessor_58_1": { - "bufferView": "bufferView_65_1", + { + "bufferView": 5, "byteOffset": 7168, "byteStride": 12, "componentType": 5126, @@ -130,7 +130,7 @@ ], "type": "VEC3" } - }, + ], "asset": { "generator": "collada2gltf@", "premultipliedAlpha": true, @@ -138,62 +138,62 @@ "api": "WebGL", "version": "1.0.2" }, - "version": 1 + "version": "2.0" }, - "bufferViews": { - "bufferView_29": { - "buffer": "box", + "bufferViews": [ + { + "buffer": 0, "byteLength": 72, "byteOffset": 0, "target": 34963 }, - "bufferView_30": { - "buffer": "box", + { + "buffer": 0, "byteLength": 768, "byteOffset": 72, "target": 34962 }, - "bufferView_64": { - "buffer": "input", + { + "buffer": 1, "byteLength": 1032, "byteOffset": 104, "target": 34963 }, - "bufferView_65": { - "buffer": "input", + { + "buffer": 1, "byteLength": 10240, "byteOffset": 1136, "target": 34962 }, - "bufferView_64_1": { - "buffer": "input", + { + "buffer": 1, "byteLength": 1032, "byteOffset": 104, "target": 34963 }, - "bufferView_65_1": { - "buffer": "input", + { + "buffer": 1, "byteLength": 10240, "byteOffset": 1136, "target": 34962 } - }, - "buffers": { - "box": { + ], + "buffers": [ + { "byteLength": 840, "type": "arraybuffer", "uri": "data:application/octet-stream;base64,AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUAAAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPgAAAAAAAIA+oKqqPgAAAD8AAAAAAAAAP6Cqqj4AAIA+oKqqPgAAAACgqqo+AACAPrCqKj8AAAAAsKoqPwAAAD+gqqo+AACAPqCqqj4AAAA/sKoqPwAAgD6wqio/AABAP6Cqqj4AAAA/oKqqPgAAQD+wqio/AAAAP7CqKj8AAIA/oKqqPgAAQD+gqqo+AACAP7CqKj8AAEA/sKoqPwAAgD4AAIA/AAAAPwAAgD8AAIA+sKoqPwAAAD+wqio/" }, - "input": { + { "byteLength": 11376, "type": "arraybuffer", "uri": "data:application/octet-stream;base64,AACgPwAAIEAAAAAAAAAAAAAAAAAAAIA/AACAvwAAAIAAAACAEnVFrgAAAAAAAKA/AAAgQEdVbUAAAAAAAAAAAAAAAAAAAAAArkchQAAAAAAAAAAArkchQAAAAAAAAAAAAAAAAAAAAAAAAAEAAgACAAMAAAAEAAUABgAGAAcABAAIAAkACgAKAAsACAAMAA0ADgAOAA8ADAAQABEAEgASABMAEAAUABUAFgAWABcAFAAYABkAGgAaABsAGAAcAB0AHgAeAB8AHAAgACEAIgAiACMAIAAkACUAJgAmACcAJAAoACkAKgAqACsAKAAsAC0ALgAuAC8ALAAwADEAMgAyADMAMAA0ADUANgA2ADcANAA4ADkAOgA6ADsAOAA8AD0APgA+AD8APABAAEEAQgBCAEMAQABEAEUARgBGAEcARABIAEkASgBKAEsASABMAE0ATgBOAE8ATABQAFEAUgBSAFMAUABUAFUAVgBWAFcAVABYAFkAWgBaAFsAWABcAF0AXgBeAF8AXABgAGEAYgBiAGMAYABkAGUAZgBmAGcAZABoAGkAagBqAGsAaABsAG0AbgBuAG8AbABwAHEAcgByAHMAcAB0AHUAdgB2AHcAdAB4AHkAegB6AHsAeAB8AH0AfgB+AH8AfACAAIEAggCCAIMAgACEAIUAhgCGAIcAhACIAIkAigCKAIsAiACMAI0AjgCOAI8AjACQAJEAkgCSAJMAkACUAJUAlgCWAJcAlACYAJkAmgCaAJsAmACcAJ0AngCeAJ8AnAApACgAQwBDAEIAKQAFAAQAKwArACoABQBVAFQABwAHAAYAVQBBAEAAVwBXAFYAQQCgAKEAogCiAKMAoACkAKUApgCmAKcApACoAKkAqgCqAKsAqACsAK0ArgCuAK8ArACwALEAsgCyALMAsAC0ALUAtgC2ALcAtAC4ALAAswCzALkAuAC6ALQAtwC3ALsAugC8ALgAuQC5AL0AvACxALoAuwC7ALIAsQC+ALwAvQC9AL8AvgC1AL4AvwC/ALYAtQDAAMEAwgDCAMMAwADEAMUAxgDGAMcAxADIAMkAygDKAMsAyADMAM0AzgDOAM8AzADQANEA0gDSANMA0ADUANUA1gDWANcA1ADYANkA2gDaANsA2ADcAN0A3gDeAN8A3AAAAAEAAgACAAMAAAAEAAUABgAGAAcABAAIAAkACgAKAAsACAAMAA0ADgAOAA8ADAAQABEAEgASABMAEAAUABUAFgAWABcAFAAYABkAGgAaABsAGAAcAB0AHgAeAB8AHAAgACEAIgAiACMAIAAkACUAJgAmACcAJAAoACkAKgAqACsAKAAsAC0ALgAuAC8ALAAwADEAMgAzADQANQA2ADcAOAA5ADoAOwA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBKAEsASABMAE0ATgBOAE8ATABQAFEAUgBSAFMAUABUAFUAVgBWAFcAVABYAFkAWgBaAFsAWABcAF0AXgBeAF8AXADqJrG+yXb+viGwsj7qJrE+yXb+viGwsj6oGbI+AAAAv3YbtD6oGbK+AAAAv3YbtD52G7S+AAAAv6gZsr7/6f6+AAAAv8hg/b7IYP2+AAAAv//p/r6oGbK+AAAAv3YbtL4hsLK+yXb+Puomsb4hsLK+yXb+vuomsb7qJrG+yXb+viGwsr7qJrG+yXb+PiGwsr4hsLI+yXb+vuomsT4hsLI+yXb+vuomsb52G7Q+AAAAv6gZsr52G7Q+AAAAv6gZsj52G7S+AAAAv6gZsj52G7S+AAAAv6gZsr4hsLK+yXb+vuomsb4hsLK+yXb+vuomsT7Jdv4+yXb+vgAAAD/Jdv6+yXb+vgAAAD/IYP2+AAAAv//p/j7IYP0+AAAAv//p/j7qJrE+yXb+viGwsr7qJrG+yXb+viGwsr6oGbK+AAAAv3YbtL6oGbI+AAAAv3YbtL7qJrE+yXb+PiGwsj7qJrG+yXb+PiGwsj6oGbK+AAAAP3YbtD6oGbI+AAAAP3YbtD4AAAC/yXb+vsl2/j4AAAC/yXb+vsl2/r7/6f6+AAAAv8hg/b7/6f6+AAAAv8hg/T4AAAA/yXb+vsl2/r4AAAA/yXb+vsl2/j7/6f4+AAAAv8hg/T7/6f4+AAAAv8hg/b6oGbK+AAAAv3YbtD7IYP2+AAAAv//p/j7/6f6+AAAAv8hg/T52G7S+AAAAv6gZsj4hsLI+yXb+Puomsb4hsLI+yXb+PuomsT52G7Q+AAAAP6gZsj52G7Q+AAAAP6gZsr4hsLK+yXb+PuomsT4hsLK+yXb+Puomsb52G7S+AAAAP6gZsr52G7S+AAAAP6gZsj7Jdv6+yXb+vgAAAL/Jdv4+yXb+vgAAAL/IYP0+AAAAv//p/r7IYP2+AAAAv//p/r7qJrG+yXb+PiGwsj7qJrG+yXb+viGwsj4hsLK+yXb+vuomsT4hsLK+yXb+PuomsT7IYP0+AAAAP//p/j7IYP2+AAAAP//p/j7Jdv6+yXb+PgAAAD/Jdv4+yXb+PgAAAD92G7Q+AAAAv6gZsj7/6f4+AAAAv8hg/T7IYP0+AAAAv//p/j6oGbI+AAAAv3YbtD7qJrG+yXb+PiGwsr7qJrE+yXb+PiGwsr6oGbI+AAAAP3YbtL6oGbK+AAAAP3YbtL7qJrE+yXb+viGwsj7qJrE+yXb+PiGwsj4hsLI+yXb+PuomsT4hsLI+yXb+vuomsT7/6f4+AAAAP8hg/b7/6f4+AAAAP8hg/T4AAAA/yXb+Psl2/j4AAAA/yXb+Psl2/r7/6f6+AAAAP8hg/T7/6f6+AAAAP8hg/b4AAAC/yXb+Psl2/r4AAAC/yXb+Psl2/j6oGbI+AAAAv3YbtL7IYP0+AAAAv//p/r7/6f4+AAAAv8hg/b52G7Q+AAAAv6gZsr4hsLI+yXb+vuomsb4hsLI+yXb+Puomsb7qJrE+yXb+PiGwsr7qJrE+yXb+viGwsr7IYP2+AAAAP//p/r7IYP0+AAAAP//p/r7Jdv4+yXb+PgAAAL/Jdv6+yXb+PgAAAL/Jdv6+yXb+vgAAAL/IYP2+AAAAv//p/r7/6f6+AAAAv8hg/b4AAAC/yXb+vsl2/r4AAAA/yXb+vsl2/r7/6f4+AAAAv8hg/b7IYP0+AAAAv//p/r7Jdv4+yXb+vgAAAL/Jdv4+yXb+vgAAAD/IYP0+AAAAv//p/j7/6f4+AAAAv8hg/T4AAAA/yXb+vsl2/j4AAAC/yXb+vsl2/j7/6f6+AAAAv8hg/T7IYP2+AAAAv//p/j7Jdv6+yXb+vgAAAD8AAAC/yXb+Psl2/r7/6f6+AAAAP8hg/b7IYP2+AAAAP//p/r7Jdv6+yXb+PgAAAL/IYP0+AAAAP//p/r7/6f4+AAAAP8hg/b4AAAA/yXb+Psl2/r7Jdv4+yXb+PgAAAL//6f4+AAAAP8hg/T7IYP0+AAAAP//p/j7Jdv4+yXb+PgAAAD8AAAA/yXb+Psl2/j7IYP2+AAAAP//p/j7/6f6+AAAAP8hg/T4AAAC/yXb+Psl2/j7Jdv6+yXb+PgAAAD+oGbK+AAAAv3YbtL7qJrG+yXb+viGwsr4hsLK+yXb+vuomsb52G7S+AAAAv6gZsr52G7Q+AAAAv6gZsr4hsLI+yXb+vuomsb7qJrE+yXb+viGwsr6oGbI+AAAAv3YbtL6oGbI+AAAAv3YbtD7qJrE+yXb+viGwsj4hsLI+yXb+vuomsT52G7Q+AAAAv6gZsj52G7S+AAAAv6gZsj4hsLK+yXb+vuomsT7qJrG+yXb+viGwsj6oGbK+AAAAv3YbtD52G7S+AAAAP6gZsr4hsLK+yXb+Puomsb7qJrG+yXb+PiGwsr6oGbK+AAAAP3YbtL6oGbI+AAAAP3YbtL7qJrE+yXb+PiGwsr4hsLI+yXb+Puomsb52G7Q+AAAAP6gZsr52G7Q+AAAAP6gZsj4hsLI+yXb+PuomsT7qJrE+yXb+PiGwsj6oGbI+AAAAP3YbtD6oGbK+AAAAP3YbtD7qJrG+yXb+PiGwsj4hsLK+yXb+PuomsT52G7S+AAAAP6gZsj4hsLK+yXb+PuomsT4hsLK+yXb+vuomsT4hsLK+yXb+vuomsb4hsLK+yXb+Puomsb7qJrG+yXb+PiGwsr7qJrG+yXb+viGwsr7qJrE+yXb+viGwsr7qJrE+yXb+PiGwsr4hsLI+yXb+Puomsb4hsLI+yXb+vuomsb4hsLI+yXb+vuomsT4hsLI+yXb+PuomsT7qJrE+yXb+PiGwsj7qJrE+yXb+viGwsj7qJrG+yXb+viGwsj7qJrG+yXb+PiGwsj7/6f4+AAAAP8hg/b7IYP0+AAAAP//p/r6oGbI+AAAAP3YbtL52G7Q+AAAAP6gZsr7/6f6+AAAAP8hg/b7/6f6+AAAAP8hg/T52G7S+AAAAP6gZsj52G7S+AAAAP6gZsr7/6f4+AAAAP8hg/T52G7Q+AAAAP6gZsj7IYP2+AAAAP//p/r6oGbK+AAAAP3YbtL7IYP0+AAAAP//p/j6oGbI+AAAAP3YbtD7IYP2+AAAAP//p/j6oGbK+AAAAP3YbtD4AAAC/yXb+Psl2/j4AAAC/yXb+Psl2/r4AAAC/yXb+vsl2/r4AAAC/yXb+vsl2/j7Jdv6+yXb+PgAAAL/Jdv4+yXb+PgAAAL/Jdv4+yXb+vgAAAL/Jdv6+yXb+vgAAAL/Jdv6+yXb+PgAAAD8AAAC/yXb+Psl2/j4AAAC/yXb+vsl2/j7Jdv6+yXb+vgAAAD8AAAA/yXb+Psl2/r4AAAA/yXb+Psl2/j4AAAA/yXb+vsl2/j4AAAA/yXb+vsl2/r7Jdv4+yXb+PgAAAD/Jdv6+yXb+PgAAAD/Jdv6+yXb+vgAAAD/Jdv4+yXb+vgAAAD8AAAC/yXb+Psl2/r7Jdv6+yXb+PgAAAL/Jdv6+yXb+vgAAAL8AAAC/yXb+vsl2/r4AAAA/yXb+Psl2/j7Jdv4+yXb+PgAAAD/Jdv4+yXb+vgAAAD8AAAA/yXb+vsl2/j7Jdv4+yXb+PgAAAL8AAAA/yXb+Psl2/r4AAAA/yXb+vsl2/r7Jdv4+yXb+vgAAAL8AAAAAurgtv7cIPL8AAAAAurgtv7cIPL8AAAAAurgtv7cIPL8AAAAAurgtv7cIPL8AAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAAAAAACAvwAAAID3BDU/AAAAAPcENT/3BDU/AAAAAPcENT/3BDU/AAAAAPcENT/3BDU/AAAAAPcENT+3CDy/urgtvwAAAIC3CDy/urgtvwAAAIC3CDy/urgtvwAAAIC3CDy/urgtvwAAAIC3CDw/urgtvwAAAAC3CDw/urgtvwAAAAC3CDw/urgtvwAAAAC3CDw/urgtvwAAAAAAAAAAaM0Tv9EFUT8AAAAAaM0Tv9EFUT8AAAAAaM0Tv9EFUT8AAAAAaM0Tv9EFUT8AAAAAurgtv7cIPD8AAAAAurgtv7cIPD8AAAAAurgtv7cIPD8AAAAAurgtv7cIPD8AAAAAurgtP7cIPL8AAAAAurgtP7cIPL8AAAAAurgtP7cIPL8AAAAAurgtP7cIPL/RBVG/aM0TvwAAAIDRBVG/aM0TvwAAAIDRBVG/aM0TvwAAAIDRBVG/aM0TvwAAAIDRBVE/aM0TvwAAAADRBVE/aM0TvwAAAADRBVE/aM0TvwAAAADRBVE/aM0TvwAAAAAAAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAAAAAACAvwAAAIC3CDy/urgtPwAAAAC3CDy/urgtPwAAAAC3CDy/urgtPwAAAAC3CDy/urgtPwAAAAC3CDw/urgtPwAAAAC3CDw/urgtPwAAAAC3CDw/urgtPwAAAAC3CDw/urgtPwAAAAAAAAAAaM0Tv9EFUb8AAAAAaM0Tv9EFUb8AAAAAaM0Tv9EFUb8AAAAAaM0Tv9EFUb/3BDU/AAAAAPcENb/3BDU/AAAAAPcENb/3BDU/AAAAAPcENb/3BDU/AAAAAPcENb8AAAAAaM0TP9EFUT8AAAAAaM0TP9EFUT8AAAAAaM0TP9EFUT8AAAAAaM0TP9EFUT8AAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAACAurgtP7cIPD8AAACAurgtP7cIPD8AAACAurgtP7cIPD8AAACAurgtP7cIPD/3BDW/AAAAAPcENb/3BDW/AAAAAPcENb/3BDW/AAAAAPcENb/3BDW/AAAAAPcENb/RBVE/aM0TPwAAAIDRBVE/aM0TPwAAAIDRBVE/aM0TPwAAAIDRBVE/aM0TPwAAAIDRBVG/aM0TPwAAAADRBVG/aM0TPwAAAADRBVG/aM0TPwAAAADRBVG/aM0TPwAAAAAAAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAAAAAACAvwAAAIAAAAAAAACAvwAAAID3BDW/AAAAAPcENT/3BDW/AAAAAPcENT/3BDW/AAAAAPcENT/3BDW/AAAAAPcENT8AAAAAaM0TP9EFUb8AAAAAaM0TP9EFUb8AAAAAaM0TP9EFUb8AAAAAaM0TP9EFUb+9//++GAU1v73//769//++GAU1v73//769//++GAU1v73//769//++GAU1v73//769//8+GAU1v73//769//8+GAU1v73//769//8+GAU1v73//769//8+GAU1v73//769//8+GAU1v73//z69//8+GAU1v73//z69//8+GAU1v73//z69//8+GAU1v73//z69//++GAU1v73//z69//++GAU1v73//z69//++GAU1v73//z69//++GAU1v73//z69//++GAU1P73//769//++GAU1P73//769//++GAU1P73//769//++GAU1P73//769//8+GAU1P73//769//8+GAU1P73//769//8+GAU1P73//769//8+GAU1P73//769//8+GAU1P73//z69//8+GAU1P73//z69//8+GAU1P73//z69//8+GAU1P73//z69//++GAU1P73//z69//++GAU1P73//z69//++GAU1P73//z69//++GAU1P73//z4/xvQ+lJ88vz/G9D4/xvQ+lJ88vz/G9D4/xvQ+lJ88vz/G9D4/xvQ+lJ88vz/G9D4/xvS+lJ88vz/G9D4/xvS+lJ88vz/G9D4/xvS+lJ88vz/G9D4/xvS+lJ88vz/G9D4/xvS+lJ88vz/G9L4/xvS+lJ88vz/G9L4/xvS+lJ88vz/G9L4/xvS+lJ88vz/G9L4/xvQ+lJ88vz/G9L4/xvQ+lJ88vz/G9L4/xvQ+lJ88vz/G9L4/xvQ+lJ88vz/G9L4/xvQ+lJ88Pz/G9D4/xvQ+lJ88Pz/G9D4/xvQ+lJ88Pz/G9D4/xvQ+lJ88Pz/G9D4/xvS+lJ88Pz/G9D4/xvS+lJ88Pz/G9D4/xvS+lJ88Pz/G9D4/xvS+lJ88Pz/G9D4/xvS+lJ88Pz/G9L4/xvS+lJ88Pz/G9L4/xvS+lJ88Pz/G9L4/xvS+lJ88Pz/G9L4/xvQ+lJ88Pz/G9L4/xvQ+lJ88Pz/G9L4/xvQ+lJ88Pz/G9L4/xvQ+lJ88Pz/G9L4AAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAACAAAAAgAAAgL8AAACAAAAAgAAAgL8AAACAAAAAgAAAgL8AAACAAAAAgAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAACAAAAAgAAAgL8AAACAAAAAgAAAgL8AAACAAAAAgAAAgL8AAACAAAAAgAAAgL/3BDW/AAAAAPcENT/3BDW/AAAAAPcENT/3BDW/AAAAAPcENT/3BDW/AAAAAPcENT8AAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/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" } - }, - "materials": { - "Effect_inner": { + ], + "materials": [ + { "name": "inner", - "technique": "technique0", + "technique": 0, "values": { "diffuse": [ 0.800000011920929, @@ -210,9 +210,9 @@ ] } }, - "Effect_outer": { + { "name": "outer", - "technique": "technique0", + "technique": 0, "values": { "diffuse": [ 0.3016040027141571, @@ -229,9 +229,9 @@ ] } }, - "Effect_Red": { + { "name": "Red", - "technique": "technique0", + "technique": 0, "values": { "diffuse": [ 0.8, @@ -248,56 +248,56 @@ ] } } - }, - "meshes": { - "meshTest": { + ], + "meshes": [ + { "name": "box", "primitives": [ { "attributes": { - "POSITION": "accessor_58" + "POSITION": 5 }, - "indices": "accessor_56", - "material": "Effect_outer", + "indices": 4, + "material": 0, "mode": 4 }, { "attributes": { - "POSITION": "accessor_31" + "POSITION": 3 }, - "indices": "accessor_29", - "material": "Effect_outer", + "indices": 2, + "material": 0, "mode": 4 }, { "attributes": { - "POSITION": "accessor_58_1" + "POSITION": 9 }, - "indices": "accessor_56_1", - "material": "Effect_inner", + "indices": 8, + "material": 1, "mode": 4 }, { "attributes": { - "POSITION": "accessor_31_1" + "POSITION": 7 }, - "indices": "accessor_29_1", - "material": "Effect_inner", + "indices": 6, + "material": 1, "mode": 4 }, { "attributes": { - "POSITION": "accessor_23" + "POSITION": 1 }, - "indices": "accessor_21", - "material": "Effect_Red", + "indices": 0, + "material": 2, "mode": 4 } ] } - }, - "nodes": { - "Camera-camera002Node": { + ], + "nodes": [ + { "camera": "", "children": [], "matrix": [ @@ -320,7 +320,7 @@ ], "name": "Camera" }, - "Geometry-mesh019Node": { + { "children": [], "matrix": [ 1, @@ -340,12 +340,10 @@ 0, 1 ], - "meshes": [ - "meshTest" - ], + "mesh": 0, "name": "box" }, - "Light-sunLight011Node": { + { "children": [], "matrix": [ 0.7071067690849304, @@ -367,7 +365,7 @@ ], "name": "Directional_Light" }, - "polyRender005": { + { "children": [], "matrix": [ 1, @@ -389,41 +387,41 @@ ], "name": "Render" } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position" ], - "fragmentShader": "input0FS", - "vertexShader": "input0VS" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "polyRender005", - "Geometry-mesh019Node", - "Camera-camera002Node", - "Light-sunLight011Node" + 3, + 1, + 0, + 2 ] } - }, - "shaders": { - "input0FS": { + ], + "shaders": [ + { "type": 35632, "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Owp2YXJ5aW5nIHZlYzMgdl9ub3JtYWw7CnVuaWZvcm0gdmVjNCB1X2RpZmZ1c2U7CnVuaWZvcm0gdmVjNCB1X3NwZWN1bGFyOwp1bmlmb3JtIGZsb2F0IHVfc2hpbmluZXNzOwp1bmlmb3JtIHZlYzMgdV9saWdodDBDb2xvcjsKdmFyeWluZyB2ZWMzIHZfbGlnaHQxRGlyZWN0aW9uOwp2YXJ5aW5nIHZlYzMgdl9wb3NpdGlvbjsKdW5pZm9ybSB2ZWMzIHVfbGlnaHQxQ29sb3I7CnZvaWQgbWFpbih2b2lkKSB7CnZlYzMgbm9ybWFsID0gbm9ybWFsaXplKHZfbm9ybWFsKTsKdmVjNCBjb2xvciA9IHZlYzQoMC4sIDAuLCAwLiwgMC4pOwp2ZWM0IGRpZmZ1c2UgPSB2ZWM0KDAuLCAwLiwgMC4sIDEuKTsKdmVjMyBkaWZmdXNlTGlnaHQgPSB2ZWMzKDAuLCAwLiwgMC4pOwp2ZWM0IHNwZWN1bGFyOwpkaWZmdXNlID0gdV9kaWZmdXNlOwpzcGVjdWxhciA9IHVfc3BlY3VsYXI7CnZlYzMgc3BlY3VsYXJMaWdodCA9IHZlYzMoMC4sIDAuLCAwLik7CnZlYzMgYW1iaWVudExpZ2h0ID0gdmVjMygwLiwgMC4sIDAuKTsKewphbWJpZW50TGlnaHQgKz0gdV9saWdodDBDb2xvcjsKfQp7CmZsb2F0IHNwZWN1bGFySW50ZW5zaXR5ID0gMC47CmZsb2F0IGF0dGVudWF0aW9uID0gMS4wOwp2ZWMzIGwgPSBub3JtYWxpemUodl9saWdodDFEaXJlY3Rpb24pOwp2ZWMzIHZpZXdEaXIgPSAtbm9ybWFsaXplKHZfcG9zaXRpb24pOwpmbG9hdCBwaG9uZ1Rlcm0gPSBtYXgoMC4wLCBkb3QocmVmbGVjdCgtbCxub3JtYWwpLCB2aWV3RGlyKSk7CnNwZWN1bGFySW50ZW5zaXR5ID0gbWF4KDAuLCBwb3cocGhvbmdUZXJtICwgdV9zaGluaW5lc3MpKSAqIGF0dGVudWF0aW9uOwpzcGVjdWxhckxpZ2h0ICs9IHVfbGlnaHQxQ29sb3IgKiBzcGVjdWxhckludGVuc2l0eTsKZGlmZnVzZUxpZ2h0ICs9IHVfbGlnaHQxQ29sb3IgKiBtYXgoZG90KG5vcm1hbCxsKSwgMC4pICogYXR0ZW51YXRpb247Cn0Kc3BlY3VsYXIueHl6ICo9IHNwZWN1bGFyTGlnaHQ7CmNvbG9yLnh5eiArPSBzcGVjdWxhci54eXo7CmRpZmZ1c2UueHl6ICo9IGRpZmZ1c2VMaWdodDsKY29sb3IueHl6ICs9IGRpZmZ1c2UueHl6Owpjb2xvciA9IHZlYzQoY29sb3IucmdiICogZGlmZnVzZS5hLCBkaWZmdXNlLmEpOwpnbF9GcmFnQ29sb3IgPSBjb2xvcjsKfQo=" }, - "input0VS": { + { "type": 35633, "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0OwphdHRyaWJ1dGUgdmVjMyBhX3Bvc2l0aW9uOwphdHRyaWJ1dGUgdmVjMyBhX25vcm1hbDsKdmFyeWluZyB2ZWMzIHZfbm9ybWFsOwp1bmlmb3JtIG1hdDMgdV9ub3JtYWxNYXRyaXg7CnVuaWZvcm0gbWF0NCB1X21vZGVsVmlld01hdHJpeDsKdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsKdmFyeWluZyB2ZWMzIHZfbGlnaHQxRGlyZWN0aW9uOwp2YXJ5aW5nIHZlYzMgdl9wb3NpdGlvbjsKdW5pZm9ybSBtYXQ0IHVfbGlnaHQxVHJhbnNmb3JtOwp2b2lkIG1haW4odm9pZCkgewp2ZWM0IHBvcyA9IHVfbW9kZWxWaWV3TWF0cml4ICogdmVjNChhX3Bvc2l0aW9uLDEuMCk7CnZfbm9ybWFsID0gdV9ub3JtYWxNYXRyaXggKiBhX25vcm1hbDsKdl9wb3NpdGlvbiA9IHBvcy54eXo7CnZfbGlnaHQxRGlyZWN0aW9uID0gbWF0Myh1X2xpZ2h0MVRyYW5zZm9ybSkgKiB2ZWMzKDAuLDAuLDEuKTsKZ2xfUG9zaXRpb24gPSB1X3Byb2plY3Rpb25NYXRyaXggKiBwb3M7Cn0K" } - }, + ], "skins": {}, - "techniques": { - "technique0": { + "techniques": [ + { "attributes": { "a_normal": "normal", "a_position": "position" @@ -449,7 +447,7 @@ ] }, "light1Transform": { - "node": "Light-sunLight011Node", + "node": 2, "semantic": "MODELVIEW", "type": 35676 }, @@ -480,7 +478,7 @@ "type": 35666 } }, - "program": "program_0", + "program": 0, "states": { "enable": [ 2929, @@ -499,5 +497,5 @@ "u_specular": "specular" } } - } + ] } \ No newline at end of file diff --git a/specs/lib/NodeHelpersSpec.js b/specs/lib/NodeHelpersSpec.js index a680c45e..5a81082e 100644 --- a/specs/lib/NodeHelpersSpec.js +++ b/specs/lib/NodeHelpersSpec.js @@ -180,6 +180,7 @@ describe('NodeHelpers', function() { fsReadFile(fiveBoxPath) .then(function(data) { var gltf = JSON.parse(data); + var materials = gltf.materials; var scene = gltf.scenes[gltf.scene]; var functionParameters = { @@ -197,10 +198,10 @@ describe('NodeHelpers', function() { NodeHelpers.forEachPrimitiveInScene(gltf, scene, primitiveFunction, functionParameters); expect(functionParameters.numberPrimitives).toEqual(5); - expect(functionParameters.primitiveMeshIDs[0]).toEqual('meshTest_0'); - expect(functionParameters.primitiveMeshIDs[4]).toEqual('meshTest_4'); - expect(functionParameters.materialIDs[0]).toEqual('Effect_outer'); - expect(functionParameters.materialIDs[2]).toEqual('Effect_inner'); + expect(functionParameters.primitiveMeshIDs[0]).toEqual('0_0'); + expect(functionParameters.primitiveMeshIDs[4]).toEqual('0_4'); + expect(materials[functionParameters.materialIDs[0]].name).toEqual('inner'); + expect(materials[functionParameters.materialIDs[2]].name).toEqual('outer'); done(); }) diff --git a/specs/lib/compressTexturesSpec.js b/specs/lib/compressTexturesSpec.js index bcf256f6..e9898f25 100644 --- a/specs/lib/compressTexturesSpec.js +++ b/specs/lib/compressTexturesSpec.js @@ -6,10 +6,12 @@ var dataUriToBuffer = require('data-uri-to-buffer'); var fsExtra = require('fs-extra'); var path = require('path'); var Promise = require('bluebird'); +var addDefaults = require('../../lib/addDefaults'); +var addPipelineExtras = require('../../lib/addPipelineExtras'); var compressTexture = require('../../lib/compressTexture'); var compressTextures = require('../../lib/compressTextures'); var directoryExists = require('../../lib/directoryExists'); -var Pipeline = require('../../lib/Pipeline'); +var loadGltfUris = require('../../lib/loadGltfUris'); var readGltf = require('../../lib/readGltf'); var fsExtraReadJson = Promise.promisify(fsExtra.readJson); @@ -34,7 +36,7 @@ var defaultImageUri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQ function compressGltfTexture(gltfPath, imagePath, options) { return fsExtraReadJson(gltfPath) .then(function(gltf) { - var image = gltf.images.Image0001; + var image = gltf.images[0]; if (defined(imagePath)) { image.uri = imagePath; } @@ -42,7 +44,12 @@ function compressGltfTexture(gltfPath, imagePath, options) { textureCompressionOptions : options, basePath : basePath }; - return Pipeline.processJSON(gltf, pipelineOptions) + addPipelineExtras(gltf); + addDefaults(gltf); + return loadGltfUris(gltf, pipelineOptions) + .then(function(gltf) { + return compressTextures(gltf, options); + }) .then(function(gltf) { // Return the first compressed image var compressedImages = image.extras.compressedImage3DTiles; @@ -109,7 +116,7 @@ describe('compressTextures', function() { spyOn(console, 'log'); }); - it('compresses external jpg', function(done) { + fit('compresses external jpg', function(done) { expect(verifyKTX(gltfPath, jpgPath, etc1Compression, etc1Format), done).toResolve(); }); From 9ad94f373ac71bd28d08e7827ab1a7659a363748 Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Fri, 17 Feb 2017 15:44:48 -0500 Subject: [PATCH 28/47] Bulk WIP changes for traversal --- lib/ForEach.js | 185 +++ lib/Pipeline.js | 12 +- lib/Remove.js | 284 ++++ lib/RemoveUnusedProperties.js | 561 ++++---- lib/findUsedIds.js | 19 +- lib/isTexture.js | 17 + lib/loadGltfUris.js | 117 +- lib/writeGltf.js | 21 +- lib/writeSource.js | 68 +- .../CesiumTexturedBoxTestEmbedded.gltf | 153 +-- specs/lib/RemoveUnusedPropertiesSpec.js | 1203 +++++++---------- specs/lib/compressTexturesSpec.js | 10 +- specs/lib/loadBufferUrisSpec.js | 56 +- specs/lib/loadImageUrisSpec.js | 80 +- specs/lib/loadShaderUrisSpec.js | 65 +- specs/lib/writeBuffersSpec.js | 27 +- specs/lib/writeImagesSpec.js | 31 +- specs/lib/writeShadersSpec.js | 26 +- 18 files changed, 1544 insertions(+), 1391 deletions(-) create mode 100644 lib/ForEach.js create mode 100644 lib/Remove.js create mode 100644 lib/isTexture.js diff --git a/lib/ForEach.js b/lib/ForEach.js new file mode 100644 index 00000000..3dbbd652 --- /dev/null +++ b/lib/ForEach.js @@ -0,0 +1,185 @@ +'use strict'; +var Cesium = require('cesium'); + +var defaultValue = Cesium.defaultValue; +var defined = Cesium.defined; + +module.exports = ForEach; + + +/** + * Contains traversal functions for processing elements of the glTF hierarchy. + * @constructor + */ +function ForEach() {} + +ForEach.arrayOfObjects = function(arrayOfObjects, handler) { + for (var i = 0; i < arrayOfObjects.length; i++) { + var object = arrayOfObjects[i]; + var offset = defaultValue(handler(i, object), 0); + i += offset; + } +}; + +ForEach.topLevel = function(gltf, name, handler) { + var arrayOfObjects = gltf[name]; + if (defined(arrayOfObjects)) { + ForEach.arrayOfObjects(arrayOfObjects, handler); + } +}; + +ForEach.accessor = function(gltf, handler) { + ForEach.topLevel(gltf, 'accessors', handler); +}; + +ForEach.animation = function(gltf, handler) { + ForEach.topLevel(gltf, 'animations', handler); +}; + +ForEach.animationSamplers = function(animation, handler) { + var samplers = animation.samplers; + if (defined(samplers)) { + ForEach.arrayOfObjects(samplers, handler); + } +}; + +ForEach.buffer = function(gltf, handler) { + ForEach.topLevel(gltf, 'buffers', handler); +}; + +ForEach.bufferView = function(gltf, handler) { + ForEach.topLevel(gltf, 'bufferViews', handler); +}; + +ForEach.camera = function(gltf, handler) { + ForEach.topLevel(gltf, 'cameras', handler); +}; + +ForEach.image = function(gltf, handler) { + ForEach.topLevel(gltf, 'images', handler); +}; + +ForEach.material = function(gltf, handler) { + ForEach.topLevel(gltf, 'materials', handler); +}; + +ForEach.materialValue = function(material, handler) { + var values = material.values; + if (defined(values)) { + for (var name in values) { + if (values.hasOwnProperty(name)) { + handler(name, values[name]); + } + } + } +}; + +ForEach.mesh = function(gltf, handler) { + ForEach.topLevel(gltf, 'meshes', handler); +}; + +ForEach.meshPrimitives = function(mesh, handler) { + var primitives = mesh.primitives; + if (defined(primitives)) { + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + var primitive = primitives[i]; + handler(i, primitive); + } + } +}; + +ForEach.meshPrimitiveAttributes = function(primitive, handler) { + var attributes = primitive.attributes; + if (defined(attributes)) { + for (var semantic in attributes) { + if (attributes.hasOwnProperty(semantic)) { + handler(semantic, attributes[semantic]); + } + } + } +}; + +ForEach.node = function(gltf, handler) { + ForEach.topLevel(gltf, 'nodes', handler); +}; + +ForEach.nodeInTree = function(gltf, nodeIds, handler) { + var nodes = gltf.nodes; + if (defined(nodes)) { + for (var i = 0; i < nodeIds.length; i++) { + var nodeId = nodeIds[i]; + var node = nodes[nodeId]; + if (defined(node)) { + handler(nodeId, node); + var children = node.children; + if (defined(children)) { + ForEach.nodeInTree(gltf, children, handler); + } + } + } + } +}; + +ForEach.nodeInScene = function(gltf, sceneId, handler) { + var scenes = gltf.scenes; + if (defined(scenes)) { + var scene = scenes[sceneId]; + if (defined(scene)) { + var sceneNodeIds = scene.nodes; + if (defined(sceneNodeIds)) { + ForEach.nodeInTree(gltf, sceneNodeIds, handler); + } + } + } +}; + +ForEach.program = function(gltf, handler) { + ForEach.topLevel(gltf, 'programs', handler); +}; + +ForEach.sampler = function(gltf, handler) { + ForEach.topLevel(gltf, 'samplers', handler); +}; + +ForEach.scene = function(gltf, handler) { + ForEach.topLevel(gltf, 'scenes', handler); +}; + +ForEach.shader = function(gltf, handler) { + ForEach.topLevel(gltf, 'shaders', handler); +}; + +ForEach.skin = function(gltf, handler) { + ForEach.topLevel(gltf, 'skins', handler); +}; + +ForEach.techniqueAttribute = function(technique, handler) { + var attributes = technique.attributes; + if (defined(attributes)) { + for (var semantic in attributes) { + if (attributes.hasOwnProperty(semantic)) { + handler(semantic, attributes[semantic]); + } + } + } +}; + +ForEach.techniqueParameter = function(technique, handler) { + var parameters = technique.parameters; + if (defined(parameters)) { + for (var parameterName in parameters) { + if (parameters.hasOwnProperty(parameterName)) { + handler(parameterName, parameters[parameterName]); + } + } + } +}; + +ForEach.technique = function(gltf, handler) { + ForEach.topLevel(gltf, 'techniques', handler); +}; + +ForEach.texture = function(gltf, handler) { + ForEach.topLevel(gltf, 'textures', handler); +}; \ No newline at end of file diff --git a/lib/Pipeline.js b/lib/Pipeline.js index 36c22f26..8c58a84c 100644 --- a/lib/Pipeline.js +++ b/lib/Pipeline.js @@ -264,17 +264,7 @@ function writeSources(gltf) { writeSource(gltf.images, 'images', undefined, embed, embedImage), writeSource(gltf.shaders, 'shaders', undefined, embed, embedImage) ]; - // Write sources for compressed textures - var images = gltf.images; - for (var imageId in images) { - if (images.hasOwnProperty(imageId)) { - var image = images[imageId]; - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - writeSourcePromises.push(writeSource(compressedImages, 'images', undefined, embed, embedImage)); - } - } - } + return Promise.all(writeSourcePromises) .then(function() { return gltf; diff --git a/lib/Remove.js b/lib/Remove.js new file mode 100644 index 00000000..b9883ecc --- /dev/null +++ b/lib/Remove.js @@ -0,0 +1,284 @@ +'use strict'; +var Cesium = require('cesium'); +var ForEach = require('./ForEach'); +var isTexture = require('./isTexture'); + +var defined = Cesium.defined; + +module.exports = Remove; + +/** + * Contains functions for removing elements from a glTF hierarchy. + * Since top-level glTF elements are arrays, when something is removed, referring + * indices need to be updated. + * @constructor + */ +function Remove() {} + +Remove.accessor = function(gltf, accessorId) { + var accessors = gltf.accessors; + + accessors.splice(accessorId, 1); + + /* jshint unused:vars */ + ForEach.mesh(gltf, function(meshId, mesh) { + ForEach.meshPrimitives(mesh, function(i, primitive) { + ForEach.meshPrimitiveAttributes(primitive, function(semantic, attributeAccessorId) { + if (attributeAccessorId > accessorId) { + primitive.attributes[semantic]--; + } + }); + var indices = primitive.indices; + if (defined(indices) && indices > accessorId) { + primitive.indices--; + } + }); + }); + + ForEach.skin(gltf, function(skinId, skin) { + if (defined(skin.inverseBindMatrices) && skin.inverseBindMatrices > accessorId) { + skin.inverseBindMatrices--; + } + }); + + ForEach.animation(gltf, function(animationId, animation) { + ForEach.animationSamplers(animation, function(samplerId, sampler) { + if (defined(sampler.input) && sampler.input > accessorId) { + sampler.input--; + } + if (defined(sampler.output) && sampler.output > accessorId) { + sampler.output--; + } + }); + }); +}; + +Remove.buffer = function(gltf, bufferId) { + var buffers = gltf.buffers; + + buffers.splice(bufferId, 1); + + /* jshint unused:vars */ + ForEach.bufferView(gltf, function(bufferViewId, bufferView) { + if (defined(bufferView.buffer) && bufferView.buffer > bufferId) { + bufferView.buffer--; + } + }); +}; + +Remove.bufferView = function(gltf, bufferViewId) { + var bufferViews = gltf.bufferViews; + + bufferViews.splice(bufferViewId, 1); + + /* jshint unused:vars */ + ForEach.accessor(gltf, function(accessorId, accessor) { + if (defined(accessor.bufferView) && accessor.bufferView > bufferViewId) { + accessor.bufferView--; + } + }); +}; + +Remove.camera = function(gltf, cameraId) { + var cameras = gltf.cameras; + + cameras.splice(cameraId, 1); + + /* jshint unused:vars */ + ForEach.node(gltf, function(nodeId, node) { + if (defined(node.camera) && node.camera > cameraId) { + node.camera--; + } + }); +}; + +Remove.image = function(gltf, imageId) { + var images = gltf.images; + + images.splice(imageId, 1); + + /* jshint unused:vars */ + ForEach.texture(gltf, function(textureId, texture) { + if (defined(texture.source) && texture.source > imageId) { + texture.source--; + } + }); +}; + +Remove.material = function(gltf, materialId) { + var materials = gltf.materials; + + materials.splice(materialId, 1); + + /* jshint unused:vars */ + ForEach.mesh(gltf, function(meshId, mesh) { + ForEach.meshPrimitives(mesh, function(i, primitive) { + if (defined(primitive.material) && primitive.material > materialId) { + primitive.material--; + } + }); + }); +}; + +Remove.mesh = function(gltf, meshId) { + var meshes = gltf.meshes; + + meshes.splice(meshId, 1); + + /* jshint unused:vars */ + ForEach.node(gltf, function(nodeId, node) { + if (defined(node.mesh) && node.mesh > meshId) { + node.mesh--; + } + }); +}; + +Remove.node = function(gltf, nodeId) { + var nodes = gltf.nodes; + + nodes.splice(nodeId, 1); + + /* jshint unused:vars */ + ForEach.node(gltf, function(id, node) { + var children = node.children; + if (defined(children)) { + var childrenLength = children.length; + for (var i = 0; i < childrenLength; i++) { + var childId = children[i]; + if (childId > nodeId) { + children[i]--; + } + } + } + var skeletons = node.skeletons; + if (defined(skeletons)) { + var skeletonsLength = skeletons.length; + for (var j = 0; j < skeletonsLength; j++) { + var skeletonId = skeletons[j]; + if (skeletonId > nodeId) { + skeletons[j]--; + } + } + } + }); + + ForEach.technique(gltf, function(techniqueId, technique) { + /* jshint unused:vars */ + ForEach.techniqueParameter(technique, function(name, value) { + if (defined(value.node) && value.node > nodeId) { + value.node--; + } + }); + }); + + ForEach.scene(gltf, function(sceneId, scene) { + var sceneNodeIds = scene.nodes; + if (defined(sceneNodeIds)) { + var sceneNodeIdsLength = sceneNodeIds.length; + for (var k = 0; k < sceneNodeIdsLength; k++) { + var sceneNodeId = sceneNodeIds[k]; + if (sceneNodeId > nodeId) { + sceneNodeIds[k]--; + } + } + } + }); +}; + +Remove.program = function(gltf, programId) { + var programs = gltf.programs; + + programs.splice(programId, 1); + + /* jshint unused:vars */ + ForEach.technique(gltf, function(techniqueId, technique) { + if (defined(technique.program) && technique.program > programId) { + technique.program--; + } + }); +}; + +Remove.sampler = function(gltf, samplerId) { + var samplers = gltf.samplers; + + samplers.splice(samplerId, 1); + + /* jshint unused:vars */ + ForEach.texture(gltf, function(textureId, texture) { + if (defined(texture.sampler) && texture.sampler > samplerId) { + texture.sampler--; + } + }); +}; + +Remove.shader = function(gltf, shaderId) { + var shaders = gltf.shaders; + + shaders.splice(shaderId, 1); + + /* jshint unused:vars */ + ForEach.program(gltf, function(programId, program) { + if (defined(program.vertexShader) && program.vertexShader > shaderId) { + program.vertexShader--; + } + if (defined(program.fragmentShader) && program.fragmentShader > shaderId) { + program.fragmentShader--; + } + }); +}; + +Remove.skin = function(gltf, skinId) { + var skins = gltf.skins; + + skins.splice(skinId, 1); + + /* jshint unused:vars */ + ForEach.node(gltf, function(nodeId, node) { + if (defined(node.skin) && node.skin > skinId) { + node.skin--; + } + }); +}; + +Remove.technique = function(gltf, techniqueId) { + var techniques = gltf.techniques; + + techniques.splice(techniqueId, 1); + + /* jshint unused:vars */ + ForEach.material(gltf, function(materialId, material) { + if (defined(material.technique) && material.technique > techniqueId) { + material.technique--; + } + }); +}; + +Remove.texture = function(gltf, textureId) { + var textures = gltf.textures; + + textures.splice(textureId, 1); + + /* jshint unused:vars */ + ForEach.material(gltf, function(materialId, material) { + ForEach.materialValue(material, function(name, value) { + if (isTexture(name, value)) { + if (value[0] > textureId) { + value[0]--; + } + } + }); + }); + + ForEach.technique(gltf, function(techniqueId, technique) { + ForEach.techniqueParameter(technique, function(name, parameter) { + var value = parameter.value; + if (defined(value)) { + if (isTexture(name, value)) { + if (value[0] > textureId) { + value[0]--; + } + } + } + }); + }); +}; \ No newline at end of file diff --git a/lib/RemoveUnusedProperties.js b/lib/RemoveUnusedProperties.js index 162e0c15..a470c8d0 100644 --- a/lib/RemoveUnusedProperties.js +++ b/lib/RemoveUnusedProperties.js @@ -1,7 +1,8 @@ 'use strict'; var Cesium = require('cesium'); -var findUsedIds = require('./findUsedIds'); -var removeObject = require('./removeObject'); +var ForEach = require('./ForEach'); +var isTexture = require('./isTexture'); +var Remove = require('./Remove'); var defined = Cesium.defined; @@ -38,68 +39,15 @@ RemoveUnusedProperties.removeAll = function(gltf) { RemoveUnusedProperties.removePrimitiveAttributes(gltf); }; -function removeNode(gltf, nodeId) { - var nodes = gltf.nodes; - var scenes = gltf.scenes; - var techniques = gltf.techniques; - var j; - - nodes.splice(nodeId, 1); - var nodesLength = nodes.length; - for (var i = 0; i < nodesLength; i++) { - var node = nodes[i]; - var children = node.children; - if (defined(children)) { - var childrenLength = children.length; - for (j = 0; j < childrenLength; j++) { - var childId = children[j]; - if (childId > nodeId) { - children[j] = childId - 1; - } - } - } - var skeletons = node.skeletons; - if (defined(skeletons)) { - var skeletonsLength = skeletons.length; - for (j = 0; j < skeletonsLength; j++) { - var skeletonId = skeletons[j]; - if (skeletonId > nodeId) { - skeletons[j] = skeletonId - 1; - } - } - } - } - - if (defined(techniques)) { - var techniquesLength = techniques.length; - for (var techniqueId = 0; techniqueId < techniquesLength; techniqueId++) { - var technique = techniques[techniqueId]; - var parameters = technique.parameters; - for (var parameterName in parameters) { - if (parameters.hasOwnProperty(parameterName)) { - var parameter = parameters[parameterName]; - if (defined(parameter.node) && parameter.node > nodeId) { - parameter.node--; - } - } - } - } - } - - var scenesLength = scenes.length; - for (var sceneId = 0; sceneId < scenesLength; sceneId++) { - var scene = scenes[sceneId]; - var sceneNodes = scene.nodes; - if (defined(sceneNodes)) { - var sceneNodesLength = sceneNodes.length; - for (j = 0; j < sceneNodesLength; j++) { - var sceneNodeId = sceneNodes[j]; - if (sceneNodeId > nodeId) { - sceneNodes[j] = sceneNodeId - 1; - } - } - } - } +function removeUnusedElements(gltf, type, usedIds) { + var removed = 0; + ForEach[type](gltf, function(id) { + if (!usedIds[id + removed]) { + Remove[type](gltf, id); + removed++; + return -1; + } + }); } /** @@ -110,57 +58,30 @@ function removeNode(gltf, nodeId) { */ RemoveUnusedProperties.removeNodes = function(gltf) { var usedNodeIds = {}; - var scenes = gltf.scenes; - var nodes = gltf.nodes; - var i, j; - - // Build hash of used nodes by traversing through node trees starting at scenes - if (defined(scenes)) { - var scenesLength = scenes.length; - for (var sceneId = 0; sceneId < scenesLength; sceneId++) { - var roots = scenes[sceneId].nodes; - if (defined(roots)) { - var nodeStack = []; - var rootsLength = roots.length; - for (i = 0; i < rootsLength; i++) { - var root = roots[i]; - nodeStack.push(root); - } - while (nodeStack.length > 0) { - var node = nodeStack.pop(); - usedNodeIds[node] = true; - - var children = nodes[node].children; - if (defined(children)) { - var childrenLength = children.length; - for (j = 0; j < childrenLength; j++) { - var child = children[j]; - nodeStack.push(child); - } - } - var skeletons = nodes[node].skeletons; - if (defined(skeletons)) { - var skeletonsLength = skeletons.length; - for (j = 0; j < skeletonsLength; j++) { - var skeleton = skeletons[j]; - nodeStack.push(skeleton); - } - } + ForEach.scene(gltf, function(sceneId) { + ForEach.nodeInScene(gltf, sceneId, function(nodeId, node) { + usedNodeIds[nodeId] = true; + var skeletons = node.skeletons; + if (defined(skeletons)) { + var skeletonsLength = skeletons.length; + for (var i = 0; i < skeletonsLength; i++) { + usedNodeIds[skeletons[i]] = true; } } - } - } + }); + }); + + /* jshint unused:vars */ + ForEach.technique(gltf, function(techniqueId, technique) { + ForEach.techniqueParameter(technique, function(name, value) { + if (defined(value.node)) { + usedNodeIds[value.node] = true; + } + }); + }); - var removed = 0; - for (i = 0; i < nodes.length; i++) { - var nodeId = i + removed; - if (!usedNodeIds[nodeId]) { - removeNode(gltf, i); - removed++; - i--; - } - } + removeUnusedElements(gltf, 'node', usedNodeIds); return gltf; }; @@ -171,8 +92,18 @@ RemoveUnusedProperties.removeNodes = function(gltf) { * @returns {Object} The glTF asset with removed unused skins. */ RemoveUnusedProperties.removeSkins = function(gltf) { - var usedSkinIds = findUsedIds(gltf, 'nodes', 'skin'); - return removeObject(gltf, 'skins', usedSkinIds); + var usedSkinIds = {}; + + /* jshint unused:vars */ + ForEach.node(gltf, function(nodeId, node) { + var nodeSkinId = node.skin; + if (defined(nodeSkinId)) { + usedSkinIds[nodeSkinId] = true; + } + }); + + removeUnusedElements(gltf, 'skin', usedSkinIds); + return gltf; }; /** @@ -182,23 +113,19 @@ RemoveUnusedProperties.removeSkins = function(gltf) { * @returns {Object} The glTF asset with removed unused cameras. */ RemoveUnusedProperties.removeCameras = function(gltf) { - var usedCameraIds = findUsedIds(gltf, 'nodes', 'camera'); - return removeObject(gltf, 'cameras', usedCameraIds); -}; + var usedCameraIds = {}; -function removeMesh(gltf, meshId) { - var nodes = gltf.nodes; + /* jshint unused:vars */ + ForEach.node(gltf, function(nodeId, node) { + var cameraId = node.camera; + if (defined(cameraId)) { + usedCameraIds[cameraId] = true; + } + }); - gltf.meshes.splice(meshId, 1); - var nodesLength = nodes.length; - for (var nodeId = 0; nodeId < nodesLength; nodeId++) { - var node = nodes[nodeId]; - var nodeMeshId = node.mesh; - if (defined(nodeMeshId) && nodeMeshId > meshId) { - node.mesh--; - } - } -} + removeUnusedElements(gltf, 'camera', usedCameraIds); + return gltf; +}; /** * Remove all unused meshes in the glTF asset. @@ -208,38 +135,16 @@ function removeMesh(gltf, meshId) { */ RemoveUnusedProperties.removeMeshes = function(gltf) { var usedMeshIds = {}; - var meshes = gltf.meshes; - var nodes = gltf.nodes; - - // Build hash of used meshes by iterating through nodes - if (defined(nodes)) { - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - var node = nodes[nodeId]; - var nodeMeshId = node.mesh; - if (defined(nodeMeshId)) { - var mesh = meshes[nodeMeshId]; - if (!defined(mesh.primitives) || mesh.primitives.length === 0) { - delete node.mesh; - } else { - usedMeshIds[nodeMeshId] = true; - } - } - } - } - } - var removed = 0; - if (defined(meshes)) { - for (var i = 0; i < meshes.length; i++) { - var meshId = i + removed; - if (!usedMeshIds[meshId]) { - removeMesh(gltf, i); - removed++; - i--; - } + /* jshint unused:vars */ + ForEach.node(gltf, function(nodeId, node) { + var meshId = node.mesh; + if (defined(meshId)) { + usedMeshIds[meshId] = true; } - } + }); + + removeUnusedElements(gltf, 'mesh', usedMeshIds); return gltf; }; @@ -251,60 +156,41 @@ RemoveUnusedProperties.removeMeshes = function(gltf) { */ RemoveUnusedProperties.removeAccessors = function(gltf) { var usedAccessorIds = {}; - var meshes = gltf.meshes; - var skins = gltf.skins; - var animations = gltf.animations; - - // Build hash of used accessors by iterating through meshes, skins, and animations - if (defined(meshes)) { - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var primitives = meshes[meshId].primitives; - if (defined(primitives)) { - var length = primitives.length; - for (var i = 0; i < length; i++) { - var attributes = primitives[i].attributes; - if (defined(attributes)) { - for (var attributeId in attributes) { - if (attributes.hasOwnProperty(attributeId)) { - var primitiveAccessorId = attributes[attributeId]; - usedAccessorIds[primitiveAccessorId] = true; - } - } - } - var indicesId = primitives[i].indices; - if (defined(indicesId)) { - usedAccessorIds[indicesId] = true; - } - } - } + + /* jshint unused:vars */ + ForEach.mesh(gltf, function(meshId, mesh) { + ForEach.meshPrimitives(mesh, function(i, primitive) { + ForEach.meshPrimitiveAttributes(primitive, function(semantic, accessorId) { + usedAccessorIds[accessorId] = true; + }); + var indices = primitive.indices; + if (defined(indices)) { + usedAccessorIds[indices] = true; } - } - } - if (defined(skins)) { - for (var skinId in skins) { - if (skins.hasOwnProperty(skinId)) { - var skinAccessorId = skins[skinId].inverseBindMatrices; - usedAccessorIds[skinAccessorId] = true; + }); + }); + + /* jshint unused:vars */ + ForEach.skin(gltf, function(skinId, skin) { + if (defined(skin.inverseBindMatrices)) { + usedAccessorIds[skin.inverseBindMatrices] = true; + } + }); + + /* jshint unused:vars */ + ForEach.animation(gltf, function(animationId, animation) { + ForEach.animationSamplers(animation, function(samplerId, sampler) { + if (defined(sampler.input)) { + usedAccessorIds[sampler.input] = true; } - } - } - if (defined(animations)) { - for (var animationId in animations) { - if (animations.hasOwnProperty(animationId)) { - var animation = animations[animationId]; - var samplers = animation.samplers; - for (var samplerId in samplers) { - if (samplers.hasOwnProperty(samplerId)) { - var sampler = samplers[samplerId]; - usedAccessorIds[sampler.input] = true; - usedAccessorIds[sampler.output] = true; - } - } + if (defined(sampler.output)) { + usedAccessorIds[sampler.output] = true; } - } - } - return removeObject(gltf, 'accessors', usedAccessorIds); + }); + }); + + removeUnusedElements(gltf, 'accessor', usedAccessorIds); + return gltf; }; /** @@ -315,24 +201,18 @@ RemoveUnusedProperties.removeAccessors = function(gltf) { */ RemoveUnusedProperties.removeMaterials = function(gltf) { var usedMaterialIds = {}; - var meshes = gltf.meshes; - - // Build hash of used materials by iterating through meshes - if (defined(meshes)) { - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - if (defined(meshes[meshId].primitives)) { - var primitives = meshes[meshId].primitives; - var length = primitives.length; - for (var i = 0; i < length; i++) { - var id = primitives[i].material; - usedMaterialIds[id] = true; - } - } + + /* jshint unused:vars */ + ForEach.mesh(gltf, function(meshId, mesh) { + ForEach.meshPrimitives(mesh, function(i, primitive) { + if (defined(primitive.material)) { + usedMaterialIds[primitive.material] = true; } - } - } - return removeObject(gltf, 'materials', usedMaterialIds); + }); + }); + + removeUnusedElements(gltf, 'material', usedMaterialIds); + return gltf; }; /** @@ -342,8 +222,17 @@ RemoveUnusedProperties.removeMaterials = function(gltf) { * @returns {Object} The glTF asset with removed unused buffers views. */ RemoveUnusedProperties.removeBufferViews = function(gltf) { - var usedBufferViewIds = findUsedIds(gltf, 'accessors', 'bufferView'); - return removeObject(gltf, 'bufferViews', usedBufferViewIds); + var usedBufferViewIds = {}; + + /* jshint unused:vars */ + ForEach.accessor(gltf, function(accessorId, accessor) { + if (defined(accessor.bufferView)) { + usedBufferViewIds[accessor.bufferView] = true; + } + }); + + removeUnusedElements(gltf, 'bufferView', usedBufferViewIds); + return gltf; }; /** @@ -353,8 +242,17 @@ RemoveUnusedProperties.removeBufferViews = function(gltf) { * @returns {Object} The glTF asset with removed unused techniques */ RemoveUnusedProperties.removeTechniques = function(gltf) { - var usedTechniqueIds = findUsedIds(gltf, 'materials', 'technique'); - return removeObject(gltf, 'techniques', usedTechniqueIds); + var usedTechniqueIds = {}; + + /* jshint unused:vars */ + ForEach.material(gltf, function(materialId, material) { + if (defined(material.technique)) { + usedTechniqueIds[material.technique] = true; + } + }); + + removeUnusedElements(gltf, 'technique', usedTechniqueIds); + return gltf; }; /** @@ -365,57 +263,30 @@ RemoveUnusedProperties.removeTechniques = function(gltf) { */ RemoveUnusedProperties.removeTextures = function(gltf) { var usedTextureIds = {}; - var materials = gltf.materials; - var techniques = gltf.techniques; - // Build hash of used textures by iterating through materials and techniques - var i; - var values; - var valueLength; - var value; - if (defined(materials)) { - for (var materialId in materials) { - if (materials.hasOwnProperty(materialId)) { - if (defined(materials[materialId].values)) { - values = materials[materialId].values; - for (var valueId in values) { - if (values.hasOwnProperty(valueId)) { - value = values[valueId]; - valueLength = value.length; - for (i = 0; i < valueLength; i++) { - if (typeof value[i] === 'string') { - usedTextureIds[value[i]] = true; - } - } - } - } - } + /* jshint unused:vars */ + ForEach.material(gltf, function(materialId, material) { + ForEach.materialValue(material, function(name, value) { + if (isTexture(name, value)) { + usedTextureIds[value[0]] = true; } - } - } - if (defined(techniques)) { - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - if (defined(techniques[techniqueId].parameters)) { - var parameters = techniques[techniqueId].parameters; - for (var parameterId in parameters) { - if (parameters.hasOwnProperty(parameterId)) { - value = parameters[parameterId].value; - if (defined(value)) { - valueLength = value.length; - for (i = 0; i < valueLength; i++) { - if (typeof value[i] === 'string') { - usedTextureIds[value[i]] = true; - } - } - } - } - } + }); + }); + + /* jshint unused:vars */ + ForEach.technique(gltf, function(techniqueId, technique) { + ForEach.techniqueParameter(technique, function(name, parameter) { + var value = parameter.value; + if (defined(value)) { + if (isTexture(name, value)) { + usedTextureIds[value[0]] = true; } } - } - } - return removeObject(gltf, 'textures', usedTextureIds); + }); + }); + + removeUnusedElements(gltf, 'texture', usedTextureIds); + return gltf; }; /** @@ -425,8 +296,17 @@ RemoveUnusedProperties.removeTextures = function(gltf) { * @returns {Object} The glTF asset with removed unused buffers. */ RemoveUnusedProperties.removeBuffers = function(gltf) { - var usedBufferIds = findUsedIds(gltf, 'bufferViews', 'buffer'); - return removeObject(gltf, 'buffers', usedBufferIds); + var usedBufferIds = {}; + + /* jshint unused:vars */ + ForEach.bufferView(gltf, function(bufferViewId, bufferView) { + if (defined(bufferView.buffer)) { + usedBufferIds[bufferView.buffer] = true; + } + }); + + removeUnusedElements(gltf, 'buffer', usedBufferIds); + return gltf; }; /** @@ -436,8 +316,17 @@ RemoveUnusedProperties.removeBuffers = function(gltf) { * @returns {Object} The glTF asset with removed unused programs. */ RemoveUnusedProperties.removePrograms = function(gltf) { - var usedProgramIds = findUsedIds(gltf, 'techniques', 'program'); - return removeObject(gltf, 'programs', usedProgramIds); + var usedProgramIds = {}; + + /* jshint unused:vars */ + ForEach.technique(gltf, function(techniqueId, technique) { + if (defined(technique.program)) { + usedProgramIds[technique.program] = true; + } + }); + + removeUnusedElements(gltf, 'program', usedProgramIds); + return gltf; }; /** @@ -447,8 +336,16 @@ RemoveUnusedProperties.removePrograms = function(gltf) { * @returns {Object} The glTF asset with removed unused images. */ RemoveUnusedProperties.removeImages = function(gltf) { - var usedImageIds = findUsedIds(gltf, 'textures', 'source'); - return removeObject(gltf, 'images', usedImageIds); + var usedImageIds = {}; + + /* jshint unused:vars */ + ForEach.texture(gltf, function(textureId, texture) { + if (defined(texture.source)) { + usedImageIds[texture.source] = true; + } + }); + + removeUnusedElements(gltf, 'image', usedImageIds); }; /** @@ -458,8 +355,17 @@ RemoveUnusedProperties.removeImages = function(gltf) { * @returns {Object} The glTF asset with removed unused samplers. */ RemoveUnusedProperties.removeSamplers = function(gltf) { - var usedSamplerIds = findUsedIds(gltf, 'textures', 'sampler'); - return removeObject(gltf, 'samplers', usedSamplerIds); + var usedSamplerIds = {}; + + /* jshint unused:vars */ + ForEach.texture(gltf, function(textureId, texture) { + if (defined(texture.sampler)) { + usedSamplerIds[texture.sampler] = true; + } + }); + + removeUnusedElements(gltf, 'sampler', usedSamplerIds); + return gltf; }; /** @@ -470,20 +376,19 @@ RemoveUnusedProperties.removeSamplers = function(gltf) { */ RemoveUnusedProperties.removeShaders = function(gltf) { var usedShaderIds = {}; - var programs = gltf.programs; - - // Build hash of used shaders by iterating through programs - if (defined(programs)) { - for (var programId in programs) { - if (programs.hasOwnProperty(programId)) { - var fragId = programs[programId].fragmentShader; - var vertId = programs[programId].vertexShader; - usedShaderIds[fragId] = true; - usedShaderIds[vertId] = true; - } + + /* jshint unused:vars */ + ForEach.program(gltf, function(programId, program) { + if (defined(program.vertexShader)) { + usedShaderIds[program.vertexShader] = true; + } + if (defined(program.fragmentShader)) { + usedShaderIds[program.fragmentShader] = true; } - } - return removeObject(gltf, 'shaders', usedShaderIds); + }); + + removeUnusedElements(gltf, 'shader', usedShaderIds); + return gltf; }; /** @@ -493,46 +398,42 @@ RemoveUnusedProperties.removeShaders = function(gltf) { * @returns {Object} The glTF asset with removed unused primitive attributes. */ RemoveUnusedProperties.removePrimitiveAttributes = function(gltf) { - var meshes = gltf.meshes; var materials = gltf.materials; var techniques = gltf.techniques; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; + + /* jshint unused:vars */ + ForEach.mesh(gltf, function(meshId, mesh) { + ForEach.meshPrimitives(mesh, function(i, primitive) { + var usedAttributes = {}; + var hasAttributes = false; + ForEach.meshPrimitiveAttributes(primitive, function(semantic) { + usedAttributes[semantic] = false; + hasAttributes = true; + }); + if (hasAttributes) { var materialId = primitive.material; - var material = materials[materialId]; - var techniqueId = material.technique; - var technique = techniques[techniqueId]; - var techniqueParameters = technique.parameters; - var attributes = primitive.attributes; - var usedAttributes = {}; - for (var attributeSemantic in attributes) { - if (attributes.hasOwnProperty(attributeSemantic)) { - usedAttributes[attributeSemantic] = false; - } - } - for (var techniqueParameter in techniqueParameters) { - if (techniqueParameters.hasOwnProperty(techniqueParameter)) { - var parameterProperties = techniqueParameters[techniqueParameter]; - var parameterSemantic = parameterProperties.semantic; - if (defined(parameterSemantic)) { - usedAttributes[parameterSemantic] = true; - } + if (defined(materialId)) { + var material = materials[materialId]; + var techniqueId = material.technique; + if (defined(techniqueId)) { + var technique = techniques[techniqueId]; + ForEach.techniqueParameter(technique, function (name, parameter) { + if (defined(parameter.semantic)) { + usedAttributes[parameter.semantic] = true; + } + }); } } - for (var attribute in usedAttributes) { - if (usedAttributes.hasOwnProperty(attribute)) { - if (!usedAttributes[attribute]) { - delete attributes[attribute]; + for (var semantic in usedAttributes) { + if (usedAttributes.hasOwnProperty(semantic)) { + if (!usedAttributes[semantic]) { + delete primitive.attributes[semantic]; } } } } - } - } + }); + }); + return gltf; }; \ No newline at end of file diff --git a/lib/findUsedIds.js b/lib/findUsedIds.js index e842b363..462c3cb3 100644 --- a/lib/findUsedIds.js +++ b/lib/findUsedIds.js @@ -7,18 +7,17 @@ module.exports = findUsedIds; /** * @private */ -function findUsedIds(gltf, name, idName) { +function findUsedIds(gltf, name, propertyName) { var usedIds = {}; - var objects = gltf[name]; + var array = gltf[name]; - // Build hash of used ids by iterating through objects - if (defined(objects)) { - for (var objectId in objects) { - if (objects.hasOwnProperty(objectId)) { - var id = (objects[objectId])[idName]; - if (defined(id)) { - usedIds[id] = true; - } + if (defined(array)) { + var arrayLength = array.length; + for (var id = 0; id < arrayLength; id++) { + var object = array[id]; + var idProperty = object[propertyName]; + if (defined(idProperty)) { + usedIds[idProperty] = true; } } } diff --git a/lib/isTexture.js b/lib/isTexture.js new file mode 100644 index 00000000..064e4a08 --- /dev/null +++ b/lib/isTexture.js @@ -0,0 +1,17 @@ +'use strict'; +var Cesium = require('cesium'); + +var defined = Cesium.defined; + +module.exports = isTexture; + +var textureNames = { + ambient: true, + diffuse: true, + emission: true, + specular: true +}; + +function isTexture(name, value) { + return value.length === 1 && defined(textureNames[name]); +} \ No newline at end of file diff --git a/lib/loadGltfUris.js b/lib/loadGltfUris.js index 5f50ce4b..2789dff8 100644 --- a/lib/loadGltfUris.js +++ b/lib/loadGltfUris.js @@ -5,13 +5,13 @@ var Promise = require('bluebird'); var dataUriToBuffer = require('data-uri-to-buffer'); var fs = require('fs'); var path = require('path'); +var ForEach = require('./ForEach'); +var isDataUri = require('./isDataUri'); var defined = Cesium.defined; var defaultValue = Cesium.defaultValue; var DeveloperError = Cesium.DeveloperError; -var isDataUri = require('./isDataUri'); - var fsReadFile = Promise.promisify(fs.readFile); module.exports = loadGltfUris; @@ -28,24 +28,22 @@ module.exports = loadGltfUris; function loadGltfUris(gltf, options) { options = defaultValue(options, {}); var basePath = defaultValue(options.basePath, ''); - var loadURIs = [ - loadURI(gltf.buffers, 'buffers', basePath), - loadURI(gltf.images, 'images', basePath), - loadURI(gltf.shaders, 'shaders', basePath) + var loadPromises = [ + loadURIs(gltf.buffers, 'buffers', basePath), + loadURIs(gltf.images, 'images', basePath), + loadURIs(gltf.shaders, 'shaders', basePath) ]; // Read sources for compressed textures - var images = gltf.images; - var imagesLength = images.length; - for (var imageId = 0; imageId < imagesLength; imageId++) { - var image = images[imageId]; + /* jshint unused:vars */ + ForEach.image(function(imageId, image) { if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { var compressedImages = image.extras.compressedImage3DTiles; - loadURIs.push(loadURI(compressedImages, 'images', basePath)); + loadPromises.push(loadURIs(compressedImages, 'images', basePath)); } - } + }); - return Promise.all(loadURIs) + return Promise.all(loadPromises) .then(function() { gltf.extras = defaultValue(gltf.extras, {}); gltf.extras._pipeline = defaultValue(gltf.extras._pipeline, { @@ -56,56 +54,57 @@ function loadGltfUris(gltf, options) { }); } -function loadURI(objects, name, basePath) { - //Iterate through each object and get a promise to load its uri - var promises = []; +function loadURIs(objects, name, basePath) { if (defined(objects)) { - var objectsLength = objects.length; - for (var i = 0; i < objectsLength; i++) { - var object = objects[i]; - object.extras = defaultValue(object.extras, {}); - object.extras._pipeline = defaultValue(object.extras._pipeline, {}); - if (defined(object.extras._pipeline.source) && !defined(object.uri)) { - object.uri = 'data:,'; - } - var uri = object.uri; - //Load the uri into the extras object based on the uri type - if (isDataUri(uri)) { - if (!defined(object.extras._pipeline.source)) { - var buffer = dataUriToBuffer(uri); - if (name === 'shaders') { - object.extras._pipeline.source = buffer.toString(); - } else { - object.extras._pipeline.source = buffer; - } - } - if (!defined(object.extras._pipeline.extension)) { - switch (name) { - case 'buffers': - object.extras._pipeline.extension = '.bin'; - break; - case 'images': - object.extras._pipeline.extension = getImageDataUriFormat(uri); - break; - case 'shaders': - object.extras._pipeline.extension = '.glsl'; - break; - } - } - if (name === 'images') { - promises.push(generateJimpImage(object)); - } + return Promise.each(objects, function (object) { + return loadURI(object, name, basePath); + }); + } +} + +function loadURI(object, name, basePath) { + var promises = []; + object.extras = defaultValue(object.extras, {}); + object.extras._pipeline = defaultValue(object.extras._pipeline, {}); + if (defined(object.extras._pipeline.source) && !defined(object.uri)) { + object.uri = 'data:,'; + } + var uri = object.uri; + //Load the uri into the extras object based on the uri type + if (isDataUri(uri)) { + if (!defined(object.extras._pipeline.source)) { + var buffer = dataUriToBuffer(uri); + if (name === 'shaders') { + object.extras._pipeline.source = buffer.toString(); } else { - var uriPath = uri; - if (!path.isAbsolute(uriPath)) { - if (!defined(basePath)) { - throw new DeveloperError('glTF model references external files but no basePath is supplied'); - } - uriPath = path.join(basePath, uriPath); - } - promises.push(readFromFile(object, name, uriPath)); + object.extras._pipeline.source = buffer; + } + } + if (!defined(object.extras._pipeline.extension)) { + switch (name) { + case 'buffers': + object.extras._pipeline.extension = '.bin'; + break; + case 'images': + object.extras._pipeline.extension = getImageDataUriFormat(uri); + break; + case 'shaders': + object.extras._pipeline.extension = '.glsl'; + break; + } + } + if (name === 'images') { + promises.push(generateJimpImage(object)); + } + } else { + var uriPath = uri; + if (!path.isAbsolute(uriPath)) { + if (!defined(basePath)) { + throw new DeveloperError('glTF model references external files but no basePath is supplied'); } + uriPath = path.join(basePath, uriPath); } + promises.push(readFromFile(object, name, uriPath)); } return Promise.all(promises); } diff --git a/lib/writeGltf.js b/lib/writeGltf.js index 013d1e91..4f008b87 100755 --- a/lib/writeGltf.js +++ b/lib/writeGltf.js @@ -3,13 +3,13 @@ var Cesium = require('cesium'); var fsExtra = require('fs-extra'); var path = require('path'); var Promise = require('bluebird'); +var ForEach = require('./ForEach'); +var removePipelineExtras = require('./removePipelineExtras'); +var writeSource = require('./writeSource'); var defined = Cesium.defined; var DeveloperError = Cesium.DeveloperError; -var removePipelineExtras = require('./removePipelineExtras'); -var writeSource = require('./writeSource'); - fsExtra.outputJsonAsync = Promise.promisify(fsExtra.outputJson); module.exports = writeGltf; @@ -58,16 +58,13 @@ function writeGltf(gltf, options) { ]; // Write sources for compressed textures - var images = gltf.images; - for (var imageId in images) { - if (images.hasOwnProperty(imageId)) { - var image = images[imageId]; - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - writeSources.push(writeSource(compressedImages, 'images', basePath, embed, embedImage)); - } + /* jshint unused:vars */ + ForEach.image(gltf, function(imageId, image) { + if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { + var compressedImages = image.extras.compressedImage3DTiles; + writeSources.push(writeSource(compressedImages, 'images', basePath, embed, embedImage)); } - } + }); return Promise.all(writeSources) .then(function() { diff --git a/lib/writeSource.js b/lib/writeSource.js index 70eebbc8..7919774d 100644 --- a/lib/writeSource.js +++ b/lib/writeSource.js @@ -16,38 +16,50 @@ module.exports = writeSource; /** * @private */ -function writeSource(objects, name, basePath, embed, embedImage) { +function writeSource(arrayOfObjects, name, basePath, embed, embedImage) { var promises = []; - for (var id in objects) { - if (objects.hasOwnProperty(id)) { - var object = objects[id]; - if (defined(object.extras._pipeline.source)) { - var pipelineExtras = object.extras._pipeline; - var source = pipelineExtras.source; - var extension = pipelineExtras.extension; + var arrayLength = arrayOfObjects.length; + for (var i = 0; i < arrayLength; i++) { + var object = arrayOfObjects[i]; + if (defined(object.extras._pipeline.source)) { + var pipelineExtras = object.extras._pipeline; + var source = pipelineExtras.source; + var extension = pipelineExtras.extension; - if (embed && (embedImage || name !== 'images') || !defined(basePath)) { - if (name === 'shaders') { - object.uri = 'data:text/plain;base64,' + new Buffer(source).toString('base64'); - } else { - // .crn (Crunch) is not a supported mime type, so add it - mime.define({'image/crn' : ['crn']}); - object.uri = 'data:' + mime.lookup(extension) + ';base64,' + source.toString('base64'); - } - } else { - var fileName = id + extension; - var uri = object.uri; - if (defined(uri) && !isDataUri(uri)) { - // Use the original filename if it was external - fileName = uri; - } + // Write sources for compressed textures + if (name === 'images') { + var image = object; + if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { + var compressedImages = image.extras.compressedImage3DTiles; + promises.push(writeSource(compressedImages, 'images', undefined, embed, embedImage)); + } + } - // For compressed textures use the name stored in the extras rather than the id - fileName = defaultValue(pipelineExtras.name + extension, fileName) ; - object.uri = fileName; - var outputPath = path.join(basePath, fileName); - promises.push(fsOutputFile(outputPath, source)); + if (embed && (embedImage || name !== 'images') || !defined(basePath)) { + if (name === 'shaders') { + object.uri = 'data:text/plain;base64,' + new Buffer(source).toString('base64'); + } else { + // .crn (Crunch) is not a supported mime type, so add it + mime.define({'image/crn' : ['crn']}); + object.uri = 'data:' + mime.lookup(extension) + ';base64,' + source.toString('base64'); } + } else { + var fileName = i + extension; + // Use the name if we have one + if (defined(object.name)) { + fileName = object.name + extension; + } + var uri = object.uri; + if (defined(uri) && !isDataUri(uri)) { + // Use the original filename if it was external + fileName = uri; + } + + // For compressed textures use the name stored in the extras rather than the id + fileName = defaultValue(pipelineExtras.name + extension, fileName) ; + object.uri = fileName; + var outputPath = path.join(basePath, fileName); + promises.push(fsOutputFile(outputPath, source)); } } } diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestEmbedded.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestEmbedded.gltf index 3e05ca2f..d6deea60 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestEmbedded.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestEmbedded.gltf @@ -1,15 +1,15 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, "type": "SCALAR" }, - "accessor_23": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -26,8 +26,8 @@ ], "type": "VEC3" }, - "accessor_25": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 288, "byteStride": 12, "componentType": 5126, @@ -44,8 +44,8 @@ ], "type": "VEC3" }, - "accessor_27": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 576, "byteStride": 8, "componentType": 5126, @@ -60,51 +60,50 @@ ], "type": "VEC2" } - }, - "animations": {}, + ], + "animations": [], "asset": { - "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", "premultipliedAlpha": true, "profile": { "api": "WebGL", - "version": "1.0.2" + "version": "1.0" }, - "version": 1 + "version": "2.0" }, - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", + "bufferViews": [ + { + "buffer": 0, "byteLength": 72, "byteOffset": 0, "target": 34963 }, - "bufferView_30": { - "buffer": "CesiumTexturedBoxTest", + { + "buffer": 0, "byteLength": 768, "byteOffset": 72, "target": 34962 } - }, - "buffers": { - "CesiumTexturedBoxTest": { + ], + "buffers": [ + { "byteLength": 840, "type": "arraybuffer", "uri": "data:application/octet-stream;base64,AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUAAAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/" } - }, - "images": { - "Image0001": { + ], + "images": [ + { "name": "Image0001", "uri": "data:image/png;base64,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" } - }, - "materials": { - "Effect-Texture": { + ], + "materials": [ + { "name": "Texture", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Image0001", - "shininess": 256, + "diffuse": [0], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -113,26 +112,26 @@ ] } } - }, - "meshes": { - "Geometry-mesh002": { + ], + "meshes": [ + { "name": "Mesh", "primitives": [ { "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" + "NORMAL": 2, + "POSITION": 1, + "TEXCOORD_0": 3 }, - "indices": "accessor_21", - "material": "Effect-Texture", + "indices": 0, + "material": 0, "mode": 4 } ] } - }, - "nodes": { - "Geometry-mesh002Node": { + ], + "nodes": [ + { "children": [], "matrix": [ 1, @@ -152,14 +151,12 @@ 0, 1 ], - "meshes": [ - "Geometry-mesh002" - ], + "mesh": 0, "name": "Mesh" }, - "groupLocator030Node": { + { "children": [ - "txtrLocator026Node" + 3 ], "matrix": [ 1, @@ -181,10 +178,10 @@ ], "name": "Texture_Group" }, - "node_3": { + { "children": [ - "Geometry-mesh002Node", - "groupLocator030Node" + 0, + 1 ], "matrix": [ 1, @@ -206,7 +203,7 @@ ], "name": "Y_UP_Transform" }, - "txtrLocator026Node": { + { "children": [], "matrix": [ 1, @@ -228,47 +225,47 @@ ], "name": "Cesium_Logo_Flat__Image___Texture_" } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position", "a_texcoord0" ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "samplers": { - "sampler_0": { + ], + "samplers": [ + { "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497 } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_3" + 2 ] } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { + ], + "shaders": [ + { "type": 35632, "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0KdW5pZm9ybSBzYW1wbGVyMkQgdV9kaWZmdXNlOw0KdW5pZm9ybSB2ZWM0IHVfc3BlY3VsYXI7DQp1bmlmb3JtIGZsb2F0IHVfc2hpbmluZXNzOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzMgbm9ybWFsID0gbm9ybWFsaXplKHZfbm9ybWFsKTsNCnZlYzQgY29sb3IgPSB2ZWM0KDAuLCAwLiwgMC4sIDAuKTsNCnZlYzQgZGlmZnVzZSA9IHZlYzQoMC4sIDAuLCAwLiwgMS4pOw0KdmVjNCBzcGVjdWxhcjsNCmRpZmZ1c2UgPSB0ZXh0dXJlMkQodV9kaWZmdXNlLCB2X3RleGNvb3JkMCk7DQpzcGVjdWxhciA9IHVfc3BlY3VsYXI7DQpkaWZmdXNlLnh5eiAqPSBtYXgoZG90KG5vcm1hbCx2ZWMzKDAuLDAuLDEuKSksIDAuKTsNCmNvbG9yLnh5eiArPSBkaWZmdXNlLnh5ejsNCmNvbG9yID0gdmVjNChjb2xvci5yZ2IgKiBkaWZmdXNlLmEsIGRpZmZ1c2UuYSk7DQpnbF9GcmFnQ29sb3IgPSBjb2xvcjsNCn0NCg==" }, - "CesiumTexturedBoxTest0VS": { + { "type": 35633, "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsNCmF0dHJpYnV0ZSB2ZWMzIGFfbm9ybWFsOw0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdW5pZm9ybSBtYXQzIHVfbm9ybWFsTWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMyIGFfdGV4Y29vcmQwOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzQgcG9zID0gdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCnZfbm9ybWFsID0gdV9ub3JtYWxNYXRyaXggKiBhX25vcm1hbDsNCnZfdGV4Y29vcmQwID0gYV90ZXhjb29yZDA7DQpnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHBvczsNCn0NCg==" } - }, - "skins": {}, - "techniques": { - "technique0": { + ], + "skins": [], + "techniques": [ + { "attributes": { "a_normal": "normal", "a_position": "position", @@ -325,15 +322,15 @@ "u_specular": "specular" } } - }, - "textures": { - "texture_Image0001": { + ], + "textures": [ + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", + "sampler": 0, + "source": 0, "target": 3553, "type": 5121 } - } + ] } \ No newline at end of file diff --git a/specs/lib/RemoveUnusedPropertiesSpec.js b/specs/lib/RemoveUnusedPropertiesSpec.js index dfa1a19b..90a100c6 100644 --- a/specs/lib/RemoveUnusedPropertiesSpec.js +++ b/specs/lib/RemoveUnusedPropertiesSpec.js @@ -188,50 +188,47 @@ describe('RemoveUnusedProperties', function() { describe('removeSkins', function () { it('removes a skin', function () { var gltf = { - "nodes": { - "Cylinder": { - "skin": "Armature_Cylinder-skin" + nodes: [ + { + skin: 0 } - }, - "skins": { - "Armature_Cylinder-skin": { - "inverseBindMatrices": "IBM_Armature_Cylinder-skin", - "jointNames": [ - "Bone" - ] + ], + skins: [ + { + inverseBindMatrices: 0, + jointNames: [ + 'Bone' + ], + name: 'used' }, - "unusedSkinId": { - "inverseBindMatrices": "IBM_Armature_Cylinder-skin", - "jointNames": [ - "Bone" - ] + { + name: 'unused' } - } + ] }; removeSkins(gltf); - expect(gltf.skins.unusedSkinId).not.toBeDefined(); - expect(Object.keys(gltf.skins).length).toEqual(1); + var skins = gltf.skins; + expect(skins.length).toEqual(1); + expect(skins[0].name).toEqual('used'); }); it('does not remove any skins', function () { var gltf = { - "nodes": { - "Cylinder": { - "skin": "Armature_Cylinder-skin" + nodes: [ + { + skin: 0 } - }, - "skins": { - "Armature_Cylinder-skin": { - "inverseBindMatrices": "IBM_Armature_Cylinder-skin", - "jointNames": [ - "Bone" - ] + ], + skins: [ + { + name: 'usedSkin' } - } + ] }; removeSkins(gltf); - expect(gltf.skins["Armature_Cylinder-skin"]).toBeDefined(); - expect(Object.keys(gltf.skins).length).toEqual(1); + var skins = gltf.skins; + expect(skins.length).toEqual(1); + expect(skins[0].name).toEqual('usedSkin'); }); }); @@ -239,59 +236,60 @@ describe('RemoveUnusedProperties', function() { describe('removeCameras', function () { it('removes a camera', function () { var gltf = { - "cameras": { - "camera_0": { - "perspective": { - "aspectRatio": 1.5, - "yfov": 0.660593, - "zfar": 100, - "znear": 0.01 + cameras: [ + { + perspective: { + aspectRatio: 1.5, + yfov: 0.660593, + zfar: 100, + znear: 0.01 }, - "type": "perspective" + type: 'perspective' }, - "unusedCameraId": { - "perspective": { - "aspectRatio": 1.5, - "yfov": 0.660593, - "zfar": 100, - "znear": 0.01 + { + perspective: { + aspectRatio: 1.5, + yfov: 0.660593, + zfar: 100, + znear: 0.01 }, - "type": "perspective" + type: 'perspective', + name: 'usedCamera' } - }, - "nodes": { - "node_3": { - "camera": "camera_0" + ], + nodes: [ + { + camera: 1 } - } + ] }; removeCameras(gltf); - expect(gltf.cameras.unusedCameraId).not.toBeDefined(); - expect(Object.keys(gltf.cameras).length).toEqual(1); + expect(gltf.cameras.length).toEqual(1); + expect(gltf.cameras[0].name).toEqual('usedCamera'); + expect(gltf.nodes[0].camera).toEqual(0); }); - it('does not remove any cameras', function () { + it('does not remove any cameras', function() { var gltf = { - "cameras": { - "camera_0": { - "perspective": { - "aspectRatio": 1.5, - "yfov": 0.660593, - "zfar": 100, - "znear": 0.01 + cameras: [ + { + perspective: { + aspectRatio: 1.5, + yfov: 0.660593, + zfar: 100, + znear: 0.01 }, - "type": "perspective" + type: 'perspective' } - }, - "nodes": { - "node_3": { - "camera": "camera_0" + ], + nodes: [ + { + camera: 0 } - } + ] }; removeCameras(gltf); - expect(gltf.cameras.camera_0).toBeDefined(); - expect(Object.keys(gltf.cameras).length).toEqual(1); + expect(gltf.cameras.length).toEqual(1); }); }); @@ -301,16 +299,16 @@ describe('RemoveUnusedProperties', function() { var gltf = { meshes: [ { - primitives: [{}], - name: 'Geometry-mesh002' + name: 'unusedMeshId' }, { - name: 'unusedMeshId' + primitives: [{}], + name: 'Geometry-mesh002' } ], nodes: [ { - mesh: 0, + mesh: 1, name: 'Geometry-mesh002Node' } ] @@ -318,6 +316,7 @@ describe('RemoveUnusedProperties', function() { removeMeshes(gltf); expect(gltf.meshes.length).toEqual(1); expect(gltf.meshes[0].name).toEqual('Geometry-mesh002'); + expect(gltf.nodes[0].mesh).toEqual(0); }); it('does not remove any meshes', function () { @@ -345,145 +344,148 @@ describe('RemoveUnusedProperties', function() { describe('removeAccessors', function () { it('removes an accessor', function () { var gltf = { - "accessors": { - "IBM_Armature_Cylinder-skin": { - "bufferView": "bufferView_43", - "byteOffset": 0, - "componentType": 5126, - "count": 2, - "type": "MAT4" + accessors: [ + { + bufferView: 3, + byteOffset: 128, + componentType: 5126, + count: 3, + type: 'SCALAR' }, - "accessor_16": { - "bufferView": "bufferView_44", - "byteOffset": 0, - "componentType": 5123, - "count": 564, - "type": "SCALAR" + { + bufferView: 0, + byteOffset: 0, + componentType: 5126, + count: 2, + type: 'MAT4' }, - "accessor_18": { - "bufferView": "bufferView_45", - "byteOffset": 0, - "componentType": 5126, - "count": 160, - "type": "VEC3" + { + bufferView: 1, + byteOffset: 0, + componentType: 5123, + count: 564, + type: 'SCALAR' }, - "animAccessor_0": { - "bufferView": "bufferView_43", - "byteOffset": 128, - "componentType": 5126, - "count": 3, - "type": "SCALAR" + { + bufferView: 1, + byteOffset: 0, + componentType: 5126, + count: 160, + type: 'VEC3' }, - "unusedAccessorId": { - "bufferView": "bufferView_43", - "byteOffset": 128, - "componentType": 5126, - "count": 3, - "type": "SCALAR" + { + bufferView: 2, + byteOffset: 128, + componentType: 5126, + count: 3, + type: 'SCALAR' } - }, - "animations": { - "animation_0": { - "samplers": { - "sampler": { - "input": "animAccessor_0" + ], + animations: [ + { + samplers: [ + { + input: 4 } - } + ] } - }, - "meshes": { - "Cylinder-mesh": { - "primitives": [ + ], + meshes: [ + { + primitives: [ { - "attributes": { - "POSITION": "accessor_18" + attributes: { + POSITION: 3 }, - "indices": "accessor_16", - "material": "Material_001-effect" + indices: 2, + material: 0 } ] } - }, - "skins": { - "Armature_Cylinder-skin": { - "inverseBindMatrices": "IBM_Armature_Cylinder-skin", - "jointNames": [] + ], + skins: [ + { + inverseBindMatrices: 1, + jointNames: [] } - } + ] }; removeAccessors(gltf); - expect(gltf.accessors.unusedAccessorId).not.toBeDefined(); - expect(Object.keys(gltf.accessors).length).toEqual(4); + expect(gltf.accessors.length).toEqual(4); + expect(gltf.skins[0].inverseBindMatrices).toEqual(0); + expect(gltf.meshes[0].primitives[0].indices).toEqual(1); + expect(gltf.meshes[0].primitives[0].attributes.POSITION).toEqual(2); + expect(gltf.animations[0].samplers[0].input).toEqual(3); }); it('does not remove any accessors', function () { var gltf = { - "accessors": { - "IBM_Armature_Cylinder-skin": { - "bufferView": "bufferView_43", - "byteOffset": 0, - "componentType": 5126, - "count": 2, - "type": "MAT4" + accessors: [ + { + bufferView: 0, + byteOffset: 0, + componentType: 5126, + count: 2, + type: 'MAT4' }, - "accessor_16": { - "bufferView": "bufferView_44", - "byteOffset": 0, - "componentType": 5123, - "count": 564, - "type": "SCALAR" + { + bufferView: 1, + byteOffset: 0, + componentType: 5123, + count: 564, + type: 'SCALAR' }, - "accessor_18": { - "bufferView": "bufferView_45", - "byteOffset": 0, - "componentType": 5126, - "count": 160, - "type": "VEC3" + { + bufferView: 1, + byteOffset: 0, + componentType: 5126, + count: 160, + type: 'VEC3' }, - "animAccessor_0": { - "bufferView": "bufferView_43", - "byteOffset": 128, - "componentType": 5126, - "count": 3, - "type": "SCALAR" + { + bufferView: 2, + byteOffset: 128, + componentType: 5126, + count: 3, + type: 'SCALAR' } - }, - "animations": { - "animation_0": { - "samplers": { - "sampler": { - "input": "animAccessor_0" + ], + animations: [ + { + samplers: [ + { + input: 3 } - } + ] } - }, - "meshes": { - "Cylinder-mesh": { - "primitives": [ + ], + meshes: [ + { + primitives: [ { - "attributes": { - "POSITION": "accessor_18" + attributes: { + POSITION: 2 }, - "indices": "accessor_16", - "material": "Material_001-effect" + indices: 1, + material: 0 } ] } - }, - "skins": { - "Armature_Cylinder-skin": { - "inverseBindMatrices": "IBM_Armature_Cylinder-skin", - "jointNames": [] + ], + skins: [ + { + inverseBindMatrices: 0, + jointNames: [] } - } + ] }; removeAccessors(gltf); - expect(gltf.accessors["IBM_Armature_Cylinder-skin"]).toBeDefined(); - expect(gltf.accessors.accessor_16).toBeDefined(); - expect(gltf.accessors.accessor_18).toBeDefined(); - expect(gltf.accessors.animAccessor_0).toBeDefined(); - expect(Object.keys(gltf.accessors).length).toEqual(4); + expect(gltf.accessors.length).toEqual(4); + expect(gltf.skins[0].inverseBindMatrices).toEqual(0); + expect(gltf.meshes[0].primitives[0].indices).toEqual(1); + expect(gltf.meshes[0].primitives[0].attributes.POSITION).toEqual(2); + expect(gltf.animations[0].samplers[0].input).toEqual(3); }); }); @@ -491,64 +493,59 @@ describe('RemoveUnusedProperties', function() { describe('removeMaterials', function () { it('removes a material', function () { var gltf = { - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001", - "shininess": 256 - } + materials: [ + { + name: 'unused' }, - "unusedMaterialId": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001", - "shininess": 256 + { + name: 'Texture', + technique: 0, + values: { + diffuse: [0], + shininess: [256] } } - }, - "meshes": { - "Geometry-mesh002": { - "primitives": [ + ], + meshes: [ + { + primitives: [ { - "material": "Effect-Texture" + material: 1 } ] } - } + ] }; removeMaterials(gltf); - expect(gltf.materials.unusedMaterialId).not.toBeDefined(); - expect(Object.keys(gltf.materials).length).toEqual(1); + expect(gltf.materials.length).toEqual(1); + expect(gltf.materials[0].name).not.toEqual('unused'); + expect(gltf.meshes[0].primitives[0].material).toEqual(0); }); it('does not remove any materials', function () { var gltf = { - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001", - "shininess": 256 + materials: [ + { + name: 'Texture', + technique: 0, + values: { + diffuse: [0], + shininess: [256] } } - }, - "meshes": { - "Geometry-mesh002": { - "primitives": [ + ], + meshes: [ + { + primitives: [ { - "material": "Effect-Texture" + material: 0 } ] } - } + ] }; removeMaterials(gltf); - expect(gltf.materials["Effect-Texture"]).toBeDefined(); - expect(Object.keys(gltf.materials).length).toEqual(1); + expect(gltf.materials.length).toEqual(1); }); }); @@ -556,60 +553,59 @@ describe('RemoveUnusedProperties', function() { describe('removeBufferViews', function () { it('removes a bufferView', function () { var gltf = { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR" + accessors: [ + { + bufferView: 1, + byteOffset: 0, + byteStride: 0, + componentType: 5123, + count: 36, + type: 'SCALAR' } - }, - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 0, - "target": 34963 + ], + bufferViews: [ + { + buffer: 0, + byteLength: 768, + byteOffset: 72, + target: 34962 }, - "unusedBufferViewId": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 768, - "byteOffset": 72, - "target": 34962 + { + buffer: 0, + byteLength: 72, + byteOffset: 0, + target: 34963 } - } + ] }; removeBufferViews(gltf); - expect(gltf.bufferViews.unusedBufferViewId).not.toBeDefined(); - expect(Object.keys(gltf.bufferViews).length).toEqual(1); + expect(gltf.bufferViews.length).toEqual(1); + expect(gltf.accessors[0].bufferView).toEqual(0); }); - it('does not remove any buffers', function () { + it('does not remove any buffer views', function () { var gltf = { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR" + accessors: [ + { + bufferView: 0, + byteOffset: 0, + byteStride: 0, + componentType: 5123, + count: 36, + type: 'SCALAR' } - }, - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 0, - "target": 34963 + ], + bufferViews: [ + { + buffer: 0, + byteLength: 72, + byteOffset: 0, + target: 34963 } - } + ] }; removeBufferViews(gltf); - expect(gltf.bufferViews.bufferView_29).toBeDefined(); - expect(Object.keys(gltf.bufferViews).length).toEqual(1); + expect(gltf.bufferViews.length).toEqual(1); }); }); @@ -617,255 +613,121 @@ describe('RemoveUnusedProperties', function() { describe('removeTechniques', function () { it('removes a technique', function () { var gltf = { - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001" - } + materials: [ + { + technique: 1 } - }, - "techniques": { - "technique0": { - "attributes": { - "a_position": "position" - }, - "parameters": { - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_modelViewMatrix": "modelViewMatrix", - "u_projectionMatrix": "projectionMatrix" - } + ], + techniques: [ + { + name: 'unused' }, - "unusedTechniqueId": { - "attributes": { - "a_position": "position" - }, - "parameters": { - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_modelViewMatrix": "modelViewMatrix", - "u_projectionMatrix": "projectionMatrix" - } + { + name: 'used' } - } + ] }; removeTechniques(gltf); - expect(gltf.techniques.unusedTechniqueId).not.toBeDefined(); - expect(Object.keys(gltf.techniques).length).toEqual(1); + expect(gltf.techniques.length).toEqual(1); + expect(gltf.techniques[0].name).not.toEqual('unused'); + expect(gltf.materials[0].technique).toEqual(0); }); it('does not remove any techniques', function () { var gltf = { - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001" - } - } - }, - "techniques": { - "technique0": { - "attributes": { - "a_position": "position" - }, - "parameters": { - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_modelViewMatrix": "modelViewMatrix", - "u_projectionMatrix": "projectionMatrix" - } + materials: [ + { + technique: 0 } - } + ], + techniques: [ + {} + ] }; removeTechniques(gltf); - expect(gltf.techniques.technique0).toBeDefined(); - expect(Object.keys(gltf.techniques).length).toEqual(1); + expect(gltf.techniques.length).toEqual(1); }); }); var removeTextures = RemoveUnusedProperties.removeTextures; describe('removeTextures', function () { - it('removes a texture', function () { + it('removes a texture unused by material', function () { var gltf = { - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": ["texture_Image0001"], - "shininess": 256, - "specular": [ - 0.2, - 0.2, - 0.2, - 1 - ] + materials: [ + { + values: { + diffuse: [1] } } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 + ], + textures: [ + { + name: 'unused' }, - "unusedTextureId": { - "sampler": "sampler_0", - "source": "Image0001" + { + source: 0 } - } + ] }; + removeTextures(gltf); - expect(gltf.textures.unusedTextureId).not.toBeDefined(); - expect(Object.keys(gltf.textures).length).toEqual(1); + expect(gltf.textures.length).toEqual(1); + expect(gltf.textures[0].name).not.toEqual('unused'); + expect(gltf.materials[0].values.diffuse[0]).toEqual(0); }); - it('removes a texture', function () { + it('removes a texture unused by technique', function () { var gltf = { - "techniques": { - "technique0": { - "parameters": { - "diffuse": { - "type": 35678, - "value": ["texture_Image0001"] + techniques: [ + { + parameters: { + diffuse: { + value: [1] } - }, - "program": "program_0" + } } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 + ], + textures: [ + { + name: 'unused' }, - "unusedTextureId": { - "sampler": "sampler_0", - "source": "Image0001" + { + source: 0 } - } + ] }; + removeTextures(gltf); - expect(gltf.textures.unusedTextureId).not.toBeDefined(); - expect(Object.keys(gltf.textures).length).toEqual(1); + expect(gltf.textures.length).toEqual(1); + expect(gltf.textures[0].name).not.toEqual('unused'); + expect(gltf.techniques[0].parameters.diffuse.value[0]).toEqual(0); }); it('does not remove any textures', function () { var gltf = { - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": ["texture_Image0001"], - "shininess": [256], - "specular": [ - 0.2, - 0.2, - 0.2, - 1 - ] + materials: [ + { + values: { + diffuse: [0] } } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 - } - } - }; - removeTextures(gltf); - expect(gltf.textures.texture_Image0001).toBeDefined(); - expect(Object.keys(gltf.textures).length).toEqual(1); - }); - - it('does not remove any textures', function () { - var gltf = { - "techniques": { - "technique0": { - "parameters": { - "diffuse": { - "type": 35678, - "value": ["texture_Image0001"] + ], + techniques: [ + { + parameters: { + diffuse: { + value: [1] } - }, - "program": "program_0" - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 + } } - } + ], + textures: [ + {}, + {} + ] }; removeTextures(gltf); - expect(gltf.textures.texture_Image0001).toBeDefined(); - expect(Object.keys(gltf.textures).length).toEqual(1); + expect(gltf.textures.length).toEqual(2); }); }); @@ -873,53 +735,37 @@ describe('RemoveUnusedProperties', function() { describe('removeBuffers', function () { it('removes a buffer', function () { var gltf = { - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 0, - "target": 34963 + bufferViews: [ + { + buffer: 1 } - }, - "buffers": { - "CesiumTexturedBoxTest": { - "byteLength": 840, - "type": "arraybuffer", - "uri": "CesiumTexturedBoxTest.bin" + ], + buffers: [ + { + name: 'unused' }, - "unusedBufferId": { - "byteLength": 840, - "type": "arraybuffer", - "uri": "CesiumTexturedBoxTest.bin" - } - } + {} + ] }; removeBuffers(gltf); - expect(gltf.buffers.unusedBufferId).not.toBeDefined(); - expect(Object.keys(gltf.buffers).length).toEqual(1); + expect(gltf.buffers.length).toEqual(1); + expect(gltf.bufferViews[0].buffer).toEqual(0); + expect(gltf.buffers[0].name).not.toEqual('unused'); }); it('does not remove any buffers', function () { var gltf = { - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 0, - "target": 34963 - } - }, - "buffers": { - "CesiumTexturedBoxTest": { - "byteLength": 840, - "type": "arraybuffer", - "uri": "CesiumTexturedBoxTest.bin" + bufferViews: [ + { + buffer: 0 } - } + ], + buffers: [ + {} + ] }; removeBuffers(gltf); - expect(gltf.buffers.CesiumTexturedBoxTest).toBeDefined(); - expect(Object.keys(gltf.buffers).length).toEqual(1); + expect(gltf.buffers.length).toEqual(1); }); }); @@ -927,99 +773,39 @@ describe('RemoveUnusedProperties', function() { describe('removePrograms', function () { it('removes a program', function () { var gltf = { - "programs": { - "program_0": { - "attributes": [ - "a_position" - ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + programs: [ + { + name: 'unused' }, - "unusedProgramId": { - "attributes": [ - "a_position" - ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" - } - }, - "techniques": { - "technique0": { - "attributes": { - "a_position": "position" - }, - "parameters": { - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_modelViewMatrix": "modelViewMatrix", - "u_projectionMatrix": "projectionMatrix" - } + {} + ], + techniques: [ + { + program: 1 } - } + ] }; + removePrograms(gltf); - expect(gltf.programs.unusedProgramId).not.toBeDefined(); - expect(Object.keys(gltf.programs).length).toEqual(1); + expect(gltf.programs.length).toEqual(1); + expect(gltf.programs[0].name).not.toEqual('unused'); + expect(gltf.techniques[0].program).toEqual(0); }); it('does not remove any programs', function () { var gltf = { - "programs": { - "program_0": { - "attributes": [ - "a_position" - ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" - } - }, - "techniques": { - "technique0": { - "attributes": { - "a_position": "position" - }, - "parameters": { - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_modelViewMatrix": "modelViewMatrix", - "u_projectionMatrix": "projectionMatrix" - } + programs: [ + {} + ], + techniques: [ + { + program: 0 } - } + ] }; + removePrograms(gltf); - expect(gltf.programs.program_0).toBeDefined(); - expect(Object.keys(gltf.programs).length).toEqual(1); + expect(gltf.programs.length).toEqual(1); }); }); @@ -1027,54 +813,39 @@ describe('RemoveUnusedProperties', function() { describe('removeImages', function() { it('removes an image', function() { var gltf = { - "images": { - "Image0001": { - "name": "Image0001", - "uri": "Cesium_Logo_Flat.png" + images: [ + { + name: 'unused' }, - "unusedId": { - "name": "An unused image for testing removal", - "uri": "unused.png" - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 + {} + ], + textures: [ + { + source: 1 } - } + ] }; + removeImages(gltf); - expect(gltf.images.unusedId).not.toBeDefined(); - expect(Object.keys(gltf.images).length).toEqual(1); + expect(gltf.images.length).toEqual(1); + expect(gltf.images[0].name).not.toEqual('unused'); + expect(gltf.textures[0].source).toEqual(0); }); it('does not remove any images', function() { var gltf = { - "images": { - "Image0001": { - "name": "Image0001", - "uri": "Cesium_Logo_Flat.png" - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 + images: [ + {} + ], + textures: [ + { + source: 0 } - } + ] }; + removeImages(gltf); - expect(gltf.images.Image0001).toBeDefined(); - expect(Object.keys(gltf.images).length).toEqual(1); + expect(gltf.images.length).toEqual(1); }); }); @@ -1082,60 +853,57 @@ describe('RemoveUnusedProperties', function() { describe('removeSamplers', function() { it('removes a sampler', function() { var gltf = { - "samplers": { - "sampler_0": { - "magFilter": 9729, - "minFilter": 9987, - "wrapS": 10497, - "wrapT": 10497 + samplers: [ + { + name: 'unused' }, - "unusedSamplerId": { - "magFilter": 9729, - "minFilter": 9987, - "wrapS": 10497, - "wrapT": 10497 + { + magFilter: 9729, + minFilter: 9987, + wrapS: 10497, + wrapT: 10497 } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 + ], + textures: [ + { + format: 6408, + internalFormat: 6408, + sampler: 1, + source: 0, + target: 3553, + type: 5121 } - } + ] }; removeSamplers(gltf); - expect(gltf.samplers.unusedSamplerId).not.toBeDefined(); - expect(Object.keys(gltf.samplers).length).toEqual(1); + expect(gltf.samplers.length).toEqual(1); + expect(gltf.samplers[0].name).not.toEqual('unused'); + expect(gltf.textures[0].sampler).toEqual(0); }); it('does not remove any samplers', function() { var gltf = { - "samplers": { - "sampler_0": { - "magFilter": 9729, - "minFilter": 9987, - "wrapS": 10497, - "wrapT": 10497 + samplers: [ + { + magFilter: 9729, + minFilter: 9987, + wrapS: 10497, + wrapT: 10497 } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 + ], + textures: [ + { + format: 6408, + internalFormat: 6408, + sampler: 0, + source: 0, + target: 3553, + type: 5121 } - } + ] }; removeSamplers(gltf); - expect(gltf.samplers.sampler_0).toBeDefined(); - expect(Object.keys(gltf.samplers).length).toEqual(1); + expect(gltf.samplers.length).toEqual(1); }); }); @@ -1143,65 +911,64 @@ describe('RemoveUnusedProperties', function() { describe('removeShaders', function() { it('removes a shader', function() { var gltf = { - "programs": { - "program_0": { - "attributes": [ - "a_normal", - "a_position", - "a_texcoord0" + programs: [ + { + attributes: [ + 'a_normal', + 'a_position', + 'a_texcoord0' ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + fragmentShader: 1, + vertexShader: 2 } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "CesiumTexturedBoxTest0FS.glsl" + ], + shaders: [ + { + type: 35633, + uri: 'CesiumTexturedBoxTest0VS.glsl' }, - "CesiumTexturedBoxTest0VS": { - "type": 35633, - "uri": "CesiumTexturedBoxTest0VS.glsl" + { + type: 35632, + uri: 'CesiumTexturedBoxTest0FS.glsl' }, - "unusedShaderId": { - "type": 35633, - "uri": "CesiumTexturedBoxTest0VS.glsl" + { + type: 35633, + uri: 'CesiumTexturedBoxTest0VS.glsl' } - } + ] }; removeShaders(gltf); - expect(gltf.shaders.unusedShaderId).not.toBeDefined(); - expect(Object.keys(gltf.shaders).length).toEqual(2); + expect(gltf.shaders.length).toEqual(2); + expect(gltf.programs[0].fragmentShader).toEqual(0); + expect(gltf.programs[0].vertexShader).toEqual(1); }); it('does not remove any shaders', function() { var gltf = { - "programs": { - "program_0": { - "attributes": [ - "a_normal", - "a_position", - "a_texcoord0" + programs: [ + { + attributes: [ + 'a_normal', + 'a_position', + 'a_texcoord0' ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + fragmentShader: 0, + vertexShader: 1 } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "CesiumTexturedBoxTest0FS.glsl" + ], + shaders: [ + { + type: 35632, + uri: 'CesiumTexturedBoxTest0FS.glsl' }, - "CesiumTexturedBoxTest0VS": { - "type": 35633, - "uri": "CesiumTexturedBoxTest0VS.glsl" + { + type: 35633, + uri: 'CesiumTexturedBoxTest0VS.glsl' } - } + ] }; removeShaders(gltf); - expect(gltf.shaders.CesiumTexturedBoxTest0FS).toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0VS).toBeDefined(); - expect(Object.keys(gltf.shaders).length).toEqual(2); + expect(gltf.shaders.length).toEqual(2); }); }); @@ -1209,29 +976,29 @@ describe('RemoveUnusedProperties', function() { describe('removePrimitiveAttributes', function() { it('removes unused primitive attributes', function() { var gltf = { - meshes : { - mesh : { + meshes : [ + { primitives: [ { attributes : { - KEEP_ATTRIBUTE_1 : 'accessor_1', - KEEP_ATTRIBUTE_2 : 'accessor_2', - DROP_ATTRIBUTE_3 : 'accessor_3', - KEEP_ATTRIBUTE_4 : 'accessor_4', - DROP_ATTRIBUTE_5 : 'accessor_5' + KEEP_ATTRIBUTE_1 : 0, + KEEP_ATTRIBUTE_2 : 1, + DROP_ATTRIBUTE_3 : 2, + KEEP_ATTRIBUTE_4 : 3, + DROP_ATTRIBUTE_5 : 4 }, - material : 'material' + material : 0 } ] } - }, - materials : { - material : { - technique : 'technique' + ], + materials : [ + { + technique : 0 } - }, - techniques : { - technique : { + ], + techniques : [ + { parameters : { attribute1: { semantic : 'KEEP_ATTRIBUTE_1' @@ -1245,10 +1012,10 @@ describe('RemoveUnusedProperties', function() { } } } - } + ] }; removePrimitiveAttributes(gltf); - var attributes = gltf.meshes.mesh.primitives[0].attributes; + var attributes = gltf.meshes[0].primitives[0].attributes; expect(attributes.KEEP_ATTRIBUTE_1).toBeDefined(); expect(attributes.KEEP_ATTRIBUTE_2).toBeDefined(); expect(attributes.DROP_ATTRIBUTE_3).not.toBeDefined(); diff --git a/specs/lib/compressTexturesSpec.js b/specs/lib/compressTexturesSpec.js index e9898f25..9d75dd1f 100644 --- a/specs/lib/compressTexturesSpec.js +++ b/specs/lib/compressTexturesSpec.js @@ -13,6 +13,7 @@ var compressTextures = require('../../lib/compressTextures'); var directoryExists = require('../../lib/directoryExists'); var loadGltfUris = require('../../lib/loadGltfUris'); var readGltf = require('../../lib/readGltf'); +var writeSource = require('../../lib/writeSource'); var fsExtraReadJson = Promise.promisify(fsExtra.readJson); @@ -47,10 +48,13 @@ function compressGltfTexture(gltfPath, imagePath, options) { addPipelineExtras(gltf); addDefaults(gltf); return loadGltfUris(gltf, pipelineOptions) - .then(function(gltf) { + .then(function() { return compressTextures(gltf, options); }) - .then(function(gltf) { + .then(function() { + return writeSource(gltf.images, 'images', undefined, true, true); + }) + .then(function() { // Return the first compressed image var compressedImages = image.extras.compressedImage3DTiles; return compressedImages[Object.keys(compressedImages)[0]].uri; @@ -116,7 +120,7 @@ describe('compressTextures', function() { spyOn(console, 'log'); }); - fit('compresses external jpg', function(done) { + it('compresses external jpg', function(done) { expect(verifyKTX(gltfPath, jpgPath, etc1Compression, etc1Format), done).toResolve(); }); diff --git a/specs/lib/loadBufferUrisSpec.js b/specs/lib/loadBufferUrisSpec.js index 62fbba57..111f7c97 100644 --- a/specs/lib/loadBufferUrisSpec.js +++ b/specs/lib/loadBufferUrisSpec.js @@ -31,72 +31,72 @@ describe('loadBufferUris', function() { it('loads an external buffer', function(done) { var gltf = { - "buffers": { - "CesiumTexturedBoxTest": { - "uri": "CesiumTexturedBoxTest.bin" + buffers: [ + { + uri: "CesiumTexturedBoxTest.bin" } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.buffers.CesiumTexturedBoxTest.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.buffers.CesiumTexturedBoxTest.extras._pipeline.source, bufferData)).toBe(true); - expect(gltf.buffers.CesiumTexturedBoxTest.extras._pipeline.extension).toEqual('.bin'); + expect(gltf.buffers[0].extras._pipeline.source).toBeDefined(); + expect(bufferEqual(gltf.buffers[0].extras._pipeline.source, bufferData)).toBe(true); + expect(gltf.buffers[0].extras._pipeline.extension).toEqual('.bin'); done(); }); }); it('loads an embedded buffer', function(done) { var gltf = { - "buffers": { - "CesiumTexturedBoxTest": { - "uri": bufferUri + buffers: [ + { + uri: bufferUri } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.buffers.CesiumTexturedBoxTest.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.buffers.CesiumTexturedBoxTest.extras._pipeline.source, bufferData)).toBe(true); - expect(gltf.buffers.CesiumTexturedBoxTest.extras._pipeline.extension).toEqual('.bin'); + expect(gltf.buffers[0].extras._pipeline.source).toBeDefined(); + expect(bufferEqual(gltf.buffers[0].extras._pipeline.source, bufferData)).toBe(true); + expect(gltf.buffers[0].extras._pipeline.extension).toEqual('.bin'); done(); }); }); it('loads an external and an embedded buffer', function(done) { var gltf = { - "buffers": { - "embeddedBox": { - "uri": bufferUri + buffers: [ + { + uri: bufferUri }, - "externalBox": { - "uri": "CesiumTexturedBoxTest.bin" + { + uri: 'CesiumTexturedBoxTest.bin' } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.buffers.embeddedBox.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.buffers.embeddedBox.extras._pipeline.source, bufferData)).toBe(true); - expect(gltf.buffers.externalBox.extras._pipeline.source).toBeDefined(); - expect(gltf.buffers.externalBox.extras._pipeline.extension).toEqual('.bin'); + expect(gltf.buffers[0].extras._pipeline.source).toBeDefined(); + expect(bufferEqual(gltf.buffers[0].extras._pipeline.source, bufferData)).toBe(true); + expect(gltf.buffers[1].extras._pipeline.source).toBeDefined(); + expect(gltf.buffers[1].extras._pipeline.extension).toEqual('.bin'); done(); }); }); it('throws an error', function(done) { var gltf = { - "buffers": { - "CesiumTexturedBoxTest": { - "uri": "CesiumTexturedBoxTestError.bin" + buffers: [ + { + uri: 'CesiumTexturedBoxTestError.bin' } - } + ] }; addPipelineExtras(gltf); diff --git a/specs/lib/loadImageUrisSpec.js b/specs/lib/loadImageUrisSpec.js index 0088f132..ad5f7ab8 100644 --- a/specs/lib/loadImageUrisSpec.js +++ b/specs/lib/loadImageUrisSpec.js @@ -32,74 +32,74 @@ describe('loadImageUris', function() { it('loads an external image', function(done) { var gltf = { - "images": { - "Image0001": { - "uri": "Cesium_Logo_Flat_Low.png" + images: [ + { + uri: 'Cesium_Logo_Flat_Low.png' } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.images.Image0001.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.images.Image0001.extras._pipeline.source, imageData)).toBe(true); - expect(gltf.images.Image0001.extras._pipeline.extension).toEqual('.png'); + expect(gltf.images[0].extras._pipeline.source).toBeDefined(); + expect(bufferEqual(gltf.images[0].extras._pipeline.source, imageData)).toBe(true); + expect(gltf.images[0].extras._pipeline.extension).toEqual('.png'); done(); }); }); it('loads an embedded image', function(done) { var gltf = { - "images": { - "Image0001": { - "uri": imageUri + images: [ + { + uri: imageUri } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.images.Image0001.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.images.Image0001.extras._pipeline.source, imageData)).toBe(true); - expect(gltf.images.Image0001.extras._pipeline.extension).toEqual('.png'); + expect(gltf.images[0].extras._pipeline.source).toBeDefined(); + expect(bufferEqual(gltf.images[0].extras._pipeline.source, imageData)).toBe(true); + expect(gltf.images[0].extras._pipeline.extension).toEqual('.png'); done(); }); }); it('loads an external and an embedded image', function(done) { var gltf = { - "images": { - "embeddedImage0001": { - "uri": imageUri + images: [ + { + uri: imageUri }, - "externalImage0001": { - "uri": "Cesium_Logo_Flat_Low.png" + { + uri: "Cesium_Logo_Flat_Low.png" } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.images.embeddedImage0001.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.images.embeddedImage0001.extras._pipeline.source, imageData)).toBe(true); - expect(gltf.images.embeddedImage0001.extras._pipeline.extension).toEqual('.png'); - expect(gltf.images.externalImage0001.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.images.externalImage0001.extras._pipeline.source, imageData)).toBe(true); - expect(gltf.images.externalImage0001.extras._pipeline.extension).toEqual('.png'); + expect(gltf.images[0].extras._pipeline.source).toBeDefined(); + expect(bufferEqual(gltf.images[0].extras._pipeline.source, imageData)).toBe(true); + expect(gltf.images[0].extras._pipeline.extension).toEqual('.png'); + expect(gltf.images[0].extras._pipeline.source).toBeDefined(); + expect(bufferEqual(gltf.images[0].extras._pipeline.source, imageData)).toBe(true); + expect(gltf.images[0].extras._pipeline.extension).toEqual('.png'); done(); }); }); it('throws an error', function(done) { var gltf = { - "images": { - "Image0001": { - "uri": "Cesium_Logo_Error.png" + images: [ + { + uri: "Cesium_Logo_Error.png" } - } + ] }; addPipelineExtras(gltf); @@ -112,17 +112,17 @@ describe('loadImageUris', function() { it('adds jimpScratch and loads a jimp of the image', function(done) { var gltf = { - "images": { - "Image0001": { - "uri": imageUri + images: [ + { + uri: imageUri } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - var pipelineExtras = gltf.images.Image0001.extras._pipeline; + var pipelineExtras = gltf.images[0].extras._pipeline; expect(pipelineExtras.imageChanged).toEqual(false); expect(pipelineExtras.transparent).toEqual(false); var jimpImage = pipelineExtras.jimpImage; @@ -140,17 +140,17 @@ describe('loadImageUris', function() { it('detects that the loaded image is transparent', function(done) { var gltf = { - "images": { - "Image0001": { - "uri": transparentImageUri + images: [ + { + uri: transparentImageUri } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - var pipelineExtras = gltf.images.Image0001.extras._pipeline; + var pipelineExtras = gltf.images[0].extras._pipeline; expect(pipelineExtras.transparent).toEqual(true); done(); }); diff --git a/specs/lib/loadShaderUrisSpec.js b/specs/lib/loadShaderUrisSpec.js index e30f2f8e..817b7ff4 100644 --- a/specs/lib/loadShaderUrisSpec.js +++ b/specs/lib/loadShaderUrisSpec.js @@ -1,7 +1,6 @@ 'use strict'; var Promise = require('bluebird'); var fs = require('fs'); -var bufferEqual = require('buffer-equal'); var fsReadFile = Promise.promisify(fs.readFile); @@ -32,76 +31,76 @@ describe('loadShaderUris', function() { it('loads an external shader', function(done) { var gltf = { - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "CesiumTexturedBoxTest0FS.glsl" + shaders: [ + { + type: 35632, + uri: 'CesiumTexturedBoxTest0FS.glsl' } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras._pipeline.source).toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras._pipeline.source).toEqual(fragmentShaderData); - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras._pipeline.extension).toEqual('.glsl'); + expect(gltf.shaders[0].extras._pipeline.source).toBeDefined(); + expect(gltf.shaders[0].extras._pipeline.source).toEqual(fragmentShaderData); + expect(gltf.shaders[0].extras._pipeline.extension).toEqual('.glsl'); done(); }); }); it('loads an embedded shader', function(done) { var gltf = { - "shaders": { - "box0FS": { - "type": 35632, - "uri": fragmentShaderUri + shaders: [ + { + 'type': 35632, + 'uri': fragmentShaderUri } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.shaders.box0FS.extras._pipeline.source).toBeDefined(); - expect(gltf.shaders.box0FS.extras._pipeline.source).toEqual(fragmentShaderData); - expect(gltf.shaders.box0FS.extras._pipeline.extension).toEqual('.glsl'); + expect(gltf.shaders[0].extras._pipeline.source).toBeDefined(); + expect(gltf.shaders[0].extras._pipeline.source).toEqual(fragmentShaderData); + expect(gltf.shaders[0].extras._pipeline.extension).toEqual('.glsl'); done(); }); }); it('loads an external and an embedded shader', function(done) { var gltf = { - "shaders": { - "embeddedBox0FS": { - "type": 35632, - "uri": fragmentShaderUri + shaders: [ + { + type: 35632, + uri: fragmentShaderUri }, - "externalBox0FS": { - "type": 35632, - "uri": "CesiumTexturedBoxTest0FS.glsl" + { + type: 35632, + uri: 'CesiumTexturedBoxTest0FS.glsl' } - } + ] }; addPipelineExtras(gltf); loadGltfUris(gltf, options) .then(function() { - expect(gltf.shaders.externalBox0FS.extras._pipeline.source).toBeDefined(); - expect(gltf.shaders.embeddedBox0FS.extras._pipeline.source).toEqual(fragmentShaderData); - expect(gltf.shaders.externalBox0FS.extras._pipeline.extension).toEqual('.glsl'); + expect(gltf.shaders[0].extras._pipeline.source).toBeDefined(); + expect(gltf.shaders[0].extras._pipeline.source).toEqual(fragmentShaderData); + expect(gltf.shaders[0].extras._pipeline.extension).toEqual('.glsl'); done(); }); }); it('throws an error', function(done) { var gltf = { - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "CesiumTexturedBoxTestError.glsl" + shaders: [ + { + type: 35632, + uri: 'CesiumTexturedBoxTestError.glsl' } - } + ] }; addPipelineExtras(gltf); diff --git a/specs/lib/writeBuffersSpec.js b/specs/lib/writeBuffersSpec.js index 98b32369..5f668521 100644 --- a/specs/lib/writeBuffersSpec.js +++ b/specs/lib/writeBuffersSpec.js @@ -22,17 +22,18 @@ describe('writeBuffers', function() { .then(function(data) { bufferData = data; testGltf = { - "buffers": { - "CesiumTexturedBoxTest": { - "uri": "CesiumTexturedBoxTest.bin", - "extras": { - "_pipeline": { - "source": bufferData, - "extension": '.bin' + buffers: [ + { + uri: 'CesiumTexturedBoxTest.bin', + extras: { + _pipeline: { + source: bufferData, + extension: '.bin' } - } + }, + name: 'CesiumTexturedBoxTest' } - } + ] }; }), done).toResolve(); }); @@ -48,8 +49,8 @@ describe('writeBuffers', function() { expect(writeGltf(gltf, options) .then(function() { - expect(gltf.buffers.CesiumTexturedBoxTest.extras).not.toBeDefined(); - expect(gltf.buffers.CesiumTexturedBoxTest.uri).toEqual('CesiumTexturedBoxTest.bin'); + expect(gltf.buffers[0].extras).not.toBeDefined(); + expect(gltf.buffers[0].uri).toEqual('CesiumTexturedBoxTest.bin'); return fsReadFile(outputBufferPath); }) .then(function(outputData) { @@ -68,8 +69,8 @@ describe('writeBuffers', function() { expect(writeGltf(gltf, options) .then(function() { - expect(gltf.buffers.CesiumTexturedBoxTest.extras).not.toBeDefined(); - expect(gltf.buffers.CesiumTexturedBoxTest.uri).toEqual(bufferUri); + expect(gltf.buffers[0].extras).not.toBeDefined(); + expect(gltf.buffers[0].uri).toEqual(bufferUri); }), done).toResolve(); }); }); \ No newline at end of file diff --git a/specs/lib/writeImagesSpec.js b/specs/lib/writeImagesSpec.js index ce19ae3d..c5a380ca 100644 --- a/specs/lib/writeImagesSpec.js +++ b/specs/lib/writeImagesSpec.js @@ -22,17 +22,18 @@ describe('writeImages', function() { .then(function(data) { imageData = data; testGltf = { - "images": { - "Cesium_Logo_Flat_Low": { - "uri": imageUri, - "extras": { - "_pipeline": { - "source": imageData, - "extension": '.png' + images: [ + { + uri: imageUri, + extras: { + _pipeline: { + source: imageData, + extension: '.png' } - } + }, + name: 'Cesium_Logo_Flat_Low' } - } + ] }; }), done).toResolve(); }); @@ -48,8 +49,8 @@ describe('writeImages', function() { expect(writeGltf(gltf, options) .then(function() { - expect(gltf.images.Cesium_Logo_Flat_Low.extras).not.toBeDefined(); - expect(gltf.images.Cesium_Logo_Flat_Low.uri).toEqual('Cesium_Logo_Flat_Low.png'); + expect(gltf.images[0].extras).not.toBeDefined(); + expect(gltf.images[0].uri).toEqual('Cesium_Logo_Flat_Low.png'); return fsReadFile(outputImagePath); }) .then(function (outputData) { @@ -68,8 +69,8 @@ describe('writeImages', function() { expect(writeGltf(gltf, options) .then(function() { - expect(gltf.images.Cesium_Logo_Flat_Low.extras).not.toBeDefined(); - expect(gltf.images.Cesium_Logo_Flat_Low.uri).toEqual(imageUri); + expect(gltf.images[0].extras).not.toBeDefined(); + expect(gltf.images[0].uri).toEqual(imageUri); }), done).toResolve(); }); @@ -84,8 +85,8 @@ describe('writeImages', function() { expect(writeGltf(gltf, options) .then(function() { - expect(gltf.images.Cesium_Logo_Flat_Low.extras).not.toBeDefined(); - expect(gltf.images.Cesium_Logo_Flat_Low.uri).toEqual('Cesium_Logo_Flat_Low.png'); + expect(gltf.images[0].extras).not.toBeDefined(); + expect(gltf.images[0].uri).toEqual('Cesium_Logo_Flat_Low.png'); }), done).toResolve(); }); }); diff --git a/specs/lib/writeShadersSpec.js b/specs/lib/writeShadersSpec.js index 462877e6..5cb00f74 100644 --- a/specs/lib/writeShadersSpec.js +++ b/specs/lib/writeShadersSpec.js @@ -22,18 +22,18 @@ describe('writeShaders', function() { .then(function(data) { fragmentShaderData = data; testGltf = { - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": fragmentShaderUri, - "extras": { - "_pipeline": { - "source": fragmentShaderData, - "extension": '.glsl' + shaders: [ + { + type: 35632, + uri: fragmentShaderUri, + extras: { + _pipeline: { + source: fragmentShaderData, + extension: '.glsl' } } } - } + ] }; fragmentShaderUri = 'data:text/plain;base64,' + new Buffer(fragmentShaderData).toString('base64'); }), done).toResolve(); @@ -50,8 +50,8 @@ describe('writeShaders', function() { expect(writeGltf(gltf, options) .then(function() { - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras).not.toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0FS.uri).toEqual('CesiumTexturedBoxTest0FS.glsl'); + expect(gltf.shaders[0].extras).not.toBeDefined(); + expect(gltf.shaders[0].uri).toEqual('CesiumTexturedBoxTest0FS.glsl'); return fsReadFile(outputFragmentShaderPath); }) .then(function(outputData) { @@ -70,8 +70,8 @@ describe('writeShaders', function() { expect(writeGltf(gltf, options) .then(function() { - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras).not.toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0FS.uri).toEqual(fragmentShaderUri); + expect(gltf.shaders[0].extras).not.toBeDefined(); + expect(gltf.shaders[0].uri).toEqual(fragmentShaderUri); }), done).toResolve(); }); }); From 4c884d51e8ce918f732de428b459b0fcb4eb9c42 Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Fri, 3 Mar 2017 15:50:35 -0500 Subject: [PATCH 29/47] Fixed a few more failing tests --- lib/writeSource.js | 77 ++++++++++++++++++----------------- specs/lib/writeShadersSpec.js | 3 +- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/lib/writeSource.js b/lib/writeSource.js index 7919774d..38472b70 100644 --- a/lib/writeSource.js +++ b/lib/writeSource.js @@ -18,48 +18,51 @@ module.exports = writeSource; */ function writeSource(arrayOfObjects, name, basePath, embed, embedImage) { var promises = []; - var arrayLength = arrayOfObjects.length; - for (var i = 0; i < arrayLength; i++) { - var object = arrayOfObjects[i]; - if (defined(object.extras._pipeline.source)) { - var pipelineExtras = object.extras._pipeline; - var source = pipelineExtras.source; - var extension = pipelineExtras.extension; + if (defined(arrayOfObjects)) { + var arrayLength = arrayOfObjects.length; + for (var i = 0; i < arrayLength; i++) { + var object = arrayOfObjects[i]; + if (defined(object.extras._pipeline.source)) { + var pipelineExtras = object.extras._pipeline; + var source = pipelineExtras.source; + var extension = pipelineExtras.extension; - // Write sources for compressed textures - if (name === 'images') { - var image = object; - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - promises.push(writeSource(compressedImages, 'images', undefined, embed, embedImage)); + // Write sources for compressed textures + if (name === 'images') { + var image = object; + if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { + var compressedImages = image.extras.compressedImage3DTiles; + promises.push(writeSource(compressedImages, 'images', undefined, embed, embedImage)); + } } - } - if (embed && (embedImage || name !== 'images') || !defined(basePath)) { - if (name === 'shaders') { - object.uri = 'data:text/plain;base64,' + new Buffer(source).toString('base64'); + if (embed && (embedImage || name !== 'images') || !defined(basePath)) { + if (name === 'shaders') { + object.uri = 'data:text/plain;base64,' + new Buffer(source).toString('base64'); + } else { + // .crn (Crunch) is not a supported mime type, so add it + mime.define({'image/crn': ['crn']}); + object.uri = 'data:' + mime.lookup(extension) + ';base64,' + source.toString('base64'); + } } else { - // .crn (Crunch) is not a supported mime type, so add it - mime.define({'image/crn' : ['crn']}); - object.uri = 'data:' + mime.lookup(extension) + ';base64,' + source.toString('base64'); - } - } else { - var fileName = i + extension; - // Use the name if we have one - if (defined(object.name)) { - fileName = object.name + extension; + var fileName = i + extension; + // Use the name if we have one + if (defined(object.name)) { + fileName = object.name + extension; + } + var uri = object.uri; + if (defined(uri) && !isDataUri(uri)) { + // Use the original filename if it was external + fileName = uri; + } + // For compressed textures use the name stored in the extras rather than the id + if (defined(pipelineExtras.name)) { + fileName = pipelineExtras.name + extension; + } + object.uri = fileName; + var outputPath = path.join(basePath, fileName); + promises.push(fsOutputFile(outputPath, source)); } - var uri = object.uri; - if (defined(uri) && !isDataUri(uri)) { - // Use the original filename if it was external - fileName = uri; - } - - // For compressed textures use the name stored in the extras rather than the id - fileName = defaultValue(pipelineExtras.name + extension, fileName) ; - object.uri = fileName; - var outputPath = path.join(basePath, fileName); - promises.push(fsOutputFile(outputPath, source)); } } } diff --git a/specs/lib/writeShadersSpec.js b/specs/lib/writeShadersSpec.js index 5cb00f74..20194cc8 100644 --- a/specs/lib/writeShadersSpec.js +++ b/specs/lib/writeShadersSpec.js @@ -21,11 +21,13 @@ describe('writeShaders', function() { expect(fsReadFile(fragmentShaderPath) .then(function(data) { fragmentShaderData = data; + fragmentShaderUri = 'data:text/plain;base64,' + new Buffer(fragmentShaderData).toString('base64'); testGltf = { shaders: [ { type: 35632, uri: fragmentShaderUri, + name: 'CesiumTexturedBoxTest0FS', extras: { _pipeline: { source: fragmentShaderData, @@ -35,7 +37,6 @@ describe('writeShaders', function() { } ] }; - fragmentShaderUri = 'data:text/plain;base64,' + new Buffer(fragmentShaderData).toString('base64'); }), done).toResolve(); }); From 13aa73d35aae919605ee1a7a40669884c7c4242c Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Fri, 10 Mar 2017 12:16:17 -0500 Subject: [PATCH 30/47] Removed findUsedIds --- lib/findUsedIds.js | 26 ------------------------ specs/lib/findUsedIdsSpec.js | 39 ------------------------------------ 2 files changed, 65 deletions(-) delete mode 100644 lib/findUsedIds.js delete mode 100644 specs/lib/findUsedIdsSpec.js diff --git a/lib/findUsedIds.js b/lib/findUsedIds.js deleted file mode 100644 index 462c3cb3..00000000 --- a/lib/findUsedIds.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -var Cesium = require('cesium'); -var defined = Cesium.defined; - -module.exports = findUsedIds; - -/** - * @private - */ -function findUsedIds(gltf, name, propertyName) { - var usedIds = {}; - var array = gltf[name]; - - if (defined(array)) { - var arrayLength = array.length; - for (var id = 0; id < arrayLength; id++) { - var object = array[id]; - var idProperty = object[propertyName]; - if (defined(idProperty)) { - usedIds[idProperty] = true; - } - } - } - - return usedIds; -} \ No newline at end of file diff --git a/specs/lib/findUsedIdsSpec.js b/specs/lib/findUsedIdsSpec.js deleted file mode 100644 index 81481b3b..00000000 --- a/specs/lib/findUsedIdsSpec.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; - -var findUsedIds = require('../../lib/findUsedIds'); - -describe('findUsedIds', function() { - it('finds used ids', function() { - var gltf = { - "samplers": { - "sampler_0": { - "magFilter": 9729, - "minFilter": 9987, - "wrapS": 10497, - "wrapT": 10497 - }, - "unusedSamplerId": { - "magFilter": 9729, - "minFilter": 9987, - "wrapS": 10497, - "wrapT": 10497 - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 - } - } - }; - - var usedSamplerIds = findUsedIds(gltf, 'textures', 'sampler'); - expect(usedSamplerIds).toEqual({ - sampler_0 : true - }); - }); -}); \ No newline at end of file From b5d80024587bb72fe67520b0645b8d774b7abb31 Mon Sep 17 00:00:00 2001 From: Robert Taglang Date: Mon, 20 Mar 2017 13:15:38 -0400 Subject: [PATCH 31/47] WIP, switching workspaces --- lib/ForEach.js | 40 +- lib/PrimitiveHelpers.js | 13 +- lib/Remove.js | 67 +- lib/RemoveUnusedProperties.js | 82 +- lib/addDefaults.js | 10 +- lib/addPipelineExtras.js | 3 - lib/combinePrimitives.js | 33 +- lib/compressTextures.js | 4 +- lib/encodeImages.js | 45 +- lib/generateNormals.js | 7 +- lib/getBinaryGltf.js | 217 +++-- lib/getStatistics.js | 89 +- lib/loadGltfUris.js | 3 +- lib/mergeBuffers.js | 74 +- lib/optimizeForVertexCache.js | 57 +- lib/parseBinaryGltf.js | 233 ++--- lib/removeExtensionsRequired.js | 25 + lib/removeExtensionsUsed.js | 27 + lib/uninterleaveAndPackBuffers.js | 242 +++--- lib/updateVersion.js | 794 +++++++++--------- lib/writeBinaryGltf.js | 28 +- lib/writeGltf.js | 13 +- lib/writeSource.js | 83 +- .../CesiumTexturedBoxTestUnusedTree.gltf | 182 ++-- .../CesiumTexturedBoxTest_Binary.gltf | 148 ++-- .../CesiumTexturedBoxTest_BinaryCheck.gltf | 192 ++--- .../CesiumTexturedBoxTest_BinaryInput.gltf | 162 ++-- .../data/generateNormals/box_no_normals.gltf | 86 +- specs/data/generateNormals/box_normals.gltf | 128 +-- specs/lib/RemoveUnusedPropertiesSpec.js | 108 +-- specs/lib/combinePrimitivesSpec.js | 434 +++++----- specs/lib/encodeImagesSpec.js | 24 +- specs/lib/generateNormalsSpec.js | 10 +- specs/lib/getBinaryGltfSpec.js | 224 ++--- specs/lib/getStatisticsSpec.js | 115 ++- specs/lib/mergeBuffersSpec.js | 97 +-- specs/lib/optimizeForVertexCacheSpec.js | 2 +- specs/lib/parseBinaryGltfSpec.js | 263 +++--- specs/lib/uninterleaveAndPackBuffersSpec.js | 54 +- specs/lib/updateVersionSpec.js | 80 +- specs/lib/writeBinaryGltfSpec.js | 31 +- 41 files changed, 2108 insertions(+), 2421 deletions(-) create mode 100644 lib/removeExtensionsRequired.js create mode 100644 lib/removeExtensionsUsed.js diff --git a/lib/ForEach.js b/lib/ForEach.js index 3dbbd652..f2991f26 100644 --- a/lib/ForEach.js +++ b/lib/ForEach.js @@ -14,18 +14,18 @@ module.exports = ForEach; function ForEach() {} ForEach.arrayOfObjects = function(arrayOfObjects, handler) { - for (var i = 0; i < arrayOfObjects.length; i++) { - var object = arrayOfObjects[i]; - var offset = defaultValue(handler(i, object), 0); - i += offset; + if (defined(arrayOfObjects)) { + for (var i = 0; i < arrayOfObjects.length; i++) { + var object = arrayOfObjects[i]; + var offset = defaultValue(handler(object, i), 0); + i += offset; + } } }; ForEach.topLevel = function(gltf, name, handler) { var arrayOfObjects = gltf[name]; - if (defined(arrayOfObjects)) { - ForEach.arrayOfObjects(arrayOfObjects, handler); - } + ForEach.arrayOfObjects(arrayOfObjects, handler); }; ForEach.accessor = function(gltf, handler) { @@ -68,7 +68,7 @@ ForEach.materialValue = function(material, handler) { if (defined(values)) { for (var name in values) { if (values.hasOwnProperty(name)) { - handler(name, values[name]); + handler(values[name], name); } } } @@ -84,7 +84,7 @@ ForEach.meshPrimitives = function(mesh, handler) { var primitivesLength = primitives.length; for (var i = 0; i < primitivesLength; i++) { var primitive = primitives[i]; - handler(i, primitive); + handler(primitive, i); } } }; @@ -94,7 +94,7 @@ ForEach.meshPrimitiveAttributes = function(primitive, handler) { if (defined(attributes)) { for (var semantic in attributes) { if (attributes.hasOwnProperty(semantic)) { - handler(semantic, attributes[semantic]); + handler(attributes[semantic], semantic); } } } @@ -111,7 +111,7 @@ ForEach.nodeInTree = function(gltf, nodeIds, handler) { var nodeId = nodeIds[i]; var node = nodes[nodeId]; if (defined(node)) { - handler(nodeId, node); + handler(node, nodeId); var children = node.children; if (defined(children)) { ForEach.nodeInTree(gltf, children, handler); @@ -121,16 +121,10 @@ ForEach.nodeInTree = function(gltf, nodeIds, handler) { } }; -ForEach.nodeInScene = function(gltf, sceneId, handler) { - var scenes = gltf.scenes; - if (defined(scenes)) { - var scene = scenes[sceneId]; - if (defined(scene)) { - var sceneNodeIds = scene.nodes; - if (defined(sceneNodeIds)) { - ForEach.nodeInTree(gltf, sceneNodeIds, handler); - } - } +ForEach.nodeInScene = function(gltf, scene, handler) { + var sceneNodeIds = scene.nodes; + if (defined(sceneNodeIds)) { + ForEach.nodeInTree(gltf, sceneNodeIds, handler); } }; @@ -159,7 +153,7 @@ ForEach.techniqueAttribute = function(technique, handler) { if (defined(attributes)) { for (var semantic in attributes) { if (attributes.hasOwnProperty(semantic)) { - handler(semantic, attributes[semantic]); + handler(attributes[semantic], semantic); } } } @@ -170,7 +164,7 @@ ForEach.techniqueParameter = function(technique, handler) { if (defined(parameters)) { for (var parameterName in parameters) { if (parameters.hasOwnProperty(parameterName)) { - handler(parameterName, parameters[parameterName]); + handler(parameters[parameterName], parameterName); } } } diff --git a/lib/PrimitiveHelpers.js b/lib/PrimitiveHelpers.js index 0a5218d0..c2161c92 100644 --- a/lib/PrimitiveHelpers.js +++ b/lib/PrimitiveHelpers.js @@ -2,6 +2,7 @@ var Cesium = require('cesium'); var deepEqual = require('deep-equal'); var AccessorReader = require('./AccessorReader'); +var ForEach = require('./ForEach'); var getPrimitiveAttributeSemantics = require('./getPrimitiveAttributeSemantics'); var readAccessor = require('./readAccessor'); @@ -240,13 +241,11 @@ function getPrimitiveConflicts(primitives, primitive) { */ function getAllPrimitives(gltf) { var primitives = []; - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - primitives = primitives.concat(mesh.primitives); - } - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + primitives.push(primitive); + }); + }); return primitives; } diff --git a/lib/Remove.js b/lib/Remove.js index b9883ecc..e5378eaf 100644 --- a/lib/Remove.js +++ b/lib/Remove.js @@ -20,10 +20,9 @@ Remove.accessor = function(gltf, accessorId) { accessors.splice(accessorId, 1); - /* jshint unused:vars */ - ForEach.mesh(gltf, function(meshId, mesh) { - ForEach.meshPrimitives(mesh, function(i, primitive) { - ForEach.meshPrimitiveAttributes(primitive, function(semantic, attributeAccessorId) { + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitiveAttributes(primitive, function(attributeAccessorId, semantic) { if (attributeAccessorId > accessorId) { primitive.attributes[semantic]--; } @@ -35,14 +34,14 @@ Remove.accessor = function(gltf, accessorId) { }); }); - ForEach.skin(gltf, function(skinId, skin) { + ForEach.skin(gltf, function(skin) { if (defined(skin.inverseBindMatrices) && skin.inverseBindMatrices > accessorId) { skin.inverseBindMatrices--; } }); - ForEach.animation(gltf, function(animationId, animation) { - ForEach.animationSamplers(animation, function(samplerId, sampler) { + ForEach.animation(gltf, function(animation) { + ForEach.animationSamplers(animation, function(sampler) { if (defined(sampler.input) && sampler.input > accessorId) { sampler.input--; } @@ -58,8 +57,7 @@ Remove.buffer = function(gltf, bufferId) { buffers.splice(bufferId, 1); - /* jshint unused:vars */ - ForEach.bufferView(gltf, function(bufferViewId, bufferView) { + ForEach.bufferView(gltf, function(bufferView) { if (defined(bufferView.buffer) && bufferView.buffer > bufferId) { bufferView.buffer--; } @@ -71,8 +69,7 @@ Remove.bufferView = function(gltf, bufferViewId) { bufferViews.splice(bufferViewId, 1); - /* jshint unused:vars */ - ForEach.accessor(gltf, function(accessorId, accessor) { + ForEach.accessor(gltf, function(accessor) { if (defined(accessor.bufferView) && accessor.bufferView > bufferViewId) { accessor.bufferView--; } @@ -84,8 +81,7 @@ Remove.camera = function(gltf, cameraId) { cameras.splice(cameraId, 1); - /* jshint unused:vars */ - ForEach.node(gltf, function(nodeId, node) { + ForEach.node(gltf, function(node) { if (defined(node.camera) && node.camera > cameraId) { node.camera--; } @@ -97,8 +93,7 @@ Remove.image = function(gltf, imageId) { images.splice(imageId, 1); - /* jshint unused:vars */ - ForEach.texture(gltf, function(textureId, texture) { + ForEach.texture(gltf, function(texture) { if (defined(texture.source) && texture.source > imageId) { texture.source--; } @@ -110,9 +105,8 @@ Remove.material = function(gltf, materialId) { materials.splice(materialId, 1); - /* jshint unused:vars */ - ForEach.mesh(gltf, function(meshId, mesh) { - ForEach.meshPrimitives(mesh, function(i, primitive) { + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { if (defined(primitive.material) && primitive.material > materialId) { primitive.material--; } @@ -125,8 +119,7 @@ Remove.mesh = function(gltf, meshId) { meshes.splice(meshId, 1); - /* jshint unused:vars */ - ForEach.node(gltf, function(nodeId, node) { + ForEach.node(gltf, function(node) { if (defined(node.mesh) && node.mesh > meshId) { node.mesh--; } @@ -138,8 +131,7 @@ Remove.node = function(gltf, nodeId) { nodes.splice(nodeId, 1); - /* jshint unused:vars */ - ForEach.node(gltf, function(id, node) { + ForEach.node(gltf, function(node) { var children = node.children; if (defined(children)) { var childrenLength = children.length; @@ -162,16 +154,15 @@ Remove.node = function(gltf, nodeId) { } }); - ForEach.technique(gltf, function(techniqueId, technique) { - /* jshint unused:vars */ - ForEach.techniqueParameter(technique, function(name, value) { + ForEach.technique(gltf, function(technique) { + ForEach.techniqueParameter(technique, function(value) { if (defined(value.node) && value.node > nodeId) { value.node--; } }); }); - ForEach.scene(gltf, function(sceneId, scene) { + ForEach.scene(gltf, function(scene) { var sceneNodeIds = scene.nodes; if (defined(sceneNodeIds)) { var sceneNodeIdsLength = sceneNodeIds.length; @@ -190,8 +181,7 @@ Remove.program = function(gltf, programId) { programs.splice(programId, 1); - /* jshint unused:vars */ - ForEach.technique(gltf, function(techniqueId, technique) { + ForEach.technique(gltf, function(technique) { if (defined(technique.program) && technique.program > programId) { technique.program--; } @@ -203,8 +193,7 @@ Remove.sampler = function(gltf, samplerId) { samplers.splice(samplerId, 1); - /* jshint unused:vars */ - ForEach.texture(gltf, function(textureId, texture) { + ForEach.texture(gltf, function(texture) { if (defined(texture.sampler) && texture.sampler > samplerId) { texture.sampler--; } @@ -216,8 +205,7 @@ Remove.shader = function(gltf, shaderId) { shaders.splice(shaderId, 1); - /* jshint unused:vars */ - ForEach.program(gltf, function(programId, program) { + ForEach.program(gltf, function(program) { if (defined(program.vertexShader) && program.vertexShader > shaderId) { program.vertexShader--; } @@ -232,8 +220,7 @@ Remove.skin = function(gltf, skinId) { skins.splice(skinId, 1); - /* jshint unused:vars */ - ForEach.node(gltf, function(nodeId, node) { + ForEach.node(gltf, function(node) { if (defined(node.skin) && node.skin > skinId) { node.skin--; } @@ -245,8 +232,7 @@ Remove.technique = function(gltf, techniqueId) { techniques.splice(techniqueId, 1); - /* jshint unused:vars */ - ForEach.material(gltf, function(materialId, material) { + ForEach.material(gltf, function(material) { if (defined(material.technique) && material.technique > techniqueId) { material.technique--; } @@ -258,9 +244,8 @@ Remove.texture = function(gltf, textureId) { textures.splice(textureId, 1); - /* jshint unused:vars */ - ForEach.material(gltf, function(materialId, material) { - ForEach.materialValue(material, function(name, value) { + ForEach.material(gltf, function(material) { + ForEach.materialValue(material, function(value, name) { if (isTexture(name, value)) { if (value[0] > textureId) { value[0]--; @@ -269,8 +254,8 @@ Remove.texture = function(gltf, textureId) { }); }); - ForEach.technique(gltf, function(techniqueId, technique) { - ForEach.techniqueParameter(technique, function(name, parameter) { + ForEach.technique(gltf, function(technique) { + ForEach.techniqueParameter(technique, function(parameter, name) { var value = parameter.value; if (defined(value)) { if (isTexture(name, value)) { diff --git a/lib/RemoveUnusedProperties.js b/lib/RemoveUnusedProperties.js index a470c8d0..57b7efa5 100644 --- a/lib/RemoveUnusedProperties.js +++ b/lib/RemoveUnusedProperties.js @@ -41,7 +41,8 @@ RemoveUnusedProperties.removeAll = function(gltf) { function removeUnusedElements(gltf, type, usedIds) { var removed = 0; - ForEach[type](gltf, function(id) { + /* jshint unused:vars */ + ForEach[type](gltf, function(object, id) { if (!usedIds[id + removed]) { Remove[type](gltf, id); removed++; @@ -59,8 +60,8 @@ function removeUnusedElements(gltf, type, usedIds) { RemoveUnusedProperties.removeNodes = function(gltf) { var usedNodeIds = {}; - ForEach.scene(gltf, function(sceneId) { - ForEach.nodeInScene(gltf, sceneId, function(nodeId, node) { + ForEach.scene(gltf, function(scene) { + ForEach.nodeInScene(gltf, scene, function(node, nodeId) { usedNodeIds[nodeId] = true; var skeletons = node.skeletons; if (defined(skeletons)) { @@ -72,9 +73,8 @@ RemoveUnusedProperties.removeNodes = function(gltf) { }); }); - /* jshint unused:vars */ - ForEach.technique(gltf, function(techniqueId, technique) { - ForEach.techniqueParameter(technique, function(name, value) { + ForEach.technique(gltf, function(technique) { + ForEach.techniqueParameter(technique, function(value) { if (defined(value.node)) { usedNodeIds[value.node] = true; } @@ -94,8 +94,7 @@ RemoveUnusedProperties.removeNodes = function(gltf) { RemoveUnusedProperties.removeSkins = function(gltf) { var usedSkinIds = {}; - /* jshint unused:vars */ - ForEach.node(gltf, function(nodeId, node) { + ForEach.node(gltf, function(node) { var nodeSkinId = node.skin; if (defined(nodeSkinId)) { usedSkinIds[nodeSkinId] = true; @@ -115,8 +114,7 @@ RemoveUnusedProperties.removeSkins = function(gltf) { RemoveUnusedProperties.removeCameras = function(gltf) { var usedCameraIds = {}; - /* jshint unused:vars */ - ForEach.node(gltf, function(nodeId, node) { + ForEach.node(gltf, function(node) { var cameraId = node.camera; if (defined(cameraId)) { usedCameraIds[cameraId] = true; @@ -136,8 +134,7 @@ RemoveUnusedProperties.removeCameras = function(gltf) { RemoveUnusedProperties.removeMeshes = function(gltf) { var usedMeshIds = {}; - /* jshint unused:vars */ - ForEach.node(gltf, function(nodeId, node) { + ForEach.node(gltf, function(node) { var meshId = node.mesh; if (defined(meshId)) { usedMeshIds[meshId] = true; @@ -157,10 +154,9 @@ RemoveUnusedProperties.removeMeshes = function(gltf) { RemoveUnusedProperties.removeAccessors = function(gltf) { var usedAccessorIds = {}; - /* jshint unused:vars */ - ForEach.mesh(gltf, function(meshId, mesh) { - ForEach.meshPrimitives(mesh, function(i, primitive) { - ForEach.meshPrimitiveAttributes(primitive, function(semantic, accessorId) { + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitiveAttributes(primitive, function(accessorId) { usedAccessorIds[accessorId] = true; }); var indices = primitive.indices; @@ -170,16 +166,14 @@ RemoveUnusedProperties.removeAccessors = function(gltf) { }); }); - /* jshint unused:vars */ - ForEach.skin(gltf, function(skinId, skin) { + ForEach.skin(gltf, function(skin) { if (defined(skin.inverseBindMatrices)) { usedAccessorIds[skin.inverseBindMatrices] = true; } }); - /* jshint unused:vars */ - ForEach.animation(gltf, function(animationId, animation) { - ForEach.animationSamplers(animation, function(samplerId, sampler) { + ForEach.animation(gltf, function(animation) { + ForEach.animationSamplers(animation, function(sampler) { if (defined(sampler.input)) { usedAccessorIds[sampler.input] = true; } @@ -202,9 +196,8 @@ RemoveUnusedProperties.removeAccessors = function(gltf) { RemoveUnusedProperties.removeMaterials = function(gltf) { var usedMaterialIds = {}; - /* jshint unused:vars */ - ForEach.mesh(gltf, function(meshId, mesh) { - ForEach.meshPrimitives(mesh, function(i, primitive) { + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { if (defined(primitive.material)) { usedMaterialIds[primitive.material] = true; } @@ -224,8 +217,7 @@ RemoveUnusedProperties.removeMaterials = function(gltf) { RemoveUnusedProperties.removeBufferViews = function(gltf) { var usedBufferViewIds = {}; - /* jshint unused:vars */ - ForEach.accessor(gltf, function(accessorId, accessor) { + ForEach.accessor(gltf, function(accessor) { if (defined(accessor.bufferView)) { usedBufferViewIds[accessor.bufferView] = true; } @@ -244,8 +236,7 @@ RemoveUnusedProperties.removeBufferViews = function(gltf) { RemoveUnusedProperties.removeTechniques = function(gltf) { var usedTechniqueIds = {}; - /* jshint unused:vars */ - ForEach.material(gltf, function(materialId, material) { + ForEach.material(gltf, function(material) { if (defined(material.technique)) { usedTechniqueIds[material.technique] = true; } @@ -264,18 +255,16 @@ RemoveUnusedProperties.removeTechniques = function(gltf) { RemoveUnusedProperties.removeTextures = function(gltf) { var usedTextureIds = {}; - /* jshint unused:vars */ - ForEach.material(gltf, function(materialId, material) { - ForEach.materialValue(material, function(name, value) { + ForEach.material(gltf, function(material) { + ForEach.materialValue(material, function(value, name) { if (isTexture(name, value)) { usedTextureIds[value[0]] = true; } }); }); - /* jshint unused:vars */ - ForEach.technique(gltf, function(techniqueId, technique) { - ForEach.techniqueParameter(technique, function(name, parameter) { + ForEach.technique(gltf, function(technique) { + ForEach.techniqueParameter(technique, function(parameter, name) { var value = parameter.value; if (defined(value)) { if (isTexture(name, value)) { @@ -298,8 +287,7 @@ RemoveUnusedProperties.removeTextures = function(gltf) { RemoveUnusedProperties.removeBuffers = function(gltf) { var usedBufferIds = {}; - /* jshint unused:vars */ - ForEach.bufferView(gltf, function(bufferViewId, bufferView) { + ForEach.bufferView(gltf, function(bufferView) { if (defined(bufferView.buffer)) { usedBufferIds[bufferView.buffer] = true; } @@ -318,8 +306,7 @@ RemoveUnusedProperties.removeBuffers = function(gltf) { RemoveUnusedProperties.removePrograms = function(gltf) { var usedProgramIds = {}; - /* jshint unused:vars */ - ForEach.technique(gltf, function(techniqueId, technique) { + ForEach.technique(gltf, function(technique) { if (defined(technique.program)) { usedProgramIds[technique.program] = true; } @@ -338,8 +325,7 @@ RemoveUnusedProperties.removePrograms = function(gltf) { RemoveUnusedProperties.removeImages = function(gltf) { var usedImageIds = {}; - /* jshint unused:vars */ - ForEach.texture(gltf, function(textureId, texture) { + ForEach.texture(gltf, function(texture) { if (defined(texture.source)) { usedImageIds[texture.source] = true; } @@ -357,8 +343,7 @@ RemoveUnusedProperties.removeImages = function(gltf) { RemoveUnusedProperties.removeSamplers = function(gltf) { var usedSamplerIds = {}; - /* jshint unused:vars */ - ForEach.texture(gltf, function(textureId, texture) { + ForEach.texture(gltf, function(texture) { if (defined(texture.sampler)) { usedSamplerIds[texture.sampler] = true; } @@ -377,8 +362,7 @@ RemoveUnusedProperties.removeSamplers = function(gltf) { RemoveUnusedProperties.removeShaders = function(gltf) { var usedShaderIds = {}; - /* jshint unused:vars */ - ForEach.program(gltf, function(programId, program) { + ForEach.program(gltf, function(program) { if (defined(program.vertexShader)) { usedShaderIds[program.vertexShader] = true; } @@ -401,12 +385,12 @@ RemoveUnusedProperties.removePrimitiveAttributes = function(gltf) { var materials = gltf.materials; var techniques = gltf.techniques; - /* jshint unused:vars */ - ForEach.mesh(gltf, function(meshId, mesh) { - ForEach.meshPrimitives(mesh, function(i, primitive) { + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { var usedAttributes = {}; var hasAttributes = false; - ForEach.meshPrimitiveAttributes(primitive, function(semantic) { + /* jshint unused:vars */ + ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { usedAttributes[semantic] = false; hasAttributes = true; }); @@ -417,7 +401,7 @@ RemoveUnusedProperties.removePrimitiveAttributes = function(gltf) { var techniqueId = material.technique; if (defined(techniqueId)) { var technique = techniques[techniqueId]; - ForEach.techniqueParameter(technique, function (name, parameter) { + ForEach.techniqueParameter(technique, function (parameter) { if (defined(parameter.semantic)) { usedAttributes[parameter.semantic] = true; } diff --git a/lib/addDefaults.js b/lib/addDefaults.js index 341c109f..1bf47e3e 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -25,13 +25,7 @@ var gltfTemplate = { ] } ], - asset : { - premultipliedAlpha : false, - profile : { - api : 'WebGL', - version : '1.0' - } - }, + asset : {}, buffers : [ { byteLength: 0, @@ -62,7 +56,7 @@ var gltfTemplate = { var defaults = { ambient: [0.0, 0.0, 0.0, 1.0], emission: [0.0, 0.0, 0.0, 1.0], - transparency: [1.0], + transparency: [1.0] }; if (technique !== 'CONSTANT') { defaults.diffuse = [0.0, 0.0, 0.0, 1.0]; diff --git a/lib/addPipelineExtras.js b/lib/addPipelineExtras.js index 35fc5f4b..bde4ad5e 100644 --- a/lib/addPipelineExtras.js +++ b/lib/addPipelineExtras.js @@ -57,8 +57,5 @@ function addPipelineExtras(gltf) { gltf.asset = defaultValue(gltf.asset, {}); gltf.asset.extras = defaultValue(gltf.asset.extras, {}); gltf.asset.extras._pipeline = defaultValue(gltf.asset.extras._pipeline, {}); - gltf.asset.profile = defaultValue(gltf.asset.profile, {}); - gltf.asset.profile.extras = defaultValue(gltf.asset.profile.extras, {}); - gltf.asset.profile.extras._pipeline = defaultValue(gltf.asset.profile.extras_pipeline, {}); return gltf; } \ No newline at end of file diff --git a/lib/combinePrimitives.js b/lib/combinePrimitives.js index 0962793a..c30431a1 100644 --- a/lib/combinePrimitives.js +++ b/lib/combinePrimitives.js @@ -1,6 +1,7 @@ 'use strict'; var Cesium = require('cesium'); var deepEqual = require('deep-equal'); +var ForEach = require('./ForEach'); var PrimitiveHelpers = require('./PrimitiveHelpers'); var createAccessor = require('./createAccessor'); var readAccessor = require('./readAccessor'); @@ -26,29 +27,25 @@ module.exports = combinePrimitives; */ function combinePrimitives(gltf) { var allPrimitives = PrimitiveHelpers.getAllPrimitives(gltf); - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitivesByMaterialMode = PrimitiveHelpers.getPrimitivesByMaterialMode(mesh.primitives); - mesh.primitives = []; - for (var materialId in primitivesByMaterialMode) { - if (primitivesByMaterialMode.hasOwnProperty(materialId)) { - var primitivesByMode = primitivesByMaterialMode[materialId]; - for (var mode in primitivesByMode) { - if (primitivesByMode.hasOwnProperty(mode)) { - var primitives = primitivesByMode[mode]; - primitives = combinePrimitivesInGroup(gltf, allPrimitives, primitives, materialId, parseInt(mode), false); - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - mesh.primitives.push(primitives[i]); - } + ForEach.mesh(gltf, function(mesh) { + var primitivesByMaterialMode = PrimitiveHelpers.getPrimitivesByMaterialMode(mesh.primitives); + mesh.primitives = []; + for (var materialId in primitivesByMaterialMode) { + if (primitivesByMaterialMode.hasOwnProperty(materialId)) { + var primitivesByMode = primitivesByMaterialMode[materialId]; + for (var mode in primitivesByMode) { + if (primitivesByMode.hasOwnProperty(mode)) { + var primitives = primitivesByMode[mode]; + primitives = combinePrimitivesInGroup(gltf, allPrimitives, primitives, materialId, parseInt(mode), false); + var primitivesLength = primitives.length; + for (var i = 0; i < primitivesLength; i++) { + mesh.primitives.push(primitives[i]); } } } } } - } + }); } function combinePrimitivesInGroup(gltf, allPrimitives, primitives, materialId, mode, uint32Enabled) { diff --git a/lib/compressTextures.js b/lib/compressTextures.js index dc9f8db7..eac054b4 100644 --- a/lib/compressTextures.js +++ b/lib/compressTextures.js @@ -49,7 +49,7 @@ function compressTextures(gltf, options) { for (var imageId = 0; imageId < imagesLength; imageId++) { var image = images[imageId]; var pipelineExtras = image.extras._pipeline; - var compressedImages = {}; + var compressedImages = []; var length = optionsArray.length; for (var i = 0; i < length; ++i) { var compressionOptions = optionsArray[i]; @@ -71,7 +71,7 @@ function compressTextures(gltf, options) { } } }; - compressedImages[compressedType] = compressedImage; + compressedImages.push(compressedImage); promises.push(compressTexture(gltf, imageId, compressionOptions) .then(replaceImage(compressedImage))); } diff --git a/lib/encodeImages.js b/lib/encodeImages.js index 9c0ab329..f39aa9bc 100644 --- a/lib/encodeImages.js +++ b/lib/encodeImages.js @@ -1,6 +1,7 @@ 'use strict'; var Jimp = require('jimp'); var Promise = require('bluebird'); +var ForEach = require('./ForEach'); Jimp.prototype.getBufferAsync = Promise.promisify(Jimp.prototype.getBuffer); @@ -18,33 +19,29 @@ module.exports = encodeImages; * @see loadGltfUris */ function encodeImages(gltf) { - var images = gltf.images; var promises = []; - for (var imageId in images) { - if (images.hasOwnProperty(imageId)) { - var image = images[imageId]; - var pipelineExtras = image.extras._pipeline; - if (pipelineExtras.imageChanged) { - // re-encode the jimp image here to a buffer that can be put in source - var mime; - switch (pipelineExtras.extension) { - case '.png': - mime = Jimp.MIME_PNG; - break; - case '.jpeg': - mime = Jimp.MIME_JPEG; - break; - case '.jpg': - mime = Jimp.MIME_JPEG; - break; - case '.bmp': - mime = Jimp.MIME_BMP; - break; - } - promises.push(loadImageSource(pipelineExtras, mime)); + ForEach.image(gltf, function(image) { + var pipelineExtras = image.extras._pipeline; + if (pipelineExtras.imageChanged) { + // re-encode the jimp image here to a buffer that can be put in source + var mime; + switch (pipelineExtras.extension) { + case '.png': + mime = Jimp.MIME_PNG; + break; + case '.jpeg': + mime = Jimp.MIME_JPEG; + break; + case '.jpg': + mime = Jimp.MIME_JPEG; + break; + case '.bmp': + mime = Jimp.MIME_BMP; + break; } + promises.push(loadImageSource(pipelineExtras, mime)); } - } + }); return Promise.all(promises) .then(function() { return gltf; diff --git a/lib/generateNormals.js b/lib/generateNormals.js index 0cb79079..3217aab0 100644 --- a/lib/generateNormals.js +++ b/lib/generateNormals.js @@ -10,11 +10,11 @@ var defined = Cesium.defined; var RemoveUnusedProperties = require('./RemoveUnusedProperties'); var addExtensionsUsed = require('./addExtensionsUsed'); +var addToArray = require('./addToArray'); var cesiumGeometryToGltfPrimitive = require('./cesiumGeometryToGltfPrimitive'); var createAccessor = require('./createAccessor'); var gltfPrimitiveToCesiumGeometry = require('./gltfPrimitiveToCesiumGeometry'); var getPrimitiveAttributeSemantics = require('./getPrimitiveAttributeSemantics'); -var getUniqueId = require('./getUniqueId'); var mergeBuffers = require('./mergeBuffers'); var processModelMaterialsCommon = require('./processModelMaterialsCommon'); var packArray = require('./packArray'); @@ -191,7 +191,6 @@ function generateMaterial(gltf, primitive, generatedMaterials) { } if (!defined(normalParameter)) { addExtensionsUsed(gltf, 'KHR_materials_common'); - generatedMaterialId = getUniqueId(gltf, materialId + '-common'); var values = clone(material.values); values.doubleSided = true; @@ -204,7 +203,7 @@ function generateMaterial(gltf, primitive, generatedMaterials) { values.transparent = true; } - materials[generatedMaterialId] = { + var generatedMaterial = { extensions : { KHR_materials_common : { technique : 'BLINN', @@ -215,6 +214,8 @@ function generateMaterial(gltf, primitive, generatedMaterials) { } } }; + + generatedMaterialId = addToArray(materials, generatedMaterial); primitive.material = generatedMaterialId; generatedMaterials[materialId] = generatedMaterialId; } diff --git a/lib/getBinaryGltf.js b/lib/getBinaryGltf.js index 252f0341..637baa26 100644 --- a/lib/getBinaryGltf.js +++ b/lib/getBinaryGltf.js @@ -1,66 +1,39 @@ 'use strict'; var Cesium = require('cesium'); var mime = require('mime'); -var sizeOf = require('image-size'); +var addToArray = require('./addToArray'); +var ForEach = require('./ForEach'); +var mergeBuffers = require('./mergeBuffers'); +var removePipelineExtras = require('./removePipelineExtras'); var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; -var addExtensionsRequired = require('./addExtensionsRequired'); -var mergeBuffers = require('./mergeBuffers'); -var removePipelineExtras = require('./removePipelineExtras'); +// .crn (Crunch) is not a supported mime type, so add it +mime.define({'image/cr': ['crn']}); module.exports = getBinaryGltf; -// Update object with KHR_binary_glTF properties and add to body and bufferViews -function updateBinaryObject(gltf, objects, name, pipelineExtras, state) { - var bufferViews = gltf.bufferViews; - if (defined(objects)) { - for (var objectId in objects) { - if (objects.hasOwnProperty(objectId)) { - var object = objects[objectId]; - - // Update object with binary format - object.uri = 'data:,'; - object.extensions = defaultValue(object.extensions, {}); - object.extensions.KHR_binary_glTF = defaultValue(object.extensions.KHR_binary_glTF, {}); - var KHR_binary_glTF = object.extensions.KHR_binary_glTF; - - // Create a bufferView based on the byte length and current offset - var bufferViewKeys = Object.keys(bufferViews); - while (bufferViewKeys.indexOf('binary_bufferView' + state.currentBinaryView) !== -1) { - state.currentBinaryView++; - } - - var objectSource = new Buffer(object.extras._pipeline.source); - var bufferViewId = 'binary_bufferView' + state.currentBinaryView; - KHR_binary_glTF.bufferView = bufferViewId; //Create bufferview - bufferViews[bufferViewId] = { - buffer : 'binary_glTF', - byteLength : objectSource.length, - byteOffset : state.offset - }; - state.offset += objectSource.length; - - // Append the object source to the binary body - pipelineExtras.source = Buffer.concat([pipelineExtras.source, objectSource]); - - // Add additional properties for images - if (name === 'images') { - // .crn (Crunch) is not a supported mime type, so add it - mime.define({'image/crn' : ['crn']}); - var mimeType = mime.lookup(object.extras._pipeline.extension); - KHR_binary_glTF.mimeType = mimeType; - - if (mimeType !== 'image/ktx' && mimeType !== 'image/crn') { - var dimensions = sizeOf(object.extras._pipeline.source); - KHR_binary_glTF.width = dimensions.width; - KHR_binary_glTF.height = dimensions.height; - } - } - } +function updateBinaryObject(gltf, objects, hasMimeType) { + hasMimeType = defaultValue(hasMimeType, false); + var buffer = gltf.buffers[0]; + var bufferPipelineExtras = buffer.extras._pipeline; + ForEach.arrayOfObjects(objects, function(object) { + var pipelineExtras = object.extras._pipeline; + var source = pipelineExtras.source; + var bufferView = { + buffer: 0, + byteLength: source.length, + byteOffset: buffer.byteLength + }; + if (hasMimeType) { + object.mimeType = mime.lookup(pipelineExtras.extension); } - } + buffer.byteLength += source.length; + bufferPipelineExtras.source = Buffer.concat([bufferPipelineExtras.source, source]); + var bufferViewId = addToArray(gltf.bufferViews, bufferView); + object.bufferView = bufferViewId; + }); } /** @@ -69,80 +42,96 @@ function updateBinaryObject(gltf, objects, name, pipelineExtras, state) { * The glTF asset must be initialized for the pipeline. * * @param {Object} gltf A javascript object containing a glTF asset. - * @param {Boolean} embed Embed shaders into the binary. - * @param {Boolean} embedImage Embed images into the binary - * @returns {{glb: Buffer, header: Buffer, scene: Buffer, body: Buffer}} glb holds the whole buffer, each piece is also available via the returned object. + * @param {Object} options Options specifying custom behavior. + * @param {Boolean} options.embed Embed shaders into the binary. + * @param {Boolean} options.embedImage Embed images into the binary + * @returns {Buffer} A buffer containing the binary glTF blob * * @see addPipelineExtras * @see loadGltfUris */ -function getBinaryGltf(gltf, embed, embedImage) { - addExtensionsRequired(gltf, 'KHR_binary_glTF'); +function getBinaryGltf(gltf, options) { + options = defaultValue(options, {}); + options.embed = defaultValue(options.embed, true); + options.embedImage = defaultValue(options.embedImage, true); // Create the special binary buffer from the existing buffers - gltf.bufferViews = defaultValue(gltf.bufferViews, {}); - gltf.buffers = defaultValue(gltf.buffers, {}); - mergeBuffers(gltf, 'binary_glTF'); - + gltf.bufferViews = defaultValue(gltf.bufferViews, []); + gltf.buffers = defaultValue(gltf.buffers, []); + mergeBuffers(gltf); var buffers = gltf.buffers; - var currentOffset = buffers.binary_glTF.byteLength; - var pipelineExtras = buffers.binary_glTF.extras._pipeline; - var state = { - offset: currentOffset, - currentBinaryView: 0 - }; - - if (embed) { - updateBinaryObject(gltf, gltf.shaders, 'shaders', pipelineExtras, state); - } - if (embedImage) { - updateBinaryObject(gltf, gltf.images, 'images', pipelineExtras, state); - } - - // Update binary with compressed textures - if (embedImage) { - var images = gltf.images; - for (var imageId in images) { - if (images.hasOwnProperty(imageId)) { - var image = images[imageId]; - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - updateBinaryObject(gltf, compressedImages, 'images', pipelineExtras, state); + var buffer; + if (buffers.length > 0) { + buffer = buffers[0]; + } else { + buffer = { + byteLength: 0, + extras: { + _pipeline: { + source: new Buffer([]), + extension: '.bin' } } - } + }; + buffers.push(buffer); } - var body = buffers.binary_glTF.extras._pipeline.source; - buffers.binary_glTF.byteLength = state.offset; + if (options.embed) { + updateBinaryObject(gltf, gltf.shaders); + } + if (options.embedImage) { + updateBinaryObject(gltf, gltf.images, true); + ForEach.image(function(gltf, image) { + if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { + var compressedImages = image.extras.compressedImage3DTiles; + updateBinaryObject(gltf, compressedImages, true); + } + }); + } + var binaryBuffer = buffer.extras._pipeline.source; + if (binaryBuffer.length === 0) { + delete gltf.buffers; + } // Remove extras objects before writing removePipelineExtras(gltf); - // Create padded binary scene string and calculate total length - var sceneString = JSON.stringify(gltf); - var sceneLength = Buffer.byteLength(sceneString); - sceneLength += 4 - (sceneLength % 4); - var padding = new Array(sceneLength + 1).join(' '); - sceneString = (sceneString + padding).substring(0, sceneLength); - var bodyOffset = 20 + sceneLength; - var glbLength = bodyOffset + body.length; - - // Write binary glTF header (magic, version, length, sceneLength, sceneFormat) - var header = new Buffer(20); - header.write('glTF', 0); - header.writeUInt32LE(1, 4); - header.writeUInt32LE(glbLength, 8); - header.writeUInt32LE(sceneLength, 12); - header.writeUInt32LE(0, 16); - - // Create scene buffer and overall buffer - var scene = new Buffer(sceneString); - var glb = Buffer.concat([header, scene, body], glbLength); - - return { - glb : glb, - header : header, - scene : scene, - body : body - }; + // Create padded binary scene string + var jsonString = JSON.stringify(gltf); + while (jsonString.length % 4 !== 0) { + jsonString += ' '; + } + var jsonBuffer = Buffer.from(jsonString); + + // Allocate buffer (Global header) + (JSON chunk header) + (JSON chunk) + (Binary chunk header) + (Binary chunk) + var glbLength = 12 + 8 + jsonBuffer.length + 8 + binaryBuffer.length; + var glb = new Buffer(glbLength); + + // Write binary glTF header (magic, version, length) + var byteOffset = 0; + glb.writeUInt32LE(0x46546C67, byteOffset); + byteOffset += 4; + glb.writeUInt32LE(2, byteOffset); + byteOffset += 4; + glb.writeUInt32LE(glbLength, byteOffset); + byteOffset += 4; + + // Write JSON Chunk header (length, type) + glb.writeUInt32LE(jsonBuffer.length, byteOffset); + byteOffset += 4; + glb.writeUInt32LE(0x4E4F534A, byteOffset); // JSON + byteOffset += 4; + + // Write JSON Chunk + jsonBuffer.copy(glb, byteOffset); + byteOffset += jsonBuffer.length; + + // Write Binary Chunk header (length, type) + glb.writeUInt32LE(binaryBuffer.length, byteOffset); + byteOffset += 4; + glb.writeUInt32LE(0x004E4942, byteOffset); // BIN + byteOffset += 4; + + // Write Binary Chunk + binaryBuffer.copy(glb, byteOffset); + return glb; } \ No newline at end of file diff --git a/lib/getStatistics.js b/lib/getStatistics.js index f25a5153..982b17a0 100644 --- a/lib/getStatistics.js +++ b/lib/getStatistics.js @@ -1,8 +1,8 @@ 'use strict'; var Cesium = require('cesium'); +var ForEach = require('./ForEach'); var defined = Cesium.defined; -var defaultValue = Cesium.defaultValue; var DeveloperError = Cesium.DeveloperError; module.exports = getStatistics; @@ -43,8 +43,7 @@ function Statistics() { * @returns {String} A string describing the statistics for the glTF asset. */ Statistics.prototype.toString = function() { - var output = - 'Total size of all buffers: ' + this.buffersSizeInBytes + ' bytes' + + return 'Total size of all buffers: ' + this.buffersSizeInBytes + ' bytes' + '\nImages: ' + this.numberOfImages + '\nDraw calls: ' + this.numberOfDrawCalls + '\nRendered primitives (e.g., triangles): ' + this.numberOfRenderedPrimitives + @@ -53,8 +52,6 @@ Statistics.prototype.toString = function() { '\nMaterials: ' + this.numberOfMaterials + '\nAnimations: ' + this.numberOfAnimations + '\nExternal requests (not data uris): ' + this.numberOfExternalRequests; - - return output; }; function isDataUri(uri) { @@ -69,38 +66,30 @@ function isDataUri(uri) { function getAllPrimitives(gltf) { var primitives = []; - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - primitives = primitives.concat(mesh.primitives); - } - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + primitives.push(primitive); + }); + }); return primitives; } -function getBuffersSize(buffers) { +function getBuffersSize(gltf) { var size = 0; - for (var id in buffers) { - if (buffers.hasOwnProperty(id)) { - size += buffers[id].byteLength; - } - } + ForEach.buffer(gltf, function(buffer) { + size += buffer.byteLength; + }); return size; } function getNumberOfExternalProperties(property) { - var id; - var uri; var count = 0; - for (id in property) { - if (property.hasOwnProperty(id)) { - uri = property[id].uri; - if (defined(uri) && !isDataUri(uri)) { - ++count; - } + ForEach.arrayOfObjects(property, function(object) { + var uri = object.uri; + if (defined(uri) && !isDataUri(uri)) { + count++; } - } + }); return count; } @@ -114,10 +103,6 @@ function getNumberOfExternalRequests(gltf) { return count; } -function getNumberOfProperties(object) { - return Object.keys(object).length; -} - function getNumberOfRenderedPrimitives(gltf, primitives) { var numberOfRenderedPrimitives = 0; @@ -157,35 +142,19 @@ function getDrawCallStatisticsForNode(gltf, nodeId) { var numberOfDrawCalls = 0; var numberOfRenderedPrimitives = 0; - var nodes = gltf.nodes; var meshes = gltf.meshes; - var nodeStack = []; - - var n = nodes[nodeId]; - nodeStack.push(n); - - while (nodeStack.length > 0) { - n = nodeStack.pop(); - - var nodeMeshes = defaultValue(n.meshes, defined(n.instanceSkin) ? n.instanceSkin.meshes : undefined); - if (defined(nodeMeshes)) { - var meshesLength = nodeMeshes.length; - for (var j = 0; j < meshesLength; ++j) { - var primitives = meshes[nodeMeshes[j]].primitives; - + ForEach.nodeInTree(gltf, [nodeId], function(node) { + var meshId = node.mesh; + var mesh = meshes[meshId]; + if (defined(mesh)) { + var primitives = mesh.primitives; + if (defined(primitives)) { numberOfDrawCalls += primitives.length; numberOfRenderedPrimitives += getNumberOfRenderedPrimitives(gltf, primitives); } } - - var children = n.children; - var childrenLength = children.length; - for (var k = 0; k < childrenLength; ++k) { - var child = nodes[children[k]]; - nodeStack.push(child); - } - } + }); return { numberOfDrawCalls : numberOfDrawCalls, @@ -235,15 +204,15 @@ function getStatistics(gltf, nodeId) { var drawStats = getDrawCallStatistics(gltf); - statistics.buffersSizeInBytes = getBuffersSize(gltf.buffers); - statistics.numberOfImages = getNumberOfProperties(gltf.images); + statistics.buffersSizeInBytes = getBuffersSize(gltf); + statistics.numberOfImages = gltf.images.length; statistics.numberOfExternalRequests = getNumberOfExternalRequests(gltf); statistics.numberOfDrawCalls = drawStats.numberOfDrawCalls; statistics.numberOfRenderedPrimitives = drawStats.numberOfRenderedPrimitives; - statistics.numberOfNodes = getNumberOfProperties(gltf.nodes); - statistics.numberOfMeshes = getNumberOfProperties(gltf.meshes); - statistics.numberOfMaterials = getNumberOfProperties(gltf.materials); - statistics.numberOfAnimations = getNumberOfProperties(gltf.animations); + statistics.numberOfNodes = gltf.nodes.length; + statistics.numberOfMeshes = gltf.meshes.length; + statistics.numberOfMaterials = gltf.materials.length; + statistics.numberOfAnimations = gltf.animations.length; return statistics; } diff --git a/lib/loadGltfUris.js b/lib/loadGltfUris.js index 2789dff8..38ae2ccd 100644 --- a/lib/loadGltfUris.js +++ b/lib/loadGltfUris.js @@ -35,8 +35,7 @@ function loadGltfUris(gltf, options) { ]; // Read sources for compressed textures - /* jshint unused:vars */ - ForEach.image(function(imageId, image) { + ForEach.image(function(image) { if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { var compressedImages = image.extras.compressedImage3DTiles; loadPromises.push(loadURIs(compressedImages, 'images', basePath)); diff --git a/lib/mergeBuffers.js b/lib/mergeBuffers.js index 913278e7..4ffa0947 100644 --- a/lib/mergeBuffers.js +++ b/lib/mergeBuffers.js @@ -1,6 +1,6 @@ 'use strict'; var Cesium = require('cesium'); -var getUniqueId = require('./getUniqueId'); +var ForEach = require('./ForEach'); var defined = Cesium.defined; @@ -18,71 +18,53 @@ module.exports = mergeBuffers; * @see addPipelineExtras * @see loadGltfUris */ -function mergeBuffers(gltf, bufferId) { +function mergeBuffers(gltf) { var buffers = gltf.buffers; var bufferViews = gltf.bufferViews; var bufferViewsForBuffers = getBufferViewsForBuffers(gltf); - if (defined(buffers)) { + if (defined(buffers) && buffers.length > 0) { var buffersToMerge = []; var lengthSoFar = 0; - for (var gltfBufferId in buffers) { - if (buffers.hasOwnProperty(gltfBufferId)) { - //Add the buffer to the merged source - var buffer = buffers[gltfBufferId]; - if (!defined(bufferId)) { - bufferId = gltfBufferId; + ForEach.buffer(gltf, function(buffer, bufferId) { + var bufferViewIds = bufferViewsForBuffers[bufferId]; + for (var bufferViewId in bufferViewIds) { + if (bufferViewIds.hasOwnProperty(bufferViewId)) { + var bufferView = bufferViews[bufferViewId]; + bufferView.byteOffset += lengthSoFar; + bufferView.buffer = 0; } - var bufferViewIds = bufferViewsForBuffers[gltfBufferId]; - for (var bufferViewId in bufferViewIds) { - if (bufferViewIds.hasOwnProperty(bufferViewId)) { - var bufferView = bufferViews[bufferViewId]; - bufferView.byteOffset += lengthSoFar; - bufferView.buffer = bufferId; - } - } - buffersToMerge.push(buffer.extras._pipeline.source); - lengthSoFar += buffer.extras._pipeline.source.length; } - } + buffersToMerge.push(buffer.extras._pipeline.source); + lengthSoFar += buffer.extras._pipeline.source.length; + }); var source = Buffer.concat(buffersToMerge, lengthSoFar); - if (!defined(bufferId)) { - bufferId = getUniqueId(gltf, 'buffer'); - } - //Replace existing buffer with new merged buffer - gltf.buffers = {}; - gltf.buffers[bufferId] = { - "type": "arraybuffer", - "byteLength": source.length, - "uri": "data:,", - "extras": { - "_pipeline": { - "source": source, - "extension": ".bin" + gltf.buffers = [{ + byteLength: source.length, + extras: { + _pipeline: { + source: source, + extension: '.bin' } } - }; + }]; } return gltf; } function getBufferViewsForBuffers(gltf) { var bufferViewsForBuffers = {}; - var bufferViews = gltf.bufferViews; - for (var bufferViewId in bufferViews) { - if (bufferViews.hasOwnProperty(bufferViewId)) { - var bufferView = bufferViews[bufferViewId]; - var bufferId = bufferView.buffer; - var bufferViewsForBuffer = bufferViewsForBuffers[bufferId]; - if (!defined(bufferViewsForBuffer)) { - bufferViewsForBuffer = {}; - bufferViewsForBuffers[bufferId] = bufferViewsForBuffer; - } - bufferViewsForBuffer[bufferViewId] = true; + ForEach.bufferView(gltf, function(bufferView, bufferViewId) { + var bufferId = bufferView.buffer; + var bufferViewsForBuffer = bufferViewsForBuffers[bufferId]; + if (!defined(bufferViewsForBuffer)) { + bufferViewsForBuffer = {}; + bufferViewsForBuffers[bufferId] = bufferViewsForBuffer; } - } + bufferViewsForBuffer[bufferViewId] = true; + }); return bufferViewsForBuffers; } \ No newline at end of file diff --git a/lib/optimizeForVertexCache.js b/lib/optimizeForVertexCache.js index 87a29b00..ab25be73 100644 --- a/lib/optimizeForVertexCache.js +++ b/lib/optimizeForVertexCache.js @@ -1,5 +1,6 @@ 'use strict'; var Cesium = require('cesium'); +var ForEach = require('./ForEach'); var gltfPrimitiveToCesiumGeometry = require('./gltfPrimitiveToCesiumGeometry'); var cesiumGeometryToGltfPrimitive = require('./cesiumGeometryToGltfPrimitive'); var createAccessorUsageTables = require('./createAccessorUsageTables'); @@ -12,28 +13,19 @@ module.exports = optimizeForVertexCache; // Helper method to map accessor collections from the usageTable to an independent primitive (if there is one) function createIndicesToAttributeDictionary(gltf) { var dictionary = {}; - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - var indicesId = primitive.indices; - - var primitivesOfIndicesId; - if (!dictionary[indicesId]) { - primitivesOfIndicesId = []; - } else { - primitivesOfIndicesId = dictionary[indicesId]; - } - primitivesOfIndicesId.push(primitive); - - dictionary[indicesId] = primitivesOfIndicesId; + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + var indicesId = primitive.indices; + var primitivesOfIndicesId; + if (!dictionary[indicesId]) { + primitivesOfIndicesId = []; + } else { + primitivesOfIndicesId = dictionary[indicesId]; } - } - } + primitivesOfIndicesId.push(primitive); + dictionary[indicesId] = primitivesOfIndicesId; + }); + }); return dictionary; } @@ -80,22 +72,15 @@ function optimizeForVertexCache(gltf, cacheSize) { // perform post vertex cache optimization var primitive; var geometry; - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - primitive = primitives[i]; - if (defined(primitive.indices)) { - geometry = gltfPrimitiveToCesiumGeometry(gltf, primitive); - GeometryPipeline.reorderForPostVertexCache(geometry, cacheSize); - cesiumGeometryToGltfPrimitive(gltf, primitive, geometry); - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + if (defined(primitive.indices)) { + geometry = gltfPrimitiveToCesiumGeometry(gltf, primitive); + GeometryPipeline.reorderForPostVertexCache(geometry, cacheSize); + cesiumGeometryToGltfPrimitive(gltf, primitive, geometry); } - } - } + }); + }); // perform pre vertex cache optimization on each independent primitive var usageTables = createAccessorUsageTables(gltf); var dictionary = createIndicesToAttributeDictionary(gltf); diff --git a/lib/parseBinaryGltf.js b/lib/parseBinaryGltf.js index 6ea8e7c6..8c676f7e 100644 --- a/lib/parseBinaryGltf.js +++ b/lib/parseBinaryGltf.js @@ -1,12 +1,12 @@ 'use strict'; var Cesium = require('cesium'); - var addPipelineExtras = require('./addPipelineExtras'); +var removeExtensionsUsed = require('./removeExtensionsUsed'); +var updateVersion = require('./updateVersion'); var ComponentDatatype = Cesium.ComponentDatatype; var defined = Cesium.defined; var DeveloperError = Cesium.DeveloperError; -var defaultValue = Cesium.defaultValue; var getMagic = Cesium.getMagic; var getStringFromTypedArray = Cesium.getStringFromTypedArray; var WebGLConstants = Cesium.WebGLConstants; @@ -20,194 +20,83 @@ module.exports = parseBinaryGltf; * @returns {Object} The parsed binary glTF. */ function parseBinaryGltf(data) { - var bufferViewId; + var headerView = ComponentDatatype.createArrayBufferView(WebGLConstants.INT, data.buffer, data.byteOffset, 5); // Check that the magic string is present - if (getMagic(data) !== 'glTF') { + var magic = getMagic(data); + if (magic !== 'glTF') { throw new DeveloperError('File is not valid binary glTF'); } - var uint32View = ComponentDatatype.createArrayBufferView(WebGLConstants.INT, data.buffer, data.byteOffset, 5); - - // Check that the version is 1 - if (uint32View[1] !== 1) { - throw new DeveloperError('Binary glTF version is not 1'); - } - - // Get the length of the glTF scene - var sceneLength = uint32View[3]; - - // Check that the scene format is 0, indicating that it is JSON - if (uint32View[4]) { - throw new DeveloperError('Binary glTF scene format is not JSON'); + // Check that the version is 1 or 2 + var version = headerView[1]; + if (version !== 1 && version !== 2) { + throw new DeveloperError('Binary glTF version is not 1 or 2'); } - // Parse gltf scene - var scene = getStringFromTypedArray(data.slice(20, 20 + sceneLength)); - var gltf = JSON.parse(scene); - addPipelineExtras(gltf); - - // Extract binary body - var body = data.slice(20 + sceneLength); - - // Find bufferViews used by accessors - var usedBufferViews = getUsedBufferViews(gltf); - - // Add image and shader sources, and delete their bufferView if not referenced by an accessor - loadSourceFromBody(gltf, gltf.images, 'images', body, usedBufferViews); - loadSourceFromBody(gltf, gltf.shaders, 'shaders', body, usedBufferViews); + var gltf; + var buffers; + var length; + // Load binary glTF version 1 + if (version === 1) { + length = headerView[2]; + var contentLength = headerView[3]; + var contentFormat = headerView[4]; - // Read sources for compressed textures - var images = gltf.images; - for (var imageId in images) { - if (images.hasOwnProperty(imageId)) { - var image = images[imageId]; - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - loadSourceFromBody(gltf, compressedImages, 'images', body, usedBufferViews); - } + // Check that the content format is 0, indicating that it is JSON + if (contentFormat !== 0) { + throw new DeveloperError('Binary glTF scene format is not JSON'); } - } - - // Create a new buffer for each bufferView, and delete the original body buffer - var buffers = gltf.buffers; - var bufferViews = gltf.bufferViews; - // The extension 'KHR_binary_glTF' uses a special buffer entitled just 'binary_glTF'. - // The 'KHR_binary_glTF' check is for backwards compatibility for the Cesium model converter - // circa Cesium 1.15-1.20 when the converter incorrectly used the buffer name 'KHR_binary_glTF'. - if (defined(buffers) && (defined(buffers.binary_glTF) || defined(buffers.KHR_binary_glTF))) { - if (defined(bufferViews)) { - //Add id to each bufferView object - for (bufferViewId in bufferViews) { - if (bufferViews.hasOwnProperty(bufferViewId)) { - var bufferView = bufferViews[bufferViewId]; - bufferView.extras._pipeline.id = bufferViewId; - } - } - - //Create bufferView array and get bufferViews referencing binary_glTF - var sortedBufferViews = []; - for (bufferViewId in bufferViews) { - if (bufferViews.hasOwnProperty(bufferViewId)) { - sortedBufferViews.push(bufferViews[bufferViewId]); - } - } - sortedBufferViews = sortedBufferViews.filter(function(bufferView) { - return bufferView.buffer === 'binary_glTF' || bufferView.buffer === 'KHR_binary_glTF'; - }); - //Sort bufferViews by increasing byteOffset - sortedBufferViews.sort(function(a, b) { - return a.byteOffset - b.byteOffset; - }); - - //Create a new buffer for each set of overlapping bufferViews - for (var i = 0; i < sortedBufferViews.length; i++) { - var currentView = sortedBufferViews[i]; - var viewStart = currentView.byteOffset; - var viewLength = defaultValue(currentView.byteLength, 0); - var viewEnd = viewStart + viewLength; - currentView.byteOffset = 0; - currentView.byteLength = viewLength; - - var bufferName = currentView.extras._pipeline.id + '_buffer'; - var bufferKeys = Object.keys(buffers); - while (bufferKeys.indexOf(bufferName) !== -1) { - bufferName += '_'; - } - currentView.buffer = bufferName; - - for (var j = i + 1; j < sortedBufferViews.length; i = j, j++) { - var nextView = sortedBufferViews[j]; - var nextViewStart = nextView.byteOffset; - var nextViewLength = defaultValue(nextView.byteLength, 0); - var nextViewEnd = nextViewStart + nextViewLength; - //Merge view ranges if they overlap - if (nextViewStart < viewEnd) { - nextView.byteOffset = nextViewStart - viewStart; - nextView.byteLength = nextViewLength; - nextView.buffer = bufferName; - if (nextViewEnd > viewEnd) { - viewEnd = nextViewEnd; - } - } - else { - break; - } - } - - buffers[bufferName] = { - "byteLength" : viewEnd - viewStart, - "uri" : "data:,", - "extras" : { - "_pipeline" : { - "source" : body.slice(viewStart, viewEnd) - } - } - }; + var contentString = getStringFromTypedArray(data.slice(20, 20 + contentLength)); + gltf = JSON.parse(contentString); + // Update to glTF 2.0 + updateVersion(gltf); + // Remove the KHR_binary_glTF extension + removeExtensionsUsed(gltf, 'KHR_binary_glTF'); + addPipelineExtras(gltf); + + var binaryData = data.slice(20 + contentLength, length); + buffers = gltf.buffers; + if (defined(buffers) && buffers.length > 0) { + var binaryGltfBuffer = buffers[0]; + if (defined(binaryGltfBuffer)) { + binaryGltfBuffer.extras._pipeline.source = binaryData; } } - delete gltf.buffers.binary_glTF; } - // Remove the KHR_binary_glTF extension - gltf.extensionsUsed = gltf.extensionsUsed.filter(function(extension) { - return extension !== 'KHR_binary_glTF'; - }); - if (Object.keys(gltf.extensionsUsed).length === 0) { - delete gltf.extensionsUsed; - } - - return gltf; -} - -// Load the source from the binary body to the corresponding objects -function loadSourceFromBody(gltf, objects, name, body, usedBufferViews) { - if (defined(objects)) { - for (var objectId in objects) { - if (objects.hasOwnProperty(objectId)) { - var object = objects[objectId]; - var objectExtensions = object.extensions; - if (defined(objectExtensions) && defined(objectExtensions.KHR_binary_glTF)) { - var viewId = objectExtensions.KHR_binary_glTF.bufferView; - var bufferView = gltf.bufferViews[viewId]; - var source = body.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); - object.extras._pipeline.source = source; - - if (name === 'shaders') { - object.extras._pipeline.extension = '.glsl'; - object.extras._pipeline.source = getStringFromTypedArray(source); - } - else if (name === 'images') { - object.extras._pipeline.extension = getBinaryImageFormat(source.slice(0, 2)); - } - delete object.extensions.KHR_binary_glTF; - if (Object.keys(object.extensions).length === 0) { - delete object.extensions; - } - //Delete the original referenced bufferView if not used anywhere else - if (!defined(usedBufferViews[viewId])) { - delete gltf.bufferViews[viewId]; - } - } + // Load binary glTF version 2 + if (version === 2) { + length = headerView[2]; + var byteOffset = 12; + var binaryBuffer; + while (byteOffset < length) { + var chunkHeaderView = ComponentDatatype.createArrayBufferView(WebGLConstants.INT, data.buffer, data.byteOffset + byteOffset, 2); + var chunkLength = chunkHeaderView[0]; + var chunkType = chunkHeaderView[1]; + byteOffset += 8; + var chunkBuffer = data.slice(byteOffset, byteOffset + chunkLength); + byteOffset += chunkLength; + // Load JSON chunk + if (chunkType === 0x4E4F534A) { + var jsonString = chunkBuffer.toString(); + gltf = JSON.parse(jsonString); + addPipelineExtras(gltf); + } + // Load Binary chunk + else if (chunkType === 0x004E4942) { + binaryBuffer = chunkBuffer; } } - } -} - -//Get the set bufferViews used by accessors -function getUsedBufferViews(gltf) { - var usedBufferViews = {}; - var accessors = gltf.accessors; - - if (defined(accessors)) { - for (var accessorId in accessors) { - if (accessors.hasOwnProperty(accessorId)) { - usedBufferViews[accessors[accessorId].bufferView] = true; + if (defined(gltf) && defined(binaryBuffer)) { + buffers = gltf.buffers; + if (defined(buffers) && buffers.length > 0) { + var buffer = buffers[0]; + buffer.extras._pipeline.source = binaryBuffer; } } } - - return usedBufferViews; + return gltf; } function bufferEqual(first, second) { diff --git a/lib/removeExtensionsRequired.js b/lib/removeExtensionsRequired.js new file mode 100644 index 00000000..5e706c74 --- /dev/null +++ b/lib/removeExtensionsRequired.js @@ -0,0 +1,25 @@ +'use strict'; +var Cesium = require('cesium'); + +var defined = Cesium.defined; + +module.exports = removeExtensionsRequired; + +/** + * Removes an extension from gltf.extensionsRequired if it is present. + * + * @param {Object} gltf A javascript object containing a glTF asset. + * @param {String} extension The extension to remove. + */ +function removeExtensionsRequired(gltf, extension) { + var extensionsRequired = gltf.extensionsRequired; + if (defined(extensionsRequired)) { + var index = extensionsRequired.indexOf(extension); + if (index >= 0) { + extensionsRequired.splice(index, 1); + } + if (extensionsRequired.length === 0) { + delete gltf.extensionsRequired; + } + } +} diff --git a/lib/removeExtensionsUsed.js b/lib/removeExtensionsUsed.js new file mode 100644 index 00000000..f0f68c7b --- /dev/null +++ b/lib/removeExtensionsUsed.js @@ -0,0 +1,27 @@ +'use strict'; +var Cesium = require('cesium'); +var removeExtensionsRequired = require('./removeExtensionsRequired'); + +var defined = Cesium.defined; + +module.exports = removeExtensionsUsed; + +/** + * Removes an extension from gltf.extensionsUsed and gltf.extensionsRequired if it is present. + * + * @param {Object} gltf A javascript object containing a glTF asset. + * @param {String} extension The extension to remove. + */ +function removeExtensionsUsed(gltf, extension) { + var extensionsUsed = gltf.extensionsUsed; + if (defined(extensionsUsed)) { + var index = extensionsUsed.indexOf(extension); + if (index >= 0) { + extensionsUsed.splice(index, 1); + } + removeExtensionsRequired(gltf, extension); + if (extensionsUsed.length === 0) { + delete gltf.extensionsUsed; + } + } +} \ No newline at end of file diff --git a/lib/uninterleaveAndPackBuffers.js b/lib/uninterleaveAndPackBuffers.js index 8bc8c962..1771324b 100644 --- a/lib/uninterleaveAndPackBuffers.js +++ b/lib/uninterleaveAndPackBuffers.js @@ -1,14 +1,16 @@ 'use strict'; var Cesium = require('cesium'); +var AccessorReader = require('./AccessorReader'); +var byteLengthForComponentType = require('./byteLengthForComponentType'); +var ForEach = require('./ForEach'); +var numberOfComponentsForType = require('./numberOfComponentsForType'); +var Remove = require('./Remove'); +var writeBufferComponent = require('./writeBufferComponent'); var WebGLConstants = Cesium.WebGLConstants; var defined = Cesium.defined; var defaultValue = Cesium.defaultValue; -var byteLengthForComponentType = require('./byteLengthForComponentType'); -var getAccessorByteStride = require('./getAccessorByteStride'); -var numberOfComponentsForType = require('./numberOfComponentsForType'); - module.exports = uninterleaveAndPackBuffers; /** @@ -24,148 +26,116 @@ module.exports = uninterleaveAndPackBuffers; * @see loadGltfUris */ function uninterleaveAndPackBuffers(gltf) { - var accessors = gltf.accessors; - var buffers = gltf.buffers; - var packBufferViews = {length : 0}; - for (var bufferId in buffers) { - if (buffers.hasOwnProperty(bufferId)) { - packGltfBuffer(gltf, bufferId, packBufferViews); - } - } - delete packBufferViews.length; - gltf.bufferViews = packBufferViews; + var arrayBufferDataOffset = 0; + var arrayBufferDataLength = 0; + var elementArrayBufferDataOffset = 0; + var elementArrayBufferDataLength = 0; + var otherDataOffset = 0; + var otherDataLength = 0; - // Change the accessor bufferViews to point to the new bufferViews - for (var accessorId in accessors) { - if (accessors.hasOwnProperty(accessorId)) { - var accessor = accessors[accessorId]; - accessor.bufferView = accessor.extras._pipeline.bufferView; + // compute the total size for each arraybuffer type + ForEach.accessor(gltf, function (accessor) { + var bufferView = gltf.bufferViews[accessor.bufferView]; + var accessorLength = byteLengthForComponentType(accessor.componentType) * numberOfComponentsForType(accessor.type) * accessor.count; + switch (bufferView.target) { + case WebGLConstants.ARRAY_BUFFER: + arrayBufferDataLength += accessorLength; + break; + case WebGLConstants.ELEMENT_ARRAY_BUFFER: + elementArrayBufferDataLength += accessorLength; + break; + default: + otherDataLength += accessorLength; + break; } - } - return gltf; -} + }); -function packGltfBuffer(gltf, bufferId, packBufferViews) { - var buffers = gltf.buffers; - var buffer = buffers[bufferId]; - var source = buffer.extras._pipeline.source; - var packBuffer = new Uint8Array(source.length); - var accessors = getAccessorsByTargetAndByteLength(gltf, bufferId); - var offset = 0; + // allocate buffer data + var bufferData = new Buffer(arrayBufferDataLength + elementArrayBufferDataLength + otherDataLength); + var arrayBufferData = bufferData.slice(0, arrayBufferDataLength); + var elementArrayBufferData = bufferData.slice(arrayBufferDataLength, arrayBufferDataLength + elementArrayBufferDataLength); + var otherData = bufferData.slice(arrayBufferDataLength + elementArrayBufferDataLength); - var targets = [WebGLConstants.ARRAY_BUFFER, 0, WebGLConstants.ELEMENT_ARRAY_BUFFER]; - for (var i = 0; i < targets.length; i++) { - var target = targets[i]; - var accessorsByByteLength = accessors[target]; - if (defined(accessorsByByteLength)) { - offset = packAccessorsForTarget(gltf, bufferId, target, accessorsByByteLength, source, packBuffer, packBufferViews, offset); - } - } - packBuffer = new Buffer(new Uint8Array(packBuffer.buffer, 0, offset)); - buffer.extras._pipeline.source = packBuffer; - buffer.byteLength = packBuffer.length; -} + // read data from accessors into the new buffers + ForEach.accessor(gltf, function (accessor) { + var reader = new AccessorReader(gltf, accessor); + var components = []; + var bufferView = gltf.bufferViews[accessor.bufferView]; + var componentByteLength = byteLengthForComponentType(accessor.componentType); -function packAccessorsForTarget(gltf, bufferId, target, accessorsByByteLength, sourceBuffer, packBuffer, packBufferViews, offset) { - var bufferViewId = 'bufferView_' + packBufferViews.length; - var originalOffset = offset; - var byteLengths = [4, 2, 1]; - var packOffset = offset; - for (var i = 0; i < byteLengths.length; i++) { - var byteLength = byteLengths[i]; - var accessorIds = accessorsByByteLength[byteLength]; - if (defined(accessorIds) && accessorIds.length > 0) { - // Byte-boundary align the offset if it isn't already - packOffset += packOffset % byteLength; - packOffset = packAccessors(gltf, accessorIds, sourceBuffer, packBuffer, bufferViewId, originalOffset, packOffset); + while (!reader.pastEnd()) { + reader.read(components); + var componentsLength = components.length; + for (var i = 0; i < componentsLength; i++) { + switch (bufferView.target) { + case WebGLConstants.ARRAY_BUFFER: + writeBufferComponent(arrayBufferData, accessor.componentType, components[i], arrayBufferDataOffset); + arrayBufferDataOffset += componentByteLength; + break; + case WebGLConstants.ELEMENT_ARRAY_BUFFER: + writeBufferComponent(elementArrayBufferData, accessor.componentType, components[i], elementArrayBufferDataOffset); + elementArrayBufferDataOffset += componentByteLength; + break; + default: + writeBufferComponent(otherData, accessor.componentType, components[i], otherDataOffset); + otherDataOffset += componentByteLength; + break; + } + } } - } - var packBufferView = { - buffer : bufferId, - byteLength : packOffset - originalOffset, - byteOffset : originalOffset, - extras : { - _pipeline : {} + // assign bufferViews since we're done reading + switch (bufferView.target) { + case WebGLConstants.ARRAY_BUFFER: + accessor.bufferView = 0; + break; + case WebGLConstants.ELEMENT_ARRAY_BUFFER: + accessor.bufferView = 1; + break; + default: + accessor.bufferView = 2; + break; } - }; - if (target > 0) { - packBufferView.target = target; - } - packBufferViews[bufferViewId] = packBufferView; - packBufferViews.length++; - return packOffset; -} - -function getPipelineExtras(object) { - var extras = object.extras; - if (!defined(extras)) { - extras = {}; - object.extras = extras; - } - var pipeline = extras._pipeline; - if (!defined(pipeline)) { - pipeline = {}; - extras._pipeline = pipeline; - } - return pipeline; -} + reader.next(); + }); -function packAccessors(gltf, accessorsToPack, sourceBuffer, packBuffer, bufferViewId, originalOffset, packOffset) { - var accessors = gltf.accessors; - var bufferViews = gltf.bufferViews; - var length = accessorsToPack.length; - var bytesWritten = 0; - for (var i = 0; i < length; i++) { - var accessorId = accessorsToPack[i]; - var accessor = accessors[accessorId]; - var bufferView = bufferViews[accessor.bufferView]; - var byteStride = getAccessorByteStride(accessor); - var byteOffset = accessor.byteOffset + bufferView.byteOffset; - var numberOfComponents = numberOfComponentsForType(accessor.type); - var componentByteLength = byteLengthForComponentType(accessor.componentType); - var byteLength = numberOfComponents * componentByteLength; - var offset = byteOffset; - var count = accessor.count; - accessor.byteStride = 0; - // Store as temp for now, finalize later - var extras = getPipelineExtras(accessor); - extras.bufferView = bufferViewId; - accessor.byteOffset = packOffset - originalOffset + bytesWritten; - for (var num = 0; num < count; num++) { - for (var j = 0; j < byteLength; j++) { - packBuffer[packOffset + bytesWritten] = sourceBuffer[offset + j]; - bytesWritten++; + var buffers = [{ + byteLength: bufferData.length, + extras: { + _pipeline: { + source: bufferData } - offset += byteStride; } - } - return packOffset + bytesWritten; -} + }]; -function getAccessorsByTargetAndByteLength(gltf, bufferId) { - var accessors = gltf.accessors; - var bufferViews = gltf.bufferViews; - var accessorsByTargetAndByteLength = {}; - for (var accessorId in accessors) { - if (accessors.hasOwnProperty(accessorId)) { - var accessor = accessors[accessorId]; - var bufferView = bufferViews[accessor.bufferView]; - if (bufferView.buffer === bufferId) { - var target = defaultValue(bufferView.target, 0); - var accessorsByByteLength = accessorsByTargetAndByteLength[target]; - if (!defined(accessorsByByteLength)) { - accessorsByByteLength = {}; - accessorsByTargetAndByteLength[target] = accessorsByByteLength; - } - var byteLength = byteLengthForComponentType(accessor.componentType); - var accessorIds = accessorsByByteLength[byteLength]; - if (!defined(accessorIds)) { - accessorIds = []; - accessorsByByteLength[byteLength] = accessorIds; - } - accessorIds.push(accessorId); - } - } + var bufferViews = [{ + buffer: 0, + byteLength: arrayBufferDataLength, + byteOffset: 0, + byteStride: 0 + }, { + buffer: 0, + byteLength: elementArrayBufferDataLength, + byteOffset: arrayBufferDataLength + }, { + buffer: 0, + byteLength: otherDataLength, + byteOffset: arrayBufferDataLength + elementArrayBufferDataLength, + byteStride: 0 + }]; + + gltf.buffers = buffers; + gltf.bufferViews = bufferViews; + + var removed = 0; + if (arrayBufferDataLength > 0) { + Remove.bufferView(gltf, 0); + removed++; + } + if (elementArrayBufferDataLength > 0) { + Remove.bufferView(gltf, 1 - removed); + removed++; + } + if (otherDataLength > 0) { + Remove.bufferView(gltf, 2 - removed); } - return accessorsByTargetAndByteLength; } \ No newline at end of file diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 79dcb41a..e5177b3e 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -1,7 +1,7 @@ 'use strict'; var Cesium = require('cesium'); - -var getUniqueId = require('./getUniqueId'); +var addToArray = require('./addToArray'); +var ForEach = require('./ForEach'); var findAccessorMinMax = require('./findAccessorMinMax'); var Cartesian3 = Cesium.Cartesian3; @@ -186,62 +186,6 @@ function glTF08to10(gltf) { } } -function stripWebGLRevisionNumber(gltf) { - var asset = gltf.asset; - var profile = asset.profile; - if (defined(profile)) { - var version = profile.version; - if (defined(version)) { - profile.version = version[0] + '.' + version[2]; - } - } -} - -var knownExtensions = { - CESIUM_RTC : true, - KHR_binary_glTF : true, - KHR_materials_common : true, - WEB3D_quantized_attributes : true -}; -function requireKnownExtensions(gltf) { - var extensionsUsed = gltf.extensionsUsed; - gltf.extensionsRequired = defaultValue(gltf.extensionsRequired, []); - if (defined(extensionsUsed)) { - var extensionsUsedLength = extensionsUsed.length; - for (var i = 0; i < extensionsUsedLength; i++) { - var extension = extensionsUsed[i]; - if (defined(knownExtensions[extension])) { - gltf.extensionsRequired.push(extension); - } - } - } -} - -function addGlExtensionsUsed(gltf) { - var accessors = gltf.accessors; - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - if (defined(primitives)) { - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - var indicesAccessorId = primitive.indices; - if (defined(indicesAccessorId)) { - var indicesAccessor = accessors[indicesAccessorId]; - if (indicesAccessor.componentType === WebGLConstants.UNSIGNED_INT) { - gltf.glExtensionsUsed = ['OES_element_index_uint']; - return; - } - } - } - } - } - } -} - function removeAnimationSamplersIndirection(gltf) { var animations = gltf.animations; for (var animationId in animations) { @@ -263,418 +207,444 @@ function removeAnimationSamplersIndirection(gltf) { } } -function removeBufferType(gltf) { - var buffers = gltf.buffers; - for (var bufferId in buffers) { - if (buffers.hasOwnProperty(bufferId)) { - var buffer = buffers[bufferId]; - delete buffer.type; + +function objectToArray(object, mapping) { + var array = []; + for (var id in object) { + if (object.hasOwnProperty(id)) { + var value = object[id]; + mapping[id] = array.length; + array.push(value); + if (!defined(value.name)) { + value.name = id; + } } } + return array; } -function makeMaterialValuesArray(gltf) { - var materials = gltf.materials; - for (var materialId in materials) { - if (materials.hasOwnProperty(materialId)) { - var material = materials[materialId]; - var materialValues = material.values; - for (var materialValueId in materialValues) { - if (materialValues.hasOwnProperty(materialValueId)) { - var materialValue = materialValues[materialValueId]; - if (!Array.isArray(materialValue)) { - materialValues[materialValueId] = [materialValue]; +function objectsToArrays(gltf) { + var i; + var globalMapping = {}; + // Convert top level objects to arrays + for (var topLevelId in gltf) { + if (gltf.hasOwnProperty(topLevelId) && topLevelId !== 'extras' && topLevelId !== 'asset') { + var objectMapping = {}; + var object = gltf[topLevelId]; + if (typeof(object) === 'object' && !Array.isArray(object)) { + gltf[topLevelId] = objectToArray(object, objectMapping); + globalMapping[topLevelId] = objectMapping; + } + } + } + // Fix references + if (defined(gltf.scene)) { + gltf.scene = globalMapping.scenes[gltf.scene]; + } + ForEach.bufferView(gltf, function(bufferView) { + if (defined(bufferView.buffer)) { + bufferView.buffer = globalMapping.buffers[bufferView.buffer]; + } + }); + ForEach.accessor(gltf, function(accessor) { + if (defined(accessor.bufferView)) { + accessor.bufferView = globalMapping.bufferViews[accessor.bufferView]; + } + }); + ForEach.shader(gltf, function(shader) { + var extensions = shader.extensions; + if (defined(extensions)) { + var binaryGltf = extensions.KHR_binary_glTF; + if (defined(binaryGltf)) { + shader.bufferView = binaryGltf.bufferView; + delete extensions.KHR_binary_glTF; + } + if (Object.keys(extensions).length === 0) { + delete shader.extensions; + } + } + }); + ForEach.program(gltf, function(program) { + if (defined(program.vertexShader)) { + program.vertexShader = globalMapping.shaders[program.vertexShader]; + } + if (defined(program.fragmentShader)) { + program.fragmentShader = globalMapping.shaders[program.fragmentShader]; + } + }); + ForEach.technique(gltf, function(technique) { + if (defined(technique.program)) { + technique.program = globalMapping.programs[technique.program]; + } + }); + ForEach.material(gltf, function(material) { + if (defined(material.technique)) { + material.technique = globalMapping.techniques[material.technique]; + } + }); + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + if (defined(primitive.indices)) { + primitive.indices = globalMapping.accessors[primitive.indices]; + } + ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + primitive.attributes[semantic] = globalMapping.accessors[accessorId]; + }); + if (defined(primitive.material)) { + primitive.material = globalMapping.materials[primitive.material]; + } + }); + }); + ForEach.skin(gltf, function(skin) { + if (defined(skin.inverseBindMatrices)) { + skin.inverseBindMatrices = globalMapping.accessors[skin.inverseBindMatrices]; + } + }); + ForEach.node(gltf, function(node) { + var children = node.children; + if (defined(children)) { + var childrenLength = children.length; + for (i = 0; i < childrenLength; i++) { + children[i] = globalMapping.nodes[children[i]]; + } + } + if (defined(node.meshes)) { + // Split out meshes on nodes + var meshes = node.meshes; + var meshesLength = meshes.length; + if (meshesLength > 0) { + node.mesh = globalMapping.meshes[meshes[0]]; + for (i = 1; i < meshesLength; i++) { + var meshNode = { + mesh: globalMapping.meshes[meshes[i]] + }; + var meshNodeId = addToArray(gltf.nodes, meshNode); + if (!defined(children)) { + children = []; + node.children = children; } + children.push(meshNodeId); } } + delete node.meshes; } - } -} - -function requireAttributeSetIndex(gltf) { - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - if (defined(primitives)) { - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - var attributes = primitive.attributes; - if (defined(attributes)) { - var semantics = Object.keys(attributes); - var semanticsLength = semantics.length; - for (var j = 0; j < semanticsLength; j++) { - var semantic = semantics[j]; - if (semantic === 'TEXCOORD') { - attributes.TEXCOORD_0 = attributes[semantic]; - delete attributes[semantic]; - } else if (semantic === 'COLOR') { - attributes.COLOR_0 = attributes[semantic]; - delete attributes[semantic]; - } - } + if (defined(node.camera)) { + node.camera = globalMapping.cameras[node.camera]; + } + if (defined(node.skeletons)) { + // Split out skeletons on nodes + var skeletons = node.skeletons; + var skeletonsLength = skeletons.length; + if (skeletonsLength > 0) { + node.skeleton = globalMapping.nodes[skeletons[0]]; + for (i = 1; i < skeletonsLength; i++) { + var skeletonNode = { + skeleton: globalMapping.nodes[skeletons[i]] + }; + var skeletonNodeId = addToArray(gltf.nodes, skeletonNode); + if (!defined(children)) { + children = []; + node.children = children; } + children.push(skeletonNodeId); } } + delete node.skeletons; } - } - var techniques = gltf.techniques; - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = techniques[techniqueId]; - var techniqueParameters = technique.parameters; - for (var techniqueParameterId in techniqueParameters) { - if (techniqueParameters.hasOwnProperty(techniqueParameterId)) { - var techniqueParameter = techniqueParameters[techniqueParameterId]; - var techniqueParameterSemantic = techniqueParameter.semantic; - if (defined(techniqueParameterSemantic)) { - if (techniqueParameterSemantic === 'TEXCOORD') { - techniqueParameter.semantic = 'TEXCOORD_0'; - } else if (techniqueParameterSemantic === 'COLOR') { - techniqueParameter.semantic = 'COLOR_0'; - } + if (defined(node.skin)) { + node.skin = globalMapping.skins[node.skin]; + } + }); + ForEach.animation(gltf, function(animation) { + var samplerMapping = {}; + animation.samplers = objectToArray(animation.samplers, samplerMapping); + ForEach.animationSamplers(animation, function(sampler) { + sampler.input = globalMapping.accessors[sampler.input]; + sampler.output = globalMapping.accessors[sampler.output]; + }); + var channels = animation.channels; + if (defined(channels)) { + var channelsLength = channels.length; + for (i = 0; i < channelsLength; i++) { + var channel = channels[i]; + channel.sampler = samplerMapping[channel.sampler]; + var target = channel.target; + if (defined(target)) { + target.node = globalMapping.nodes[target.node]; + } + } + } + }); + ForEach.material(gltf, function(material) { + ForEach.materialValue(material, function(value, name) { + if (Array.isArray(value)) { + if (value.length === 1) { + var textureId = value[0]; + if (typeof textureId === 'string') { + value[0] = globalMapping.textures[textureId]; } } } + else if (typeof value === 'string') { + material.value[name] = globalMapping.textures[value]; + } + }); + }); + ForEach.image(gltf, function(image) { + var extensions = image.extensions; + if (defined(extensions)) { + var binaryGltf = extensions.KHR_binary_glTF; + if (defined(binaryGltf)) { + image.bufferView = binaryGltf.bufferView; + image.mimeType = binaryGltf.mimeType; + delete extensions.KHR_binary_glTF; + } + if (Object.keys(extensions).length === 0) { + delete image.extensions; + } + } + }); + ForEach.texture(gltf, function(texture) { + if (defined(texture.sampler)) { + texture.sampler = globalMapping.samplers[texture.sampler]; + } + if (defined(texture.source)) { + texture.source = globalMapping.images[texture.source]; + } + }); +} + +function stripProfile(gltf) { + var asset = gltf.asset; + delete asset.profile; +} + +var knownExtensions = { + CESIUM_RTC : true, + KHR_materials_common : true, + WEB3D_quantized_attributes : true +}; +function requireKnownExtensions(gltf) { + var extensionsUsed = gltf.extensionsUsed; + gltf.extensionsRequired = defaultValue(gltf.extensionsRequired, []); + if (defined(extensionsUsed)) { + var extensionsUsedLength = extensionsUsed.length; + for (var i = 0; i < extensionsUsedLength; i++) { + var extension = extensionsUsed[i]; + if (defined(knownExtensions[extension])) { + gltf.extensionsRequired.push(extension); + } } } } +function removeBufferType(gltf) { + ForEach.buffer(gltf, function(buffer) { + delete buffer.type; + + }); +} + +function makeMaterialValuesArrays(gltf) { + ForEach.material(gltf, function(material) { + ForEach.materialValue(material, function(value, name) { + if (!Array.isArray(value)) { + material.values[name] = [value]; + } + }) ; + }); +} + +function requireAttributeSetIndex(gltf) { + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + if (semantic === 'TEXCOORD') { + primitive.attributes.TEXCOORD_0 = accessorId; + } else if (semantic === 'COLOR') { + primitive.attributes.COLOR_0 = accessorId; + } + }); + delete primitive.attributes.TEXCOORD; + delete primitive.attributes.COLOR; + }); + }); + ForEach.technique(gltf, function(technique) { + ForEach.techniqueParameter(technique, function(parameter) { + var semantic = parameter.semantic; + if (defined(semantic)) { + if (semantic === 'TEXCOORD') { + parameter.semantic = 'TEXCOORD_0'; + } else if (semantic === 'COLOR') { + parameter.semantic = 'COLOR_0'; + } + } + }); + }); +} + var knownSemantics = { POSITION: true, NORMAL: true, TEXCOORD: true, COLOR: true, JOINT: true, - WEIGHT: true, + WEIGHT: true }; function underscoreApplicationSpecificSemantics(gltf) { var mappedSemantics = {}; - var meshes = gltf.meshes; - var techniques = gltf.techniques; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - if (defined(primitives)) { - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - var attributes = primitive.attributes; - if (defined(attributes)) { - var semantics = Object.keys(attributes); - var semanticsLength = semantics.length; - for (var j = 0; j < semanticsLength; j++) { - var semantic = semantics[j]; - if (semantic.charAt(0) !== '_') { - var setIndex = semantic.search(/_[0-9]+/g); - var strippedSemantic = semantic; - if (setIndex >= 0) { - strippedSemantic = semantic.substring(0, setIndex); - } - if (!defined(knownSemantics[strippedSemantic])) { - var attributeValue = attributes[semantic]; - delete attributes[semantic]; - var newSemantic = '_' + semantic; - attributes[newSemantic] = attributeValue; - mappedSemantics[semantic] = newSemantic; - } - } - } - } - } - } - } - } - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = techniques[techniqueId]; - var techniqueParameters = technique.parameters; - for (var techniqueParameterId in techniqueParameters) { - if (techniqueParameters.hasOwnProperty(techniqueParameterId)) { - var techniqueParameter = techniqueParameters[techniqueParameterId]; - var mappedSemantic = mappedSemantics[techniqueParameter.semantic]; - if (defined(mappedSemantic)) { - techniqueParameter.semantic = mappedSemantic; - } - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + /* jshint unused:vars */ + ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + if (semantic.charAt(0) !== '_') { + var setIndex = semantic.search(/_[0-9]+/g); + var strippedSemantic = semantic; + if (setIndex >= 0) { + strippedSemantic = semantic.substring(0, setIndex); + } + if (!defined(knownSemantics[strippedSemantic])) { + var newSemantic = '_' + semantic; + mappedSemantics[semantic] = newSemantic; + } + } + }); + for(var semantic in mappedSemantics) { + if (mappedSemantics.hasOwnProperty(semantic)) { + var mappedSemantic = mappedSemantics[semantic]; + var accessorId = primitive.attributes[semantic]; + delete primitive.attributes[semantic]; + primitive.attributes[mappedSemantic] = accessorId; + } + } + }); + }); + ForEach.technique(gltf, function(technique) { + ForEach.techniqueParameter(technique, function(parameter) { + var mappedSemantic = mappedSemantics[parameter.semantic]; + if (defined(mappedSemantic)) { + parameter.semantic = mappedSemantic; } - } - } + }); + }); } function makeTechniqueValuesArrays(gltf) { - var techniques = gltf.techniques; - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = techniques[techniqueId]; - var techniqueParameters = technique.parameters; - for (var techniqueParameterId in techniqueParameters) { - if (techniqueParameters.hasOwnProperty(techniqueParameterId)) { - var techniqueParameter = techniqueParameters[techniqueParameterId]; - var techniqueParameterValue = techniqueParameter.value; - if (defined(techniqueParameterValue) && !Array.isArray(techniqueParameterValue)) { - techniqueParameter.value = [techniqueParameterValue]; - } - } + ForEach.technique(gltf, function(technique) { + ForEach.techniqueParameter(technique, function(parameter) { + var value = parameter.value; + if (defined(value) && !Array.isArray(value)) { + parameter.value = [value]; } - } - } + }); + }); } function removeScissorFromTechniques(gltf) { - var techniques = gltf.techniques; - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = techniques[techniqueId]; - var techniqueStates = technique.states; - if (defined(techniqueStates)) { - var techniqueFunctions = techniqueStates.functions; - if (defined(techniqueFunctions)) { - delete techniqueFunctions.scissor; - } - var enableStates = techniqueStates.enable; - if (defined(enableStates)) { - var scissorIndex = enableStates.indexOf(WebGLConstants.SCISSOR_TEST); - if (scissorIndex >= 0) { - enableStates.splice(scissorIndex, 1); - } + ForEach.technique(gltf, function(technique) { + var techniqueStates = technique.states; + if (defined(techniqueStates)) { + var techniqueFunctions = techniqueStates.functions; + if (defined(techniqueFunctions)) { + delete techniqueFunctions.scissor; + } + var enableStates = techniqueStates.enable; + if (defined(enableStates)) { + var scissorIndex = enableStates.indexOf(WebGLConstants.SCISSOR_TEST); + if (scissorIndex >= 0) { + enableStates.splice(scissorIndex, 1); } } } - } + }); } function clampTechniqueFunctionStates(gltf) { var i; - var techniques = gltf.techniques; - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = techniques[techniqueId]; - var techniqueStates = technique.states; - if (defined(techniqueStates)) { - var functions = techniqueStates.functions; - if (defined(functions)) { - var blendColor = functions.blendColor; - if (defined(blendColor)) { - for (i = 0; i < 4; i++) { - blendColor[i] = CesiumMath.clamp(blendColor[i], 0.0, 1.0); - } - } - var depthRange = functions.depthRange; - if (defined(depthRange)) { - depthRange[1] = CesiumMath.clamp(depthRange[1], 0.0, 1.0); - depthRange[0] = CesiumMath.clamp(depthRange[0], 0.0, depthRange[1]); + ForEach.technique(gltf, function(technique) { + var techniqueStates = technique.states; + if (defined(techniqueStates)) { + var functions = techniqueStates.functions; + if (defined(functions)) { + var blendColor = functions.blendColor; + if (defined(blendColor)) { + for (i = 0; i < 4; i++) { + blendColor[i] = CesiumMath.clamp(blendColor[i], 0.0, 1.0); } } + var depthRange = functions.depthRange; + if (defined(depthRange)) { + depthRange[1] = CesiumMath.clamp(depthRange[1], 0.0, 1.0); + depthRange[0] = CesiumMath.clamp(depthRange[0], 0.0, depthRange[1]); + } } } - } + }); } function clampCameraParameters(gltf) { - var cameras = gltf.cameras; - for (var cameraId in cameras) { - if (cameras.hasOwnProperty(cameraId)) { - var camera = cameras[cameraId]; - var perspective = camera.perspective; - if (defined(perspective)) { - var aspectRatio = perspective.aspectRatio; - if (defined(aspectRatio) && aspectRatio === 0.0) { - delete perspective.aspectRatio; - } - var yfov = perspective.yfov; - if (defined(yfov) && yfov === 0.0) { - perspective.yfov = 1.0; - } + ForEach.camera(gltf, function(camera) { + var perspective = camera.perspective; + if (defined(perspective)) { + var aspectRatio = perspective.aspectRatio; + if (defined(aspectRatio) && aspectRatio === 0.0) { + delete perspective.aspectRatio; + } + var yfov = perspective.yfov; + if (defined(yfov) && yfov === 0.0) { + perspective.yfov = 1.0; } } - } + }); } function requireByteLength(gltf) { - var buffers = gltf.buffers; - for (var bufferId in buffers) { - if (buffers.hasOwnProperty(bufferId)) { - var buffer = buffers[bufferId]; - if (!defined(buffer.byteLength)) { - buffer.byteLength = buffer.extras._pipeline.source.length; - } + ForEach.buffer(gltf, function(buffer) { + if (!defined(buffer.byteLength)) { + buffer.byteLength = buffer.extras._pipeline.source.length; } - } - var bufferViews = gltf.bufferViews; - for (var bufferViewId in bufferViews) { - if (bufferViews.hasOwnProperty(bufferViewId)) { - var bufferView = bufferViews[bufferViewId]; - if (!defined(bufferView.byteLength)) { - var bufferViewBufferId = bufferView.buffer; - var bufferViewBuffer = buffers[bufferViewBufferId]; - bufferView.byteLength = bufferViewBuffer.byteLength; - } + }); + ForEach.bufferView(gltf, function(bufferView) { + if (!defined(bufferView.byteLength)) { + var bufferViewBufferId = bufferView.buffer; + var bufferViewBuffer = gltf.buffers[bufferViewBufferId]; + bufferView.byteLength = bufferViewBuffer.byteLength; } - } + }); } function requireAccessorMinMax(gltf) { - var accessors = gltf.accessors; - for (var accessorId in accessors) { - if (accessors.hasOwnProperty(accessorId)) { - var accessor = accessors[accessorId]; - if (!defined(accessor.min) || !defined(accessor.max)) { - var minMax = findAccessorMinMax(gltf, accessor); - accessor.min = minMax.min; - accessor.max = minMax.max; - } - } - } -} - -var scratchTranslation = new Cartesian3(); -var scratchRotation = new Quaternion(); -var scratchScale = new Cartesian3(); -var defaultScale = new Cartesian3(1.0, 1.0, 1.0); -var scratchMatrix4 = new Matrix4(); -var scratchPreApplyTransform = new Matrix4(); -function getNodeTransform(node) { - if (defined(node.matrix)) { - return Matrix4.fromArray(node.matrix); - } else if (defined(node.translation) || defined(node.rotation) || defined(node.scale)) { - Cartesian3.ZERO.clone(scratchTranslation); - if (defined(node.translation)) { - Cartesian3.unpack(node.translation, scratchTranslation); - } - Quaternion.IDENTITY.clone(scratchRotation); - if (defined(node.rotation)) { - Quaternion.unpack(node.rotation, scratchRotation); - } - defaultScale.clone(scratchScale); - if (defined(node.scale)) { - Cartesian3.unpack(node.scale, scratchScale); - } - Matrix4.fromTranslationQuaternionRotationScale(scratchTranslation, scratchRotation, scratchScale, scratchMatrix4); - return scratchMatrix4; - } else { - return Matrix4.IDENTITY; - } -} - -function separateSkeletonHierarchy(gltf) { - var nodes = gltf.nodes; - var scenes = gltf.scenes; - - var skinnedNodes = []; - var parentNodes = {}; - - var i; - var skeletonIds; - - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - var node = nodes[nodeId]; - var children = node.children; - if (defined(children)) { - var childrenLength = children.length; - for (i = 0; i < childrenLength; i++) { - var childNodeId = children[i]; - parentNodes[childNodeId] = nodeId; - } - } - var skinId = node.skin; - skeletonIds = node.skeletons; - if (defined(skinId) && defined(skeletonIds)) { - skinnedNodes.push(nodeId); - } - } - } - - var sceneId = gltf.scene; - if (defined(sceneId)) { - var scene = scenes[sceneId]; - - var skinnedNodesLength = skinnedNodes.length; - for (i = 0; i < skinnedNodesLength; i++) { - var skinnedNodeId = skinnedNodes[i]; - var skinnedNode = nodes[skinnedNodeId]; - skeletonIds = skinnedNode.skeletons; - var skeletonIdsLength = skeletonIds.length; - for (var j = 0; j < skeletonIdsLength; j++) { - var skeletonId = skeletonIds[j]; - var parentNodeId = parentNodes[skeletonId]; - if (defined(parentNodeId)) { - var parentNode = nodes[parentNodeId]; - var parentChildren = parentNode.children; - var index = parentChildren.indexOf(skeletonId); - parentChildren.splice(index, 1); - parentNode.children = parentChildren; - Matrix4.IDENTITY.clone(scratchPreApplyTransform); - while (defined(parentNode)) { - var parentTransform = getNodeTransform(parentNode); - Matrix4.multiply(parentTransform, scratchPreApplyTransform, scratchPreApplyTransform); - parentNodeId = parentNodes[parentNodeId]; - parentNode = nodes[parentNodeId]; - } - if (!Matrix4.equals(scratchPreApplyTransform, Matrix4.IDENTITY)) { - var newRootNodeId = getUniqueId(gltf, 'root-' + skeletonId); - var newRootNode = { - children: [], - matrix: Matrix4.pack(scratchPreApplyTransform, [], 0), - extras: { - _pipeline: {} - } - }; - newRootNode.children.push(skeletonId); - nodes[newRootNodeId] = newRootNode; - skeletonId = newRootNodeId; - skeletonIds[j] = newRootNodeId; - } - scene.nodes.push(skeletonId); - } - } + ForEach.accessor(gltf, function(accessor) { + if (!defined(accessor.min) || !defined(accessor.max)) { + var minMax = findAccessorMinMax(gltf, accessor); + accessor.min = minMax.min; + accessor.max = minMax.max; } - } + }); } function stripTechniqueAttributeValues(gltf) { - var techniques = gltf.techniques; - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = techniques[techniqueId]; - var attributes = technique.attributes; - var parameters = technique.parameters; - for (var attributeName in attributes) { - if (attributes.hasOwnProperty(attributeName)) { - var parameterId = attributes[attributeName]; - var parameter = parameters[parameterId]; - if (defined(parameter.value)) { - delete parameter.value; - } - } - } - } - } + ForEach.technique(gltf, function(technique) { + ForEach.techniqueAttribute(technique, function(attribute) { + var parameter = technique.parameters[attribute]; + if (defined(parameter.value)) { + delete parameter.value; + } + }); + }); } function stripTechniqueParameterCount(gltf) { - var techniques = gltf.techniques; - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = techniques[techniqueId]; - var parameters = technique.parameters; - for (var parameterId in parameters) { - if (parameters.hasOwnProperty(parameterId)) { - var parameter = parameters[parameterId]; - if (defined(parameter.count)) { - var semantic = parameter.semantic; - if (!defined(semantic) || (semantic !== 'JOINTMATRIX' && semantic.indexOf('_') !== 0)) { - delete parameter.count; - } - } - } - } - } - } + ForEach.technique(gltf, function(technique) { + ForEach.techniqueParameter(technique, function(parameter) { + if (defined(parameter.count)) { + var semantic = parameter.semantic; + if (!defined(semantic) || (semantic !== 'JOINTMATRIX' && semantic.indexOf('_') !== 0)) { + delete parameter.count; + } + } + }); + }); } function glTF10to20(gltf) { @@ -683,26 +653,26 @@ function glTF10to20(gltf) { } var asset = gltf.asset; asset.version = '2.0'; - // profile.version does not include revision number ("1.0.3" -> "1.0") - stripWebGLRevisionNumber(gltf); - // move known extensions from extensionsUsed to extensionsRequired - requireKnownExtensions(gltf); - // if any index accessors have UNSIGNED_INT componentType, add the WebGL extension OES_element_index_uint - addGlExtensionsUsed(gltf); // animation.samplers now refers directly to accessors and animation.parameters should be removed removeAnimationSamplersIndirection(gltf); + // top-level objects are now arrays referenced by index instead of id + objectsToArrays(gltf); + // asset.profile no longer exists + stripProfile(gltf); + // move known extensions from extensionsUsed to extensionsRequired + requireKnownExtensions(gltf); // bufferView.byteLength and buffer.byteLength are required requireByteLength(gltf); // accessor.min and accessor.max must be defined requireAccessorMinMax(gltf); // buffer.type is unnecessary and should be removed removeBufferType(gltf); - // material.values should be arrays - makeMaterialValuesArray(gltf); // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#) requireAttributeSetIndex(gltf); // Add underscores to application-specific parameters underscoreApplicationSpecificSemantics(gltf); + // material.values should be arrays + makeMaterialValuesArrays(gltf); // technique.parameters.value should be arrays makeTechniqueValuesArrays(gltf); // remove scissor from techniques @@ -711,8 +681,6 @@ function glTF10to20(gltf) { clampTechniqueFunctionStates(gltf); // clamp camera parameters clampCameraParameters(gltf); - // skeleton hierarchy must be separate from the node hierarchy (a node with jointName cannot contain camera, skeletons, skins, or meshes) - separateSkeletonHierarchy(gltf); // a technique parameter specified as an attribute cannot have a value stripTechniqueAttributeValues(gltf); // only techniques with a JOINTMATRIX or application specific semantic may have a defined count property diff --git a/lib/writeBinaryGltf.js b/lib/writeBinaryGltf.js index 4dc28373..8c84aebc 100644 --- a/lib/writeBinaryGltf.js +++ b/lib/writeBinaryGltf.js @@ -3,13 +3,13 @@ var Cesium = require('cesium'); var fsExtra = require('fs-extra'); var path = require('path'); var Promise = require('bluebird'); +var ForEach = require('./ForEach'); +var getBinaryGltf = require('./getBinaryGltf'); +var writeSource = require('./writeSource'); var defined = Cesium.defined; var DeveloperError = Cesium.DeveloperError; -var getBinaryGltf = require('./getBinaryGltf'); -var writeSource = require('./writeSource'); - fsExtra.outputFileAsync = Promise.promisify(fsExtra.outputFile); module.exports = writeBinaryGltf; @@ -32,8 +32,6 @@ module.exports = writeBinaryGltf; */ function writeBinaryGltf(gltf, options) { var outputPath = options.outputPath; - var embed = options.embed; - var embedImage = options.embedImage; var createDirectory = options.createDirectory; if (!defined(outputPath)) { throw new DeveloperError('Output path is undefined.'); @@ -51,25 +49,21 @@ function writeBinaryGltf(gltf, options) { var basePath = path.dirname(outputPath); var writeSources = [ - writeSource(gltf.images, 'images', basePath, embed, embedImage), - writeSource(gltf.shaders, 'shaders', basePath, embed, embedImage) + writeSource(gltf.images, 'images', basePath, options), + writeSource(gltf.shaders, 'shaders', basePath, options) ]; // Write sources for compressed textures - var images = gltf.images; - for (var imageId in images) { - if (images.hasOwnProperty(imageId)) { - var image = images[imageId]; - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - writeSources.push(writeSource(compressedImages, 'images', basePath, embed, embedImage)); - } + ForEach.image(gltf, function(image) { + if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { + var compressedImages = image.extras.compressedImage3DTiles; + writeSources.push(writeSource(compressedImages, 'images', basePath, options)); } - } + }); return Promise.all(writeSources) .then(function() { - var glbData = getBinaryGltf(gltf, embed, embedImage); + var glbData = getBinaryGltf(gltf, options); var glb = glbData.glb; return fsExtra.outputFileAsync(outputPath, glb); }); diff --git a/lib/writeGltf.js b/lib/writeGltf.js index 4f008b87..fd3e9e83 100755 --- a/lib/writeGltf.js +++ b/lib/writeGltf.js @@ -32,8 +32,6 @@ module.exports = writeGltf; */ function writeGltf(gltf, options) { var outputPath = options.outputPath; - var embed = options.embed; - var embedImage = options.embedImage; var createDirectory = options.createDirectory; if (!defined(outputPath)) { @@ -52,17 +50,16 @@ function writeGltf(gltf, options) { var basePath = path.dirname(outputPath); var writeSources = [ - writeSource(gltf.buffers, 'buffers', basePath, embed, embedImage), - writeSource(gltf.images, 'images', basePath, embed, embedImage), - writeSource(gltf.shaders, 'shaders', basePath, embed, embedImage) + writeSource(gltf.buffers, 'buffers', basePath, options), + writeSource(gltf.images, 'images', basePath, options), + writeSource(gltf.shaders, 'shaders', basePath, options) ]; // Write sources for compressed textures - /* jshint unused:vars */ - ForEach.image(gltf, function(imageId, image) { + ForEach.image(gltf, function(image) { if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { var compressedImages = image.extras.compressedImage3DTiles; - writeSources.push(writeSource(compressedImages, 'images', basePath, embed, embedImage)); + writeSources.push(writeSource(compressedImages, 'images', basePath, options)); } }); diff --git a/lib/writeSource.js b/lib/writeSource.js index 38472b70..1bf1ca5f 100644 --- a/lib/writeSource.js +++ b/lib/writeSource.js @@ -4,6 +4,7 @@ var fsExtra = require('fs-extra'); var mime = require('mime'); var path = require('path'); var Promise = require('bluebird'); +var ForEach = require('./ForEach'); var isDataUri = require('./isDataUri'); var defaultValue = Cesium.defaultValue; @@ -16,55 +17,53 @@ module.exports = writeSource; /** * @private */ -function writeSource(arrayOfObjects, name, basePath, embed, embedImage) { +function writeSource(arrayOfObjects, name, basePath, options) { + var embed = defaultValue(options.embed, true); + var embedImage = defaultValue(options.embedImage, true); var promises = []; - if (defined(arrayOfObjects)) { - var arrayLength = arrayOfObjects.length; - for (var i = 0; i < arrayLength; i++) { - var object = arrayOfObjects[i]; - if (defined(object.extras._pipeline.source)) { - var pipelineExtras = object.extras._pipeline; - var source = pipelineExtras.source; - var extension = pipelineExtras.extension; + ForEach.arrayOfObjects(arrayOfObjects, function(object, i) { + if (defined(object.extras._pipeline.source)) { + var pipelineExtras = object.extras._pipeline; + var source = pipelineExtras.source; + var extension = pipelineExtras.extension; - // Write sources for compressed textures - if (name === 'images') { - var image = object; - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - promises.push(writeSource(compressedImages, 'images', undefined, embed, embedImage)); - } + // Write sources for compressed textures + if (name === 'images') { + var image = object; + if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { + var compressedImages = image.extras.compressedImage3DTiles; + promises.push(writeSource(compressedImages, 'images', undefined, embed, embedImage)); } + } - if (embed && (embedImage || name !== 'images') || !defined(basePath)) { - if (name === 'shaders') { - object.uri = 'data:text/plain;base64,' + new Buffer(source).toString('base64'); - } else { - // .crn (Crunch) is not a supported mime type, so add it - mime.define({'image/crn': ['crn']}); - object.uri = 'data:' + mime.lookup(extension) + ';base64,' + source.toString('base64'); - } + if (embed && (embedImage || name !== 'images') || !defined(basePath)) { + if (name === 'shaders') { + object.uri = 'data:text/plain;base64,' + new Buffer(source).toString('base64'); } else { - var fileName = i + extension; - // Use the name if we have one - if (defined(object.name)) { - fileName = object.name + extension; - } - var uri = object.uri; - if (defined(uri) && !isDataUri(uri)) { - // Use the original filename if it was external - fileName = uri; - } - // For compressed textures use the name stored in the extras rather than the id - if (defined(pipelineExtras.name)) { - fileName = pipelineExtras.name + extension; - } - object.uri = fileName; - var outputPath = path.join(basePath, fileName); - promises.push(fsOutputFile(outputPath, source)); + // .crn (Crunch) is not a supported mime type, so add it + mime.define({'image/crn': ['crn']}); + object.uri = 'data:' + mime.lookup(extension) + ';base64,' + source.toString('base64'); + } + } else { + var fileName = i + extension; + // Use the name if we have one + if (defined(object.name)) { + fileName = object.name + extension; + } + var uri = object.uri; + if (defined(uri) && !isDataUri(uri)) { + // Use the original filename if it was external + fileName = uri; + } + // For compressed textures use the name stored in the extras rather than the id + if (defined(pipelineExtras.name)) { + fileName = pipelineExtras.name + extension; } + object.uri = fileName; + var outputPath = path.join(basePath, fileName); + promises.push(fsOutputFile(outputPath, source)); } } - } + }); return Promise.all(promises); } diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestUnusedTree.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestUnusedTree.gltf index c804476a..8dcd9c7e 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestUnusedTree.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestUnusedTree.gltf @@ -1,141 +1,143 @@ { - "accessors": { - "accessor_23": { - "bufferView": "bufferView_30", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "componentType": 5126, "count": 24, - "type": "VEC3" + "type": "VEC3", + "name": "accessor_23" }, - "animAccessor_0": { - "bufferView": "bufferView_30", + { + "bufferView": 0, "byteOffset": 128, "componentType": 5126, "count": 3, - "type": "SCALAR" + "type": "SCALAR", + "name": "animAccessor_0" }, - "IBM_Armature_Cylinder-skin": { - "bufferView": "bufferView_30", + { + "bufferView": 0, "byteOffset": 0, "componentType": 5126, "count": 2, - "type": "MAT4" + "type": "MAT4", + "name": "IBM_Armature_Cylinder-skin" } - }, - "animations": { - "animation_0": { - "parameters": { - } + ], + "animations": [ + { } - }, - "bufferViews": { - "bufferView_30": { - "buffer": "CesiumTexturedBoxTest", + ], + "bufferViews": [ + { + "buffer": 0, "byteOffset": 72 } - }, - "buffers": { - "CesiumTexturedBoxTest": { + ], + "buffers": [ + { "uri": "CesiumTexturedBoxTest.bin" } - }, - "cameras": { - "camera_0": { + ], + "cameras": [ + { "type": "perspective" } - }, - "images": { - "Image0001": { + ], + "images": [ + { "uri": "Cesium_Logo_Flat.png" } - }, - "materials": { - "Effect-Texture": { - "technique": "technique0", + ], + "materials": [ + { + "technique": 0, "values": { - "diffuse": ["texture_Image0001"] + "diffuse": [0] } } - }, - "meshes": { - "Geometry-mesh002": { + ], + "meshes": [ + { "primitives": [ { "attributes": { - "POSITION": "accessor_23" + "POSITION": 0 }, - "material": "Effect-Texture" + "material": 0 } ] } - }, - "nodes": { - "Geometry-mesh002Node": { - "meshes": [ - "Geometry-mesh002" - ] + ], + "nodes": [ + { + "mesh": 0, + "name": "Geometry-mesh002Node" }, - "groupLocator030Node": { + { "children": [ - "txtrLocator026Node" - ] + 3 + ], + "name": "groupLocator030Node" }, - "node_3": { - "camera": "camera_0", + { + "camera": 0, "children": [ - "Geometry-mesh002Node", - "groupLocator030Node" - ] + 0, + 1 + ], + "name": "node_3" }, - "txtrLocator026Node": { - "skin": "Armature_Cylinder-skin" - } - }, - "programs": { - "program_0": { - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" - } - }, - "samplers": { - "sampler_0": { - } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { - "nodes": [ - ] - } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { + { + "skin": 0, + "name": "txtrLocator026Node" + } + ], + "programs": [ + { + "fragmentShader": 0, + "vertexShader": 1 + } + ], + "samplers": [ + { + } + ], + "scene": 0, + "scenes": [ + { + "nodes": [] + } + ], + "shaders": [ + { "type": 35632, "uri": "CesiumTexturedBoxTest0FS.glsl" }, - "CesiumTexturedBoxTest0VS": { + { "type": 35633, "uri": "CesiumTexturedBoxTest0VS.glsl" } - }, - "skins": { - "Armature_Cylinder-skin": { - "inverseBindMatrices": "IBM_Armature_Cylinder-skin", + ], + "skins": [ + { + "inverseBindMatrices": 2, "jointNames": [ "Bone", "Bone_001" ] } - }, - "techniques": { - "technique0": { - "program": "program_0" + ], + "techniques": [ + { + "program": 0 } - }, - "textures": { - "texture_Image0001": { - "sampler": "sampler_0", - "source": "Image0001" + ], + "textures": [ + { + "sampler": 0, + "source": 0 } - } + ] } \ No newline at end of file diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_Binary.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_Binary.gltf index e3b182f8..3e802e46 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_Binary.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_Binary.gltf @@ -1,15 +1,15 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, "type": "SCALAR" }, - "accessor_23": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -26,8 +26,8 @@ ], "type": "VEC3" }, - "accessor_25": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 288, "byteStride": 12, "componentType": 5126, @@ -44,8 +44,8 @@ ], "type": "VEC3" }, - "accessor_27": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 576, "byteStride": 8, "componentType": 5126, @@ -60,8 +60,8 @@ ], "type": "VEC2" } - }, - "animations": {}, + ], + "animations": [], "asset": { "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", "premultipliedAlpha": true, @@ -71,40 +71,40 @@ }, "version": 1 }, - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", + "bufferViews": [ + { + "buffer": 0, "byteLength": 72, "byteOffset": 0, "target": 34963 }, - "bufferView_30": { - "buffer": "CesiumTexturedBoxTest", + { + "buffer": 0, "byteLength": 768, "byteOffset": 72, "target": 34962 } - }, - "buffers": { - "CesiumTexturedBoxTest": { + ], + "buffers": [ + { "byteLength": 840, "type": "arraybuffer", "uri": "CesiumTexturedBoxTest.bin" } - }, - "images": { - "Image0001": { + ], + "images": [ + { "name": "Image0001", "uri": "Cesium_Logo_Flat_Binary.png" } - }, - "materials": { - "Effect-Texture": { + ], + "materials": [ + { "name": "Texture", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Image0001", - "shininess": 256, + "diffuse": [0], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -113,26 +113,26 @@ ] } } - }, - "meshes": { - "Geometry-mesh002": { + ], + "meshes": [ + { "name": "Mesh", "primitives": [ { "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" + "NORMAL": 2, + "POSITION": 1, + "TEXCOORD_0": 3 }, - "indices": "accessor_21", - "material": "Effect-Texture", + "indices": 0, + "material": 0, "mode": 4 } ] } - }, - "nodes": { - "Geometry-mesh002Node": { + ], + "nodes": [ + { "children": [], "matrix": [ 1, @@ -152,14 +152,12 @@ 0, 1 ], - "meshes": [ - "Geometry-mesh002" - ], + "mesh": 0, "name": "Mesh" }, - "groupLocator030Node": { + { "children": [ - "txtrLocator026Node" + 3 ], "matrix": [ 1, @@ -181,10 +179,10 @@ ], "name": "Texture_Group" }, - "node_3": { + { "children": [ - "Geometry-mesh002Node", - "groupLocator030Node" + 0, + 1 ], "matrix": [ 1, @@ -206,7 +204,7 @@ ], "name": "Y_UP_Transform" }, - "txtrLocator026Node": { + { "children": [], "matrix": [ 1, @@ -228,47 +226,47 @@ ], "name": "Cesium_Logo_Flat__Image___Texture_" } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position", "a_texcoord0" ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "samplers": { - "sampler_0": { + ], + "samplers": [ + { "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497 } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_3" + 2 ] } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { + ], + "shaders": [ + { "type": 35632, "uri": "CesiumTexturedBoxTest0FS_Binary.glsl" }, - "CesiumTexturedBoxTest0VS": { + { "type": 35633, "uri": "CesiumTexturedBoxTest0VS_Binary.glsl" } - }, + ], "skins": {}, - "techniques": { - "technique0": { + "techniques": [ + { "attributes": { "a_normal": "normal", "a_position": "position", @@ -309,7 +307,7 @@ "type": 35664 } }, - "program": "program_0", + "program": 0, "states": { "enable": [ 2929, @@ -325,15 +323,15 @@ "u_specular": "specular" } } - }, - "textures": { - "texture_Image0001": { + ], + "textures": [ + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", + "sampler": 0, + "source": 0, "target": 3553, "type": 5121 } - } + ] } \ No newline at end of file diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf index 0522fdca..f89736f7 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf @@ -1,15 +1,15 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, "type": "SCALAR" }, - "accessor_23": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -26,8 +26,8 @@ ], "type": "VEC3" }, - "accessor_25": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 288, "byteStride": 12, "componentType": 5126, @@ -44,8 +44,8 @@ ], "type": "VEC3" }, - "accessor_27": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 576, "byteStride": 8, "componentType": 5126, @@ -60,8 +60,8 @@ ], "type": "VEC2" } - }, - "animations": {}, + ], + "animations": [], "asset": { "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", "premultipliedAlpha": true, @@ -71,65 +71,53 @@ }, "version": 1 }, - "bufferViews": { - "bufferView_29": { - "buffer": "binary_glTF", + "bufferViews": [ + { + "buffer": 0, "byteLength": 72, "byteOffset": 0, "target": 34963 }, - "bufferView_30": { - "buffer": "binary_glTF", + { + "buffer": 0, "byteLength": 768, "byteOffset": 72, "target": 34962 }, - "binary_bufferView0": { - "buffer": "binary_glTF", + { + "buffer": 0, "byteLength": 529, "byteOffset": 840 }, - "binary_bufferView1": { - "buffer": "binary_glTF", + { + "buffer": 0, "byteLength": 439, "byteOffset": 1369 }, - "binary_bufferView2": { - "buffer": "binary_glTF", + { + "buffer": 0, "byteLength": 11982, "byteOffset": 1808 } - }, - "buffers": { - "binary_glTF": { - "type": "arraybuffer", - "byteLength": 13790, - "uri": "data:," + ], + "buffers": [ + { + "byteLength": 13790 } - }, - "extensionsUsed": ["KHR_binary_glTF"], - "extensionsRequired": ["KHR_binary_glTF"], - "images": { - "Image0001": { + ], + "images": [ + { "name": "Image0001", - "uri": "data:,", - "extensions": { - "KHR_binary_glTF": { - "bufferView": "binary_bufferView2", - "mimeType": "image/png", - "width": 211, - "height": 211 - } - } + "bufferView": 4 } - }, - "materials": { - "Effect-Texture": { + ], + "materials": [ + { "name": "Texture", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Image0001", - "shininess": 256, + "diffuse": [0], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -138,26 +126,26 @@ ] } } - }, - "meshes": { - "Geometry-mesh002": { + ], + "meshes": [ + { "name": "Mesh", "primitives": [ { "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" + "NORMAL": 2, + "POSITION": 1, + "TEXCOORD_0": 3 }, - "indices": "accessor_21", - "material": "Effect-Texture", + "indices": 0, + "material": 0, "mode": 4 } ] } - }, - "nodes": { - "Geometry-mesh002Node": { + ], + "nodes": [ + { "children": [], "matrix": [ 1, @@ -177,14 +165,12 @@ 0, 1 ], - "meshes": [ - "Geometry-mesh002" - ], + "mesh": 0, "name": "Mesh" }, - "groupLocator030Node": { + { "children": [ - "txtrLocator026Node" + 3 ], "matrix": [ 1, @@ -206,10 +192,10 @@ ], "name": "Texture_Group" }, - "node_3": { + { "children": [ - "Geometry-mesh002Node", - "groupLocator030Node" + 0, + 1 ], "matrix": [ 1, @@ -231,7 +217,7 @@ ], "name": "Y_UP_Transform" }, - "txtrLocator026Node": { + { "children": [], "matrix": [ 1, @@ -253,57 +239,47 @@ ], "name": "Cesium_Logo_Flat__Image___Texture_" } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position", "a_texcoord0" ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "samplers": { - "sampler_0": { + ], + "samplers": [ + { "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497 } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_3" + 2 ] } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { + ], + "shaders": [ + { "type": 35632, - "uri": "data:,", - "extensions": { - "KHR_binary_glTF": { - "bufferView": "binary_bufferView0" - } - } + "bufferView": 2 }, - "CesiumTexturedBoxTest0VS": { + { "type": 35633, - "uri": "data:,", - "extensions": { - "KHR_binary_glTF": { - "bufferView": "binary_bufferView1" - } - } + "bufferView": 3 } - }, - "skins": {}, - "techniques": { - "technique0": { + ], + "skins": [], + "techniques": [ + { "attributes": { "a_normal": "normal", "a_position": "position", @@ -344,7 +320,7 @@ "type": 35664 } }, - "program": "program_0", + "program": 0, "states": { "enable": [ 2929, @@ -360,15 +336,15 @@ "u_specular": "specular" } } - }, - "textures": { - "texture_Image0001": { + ], + "textures": [ + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", + "sampler": 0, + "source": 0, "target": 3553, "type": 5121 } - } + ] } \ No newline at end of file diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryInput.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryInput.gltf index e3b182f8..9bc578c5 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryInput.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryInput.gltf @@ -1,15 +1,16 @@ { - "accessors": { - "accessor_21": { - "bufferView": "bufferView_29", + "accessors": [ + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, - "type": "SCALAR" + "type": "SCALAR", + "name": "accessor_21" }, - "accessor_23": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -24,10 +25,11 @@ -0.5, -0.5 ], - "type": "VEC3" + "type": "VEC3", + "name": "accessor_23" }, - "accessor_25": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 288, "byteStride": 12, "componentType": 5126, @@ -42,10 +44,11 @@ -1, -1 ], - "type": "VEC3" + "type": "VEC3", + "name": "accessor_25" }, - "accessor_27": { - "bufferView": "bufferView_30", + { + "bufferView": 1, "byteOffset": 576, "byteStride": 8, "componentType": 5126, @@ -58,10 +61,11 @@ 0, 0 ], - "type": "VEC2" + "type": "VEC2", + "name": "accessor_27" } - }, - "animations": {}, + ], + "animations": [], "asset": { "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", "premultipliedAlpha": true, @@ -71,40 +75,40 @@ }, "version": 1 }, - "bufferViews": { - "bufferView_29": { - "buffer": "CesiumTexturedBoxTest", + "bufferViews": [ + { + "buffer": 0, "byteLength": 72, "byteOffset": 0, "target": 34963 }, - "bufferView_30": { - "buffer": "CesiumTexturedBoxTest", + { + "buffer": 0, "byteLength": 768, "byteOffset": 72, "target": 34962 } - }, - "buffers": { - "CesiumTexturedBoxTest": { + ], + "buffers": [ + { "byteLength": 840, "type": "arraybuffer", "uri": "CesiumTexturedBoxTest.bin" } - }, - "images": { - "Image0001": { + ], + "images": [ + { "name": "Image0001", "uri": "Cesium_Logo_Flat_Binary.png" } - }, - "materials": { - "Effect-Texture": { + ], + "materials": [ + { "name": "Texture", - "technique": "technique0", + "technique": 0, "values": { - "diffuse": "texture_Image0001", - "shininess": 256, + "diffuse": [0], + "shininess": [256], "specular": [ 0.2, 0.2, @@ -113,26 +117,26 @@ ] } } - }, - "meshes": { - "Geometry-mesh002": { + ], + "meshes": [ + { "name": "Mesh", "primitives": [ { "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" + "NORMAL": 2, + "POSITION": 1, + "TEXCOORD_0": 3 }, - "indices": "accessor_21", - "material": "Effect-Texture", + "indices": 0, + "material": 0, "mode": 4 } ] } - }, - "nodes": { - "Geometry-mesh002Node": { + ], + "nodes": [ + { "children": [], "matrix": [ 1, @@ -152,14 +156,12 @@ 0, 1 ], - "meshes": [ - "Geometry-mesh002" - ], + "mesh": 0, "name": "Mesh" }, - "groupLocator030Node": { + { "children": [ - "txtrLocator026Node" + 3 ], "matrix": [ 1, @@ -181,10 +183,10 @@ ], "name": "Texture_Group" }, - "node_3": { + { "children": [ - "Geometry-mesh002Node", - "groupLocator030Node" + 0, + 1 ], "matrix": [ 1, @@ -206,7 +208,7 @@ ], "name": "Y_UP_Transform" }, - "txtrLocator026Node": { + { "children": [], "matrix": [ 1, @@ -228,47 +230,47 @@ ], "name": "Cesium_Logo_Flat__Image___Texture_" } - }, - "programs": { - "program_0": { + ], + "programs": [ + { "attributes": [ "a_normal", "a_position", "a_texcoord0" ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "samplers": { - "sampler_0": { + ], + "samplers": [ + { "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497 } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_3" + 2 ] } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { + ], + "shaders": [ + { "type": 35632, "uri": "CesiumTexturedBoxTest0FS_Binary.glsl" }, - "CesiumTexturedBoxTest0VS": { + { "type": 35633, "uri": "CesiumTexturedBoxTest0VS_Binary.glsl" } - }, - "skins": {}, - "techniques": { - "technique0": { + ], + "skins": [], + "techniques": [ + { "attributes": { "a_normal": "normal", "a_position": "position", @@ -309,7 +311,7 @@ "type": 35664 } }, - "program": "program_0", + "program": 0, "states": { "enable": [ 2929, @@ -325,15 +327,15 @@ "u_specular": "specular" } } - }, - "textures": { - "texture_Image0001": { + ], + "textures": [ + { "format": 6408, "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", + "sampler": 0, + "source": 0, "target": 3553, "type": 5121 } - } + ] } \ No newline at end of file diff --git a/specs/data/generateNormals/box_no_normals.gltf b/specs/data/generateNormals/box_no_normals.gltf index 72983ec3..f51ad6cc 100644 --- a/specs/data/generateNormals/box_no_normals.gltf +++ b/specs/data/generateNormals/box_no_normals.gltf @@ -1,15 +1,16 @@ { - "accessors": { - "accessor_index_0": { - "bufferView": "bufferView_index", + "accessors": [ + { + "bufferView": 1, "byteOffset": 0, "byteStride": 0, "componentType": 5123, "count": 36, - "type": "SCALAR" + "type": "SCALAR", + "name": "accessor_index_0" }, - "accessor_position": { - "bufferView": "bufferView_vertex", + { + "bufferView": 0, "byteOffset": 0, "byteStride": 12, "componentType": 5126, @@ -24,9 +25,10 @@ 1, 1 ], - "type": "VEC3" + "type": "VEC3", + "name": "accessor_position" } - }, + ], "asset": { "generator": "OBJ2GLTF", "premultipliedAlpha": true, @@ -36,30 +38,30 @@ }, "version": 1 }, - "buffers": { - "buffer_box": { + "buffers": [ + { "byteLength": 168, "type": "arraybuffer", "uri": "data:application/octet-stream;base64,AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIA/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AAABAAIAAAACAAMAAQAEAAUAAQAFAAIABAAGAAcABAAHAAUABgAAAAMABgADAAcAAwACAAUAAwAFAAcABgAEAAEABgABAAAA" } - }, - "bufferViews": { - "bufferView_vertex": { - "buffer": "buffer_box", + ], + "bufferViews": [ + { + "buffer": 0, "byteLength": 96, "byteOffset": 0, "target": 34962 }, - "bufferView_index": { - "buffer": "buffer_box", + { + "buffer": 0, "byteLength": 72, "byteOffset": 96, "target": 34963 } - }, - "images": {}, - "materials": { - "material_czmDefaultMat": { + ], + "images": [], + "materials": [ + { "name": "czmDefaultMat", "values": { "ambient": [ @@ -86,27 +88,27 @@ 0, 1 ], - "shininess": 0 + "shininess": [0] } } - }, - "meshes": { - "mesh_box": { + ], + "meshes": [ + { "name": "box", "primitives": [ { "attributes": { - "POSITION": "accessor_position" + "POSITION": 1 }, - "indices": "accessor_index_0", - "material": "material_czmDefaultMat", + "indices": 0, + "material": 0, "mode": 4 } ] } - }, - "nodes": { - "node_box": { + ], + "nodes": [ + { "children": [], "matrix": [ 1, @@ -126,22 +128,20 @@ 0, 1 ], - "meshes": [ - "mesh_box" - ], + "mesh": 0, "name": "box" } - }, - "samplers": { - "sampler_0": {} - }, - "scene": "scene_box", - "scenes": { - "scene_box": { + ], + "samplers": [ + {} + ], + "scene": 0, + "scenes": [ + { "nodes": [ - "node_box" + 0 ] } - }, - "textures": {} + ], + "textures": [] } diff --git a/specs/data/generateNormals/box_normals.gltf b/specs/data/generateNormals/box_normals.gltf index 52ffe1d4..c995de7c 100644 --- a/specs/data/generateNormals/box_normals.gltf +++ b/specs/data/generateNormals/box_normals.gltf @@ -1,7 +1,7 @@ { - "accessors": { - "accessor_index_0": { - "bufferView": "bufferView_1", + "accessors": [ + { + "bufferView": 1, "byteOffset": 0, "byteStride": 0, "componentType": 5123, @@ -12,10 +12,11 @@ ], "max": [ 23 - ] + ], + "name": "accessor_index_0" }, - "accessor_position": { - "bufferView": "bufferView_0", + { + "bufferView": 0, "byteOffset": 0, "byteStride": 0, "componentType": 5126, @@ -30,10 +31,11 @@ 1, 1 ], - "type": "VEC3" + "type": "VEC3", + "name": "accessor_position" }, - "accessor_normal": { - "bufferView": "bufferView_0", + { + "bufferView": 0, "byteOffset": 288, "byteStride": 0, "componentType": 5126, @@ -48,9 +50,10 @@ 1, 1, 1 - ] + ], + "name": "accessor_normal" } - }, + ], "asset": { "generator": "OBJ2GLTF", "premultipliedAlpha": true, @@ -60,30 +63,30 @@ }, "version": "1.0" }, - "buffers": { - "buffer_0": { + "buffers": [ + { "type": "arraybuffer", "byteLength": 648, "uri": "data:application/octet-stream;base64,AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIA/AACAvwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcA" } - }, - "bufferViews": { - "bufferView_0": { - "buffer": "buffer_0", + ], + "bufferViews": [ + { + "buffer": 0, "byteLength": 576, "byteOffset": 0, "target": 34962 }, - "bufferView_1": { - "buffer": "buffer_0", + { + "buffer": 0, "byteLength": 72, "byteOffset": 576, "target": 34963 } - }, - "images": {}, - "materials": { - "material_czmDefaultMat": { + ], + "images": [], + "materials": [ + { "name": "czmDefaultMat", "extensions": {}, "values": { @@ -111,34 +114,32 @@ 0, 1 ], - "shininess": 0, - "transparency": 1 + "shininess": [0], + "transparency": [1] }, - "technique": "technique0" + "technique": 0 } - }, - "meshes": { - "mesh_box_normals": { + ], + "meshes": [ + { "name": "box_normals", "primitives": [ { "attributes": { - "POSITION": "accessor_position", - "NORMAL": "accessor_normal" + "POSITION": 1, + "NORMAL": 2 }, - "indices": "accessor_index_0", - "material": "material_czmDefaultMat", + "indices": 0, + "material": 0, "mode": 4 } ] } - }, - "nodes": { - "rootNode": { + ], + "nodes": [ + { "children": [], - "meshes": [ - "mesh_box_normals" - ], + "mesh": 0, "matrix": [ 1, 0, @@ -158,22 +159,22 @@ 1 ] } - }, - "samplers": {}, - "scene": "scene_box_normals", - "scenes": { - "scene_box_normals": { + ], + "samplers": [], + "scene": 0, + "scenes": [ + { "nodes": [ - "rootNode" + 0 ] } - }, - "textures": {}, + ], + "textures": [], "extensionsUsed": [], - "animations": {}, - "cameras": {}, - "techniques": { - "technique0": { + "animations": [], + "cameras": [], + "techniques": [ + { "attributes": { "a_position": "position", "a_normal": "normal" @@ -218,7 +219,7 @@ "type": 35665 } }, - "program": "program0", + "program": 0, "states": { "enable": [ 2884, @@ -237,27 +238,26 @@ "u_transparency": "transparency" } } - }, - "programs": { - "program0": { + ], + "programs": [ + { "attributes": [ "a_position", "a_normal" ], - "fragmentShader": "fragmentShader0", - "vertexShader": "vertexShader0" + "fragmentShader": 0, + "vertexShader": 1 } - }, - "shaders": { - "vertexShader0": { + ], + "shaders": [ + { "type": 35633, "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Owp1bmlmb3JtIG1hdDQgdV9tb2RlbFZpZXdNYXRyaXg7CnVuaWZvcm0gbWF0NCB1X3Byb2plY3Rpb25NYXRyaXg7CnVuaWZvcm0gbWF0MyB1X25vcm1hbE1hdHJpeDsKYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsKdmFyeWluZyB2ZWMzIHZfcG9zaXRpb25FQzsKYXR0cmlidXRlIHZlYzMgYV9ub3JtYWw7CnZhcnlpbmcgdmVjMyB2X25vcm1hbDsKdm9pZCBtYWluKHZvaWQpIHsKICB2ZWM0IHBvcyA9IHVfbW9kZWxWaWV3TWF0cml4ICogdmVjNChhX3Bvc2l0aW9uLDEuMCk7CiAgdl9wb3NpdGlvbkVDID0gcG9zLnh5ejsKICBnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHBvczsKICB2X25vcm1hbCA9IHVfbm9ybWFsTWF0cml4ICogYV9ub3JtYWw7Cn0K" }, - "fragmentShader0": { + { "type": 35632, "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Owp1bmlmb3JtIHZlYzQgdV9hbWJpZW50Owp1bmlmb3JtIHZlYzQgdV9kaWZmdXNlOwp1bmlmb3JtIHZlYzQgdV9lbWlzc2lvbjsKdW5pZm9ybSB2ZWM0IHVfc3BlY3VsYXI7CnVuaWZvcm0gZmxvYXQgdV9zaGluaW5lc3M7CnVuaWZvcm0gZmxvYXQgdV90cmFuc3BhcmVuY3k7CnZhcnlpbmcgdmVjMyB2X3Bvc2l0aW9uRUM7CnZhcnlpbmcgdmVjMyB2X25vcm1hbDsKdm9pZCBtYWluKHZvaWQpIHsKICB2ZWMzIG5vcm1hbCA9IG5vcm1hbGl6ZSh2X25vcm1hbCk7CiAgdmVjNCBkaWZmdXNlID0gdV9kaWZmdXNlOwogIHZlYzMgZGlmZnVzZUxpZ2h0ID0gdmVjMygwLjAsIDAuMCwgMC4wKTsKICB2ZWMzIHNwZWN1bGFyID0gdV9zcGVjdWxhci5yZ2I7CiAgdmVjMyBzcGVjdWxhckxpZ2h0ID0gdmVjMygwLjAsIDAuMCwgMC4wKTsKICB2ZWMzIGVtaXNzaW9uID0gdV9lbWlzc2lvbi5yZ2I7CiAgdmVjMyBhbWJpZW50ID0gdV9hbWJpZW50LnJnYjsKICB2ZWMzIHZpZXdEaXIgPSAtbm9ybWFsaXplKHZfcG9zaXRpb25FQyk7CiAgdmVjMyBhbWJpZW50TGlnaHQgPSB2ZWMzKDAuMCwgMC4wLCAwLjApOwogIGFtYmllbnRMaWdodCArPSB2ZWMzKDAuMiwgMC4yLCAwLjIpOwogIHZlYzMgbCA9IHZlYzMoMC4wLCAwLjAsIDEuMCk7CiAgZGlmZnVzZUxpZ2h0ICs9IHZlYzMoMS4wLCAxLjAsIDEuMCkgKiBtYXgoZG90KG5vcm1hbCxsKSwgMC4pOwogIHZlYzMgaCA9IG5vcm1hbGl6ZShsICsgdmlld0Rpcik7CiAgZmxvYXQgc3BlY3VsYXJJbnRlbnNpdHkgPSBtYXgoMC4sIHBvdyhtYXgoZG90KG5vcm1hbCwgaCksIDAuKSwgdV9zaGluaW5lc3MpKTsKICBzcGVjdWxhckxpZ2h0ICs9IHZlYzMoMS4wLCAxLjAsIDEuMCkgKiBzcGVjdWxhckludGVuc2l0eTsKICB2ZWMzIGNvbG9yID0gdmVjMygwLjAsIDAuMCwgMC4wKTsKICBjb2xvciArPSBkaWZmdXNlLnJnYiAqIGRpZmZ1c2VMaWdodDsKICBjb2xvciArPSBzcGVjdWxhciAqIHNwZWN1bGFyTGlnaHQ7CiAgY29sb3IgKz0gZW1pc3Npb247CiAgY29sb3IgKz0gYW1iaWVudCAqIGFtYmllbnRMaWdodDsKICBnbF9GcmFnQ29sb3IgPSB2ZWM0KGNvbG9yICogZGlmZnVzZS5hLCBkaWZmdXNlLmEgKiB1X3RyYW5zcGFyZW5jeSk7Cn0K" } - }, - "skins": {}, - "extensions": {} + ], + "skins": [] } diff --git a/specs/lib/RemoveUnusedPropertiesSpec.js b/specs/lib/RemoveUnusedPropertiesSpec.js index 90a100c6..10684322 100644 --- a/specs/lib/RemoveUnusedPropertiesSpec.js +++ b/specs/lib/RemoveUnusedPropertiesSpec.js @@ -1032,41 +1032,20 @@ describe('RemoveUnusedProperties', function() { var gltf = JSON.parse(data); removeAll(gltf); - expect(gltf.accessors.accessor_23).not.toBeDefined(); - expect(gltf.accessors.animAccessor_0).not.toBeDefined(); - expect(gltf.accessors['IBM_Armature_Cylinder-skin']).not.toBeDefined(); - expect(gltf.bufferViews.bufferView_30).not.toBeDefined(); - expect(gltf.buffers.CesiumTexturedBoxTest).not.toBeDefined(); - expect(gltf.cameras.camera_0).not.toBeDefined(); - expect(gltf.images.Image0001).not.toBeDefined(); - expect(gltf.materials['Effect-Texture']).not.toBeDefined(); - expect(gltf.meshes['Geometry-mesh002']).not.toBeDefined(); - expect(gltf.nodes['Geometry-mesh002Node']).not.toBeDefined(); - expect(gltf.nodes.groupLocator030Node).not.toBeDefined(); - expect(gltf.nodes.node_3).not.toBeDefined(); - expect(gltf.nodes.txtrLocator026Node).not.toBeDefined(); - expect(gltf.programs.program_0).not.toBeDefined(); - expect(gltf.samplers.sampler_0).not.toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0FS).not.toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0VS).not.toBeDefined(); - expect(gltf.skins['Armature_Cylinder-skin']).not.toBeDefined(); - expect(gltf.techniques.technique0).not.toBeDefined(); - expect(gltf.textures.texture_Image0001).not.toBeDefined(); - - expect(Object.keys(gltf.nodes).length).toEqual(0); - expect(Object.keys(gltf.skins).length).toEqual(0); - expect(Object.keys(gltf.cameras).length).toEqual(0); - expect(Object.keys(gltf.meshes).length).toEqual(0); - expect(Object.keys(gltf.accessors).length).toEqual(0); - expect(Object.keys(gltf.materials).length).toEqual(0); - expect(Object.keys(gltf.bufferViews).length).toEqual(0); - expect(Object.keys(gltf.techniques).length).toEqual(0); - expect(Object.keys(gltf.textures).length).toEqual(0); - expect(Object.keys(gltf.buffers).length).toEqual(0); - expect(Object.keys(gltf.programs).length).toEqual(0); - expect(Object.keys(gltf.images).length).toEqual(0); - expect(Object.keys(gltf.samplers).length).toEqual(0); - expect(Object.keys(gltf.shaders).length).toEqual(0); + expect(gltf.nodes.length).toEqual(0); + expect(gltf.skins.length).toEqual(0); + expect(gltf.cameras.length).toEqual(0); + expect(gltf.meshes.length).toEqual(0); + expect(gltf.accessors.length).toEqual(0); + expect(gltf.materials.length).toEqual(0); + expect(gltf.bufferViews.length).toEqual(0); + expect(gltf.techniques.length).toEqual(0); + expect(gltf.textures.length).toEqual(0); + expect(gltf.buffers.length).toEqual(0); + expect(gltf.programs.length).toEqual(0); + expect(gltf.images.length).toEqual(0); + expect(gltf.samplers.length).toEqual(0); + expect(gltf.shaders.length).toEqual(0); }), done).toResolve(); }); @@ -1074,49 +1053,28 @@ describe('RemoveUnusedProperties', function() { expect(fsReadFile(gltfPath) .then(function (data) { var gltf = JSON.parse(data); - gltf.scenes.defaultScene.nodes[0] = 'node_3'; - gltf.animations.animation_0.samplers = { - sampler : { - input : 'animAccessor_0' + gltf.scenes[0].nodes.push(2); + gltf.animations[0].samplers = [ + { + input : 1 } - }; + ]; removeAll(gltf); - expect(gltf.accessors.accessor_23).toBeDefined(); - expect(gltf.accessors.animAccessor_0).toBeDefined(); - expect(gltf.accessors['IBM_Armature_Cylinder-skin']).toBeDefined(); - expect(gltf.bufferViews.bufferView_30).toBeDefined(); - expect(gltf.buffers.CesiumTexturedBoxTest).toBeDefined(); - expect(gltf.cameras.camera_0).toBeDefined(); - expect(gltf.images.Image0001).toBeDefined(); - expect(gltf.materials['Effect-Texture']).toBeDefined(); - expect(gltf.meshes['Geometry-mesh002']).toBeDefined(); - expect(gltf.nodes['Geometry-mesh002Node']).toBeDefined(); - expect(gltf.nodes.groupLocator030Node).toBeDefined(); - expect(gltf.nodes.node_3).toBeDefined(); - expect(gltf.nodes.txtrLocator026Node).toBeDefined(); - expect(gltf.programs.program_0).toBeDefined(); - expect(gltf.samplers.sampler_0).toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0FS).toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0VS).toBeDefined(); - expect(gltf.skins['Armature_Cylinder-skin']).toBeDefined(); - expect(gltf.techniques.technique0).toBeDefined(); - expect(gltf.textures.texture_Image0001).toBeDefined(); - - expect(Object.keys(gltf.nodes).length).toEqual(4); - expect(Object.keys(gltf.skins).length).toEqual(1); - expect(Object.keys(gltf.cameras).length).toEqual(1); - expect(Object.keys(gltf.meshes).length).toEqual(1); - expect(Object.keys(gltf.accessors).length).toEqual(3); - expect(Object.keys(gltf.materials).length).toEqual(1); - expect(Object.keys(gltf.bufferViews).length).toEqual(1); - expect(Object.keys(gltf.techniques).length).toEqual(1); - expect(Object.keys(gltf.textures).length).toEqual(1); - expect(Object.keys(gltf.buffers).length).toEqual(1); - expect(Object.keys(gltf.programs).length).toEqual(1); - expect(Object.keys(gltf.images).length).toEqual(1); - expect(Object.keys(gltf.samplers).length).toEqual(1); - expect(Object.keys(gltf.shaders).length).toEqual(2); + expect(gltf.nodes.length).toEqual(4); + expect(gltf.skins.length).toEqual(1); + expect(gltf.cameras.length).toEqual(1); + expect(gltf.meshes.length).toEqual(1); + expect(gltf.accessors.length).toEqual(3); + expect(gltf.materials.length).toEqual(1); + expect(gltf.bufferViews.length).toEqual(1); + expect(gltf.techniques.length).toEqual(1); + expect(gltf.textures.length).toEqual(1); + expect(gltf.buffers.length).toEqual(1); + expect(gltf.programs.length).toEqual(1); + expect(gltf.images.length).toEqual(1); + expect(gltf.samplers.length).toEqual(1); + expect(gltf.shaders.length).toEqual(2); }), done).toResolve(); }); }); diff --git a/specs/lib/combinePrimitivesSpec.js b/specs/lib/combinePrimitivesSpec.js index ff014d79..3d7441ba 100644 --- a/specs/lib/combinePrimitivesSpec.js +++ b/specs/lib/combinePrimitivesSpec.js @@ -19,33 +19,35 @@ describe('combinePrimitives', function() { it('combines two primitives without indices by concatenating them', function() { var buffer = Buffer.concat([bufferOneA, bufferTwoA]); var gltf = { - accessors : { - accessorOneA : { - bufferView : 'bufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayOneA.length, - type : 'SCALAR' + type : 'SCALAR', + name: 'oneA' }, - accessorTwoA : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length, byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayTwoA.length, - type : 'SCALAR' + type : 'SCALAR', + name: 'oneB' } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : buffer.length, byteOffset : 0 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : buffer.length, extras : { _pipeline : { @@ -53,30 +55,30 @@ describe('combinePrimitives', function() { } } } - }, - meshes : { - mesh : { - primitives : [{ - attributes : { - A : 'accessorOneA' - }, - extras : { - _pipeline : {} - } - }, { - attributes : { - A : 'accessorTwoA' - }, - extras : { - _pipeline : {} - } - }] + ], + meshes : [ + { + primitives: [{ + attributes: { + A: 0 + }, + extras: { + _pipeline: {} + } + }, { + attributes: { + A: 1 + }, + extras: { + _pipeline: {} + } + }] } - } + ] }; combinePrimitives(gltf); var accessors = gltf.accessors; - var primitives = gltf.meshes.mesh.primitives; + var primitives = gltf.meshes[0].primitives; expect(primitives.length).toEqual(1); var primitive = primitives[0]; expect(primitive.indices).toBeDefined(); @@ -95,49 +97,52 @@ describe('combinePrimitives', function() { var bufferIndicesTwo = new Buffer(indicesTwo.buffer); var buffer = Buffer.concat([bufferOneA, bufferTwoA, bufferIndicesOne, bufferIndicesTwo]); var gltf = { - accessors : { - accessorOneA : { - bufferView : 'bufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayOneA.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'oneA' }, - accessorTwoA : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length, byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayTwoA.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'twoA' }, - indicesOne : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length + bufferTwoA.length, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesOne.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'indicesOne' }, - indicesTwo : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length + bufferTwoA.length + bufferIndicesOne.length, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesOne.length, type : 'SCALAR' } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : buffer.length, byteOffset : 0 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : buffer.length, extras : { _pipeline : { @@ -145,32 +150,32 @@ describe('combinePrimitives', function() { } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [{ attributes : { - A : 'accessorOneA' + A : 0 }, - indices : 'indicesOne', + indices : 2, extras : { _pipeline : {} } }, { attributes : { - A : 'accessorTwoA' + A : 1 }, - indices : 'indicesTwo', + indices : 3, extras : { _pipeline : {} } }] } - } + ] }; combinePrimitives(gltf); var accessors = gltf.accessors; - var primitives = gltf.meshes.mesh.primitives; + var primitives = gltf.meshes[0].primitives; expect(primitives.length).toEqual(1); var primitive = primitives[0]; var indices = []; @@ -188,41 +193,44 @@ describe('combinePrimitives', function() { var bufferIndicesTwo = new Buffer(indicesTwo.buffer); var buffer = Buffer.concat([bufferOneA, bufferIndicesOne, bufferIndicesTwo]); var gltf = { - accessors : { - accessorOneA : { - bufferView : 'bufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayOneA.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'oneA' }, - indicesOne : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesOne.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'indicesOne' }, - indicesTwo : { - bufferView : 'bufferView', - byteOffset : bufferOneA.length + bufferIndicesOne.length, - byteStride : 0, - componentType : WebGLConstants.UNSIGNED_SHORT, - count : indicesOne.length, - type : 'SCALAR' + { + bufferView: 0, + byteOffset: bufferOneA.length + bufferIndicesOne.length, + byteStride: 0, + componentType: WebGLConstants.UNSIGNED_SHORT, + count: indicesOne.length, + type: 'SCALAR', + name: 'indicesTwo' } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : buffer.length, byteOffset : 0 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : buffer.length, extras : { _pipeline : { @@ -230,32 +238,32 @@ describe('combinePrimitives', function() { } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [{ attributes : { - A : 'accessorOneA' + A : 0 }, - indices : 'indicesOne', + indices : 1, extras : { _pipeline : {} } }, { attributes : { - A : 'accessorOneA' + A : 0 }, - indices : 'indicesTwo', + indices : 2, extras : { _pipeline : {} } }] } - } + ] }; combinePrimitives(gltf); var accessors = gltf.accessors; - var primitives = gltf.meshes.mesh.primitives; + var primitives = gltf.meshes[0].primitives; expect(primitives.length).toEqual(1); var primitive = primitives[0]; var indices = []; @@ -275,57 +283,62 @@ describe('combinePrimitives', function() { var bufferIndicesThree = new Buffer(indicesThree.buffer); var buffer = Buffer.concat([bufferOneA, bufferTwoB, bufferIndicesOne, bufferIndicesTwo, bufferIndicesThree]); var gltf = { - accessors : { - accessorOneA : { - bufferView : 'bufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayOneA.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'oneA' }, - accessorTwoB : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length, byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayTwoB.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'twoB' }, - indicesOne : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length + bufferTwoB.length, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesOne.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'indicesOne' }, - indicesTwo : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length + bufferTwoB.length + bufferIndicesOne.length, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesTwo.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'indicesTwo' }, - indicesThree : { - bufferView : 'bufferView', + { + bufferView : 0, byteOffset : bufferOneA.length + bufferTwoB.length + bufferIndicesOne.length + bufferIndicesTwo.length, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesThree.length, - type : 'SCALAR' + type : 'SCALAR', + name : 'indicesThree' } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : buffer.length, byteOffset : 0 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : buffer.length, extras : { _pipeline : { @@ -333,40 +346,40 @@ describe('combinePrimitives', function() { } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [{ attributes : { - A : 'accessorOneA' + A : 0 }, - indices : 'indicesOne', + indices : 2, extras : { _pipeline : {} } }, { attributes : { - A : 'accessorOneA' + A : 0 }, - indices : 'indicesTwo', + indices : 3, extras : { _pipeline : {} } }, { attributes : { - A : 'accessorTwoB' + A : 1 }, - indices : 'indicesThree', + indices : 4, extras : { _pipeline : {} } }] } - } + ] }; combinePrimitives(gltf); var accessors = gltf.accessors; - var primitives = gltf.meshes.mesh.primitives; + var primitives = gltf.meshes[0].primitives; expect(primitives.length).toEqual(1); var primitive = primitives[0]; var indices = []; @@ -379,134 +392,141 @@ describe('combinePrimitives', function() { it('doesn\'t combine primitive that has attribute accessors that are different sizes', function() { var gltf = { - accessors: { - accessorOneA: { + accessors: [ + { componentType: WebGLConstants.FLOAT, count: arrayOneA.length, - type: 'SCALAR' + type: 'SCALAR', + name: 'oneA' }, - accessorOneB: { + { componentType: WebGLConstants.FLOAT, count: arrayOneB.length, - type: 'SCALAR' + type: 'SCALAR', + name: 'oneB' }, - accessorTwoA: { + { componentType: WebGLConstants.UNSIGNED_SHORT, count: arrayTwoA.length, - type: 'SCALAR' + type: 'SCALAR', + name: 'twoA' }, - accessorTwoB: { + { componentType: WebGLConstants.UNSIGNED_SHORT, count: arrayTwoB.length, - type: 'SCALAR' + type: 'SCALAR', + name: 'twoB' } - }, - meshes: { - mesh: { + ], + meshes: [ + { primitives: [{ attributes: { - A: 'accessorOneA', - B: 'accessorOneB' + A: 0, + B: 1 }, extras: { _pipeline: {} } }, { attributes: { - A: 'accessorTwoA', - B: 'accessorTwoB' + A: 2, + B: 3 }, extras: { _pipeline: {} } }] } - } + ] }; var originalGltf = clone(gltf); combinePrimitives(gltf); - delete gltf.meshes.mesh.primitives[0].extras._pipeline.conflicts; - delete gltf.meshes.mesh.primitives[1].extras._pipeline.conflicts; + delete gltf.meshes[0].primitives[0].extras._pipeline.conflicts; + delete gltf.meshes[0].primitives[1].extras._pipeline.conflicts; expect(gltf).toEqual(originalGltf); }); it('doesn\'t combine primitives that share only a single attribute accessor', function() { var gltf = { - accessors: { - accessorOneA: { + accessors: [ + { componentType: WebGLConstants.FLOAT, count: arrayOneA.length, - type: 'SCALAR' + type: 'SCALAR', + name: 'oneA' }, - accessorOneB: { + { componentType: WebGLConstants.FLOAT, count: arrayOneB.length, - type: 'SCALAR' + type: 'SCALAR', + name: 'oneB' }, - accessorTwoB: { + { componentType: WebGLConstants.UNSIGNED_SHORT, count: arrayTwoB.length, - type: 'SCALAR' + type: 'SCALAR', + name: 'twoB' } - }, - meshes: { - mesh: { + ], + meshes: [ + { primitives: [{ attributes: { - A: 'accessorOneA', - B: 'accessorTwoB' + A: 0, + B: 2 }, extras: { _pipeline: {} } }, { attributes: { - A: 'accessorOneA', - B: 'accessorOneB' + A: 0, + B: 1 }, extras: { _pipeline: {} } }] } - } + ] }; var originalGltf = clone(gltf); combinePrimitives(gltf); - delete gltf.meshes.mesh.primitives[0].extras._pipeline.conflicts; - delete gltf.meshes.mesh.primitives[1].extras._pipeline.conflicts; + delete gltf.meshes[0].primitives[0].extras._pipeline.conflicts; + delete gltf.meshes[0].primitives[1].extras._pipeline.conflicts; expect(gltf).toEqual(originalGltf); }); it('doesn\'t combine primitives with different materials', function() { var gltf = { - meshes : { - mesh: { + meshes : [ + { primitives: [{ - material: 'materialOne', + material: 0, extras: { _pipeline: {} } }, { - material: 'materialTwo', + material: 1, extras: { _pipeline: {} } }] } - } + ] }; var originalGltf = clone(gltf); combinePrimitives(gltf); - delete gltf.meshes.mesh.primitives[0].extras._pipeline.conflicts; - delete gltf.meshes.mesh.primitives[1].extras._pipeline.conflicts; + delete gltf.meshes[0].primitives[0].extras._pipeline.conflicts; + delete gltf.meshes[0].primitives[1].extras._pipeline.conflicts; expect(gltf).toEqual(originalGltf); }); it('doesn\'t combine primitives with different modes', function() { var gltf = { - meshes : { - mesh: { + meshes : [ + { primitives: [{ mode: 0, extras: { @@ -519,12 +539,12 @@ describe('combinePrimitives', function() { } }] } - } + ] }; var originalGltf = clone(gltf); combinePrimitives(gltf); - delete gltf.meshes.mesh.primitives[0].extras._pipeline.conflicts; - delete gltf.meshes.mesh.primitives[1].extras._pipeline.conflicts; + delete gltf.meshes[0].primitives[0].extras._pipeline.conflicts; + delete gltf.meshes[0].primitives[1].extras._pipeline.conflicts; expect(gltf).toEqual(originalGltf); }); @@ -537,7 +557,7 @@ describe('combinePrimitives', function() { } var quarterOverflowBuffer = new Buffer(quarterOverflow.buffer); var quarterOverflowAccessor = { - bufferView : 'bufferView', + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, @@ -546,30 +566,30 @@ describe('combinePrimitives', function() { }; var gltf = { - accessors : { - dataA : quarterOverflowAccessor, - dataB : quarterOverflowAccessor, - dataC : quarterOverflowAccessor, - dataD : quarterOverflowAccessor, - dataE : quarterOverflowAccessor, - dataF : { - bufferView : 'bufferView', + accessors : [ + quarterOverflowAccessor, + quarterOverflowAccessor, + quarterOverflowAccessor, + quarterOverflowAccessor, + quarterOverflowAccessor, + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : smallerValueCount, type : 'SCALAR' } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : quarterOverflowBuffer.length, byteOffset : 0 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : quarterOverflowBuffer.length, extras : { _pipeline : { @@ -577,64 +597,64 @@ describe('combinePrimitives', function() { } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [{ attributes : { - A : 'dataA' + A : 0 }, - indices : 'dataA', + indices : 0, extras : { _pipeline : {} } }, { attributes : { - A : 'dataB' + A : 1 }, - indices : 'dataB', + indices : 1, extras : { _pipeline : {} } }, { attributes : { - A : 'dataC' + A : 2 }, - indices : 'dataC', + indices : 2, extras : { _pipeline : {} } }, { attributes : { - A : 'dataD' + A : 3 }, - indices : 'dataD', + indices : 3, extras : { _pipeline : {} } }, { attributes : { - A : 'dataE' + A : 4 }, - indices : 'dataE', + indices : 4, extras : { _pipeline : {} } }, { attributes : { - A : 'dataF' + A : 5 }, - indices : 'dataF', + indices : 5, extras : { _pipeline : {} } }] } - } + ] }; combinePrimitives(gltf); - var newPrimitives = gltf.meshes.mesh.primitives; + var newPrimitives = gltf.meshes[0].primitives; expect(newPrimitives.length).toEqual(2); var primitive0 = newPrimitives[0]; diff --git a/specs/lib/encodeImagesSpec.js b/specs/lib/encodeImagesSpec.js index 718865b2..c7cb70a8 100644 --- a/specs/lib/encodeImagesSpec.js +++ b/specs/lib/encodeImagesSpec.js @@ -19,16 +19,16 @@ describe('encodeImages', function() { }; var gltf = { - "images": { - "Image0001": { - "uri": imageUri + images: [ + { + uri: imageUri }, - "Image0002": { - "uri": imageUri + { + uri: imageUri } - }, - "extras": { - "_pipeline": {} + ], + extras: { + _pipeline: {} } }; @@ -38,8 +38,8 @@ describe('encodeImages', function() { addPipelineExtras(gltf); loadGltfUris(gltfClone, options) .then(function() { - var pipelineExtras0001 = gltfClone.images.Image0001.extras._pipeline; - var pipelineExtras0002 = gltfClone.images.Image0002.extras._pipeline; + var pipelineExtras0001 = gltfClone.images[0].extras._pipeline; + var pipelineExtras0002 = gltfClone.images[1].extras._pipeline; encodeImages(gltfClone) .then(function() { @@ -56,12 +56,12 @@ describe('encodeImages', function() { addPipelineExtras(gltf); loadGltfUris(gltfClone, options) .then(function() { - var pipelineExtras0001 = gltfClone.images.Image0001.extras._pipeline; + var pipelineExtras0001 = gltfClone.images[0].extras._pipeline; var jimpImage001 = pipelineExtras0001.jimpImage; jimpImage001.resize(10, 10, Jimp.RESIZE_BEZIER); pipelineExtras0001.imageChanged = true; - var pipelineExtras0002 = gltfClone.images.Image0002.extras._pipeline; + var pipelineExtras0002 = gltfClone.images[1].extras._pipeline; var jimpImage002 = pipelineExtras0002.jimpImage; pipelineExtras0002.imageChanged = true; diff --git a/specs/lib/generateNormalsSpec.js b/specs/lib/generateNormalsSpec.js index a219d12b..efc31a79 100644 --- a/specs/lib/generateNormalsSpec.js +++ b/specs/lib/generateNormalsSpec.js @@ -31,8 +31,8 @@ describe('generateNormals', function(){ var byteLengthBefore = 168; generateNormals(gltf); - var attributes = gltf.meshes.mesh_box.primitives[0].attributes; - var byteLengthAfter = gltf.buffers[Object.keys(gltf.buffers)[0]].byteLength; + var attributes = gltf.meshes[0].primitives[0].attributes; + var byteLengthAfter = gltf.buffers[0].byteLength; expect(attributes.NORMAL).toBeDefined(); expect(gltf.accessors[attributes.NORMAL]).toBeDefined(); expect(byteLengthAfter).toBe(byteLengthBefore + 8 * 3 * 4); // 8 normals are generated @@ -52,12 +52,10 @@ describe('generateNormals', function(){ faceNormals : true }); - var attributes = gltf.meshes.mesh_box.primitives[0].attributes; - var byteLengthAfter = gltf.buffers[Object.keys(gltf.buffers)[0]].byteLength; + var attributes = gltf.meshes[0].primitives[0].attributes; + var byteLengthAfter = gltf.buffers[0].byteLength; expect(attributes.NORMAL).toBeDefined(); expect(gltf.accessors[attributes.NORMAL]).toBeDefined(); expect(byteLengthAfter).toBe(byteLengthBefore + 8 * 3 * 4); // 8 normals are generated }); - - }); diff --git a/specs/lib/getBinaryGltfSpec.js b/specs/lib/getBinaryGltfSpec.js index 699c7f5f..49fac782 100644 --- a/specs/lib/getBinaryGltfSpec.js +++ b/specs/lib/getBinaryGltfSpec.js @@ -1,120 +1,128 @@ 'use strict'; -var bufferEqual = require('buffer-equal'); -var clone = require('clone'); -var fs = require('fs'); -var Promise = require('bluebird'); - +var addPipelineExtras = require('../../lib/addPipelineExtras'); var getBinaryGltf = require('../../lib/getBinaryGltf'); -var readGltf = require('../../lib/readGltf'); - -var fsReadFile = Promise.promisify(fs.readFile); - -var gltfPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryInput.gltf'; -var scenePath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest_BinaryCheck.gltf'; -var bufferPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.bin'; -var imagePath = './specs/data/boxTexturedUnoptimized/Cesium_Logo_Flat_Binary.png'; -var fragmentShaderPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest0FS_Binary.glsl'; -var vertexShaderPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest0VS_Binary.glsl'; +var parseBinaryGltf = require('../../lib/parseBinaryGltf'); describe('getBinaryGltf', function() { - var testData = { - gltf: gltfPath, - scene: scenePath, - image: imagePath, - buffer: bufferPath, - fragmentShader: fragmentShaderPath, - vertexShader: vertexShaderPath - }; - - beforeAll(function(done) { - expect(readGltf(gltfPath) - .then(function(gltf) { - testData.gltf = gltf; - return fsReadFile(scenePath); - }) - .then(function(data) { - testData.scene = JSON.parse(data); - - var readFiles = [ - fsReadFile(testData.image), - fsReadFile(testData.buffer), - fsReadFile(testData.fragmentShader), - fsReadFile(testData.vertexShader) - ]; - return Promise.all(readFiles); - }) - .then(function(results) { - testData.image = results[0]; - testData.buffer = results[1]; - testData.fragmentShader = results[2]; - testData.vertexShader = results[3]; - }), done).toResolve(); + it('writes a binary glTF with embedded resources', function () { + var shaderText = "testing shader"; + var imageText = "testing image"; + var gltf = { + images: [{ + extras: { + _pipeline: { + source: Buffer.from(imageText), + extension: '.png' + } + } + }], + shaders: [{ + extras: { + _pipeline: { + source: Buffer.from(shaderText) + } + } + }] + }; + var glb = getBinaryGltf(gltf); + var parsedGltf = parseBinaryGltf(glb); + var buffer = parsedGltf.buffers[0]; + var source = buffer.extras._pipeline.source; + var shader = parsedGltf.shaders[0]; + var image = parsedGltf.images[0]; + var shaderBufferView = parsedGltf.bufferViews[shader.bufferView]; + var imageBufferView = parsedGltf.bufferViews[image.bufferView]; + var testShaderText = source.slice(shaderBufferView.byteOffset, shaderBufferView.byteOffset + shaderBufferView.byteLength).toString(); + var testImageText = source.slice(imageBufferView.byteOffset, imageBufferView.byteOffset + imageBufferView.byteLength).toString(); + expect(testShaderText).toEqual(shaderText); + expect(testImageText).toEqual(imageText); + expect(image.mimeType).toEqual('image/png'); }); - it('writes a valid binary gltf header with embedded resources', function () { - var gltf = clone(testData.gltf); - var glbData = getBinaryGltf(gltf, true, true); - var header = glbData.header; - - expect(header.toString('utf8', 0, 4)).toEqual('glTF'); - expect(header.readUInt32LE(4)).toEqual(1); - expect(header.readUInt32LE(8)).toEqual(17782); - expect(header.readUInt32LE(12)).toEqual(3972); - expect(header.readUInt32LE(16)).toEqual(0); + it('writes a binary glTF with embedded shaders and separate images', function() { + var shaderText = "testing shader"; + var imageText = "testing image"; + var gltf = { + images: [{ + uri: shaderText + }], + shaders: [{ + extras: { + _pipeline: { + source: Buffer.from(shaderText) + } + } + }] + }; + var glb = getBinaryGltf(gltf, { + embedImage: false + }); + var parsedGltf = parseBinaryGltf(glb); + var buffer = parsedGltf.buffers[0]; + var source = buffer.extras._pipeline.source; + var shader = parsedGltf.shaders[0]; + var shaderBufferView = parsedGltf.bufferViews[shader.bufferView]; + var image = parsedGltf.images[0]; + expect(image.bufferView).not.toBeDefined(); + var testShaderText = source.slice(shaderBufferView.byteOffset, shaderBufferView.byteOffset + shaderBufferView.byteLength).toString(); + expect(testShaderText).toEqual(shaderText); + expect(image.uri).toEqual(shaderText); }); - it('writes a valid binary gltf header with separate resources', function () { - var gltf = clone(testData.gltf); - var glbData = getBinaryGltf(gltf, false, false); - var header = glbData.header; - - expect(header.toString('utf8', 0, 4)).toEqual('glTF'); - expect(header.readUInt32LE(4)).toEqual(1); - expect(header.readUInt32LE(8)).toEqual(4412); - expect(header.readUInt32LE(12)).toEqual(3552); - expect(header.readUInt32LE(16)).toEqual(0); + it('writes a binary glTF with separate shaders and embedded images', function() { + var shaderText = "testing shader"; + var imageText = "testing image"; + var gltf = { + images: [{ + extras: { + _pipeline: { + source: Buffer.from(imageText), + extension: '.png' + } + } + }], + shaders: [{ + uri: shaderText + }] + }; + var glb = getBinaryGltf(gltf, { + embed: false + }); + var parsedGltf = parseBinaryGltf(glb); + var buffer = parsedGltf.buffers[0]; + var source = buffer.extras._pipeline.source; + var shader = parsedGltf.shaders[0]; + expect(shader.bufferView).not.toBeDefined(); + var image = parsedGltf.images[0]; + var imageBufferView = parsedGltf.bufferViews[image.bufferView]; + var testImageText = source.slice(imageBufferView.byteOffset, imageBufferView.byteOffset + imageBufferView.byteLength).toString(); + expect(testImageText).toEqual(imageText); + expect(image.mimeType).toEqual('image/png'); + expect(shader.uri).toEqual(shaderText); }); - it('writes the correct binary scene', function () { - var gltf = clone(testData.gltf); - var glbData = getBinaryGltf(gltf, true, true); - var scene = glbData.scene; - expect(JSON.parse(scene.toString())).toEqual(testData.scene); - }); - - it('writes the correct binary body with embedded resources', function () { - var gltf = clone(testData.gltf); - var glbData = getBinaryGltf(gltf, true, true); - var body = glbData.body; - - var binaryBody = Buffer.concat([testData.buffer, testData.fragmentShader, testData.vertexShader, testData.image]); - expect(bufferEqual(binaryBody, body)).toBe(true); - }); - - it('writes the correct binary body with separate images', function () { - var gltf = clone(testData.gltf); - var glbData = getBinaryGltf(gltf, true, false); - var body = glbData.body; - - var binaryBody = Buffer.concat([testData.buffer, testData.fragmentShader, testData.vertexShader]); - expect(bufferEqual(binaryBody, body)).toBe(true); - }); - - it('writes the correct binary body with separate resources except images', function () { - var gltf = clone(testData.gltf); - var glbData = getBinaryGltf(gltf, false, true); - var body = glbData.body; - - var binaryBody = Buffer.concat([testData.buffer, testData.image]); - expect(bufferEqual(binaryBody, body)).toBe(true); - }); - - it('writes the correct binary body with separate resources', function () { - var gltf = clone(testData.gltf); - var glbData = getBinaryGltf(gltf, false, false); - var body = glbData.body; - - var binaryBody = testData.buffer; - expect(bufferEqual(binaryBody, body)).toBe(true); + it('writes a binary glTF with separate shaders and images', function() { + var shaderText = "testing shader"; + var imageText = "testing image"; + var gltf = { + images: [{ + uri: imageText + }], + shaders: [{ + uri: shaderText + }] + }; + var glb = getBinaryGltf(gltf, { + embed: false, + embedImage: false + }); + var parsedGltf = parseBinaryGltf(glb); + expect(parsedGltf.buffers).not.toBeDefined(); + var shader = parsedGltf.shaders[0]; + expect(shader.bufferView).not.toBeDefined(); + expect(shader.uri).toEqual(shaderText); + var image = parsedGltf.images[0]; + expect(image.bufferView).not.toBeDefined(); + expect(image.uri).toEqual(imageText); }); }); diff --git a/specs/lib/getStatisticsSpec.js b/specs/lib/getStatisticsSpec.js index b0464a1b..e83ff5a2 100644 --- a/specs/lib/getStatisticsSpec.js +++ b/specs/lib/getStatisticsSpec.js @@ -1,46 +1,81 @@ 'use strict'; -var fs = require('fs'); -var addDefaults = require('../../lib/addDefaults'); -var addPipelineExtras = require('../../lib/addPipelineExtras'); var getStatistics = require('../../lib/getStatistics'); -var readGltf = require('../../lib/readGltf'); describe('getStatistics', function() { - it('should return stats for simple box test', function(done){ - expect(readGltf('specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf') - .then(function(gltf) { - var stats = getStatistics(gltf); - - expect(stats.buffersSizeInBytes).toEqual(840); - expect(stats.numberOfImages).toEqual(1); - expect(stats.numberOfExternalRequests).toEqual(4); - - expect(stats.numberOfDrawCalls).toEqual(1); - expect(stats.numberOfRenderedPrimitives).toEqual(12); - - expect(stats.numberOfNodes).toEqual(4); - expect(stats.numberOfMeshes).toEqual(1); - expect(stats.numberOfMaterials).toEqual(1); - expect(stats.numberOfAnimations).toEqual(0); - }), done).toResolve(); - }); - - it('works with rigged test', function(done) { - expect(readGltf('specs/data/riggedSimpleUnoptimized/riggedSimple.gltf') - .then(function(gltf) { - var stats = getStatistics(addDefaults(gltf)); - - expect(stats.buffersSizeInBytes).toEqual(10468); - expect(stats.numberOfImages).toEqual(0); - expect(stats.numberOfExternalRequests).toEqual(3); - - expect(stats.numberOfDrawCalls).toEqual(1); - expect(stats.numberOfRenderedPrimitives).toEqual(188); - - expect(stats.numberOfNodes).toEqual(5); - expect(stats.numberOfMeshes).toEqual(1); - expect(stats.numberOfMaterials).toEqual(1); - expect(stats.numberOfAnimations).toEqual(2); - }), done).toResolve(); + it('returns statistics for a gltf', function() { + var gltf = { + accessors: [ + { + count: 1 + }, { + count: 2 + }, { + count: 6 + } + ], + buffers: [ + { + byteLength: 140 + }, { + byteLength: 120, + uri: 'external_buffer' + } + ], + images: [ + { + uri: 'external_image' + }, { + uri: 'data:image/png;' + }, { + uri: 'another_external_image' + } + ], + meshes: [ + { + primitives: [ + { + indices: 0, + mode: 0 // POINTS + }, { + indices: 1, + mode: 1 // LINES + } + ] + }, { + primitives: [ + { + indices: 2, + mode: 4 // TRIANGLES + } + ] + } + ], + materials: [ + {}, {} + ], + animations: [ + {}, {} ,{} + ], + shaders: [ + { + uri: 'external_shader' + }, { + uri: 'data:text/plain;' + } + ], + nodes: [ + {} + ] + }; + var statistics = getStatistics(gltf); + expect(statistics.buffersSizeInBytes).toEqual(260); + expect(statistics.numberOfImages).toEqual(3); + expect(statistics.numberOfExternalRequests).toEqual(4); + expect(statistics.numberOfDrawCalls).toEqual(3); + expect(statistics.numberOfRenderedPrimitives).toEqual(4); + expect(statistics.numberOfNodes).toEqual(1); + expect(statistics.numberOfMeshes).toEqual(2); + expect(statistics.numberOfMaterials).toEqual(2); + expect(statistics.numberOfAnimations).toEqual(3); }); }); diff --git a/specs/lib/mergeBuffersSpec.js b/specs/lib/mergeBuffersSpec.js index 5128f86a..2c2dfff3 100644 --- a/specs/lib/mergeBuffersSpec.js +++ b/specs/lib/mergeBuffersSpec.js @@ -1,6 +1,6 @@ 'use strict'; - var mergeBuffers = require('../../lib/mergeBuffers'); +var removePipelineExtras = require('../../lib/removePipelineExtras'); describe('mergeBuffers', function() { it('merges buffers', function() { @@ -8,72 +8,65 @@ describe('mergeBuffers', function() { var buffer1 = new Buffer([3, 4, 5]); var bufferMerged = new Buffer([1, 2, 3, 4, 5]); var gltf = { - "bufferViews": { - "bufferView_0": { - "buffer": "bufferView_0_buffer", - "byteLength": 2, - "byteOffset": 0 + bufferViews: [ + { + buffer: 0, + byteLength: 2, + byteOffset: 0 }, - "bufferView_1": { - "buffer": "bufferView_1_buffer", - "byteLength": 3, - "byteOffset": 0 + { + buffer: 1, + byteLength: 3, + byteOffset: 0 } - }, - "buffers": { - "bufferView_0_buffer": { - "byteLength": 2, - "type": "arraybuffer", - "uri": "data:,", - "extras": { - "_pipeline": { - "source": buffer0, - "extension": ".bin" + ], + buffers: [ + { + byteLength: 2, + extras: { + _pipeline: { + source: buffer0, + extension: '.bin' } } }, - "bufferView_1_buffer": { - "byteLength": 3, - "type": "arraybuffer", - "uri": "data:,", - "extras": { - "_pipeline": { - "source": buffer1, - "extension": ".bin" + { + byteLength: 3, + extras: { + _pipeline: { + source: buffer1, + extension: '.bin' } } } - } + ] }; - mergeBuffers(gltf, 'mergedBuffers'); + mergeBuffers(gltf); + var buffer = gltf.buffers[0].extras._pipeline.source; + removePipelineExtras(gltf); expect(gltf).toEqual({ - "bufferViews": { - "bufferView_0": { - "buffer": "mergedBuffers", - "byteLength": 2, - "byteOffset": 0 + bufferViews: [ + { + buffer: 0, + byteLength: 2, + byteOffset: 0 }, - "bufferView_1": { - "buffer": "mergedBuffers", - "byteLength": 3, - "byteOffset": 2 + { + buffer: 0, + byteLength: 3, + byteOffset: 2 } - }, - "buffers": { - "mergedBuffers": { - "byteLength": 5, - "type": "arraybuffer", - "uri": "data:,", - "extras": { - "_pipeline": { - "source": bufferMerged, - "extension": ".bin" - } - } + ], + buffers: [ + { + byteLength: 5 } - } + ] }); + for(var i = 0; i < bufferMerged.length; i++) { + expect(buffer[i]).toEqual(bufferMerged[i]); + } }); }); diff --git a/specs/lib/optimizeForVertexCacheSpec.js b/specs/lib/optimizeForVertexCacheSpec.js index 09fc0718..bdd311db 100644 --- a/specs/lib/optimizeForVertexCacheSpec.js +++ b/specs/lib/optimizeForVertexCacheSpec.js @@ -45,7 +45,7 @@ describe('optimizeForVertexCache', function() { expect(readGltf(gltfPath) .then(function(gltf) { addDefaults(gltf); - var positionAccessor = gltf.accessors.accessor_23; + var positionAccessor = gltf.accessors[1]; // Use write/read accessor to unpack the optimizedVertices for us writeAccessor(gltf, positionAccessor, optimizedVertices); var unpackedOptimizedVertices = []; diff --git a/specs/lib/parseBinaryGltfSpec.js b/specs/lib/parseBinaryGltfSpec.js index a4e8819a..a242688e 100644 --- a/specs/lib/parseBinaryGltfSpec.js +++ b/specs/lib/parseBinaryGltfSpec.js @@ -1,155 +1,144 @@ 'use strict'; -var fs = require('fs'); -var async = require('async'); -var bufferEqual = require('buffer-equal'); +var getBinaryGltf = require('../../lib/getBinaryGltf'); var parseBinaryGltf = require('../../lib/parseBinaryGltf'); var removePipelineExtras = require('../../lib/removePipelineExtras'); -var binaryGltfPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.glb'; -var overlapGltfPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestOverlap.glb'; -var gltfScenePath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestBinary.txt'; -var bufferPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxBuffer_Binary.bin'; -var fragmentShaderPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest0FS_Binary.glsl'; -var imagePath = './specs/data/boxTexturedUnoptimized/Cesium_Logo_Flat_Binary.png'; describe('parseBinaryGltf', function() { - var testData = { - binary: binaryGltfPath, - gltf: gltfScenePath, - buffer: bufferPath, - shader: fragmentShaderPath, - image: imagePath, - overlap: overlapGltfPath - }; - - beforeAll(function(done) { - var names = Object.keys(testData); - async.each(names, function(name, callback) { - fs.readFile(testData[name], function(err, data) { - if (err) { - callback(err); - } - else { - testData[name] = data; - callback(); - } - }); - }, function(err) { - if (err) { - throw err; - } - - done(); - }); - }); - - it('loads a glTF scene', function() { - var gltf = parseBinaryGltf(testData.binary); - - expect(gltf).toBeDefined(); - expect(gltf.buffers.bufferView_29_buffer).toBeDefined(); - expect(gltf.buffers.bufferView_30_buffer).toBeDefined(); - expect(gltf.images.Image0001).toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0FS).toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0VS).toBeDefined(); - - removePipelineExtras(gltf); - expect(gltf).toEqual(JSON.parse(testData.gltf)); - }); - - it('loads a glTF scene with overlapping buffer views', function() { - var gltf = parseBinaryGltf(testData.overlap); - var noOverlapGltf = parseBinaryGltf(testData.binary); - - expect(gltf).toBeDefined(); - expect(gltf.bufferViews.bufferView_29).toBeDefined(); - expect(gltf.bufferViews.bufferView_29_a).toBeDefined(); - expect(gltf.bufferViews.bufferView_30).toBeDefined(); - expect(gltf.bufferViews.bufferView_30_a).toBeDefined(); - - expect (gltf.bufferViews.bufferView_29.buffer).toEqual('bufferView_29_buffer'); - expect (gltf.bufferViews.bufferView_29_a.buffer).toEqual('bufferView_29_buffer'); - expect (gltf.bufferViews.bufferView_30.buffer).toEqual('bufferView_30_buffer'); - expect (gltf.bufferViews.bufferView_30.buffer).toEqual('bufferView_30_buffer'); - - expect (gltf.bufferViews.bufferView_29.byteOffset).toEqual(0); - expect (gltf.bufferViews.bufferView_29.byteLength).toEqual(72); - expect (gltf.bufferViews.bufferView_29_a.byteOffset).toEqual(12); - expect (gltf.bufferViews.bufferView_29_a.byteLength).toEqual(12); - expect (gltf.bufferViews.bufferView_30.byteOffset).toEqual(0); - expect (gltf.bufferViews.bufferView_30.byteLength).toEqual(528); - expect (gltf.bufferViews.bufferView_30_a.byteOffset).toEqual(468); - expect (gltf.bufferViews.bufferView_30_a.byteLength).toEqual(300); - - expect(gltf.buffers.bufferView_29_buffer).toBeDefined(); - expect(gltf.buffers.bufferView_30_buffer).toBeDefined(); - - expect(bufferEqual(gltf.buffers.bufferView_29_buffer.extras._pipeline.source, noOverlapGltf.buffers.bufferView_29_buffer.extras._pipeline.source)).toBe(true); - expect(bufferEqual(gltf.buffers.bufferView_30_buffer.extras._pipeline.source, noOverlapGltf.buffers.bufferView_30_buffer.extras._pipeline.source)).toBe(true); - }); - - it('loads an embedded buffer', function() { - var gltf = parseBinaryGltf(testData.binary); - - expect(gltf.buffers.bufferView_30_buffer.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.buffers.bufferView_30_buffer.extras._pipeline.source, testData.buffer)).toBe(true); - }); - - it('loads an embedded image', function() { - var gltf = parseBinaryGltf(testData.binary); - - expect(gltf.images.Image0001.extras._pipeline.source).toBeDefined(); - expect(bufferEqual(gltf.images.Image0001.extras._pipeline.source, testData.image)).toBe(true); + it('throws an error with invalid magic', function() { + var glb = new Buffer(20); + glb.write('NOPE', 0); + expect(function() { + parseBinaryGltf(glb); + }).toThrowDeveloperError(); }); - it('loads an embedded shader', function() { - var gltf = parseBinaryGltf(testData.binary); - - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras._pipeline.source).toBeDefined(); - expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras._pipeline.source).toEqual(testData.shader.toString()); + it('throws an error if version is not 1 or 2', function() { + var glb = new Buffer(20); + glb.write('glTF', 0); + glb.writeUInt32LE(3, 4); + expect(function() { + parseBinaryGltf(glb); + }).toThrowDeveloperError(); }); - it('throws an error', function() { - var magicError = new Buffer(testData.binary); - magicError.fill(0, 0, 4); - expect(function() { - try { - parseBinaryGltf(magicError); - } - catch (err) { - expect(err).toBeDefined(); - expect(err.message).toEqual('File is not valid binary glTF'); - throw err; - } - }).toThrowDeveloperError(); - }); + describe('1.0', function() { + it('throws an error if content format is not JSON', function() { + var glb = new Buffer(20); + glb.write('glTF', 0); + glb.writeUInt32LE(1, 4); + glb.writeUInt32LE(20, 8); + glb.writeUInt32LE(0, 12); + glb.writeUInt32LE(1, 16); + expect(function() { + parseBinaryGltf(glb); + }).toThrowDeveloperError(); + }); - it('throws a version error', function() { - var versionError = new Buffer(testData.binary); - versionError.fill(0, 4, 8); - expect(function() { - try { - parseBinaryGltf(versionError); + it('loads binary glTF', function() { + var binaryData = new Buffer([0, 1, 2, 3, 4, 5]); + var gltf = { + buffers: { + binary_glTF: { + byteLength: binaryData.length + } + }, + images: { + image: { + extensions: { + KHR_binary_glTF: { + bufferView: 'imageBufferView', + mimeType: 'image/jpg' + } + } + } + }, + shaders: { + shader: { + extensions: { + KHR_binary_glTF: { + bufferView: 'shaderBufferView' + } + } + } + }, + extensionsUsed: ['KHR_binary_glTF'] + }; + var gltfString = JSON.stringify(gltf); + while (gltfString.length % 4 !== 0) { + gltfString += ' '; } - catch (err) { - expect(err).toBeDefined(); - expect(err.message).toEqual('Binary glTF version is not 1'); - throw err; + var glb = new Buffer(20 + gltfString.length + binaryData.length); + glb.write('glTF', 0); + glb.writeUInt32LE(1, 4); + glb.writeUInt32LE(20 + gltfString.length + binaryData.length, 8); + glb.writeUInt32LE(gltfString.length, 12); + glb.writeUInt32LE(0, 16); + glb.write(gltfString, 20); + binaryData.copy(glb, 20 + gltfString.length); + + var parsedGltf = parseBinaryGltf(glb); + expect(parsedGltf.extensionsUsed).not.toBeDefined(); + var buffer = parsedGltf.buffers[0]; + for (var i = 0; i < binaryData.length; i++) { + expect(buffer.extras._pipeline.source[i]).toEqual(binaryData[i]); } - }).toThrowDeveloperError(); + var image = parsedGltf.images[0]; + expect(image.extensions).not.toBeDefined(); + expect(image.bufferView).toEqual('imageBufferView'); + expect(image.mimeType).toEqual('image/jpg'); + var shader = parsedGltf.shaders[0]; + expect(shader.extensions).not.toBeDefined(); + expect(shader.bufferView).toEqual('shaderBufferView'); + }); }); - it('throws a format error', function() { - var formatError = new Buffer(testData.binary); - formatError.fill(1, 16, 20); - expect(function() { - try { - parseBinaryGltf(formatError); + describe('2.0', function() { + it('loads binary glTF', function() { + var i; + var binaryData = new Buffer([0, 1, 2, 3, 4, 5]); + var gltf = { + asset: { + version: '2.0' + }, + buffers: [ + { + byteLength: binaryData.length + } + ], + images: [ + { + bufferView: 0, + mimeType: 'image/jpg' + } + ], + shaders: [ + { + bufferView: 1 + } + ] + }; + var gltfString = JSON.stringify(gltf); + while (gltfString.length % 4 !== 0) { + gltfString += ' '; } - catch (err) { - expect(err).toBeDefined(); - expect(err.message).toEqual('Binary glTF scene format is not JSON'); - throw err; + var glb = new Buffer(28 + gltfString.length + binaryData.length); + glb.write('glTF', 0); + glb.writeUInt32LE(2, 4); + glb.writeUInt32LE(12 + 8 + gltfString.length + 8 + binaryData.length, 8); + glb.writeUInt32LE(gltfString.length, 12); + glb.writeUInt32LE(0x4E4F534A, 16); + glb.write(gltfString, 20); + glb.writeUInt32LE(binaryData.length, 20 + gltfString.length); + glb.writeUInt32LE(0x004E4942, 24 + gltfString.length); + binaryData.copy(glb, 28 + gltfString.length); + + var parsedGltf = parseBinaryGltf(glb); + var buffer = parsedGltf.buffers[0]; + for (i = 0; i < binaryData.length; i++) { + expect(buffer.extras._pipeline.source[i]).toEqual(binaryData[i]); } - }).toThrowDeveloperError(); + removePipelineExtras(parsedGltf); + expect(parsedGltf).toEqual(gltf); + }); }); }); \ No newline at end of file diff --git a/specs/lib/uninterleaveAndPackBuffersSpec.js b/specs/lib/uninterleaveAndPackBuffersSpec.js index b0efc610..d08517b6 100644 --- a/specs/lib/uninterleaveAndPackBuffersSpec.js +++ b/specs/lib/uninterleaveAndPackBuffersSpec.js @@ -3,23 +3,23 @@ var clone = require('clone'); var byteLengthForComponentType = require('../../lib/byteLengthForComponentType'); var numberOfComponentsForType = require('../../lib/numberOfComponentsForType'); -var packBuffers = require('../../lib/uninterleaveAndPackBuffers'); +var uninterleaveAndPackBuffers = require('../../lib/uninterleaveAndPackBuffers'); describe('uninterleaveAndPackBuffers', function() { var buffer = new Uint8Array(96); var testGltf = { - accessors : { + accessors : [ // Interleaved accessors in bufferView_0 - accessor_0 : { - bufferView : 'bufferView_0', + { + bufferView : 0, byteOffset : 0, byteStride : 18, componentType : 5126, count : 3, type : 'VEC3' }, - accessor_1 : { - bufferView : 'bufferView_0', + { + bufferView : 0, byteOffset : 12, byteStride : 18, componentType : 5123, @@ -27,58 +27,58 @@ describe('uninterleaveAndPackBuffers', function() { type : 'VEC2' }, // Block accessors in bufferView_1 - accessor_2 : { - bufferView : 'bufferView_1', + { + bufferView : 1, byteOffset : 0, byteStride : 12, componentType : 5126, count : 3, type : 'VEC3' }, - accessor_3 : { - bufferView : 'bufferView_1', + { + bufferView : 1, byteOffset : 36, componentType : 5123, count : 3, type : 'VEC2' } - }, - bufferViews : { - bufferView_0 : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : 48, byteOffset : 0, target : 34962 }, - bufferView_1 : { - buffer : 'buffer', + { + buffer : 0, byteLength : 48, byteOffset : 48, target : 34963 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : buffer.length, type : 'arraybuffer', extras : { _pipeline : {} } } - } + ] }; - it('doesn\'t remove any data if the whole buffer is used', function() { + fit('doesn\'t remove any data if the whole buffer is used', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; - packBuffers(gltf); + gltf.buffers[0].extras._pipeline.source = buffer; + uninterleaveAndPackBuffers(gltf); expect(gltf.buffers.buffer.byteLength).toEqual(testGltf.buffers.buffer.byteLength); }); it('removes extra trailing data on the buffer', function() { var gltf = clone(testGltf); gltf.buffers.buffer.extras._pipeline.source = new Uint8Array(buffer.length * 2); - packBuffers(gltf); + uninterleaveAndPackBuffers(gltf); expect(gltf.buffers.buffer.byteLength).toEqual(testGltf.buffers.buffer.byteLength); }); @@ -89,7 +89,7 @@ describe('uninterleaveAndPackBuffers', function() { var deletedAccessor = gltf.accessors[deletedAccessorId]; var size = byteLengthForComponentType(deletedAccessor.componentType) * numberOfComponentsForType(deletedAccessor.type) * deletedAccessor.count; delete gltf.accessors[deletedAccessorId]; - packBuffers(gltf); + uninterleaveAndPackBuffers(gltf); expect(gltf.buffers.buffer.byteLength + size).toEqual(testGltf.buffers.buffer.byteLength); }); @@ -100,7 +100,7 @@ describe('uninterleaveAndPackBuffers', function() { var deletedAccessor = gltf.accessors[deletedAccessorId]; var size = byteLengthForComponentType(deletedAccessor.componentType) * numberOfComponentsForType(deletedAccessor.type) * deletedAccessor.count; delete gltf.accessors[deletedAccessorId]; - packBuffers(gltf); + uninterleaveAndPackBuffers(gltf); expect(gltf.buffers.buffer.byteLength + size).toEqual(testGltf.buffers.buffer.byteLength); var bufferView1 = gltf.bufferViews.bufferView_1; expect(bufferView1.byteLength).toEqual(gltf.buffers.buffer.byteLength - bufferView1.byteOffset); @@ -112,7 +112,7 @@ describe('uninterleaveAndPackBuffers', function() { var size = gltf.bufferViews.bufferView_0.byteLength; delete gltf.accessors.accessor_0; delete gltf.accessors.accessor_1; - packBuffers(gltf); + uninterleaveAndPackBuffers(gltf); expect(gltf.buffers.buffer.byteLength + size).toEqual(testGltf.buffers.buffer.byteLength); var bufferViewCount = Object.keys(gltf.bufferViews).length; expect(bufferViewCount).toEqual(1); diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index ad39094a..3164923c 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -242,7 +242,12 @@ describe('updateVersion', function() { }, accessor_indices: { componentType: WebGLConstants.UNSIGNED_INT - } + }, + accessor_input: {}, + accessor_output: {}, + accessor_texcoord: {}, + accessor_color: {}, + accessor_temperature: {} }, bufferViews: { bufferView: { @@ -296,12 +301,14 @@ describe('updateVersion', function() { 'rootTransform' ] } + }, + skins: { + someSkin: {} } }; - updateVersion(gltf, { - targetVersion: '1.1' - }); - expect(gltf.asset.profile.version).toEqual('1.0'); + updateVersion(gltf); + expect(gltf.asset.version).toEqual('2.0'); + expect(gltf.asset.profile).not.toBeDefined(); var extensionsUsed = gltf.extensionsUsed; expect(extensionsUsed).toEqual([ 'KHR_materials_common', @@ -313,16 +320,14 @@ describe('updateVersion', function() { 'KHR_materials_common', 'WEB3D_quantized_attributes' ]); - var glExtensionsUsed = gltf.glExtensionsUsed; - expect(glExtensionsUsed).toEqual(['OES_element_index_uint']); - var animation = gltf.animations.animation; - var sampler = animation.samplers.sampler; - expect(sampler.input).toEqual('accessor_input'); - expect(sampler.output).toEqual('accessor_output'); + var animation = gltf.animations[0]; + var sampler = animation.samplers[0]; + expect(sampler.input).toEqual(2); + expect(sampler.output).toEqual(3); expect(animation.parameters).not.toBeDefined(); - var material = gltf.materials.material; + var material = gltf.materials[0]; expect(material.values.shininess).toEqual([1.0]); - var technique = gltf.techniques.technique; + var technique = gltf.techniques[0]; expect(technique.parameters.lightAttenuation.value).toEqual([1.0]); expect(technique.parameters.application.value).not.toBeDefined(); expect(technique.parameters.texcoord.semantic).toEqual('TEXCOORD_0'); @@ -333,59 +338,28 @@ describe('updateVersion', function() { expect(states.functions.scissor).not.toBeDefined(); expect(states.functions.blendColor).toEqual([0.0, 0.0, 0.0, 1.0]); expect(states.functions.depthRange).toEqual([0.0, 0.0]); - var accessor = gltf.accessors.accessor; + var accessor = gltf.accessors[0]; expect(accessor.min).toEqual([-2.0]); expect(accessor.max).toEqual([3.0]); - var primitive = gltf.meshes.mesh.primitives[0]; + var primitive = gltf.meshes[0].primitives[0]; expect(primitive.attributes.TEXCOORD).not.toBeDefined(); - expect(primitive.attributes.TEXCOORD_0).toEqual('accessor_texcoord'); + expect(primitive.attributes.TEXCOORD_0).toEqual(4); expect(primitive.attributes.COLOR).not.toBeDefined(); - expect(primitive.attributes.COLOR_0).toEqual('accessor_color'); + expect(primitive.attributes.COLOR_0).toEqual(5); expect(primitive.attributes.APPLICATIONSPECIFIC).not.toBeDefined(); - expect(primitive.attributes._APPLICATIONSPECIFIC).toEqual('accessor'); - expect(primitive.attributes._TEMPERATURE).toEqual('accessor_temperature'); - var rootTransform = gltf.nodes.rootTransform; - var rootSkeletonNode = gltf.nodes['root-skeletonNode']; - var scene = gltf.scenes.defaultScene; - expect(scene.nodes).toEqual(['rootTransform', 'root-skeletonNode']); - expect(rootTransform.children).toEqual(['meshNode']); - expect(rootSkeletonNode.matrix).toEqual(rootTransform.matrix); - var camera = gltf.cameras.camera; + expect(primitive.attributes._APPLICATIONSPECIFIC).toEqual(0); + expect(primitive.attributes._TEMPERATURE).toEqual(6); + var camera = gltf.cameras[0]; expect(camera.perspective.aspectRatio).not.toBeDefined(); expect(camera.perspective.yfov).toEqual(1.0); - var buffer = gltf.buffers.buffer; + var buffer = gltf.buffers[0]; expect(buffer.type).not.toBeDefined(); expect(buffer.byteLength).toEqual(arrayBuffer.length); - var bufferView = gltf.bufferViews.bufferView; + var bufferView = gltf.bufferViews[0]; expect(bufferView.byteLength).toEqual(arrayBuffer.length); expect(technique.parameters.application.count).toEqual(1); expect(technique.parameters.jointMatrix.count).toEqual(2); expect(technique.parameters.notJointMatrix.count).not.toBeDefined(); expect(technique.parameters.notJointMatrixWithSemantic.count).not.toBeDefined(); }); - - it('does not add glExtensionsUsed if primitive indices are not UNSIGNED_INT', function() { - var gltf = { - asset: { - version: '1.0' - }, - accessors: { - indices_accessor: { - componentType: WebGLConstants.UNSIGNED_SHORT - } - }, - meshes : { - mesh : { - primitives : [ - { - indices: 'indices_accessor' - } - ] - } - } - }; - updateVersion(gltf); - expect(gltf.asset.version).toEqual('2.0'); - expect(gltf.glExtensionsUsed).not.toBeDefined(); - }); }); \ No newline at end of file diff --git a/specs/lib/writeBinaryGltfSpec.js b/specs/lib/writeBinaryGltfSpec.js index 79bd671e..f059e813 100644 --- a/specs/lib/writeBinaryGltfSpec.js +++ b/specs/lib/writeBinaryGltfSpec.js @@ -8,7 +8,6 @@ var loadGltfUris = require('../../lib/loadGltfUris'); var readGltf = require('../../lib/readGltf'); var writeBinaryGltf = require('../../lib/writeBinaryGltf'); -var gltfPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf'; var outputGltfPath = './output/CesiumTexturedBoxTest.glb'; var invalidPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.exe'; @@ -22,11 +21,9 @@ describe('writeBinaryGltf', function() { createDirectory : false }; - expect(readGltf(gltfPath) + var gltf = {}; + expect(writeBinaryGltf(gltf, writeOptions) .then(function(gltf) { - return writeBinaryGltf(gltf, writeOptions); - }) - .then(function() { expect(path.normalize(spy.calls.first().args[0])).toEqual(path.normalize(outputGltfPath)); }) .catch(function (err) { @@ -34,7 +31,7 @@ describe('writeBinaryGltf', function() { }), done).toResolve(); }); - it('throws an invalid output path error', function(done) { + it('throws an invalid output path error', function() { var writeOptions = { outputPath : undefined, embed : true, @@ -42,15 +39,13 @@ describe('writeBinaryGltf', function() { createDirectory : true }; - expect(readGltf(gltfPath) - .then(function(gltf) { - expect(function() { - writeBinaryGltf(gltf, writeOptions); - }).toThrowError('Output path is undefined.'); - }), done).toResolve(); + var gltf = {}; + expect(function() { + writeBinaryGltf(gltf, writeOptions); + }).toThrowError('Output path is undefined.'); }); - it('throws an invalid output extension error', function(done) { + it('throws an invalid output extension error', function() { var writeOptions = { outputPath : invalidPath, embed : true, @@ -58,11 +53,9 @@ describe('writeBinaryGltf', function() { createDirectory : true }; - expect(readGltf(gltfPath) - .then(function(gltf) { - expect(function() { - writeBinaryGltf(gltf, writeOptions); - }).toThrowError('Invalid output path extension.'); - }), done).toResolve(); + var gltf = {}; + expect(function() { + writeBinaryGltf(gltf, writeOptions); + }).toThrowError('Invalid output path extension.'); }); }); From 6427738324a312cf0a31541d0261ded0a92dae89 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Mon, 20 Mar 2017 21:37:06 -0400 Subject: [PATCH 32/47] WIP, pretty much just AO left --- lib/ForEach.js | 20 +- lib/NodeHelpers.js | 2 +- lib/Pipeline.js | 53 +- lib/compressIntegerAccessors.js | 50 +- lib/compressTextureCoordinates.js | 169 +++--- lib/createAccessorUsageTables.js | 156 +++-- lib/generateTangentsBitangents.js | 49 +- lib/getAccessorsForSemantic.js | 40 -- lib/loadGltfUris.js | 66 ++- lib/mergeDuplicateVertices.js | 15 +- lib/octEncodeNormals.js | 176 +++--- lib/parseBinaryGltf.js | 20 +- lib/quantizeAttributes.js | 53 +- lib/removeUnusedVertices.js | 3 - lib/uninterleaveAndPackBuffers.js | 20 +- lib/updateVersion.js | 6 +- .../CesiumTexturedBoxTest.gltf | 12 +- specs/lib/PipelineSpec.js | 20 +- specs/lib/addDefaultsSpec.js | 34 +- specs/lib/addPipelineExtrasSpec.js | 15 +- specs/lib/compressIntegerAccessorsSpec.js | 179 +++--- specs/lib/compressTextureCoordinatesSpec.js | 234 ++++---- specs/lib/compressTexturesSpec.js | 25 +- specs/lib/generateTangentsBitangentsSpec.js | 126 +++- specs/lib/mergeDuplicateVerticesSpec.js | 193 +++--- specs/lib/octEncodeNormalsSpec.js | 237 ++++---- specs/lib/parseBinaryGltfSpec.js | 62 +- specs/lib/quantizeAttributesSpec.js | 136 ++--- specs/lib/removeUnusedVerticesSpec.js | 547 +++++++++--------- specs/lib/uninterleaveAndPackBuffersSpec.js | 52 +- 30 files changed, 1373 insertions(+), 1397 deletions(-) delete mode 100644 lib/getAccessorsForSemantic.js diff --git a/lib/ForEach.js b/lib/ForEach.js index f2991f26..f594a923 100644 --- a/lib/ForEach.js +++ b/lib/ForEach.js @@ -32,6 +32,18 @@ ForEach.accessor = function(gltf, handler) { ForEach.topLevel(gltf, 'accessors', handler); }; +ForEach.accessorWithSemantic = function(gltf, semantic, handler) { + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitiveAttributes(primitive, function(accessorId, attributeSemantic) { + if (attributeSemantic.indexOf(semantic) === 0) { + handler(accessorId, attributeSemantic, primitive); + } + }); + }); + }); +}; + ForEach.animation = function(gltf, handler) { ForEach.topLevel(gltf, 'animations', handler); }; @@ -153,7 +165,9 @@ ForEach.techniqueAttribute = function(technique, handler) { if (defined(attributes)) { for (var semantic in attributes) { if (attributes.hasOwnProperty(semantic)) { - handler(attributes[semantic], semantic); + if (handler(attributes[semantic], semantic)) { + break; + } } } } @@ -164,7 +178,9 @@ ForEach.techniqueParameter = function(technique, handler) { if (defined(parameters)) { for (var parameterName in parameters) { if (parameters.hasOwnProperty(parameterName)) { - handler(parameters[parameterName], parameterName); + if (handler(parameters[parameterName], parameterName)) { + break; + } } } } diff --git a/lib/NodeHelpers.js b/lib/NodeHelpers.js index 657317c6..e8cff21b 100644 --- a/lib/NodeHelpers.js +++ b/lib/NodeHelpers.js @@ -1,12 +1,12 @@ 'use strict'; var Cesium = require('cesium'); + var defined = Cesium.defined; var defaultValue = Cesium.defaultValue; var Matrix4 = Cesium.Matrix4; var Cartesian3 = Cesium.Cartesian3; var Quaternion = Cesium.Quaternion; - module.exports = NodeHelpers; /** diff --git a/lib/Pipeline.js b/lib/Pipeline.js index 0dd38641..4587197c 100644 --- a/lib/Pipeline.js +++ b/lib/Pipeline.js @@ -136,39 +136,36 @@ Pipeline.processJSONWithExtras = function(gltfWithExtras, options) { bakeAmbientOcclusion(gltfWithExtras, aoOptions); } - var waitForStages = [new Promise(function(resolve) {resolve();})]; if (options.encodeNormals) { - waitForStages.push(octEncodeNormals(gltfWithExtras)); + octEncodeNormals(gltfWithExtras); } if (options.compressTextureCoordinates) { - waitForStages.push(compressTextureCoordinates(gltfWithExtras)); + compressTextureCoordinates(gltfWithExtras); } - waitForStages.push(compressIntegerAccessors(gltfWithExtras, { + compressIntegerAccessors(gltfWithExtras, { semantics : ["JOINT"] - })); - return Promise.all(waitForStages) - .then(function() { - if (options.quantize) { - var quantizedOptions = { - findMinMax : true, - exclude : [ - 'JOINT', - '_OCCLUSION' - ] - }; - if (options.compressTextureCoordinates) { - quantizedOptions.exclude.push('TEXCOORD'); - } - quantizeAttributes(gltfWithExtras, quantizedOptions); - } - var textureCompressionOptions = options.textureCompressionOptions; - if (defined(textureCompressionOptions)) { - return compressTextures(gltfWithExtras, textureCompressionOptions); - } else { - return encodeImages(gltfWithExtras); - } - }) - .then(function() { + }); + if (options.quantize) { + var quantizedOptions = { + findMinMax : true, + exclude : [ + 'JOINT', + '_OCCLUSION' + ] + }; + if (options.compressTextureCoordinates) { + quantizedOptions.exclude.push('TEXCOORD'); + } + quantizeAttributes(gltfWithExtras, quantizedOptions); + } + var textureCompressionOptions = options.textureCompressionOptions; + var promise; + if (defined(textureCompressionOptions)) { + promise = compressTextures(gltfWithExtras, textureCompressionOptions); + } else { + promise = encodeImages(gltfWithExtras); + } + return promise.then(function() { var kmcOptions = options.kmcOptions; if (defined(kmcOptions)) { generateModelMaterialsCommon(gltfWithExtras, options.kmcOptions); diff --git a/lib/compressIntegerAccessors.js b/lib/compressIntegerAccessors.js index fdbed8f3..98e521ac 100644 --- a/lib/compressIntegerAccessors.js +++ b/lib/compressIntegerAccessors.js @@ -1,17 +1,14 @@ 'use strict'; var Cesium = require('cesium'); -var Promise = require('bluebird'); +var AccessorReader = require('./AccessorReader'); +var changeAccessorComponentType = require('./changeAccessorComponentType'); +var findAccessorMinMax = require('./findAccessorMinMax'); +var ForEach = require('./ForEach'); var WebGLConstants = Cesium.WebGLConstants; var defined = Cesium.defined; var defaultValue = Cesium.defaultValue; -var AccessorReader = require('./AccessorReader'); -var changeAccessorComponentType = require('./changeAccessorComponentType'); -var findAccessorMinMax = require('./findAccessorMinMax'); -var getAccessorsForSemantic = require('./getAccessorsForSemantic'); -var uninterLeaveAndPackBuffers = require('./uninterleaveAndPackBuffers'); - module.exports = compressIntegerAccessors; var signedComponentTypes = [ @@ -50,7 +47,7 @@ var unsignedComponentTypes = [ * @param {Object} gltf A javascript object containing a glTF asset. * @param {Object} [options] Options defining custom behavior. * @param {Array} [options.semantics] An array of semantics to compress. - * @returns {Promise} A promise that resolves to the glTF asset with compressed integer accessors. + * @returns {Object} The glTF asset with compressed integer accessors. * * @see addPipelineExtras * @see loadGltfUris @@ -59,32 +56,27 @@ function compressIntegerAccessors(gltf, options) { options = defaultValue(options, {}); var semantics = defaultValue(options.semantics, []); var semanticsLength = semantics.length; - var promises = []; + + var handler = function(accessorId) { + var accessors = gltf.accessors; + var accessor = accessors[accessorId]; + var accessorReader = new AccessorReader(gltf, accessor); + var bufferView = accessorReader.bufferView; + if (bufferView.target === WebGLConstants.ARRAY_BUFFER) { + var newComponentType = canCompressAccessor(gltf, accessorReader); + if (defined(newComponentType)) { + changeAccessorComponentType(gltf, accessor, newComponentType); + } + } + }; + for (var i = 0; i < semanticsLength; i++) { var semantic = semantics[i]; - promises.push(getAccessorsForSemantic(gltf, semantic, compressIntegerAccessor)); + ForEach.accessorWithSemantic(gltf, semantic, handler); } - return Promise.all(promises).then(function() { - uninterLeaveAndPackBuffers(gltf); - return gltf; - }); + return gltf; } -function compressIntegerAccessor(gltf, primitive, accessorId, matchedSemantic) { - /* These callback parameters are unused */ - void(primitive, matchedSemantic); - - var accessors = gltf.accessors; - var accessor = accessors[accessorId]; - var accessorReader = new AccessorReader(gltf, accessor); - var bufferView = accessorReader.bufferView; - if (bufferView.target === WebGLConstants.ARRAY_BUFFER) { - var newComponentType = canCompressAccessor(gltf, accessorReader); - if (defined(newComponentType)) { - changeAccessorComponentType(gltf, accessor, newComponentType); - } - } -} function canCompressAccessor(gltf, accessorReader) { // Can't compress something smaller than a byte diff --git a/lib/compressTextureCoordinates.js b/lib/compressTextureCoordinates.js index 83342061..abf7b765 100644 --- a/lib/compressTextureCoordinates.js +++ b/lib/compressTextureCoordinates.js @@ -1,6 +1,12 @@ 'use strict'; var Cesium = require('cesium'); -var Promise = require('bluebird'); +var byteLengthForComponentType = require('./byteLengthForComponentType'); +var findAccessorMinMax = require('./findAccessorMinMax'); +var ForEach = require('./ForEach'); +var getAccessorByteStride = require('./getAccessorByteStride'); +var numberOfComponentsForType = require('./numberOfComponentsForType'); +var readBufferComponent = require('./readBufferComponent'); +var writeBufferComponent = require('./writeBufferComponent'); var AttributeCompression = Cesium.AttributeCompression; var Cartesian2 = Cesium.Cartesian2; @@ -9,15 +15,6 @@ var ShaderSource = Cesium.ShaderSource; var WebGLConstants = Cesium.WebGLConstants; var defined = Cesium.defined; -var byteLengthForComponentType = require('./byteLengthForComponentType'); -var findAccessorMinMax = require('./findAccessorMinMax'); -var getAccessorByteStride = require('./getAccessorByteStride'); -var getAccessorsForSemantic = require('./getAccessorsForSemantic'); -var numberOfComponentsForType = require('./numberOfComponentsForType'); -var readBufferComponent = require('./readBufferComponent'); -var uninterleaveAndPackBuffers = require('./uninterleaveAndPackBuffers'); -var writeBufferComponent = require('./writeBufferComponent'); - module.exports = compressTextureCoordinates; /** @@ -27,75 +24,72 @@ module.exports = compressTextureCoordinates; * The glTF asset must be initialized for the pipeline. * * @param {Object} gltf A javascript object containing a glTF asset. - * @returns {Promise} A promise that resolves to the glTF asset with compressed texture coordinates. + * @returns {Object} The glTF asset with compressed texture coordinates. * * @see addPipelineExtras * @see loadGltfUris */ function compressTextureCoordinates(gltf) { - return new Promise(function(resolve) { - var accessors = gltf.accessors; - var bufferViews = gltf.bufferViews; - var buffers = gltf.buffers; - var materials = gltf.materials; - var techniques = gltf.techniques; - var patchedTechniques = {}; - var patchedPrograms = {}; - var patchedShaders = {}; + var accessors = gltf.accessors; + var bufferViews = gltf.bufferViews; + var buffers = gltf.buffers; + var materials = gltf.materials; + var techniques = gltf.techniques; + var patchedTechniques = {}; + var patchedPrograms = {}; + var patchedShaders = {}; - getAccessorsForSemantic(gltf, 'TEXCOORD', function(gltf, primitive, accessorId) { - var accessor = accessors[accessorId]; - if (canCompress(accessor, primitive)) { - // Compress texture coordinates to a single float - var bufferViewId = accessor.bufferView; - var bufferView = bufferViews[bufferViewId]; - var bufferId = bufferView.buffer; - var buffer = buffers[bufferId]; - var source = buffer.extras._pipeline.source; - var byteStride = getAccessorByteStride(accessor); - var byteOffset = accessor.byteOffset + bufferView.byteOffset; - var componentType = accessor.componentType; - var newComponentType = WebGLConstants.FLOAT; - var componentByteLength = byteLengthForComponentType(componentType); - var numElements = accessor.count; - var numComponents = numberOfComponentsForType(accessor.type); - for (var j = 0; j < numElements; j++) { - var elementArray = []; - for (var k = 0; k < numComponents; k++) { - var element = readBufferComponent(source, componentType, byteOffset + componentByteLength * k); - elementArray.push(element); - } - var texCoord = Cartesian2.fromArray(elementArray); - var compressed = AttributeCompression.compressTextureCoordinates(texCoord); - writeBufferComponent(source, newComponentType, compressed, byteOffset); - byteOffset += byteStride; - } - accessor.byteStride = byteStride; - accessor.componentType = newComponentType; - accessor.type = 'SCALAR'; - var minMax = findAccessorMinMax(gltf, accessor); - accessor.min = minMax.min; - accessor.max = minMax.max; - var materialId = primitive.material; - var material = materials[materialId]; - var techniqueId = material.technique; - var attributeVariableName = patchedTechniques[techniqueId]; - if (!defined(patchedTechniques[techniqueId])) { - attributeVariableName = patchTechnique(gltf, techniqueId); - patchedTechniques[techniqueId] = attributeVariableName; - } - var technique = techniques[techniqueId]; - var programId = technique.program; - if (!defined(patchedPrograms[programId])) { - patchProgram(gltf, programId, attributeVariableName, patchedShaders); - patchedPrograms[programId] = true; + /* jshint unused:vars */ + ForEach.accessorWithSemantic(gltf, 'TEXCOORD', function(accessorId, semantic, primitive) { + var accessor = accessors[accessorId]; + if (canCompress(accessor, primitive)) { + // Compress texture coordinates to a single float + var bufferViewId = accessor.bufferView; + var bufferView = bufferViews[bufferViewId]; + var bufferId = bufferView.buffer; + var buffer = buffers[bufferId]; + var source = buffer.extras._pipeline.source; + var byteStride = getAccessorByteStride(accessor); + var byteOffset = accessor.byteOffset + bufferView.byteOffset; + var componentType = accessor.componentType; + var newComponentType = WebGLConstants.FLOAT; + var componentByteLength = byteLengthForComponentType(componentType); + var numElements = accessor.count; + var numComponents = numberOfComponentsForType(accessor.type); + for (var j = 0; j < numElements; j++) { + var elementArray = []; + for (var k = 0; k < numComponents; k++) { + var element = readBufferComponent(source, componentType, byteOffset + componentByteLength * k); + elementArray.push(element); } + var texCoord = Cartesian2.fromArray(elementArray); + var compressed = AttributeCompression.compressTextureCoordinates(texCoord); + writeBufferComponent(source, newComponentType, compressed, byteOffset); + byteOffset += byteStride; } - }).then(function() { - uninterleaveAndPackBuffers(gltf); - resolve(gltf); - }); + accessor.byteStride = byteStride; + accessor.componentType = newComponentType; + accessor.type = 'SCALAR'; + var minMax = findAccessorMinMax(gltf, accessor); + accessor.min = minMax.min; + accessor.max = minMax.max; + var materialId = primitive.material; + var material = materials[materialId]; + var techniqueId = material.technique; + var attributeVariableName = patchedTechniques[techniqueId]; + if (!defined(patchedTechniques[techniqueId])) { + attributeVariableName = patchTechnique(gltf, techniqueId); + patchedTechniques[techniqueId] = attributeVariableName; + } + var technique = techniques[techniqueId]; + var programId = technique.program; + if (!defined(patchedPrograms[programId])) { + patchProgram(gltf, programId, attributeVariableName, patchedShaders); + patchedPrograms[programId] = true; + } + } }); + return gltf; } function canCompress(accessor) { @@ -107,34 +101,29 @@ function canCompress(accessor) { function patchTechnique(gltf, techniqueId) { var techniques = gltf.techniques; var technique = techniques[techniqueId]; - var attributes = technique.attributes; - var parameters = technique.parameters; var texCoordParameterName; - for (var parameterName in parameters) { - if (parameters.hasOwnProperty(parameterName)) { - var parameter = parameters[parameterName]; - var semantic = parameter.semantic; - if (defined(semantic)) { - if (semantic.indexOf('TEXCOORD') === 0) { - texCoordParameterName = parameterName; - parameter.type = WebGLConstants.FLOAT; - break; - } + ForEach.techniqueParameter(technique, function(parameter, parameterName) { + var semantic = parameter.semantic; + if (defined(semantic)) { + if (semantic.indexOf('TEXCOORD') === 0) { + texCoordParameterName = parameterName; + parameter.type = WebGLConstants.FLOAT; + return true; } } - } + }); + var texcoordVariableName; if (!defined(texCoordParameterName)) { throw new DeveloperError('TEXCOORD semantic in technique' + techniqueId + ' doesn\'t have a defined parameter'); } else { - for (var attributeVariableName in attributes) { - if (attributes.hasOwnProperty(attributeVariableName)) { - var attributeParameterName = attributes[attributeVariableName]; - if (attributeParameterName === texCoordParameterName) { - return attributeVariableName; - } + ForEach.techniqueAttribute(technique, function(attributeParameterName, attributeVariableName) { + if (attributeParameterName === texCoordParameterName) { + texcoordVariableName = attributeVariableName; + return true; } - } + }); } + return texcoordVariableName; } function patchProgram(gltf, programId, texCoordVariableName, patchedShaders) { diff --git a/lib/createAccessorUsageTables.js b/lib/createAccessorUsageTables.js index 5b10164c..223a79b2 100644 --- a/lib/createAccessorUsageTables.js +++ b/lib/createAccessorUsageTables.js @@ -1,6 +1,7 @@ 'use strict'; var Cesium = require('cesium'); var defined = Cesium.defined; +var ForEach = require('./ForEach'); var getAccessorByteStride = require('./getAccessorByteStride'); var readBufferComponent = require('./readBufferComponent'); @@ -71,7 +72,6 @@ function markUsageForIndexAccessor(gltf, accessor, usage) { */ function createAccessorUsageTables(gltf) { var accessors = gltf.accessors; - var meshes = gltf.meshes; var tables = []; var accessorTableMapping = {}; var attribute; @@ -79,86 +79,80 @@ function createAccessorUsageTables(gltf) { var table; var tableIndex; var i; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (i = 0; i < primitivesLength ; i++) { - var primitive = primitives[i]; - var attributes = primitive.attributes; - var indexAccessorId = primitive.indices; - if (defined(indexAccessorId)) { - var indexAccessor = accessors[indexAccessorId]; - tableIndex = accessorTableMapping[indexAccessorId]; - if (!defined(tableIndex)) { - // There is no mapping for this index accessor, check if there is an existing mapping for any of the attributes - var mappedTableIndex; - var mappedTableIndices = {}; - for (attribute in attributes) { - if (attributes.hasOwnProperty(attribute)) { - attributeAccessorId = attributes[attribute]; - if (defined(accessorTableMapping[attributeAccessorId])) { - // There is already a mapping for one of the attributes, join that one - mappedTableIndices[accessorTableMapping[attributeAccessorId]] = true; - } - } - } - var mappedTableIndexArray = Object.keys(mappedTableIndices); - var mappedTableIndexArrayLength = mappedTableIndexArray.length; - if (mappedTableIndexArrayLength > 0) { - mappedTableIndex = parseInt(mappedTableIndexArray[0]); - for (var j = 1; j < mappedTableIndexArrayLength; j++) { - // Multiple attributes mapped to different tables, merge them - var indexB = mappedTableIndexArray[j]; - mergeUsageTables(tables, accessorTableMapping, mappedTableIndex, indexB); - } - } - if (!defined(mappedTableIndex)) { - // There are no existing linkages to other accessors, make a new table entry - table = { - indexAccessors : {}, - attributeAccessors : {}, - usage : [] - }; - tables.push(table); - mappedTableIndex = tables.length - 1; - } else { - // Join an existing mapping - table = tables[mappedTableIndex]; - } - table.usage = markUsageForIndexAccessor(gltf, indexAccessor, table.usage); - table.indexAccessors[indexAccessorId] = true; - for (attribute in attributes) { - if (attributes.hasOwnProperty(attribute)) { - attributeAccessorId = attributes[attribute]; - table.attributeAccessors[attributeAccessorId] = true; - accessorTableMapping[attributeAccessorId] = mappedTableIndex; - } - } - accessorTableMapping[indexAccessorId] = mappedTableIndex; - mappedTableIndex = undefined; - } else { - // This index accessor has already been done - table = tables[tableIndex]; - for (attribute in attributes) { - if (attributes.hasOwnProperty(attribute)) { - attributeAccessorId = attributes[attribute]; - // Make sure the attribute accessors haven't been assigned somewhere else - var attributeTableIndex = accessorTableMapping[attributeAccessorId]; - if (defined(attributeTableIndex) && attributeTableIndex !== tableIndex) { - // Merge them into this one if they have been - mergeUsageTables(tables, accessorTableMapping, tableIndex, attributeTableIndex); - } - table.attributeAccessors[attributeAccessorId] = true; - accessorTableMapping[attributeAccessorId] = tableIndex; - } - } - } - } - } - } - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + var attributes = primitive.attributes; + var indexAccessorId = primitive.indices; + if (defined(indexAccessorId)) { + var indexAccessor = accessors[indexAccessorId]; + tableIndex = accessorTableMapping[indexAccessorId]; + if (!defined(tableIndex)) { + // There is no mapping for this index accessor, check if there is an existing mapping for any of the attributes + var mappedTableIndex; + var mappedTableIndices = {}; + for (attribute in attributes) { + if (attributes.hasOwnProperty(attribute)) { + attributeAccessorId = attributes[attribute]; + if (defined(accessorTableMapping[attributeAccessorId])) { + // There is already a mapping for one of the attributes, join that one + mappedTableIndices[accessorTableMapping[attributeAccessorId]] = true; + } + } + } + var mappedTableIndexArray = Object.keys(mappedTableIndices); + var mappedTableIndexArrayLength = mappedTableIndexArray.length; + if (mappedTableIndexArrayLength > 0) { + mappedTableIndex = parseInt(mappedTableIndexArray[0]); + for (var j = 1; j < mappedTableIndexArrayLength; j++) { + // Multiple attributes mapped to different tables, merge them + var indexB = mappedTableIndexArray[j]; + mergeUsageTables(tables, accessorTableMapping, mappedTableIndex, indexB); + } + } + if (!defined(mappedTableIndex)) { + // There are no existing linkages to other accessors, make a new table entry + table = { + indexAccessors : {}, + attributeAccessors : {}, + usage : [] + }; + tables.push(table); + mappedTableIndex = tables.length - 1; + } else { + // Join an existing mapping + table = tables[mappedTableIndex]; + } + table.usage = markUsageForIndexAccessor(gltf, indexAccessor, table.usage); + table.indexAccessors[indexAccessorId] = true; + for (attribute in attributes) { + if (attributes.hasOwnProperty(attribute)) { + attributeAccessorId = attributes[attribute]; + table.attributeAccessors[attributeAccessorId] = true; + accessorTableMapping[attributeAccessorId] = mappedTableIndex; + } + } + accessorTableMapping[indexAccessorId] = mappedTableIndex; + mappedTableIndex = undefined; + } else { + // This index accessor has already been done + table = tables[tableIndex]; + for (attribute in attributes) { + if (attributes.hasOwnProperty(attribute)) { + attributeAccessorId = attributes[attribute]; + // Make sure the attribute accessors haven't been assigned somewhere else + var attributeTableIndex = accessorTableMapping[attributeAccessorId]; + if (defined(attributeTableIndex) && attributeTableIndex !== tableIndex) { + // Merge them into this one if they have been + mergeUsageTables(tables, accessorTableMapping, tableIndex, attributeTableIndex); + } + table.attributeAccessors[attributeAccessorId] = true; + accessorTableMapping[attributeAccessorId] = tableIndex; + } + } + } + } + }) ; + }); var finalTables = []; var tablesLength = tables.length; for (i = 0; i < tablesLength; i++) { diff --git a/lib/generateTangentsBitangents.js b/lib/generateTangentsBitangents.js index 3d6bd385..bf914a10 100644 --- a/lib/generateTangentsBitangents.js +++ b/lib/generateTangentsBitangents.js @@ -1,20 +1,19 @@ 'use strict'; var Cesium = require('cesium'); +var ForEach = require('./ForEach'); var gltfPrimitiveToCesiumGeometry = require('./gltfPrimitiveToCesiumGeometry'); var cesiumGeometryToGltfPrimitive = require('./cesiumGeometryToGltfPrimitive'); -var PrimitiveHelpers = require('./PrimitiveHelpers'); var defined = Cesium.defined; var WebGLConstants = Cesium.WebGLConstants; var GeometryPipeline = Cesium.GeometryPipeline; -var getAllPrimitives = PrimitiveHelpers.getAllPrimitives; module.exports = generateTangentsBitangents; /** * Generates tangents and bitangents for primitives if they do not exist. * - * The glTF asset must be initialized for the pipeline. It mus already have normals. + * The glTF asset must be initialized for the pipeline. It must already have normals. * * @param {Object} gltf A javascript object containing a glTF asset. * @returns {Object} The glTF asset with generated tangents and bitangents. @@ -23,27 +22,27 @@ module.exports = generateTangentsBitangents; * @see loadGltfUris */ function generateTangentsBitangents(gltf) { - var primitives = getAllPrimitives(gltf); - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - var positionAccessorId = primitive.attributes.POSITION; - var normalAccessorId = primitive.attributes.NORMAL; - var texcoordAccessorId = primitive.attributes.TEXCOORD_0; - var bitangentAccessorId = primitive.attributes.BITANGENT; - var tangentAccessorId = primitive.attributes.TANGENT; - var indicesAccessorId = primitive.indices; + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + var positionAccessorId = primitive.attributes.POSITION; + var normalAccessorId = primitive.attributes.NORMAL; + var texcoordAccessorId = primitive.attributes.TEXCOORD_0; + var bitangentAccessorId = primitive.attributes.BITANGENT; + var tangentAccessorId = primitive.attributes.TANGENT; + var indicesAccessorId = primitive.indices; - if (primitive.mode === WebGLConstants.TRIANGLES && defined(indicesAccessorId) && - defined(positionAccessorId) && - defined(normalAccessorId) && - defined(texcoordAccessorId) && - !defined(bitangentAccessorId) && - !defined(tangentAccessorId) ) { - var geometry = gltfPrimitiveToCesiumGeometry(gltf, primitive); - GeometryPipeline.computeTangentAndBitangent(geometry); - cesiumGeometryToGltfPrimitive(gltf, primitive, geometry); - } - } + if (primitive.mode === WebGLConstants.TRIANGLES && + defined(indicesAccessorId) && + defined(positionAccessorId) && + defined(normalAccessorId) && + defined(texcoordAccessorId) && + !defined(bitangentAccessorId) && + !defined(tangentAccessorId)) { + var geometry = gltfPrimitiveToCesiumGeometry(gltf, primitive); + GeometryPipeline.computeTangentAndBitangent(geometry); + cesiumGeometryToGltfPrimitive(gltf, primitive, geometry); + } + }); + }); return gltf; -} +} \ No newline at end of file diff --git a/lib/getAccessorsForSemantic.js b/lib/getAccessorsForSemantic.js deleted file mode 100644 index faf390b2..00000000 --- a/lib/getAccessorsForSemantic.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; -var Promise = require('bluebird'); - -module.exports = getAccessorsForSemantic; - -/** - * Iterates over the provided glTF meshes and calls the callback when a primitive is - * found that uses a particular semantic. - * - * @param {Object} gltf The glTF hierarchy - * @param {String} semantic Matches against the beginning of the semantic string for the primitives' attributes - * @param {Function} callback This gets called when a match is found with the arguments (gltf, primitive, accessorId, matchedSemantic) - * - * @returns {Promise} A promise that resolves when all primitives have been searched. - * @private - */ -function getAccessorsForSemantic(gltf, semantic, callback) { - return new Promise(function(resolve) { - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - var primitiveAttributes = primitive.attributes; - for (var attributeSemantic in primitiveAttributes) { - if (primitiveAttributes.hasOwnProperty(attributeSemantic)) { - if (attributeSemantic.indexOf(semantic) === 0) { - callback(gltf, primitive, primitiveAttributes[attributeSemantic], attributeSemantic); - } - } - } - } - } - } - resolve(); - }); -} \ No newline at end of file diff --git a/lib/loadGltfUris.js b/lib/loadGltfUris.js index 38ae2ccd..c8c46cd3 100644 --- a/lib/loadGltfUris.js +++ b/lib/loadGltfUris.js @@ -28,40 +28,44 @@ module.exports = loadGltfUris; function loadGltfUris(gltf, options) { options = defaultValue(options, {}); var basePath = defaultValue(options.basePath, ''); - var loadPromises = [ - loadURIs(gltf.buffers, 'buffers', basePath), - loadURIs(gltf.images, 'images', basePath), - loadURIs(gltf.shaders, 'shaders', basePath) - ]; - - // Read sources for compressed textures - ForEach.image(function(image) { - if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { - var compressedImages = image.extras.compressedImage3DTiles; - loadPromises.push(loadURIs(compressedImages, 'images', basePath)); - } - }); - - return Promise.all(loadPromises) + // Buffers need to be loaded first because images and shader may resolve to bufferViews + return loadURIs(gltf, gltf.buffers, 'buffers', basePath) .then(function() { - gltf.extras = defaultValue(gltf.extras, {}); - gltf.extras._pipeline = defaultValue(gltf.extras._pipeline, { - deleteExtras: true + var loadPromises = [ + loadURIs(gltf, gltf.images, 'images', basePath), + loadURIs(gltf, gltf.shaders, 'shaders', basePath) + ]; + + // Read sources for compressed textures + ForEach.image(function (image) { + if (defined(image.extras) && defined(image.extras.compressedImage3DTiles)) { + var compressedImages = image.extras.compressedImage3DTiles; + loadPromises.push(loadURIs(gltf, compressedImages, 'images', basePath)); + } }); - gltf.extras._pipeline.jimpScratch = new Jimp(1, 1); - return gltf; + + return Promise.all(loadPromises) + .then(function () { + gltf.extras = defaultValue(gltf.extras, {}); + gltf.extras._pipeline = defaultValue(gltf.extras._pipeline, { + deleteExtras: true + }); + gltf.extras._pipeline.jimpScratch = new Jimp(1, 1); + return gltf; + }); }); } -function loadURIs(objects, name, basePath) { +function loadURIs(gltf, objects, name, basePath) { if (defined(objects)) { return Promise.each(objects, function (object) { - return loadURI(object, name, basePath); + return loadURI(gltf, object, name, basePath); }); } + return Promise.resolve(); } -function loadURI(object, name, basePath) { +function loadURI(gltf, object, name, basePath) { var promises = []; object.extras = defaultValue(object.extras, {}); object.extras._pipeline = defaultValue(object.extras._pipeline, {}); @@ -70,13 +74,21 @@ function loadURI(object, name, basePath) { } var uri = object.uri; //Load the uri into the extras object based on the uri type - if (isDataUri(uri)) { + var bufferViews = gltf.bufferViews; + var buffers = gltf.buffers; + if (defined(object.bufferView)) { + var bufferView = bufferViews[object.bufferView]; + var bufferId = bufferView.buffer; + var buffer = buffers[bufferId]; + var source = buffer.extras._pipeline.source; + object.extras._pipeline.source = source.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); + } else if (isDataUri(uri)) { if (!defined(object.extras._pipeline.source)) { - var buffer = dataUriToBuffer(uri); + var dataBuffer = dataUriToBuffer(uri); if (name === 'shaders') { - object.extras._pipeline.source = buffer.toString(); + object.extras._pipeline.source = dataBuffer.toString(); } else { - object.extras._pipeline.source = buffer; + object.extras._pipeline.source = dataBuffer; } } if (!defined(object.extras._pipeline.extension)) { diff --git a/lib/mergeDuplicateVertices.js b/lib/mergeDuplicateVertices.js index d86cc65c..1ff64447 100644 --- a/lib/mergeDuplicateVertices.js +++ b/lib/mergeDuplicateVertices.js @@ -1,13 +1,13 @@ 'use strict'; var Cesium = require('cesium'); -var defined = Cesium.defined; - var byteLengthForComponentType = require('./byteLengthForComponentType'); +var ForEach = require('./ForEach'); var getAccessorByteStride = require('./getAccessorByteStride'); var numberOfComponentsForType = require('./numberOfComponentsForType'); var readBufferComponent = require('./readBufferComponent'); var writeBufferComponent = require('./writeBufferComponent'); -var removeUnusedVertices = require('./removeUnusedVertices'); + +var defined = Cesium.defined; module.exports = mergeDuplicateVertices; @@ -22,7 +22,6 @@ module.exports = mergeDuplicateVertices; * * @see addPipelineExtras * @see loadGltfUris - * @see removeUnusedVertices */ function mergeDuplicateVertices(gltf) { var meshes = gltf.meshes; @@ -35,7 +34,6 @@ function mergeDuplicateVertices(gltf) { } } mergeDuplicateVerticesFromMapping(gltf, indexAccessors); - removeUnusedVertices(gltf); return gltf; } @@ -70,10 +68,7 @@ function findDuplicateVerticesInMesh(gltf, mesh, indexAccessors) { var accessors = gltf.accessors; var buffers = gltf.buffers; var bufferViews = gltf.bufferViews; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var n = 0; n < primitivesLength; n++) { - var primitive = primitives[n]; + ForEach.meshPrimitives(mesh, function(primitive) { var indexAccessorId = primitive.indices; var attribute; if (defined(indexAccessorId)) { @@ -150,6 +145,6 @@ function findDuplicateVerticesInMesh(gltf, mesh, indexAccessors) { } } } - } + }); } diff --git a/lib/octEncodeNormals.js b/lib/octEncodeNormals.js index 15eb6e68..a01d5ecc 100644 --- a/lib/octEncodeNormals.js +++ b/lib/octEncodeNormals.js @@ -1,5 +1,13 @@ 'use strict'; var Cesium = require('cesium'); +var byteLengthForComponentType = require('./byteLengthForComponentType'); +var findAccessorMinMax = require('./findAccessorMinMax'); +var ForEach = require('./ForEach'); +var getAccessorByteStride = require('./getAccessorByteStride'); +var numberOfComponentsForType = require('./numberOfComponentsForType'); +var readBufferComponent = require('./readBufferComponent'); +var writeBufferComponent = require('./writeBufferComponent'); + var AttributeCompression = Cesium.AttributeCompression; var Cartesian2 = Cesium.Cartesian2; var Cartesian3 = Cesium.Cartesian3; @@ -7,16 +15,6 @@ var DeveloperError = Cesium.DeveloperError; var ShaderSource = Cesium.ShaderSource; var WebGLConstants = Cesium.WebGLConstants; var defined = Cesium.defined; -var Promise = require('bluebird'); - -var byteLengthForComponentType = require('./byteLengthForComponentType'); -var findAccessorMinMax = require('./findAccessorMinMax'); -var getAccessorByteStride = require('./getAccessorByteStride'); -var getAccessorsForSemantic = require('./getAccessorsForSemantic'); -var numberOfComponentsForType = require('./numberOfComponentsForType'); -var readBufferComponent = require('./readBufferComponent'); -var writeBufferComponent = require('./writeBufferComponent'); -var uninterleaveAndPackBuffers = require('./uninterleaveAndPackBuffers'); module.exports = octEncodeNormals; @@ -27,79 +25,76 @@ module.exports = octEncodeNormals; * The glTF asset must be initialized for the pipeline. * * @param {Object} gltf A glTF hierarchy. - * @returns {Promise} A promise that resolves to the glTF asset with oct-encoded normals when the operation completes. + * @returns {Object} The glTF asset with oct-encoded normals when the operation completes. * * @see addPipelineExtras * @see loadGltfUris */ function octEncodeNormals(gltf) { - return new Promise(function(resolve) { - var accessors = gltf.accessors; - var bufferViews = gltf.bufferViews; - var buffers = gltf.buffers; - var materials = gltf.materials; - var techniques = gltf.techniques; - var patchedTechniques = {}; - var patchedPrograms = {}; - var patchedShaders = {}; + var accessors = gltf.accessors; + var bufferViews = gltf.bufferViews; + var buffers = gltf.buffers; + var materials = gltf.materials; + var techniques = gltf.techniques; + var patchedTechniques = {}; + var patchedPrograms = {}; + var patchedShaders = {}; - getAccessorsForSemantic(gltf, 'NORMAL', function(gltf, primitive, accessorId) { - var accessor = accessors[accessorId]; - if (canOctEncode(accessor, primitive)) { - // Oct-encode normals to 2-bytes - var bufferViewId = accessor.bufferView; - var bufferView = bufferViews[bufferViewId]; - var bufferId = bufferView.buffer; - var buffer = buffers[bufferId]; - var source = buffer.extras._pipeline.source; - var byteStride = getAccessorByteStride(accessor); - var byteOffset = accessor.byteOffset + bufferView.byteOffset; - var componentType = accessor.componentType; - var newComponentType = WebGLConstants.UNSIGNED_BYTE; - var componentByteLength = byteLengthForComponentType(componentType); - var newComponentByteLength = byteLengthForComponentType(newComponentType); - var numElements = accessor.count; - var numComponents = numberOfComponentsForType(accessor.type); - for (var j = 0; j < numElements; j++) { - var elementArray = []; - for (var k = 0; k < numComponents; k++) { - var element = readBufferComponent(source, componentType, byteOffset + componentByteLength * k); - elementArray.push(element); - } - var normalVector = Cartesian3.fromArray(elementArray); - Cartesian3.normalize(normalVector, normalVector); - var octEncodedVector = new Cartesian2(); - AttributeCompression.octEncode(normalVector, octEncodedVector); - writeBufferComponent(source, newComponentType, octEncodedVector.x, byteOffset); - writeBufferComponent(source, newComponentType, octEncodedVector.y, byteOffset + newComponentByteLength); - byteOffset += byteStride; - } - accessor.byteStride = byteStride; - accessor.componentType = newComponentType; - accessor.type = 'VEC2'; - var minMax = findAccessorMinMax(gltf, accessor); - accessor.min = minMax.min; - accessor.max = minMax.max; - var materialId = primitive.material; - var material = materials[materialId]; - var techniqueId = material.technique; - var attributeVariableName = patchedTechniques[techniqueId]; - if (!defined(patchedTechniques[techniqueId])) { - attributeVariableName = patchTechnique(gltf, techniqueId); - patchedTechniques[techniqueId] = attributeVariableName; - } - var technique = techniques[techniqueId]; - var programId = technique.program; - if (!defined(patchedPrograms[programId])) { - patchProgram(gltf, programId, attributeVariableName, patchedShaders); - patchedPrograms[programId] = true; + /* jshint unused:vars */ + ForEach.accessorWithSemantic(gltf, 'NORMAL', function(accessorId, semantic, primitive) { + var accessor = accessors[accessorId]; + if (canOctEncode(accessor, primitive)) { + // Oct-encode normals to 2-bytes + var bufferViewId = accessor.bufferView; + var bufferView = bufferViews[bufferViewId]; + var bufferId = bufferView.buffer; + var buffer = buffers[bufferId]; + var source = buffer.extras._pipeline.source; + var byteStride = getAccessorByteStride(accessor); + var byteOffset = accessor.byteOffset + bufferView.byteOffset; + var componentType = accessor.componentType; + var newComponentType = WebGLConstants.UNSIGNED_BYTE; + var componentByteLength = byteLengthForComponentType(componentType); + var newComponentByteLength = byteLengthForComponentType(newComponentType); + var numElements = accessor.count; + var numComponents = numberOfComponentsForType(accessor.type); + for (var j = 0; j < numElements; j++) { + var elementArray = []; + for (var k = 0; k < numComponents; k++) { + var element = readBufferComponent(source, componentType, byteOffset + componentByteLength * k); + elementArray.push(element); } + var normalVector = Cartesian3.fromArray(elementArray); + Cartesian3.normalize(normalVector, normalVector); + var octEncodedVector = new Cartesian2(); + AttributeCompression.octEncode(normalVector, octEncodedVector); + writeBufferComponent(source, newComponentType, octEncodedVector.x, byteOffset); + writeBufferComponent(source, newComponentType, octEncodedVector.y, byteOffset + newComponentByteLength); + byteOffset += byteStride; } - }).then(function() { - uninterleaveAndPackBuffers(gltf); - resolve(gltf); - }); + accessor.byteStride = byteStride; + accessor.componentType = newComponentType; + accessor.type = 'VEC2'; + var minMax = findAccessorMinMax(gltf, accessor); + accessor.min = minMax.min; + accessor.max = minMax.max; + var materialId = primitive.material; + var material = materials[materialId]; + var techniqueId = material.technique; + var attributeVariableName = patchedTechniques[techniqueId]; + if (!defined(patchedTechniques[techniqueId])) { + attributeVariableName = patchTechnique(gltf, techniqueId); + patchedTechniques[techniqueId] = attributeVariableName; + } + var technique = techniques[techniqueId]; + var programId = technique.program; + if (!defined(patchedPrograms[programId])) { + patchProgram(gltf, programId, attributeVariableName, patchedShaders); + patchedPrograms[programId] = true; + } + } }); + return gltf; } function canOctEncode(accessor) { @@ -109,32 +104,27 @@ function canOctEncode(accessor) { function patchTechnique(gltf, techniqueId) { var techniques = gltf.techniques; var technique = techniques[techniqueId]; - var attributes = technique.attributes; - var parameters = technique.parameters; var normalParameterName; - for (var parameterName in parameters) { - if (parameters.hasOwnProperty(parameterName)) { - var parameter = parameters[parameterName]; - var semantic = parameter.semantic; - if (semantic === 'NORMAL') { - normalParameterName = parameterName; - parameter.type = WebGLConstants.INT_VEC2; - break; - } + ForEach.techniqueParameter(technique, function(parameter, parameterName) { + var semantic = parameter.semantic; + if (semantic === 'NORMAL') { + normalParameterName = parameterName; + parameter.type = WebGLConstants.INT_VEC2; + return true; } - } + }); + var normalVariableName; if (!defined(normalParameterName)) { throw new DeveloperError('NORMAL semantic in technique' + techniqueId + ' doesn\'t have a defined parameter'); } else { - for (var attributeVariableName in attributes) { - if (attributes.hasOwnProperty(attributeVariableName)) { - var attributeParameterName = attributes[attributeVariableName]; - if (attributeParameterName === normalParameterName) { - return attributeVariableName; - } + ForEach.techniqueAttribute(technique, function(attributeParameterName, attributeVariableName) { + if (attributeParameterName === normalParameterName) { + normalVariableName = attributeVariableName; + return true; } - } + }); } + return normalVariableName; } function patchProgram(gltf, programId, normalVariableName, patchedShaders) { diff --git a/lib/parseBinaryGltf.js b/lib/parseBinaryGltf.js index 8c676f7e..45c5b5ca 100644 --- a/lib/parseBinaryGltf.js +++ b/lib/parseBinaryGltf.js @@ -49,20 +49,24 @@ function parseBinaryGltf(data) { } var contentString = getStringFromTypedArray(data.slice(20, 20 + contentLength)); gltf = JSON.parse(contentString); - // Update to glTF 2.0 - updateVersion(gltf); - // Remove the KHR_binary_glTF extension - removeExtensionsUsed(gltf, 'KHR_binary_glTF'); - addPipelineExtras(gltf); var binaryData = data.slice(20 + contentLength, length); buffers = gltf.buffers; - if (defined(buffers) && buffers.length > 0) { - var binaryGltfBuffer = buffers[0]; + if (defined(buffers) && Object.keys(buffers).length > 0) { + var binaryGltfBuffer = buffers.binary_glTF; if (defined(binaryGltfBuffer)) { - binaryGltfBuffer.extras._pipeline.source = binaryData; + binaryGltfBuffer.extras = { + _pipeline: { + source: binaryData + } + }; } } + // Update to glTF 2.0 + updateVersion(gltf); + // Remove the KHR_binary_glTF extension + removeExtensionsUsed(gltf, 'KHR_binary_glTF'); + addPipelineExtras(gltf); } // Load binary glTF version 2 diff --git a/lib/quantizeAttributes.js b/lib/quantizeAttributes.js index 5596a49d..499f221f 100644 --- a/lib/quantizeAttributes.js +++ b/lib/quantizeAttributes.js @@ -1,15 +1,14 @@ 'use strict'; var Cesium = require('cesium'); -var WebGLConstants = Cesium.WebGLConstants; -var defaultValue = Cesium.defaultValue; -var defined = Cesium.defined; - var AccessorReader = require('./AccessorReader'); - var addExtensionsRequired = require('./addExtensionsRequired'); var findAccessorMinMax = require('./findAccessorMinMax'); +var ForEach = require('./ForEach'); var numberOfComponentsForType = require('./numberOfComponentsForType'); -var uninterleaveAndPackBuffers = require('./uninterleaveAndPackBuffers'); + +var WebGLConstants = Cesium.WebGLConstants; +var defaultValue = Cesium.defaultValue; +var defined = Cesium.defined; module.exports = quantizeAttributes; @@ -142,8 +141,6 @@ function quantizeAttributes(gltf, options) { } } if (isQuantized) { - // Repack the buffers - uninterleaveAndPackBuffers(gltf); // Finalize addExtensionsRequired(gltf, 'WEB3D_quantized_attributes'); } @@ -194,38 +191,24 @@ function createDecodeMatrix5(min, max, range) { function getAllQuantizableAttributes(gltf, validSemantics, excludeSemantics) { var accessors = gltf.accessors; - var meshes = gltf.meshes; var visitedAccessors = {}; var accessorAttributes = {}; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - if (defined(primitives)) { - for (var i = 0; i < primitives.length; i++) { - var primitive = primitives[i]; - var attributes = primitive.attributes; - if (defined(attributes)) { - for (var attribute in attributes) { - if (attributes.hasOwnProperty(attribute)) { - if ((!defined(validSemantics) && !defined(excludeSemantics)) || - isSemanticValid(attribute, validSemantics, excludeSemantics)) { - var accessorId = attributes[attribute]; - if (!defined(visitedAccessors[accessorId])) { - var accessor = accessors[accessorId]; - if (accessorIsQuantizable(accessor)) { - accessorAttributes[accessorId] = attribute; - } - visitedAccessors[accessorId] = true; - } - } - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + if ((!defined(validSemantics) && !defined(excludeSemantics)) || + isSemanticValid(semantic, validSemantics, excludeSemantics)) { + if (!defined(visitedAccessors[accessorId])) { + var accessor = accessors[accessorId]; + if (accessorIsQuantizable(accessor)) { + accessorAttributes[accessorId] = semantic; } + visitedAccessors[accessorId] = true; } } - } - } - } + }); + }); + }); return accessorAttributes; } diff --git a/lib/removeUnusedVertices.js b/lib/removeUnusedVertices.js index 9082f442..b3c23e88 100644 --- a/lib/removeUnusedVertices.js +++ b/lib/removeUnusedVertices.js @@ -9,7 +9,6 @@ var byteLengthForComponentType = require('./byteLengthForComponentType'); var createAccessorUsageTables = require('./createAccessorUsageTables'); var getAccessorByteStride = require('./getAccessorByteStride'); var numberOfComponentsForType = require('./numberOfComponentsForType'); -var uninterleaveAndPackBuffers = require('./uninterleaveAndPackBuffers'); module.exports = removeUnusedVertices; @@ -23,12 +22,10 @@ module.exports = removeUnusedVertices; * * @see addPipelineExtras * @see loadGltfUris - * @see uninterleaveAndPackBuffers */ function removeUnusedVertices(gltf) { if (defined(gltf.accessors) && defined(gltf.buffers) && defined(gltf.bufferViews) && defined(gltf.meshes)) { removeUnusedVerticesFromAccessors(gltf); - uninterleaveAndPackBuffers(gltf); } return gltf; } diff --git a/lib/uninterleaveAndPackBuffers.js b/lib/uninterleaveAndPackBuffers.js index 1771324b..53bf67df 100644 --- a/lib/uninterleaveAndPackBuffers.js +++ b/lib/uninterleaveAndPackBuffers.js @@ -8,8 +8,6 @@ var Remove = require('./Remove'); var writeBufferComponent = require('./writeBufferComponent'); var WebGLConstants = Cesium.WebGLConstants; -var defined = Cesium.defined; -var defaultValue = Cesium.defaultValue; module.exports = uninterleaveAndPackBuffers; @@ -62,6 +60,7 @@ function uninterleaveAndPackBuffers(gltf) { var components = []; var bufferView = gltf.bufferViews[accessor.bufferView]; var componentByteLength = byteLengthForComponentType(accessor.componentType); + var bytesWritten = 0; while (!reader.pastEnd()) { reader.read(components); @@ -81,28 +80,33 @@ function uninterleaveAndPackBuffers(gltf) { otherDataOffset += componentByteLength; break; } + bytesWritten += componentByteLength; } + reader.next(); } - // assign bufferViews since we're done reading + // assign bufferViews and offsets since we're done reading switch (bufferView.target) { case WebGLConstants.ARRAY_BUFFER: accessor.bufferView = 0; + accessor.byteOffset = arrayBufferDataOffset - bytesWritten; break; case WebGLConstants.ELEMENT_ARRAY_BUFFER: accessor.bufferView = 1; + accessor.byteOffset = elementArrayBufferDataOffset - bytesWritten; break; default: accessor.bufferView = 2; + accessor.byteOffset = otherDataOffset - bytesWritten; break; } - reader.next(); }); var buffers = [{ byteLength: bufferData.length, extras: { _pipeline: { - source: bufferData + source: bufferData, + extension: '.bin' } } }]; @@ -127,15 +131,15 @@ function uninterleaveAndPackBuffers(gltf) { gltf.bufferViews = bufferViews; var removed = 0; - if (arrayBufferDataLength > 0) { + if (arrayBufferDataLength === 0) { Remove.bufferView(gltf, 0); removed++; } - if (elementArrayBufferDataLength > 0) { + if (elementArrayBufferDataLength === 0) { Remove.bufferView(gltf, 1 - removed); removed++; } - if (otherDataLength > 0) { + if (otherDataLength === 0) { Remove.bufferView(gltf, 2 - removed); } } \ No newline at end of file diff --git a/lib/updateVersion.js b/lib/updateVersion.js index e5177b3e..1fb4b0a1 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -256,7 +256,7 @@ function objectsToArrays(gltf) { if (defined(extensions)) { var binaryGltf = extensions.KHR_binary_glTF; if (defined(binaryGltf)) { - shader.bufferView = binaryGltf.bufferView; + shader.bufferView = globalMapping.bufferViews[binaryGltf.bufferView]; delete extensions.KHR_binary_glTF; } if (Object.keys(extensions).length === 0) { @@ -386,7 +386,7 @@ function objectsToArrays(gltf) { } } else if (typeof value === 'string') { - material.value[name] = globalMapping.textures[value]; + material.values[name] = [globalMapping.textures[value]]; } }); }); @@ -395,7 +395,7 @@ function objectsToArrays(gltf) { if (defined(extensions)) { var binaryGltf = extensions.KHR_binary_glTF; if (defined(binaryGltf)) { - image.bufferView = binaryGltf.bufferView; + image.bufferView = globalMapping.bufferViews[binaryGltf.bufferView]; image.mimeType = binaryGltf.mimeType; delete extensions.KHR_binary_glTF; } diff --git a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf index 60f6005f..400bdefa 100644 --- a/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf +++ b/specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf @@ -63,11 +63,6 @@ ], "animations": [], "asset": { - "premultipliedAlpha": true, - "profile": { - "api": "WebGL", - "version": "1.0" - }, "version": "2.0" }, "bufferViews": [ @@ -87,7 +82,6 @@ "buffers": [ { "byteLength": 840, - "type": "arraybuffer", "uri": "CesiumTexturedBoxTest.bin" } ], @@ -156,7 +150,7 @@ }, { "children": [ - "txtrLocator026Node" + 3 ], "matrix": [ 1, @@ -180,8 +174,8 @@ }, { "children": [ - "Geometry-mesh002Node", - "groupLocator030Node" + 0, + 1 ], "matrix": [ 1, diff --git a/specs/lib/PipelineSpec.js b/specs/lib/PipelineSpec.js index 2925fc01..e26b9c3e 100644 --- a/specs/lib/PipelineSpec.js +++ b/specs/lib/PipelineSpec.js @@ -32,7 +32,7 @@ describe('Pipeline', function() { .then(function(gltf) { expect(gltf).toBeDefined(); expect(clone(gltf)).not.toEqual(gltfCopy); - expect(gltf.scenes.defaultScene.extras).toBeUndefined(); + expect(gltf.scenes[0].extras).toBeUndefined(); }), done).toResolve(); }); @@ -50,7 +50,7 @@ describe('Pipeline', function() { .then(function(gltf) { expect(gltf).toBeDefined(); expect(clone(gltf)).not.toEqual(gltfCopy); - expect(gltf.scenes.defaultScene.extras).toBeUndefined(); + expect(gltf.scenes[0].extras).toBeUndefined(); }), done).toResolve(); }); @@ -64,11 +64,11 @@ describe('Pipeline', function() { .then(function(gltf) { expect(gltf).toBeDefined(); expect(clone(gltf)).not.toEqual(gltfCopy); - expect(gltf.scenes.defaultScene.extras).toBeUndefined(); + expect(gltf.scenes[0].extras).toBeUndefined(); }), done).toResolve(); }); - it('optimizes a glb file', function(done) { + fit('optimizes a glb file', function(done) { var gltfCopy; expect(readGltf(glbPath) .then(function(gltf) { @@ -78,7 +78,7 @@ describe('Pipeline', function() { .then(function(gltf) { expect(gltf).toBeDefined(); expect(clone(gltf)).not.toEqual(gltfCopy); - expect(gltf.scenes.defaultScene.extras).toBeUndefined(); + expect(gltf.scenes[0].extras).toBeUndefined(); }), done).toResolve(); }); @@ -134,12 +134,11 @@ describe('Pipeline', function() { var initialUri; expect(readGltf(gltfEmbeddedPath) .then(function(gltf) { - initialUri = gltf.buffers.CesiumTexturedBoxTest.uri; + initialUri = gltf.buffers[0].uri; return processJSON(gltf); }) .then(function(gltf) { - var firstBufferId = Object.keys(gltf.buffers)[0]; - var testBuffer = gltf.buffers[firstBufferId]; + var testBuffer = gltf.buffers[0]; var finalUri = testBuffer.uri; expect(initialUri).not.toEqual(finalUri); }), done).toResolve(); @@ -149,12 +148,11 @@ describe('Pipeline', function() { var initialUri; expect(readGltf(gltfEmbeddedPath) .then(function(gltf) { - initialUri = gltf.buffers.CesiumTexturedBoxTest.uri; + initialUri = gltf.buffers[0].uri; return processFile(gltfEmbeddedPath); }) .then(function(gltfFinal) { - var firstBufferId = Object.keys(gltfFinal.buffers)[0]; - var testBuffer = gltfFinal.buffers[firstBufferId]; + var testBuffer = gltfFinal.buffers[0]; var finalUri = testBuffer.uri; expect(initialUri).not.toEqual(finalUri); }), done).toResolve(); diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index b57e350e..38aa9f13 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -74,10 +74,6 @@ describe('addDefaults', function() { addDefaults(gltf); expect(gltf.asset).toBeDefined(); - expect(gltf.asset.premultipliedAlpha).toEqual(false); - expect(gltf.asset.profile).toBeDefined(); - expect(gltf.asset.profile.api).toEqual('WebGL'); - expect(gltf.asset.profile.version).toEqual('1.0'); }); it('Adds buffer properties', function() { @@ -141,23 +137,23 @@ describe('addDefaults', function() { it('generates a material with alpha blending if the diffuse texture is transparent and no technique or extension values are given', function(done) { var gltf = { - "textures": [{ - "format": 6408, - "internalFormat": 6408, - "sampler": 0, - "source": 0, - "target": 3553, - "type": 5121 + textures: [{ + format: 6408, + internalFormat: 6408, + sampler: 0, + source: 0, + target: 3553, + type: 5121 }], - "images": [{ - "name": "Image0001", - "uri": transparentImageUri + images: [{ + name: 'Image0001', + uri: transparentImageUri }], - "materials": [{ - "values": { - "ambient": [0, 0, 0, 1], - "diffuse": [0], - "emission": [1, 0, 0, 1] + materials: [{ + values: { + ambient: [0, 0, 0, 1], + diffuse: [0], + emission: [1, 0, 0, 1] } }] }; diff --git a/specs/lib/addPipelineExtrasSpec.js b/specs/lib/addPipelineExtrasSpec.js index 45dcda77..04b8b1e8 100644 --- a/specs/lib/addPipelineExtrasSpec.js +++ b/specs/lib/addPipelineExtrasSpec.js @@ -24,7 +24,6 @@ describe('addPipelineExtras', function() { expect(gltf.animations[0].channels[0].target.extras._pipeline).toBeDefined(); expect(gltf.animations[0].samplers[0].extras._pipeline).toBeDefined(); expect(gltf.asset.extras._pipeline).toBeDefined(); - expect(gltf.asset.profile.extras._pipeline).toBeDefined(); expect(gltf.extras._pipeline).toBeDefined(); expect(gltf.buffers[0].extras._pipeline).toBeDefined(); expect(gltf.bufferViews[0].extras._pipeline).toBeDefined(); @@ -62,17 +61,17 @@ describe('addPipelineExtras', function() { it('does not attempt to add extras to null objects', function() { gltf.accessors.push({ - "bufferView": "bufferView_29", - "byteOffset": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR", - "min": [ + bufferView: 0, + byteOffset: 0, + componentType: 5123, + count: 36, + type: 'SCALAR', + min: [ null, null, null ], - "max": [ + max: [ null, null, null diff --git a/specs/lib/compressIntegerAccessorsSpec.js b/specs/lib/compressIntegerAccessorsSpec.js index 8ce049f2..9d23268d 100644 --- a/specs/lib/compressIntegerAccessorsSpec.js +++ b/specs/lib/compressIntegerAccessorsSpec.js @@ -1,11 +1,10 @@ 'use strict'; var Cesium = require('cesium'); var clone = require('clone'); +var compressIntegerAccessors = require('../../lib/compressIntegerAccessors'); var WebGLConstants = Cesium.WebGLConstants; -var compressIntegerAccessors = require('../../lib/compressIntegerAccessors'); - var cantCompressByte = new Buffer([-1, 0, 1]); var cantCompressUByte = new Buffer([0, 1, 2]); var cantCompressIndices = new Buffer(new Uint16Array([1, 2, 3]).buffer); @@ -14,185 +13,167 @@ var floatToShort = new Buffer(new Float32Array([32767.0, -1.0, 0.0]).buffer); var floatToByte = new Buffer(new Float32Array([255.0, -1.0, 0.0]).buffer); var shortToByte = new Buffer(new Uint16Array([-2, 0, 2]).buffer); var testGltf = { - accessors : { - cantCompressByte : { - bufferView : 'cantCompressByteBufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.BYTE, count : 3, - type : "SCALAR" - }, - cantCompressUByte : { - bufferView : 'cantCompressUByteBufferView', + type : 'SCALAR', + name: 'cantCompressByte' + }, { + bufferView : 1, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.UNSIGNED_BYTE, count : 3, - type : "SCALAR" - }, - cantCompressIndices : { - bufferView : 'cantCompressIndicesBufferView', + type : 'SCALAR', + name: 'cantCompressUByte' + }, { + bufferView : 2, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : 3, - type : "SCALAR" - }, - cantCompressBigShort : { - bufferView : 'cantCompressBigShortBufferView', + type : 'SCALAR', + name: 'cantCompressIndices' + }, { + bufferView : 3, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : 3, - type : "SCALAR" - }, - floatToShort : { - bufferView : 'floatToShortBufferView', + type : 'SCALAR', + name: 'cantCompressBigShort' + }, { + bufferView : 4, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.FLOAT, count : 3, - type : "SCALAR" - }, - floatToByte : { - bufferView : 'floatToByteBufferView', + type : 'SCALAR', + name: 'floatToShort' + }, { + bufferView : 5, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.FLOAT, count : 3, - type : "SCALAR" - }, - shortToByte : { - bufferView : 'shortToByteBufferView', + type : 'SCALAR', + name: 'floatToByte' + }, { + bufferView : 6, byteOffset : 0, byteStride : 0, componentType : WebGLConstants.SHORT, count : 3, - type : "SCALAR" + type : 'SCALAR', + name: 'shortToByte' } - }, - bufferViews : { - cantCompressByteBufferView : { - buffer : 'cantCompressByteBuffer', + ], + bufferViews : [ + { + buffer : 0, byteOffset : 0, byteLength : cantCompressByte.length, target : WebGLConstants.ARRAY_BUFFER - }, - cantCompressUByteBufferView : { - buffer : 'cantCompressUByteBuffer', + }, { + buffer : 1, byteOffset : 0, byteLength : cantCompressUByte.length, target : WebGLConstants.ARRAY_BUFFER - }, - cantCompressIndicesBufferView : { - buffer : 'cantCompressIndicesBuffer', + }, { + buffer : 2, byteOffset : 0, byteLength : cantCompressIndices.length, target : WebGLConstants.ELEMENT_ARRAY_BUFFER - }, - cantCompressBigShortBufferView : { - buffer : 'cantCompressBigShortBuffer', + }, { + buffer : 3, byteOffset : 0, byteLength : cantCompressBigShort.length, target : WebGLConstants.ARRAY_BUFFER - }, - floatToShortBufferView : { - buffer : 'floatToShortBuffer', + }, { + buffer : 4, byteOffset : 0, byteLength : floatToShort.length, target : WebGLConstants.ARRAY_BUFFER - }, - floatToByteBufferView : { - buffer : 'floatToByteBuffer', + }, { + buffer : 5, byteOffset : 0, byteLength : floatToByte.length, target : WebGLConstants.ARRAY_BUFFER - }, - shortToByteBufferView : { - buffer : 'shortToByteBuffer', + }, { + buffer : 6, byteOffset : 0, byteLength : shortToByte.length, target : WebGLConstants.ARRAY_BUFFER } - }, - buffers : { - cantCompressByteBuffer : { + ], + buffers : [ + { byteLength : cantCompressByte.length, extras : { _pipeline : { source : cantCompressByte } - }, - type : "arraybuffer" - }, - cantCompressUByteBuffer : { + } + }, { byteLength : cantCompressUByte.length, extras : { _pipeline : { source : cantCompressUByte } - }, - type : "arraybuffer" - }, - cantCompressIndicesBuffer : { + } + }, { byteLength : cantCompressIndices.length, extras : { _pipeline : { source : cantCompressIndices } - }, - type : "arraybuffer" - }, - cantCompressBigShortBuffer : { + } + }, { byteLength : cantCompressBigShort.length, extras : { _pipeline : { source : cantCompressBigShort } - }, - type : "arraybuffer" - }, - floatToShortBuffer : { + } + }, { byteLength : floatToShort.length, extras : { _pipeline : { source : floatToShort } - }, - type : "arraybuffer" - }, - floatToByteBuffer : { + } + }, { byteLength : floatToByte.length, extras : { _pipeline : { source : floatToByte } - }, - type : "arraybuffer" - }, - shortToByteBuffer : { + } + }, { byteLength : shortToByte.length, extras : { _pipeline : { source : shortToByte } - }, - type : "arraybuffer" + } } - }, + ], meshes : { mesh : { primitives : [ { attributes : { - A : 'cantCompressByte', - B : 'cantCompressUByte', - C : 'cantCompressIndices', - D : 'cantCompressBigShort', - E : 'floatToShort', - F : 'floatToByte', - G : 'shortToByte' + A : 0, + B : 1, + C : 2, + D : 3, + E : 4, + F : 5, + G : 6 } } ] @@ -206,18 +187,18 @@ describe('compressIntegerAccessors', function() { compressIntegerAccessors(gltf, { semantics : ['A', 'B', 'C', 'D', 'E', 'F', 'G'] }); - expect(gltf.accessors.cantCompressByte.componentType === WebGLConstants.BYTE); - expect(gltf.accessors.cantCompressUByte.componentType === WebGLConstants.UNSIGNED_BYTE); - expect(gltf.accessors.cantCompressIndices.componentType === WebGLConstants.UNSIGNED_SHORT); - expect(gltf.accessors.cantCompressBigShort.componentType === WebGLConstants.UNSIGNED_SHORT); + expect(gltf.accessors[0].componentType === WebGLConstants.BYTE); + expect(gltf.accessors[1].componentType === WebGLConstants.UNSIGNED_BYTE); + expect(gltf.accessors[2].componentType === WebGLConstants.UNSIGNED_SHORT); + expect(gltf.accessors[3].componentType === WebGLConstants.UNSIGNED_SHORT); - expect(gltf.accessors.floatToShort.componentType === WebGLConstants.UNSIGNED_SHORT); - expect(gltf.buffers.floatToShortBuffer.extras._pipeline.source.length === 3 * 2); + expect(gltf.accessors[4].componentType === WebGLConstants.UNSIGNED_SHORT); + expect(gltf.buffers[4].extras._pipeline.source.length === 3 * 2); - expect(gltf.accessors.floatToByte.componentType === WebGLConstants.BYTE); - expect(gltf.buffers.floatToByteBuffer.extras._pipeline.source.length === 3); + expect(gltf.accessors[5].componentType === WebGLConstants.BYTE); + expect(gltf.buffers[5].extras._pipeline.source.length === 3); - expect(gltf.accessors.shortToByte.componentType === WebGLConstants.BYTE); - expect(gltf.buffers.floatToByteBuffer.extras._pipeline.source.length === 3); + expect(gltf.accessors[6].componentType === WebGLConstants.BYTE); + expect(gltf.buffers[6].extras._pipeline.source.length === 3); }); }); diff --git a/specs/lib/compressTextureCoordinatesSpec.js b/specs/lib/compressTextureCoordinatesSpec.js index 95dee89e..4d7f3790 100644 --- a/specs/lib/compressTextureCoordinatesSpec.js +++ b/specs/lib/compressTextureCoordinatesSpec.js @@ -1,23 +1,24 @@ 'use strict'; var Cesium = require('cesium'); var compressTextureCoordinates = require('../../lib/compressTextureCoordinates'); +var uninterleaveAndPackBuffers = require('../../lib/uninterleaveAndPackBuffers'); var AttributeCompression = Cesium.AttributeCompression; var Cartesian2 = Cesium.Cartesian2; var WebGLConstants = Cesium.WebGLConstants; describe('compressTextureCoordinates', function() { - it('compresses texture coordinates', function(done) { + it('compresses texture coordinates', function() { var texCoords = new Float32Array([1.0, 0.0, 0.0, 1.0, 0.5, 0.5]); var texCoordBuffer = new Buffer(texCoords.buffer.slice(0)); var gltf = { - accessors : { - texCoordAccessor : { + accessors : [ + { byteOffset : 0, byteStride : 0, - bufferView : 'bufferView', + bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, max : [ @@ -28,9 +29,9 @@ describe('compressTextureCoordinates', function() { ], type : 'VEC2' } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : texCoordBuffer.length, extras : { _pipeline : { @@ -38,33 +39,33 @@ describe('compressTextureCoordinates', function() { } } } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : texCoordBuffer.length, byteOffset : 0 } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - TEXCOORD_0 : 'texCoordAccessor' + TEXCOORD_0 : 0 }, - material : 'material' + material : 0 } ] } - }, - materials : { - material : { - technique : 'technique' + ], + materials : [ + { + technique : 0 } - }, - techniques : { - technique : { + ], + techniques : [ + { attributes : { a_texcoord : 'texcoord' }, @@ -74,19 +75,19 @@ describe('compressTextureCoordinates', function() { type : WebGLConstants.FLOAT_VEC2 } }, - program : 'program' + program : 0 } - }, - programs : { - program : { + ], + programs : [ + { attributes : [ 'a_texcoord' ], - vertexShader : 'VS' + vertexShader : 0 } - }, - shaders : { - VS : { + ], + shaders : [ + { type : WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { @@ -94,36 +95,35 @@ describe('compressTextureCoordinates', function() { } } } - } + ] }; - compressTextureCoordinates(gltf).then(function() { - var texCoordAccessor = gltf.accessors.texCoordAccessor; - expect(texCoordAccessor.componentType).toEqual(WebGLConstants.FLOAT); - expect(texCoordAccessor.type).toEqual('SCALAR'); + compressTextureCoordinates(gltf); + uninterleaveAndPackBuffers(gltf); + var texCoordAccessor = gltf.accessors[0]; + expect(texCoordAccessor.componentType).toEqual(WebGLConstants.FLOAT); + expect(texCoordAccessor.type).toEqual('SCALAR'); - var technique = gltf.techniques.technique; - expect(technique.parameters.texcoord.type).toEqual(WebGLConstants.FLOAT); + var technique = gltf.techniques[0]; + expect(technique.parameters.texcoord.type).toEqual(WebGLConstants.FLOAT); - var buffer = gltf.buffers.buffer; - var encodedBuffer = buffer.extras._pipeline.source; - expect(encodedBuffer.length).toEqual(12); - expect(encodedBuffer.length).toEqual(buffer.byteLength); + var buffer = gltf.buffers[0]; + var encodedBuffer = buffer.extras._pipeline.source; + expect(encodedBuffer.length).toEqual(12); + expect(encodedBuffer.length).toEqual(buffer.byteLength); - var vs = gltf.shaders.VS.extras._pipeline.source; - expect(typeof vs).toEqual('string'); + var vs = gltf.shaders[0].extras._pipeline.source; + expect(typeof vs).toEqual('string'); - var texCoord = new Cartesian2(); - for (var i = 0; i < texCoordAccessor.count; i++) { - var encoded = encodedBuffer.readFloatLE(i * 4); - AttributeCompression.decompressTextureCoordinates(encoded, texCoord); - expect(texCoord.x).toBeCloseTo(texCoords[i * 2]); - expect(texCoord.y).toBeCloseTo(texCoords[i * 2 + 1]); - } - done(); - }); + var texCoord = new Cartesian2(); + for (var i = 0; i < texCoordAccessor.count; i++) { + var encoded = encodedBuffer.readFloatLE(i * 4); + AttributeCompression.decompressTextureCoordinates(encoded, texCoord); + expect(texCoord.x).toBeCloseTo(texCoords[i * 2]); + expect(texCoord.y).toBeCloseTo(texCoords[i * 2 + 1]); + } }); - it('should only patch a program whos shader has not been patched yet', function(done) { + it('should only patch a program whos shader has not been patched yet', function() { var texCoords = new Float32Array([ 1.0, 0.0, 0.0, 1.0, @@ -137,11 +137,11 @@ describe('compressTextureCoordinates', function() { ]); var texCoordBuffer = new Buffer(texCoords.buffer.slice(0)); var gltf = { - accessors : { - texCoordAccessor_1 : { + accessors : [ + { byteOffset : 0, byteStride : 0, - bufferView : 'bufferView', + bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, max : [ @@ -151,11 +151,10 @@ describe('compressTextureCoordinates', function() { 0.0, 0.0 ], type : 'VEC2' - }, - texCoordAccessor_2 : { + }, { byteOffset : 0, byteStride : 0, - bufferView : 'bufferView', + bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, max : [ @@ -165,11 +164,10 @@ describe('compressTextureCoordinates', function() { 0.0, 0.0 ], type : 'VEC2' - }, - texCoordAccessor_3 : { + }, { byteOffset : 0, byteStride : 0, - bufferView : 'bufferView', + bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, max : [ @@ -180,9 +178,9 @@ describe('compressTextureCoordinates', function() { ], type : 'VEC2' } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : texCoordBuffer.length, extras : { _pipeline : { @@ -190,51 +188,47 @@ describe('compressTextureCoordinates', function() { } } } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : texCoordBuffer.length, byteOffset : 0 } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - TEXCOORD_0 : 'texCoordAccessor_1' + TEXCOORD_0 : 0 }, - material : 'material_1' - }, - { + material : 0 + }, { attributes : { - TEXCOORD_0 : 'texCoordAccessor_2' + TEXCOORD_0 : 1 }, - material : 'material_2' - }, - { + material : 1 + }, { attributes : { - TEXCOORD_0 : 'texCoordAccessor_3' + TEXCOORD_0 : 2 }, - material : 'material_3' + material : 2 } ] } - }, - materials : { - material_1 : { - technique : 'technique_1' - }, - material_2 : { - technique : 'technique_2' - }, - material_3 : { - technique : 'technique_3' + ], + materials : [ + { + technique : 0 + }, { + technique : 1 + }, { + technique : 2 } - }, - techniques : { - technique_1 : { + ], + techniques : [ + { attributes : { a_texcoord : 'texcoord' }, @@ -244,9 +238,8 @@ describe('compressTextureCoordinates', function() { type : WebGLConstants.FLOAT_VEC2 } }, - program : 'program_1' - }, - technique_2 : { + program : 0 + }, { attributes : { a_texcoord : 'texcoord' }, @@ -256,9 +249,8 @@ describe('compressTextureCoordinates', function() { type : WebGLConstants.FLOAT_VEC2 } }, - program : 'program_2' - }, - technique_3 : { + program : 1 + }, { attributes : { a_texcoord : 'texcoord' }, @@ -268,39 +260,36 @@ describe('compressTextureCoordinates', function() { type : WebGLConstants.FLOAT_VEC2 } }, - program : 'program_3' + program : 2 } - }, - programs : { - program_1 : { + ], + programs : [ + { attributes : [ 'a_texcoord' ], - vertexShader : 'VS_1' - }, - program_2 : { + vertexShader : 0 + }, { attributes : [ 'a_texcoord' ], - vertexShader : 'VS_2' - }, - program_3 : { + vertexShader : 1 + }, { attributes : [ 'a_texcoord' ], - vertexShader : 'VS_1' + vertexShader : 0 } - }, - shaders : { - VS_1 : { + ], + shaders : [ + { type: WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { source : '' } } - }, - VS_2 : { + }, { type: WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { @@ -308,13 +297,10 @@ describe('compressTextureCoordinates', function() { } } } - } + ] }; - spyOn(Cesium.ShaderSource, 'replaceMain'); - compressTextureCoordinates(gltf).then(function() { - expect(Cesium.ShaderSource.replaceMain).toHaveBeenCalledTimes(2); - done(); - }); + compressTextureCoordinates(gltf); + expect(Cesium.ShaderSource.replaceMain).toHaveBeenCalledTimes(2); }); }); \ No newline at end of file diff --git a/specs/lib/compressTexturesSpec.js b/specs/lib/compressTexturesSpec.js index 9d75dd1f..95f5fed2 100644 --- a/specs/lib/compressTexturesSpec.js +++ b/specs/lib/compressTexturesSpec.js @@ -481,15 +481,24 @@ describe('compressTextures', function() { }; expect(fsExtraReadJson(gltfPath) .then(function(gltf) { - var sampler = gltf.samplers.sampler_0; + var sampler = gltf.samplers[0]; expect(sampler.minFilter).toBe(WebGLConstants.LINEAR_MIPMAP_LINEAR); var pipelineOptions = { textureCompressionOptions : options, basePath : basePath }; - return Pipeline.processJSON(gltf, pipelineOptions) + addPipelineExtras(gltf); + addDefaults(gltf); + return loadGltfUris(gltf, pipelineOptions) + .then(function() { + return compressTextures(gltf, options); + }) + .then(function() { + return writeSource(gltf.images, 'images', undefined, true, true); + }) .then(function() { expect(sampler.minFilter).toBe(WebGLConstants.LINEAR); + }); }), done).toResolve(); }); @@ -509,15 +518,15 @@ describe('compressTextures', function() { expect(readGltf(gltfEmbeddedPath) .then(function(gltf) { var images = gltf.images; - expect(Object.keys(images).length).toBe(1); + expect(images.length).toEqual(1); return compressTextures(gltf, optionsArray) .then(function() { - var image = gltf.images.Image0001; + var image = gltf.images[0]; var compressedImages = image.extras.compressedImage3DTiles; - var s3tcImagePipelineExtras = compressedImages.s3tc.extras._pipeline; - var astcImagePipelineExtras = compressedImages.astc.extras._pipeline; - var crunchImagePipelineExtras = compressedImages.crunch.extras._pipeline; - expect(image.uri).toBe(defaultImageUri); + var s3tcImagePipelineExtras = compressedImages[0].extras._pipeline; + var astcImagePipelineExtras = compressedImages[1].extras._pipeline; + var crunchImagePipelineExtras = compressedImages[2].extras._pipeline; + expect(image.uri).toEqual(defaultImageUri); expect(s3tcImagePipelineExtras.source).toBeDefined(); expect(s3tcImagePipelineExtras.extension).toEqual('.ktx'); expect(astcImagePipelineExtras.source).toBeDefined(); diff --git a/specs/lib/generateTangentsBitangentsSpec.js b/specs/lib/generateTangentsBitangentsSpec.js index bc82d527..1bd9e140 100644 --- a/specs/lib/generateTangentsBitangentsSpec.js +++ b/specs/lib/generateTangentsBitangentsSpec.js @@ -1,45 +1,121 @@ 'use strict'; +var Cesium = require('cesium'); var clone = require('clone'); -var fs = require('fs'); -var readGltf = require('../../lib/readGltf'); var generateTangentsBitangents = require('../../lib/generateTangentsBitangents'); -var gltfNoTangentsBitangentsPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf'; -var gltfTangentsBitangentsPath = './specs/data/generateTangentsBitangents/CesiumTexturedBoxTest_TangentsBitangents.gltf'; +var WebGLConstants = Cesium.WebGLConstants; describe('generateTangentsBitangents', function(){ - var gltfNoTangentsBitangents; - var gltfTangentsBitangents; - - beforeAll(function(done) { - readGltf(gltfNoTangentsBitangentsPath) - .then(function(gltf) { - gltfNoTangentsBitangents = gltf; - return readGltf(gltfTangentsBitangentsPath); - }) - .then(function(gltf) { - gltfTangentsBitangents = gltf; - done(); - }); - }); - it('generates tangents and bitangents if they do not exist', function() { - var gltf = gltfNoTangentsBitangents; - var byteLengthBefore = 840; + var gltf = { + accessors: [ + { + byteOffset: 0, + bufferView: 0, + count: 4, + componentType: WebGLConstants.FLOAT, + type: 'VEC3' + }, { + byteOffset: 48, + bufferView: 0, + count: 4, + componentType: WebGLConstants.FLOAT, + type: 'VEC3' + }, { + byteOffset: 96, + bufferView: 0, + count: 4, + componentType: WebGLConstants.FLOAT, + type: 'VEC2' + }, { + byteOffset: 0, + bufferView: 1, + count: 6, + componentType: WebGLConstants.UNSIGNED_SHORT, + type: 'SCALAR' + } + ], + bufferViews: [ + { + byteOffset: 0, + byteLength: 128, + buffer: 0 + }, { + byteOffset: 128, + byteLength: 12, + buffer: 0 + } + ], + buffers: [ + { + byteLength: 140, + extras: { + _pipeline: { + source: Buffer.concat([ + new Buffer(new Float32Array([0, 0, 0, + 0, 1, 0, + 0, 0, 1, + 0, 1, 1 + ]).buffer), + new Buffer(new Float32Array([1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0]).buffer), + new Buffer(new Float32Array([0, 0, + 1, 0, + 0, 1, + 1, 1]).buffer), + new Buffer(new Uint16Array([0, 1, 2, 2, 1, 3]).buffer) + ]) + } + } + } + ], + meshes: [ + { + primitives: [ + { + attributes: { + POSITION: 0, + NORMAL: 1, + TEXCOORD_0: 2 + }, + indices: 3, + mode: WebGLConstants.TRIANGLES + } + ] + } + ] + }; + var byteLengthBefore = gltf.buffers[0].byteLength; generateTangentsBitangents(gltf); - var attributes = gltf.meshes[Object.keys(gltf.meshes)[0]].primitives[0].attributes; - var byteLengthAfter = gltf.buffers[Object.keys(gltf.buffers)[0]].byteLength; + var attributes = gltf.meshes[0].primitives[0].attributes; + var byteLengthAfter = gltf.buffers[0].byteLength; expect(attributes.TANGENT).toBeDefined(); expect(attributes.BITANGENT).toBeDefined(); expect(gltf.accessors[attributes.TANGENT]).toBeDefined(); expect(gltf.accessors[attributes.BITANGENT]).toBeDefined(); - expect(byteLengthAfter).toBe(byteLengthBefore + 2 * 24 * 3 * 4); // 24 tangents and 24 bitangents are generated + expect(byteLengthAfter).toBe(byteLengthBefore + 4 * 12 + 4 * 12); // 4 tangents and 4 bitangents are generated }); it('does not generate tangents and bitangents if they already exist', function() { - var gltf = gltfTangentsBitangents; + var gltf = { + meshes: [{ + primitives: [{ + attributes: { + POSITION: 0, + NORMAL: 1, + TEXCOORD_0: 2, + TANGENT: 3, + BITANGENT: 4 + }, + indices: 5, + mode: WebGLConstants.TRIANGLES + }] + }] + }; var gltfCopy = clone(gltf); generateTangentsBitangents(gltf); expect(gltf.meshes).toEqual(gltfCopy.meshes); diff --git a/specs/lib/mergeDuplicateVerticesSpec.js b/specs/lib/mergeDuplicateVerticesSpec.js index 34e2d0cd..15bd80e1 100644 --- a/specs/lib/mergeDuplicateVerticesSpec.js +++ b/specs/lib/mergeDuplicateVerticesSpec.js @@ -1,6 +1,8 @@ 'use strict'; - +var AccessorReader = require('../../lib/AccessorReader'); var mergeDuplicateVertices = require('../../lib/mergeDuplicateVertices'); +var removeUnusedVertices = require('../../lib/removeUnusedVertices'); +var uninterleaveAndPackBuffers = require('../../lib/uninterleaveAndPackBuffers'); describe('mergeDuplicateVertices', function() { it('merges duplicate vertices', function() { @@ -8,67 +10,61 @@ describe('mergeDuplicateVertices', function() { var B = new Buffer(new Uint16Array([6, 7, 8, 9, 6, 7, 6, 7, 6, 7]).buffer); var C = new Buffer(new Uint16Array([0, 1, 2, 3, 4, 3, 2, 1, 0]).buffer); var gltf = { - accessors : { - accessorA : { - bufferView : 'bufferViewA', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : 5126, count : 5, type : 'VEC3' - }, - accessorB : { - bufferView : 'bufferViewB', + }, { + bufferView : 1, byteOffset : 0, byteStride : 0, componentType : 5123, count : 5, type : 'VEC2' - }, - accessorC : { - bufferView : 'bufferViewC', + }, { + bufferView : 2, byteOffset : 0, byteStride : 0, componentType : 5123, count : 9, type : 'SCALAR' } - }, - bufferViews : { - bufferViewA : { - buffer : 'bufferA', + ], + bufferViews : [ + { + buffer : 0, byteOffset : 0, byteLength : A.length - }, - bufferViewB : { - buffer : 'bufferB', + }, { + buffer : 1, byteOffset : 0, byteLength : B.length - }, - bufferViewC : { - buffer : 'bufferC', + }, { + buffer : 2, byteOffset : 0, byteLength : C.length } - }, - buffers : { - bufferA : { + ], + buffers : [ + { byteLength : A.length, extras : { _pipeline : { source : A } } - }, - bufferB : { + }, { byteLength : B.length, extras : { _pipeline : { source : B } } - }, - bufferC : { + }, { byteLength : C.length, extras : { _pipeline : { @@ -76,28 +72,35 @@ describe('mergeDuplicateVertices', function() { } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - A : 'accessorA', - B : 'accessorB' + A : 0, + B : 1, }, - indices : 'accessorC' + indices : 2 } ] } - } + ] }; mergeDuplicateVertices(gltf); - var source = new Uint8Array(gltf.buffers.bufferC.extras._pipeline.source); - var indices = new Uint16Array(source.buffer); - // 3 and 4 are unused - expect(indices).toEqual(new Uint16Array([0, 1, 0, 2, 0, 2, 0, 1, 0])); - expect(gltf.buffers.bufferA.byteLength).toEqual(A.length - 24); - expect(gltf.buffers.bufferB.byteLength).toEqual(B.length - 8); + removeUnusedVertices(gltf); + uninterleaveAndPackBuffers(gltf); + var reader = new AccessorReader(gltf, gltf.accessors[2]); + var component = []; + var expectIndices = [0, 1, 0, 2, 0, 2, 0, 1, 0]; + var i = 0; + while (!reader.pastEnd()) { + reader.read(component); + expect(component[0]).toEqual(expectIndices[i]); + reader.next(); + i++; + } + expect(gltf.buffers[0].byteLength).toEqual(A.length - 24 + B.length - 8 + C.length); }); it('merges duplicate vertices with repeated index accessors', function() { @@ -107,109 +110,97 @@ describe('mergeDuplicateVertices', function() { var B2 = new Buffer(new Uint16Array([10, 11, 12, 13, 10, 11, 10, 11, 10, 11]).buffer); var C = new Buffer(new Uint16Array([0, 1, 2, 3, 4, 3, 2, 1, 0]).buffer); var gltf = { - accessors : { - accessorA : { - bufferView : 'bufferViewA', + accessors : [ + { + bufferView : 0, byteOffset : 0, byteStride : 0, componentType : 5126, count : 5, type : 'VEC3' - }, - accessorA2 : { - bufferView : 'bufferViewA2', + }, { + bufferView : 1, byteOffset : 0, byteStride : 0, componentType : 5126, count : 5, type : 'VEC3' - }, - accessorB : { - bufferView : 'bufferViewB', + }, { + bufferView : 2, byteOffset : 0, byteStride : 0, componentType : 5123, count : 5, type : 'VEC2' - }, - accessorB2 : { - bufferView : 'bufferViewB2', + }, { + bufferView : 3, byteOffset : 0, byteStride : 0, componentType : 5123, count : 5, type : 'VEC2' - }, - accessorC : { - bufferView : 'bufferViewC', + }, { + bufferView : 4, byteOffset : 0, byteStride : 0, componentType : 5123, count : 9, type : 'SCALAR' } - }, - bufferViews : { - bufferViewA : { - buffer : 'bufferA', + ], + bufferViews : [ + { + buffer : 0, byteOffset : 0, byteLength : A.length - }, - bufferViewA2 : { - buffer : 'bufferA2', + }, { + buffer : 1, byteOffset : 0, byteLength : A2.length - }, - bufferViewB : { - buffer : 'bufferB', + }, { + buffer : 2, byteOffset : 0, byteLength : B.length - }, - bufferViewB2 : { - buffer : 'bufferB2', + }, { + buffer : 3, byteOffset : 0, byteLength : B2.length - }, - bufferViewC : { - buffer : 'bufferC', + }, { + buffer : 4, byteOffset : 0, byteLength : C.length } - }, - buffers : { - bufferA : { + ], + buffers : [ + { byteLength : A.length, extras : { _pipeline : { source : A } } - }, - bufferA2 : { + }, { byteLength : A2.length, extras : { _pipeline : { source : A2 } } - }, - bufferB : { + }, { byteLength : B.length, extras : { _pipeline : { source : B } } - }, - bufferB2 : { + }, { byteLength : B2.length, extras : { _pipeline : { source : B2 } } - }, - bufferC : { + }, { byteLength : C.length, extras : { _pipeline : { @@ -217,34 +208,42 @@ describe('mergeDuplicateVertices', function() { } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - A : 'accessorA', - B : 'accessorB' + A : 0, + B : 2 }, - indices : 'accessorC' + indices : 4 }, { attributes : { - A : 'accessorA2', - B : 'accessorB2' + A : 1, + B : 3 }, - indices : 'accessorC' + indices : 4 } ] } - } + ] }; mergeDuplicateVertices(gltf); - var source = new Uint8Array(gltf.buffers.bufferC.extras._pipeline.source); - var indices = new Uint16Array(source.buffer); + removeUnusedVertices(gltf); + uninterleaveAndPackBuffers(gltf); // Only 4 is unused across the two primitives - expect(indices).toEqual(new Uint16Array([0, 1, 2, 3, 0, 3, 2, 1, 0])); - expect(gltf.buffers.bufferA.byteLength).toEqual(A.length - 12); - expect(gltf.buffers.bufferB.byteLength).toEqual(B.length - 4); + var reader = new AccessorReader(gltf, gltf.accessors[4]); + var component = []; + var expectIndices = [0, 1, 2, 3, 0, 3, 2, 1, 0]; + var i = 0; + while (!reader.pastEnd()) { + reader.read(component); + expect(component[0]).toEqual(expectIndices[i]); + reader.next(); + i++; + } + expect(gltf.buffers[0].byteLength).toEqual(A.length - 24 + B.length - 8 + A2.length + B2.length + C.length); }); }); \ No newline at end of file diff --git a/specs/lib/octEncodeNormalsSpec.js b/specs/lib/octEncodeNormalsSpec.js index 6dd8d1c3..8a09b00b 100644 --- a/specs/lib/octEncodeNormalsSpec.js +++ b/specs/lib/octEncodeNormalsSpec.js @@ -1,23 +1,25 @@ 'use strict'; var Cesium = require('cesium'); +var octEncodeNormals = require('../../lib/octEncodeNormals'); +var uninterleaveAndPackBuffers = require('../../lib/uninterleaveAndPackBuffers'); + var AttributeCompression = Cesium.AttributeCompression; var Cartesian2 = Cesium.Cartesian2; var Cartesian3 = Cesium.Cartesian3; var WebGLConstants = Cesium.WebGLConstants; -var octEncodeNormals = require('../../lib/octEncodeNormals'); describe('octEncodeNormals', function() { - it('oct-encodes normals', function(done) { + it('oct-encodes normals', function() { var normals = new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]); var normalBuffer = new Buffer(normals.buffer.slice(0)); var gltf = { - accessors : { - normalAccessor : { + accessors : [ + { byteOffset : 0, byteStride : 0, - bufferView : 'bufferView', + bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, max : [ @@ -28,9 +30,9 @@ describe('octEncodeNormals', function() { ], type : 'VEC3' } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : normalBuffer.length, extras : { _pipeline : { @@ -38,33 +40,33 @@ describe('octEncodeNormals', function() { } } } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : normalBuffer.length, byteOffset : 0 } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - NORMAL : 'normalAccessor' + NORMAL : 0 }, - material : 'material' + material : 0 } ] } - }, - materials : { - material : { - technique : 'technique' + ], + materials : [ + { + technique : 0 } - }, - techniques : { - technique : { + ], + techniques : [ + { attributes : { a_normal : 'normal' }, @@ -74,19 +76,19 @@ describe('octEncodeNormals', function() { type : WebGLConstants.FLOAT_VEC3 } }, - program : 'program' + program : 0 } - }, - programs : { - program : { + ], + programs : [ + { attributes : [ 'a_normal' ], - vertexShader : 'VS' + vertexShader : 0 } - }, - shaders : { - VS : { + ], + shaders : [ + { type: WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { @@ -94,47 +96,45 @@ describe('octEncodeNormals', function() { } } } - } + ] }; - octEncodeNormals(gltf).then(function() { - var normalAccessor = gltf.accessors.normalAccessor; - expect(normalAccessor.componentType).toEqual(WebGLConstants.UNSIGNED_BYTE); - expect(normalAccessor.type).toEqual('VEC2'); + octEncodeNormals(gltf); + uninterleaveAndPackBuffers(gltf); + var normalAccessor = gltf.accessors[0]; + expect(normalAccessor.componentType).toEqual(WebGLConstants.UNSIGNED_BYTE); + expect(normalAccessor.type).toEqual('VEC2'); - var technique = gltf.techniques.technique; - expect(technique.parameters.normal.type).toEqual(WebGLConstants.INT_VEC2); + var technique = gltf.techniques[0]; + expect(technique.parameters.normal.type).toEqual(WebGLConstants.INT_VEC2); - var buffer = gltf.buffers.buffer; - var encodedBuffer = buffer.extras._pipeline.source; - expect(encodedBuffer.length).toEqual(6); - expect(encodedBuffer.length).toEqual(buffer.byteLength); + var buffer = gltf.buffers[0]; + var encodedBuffer = buffer.extras._pipeline.source; + expect(encodedBuffer.length).toEqual(6); + expect(encodedBuffer.length).toEqual(buffer.byteLength); - var vs = gltf.shaders.VS.extras._pipeline.source; - expect(typeof vs).toEqual('string'); + var vs = gltf.shaders[0].extras._pipeline.source; + expect(typeof vs).toEqual('string'); - var normal = new Cartesian3(); - for (var i = 0; i < normalAccessor.count; i++) { - var compressed = Cartesian2.unpack(encodedBuffer, i*2); - AttributeCompression.octDecode(compressed.x, compressed.y, normal); - expect(normal.x).toBeCloseTo(normals[i*3]); - expect(normal.y).toBeCloseTo(normals[i*3 + 1]); - expect(normal.z).toBeCloseTo(normals[i*3 + 2]); - } - done(); - }); + var normal = new Cartesian3(); + for (var i = 0; i < normalAccessor.count; i++) { + var compressed = Cartesian2.unpack(encodedBuffer, i*2); + AttributeCompression.octDecode(compressed.x, compressed.y, normal); + expect(normal.x).toBeCloseTo(normals[i*3]); + expect(normal.y).toBeCloseTo(normals[i*3 + 1]); + expect(normal.z).toBeCloseTo(normals[i*3 + 2]); + } }); - it('should only patch a program whos shader has not been patched yet', function(done) { + it('should only patch a program whos shader has not been patched yet', function() { var normals = new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]); var normalBuffer = new Buffer(normals.buffer.slice(0)); var gltf = { - accessors : { - normalAccessor_1 : { + accessors : [{ byteOffset : 0, byteStride : 0, - bufferView : 'bufferView', + bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, max : [ @@ -144,11 +144,10 @@ describe('octEncodeNormals', function() { 0.0, 0.0, 0.0 ], type : 'VEC3' - }, - normalAccessor_2 : { + }, { byteOffset : 0, byteStride : 0, - bufferView : 'bufferView', + bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, max : [ @@ -158,11 +157,10 @@ describe('octEncodeNormals', function() { 0.0, 0.0, 0.0 ], type : 'VEC3' - }, - normalAccessor_3 : { + },{ byteOffset : 0, byteStride : 0, - bufferView : 'bufferView', + bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, max : [ @@ -173,9 +171,9 @@ describe('octEncodeNormals', function() { ], type : 'VEC3' } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : normalBuffer.length, extras : { _pipeline : { @@ -183,51 +181,47 @@ describe('octEncodeNormals', function() { } } } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : normalBuffer.length, byteOffset : 0 } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - NORMAL : 'normalAccessor_1' + NORMAL : 0 }, - material : 'material_1' - }, - { + material : 0 + }, { attributes : { - NORMAL : 'normalAccessor_2' + NORMAL : 1 }, - material : 'material_2' - }, - { + material : 1 + }, { attributes : { - NORMAL : 'normalAccessor_3' + NORMAL : 2 }, - material : 'material_3' + material : 2 } ] } - }, - materials : { - material_1 : { - technique : 'technique_1' - }, - material_2 : { - technique : 'technique_2' - }, - material_3 : { - technique : 'technique_3' + ], + materials : [ + { + technique : 0 + }, { + technique : 1 + }, { + technique : 2 } - }, - techniques : { - technique_1 : { + ], + techniques : [ + { attributes : { a_normal : 'normal' }, @@ -237,9 +231,8 @@ describe('octEncodeNormals', function() { type : WebGLConstants.FLOAT_VEC3 } }, - program : 'program_1' - }, - technique_2 : { + program : 0 + }, { attributes : { a_normal : 'normal' }, @@ -249,9 +242,8 @@ describe('octEncodeNormals', function() { type : WebGLConstants.FLOAT_VEC3 } }, - program : 'program_2' - }, - technique_3 : { + program : 1 + }, { attributes : { a_normal : 'normal' }, @@ -261,39 +253,36 @@ describe('octEncodeNormals', function() { type : WebGLConstants.FLOAT_VEC3 } }, - program : 'program_3' + program : 2 } - }, - programs : { - program_1 : { + ], + programs : [ + { attributes : [ 'a_normal' ], - vertexShader : 'VS_1' - }, - program_2 : { + vertexShader : 0 + }, { attributes : [ 'a_normal' ], - vertexShader : 'VS_1' - }, - program_3 : { + vertexShader : 0 + }, { attributes : [ 'a_normal' ], - vertexShader : 'VS_2' + vertexShader : 1 } - }, - shaders : { - VS_1 : { + ], + shaders : [ + { type: WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { source : '' } } - }, - VS_2 : { + }, { type: WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { @@ -301,13 +290,11 @@ describe('octEncodeNormals', function() { } } } - } + ] }; spyOn(Cesium.ShaderSource, 'replaceMain'); - octEncodeNormals(gltf).then(function() { - expect(Cesium.ShaderSource.replaceMain).toHaveBeenCalledTimes(2); - done(); - }); + octEncodeNormals(gltf); + expect(Cesium.ShaderSource.replaceMain).toHaveBeenCalledTimes(2); }); }); \ No newline at end of file diff --git a/specs/lib/parseBinaryGltfSpec.js b/specs/lib/parseBinaryGltfSpec.js index a242688e..e99e4e2d 100644 --- a/specs/lib/parseBinaryGltfSpec.js +++ b/specs/lib/parseBinaryGltfSpec.js @@ -37,31 +37,39 @@ describe('parseBinaryGltf', function() { it('loads binary glTF', function() { var binaryData = new Buffer([0, 1, 2, 3, 4, 5]); var gltf = { - buffers: { - binary_glTF: { - byteLength: binaryData.length - } - }, - images: { - image: { - extensions: { - KHR_binary_glTF: { - bufferView: 'imageBufferView', - mimeType: 'image/jpg' - } - } - } - }, - shaders: { - shader: { - extensions: { - KHR_binary_glTF: { - bufferView: 'shaderBufferView' - } - } - } - }, - extensionsUsed: ['KHR_binary_glTF'] + bufferViews: { + imageBufferView: { + byteLength: 0 + }, + shaderBufferView: { + byteLength: 0 + } + }, + buffers: { + binary_glTF: { + byteLength: binaryData.length + } + }, + images: { + image: { + extensions: { + KHR_binary_glTF: { + bufferView: 'imageBufferView', + mimeType: 'image/jpg' + } + } + } + }, + shaders: { + shader: { + extensions: { + KHR_binary_glTF: { + bufferView: 'shaderBufferView' + } + } + } + }, + extensionsUsed: ['KHR_binary_glTF'] }; var gltfString = JSON.stringify(gltf); while (gltfString.length % 4 !== 0) { @@ -84,11 +92,11 @@ describe('parseBinaryGltf', function() { } var image = parsedGltf.images[0]; expect(image.extensions).not.toBeDefined(); - expect(image.bufferView).toEqual('imageBufferView'); + expect(image.bufferView).toEqual(0); expect(image.mimeType).toEqual('image/jpg'); var shader = parsedGltf.shaders[0]; expect(shader.extensions).not.toBeDefined(); - expect(shader.bufferView).toEqual('shaderBufferView'); + expect(shader.bufferView).toEqual(1); }); }); diff --git a/specs/lib/quantizeAttributesSpec.js b/specs/lib/quantizeAttributesSpec.js index 3c87a467..1f850a53 100644 --- a/specs/lib/quantizeAttributesSpec.js +++ b/specs/lib/quantizeAttributesSpec.js @@ -1,17 +1,17 @@ 'use strict'; var clone = require('clone'); - var byteLengthForComponentType = require('../../lib/byteLengthForComponentType'); var numberOfComponentsForType = require('../../lib/numberOfComponentsForType'); var quantizeAttributes = require('../../lib/quantizeAttributes'); +var uninterleaveAndPackBuffers = require('../../lib/uninterleaveAndPackBuffers'); describe('quantizeAttributes', function() { var buffer = new Buffer(new Uint8Array(120)); var testGltf = { - accessors : { - // Interleaved accessors in bufferView_0 - accessor_0 : { - bufferView : 'bufferView_0', + accessors : [ + { + // Interleaved accessors in bufferView_0 + bufferView : 0, byteOffset : 0, byteStride : 18, componentType : 5126, @@ -19,9 +19,8 @@ describe('quantizeAttributes', function() { min : [-1.0, -1.0, -1.0], max : [1.0, 1.0, 1.0], type : 'VEC3' - }, - accessor_1 : { - bufferView : 'bufferView_0', + }, { + bufferView : 0, byteOffset : 12, byteStride : 18, componentType : 5123, @@ -29,10 +28,9 @@ describe('quantizeAttributes', function() { min : [-1.0, -1.0, -1.0], max : [1.0, 1.0, 1.0], type : 'VEC2' - }, - // Block accessors in bufferView_1 - accessor_2 : { - bufferView : 'bufferView_1', + }, { + // Block accessors in bufferView_1 + bufferView : 1, byteOffset : 0, byteStride : 12, componentType : 5126, @@ -40,10 +38,9 @@ describe('quantizeAttributes', function() { min : [-1.0, -1.0, -1.0], max : [1.0, 1.0, 1.0], type : 'VEC3' - }, - // Already quantized - accessor_3 : { - bufferView : 'bufferView_1', + }, { + // Already quantized + bufferView : 1, byteOffset : 36, componentType : 5126, count : 3, @@ -61,20 +58,18 @@ describe('quantizeAttributes', function() { decodeMax : [1.0, 1.0] } } - }, - // SCALAR attribute - accessor_4 : { - bufferView : 'bufferView_1', + }, { + // SCALAR attribute + bufferView : 1, byteOffset : 60, componentType : 5126, count : 3, min : [0], max : [1], type : 'SCALAR' - }, + }, { // floating-point rounding test - accessor_5 : { - bufferView : 'bufferView_2', + bufferView : 2, byteOffset : 0, componentType : 5126, count : 1, @@ -82,112 +77,114 @@ describe('quantizeAttributes', function() { max : [0.0026710000820457935], type : 'SCALAR' } - }, - bufferViews : { - bufferView_0 : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : 48, byteOffset : 0, target : 34962 }, - bufferView_1 : { - buffer : 'buffer', + { + buffer : 0, byteLength : 72, byteOffset : 48, target : 34962 }, - bufferView_2 : { - buffer : 'buffer_float', + { + buffer : 1, byteLength : 4, byteOffset : 0, target: 34962 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength : buffer.length, - type : 'arraybuffer', extras : { _pipeline : {} } }, - buffer_float : { + { byteLength : 4, - type : 'array_buffer', extras : { _pipeline : { source : new Buffer(new Float32Array([0.0026710000820457935]).buffer) } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - POSITION : 'accessor_0', - NORMAL : 'accessor_1' + POSITION : 0, + NORMAL : 1 } }, { attributes : { - POSITION : 'accessor_2', - TEXCOORD : 'accessor_3', - SCALAR_TEST : 'accessor_4' + POSITION : 2, + TEXCOORD : 3, + SCALAR_TEST : 4 } }, { attributes : { - FLOAT_TEST : 'accessor_5' + FLOAT_TEST : 5 } } ] } - } + ] }; it('Doesn\'t quantize if options.semantics is empty', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; + gltf.buffers[0].extras._pipeline.source = buffer; quantizeAttributes(gltf, {semantics: []}); - expect(gltf.buffers.buffer.byteLength).toEqual(buffer.length); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength).toEqual(buffer.length + 4); }); it('Doesn\'t quantize excluded semantics', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; + gltf.buffers[0].extras._pipeline.source = buffer; quantizeAttributes(gltf, {exclude: ['POSITION', 'NORMAL', 'TEXCOORD', 'SCALAR_TEST', 'FLOAT_TEST']}); - expect(gltf.buffers.buffer.byteLength).toEqual(buffer.length); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength).toEqual(buffer.length + 4); }); it('Quantizes attributes for semantic', function() { var gltf = clone(testGltf); - var accessor_0 = gltf.accessors.accessor_0; - var accessor_2 = gltf.accessors.accessor_2; + var accessor_0 = gltf.accessors[0]; + var accessor_2 = gltf.accessors[2]; var size = byteLengthForComponentType(accessor_0.componentType) * numberOfComponentsForType(accessor_0.type) * accessor_0.count; size += byteLengthForComponentType(accessor_2.componentType) * numberOfComponentsForType(accessor_2.type) * accessor_2.count; size = size/2.0; - gltf.buffers.buffer.extras._pipeline.source = buffer; + gltf.buffers[0].extras._pipeline.source = buffer; quantizeAttributes(gltf, {semantics: ['POSITION']}); - expect(gltf.buffers.buffer.byteLength + size).toEqual(buffer.length); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength + size).toEqual(buffer.length + 4); var decodeMatrix = accessor_0.extensions.WEB3D_quantized_attributes.decodeMatrix; expect(decodeMatrix[0]).toBe(2.0 / 65535.0); }); it('Quantizes attributes using options.normalized for higher precision decode', function() { var gltf = clone(testGltf); - var accessor_0 = gltf.accessors.accessor_0; - var accessor_2 = gltf.accessors.accessor_2; + var accessor_0 = gltf.accessors[0]; + var accessor_2 = gltf.accessors[2]; var size = byteLengthForComponentType(accessor_0.componentType) * numberOfComponentsForType(accessor_0.type) * accessor_0.count; size += byteLengthForComponentType(accessor_2.componentType) * numberOfComponentsForType(accessor_2.type) * accessor_2.count; size = size/2.0; - gltf.buffers.buffer.extras._pipeline.source = buffer; + gltf.buffers[0].extras._pipeline.source = buffer; quantizeAttributes(gltf, { semantics : ['POSITION'], normalized : true }); - expect(gltf.buffers.buffer.byteLength + size).toEqual(buffer.length); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength + size).toEqual(buffer.length + 4); expect(accessor_0.normalized).toBeTruthy(); expect(accessor_2.normalized).toBeTruthy(); var decodeMatrix = accessor_0.extensions.WEB3D_quantized_attributes.decodeMatrix; @@ -196,35 +193,38 @@ describe('quantizeAttributes', function() { it('Reduces the decimal places in decode matrix using options.precision', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; + gltf.buffers[0].extras._pipeline.source = buffer; var precision = 6; quantizeAttributes(gltf, {precision: precision}); - var matrixEntry = '' + gltf.accessors.accessor_0.extensions.WEB3D_quantized_attributes.decodeMatrix[0]; + var matrixEntry = '' + gltf.accessors[0].extensions.WEB3D_quantized_attributes.decodeMatrix[0]; var calculatedPrecision = matrixEntry.substring(matrixEntry.indexOf('.')).length; expect(precision).toEqual(calculatedPrecision); }); it('Doesn\'t quantize non-float attribute', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; + gltf.buffers[0].extras._pipeline.source = buffer; quantizeAttributes(gltf, {semantics: ['NORMAL']}); - expect(gltf.buffers.buffer.byteLength).toEqual(buffer.length); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength).toEqual(buffer.length + 4); }); it('Doesn\'t quantize already quantized attribute', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; + gltf.buffers[0].extras._pipeline.source = buffer; quantizeAttributes(gltf, {semantics: ['TEXCOORD']}); - expect(gltf.buffers.buffer.byteLength).toEqual(buffer.length); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength).toEqual(buffer.length + 4); }); it('Quantizes scalar attribute', function() { var gltf = clone(testGltf); - var accessor_4 = gltf.accessors.accessor_4; + var accessor_4 = gltf.accessors[4]; var size = byteLengthForComponentType(accessor_4.componentType) * numberOfComponentsForType(accessor_4.type) * accessor_4.count; size = size/2.0; - gltf.buffers.buffer.extras._pipeline.source = buffer; + gltf.buffers[0].extras._pipeline.source = buffer; quantizeAttributes(gltf, {semantics: ['SCALAR_TEST']}); - expect(gltf.buffers.buffer.byteLength + size).toEqual(buffer.length); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength + size).toEqual(buffer.length + 4); }); }); \ No newline at end of file diff --git a/specs/lib/removeUnusedVerticesSpec.js b/specs/lib/removeUnusedVerticesSpec.js index 1df660fe..a1827c4d 100644 --- a/specs/lib/removeUnusedVerticesSpec.js +++ b/specs/lib/removeUnusedVerticesSpec.js @@ -1,9 +1,10 @@ 'use strict'; var clone = require('clone'); -var removeUnusedVertices = require('../../lib/removeUnusedVertices'); +var AccessorReader = require('../../lib/AccessorReader'); var byteLengthForComponentType = require('../../lib/byteLengthForComponentType'); var numberOfComponentsForType = require('../../lib/numberOfComponentsForType'); - +var removeUnusedVertices = require('../../lib/removeUnusedVertices'); +var uninterleaveAndPackBuffers = require('../../lib/uninterleaveAndPackBuffers'); describe('removeUnusedVertices', function() { var indices = new Uint16Array([0, 1, 2]); @@ -15,248 +16,277 @@ describe('removeUnusedVertices', function() { var attributesBuffer = Buffer.concat([attributeOne, attributeTwo, attributeThree]); var testGltf = { - accessors : { - indexAccessor : { + accessors : [ + { byteOffset : 0, byteStride : 0, - bufferView : 'indexBufferView', + bufferView : 0, componentType : 5123, type : 'SCALAR' }, - attributeAccessor1 : { + { byteStride : 0, - bufferView : 'attributesBufferView', + bufferView : 1, componentType : 5126, count : 3, byteOffset : 0, type : 'VEC3' }, - attributeAccessor2 : { + { byteStride : 0, - bufferView : 'attributesBufferView', + bufferView : 1, componentType : 5123, count : 3, byteOffset : attributeOne.length, type : 'VEC2' }, - attributeAccessor3 : { + { byteStride : 0, - bufferView : 'attributesBufferView', + bufferView : 1, componentType : 5123, count : 3, byteOffset : 0, type : 'VEC3' } - }, - buffers : { - indexBuffer : { - type : 'arraybuffer', + ], + buffers : [ + { extras : { _pipeline : {} } }, - attributesBuffer : { + { byteLength : attributesBuffer.length, - type : 'arraybuffer', extras : { _pipeline : { source : attributesBuffer } } } - }, - bufferViews : { - indexBufferView : { - buffer : 'indexBuffer', + ], + bufferViews : [ + { + buffer : 0, byteOffset : 0, target : 34963 }, - attributesBufferView : { - buffer : 'attributesBuffer', + { + buffer : 1, byteOffset : 0, byteLength : attributesBuffer.length, target : 34962 } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives : [ { attributes : { - POSITION : 'attributeAccessor1', - NORMAL : 'attributeAccessor2' + POSITION : 1, + NORMAL : 2 }, - indices : 'indexAccessor' + indices : 0 } ] } - } + ] }; it('does not remove any data if all attribute values are accessed', function() { var gltf = clone(testGltf); - var gltfIndexBuffer = gltf.buffers.indexBuffer; + var gltfIndexBuffer = gltf.buffers[0]; var indexBuffer = new Buffer(indices.buffer); gltfIndexBuffer.extras._pipeline.source = indexBuffer; gltfIndexBuffer.byteLength = indexBuffer.length; - gltf.bufferViews.indexBufferView.byteLength = indexBuffer.length; - var indexAccessor = gltf.accessors.indexAccessor; + gltf.bufferViews[0].byteLength = indexBuffer.length; + var indexAccessor = gltf.accessors[0]; indexAccessor.count = indices.length; - var attributesBuffer = gltf.buffers.attributesBuffer; var byteLength = attributesBuffer.byteLength; removeUnusedVertices(gltf); + uninterleaveAndPackBuffers(gltf); expect(attributesBuffer.byteLength).toEqual(byteLength); }); it('removes one unused attribute', function() { var gltf = clone(testGltf); - var gltfIndexBuffer = gltf.buffers.indexBuffer; + var gltfIndexBuffer = gltf.buffers[0]; var indexBuffer = new Buffer(indicesOneUnused.slice(0).buffer); gltfIndexBuffer.extras._pipeline.source = indexBuffer; gltfIndexBuffer.byteLength = indexBuffer.length; - gltf.bufferViews.indexBufferView.byteLength = indexBuffer.length; - var indexAccessor = gltf.accessors.indexAccessor; + gltf.bufferViews[0].byteLength = indexBuffer.length; + var indexAccessor = gltf.accessors[0]; indexAccessor.count = indicesOneUnused.length; - var attributesBuffer = gltf.buffers.attributesBuffer; + var attributesBuffer = gltf.buffers[1]; var byteLength = attributesBuffer.byteLength; - var attributeAccessor1 = gltf.accessors.attributeAccessor1; + var attributeAccessor1 = gltf.accessors[1]; var expectBytesDropped1 = numberOfComponentsForType(attributeAccessor1.type) * byteLengthForComponentType(attributeAccessor1.componentType); - var attributeAccessor2 = gltf.accessors.attributeAccessor2; + var attributeAccessor2 = gltf.accessors[2]; var expectBytesDropped2 = numberOfComponentsForType(attributeAccessor2.type) * byteLengthForComponentType(attributeAccessor2.componentType); var expectBytesDropped = expectBytesDropped1 + expectBytesDropped2; removeUnusedVertices(gltf); - expect(attributesBuffer.byteLength + expectBytesDropped).toEqual(byteLength); - - var expectAttribute1 = new Float32Array([0, 1, 2, 6, 7, 8]); - var expectAttribute2 = new Uint16Array([0, 1, 4, 5]); - var attributesSource = Uint8Array.from(attributesBuffer.extras._pipeline.source); - var check1 = new Float32Array(attributesSource.buffer, attributeAccessor1.byteOffset, expectAttribute1.length); - var check2 = new Uint16Array(attributesSource.buffer, attributeAccessor2.byteOffset, expectAttribute2.length); - expect(check1).toEqual(expectAttribute1); - expect(check2).toEqual(expectAttribute2); - - var expectIndices = new Uint16Array([0, 1]); - var indicesSource = Uint8Array.from(gltf.buffers.indexBuffer.extras._pipeline.source); - var check = new Uint16Array(indicesSource.buffer, 0, expectIndices.length); - expect(check).toEqual(expectIndices); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength - indexBuffer.length + expectBytesDropped).toEqual(byteLength); + + var expectAttribute1 = [[0, 1, 2], [6, 7, 8]]; + var reader = new AccessorReader(gltf, attributeAccessor1); + var components = []; + var i = 0; + while(!reader.pastEnd()) { + reader.read(components); + expect(components).toEqual(expectAttribute1[i]); + reader.next(); + i++; + } + var expectAttribute2 = [[0, 1], [4, 5]]; + reader = new AccessorReader(gltf, attributeAccessor2); + components = []; + i = 0; + while(!reader.pastEnd()) { + reader.read(components); + expect(components).toEqual(expectAttribute2[i]); + reader.next(); + i++; + } + var expectIndices = [[0], [1]]; + reader = new AccessorReader(gltf, indexAccessor); + components = []; + i = 0; + while(!reader.pastEnd()) { + reader.read(components); + expect(components).toEqual(expectIndices[i]); + reader.next(); + i++; + } }); it('removes two unused attributes', function() { var gltf = clone(testGltf); - var gltfIndexBuffer = gltf.buffers.indexBuffer; + var gltfIndexBuffer = gltf.buffers[0]; var indexBuffer = new Buffer(indicesTwoUnused.slice(0).buffer); gltfIndexBuffer.extras._pipeline.source = indexBuffer; gltfIndexBuffer.byteLength = indexBuffer.length; - gltf.bufferViews.indexBufferView.byteLength = indexBuffer.length; - var indexAccessor = gltf.accessors.indexAccessor; + gltf.bufferViews[0].byteLength = indexBuffer.length; + var indexAccessor = gltf.accessors[0]; indexAccessor.count = indicesTwoUnused.length; - var attributesBuffer = gltf.buffers.attributesBuffer; + var attributesBuffer = gltf.buffers[1]; var byteLength = attributesBuffer.byteLength; - var attributeAccessor1 = gltf.accessors.attributeAccessor1; + var attributeAccessor1 = gltf.accessors[1]; var expectBytesDropped1 = numberOfComponentsForType(attributeAccessor1.type) * byteLengthForComponentType(attributeAccessor1.componentType); - var attributeAccessor2 = gltf.accessors.attributeAccessor2; + var attributeAccessor2 = gltf.accessors[2]; var expectBytesDropped2 = numberOfComponentsForType(attributeAccessor2.type) * byteLengthForComponentType(attributeAccessor2.componentType); var expectBytesDropped = 2 * (expectBytesDropped1 + expectBytesDropped2); removeUnusedVertices(gltf); - expect(attributesBuffer.byteLength + expectBytesDropped).toEqual(byteLength); - - var expectAttribute1 = [3, 4, 5]; - var expectAttribute2 = [2, 3]; - var attributesSource = Uint8Array.from(attributesBuffer.extras._pipeline.source); - var check1 = new Float32Array(attributesSource.buffer, attributeAccessor1.byteOffset, expectAttribute1.length); - var check2 = new Uint16Array(attributesSource.buffer, attributeAccessor2.byteOffset, expectAttribute2.length); - var i; - for (i = 0; i < expectAttribute1.length; i++) { - expect(expectAttribute1[i]).toEqual(check1[i]); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength - indexBuffer.length + expectBytesDropped).toEqual(byteLength); + + var expectAttribute1 = [[3, 4, 5]]; + var reader = new AccessorReader(gltf, attributeAccessor1); + var components = []; + var i = 0; + while (!reader.pastEnd()) { + reader.read(components); + expect(components).toEqual(expectAttribute1[i]); + reader.next(); + i++; } - for (i = 0; i < expectAttribute2.length; i++) { - expect(expectAttribute2[i]).toEqual(check2[i]); + var expectAttribute2 = [[2, 3]]; + reader = new AccessorReader(gltf, attributeAccessor2); + components = []; + i = 0; + while (!reader.pastEnd()) { + reader.read(components); + expect(components).toEqual(expectAttribute2[i]); + reader.next(); + i++; } - - var expectIndices = [0]; - var indicesSource = Uint8Array.from(gltfIndexBuffer.extras._pipeline.source); - var check = new Uint16Array(indicesSource.buffer, 0, expectIndices.length); - for (i = 0; i < expectIndices.length; i++) { - expect(expectIndices[i]).toEqual(check[i]); + var expectIndices = [[0]]; + reader = new AccessorReader(gltf, indexAccessor); + components = []; + i = 0; + while (!reader.pastEnd()) { + reader.read(components); + expect(components).toEqual(expectIndices[i]); + reader.next(); + i++; } }); it('handles when primitives use the same accessors with different indices', function() { var gltf = clone(testGltf); - var gltfIndexBuffer = gltf.buffers.indexBuffer; + var gltfIndexBuffer = gltf.buffers[0]; var indexBuffer = new Buffer(indicesTwoUnused.slice(0).buffer); gltfIndexBuffer.extras._pipeline.source = indexBuffer; gltfIndexBuffer.byteLength = indexBuffer.length; - var indexBufferView = gltf.bufferViews.indexBufferView; + var indexBufferView = gltf.bufferViews[0]; indexBufferView.byteLength = indexBuffer.length; var gltfIndexBuffer2 = clone(gltfIndexBuffer); var indexBuffer2 = new Buffer(indicesOneUnused.slice(0).buffer); gltfIndexBuffer2.extras._pipeline.source = indexBuffer2; gltfIndexBuffer2.byteLength = indexBuffer2.length; - gltf.buffers.indexBuffer2 = gltfIndexBuffer2; + gltf.buffers.push(gltfIndexBuffer2); var gltfIndexBufferView2 = clone(indexBufferView); - gltfIndexBufferView2.buffer = 'indexBuffer2'; + gltfIndexBufferView2.buffer = 2; gltfIndexBufferView2.byteLength = indexBuffer2.length; - gltf.bufferViews.indexBufferView2 = gltfIndexBufferView2; + gltf.bufferViews.push(gltfIndexBufferView2); - var gltfIndexAccessor = gltf.accessors.indexAccessor; + var gltfIndexAccessor = gltf.accessors[0]; gltfIndexAccessor.count = indicesTwoUnused.length; var gltfIndexAccessor2 = clone(gltfIndexAccessor); gltfIndexAccessor2.count = indicesOneUnused.length; - gltfIndexAccessor2.bufferView = 'indexBufferView2'; - gltf.accessors.indexAccessor2 = gltfIndexAccessor2; + gltfIndexAccessor2.bufferView = 2; + gltf.accessors.push(gltfIndexAccessor2); - var mesh2 = clone(gltf.meshes.mesh); - mesh2.primitives[0].indices = 'indexAccessor2'; - gltf.meshes.mesh2 = mesh2; + var mesh2 = clone(gltf.meshes[0]); + mesh2.primitives[0].indices = 4; + gltf.meshes.push(mesh2); // All indices are used, 0 and 2 by the first primitive and 1 by the other - var attributesBuffer = gltf.buffers.attributesBuffer; - var byteLength = attributesBuffer.byteLength; + var byteLength = gltf.buffers[0].byteLength + gltf.buffers[1].byteLength + gltf.buffers[2].byteLength; removeUnusedVertices(gltf); - expect(attributesBuffer.byteLength).toEqual(byteLength); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength).toEqual(byteLength); }); it('handles when primitives use the same accessors along with different accessors with different indices', function() { var gltf = clone(testGltf); - var gltfIndexBuffer = gltf.buffers.indexBuffer; + var gltfIndexBuffer = gltf.buffers[0]; var indexBuffer = new Buffer(indicesTwoUnused.slice(0).buffer); gltfIndexBuffer.extras._pipeline.source = indexBuffer; gltfIndexBuffer.byteLength = indexBuffer.length; - var indexBufferView = gltf.bufferViews.indexBufferView; + var indexBufferView = gltf.bufferViews[0]; indexBufferView.byteLength = indexBuffer.length; var gltfIndexBuffer2 = clone(gltfIndexBuffer); var indexBuffer2 = new Buffer(indicesOneUnused.slice(0).buffer); gltfIndexBuffer2.extras._pipeline.source = indexBuffer2; gltfIndexBuffer2.byteLength = indexBuffer2.length; - gltf.buffers.indexBuffer2 = gltfIndexBuffer2; + gltf.buffers.push(gltfIndexBuffer2); var gltfIndexBufferView2 = clone(indexBufferView); - gltfIndexBufferView2.buffer = 'indexBuffer2'; + gltfIndexBufferView2.buffer = 2; gltfIndexBufferView2.byteLength = indexBuffer2.length; - gltf.bufferViews.indexBufferView2 = gltfIndexBufferView2; + gltf.bufferViews.push(gltfIndexBufferView2); - var gltfIndexAccessor = gltf.accessors.indexAccessor; + var gltfIndexAccessor = gltf.accessors[0]; gltfIndexAccessor.count = indicesTwoUnused.length; var gltfIndexAccessor2 = clone(gltfIndexAccessor); gltfIndexAccessor2.count = indicesOneUnused.length; - gltfIndexAccessor2.bufferView = 'indexBufferView2'; - gltf.accessors.indexAccessor2 = gltfIndexAccessor2; + gltfIndexAccessor2.bufferView = 2; + gltf.accessors.push(gltfIndexAccessor2); - var mesh2 = clone(gltf.meshes.mesh); + var mesh2 = clone(gltf.meshes[0]); var primitive = mesh2.primitives[0]; - primitive.attributes.POSITION = 'attributeAccessor3'; - primitive.indices = 'indexAccessor2'; - gltf.meshes.mesh2 = mesh2; + primitive.attributes.POSITION = 3; + primitive.indices = 4; + gltf.meshes.push(mesh2); // All indices are used, 0 and 2 by the first primitive and 1 by the other - var attributesBuffer = gltf.buffers.attributesBuffer; - var byteLength = attributesBuffer.byteLength; + var byteLength = gltf.buffers[0].byteLength + gltf.buffers[1].byteLength + gltf.buffers[2].byteLength; removeUnusedVertices(gltf); - expect(attributesBuffer.byteLength).toEqual(byteLength); + uninterleaveAndPackBuffers(gltf); + expect(gltf.buffers[0].byteLength).toEqual(byteLength); }); it('handles when there is a cross-dependency between two groups of primitives', function() { @@ -269,92 +299,83 @@ describe('removeUnusedVertices', function() { var indexData2 = new Uint16Array([0, 1, 3, 4, 3, 1, 0]); var indexDataBuffer2 = new Buffer(indexData2.buffer); var gltf = { - accessors : { - attributeAccessor1 : { - bufferView : 'attributeBufferView1', + accessors : [ + { + bufferView : 0, byteStride : 0, byteOffset : 0, componentType : 5126, count : 5, type : 'VEC3' - }, - attributeAccessor2 : { - bufferView : 'attributeBufferView2', + }, { + bufferView : 1, byteStride : 0, byteOffset : 0, componentType : 5126, count : 5, type : 'VEC3' - }, - indexAccessor1 : { - bufferView : 'indexBufferView1', + }, { + bufferView : 2, byteStride : 0, byteOffset : 0, componentType : 5123, count : 9, type : 'SCALAR' - }, - indexAccessor2 : { - bufferView : 'indexBufferView2', + }, { + bufferView : 3, byteStride : 0, byteOffset : 0, componentType : 5123, count : 7, type : 'SCALAR' } - }, - bufferViews : { - attributeBufferView1 : { - buffer : 'attributeBuffer1', + ], + bufferViews : [ + { + buffer : 0, byteOffset : 0, byteLength : attributeDataBuffer1.length, target : 34962 - }, - attributeBufferView2 : { - buffer : 'attributeBuffer2', + }, { + buffer : 1, byteOffset : 0, byteLength : attributeDataBuffer2.length, target : 34962 - }, - indexBufferView1 : { - buffer : 'indexBuffer1', + }, { + buffer : 2, byteOffset : 0, byteLength : indexDataBuffer1.length, target : 34963 - }, - indexBufferView2 : { - buffer : 'indexBuffer2', + }, { + buffer : 3, byteOffset : 0, byteLength : indexDataBuffer2.length, target : 34963 } - }, - buffers : { - attributeBuffer1 : { + ], + buffers : [ + { byteLength : attributeDataBuffer1.length, extras : { _pipeline : { source : attributeDataBuffer1.slice(0) } } - }, - attributeBuffer2 : { + }, { byteLength : attributeDataBuffer2.length, extras : { _pipeline : { source : attributeDataBuffer2.slice(0) } } - }, - indexBuffer1 : { + }, { byteLength : indexDataBuffer1.length, extras : { _pipeline : { source : indexDataBuffer1.slice(0) } } - }, - indexBuffer2 : { + }, { byteLength : indexDataBuffer2.length, extras : { _pipeline : { @@ -362,38 +383,35 @@ describe('removeUnusedVertices', function() { } } } - }, - meshes : { - mesh : { + ], + meshes : [ + { primitives: [ { attributes : { - TEST : 'attributeAccessor1' + TEST : 0 }, - indices : 'indexAccessor1' - }, - { + indices : 2 + }, { attributes : { - TEST : 'attributeAccessor2' + TEST : 1 }, - indices : 'indexAccessor2' - }, - { + indices : 3 + }, { attributes : { - TEST : 'attributeAccessor1' + TEST : 0 }, - indices : 'indexAccessor2' + indices : 3 } ] } - } + ] }; removeUnusedVertices(gltf); - var buffers = gltf.buffers; - expect(buffers.indexBuffer1.extras._pipeline.source).toEqual(indexDataBuffer1); - expect(buffers.indexBuffer2.extras._pipeline.source).toEqual(indexDataBuffer2); - expect(buffers.attributeBuffer1.extras._pipeline.source).toEqual(attributeDataBuffer1); - expect(buffers.attributeBuffer2.extras._pipeline.source).toEqual(attributeDataBuffer2); + uninterleaveAndPackBuffers(gltf); + var bufferViews = gltf.bufferViews; + expect(bufferViews[0].byteLength).toEqual(attributeDataBuffer1.length + attributeDataBuffer2.length); + expect(bufferViews[1].byteLength).toEqual(indexDataBuffer1.length + indexDataBuffer2.length); }); it('removes parts of the buffer based on the attribute type if the stride is 0', function() { @@ -421,76 +439,73 @@ describe('removeUnusedVertices', function() { var dataBuffer = Buffer.concat([indicesBuffer, positionsBuffer]); var testGltf = { - "accessors": { - "accessor_index": { - "bufferView": "index_view", - "byteOffset": 0, - "componentType": 5123, - "count": 6, - "type": "SCALAR", - "extras": { - "_pipeline": {} + accessors : [ + { + bufferView : 1, + byteOffset : 0, + componentType : 5123, + count : 6, + type : 'SCALAR', + extras : { + _pipeline: {} } - }, - "accessor_position": { - "bufferView": "position_view", - "byteOffset": 0, - "componentType": 5126, - "count": 4, - "type": "VEC3", - "extras": { - "_pipeline": {} + }, { + bufferView : 0, + byteOffset : 0, + componentType : 5126, + count : 4, + type : 'VEC3', + extras : { + _pipeline : {} } } - }, - "bufferViews": { - "position_view": { - "buffer": "buffer_0", - "byteOffset": 6 * 2, - "byteLength": 7 * 3 * 4, - "target": 34962, - "extras": { - "_pipeline": {} + ], + bufferViews : [ + { + buffer : 0, + byteOffset : 6 * 2, + byteLength : 7 * 3 * 4, + target : 34962, + extras : { + _pipeline : {} } - }, - "index_view": { - "buffer": "buffer_0", - "byteOffset": 0, - "byteLength": 6 * 2, - "target": 34963, - "extras": { - "_pipeline": {} + }, { + buffer : 0, + byteOffset : 0, + byteLength : 6 * 2, + target : 34963, + extras : { + _pipeline : {} } } - }, - "buffers": { - "buffer_0": { - "uri": "data:", - "byteLength": indices.length * 2 + positions.length * 4, - "extras": { - "_pipeline": { - "source": dataBuffer + ], + buffers : [ + { + byteLength : indices.length * 2 + positions.length * 4, + extras : { + _pipeline : { + source : dataBuffer } } } - }, - "meshes": { - "mesh_square": { - "name": "square", - "primitives": [ + ], + meshes : [ + { + name : 'square', + primitives : [ { - "attributes": { - "POSITION": "accessor_position" + attributes : { + POSITION : 1 }, - "indices": "accessor_index" + indices : 0 } ] } - } + ] }; - removeUnusedVertices(testGltf); - expect(testGltf.buffers.buffer_0.byteLength).toEqual(6 * 2 + 4 * 3 * 4); + uninterleaveAndPackBuffers(testGltf); + expect(testGltf.buffers[0].byteLength).toEqual(6 * 2 + 4 * 3 * 4); }); it('handles 8 bit indices', function(){ @@ -518,75 +533,73 @@ describe('removeUnusedVertices', function() { var dataBuffer = Buffer.concat([indicesBuffer, positionsBuffer]); var testGltf = { - "accessors": { - "accessor_index": { - "bufferView": "index_view", - "byteOffset": 0, - "componentType": 5121, // unsigned short - "count": 6, - "type": "SCALAR", - "extras": { - "_pipeline": {} + accessors: [ + { + bufferView : 1, + byteOffset: 0, + componentType: 5121, // unsigned short + count: 6, + type: 'SCALAR', + extras: { + _pipeline: {} } - }, - "accessor_position": { - "bufferView": "position_view", - "byteOffset": 0, - "componentType": 5126, - "count": 4, - "type": "VEC3", - "extras": { - "_pipeline": {} + }, { + bufferView: 0, + byteOffset: 0, + componentType: 5126, + count: 4, + type: 'VEC3', + extras: { + _pipeline: {} } } - }, - "bufferViews": { - "position_view": { - "buffer": "buffer_0", - "byteOffset": 6, - "byteLength": 7 * 3 * 4, - "target": 34962, - "extras": { - "_pipeline": {} + ], + bufferViews: [ + { + buffer: 0, + byteOffset: 6, + byteLength: 7 * 3 * 4, + target: 34962, + extras: { + _pipeline: {} } }, - "index_view": { - "buffer": "buffer_0", - "byteOffset": 0, - "byteLength": 6, - "target": 34963, - "extras": { - "_pipeline": {} + { + buffer: 0, + byteOffset: 0, + byteLength: 6, + target: 34963, + extras: { + _pipeline: {} } } - }, - "buffers": { - "buffer_0": { - "uri": "data:", - "byteLength": indices.length + positions.length * 4, - "extras": { - "_pipeline": { - "source": dataBuffer + ], + buffers: [ + { + byteLength: indices.length + positions.length * 4, + extras: { + _pipeline: { + source: dataBuffer } } } - }, - "meshes": { - "mesh_square": { - "name": "square", - "primitives": [ + ], + meshes: [ + { + name: 'square', + primitives: [ { - "attributes": { - "POSITION": "accessor_position" + attributes: { + POSITION: 1 }, - "indices": "accessor_index" + indices: 0 } ] } - } + ] }; - removeUnusedVertices(testGltf); - expect(testGltf.buffers.buffer_0.byteLength).toEqual(6 + 4 * 3 * 4); + uninterleaveAndPackBuffers(testGltf); + expect(testGltf.buffers[0].byteLength).toEqual(6 + 4 * 3 * 4); }); }); \ No newline at end of file diff --git a/specs/lib/uninterleaveAndPackBuffersSpec.js b/specs/lib/uninterleaveAndPackBuffersSpec.js index d08517b6..9d3cf65c 100644 --- a/specs/lib/uninterleaveAndPackBuffersSpec.js +++ b/specs/lib/uninterleaveAndPackBuffersSpec.js @@ -1,12 +1,12 @@ 'use strict'; var clone = require('clone'); - var byteLengthForComponentType = require('../../lib/byteLengthForComponentType'); var numberOfComponentsForType = require('../../lib/numberOfComponentsForType'); +var Remove = require('../../lib/Remove'); var uninterleaveAndPackBuffers = require('../../lib/uninterleaveAndPackBuffers'); describe('uninterleaveAndPackBuffers', function() { - var buffer = new Uint8Array(96); + var buffer = new Buffer(96); var testGltf = { accessors : [ // Interleaved accessors in bufferView_0 @@ -60,61 +60,59 @@ describe('uninterleaveAndPackBuffers', function() { buffers : [ { byteLength : buffer.length, - type : 'arraybuffer', extras : { - _pipeline : {} + _pipeline : { + source: buffer + } } } ] }; - fit('doesn\'t remove any data if the whole buffer is used', function() { + it('doesn\'t remove any data if the whole buffer is used', function() { var gltf = clone(testGltf); gltf.buffers[0].extras._pipeline.source = buffer; uninterleaveAndPackBuffers(gltf); - expect(gltf.buffers.buffer.byteLength).toEqual(testGltf.buffers.buffer.byteLength); + expect(gltf.buffers[0].byteLength).toEqual(testGltf.buffers[0].byteLength); }); it('removes extra trailing data on the buffer', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = new Uint8Array(buffer.length * 2); + gltf.buffers[0].extras._pipeline.source = new Buffer(buffer.length * 2); uninterleaveAndPackBuffers(gltf); - expect(gltf.buffers.buffer.byteLength).toEqual(testGltf.buffers.buffer.byteLength); + expect(gltf.buffers[0].byteLength).toEqual(testGltf.buffers[0].byteLength); }); it('removes interleaved unused data', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; - var deletedAccessorId = 'accessor_1'; - var deletedAccessor = gltf.accessors[deletedAccessorId]; + gltf.buffers[0].extras._pipeline.source = buffer; + var deletedAccessor = gltf.accessors[1]; var size = byteLengthForComponentType(deletedAccessor.componentType) * numberOfComponentsForType(deletedAccessor.type) * deletedAccessor.count; - delete gltf.accessors[deletedAccessorId]; + Remove.accessor(gltf, 1); uninterleaveAndPackBuffers(gltf); - expect(gltf.buffers.buffer.byteLength + size).toEqual(testGltf.buffers.buffer.byteLength); + expect(gltf.buffers[0].byteLength + size).toEqual(testGltf.buffers[0].byteLength); }); it('removes block unused data', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; - var deletedAccessorId = 'accessor_2'; - var deletedAccessor = gltf.accessors[deletedAccessorId]; + gltf.buffers[0].extras._pipeline.source = buffer; + var deletedAccessor = gltf.accessors[2]; var size = byteLengthForComponentType(deletedAccessor.componentType) * numberOfComponentsForType(deletedAccessor.type) * deletedAccessor.count; - delete gltf.accessors[deletedAccessorId]; + Remove.accessor(gltf, 2); uninterleaveAndPackBuffers(gltf); - expect(gltf.buffers.buffer.byteLength + size).toEqual(testGltf.buffers.buffer.byteLength); - var bufferView1 = gltf.bufferViews.bufferView_1; - expect(bufferView1.byteLength).toEqual(gltf.buffers.buffer.byteLength - bufferView1.byteOffset); + expect(gltf.buffers[0].byteLength + size).toEqual(testGltf.buffers[0].byteLength); + var bufferView = gltf.bufferViews[1]; + expect(bufferView.byteLength).toEqual(gltf.buffers[0].byteLength - bufferView.byteOffset); }); it('removes unused bufferView', function() { var gltf = clone(testGltf); - gltf.buffers.buffer.extras._pipeline.source = buffer; - var size = gltf.bufferViews.bufferView_0.byteLength; - delete gltf.accessors.accessor_0; - delete gltf.accessors.accessor_1; + gltf.buffers[0].extras._pipeline.source = buffer; + var size = gltf.bufferViews[0].byteLength; + Remove.accessor(gltf, 0); + Remove.accessor(gltf, 0); uninterleaveAndPackBuffers(gltf); - expect(gltf.buffers.buffer.byteLength + size).toEqual(testGltf.buffers.buffer.byteLength); - var bufferViewCount = Object.keys(gltf.bufferViews).length; - expect(bufferViewCount).toEqual(1); + expect(gltf.buffers[0].byteLength + size).toEqual(testGltf.buffers[0].byteLength); + expect(gltf.bufferViews.length).toEqual(1); }); }); \ No newline at end of file From af0a51a0094edca059e3102c5765bbed8b30a2ea Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Mon, 20 Mar 2017 21:52:58 -0400 Subject: [PATCH 33/47] Fixed a few more tests --- lib/getBinaryGltf.js | 2 +- lib/updateVersion.js | 9 +++++++++ lib/writeSource.js | 11 ++++++++--- specs/lib/PipelineSpec.js | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/getBinaryGltf.js b/lib/getBinaryGltf.js index 637baa26..cdea87ea 100644 --- a/lib/getBinaryGltf.js +++ b/lib/getBinaryGltf.js @@ -10,7 +10,7 @@ var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; // .crn (Crunch) is not a supported mime type, so add it -mime.define({'image/cr': ['crn']}); +mime.define({'image/crn': ['crn']}); module.exports = getBinaryGltf; diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 1fb4b0a1..670f383a 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -355,6 +355,15 @@ function objectsToArrays(gltf) { node.skin = globalMapping.skins[node.skin]; } }); + ForEach.scene(gltf, function(scene) { + var sceneNodes = scene.nodes; + if (defined(sceneNodes)) { + var sceneNodesLength = sceneNodes.length; + for (i = 0; i < sceneNodesLength; i++) { + sceneNodes[i] = globalMapping.nodes[sceneNodes[i]]; + } + } + }); ForEach.animation(gltf, function(animation) { var samplerMapping = {}; animation.samplers = objectToArray(animation.samplers, samplerMapping); diff --git a/lib/writeSource.js b/lib/writeSource.js index 1bf1ca5f..678974f0 100644 --- a/lib/writeSource.js +++ b/lib/writeSource.js @@ -12,6 +12,9 @@ var defined = Cesium.defined; var fsOutputFile = Promise.promisify(fsExtra.outputFile); +// .crn (Crunch) is not a supported mime type, so add it +mime.define({'image/crn': ['crn']}); + module.exports = writeSource; /** @@ -40,9 +43,11 @@ function writeSource(arrayOfObjects, name, basePath, options) { if (name === 'shaders') { object.uri = 'data:text/plain;base64,' + new Buffer(source).toString('base64'); } else { - // .crn (Crunch) is not a supported mime type, so add it - mime.define({'image/crn': ['crn']}); - object.uri = 'data:' + mime.lookup(extension) + ';base64,' + source.toString('base64'); + var mimeType = object.mimeType; + if (!defined(mimeType)) { + mimeType = mime.lookup(extension); + } + object.uri = 'data:' + mimeType + ';base64,' + source.toString('base64'); } } else { var fileName = i + extension; diff --git a/specs/lib/PipelineSpec.js b/specs/lib/PipelineSpec.js index e26b9c3e..68842804 100644 --- a/specs/lib/PipelineSpec.js +++ b/specs/lib/PipelineSpec.js @@ -68,7 +68,7 @@ describe('Pipeline', function() { }), done).toResolve(); }); - fit('optimizes a glb file', function(done) { + it('optimizes a glb file', function(done) { var gltfCopy; expect(readGltf(glbPath) .then(function(gltf) { From a4a0331bbbaa4dbf9589efa07b4881cfb739d28e Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 11:58:32 -0400 Subject: [PATCH 34/47] All tests pass --- lib/bakeAmbientOcclusion.js | 98 ++++---- lib/loadGltfUris.js | 38 +++ lib/parseBinaryGltf.js | 34 --- lib/processModelMaterialsCommon.js | 153 ++++++------- lib/updateVersion.js | 1 - .../ambientOcclusion/cube_over_ground.gltf | 6 +- specs/lib/bakeAmbientOcclusionSpec.js | 216 +++++++++--------- specs/lib/processModelMaterialsCommonSpec.js | 48 ++-- 8 files changed, 281 insertions(+), 313 deletions(-) diff --git a/lib/bakeAmbientOcclusion.js b/lib/bakeAmbientOcclusion.js index 09dc3e77..096298a7 100644 --- a/lib/bakeAmbientOcclusion.js +++ b/lib/bakeAmbientOcclusion.js @@ -2,6 +2,7 @@ var Cesium = require('cesium'); var Jimp = require('jimp'); var addToArray = require('./addToArray'); +var isTexture = require('./isTexture'); var GeometryMath = require('./GeometryMath'); var NodeHelpers = require('./NodeHelpers'); var readAccessor = require('./readAccessor'); @@ -182,8 +183,7 @@ function cloneJsonAsNeeded(id, cloneIds, items) { var cloneID = cloneIds[id]; if (defined(cloneID)) { if (cloneID === '') { // No clone exists yet. Make one! - cloneID = id + "_noAO"; - items[cloneID] = clone(items[id]); + cloneID = addToArray(items, clone(items[id])); cloneIds[id] = cloneID; } return cloneID; @@ -573,7 +573,7 @@ function bakeToTexture(gltf, options) { for (var materialId = 0; materialId < materialsLength; materialId++) { var material = materials[materialId]; if (defined(material.values) && defined(material.values.diffuse)) { - if (typeof material.values.diffuse === 'string') { + if (isTexture('diffuse', material.values.diffuse)) { exampleMaterialID = materialId; exampleTextureID = material.values.diffuse; exampleImageID = textures[exampleTextureID].source; @@ -660,10 +660,6 @@ function postProcessAO(options) { } function cloneAndSetupMaterialTextureImage(options) { - var newMaterialID = options.newMaterialID; - var newTextureID = options.newTextureID; - var newImageID = options.newImageID; - var materials = options.materials; var textures = options.textures; var images = options.images; @@ -672,24 +668,24 @@ function cloneAndSetupMaterialTextureImage(options) { var newTexture; var newMaterial; - if (defined(newImageID)) { + if (defined(options.oldImageID)) { var oldImage = images[options.oldImageID]; if (!defined(oldImage.extras._pipeline.jimpImage)) { throw new DeveloperError('gltf pipeline image processing does not currently support the ' + oldImage.extras._pipeline.extension + ' format.'); } newImage = clone(oldImage); newImage.extras._pipeline.jimpImage = oldImage.extras._pipeline.jimpImage.clone(); - images[newImageID] = newImage; + options.newImageID = addToArray(images, newImage); } - if (defined(newTextureID)) { + if (defined(options.oldTextureID)) { var oldTexture = textures[options.oldTextureID]; newTexture = clone(oldTexture); - newTexture.source = newImageID; - textures[newTextureID] = newTexture; - if (defined(newMaterialID)) { + newTexture.source = options.newImageID; + options.newTextureID = addToArray(textures, newTexture); + if (defined(options.oldMaterialID)) { newMaterial = clone(materials[options.oldMaterialID]); - newMaterial.texture = newTextureID; - materials[newMaterialID] = newMaterial; + newMaterial.texture = options.newTextureID; + options.newMaterialID = addToArray(materials, newMaterial); } } } @@ -697,8 +693,8 @@ function cloneAndSetupMaterialTextureImage(options) { // Check and modify the given material to ensure every primitive gets a unique material, texture, and image function ensureImageUniqueness(gltf, options) { var primitive = options.primitive; - var meshPrimitiveID = options.meshPrimitiveID; var state = options.state; + var parameters; var materialsSeen = state.materialsSeen; var texturesSeen = state.texturesSeen; @@ -708,13 +704,9 @@ function ensureImageUniqueness(gltf, options) { var allTextures = gltf.textures; var allImages = gltf.images; - // Generate some new IDs - var newMaterialID = meshPrimitiveID + '_AO_material'; - var newTextureID = meshPrimitiveID + '_AO_texture'; - var newImageID = meshPrimitiveID + '_AO_image'; - // Grab the existing material - var material = allMaterials[primitive.material]; + var materialID = primitive.material; + var material = allMaterials[materialID]; var values = material.values; var diffuse = values.diffuse; @@ -723,17 +715,18 @@ function ensureImageUniqueness(gltf, options) { // - clone the example texture // - clone the example image. resize to resolution and set to diffuse color, if any if (!defined(diffuse) || diffuse.length > 1) { - cloneAndSetupMaterialTextureImage({ - newMaterialID : newMaterialID, - newTextureID : newTextureID, - newImageID : newImageID, + parameters = { + newMaterialID : undefined, + newTextureID : undefined, + newImageID : undefined, oldMaterialID : state.exampleMaterialID, oldTextureID : state.exampleTextureID, oldImageID : state.exampleImageID, materials : allMaterials, textures : allTextures, images : allImages - }); + }; + cloneAndSetupMaterialTextureImage(parameters); var color = defaultValue(diffuse, [1.0, 1.0, 1.0, 1.0]); // For jimp @@ -742,7 +735,7 @@ function ensureImageUniqueness(gltf, options) { color[2] *= 255; color[3] *= 255; - var newJimpImage = allImages[newImageID].extras._pipeline.jimpImage; + var newJimpImage = allImages[parameters.newImageID].extras._pipeline.jimpImage; var resolution = state.resolution; newJimpImage.resize(resolution, resolution); @@ -752,61 +745,64 @@ function ensureImageUniqueness(gltf, options) { newJimpImage.setPixelColor(x, y, hexColor); } } - primitive.material = newMaterialID; - return allImages[newImageID]; + primitive.material = parameters.newMaterialID; + return allImages[parameters.newImageID]; } - var textureID = diffuse; + var textureID = diffuse[0]; var imageID = allTextures[textureID].source; if (materialsSeen.hasOwnProperty(materialID)) { // Check if the material is unique. If not, clone material, texture, and image - cloneAndSetupMaterialTextureImage({ - newMaterialID : newMaterialID, - newTextureID : newTextureID, - newImageID : newImageID, + parameters = { + newMaterialID : undefined, + newTextureID : undefined, + newImageID : undefined, oldMaterialID : materialID, oldTextureID : textureID, oldImageID : imageID, materials : allMaterials, textures : allTextures, images : allImages - }); - primitive.material = newMaterialID; + }; + cloneAndSetupMaterialTextureImage(parameters); + primitive.material = options.newMaterialID; } else if(texturesSeen.hasOwnProperty(textureID)) { // Check if the texture is unique. If not clone the texture and the image. - cloneAndSetupMaterialTextureImage({ - newTextureID : newTextureID, - newImageID : newImageID, - oldMaterialID : materialID, + parameters = { + newTextureID : undefined, + newImageID : undefined, + oldMaterialID : undefined, oldTextureID : textureID, oldImageID : imageID, materials : allMaterials, textures : allTextures, images : allImages - }); - values.diffuse = newTextureID; + }; + cloneAndSetupMaterialTextureImage(parameters); + values.diffuse = parameters.newTextureID; } else if(imagesSeen.hasOwnProperty(imageID)) { // Check if the image is unique. if not, clone the image. var texture = allTextures[textureID]; - cloneAndSetupMaterialTextureImage({ - newImageID : newImageID, - oldMaterialID : materialID, - oldTextureID : textureID, + parameters = { + newImageID : undefined, + oldMaterialID : undefined, + oldTextureID : undefined, oldImageID : imageID, materials : allMaterials, textures : allTextures, images : allImages - }); - texture.source = newImageID; + }; + cloneAndSetupMaterialTextureImage(parameters); + texture.source = parameters.newImageID; } else { // If nothing was cloned, mark this material, texture, and image as seen materialsSeen[materialID] = true; texturesSeen[textureID] = true; imagesSeen[imageID] = true; - newImageID = imageID; + return allImages[imageID]; } - return allImages[newImageID]; + return allImages[parameters.newImageID]; } ////////// loading ////////// diff --git a/lib/loadGltfUris.js b/lib/loadGltfUris.js index c8c46cd3..4565690d 100644 --- a/lib/loadGltfUris.js +++ b/lib/loadGltfUris.js @@ -82,6 +82,11 @@ function loadURI(gltf, object, name, basePath) { var buffer = buffers[bufferId]; var source = buffer.extras._pipeline.source; object.extras._pipeline.source = source.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); + if (!defined(object.extras._pipeline.extension)) { + if (name === 'images') { + object.extras._pipeline.extension = getBinaryImageFormat(object.extras._pipeline.source.slice(0, 2)); + } + } } else if (isDataUri(uri)) { if (!defined(object.extras._pipeline.source)) { var dataBuffer = dataUriToBuffer(uri); @@ -120,6 +125,39 @@ function loadURI(gltf, object, name, basePath) { return Promise.all(promises); } +function bufferEqual(first, second) { + for (var i = 0; i < first.length && i < second.length; i++) { + if (first[i] !== second[i]) { + return false; + } + } + return true; +} + +function getBinaryImageFormat(header) { + if (bufferEqual(header, new Uint8Array([66, 77]))) { //.bmp: 42 4D + return '.bmp'; + } + else if (bufferEqual(header, new Uint8Array([71, 73]))) { //.gif: 47 49 + return '.gif'; + } + else if (bufferEqual(header, new Uint8Array([255, 216]))) { //.jpg: ff d8 + return '.jpg'; + } + else if (bufferEqual(header, new Uint8Array([137, 80]))) { //.png: 89 50 + return '.png'; + } + else if (bufferEqual(header, new Uint8Array([171, 75]))) { //.ktx ab 4b + return '.ktx'; + } + else if (bufferEqual(header, new Uint8Array([72, 120]))) { //.crn 48 78 + return '.crn'; + } + else { + throw new DeveloperError('Binary image does not have valid header'); + } +} + /** * Return the extension of the data uri. * diff --git a/lib/parseBinaryGltf.js b/lib/parseBinaryGltf.js index 45c5b5ca..f929d7ef 100644 --- a/lib/parseBinaryGltf.js +++ b/lib/parseBinaryGltf.js @@ -101,38 +101,4 @@ function parseBinaryGltf(data) { } } return gltf; -} - -function bufferEqual(first, second) { - for (var i = 0; i < first.length && i < second.length; i++) { - if (first[i] !== second[i]) { - return false; - } - } - return true; -} - -//Get binary image file format from first two bytes -function getBinaryImageFormat(header) { - if (bufferEqual(header, new Uint8Array([66, 77]))) { //.bmp: 42 4D - return '.bmp'; - } - else if (bufferEqual(header, new Uint8Array([71, 73]))) { //.gif: 47 49 - return '.gif'; - } - else if (bufferEqual(header, new Uint8Array([255, 216]))) { //.jpg: ff d8 - return '.jpg'; - } - else if (bufferEqual(header, new Uint8Array([137, 80]))) { //.png: 89 50 - return '.png'; - } - else if (bufferEqual(header, new Uint8Array([171, 75]))) { //.ktx ab 4b - return '.ktx'; - } - else if (bufferEqual(header, new Uint8Array([72, 120]))) { //.crn 48 78 - return '.crn'; - } - else { - throw new DeveloperError('Binary image does not have valid header'); - } } \ No newline at end of file diff --git a/lib/processModelMaterialsCommon.js b/lib/processModelMaterialsCommon.js index aeccbcba..de7044fe 100644 --- a/lib/processModelMaterialsCommon.js +++ b/lib/processModelMaterialsCommon.js @@ -1,6 +1,7 @@ 'use strict'; var Cesium = require('cesium'); var addToArray = require('./addToArray'); +var ForEach = require('./ForEach'); var numberOfComponentsForType = require('./numberOfComponentsForType'); var techniqueParameterForSemantic = require('./techniqueParameterForSemantic'); @@ -813,68 +814,55 @@ function ensureSemanticExistenceForPrimitive(gltf, primitive) { } function ensureSemanticExistence(gltf) { - var meshes = gltf.meshes; - var meshesLength = meshes.length; - for (var meshId = 0; meshId < meshesLength; meshId++) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - ensureSemanticExistenceForPrimitive(gltf, primitives[i]); - } - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + ensureSemanticExistenceForPrimitive(gltf, primitive); + }); + }); } function splitIncompatibleSkins(gltf) { var accessors = gltf.accessors; var materials = gltf.materials; - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var j = 0; j < primitivesLength; j++) { - var primitive = primitives[j]; - - var materialId = primitive.material; - var material = materials[materialId]; - - if (defined(material.extensions) && defined(material.extensions.KHR_materials_common)) { - var khrMaterialsCommon = material.extensions.KHR_materials_common; - var jointAccessorId = primitive.attributes.JOINT; - var componentType; - var type; - if (defined(jointAccessorId)) { - var jointAccessor = accessors[jointAccessorId]; - componentType = jointAccessor.componentType; - type = jointAccessor.type; - } - var isSkinned = defined(jointAccessorId); - - var skinningInfo = khrMaterialsCommon.extras._pipeline.skinning; - if (!defined(skinningInfo)) { - khrMaterialsCommon.extras._pipeline.skinning = { - skinned: isSkinned, - componentType: componentType, - type: type - }; - } else if ((skinningInfo.skinned !== isSkinned) || (skinningInfo.type !== type)) { - // This primitive uses the same material as another one that either isn't skinned or uses a different type to store joints and weights - var clonedMaterial = clone(material, true); - clonedMaterial.extensions.KHR_materials_common.extras._pipeline.skinning = { - skinned: isSkinned, - componentType: componentType, - type: type - }; - // Split this off as a separate material - materialId = addToArray(gltf, clonedMaterial); - primitive.material = materialId; - } - } - } - } - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function(primitive) { + var materialId = primitive.material; + var material = materials[materialId]; + + if (defined(material.extensions) && defined(material.extensions.KHR_materials_common)) { + var khrMaterialsCommon = material.extensions.KHR_materials_common; + var jointAccessorId = primitive.attributes.JOINT; + var componentType; + var type; + if (defined(jointAccessorId)) { + var jointAccessor = accessors[jointAccessorId]; + componentType = jointAccessor.componentType; + type = jointAccessor.type; + } + var isSkinned = defined(jointAccessorId); + + var skinningInfo = khrMaterialsCommon.extras._pipeline.skinning; + if (!defined(skinningInfo)) { + khrMaterialsCommon.extras._pipeline.skinning = { + skinned: isSkinned, + componentType: componentType, + type: type + }; + } else if ((skinningInfo.skinned !== isSkinned) || (skinningInfo.type !== type)) { + // This primitive uses the same material as another one that either isn't skinned or uses a different type to store joints and weights + var clonedMaterial = clone(material, true); + clonedMaterial.extensions.KHR_materials_common.extras._pipeline.skinning = { + skinned: isSkinned, + componentType: componentType, + type: type + }; + // Split this off as a separate material + materialId = addToArray(materials, clonedMaterial); + primitive.material = materialId; + } + } + }); + }); } @@ -906,7 +894,6 @@ function processModelMaterialsCommon(gltf, options) { } if (hasExtension) { - gltf.asset.premultipliedAlpha = true; if (!defined(gltf.programs)) { gltf.programs = []; } @@ -924,39 +911,35 @@ function processModelMaterialsCommon(gltf, options) { splitIncompatibleSkins(gltf); var techniques = {}; - var materials = gltf.materials; - for (var materialId in materials) { - if (materials.hasOwnProperty(materialId)) { - var material = materials[materialId]; - if (defined(material.extensions) && defined(material.extensions.KHR_materials_common)) { - var khrMaterialsCommon = material.extensions.KHR_materials_common; - var techniqueKey = getTechniqueKey(khrMaterialsCommon); - var technique = techniques[techniqueKey]; - if (!defined(technique)) { - technique = generateTechnique(gltf, khrMaterialsCommon, lightParameters, options.optimizeForCesium); - techniques[techniqueKey] = technique; - } + ForEach.material(gltf, function(material) { + if (defined(material.extensions) && defined(material.extensions.KHR_materials_common)) { + var khrMaterialsCommon = material.extensions.KHR_materials_common; + var techniqueKey = getTechniqueKey(khrMaterialsCommon); + var technique = techniques[techniqueKey]; + if (!defined(technique)) { + technique = generateTechnique(gltf, khrMaterialsCommon, lightParameters, options.optimizeForCesium); + techniques[techniqueKey] = technique; + } - // Take advantage of the fact that we generate techniques that use the - // same parameter names as the extension values. - material.values = {}; - var values = khrMaterialsCommon.values; - for (var valueName in values) { - if (values.hasOwnProperty(valueName)) { - var value = values[valueName]; - material.values[valueName] = value; - } + // Take advantage of the fact that we generate techniques that use the + // same parameter names as the extension values. + material.values = {}; + var values = khrMaterialsCommon.values; + for (var valueName in values) { + if (values.hasOwnProperty(valueName)) { + var value = values[valueName]; + material.values[valueName] = value; } + } - material.technique = technique; + material.technique = technique; - delete material.extensions.KHR_materials_common; - if (Object.keys(material.extensions).length === 0) { - delete material.extensions; - } + delete material.extensions.KHR_materials_common; + if (Object.keys(material.extensions).length === 0) { + delete material.extensions; } } - } + }); if (defined(gltf.extensions)) { delete gltf.extensions.KHR_materials_common; diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 670f383a..f535fbb0 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -6,7 +6,6 @@ var findAccessorMinMax = require('./findAccessorMinMax'); var Cartesian3 = Cesium.Cartesian3; var CesiumMath = Cesium.Math; -var Matrix4 = Cesium.Matrix4; var Quaternion = Cesium.Quaternion; var WebGLConstants = Cesium.WebGLConstants; var defaultValue = Cesium.defaultValue; diff --git a/specs/data/ambientOcclusion/cube_over_ground.gltf b/specs/data/ambientOcclusion/cube_over_ground.gltf index 7c277cf8..7ee96cc9 100644 --- a/specs/data/ambientOcclusion/cube_over_ground.gltf +++ b/specs/data/ambientOcclusion/cube_over_ground.gltf @@ -402,14 +402,12 @@ { "nodes": [ 2 - ], - "node": [] + ] }, { "nodes": [ 3 - ], - "node": [] + ] } ], "shaders": [ diff --git a/specs/lib/bakeAmbientOcclusionSpec.js b/specs/lib/bakeAmbientOcclusionSpec.js index 038d9b0f..68242984 100644 --- a/specs/lib/bakeAmbientOcclusionSpec.js +++ b/specs/lib/bakeAmbientOcclusionSpec.js @@ -83,110 +83,109 @@ describe('AmbientOcclusion', function() { var dataBuffer = Buffer.concat([indicesBuffer, positionsBuffer, normalsBuffer, uvsBuffer]); var testGltf = { - "accessors": [ + accessors: [ { - "bufferView": 0, - "byteOffset": 0, - "componentType": 5123, - "count": 6, - "type": "SCALAR" + bufferView: 0, + byteOffset: 0, + componentType: 5123, + count: 6, + type: 'SCALAR' }, { - "bufferView": 1, - "byteOffset": 0, - "componentType": 5126, - "count": 4, - "type": "VEC3" + bufferView: 1, + byteOffset: 0, + componentType: 5126, + count: 4, + type: 'VEC3' }, { - "bufferView": 2, - "byteOffset": 0, - "componentType": 5126, - "count": 4, - "type": "VEC3" + bufferView: 2, + byteOffset: 0, + componentType: 5126, + count: 4, + type: 'VEC3' }, { - "bufferView": 3, - "byteOffset": 0, - "componentType": 5126, - "count": 4, - "type": "VEC2" + bufferView: 3, + byteOffset: 0, + componentType: 5126, + count: 4, + type: 'VEC2' } ], - "bufferViews": [ + bufferViews: [ { - "buffer": 0, - "byteOffset": 0, - "byteLength": 6 * 2, - "target": 34963 + buffer: 0, + byteOffset: 0, + byteLength: 6 * 2, + target: 34963 }, { - "buffer": 0, - "byteOffset": 6 * 2, - "byteLength": 4 * 3 * 4, - "target": 34962 + buffer: 0, + byteOffset: 6 * 2, + byteLength: 4 * 3 * 4, + target: 34962 }, { - "buffer": 0, - "byteOffset": 6 * 2 + (4 * 3 * 4), - "byteLength": 4 * 3 * 4, - "target": 34962 + buffer: 0, + byteOffset: 6 * 2 + (4 * 3 * 4), + byteLength: 4 * 3 * 4, + target: 34962 }, { - "buffer": 0, - "byteOffset": 6 * 2 + (4 * 3 * 4) * 2, - "byteLength": 4 * 2 * 4, - "target": 34962 + buffer: 0, + byteOffset: 6 * 2 + (4 * 3 * 4) * 2, + byteLength: 4 * 2 * 4, + target: 34962 } ], - "buffers": [ + buffers: [ { - "uri": "data:", - "byteLength": indicesLength * 2 + (positionsLength + normalsLength + uvsLength) * 4, - "extras": { - "_pipeline": { - "source": dataBuffer + byteLength: indicesLength * 2 + (positionsLength + normalsLength + uvsLength) * 4, + extras: { + _pipeline: { + source: dataBuffer } } } ], - "scene": 0, - "scenes": [ + scene: 0, + scenes: [ { - "nodes": [ + nodes: [ 0 ] } ], - "nodes": [ + nodes: [ { - "children": [], - "matrix": [ + children: [], + matrix: [ 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1 ], - "mesh": 0, - "name": "square", - "extras": { - "_pipeline": {} + mesh: 0, + name: 'square', + extras: { + _pipeline: {} } } ], - "meshes": [ + meshes: [ { - "name": "square", - "primitives": [ + name: 'square', + primitives: [ { - "attributes": { - "POSITION": 1, - "NORMAL": 2, - "TEXCOORD_0": 3, + attributes: { + POSITION: 1, + NORMAL: 2, + TEXCOORD_0: 3, }, - "indices": 0, - "extras": { - "_pipeline": {} + indices: 0, + extras: { + _pipeline: {} } } ] @@ -264,7 +263,7 @@ describe('AmbientOcclusion', function() { // check ao buffers var aoBuffersByPrimitive = raytracerScene.aoBufferByPrimitive; - var aoBuffer = aoBuffersByPrimitive.mesh_square_0; + var aoBuffer = aoBuffersByPrimitive['0_0']; expect(aoBuffer).toBeDefined(); expect(aoBuffer.resolution).toEqual(10); @@ -399,15 +398,13 @@ describe('AmbientOcclusion', function() { var boxOverGroundGltfClone = cloneGltfWithJimps(boxOverGroundGltf); // remove some images - var imageID = 'Untitled'; - var image = boxOverGroundGltfClone.images[imageID]; - boxOverGroundGltfClone.images = {}; - boxOverGroundGltfClone.images[imageID] = image; + var image = boxOverGroundGltfClone.images[0]; + boxOverGroundGltfClone.images = [image]; var textures = boxOverGroundGltfClone.textures; for (var textureID in textures) { if (textures.hasOwnProperty(textureID)) { var texture = textures[textureID]; - texture.source = imageID; + texture.source = 0; } } @@ -418,24 +415,22 @@ describe('AmbientOcclusion', function() { }; bakeAmbientOcclusion(boxOverGroundGltfClone, options); - expect(Object.keys(boxOverGroundGltfClone.images).length).toEqual(2); - expect(Object.keys(boxOverGroundGltfClone.textures).length).toEqual(2); - expect(Object.keys(boxOverGroundGltfClone.materials).length).toEqual(3); + expect(boxOverGroundGltfClone.images.length).toEqual(2); + expect(boxOverGroundGltfClone.textures.length).toEqual(2); + expect(boxOverGroundGltfClone.materials.length).toEqual(3); }); it('adds additional textures as needed', function() { var boxOverGroundGltfClone = cloneGltfWithJimps(boxOverGroundGltf); // remove some textures - var textureID = 'texture_Untitled'; - var texture = boxOverGroundGltfClone.textures[textureID]; - boxOverGroundGltfClone.textures = {}; - boxOverGroundGltfClone.textures[textureID] = texture; + var texture = boxOverGroundGltfClone.textures[1]; + boxOverGroundGltfClone.textures = [texture]; var materials = boxOverGroundGltfClone.materials; for (var materialID in materials) { if (materials.hasOwnProperty(materialID)) { - materials[materialID].values.diffuse = textureID; + materials[materialID].values.diffuse = [0]; } } @@ -446,23 +441,21 @@ describe('AmbientOcclusion', function() { }; bakeAmbientOcclusion(boxOverGroundGltfClone, options); - expect(Object.keys(boxOverGroundGltfClone.images).length).toEqual(3); // 1 unused image and 2 images with AO - expect(Object.keys(boxOverGroundGltfClone.textures).length).toEqual(2); - expect(Object.keys(boxOverGroundGltfClone.materials).length).toEqual(3); + expect(boxOverGroundGltfClone.images.length).toEqual(3); // 1 unused image and 2 images with AO + expect(boxOverGroundGltfClone.textures.length).toEqual(2); + expect(boxOverGroundGltfClone.materials.length).toEqual(3); }); it('adds additional materials as needed', function() { var boxOverGroundGltfClone = cloneGltfWithJimps(boxOverGroundGltf); // remove some materials - var materialID = 'Material-effect'; - var material = boxOverGroundGltfClone.materials[materialID]; - boxOverGroundGltfClone.materials = {}; - boxOverGroundGltfClone.materials[materialID] = material; + var material = boxOverGroundGltfClone.materials[0]; + boxOverGroundGltfClone.materials = [material]; var scene = boxOverGroundGltfClone.scenes[boxOverGroundGltfClone.scene]; var primitiveFunction = function(primitive) { - primitive.material = materialID; + primitive.material = 0; }; NodeHelpers.forEachPrimitiveInScene(boxOverGroundGltfClone, scene, primitiveFunction, {}); @@ -483,11 +476,10 @@ describe('AmbientOcclusion', function() { var boxOverGroundGltfClone = cloneGltfWithJimps(boxOverGroundGltf); // remove some textures - var textureID = 'texture_Untitled'; var materials = boxOverGroundGltfClone.materials; for (var materialID in materials) { if (materials.hasOwnProperty(materialID)) { - if (materials[materialID].values.diffuse === textureID) { + if (materials[materialID].values.diffuse[0] === 1) { materials[materialID].values.diffuse = [1.0, 1.0, 1.0, 1.0]; } } @@ -500,9 +492,9 @@ describe('AmbientOcclusion', function() { }; bakeAmbientOcclusion(boxOverGroundGltfClone, options); - expect(Object.keys(boxOverGroundGltfClone.images).length).toEqual(3); // 1 unused image and 2 images with AO - expect(Object.keys(boxOverGroundGltfClone.textures).length).toEqual(3); // 1 unused texture, 2 with AO - expect(Object.keys(boxOverGroundGltfClone.materials).length).toEqual(4); // 1 unused material, 2 with AO + expect(boxOverGroundGltfClone.images.length).toEqual(3); // 1 unused image and 2 images with AO + expect(boxOverGroundGltfClone.textures.length).toEqual(3); // 1 unused texture, 2 with AO + expect(boxOverGroundGltfClone.materials.length).toEqual(4); // 1 unused material, 2 with AO }); it('adds a buffer, bufferView, and an accessor for each primitive when baking AO to vertices', function() { @@ -514,13 +506,13 @@ describe('AmbientOcclusion', function() { }; bakeAmbientOcclusion(boxOverGroundGltfClone, options); - expect(Object.keys(boxOverGroundGltfClone.accessors).length).toEqual(10); - var cubeMeshPrimitives = boxOverGroundGltfClone.meshes.Cube_mesh.primitives; - expect(cubeMeshPrimitives[0].attributes._OCCLUSION).toEqual('accessor_Cube_mesh_0_AO'); + expect(boxOverGroundGltfClone.accessors.length).toEqual(10); + var cubeMeshPrimitives = boxOverGroundGltfClone.meshes[0].primitives; + expect(cubeMeshPrimitives[0].attributes._OCCLUSION).toEqual(8); - expect(boxOverGroundGltfClone.buffers.aoBuffer).toBeDefined(); - expect(boxOverGroundGltfClone.bufferViews.aoBufferView).toBeDefined(); - expect(boxOverGroundGltfClone.bufferViews.aoBufferView.byteLength).toEqual(72 * 4); + expect(boxOverGroundGltfClone.buffers.length).toEqual(2); + expect(boxOverGroundGltfClone.bufferViews.length).toEqual(3); + expect(boxOverGroundGltfClone.bufferViews[2].byteLength).toEqual(72 * 4); }); it('clones the shading chain as needed for primitives that should not have AO', function() { @@ -532,19 +524,19 @@ describe('AmbientOcclusion', function() { }; bakeAmbientOcclusion(boxOverGroundGltfClone, options); - expect(Object.keys(boxOverGroundGltfClone.materials).length).toEqual(4); - expect(Object.keys(boxOverGroundGltfClone.techniques).length).toEqual(2); - expect(Object.keys(boxOverGroundGltfClone.programs).length).toEqual(2); - expect(Object.keys(boxOverGroundGltfClone.shaders).length).toEqual(4); + expect(boxOverGroundGltfClone.materials.length).toEqual(4); + expect(boxOverGroundGltfClone.techniques.length).toEqual(2); + expect(boxOverGroundGltfClone.programs.length).toEqual(2); + expect(boxOverGroundGltfClone.shaders.length).toEqual(4); - var usedPrimitives = boxOverGroundGltfClone.meshes.Cube_mesh.primitives; - expect(usedPrimitives[0].material).toEqual('Material-effect'); + var usedPrimitives = boxOverGroundGltfClone.meshes[0].primitives; + expect(usedPrimitives[0].material).toEqual(0); - var unusedPrimitives = boxOverGroundGltfClone.meshes.useless_mesh.primitives; - expect(unusedPrimitives[0].material).toEqual('Material_001-effect_noAO'); - expect(unusedPrimitives[1].material).toEqual('Material_001-effect_noAO'); - expect(unusedPrimitives[2].material).toEqual('useless-material'); - expect(unusedPrimitives[3].material).toEqual('useless-material'); + var unusedPrimitives = boxOverGroundGltfClone.meshes[2].primitives; + expect(unusedPrimitives[0].material).toEqual(3); + expect(unusedPrimitives[1].material).toEqual(3); + expect(unusedPrimitives[2].material).toEqual(2); + expect(unusedPrimitives[3].material).toEqual(2); }); it('it can sample occlusion just at a triangle center', function() { @@ -659,7 +651,7 @@ describe('AmbientOcclusion', function() { expect(options.rayDistance).toEqual(-1); expect(options.nearCull).toEqual(0.0001); expect(options.shaderMode).toEqual('blend'); - expect(options.sceneID).toEqual('defaultScene'); + expect(options.sceneID).toEqual(0); aoOptions = { quality: 'medium' @@ -675,7 +667,7 @@ describe('AmbientOcclusion', function() { expect(options.rayDistance).toEqual(-1); expect(options.nearCull).toEqual(0.0001); expect(options.shaderMode).toEqual('blend'); - expect(options.sceneID).toEqual('defaultScene'); + expect(options.sceneID).toEqual(0); aoOptions = { quality: 'high' @@ -691,7 +683,7 @@ describe('AmbientOcclusion', function() { expect(options.rayDistance).toEqual(-1); expect(options.nearCull).toEqual(0.0001); expect(options.shaderMode).toEqual('blend'); - expect(options.sceneID).toEqual('defaultScene'); + expect(options.sceneID).toEqual(0); }); it('overwrites parameters in base options when advanced settings are specified', function() { @@ -712,7 +704,7 @@ describe('AmbientOcclusion', function() { expect(options.rayDistance).toEqual(10.0); expect(options.nearCull).toEqual(0.0001); expect(options.shaderMode).toEqual('blend'); - expect(options.sceneID).toEqual('defaultScene'); + expect(options.sceneID).toEqual(0); }); it('has a helper that can extract a function call from a shader', function() { diff --git a/specs/lib/processModelMaterialsCommonSpec.js b/specs/lib/processModelMaterialsCommonSpec.js index 1ccc8709..af959ad6 100644 --- a/specs/lib/processModelMaterialsCommonSpec.js +++ b/specs/lib/processModelMaterialsCommonSpec.js @@ -108,7 +108,7 @@ describe('processModelMaterialsCommon', function() { addDefaults(gltf); addPipelineExtras(gltf); processModelMaterialsCommon(gltf); - expect(gltf.materials.length).toBeGreaterThan(0) + expect(gltf.materials.length).toBeGreaterThan(0); expect(gltf.techniques.length).toBeGreaterThan(0); var materialsLength = gltf.materials.length; for (var materialId = 0; materialId < materialsLength; materialId++) { @@ -229,29 +229,26 @@ describe('processModelMaterialsCommon', function() { it('splits two materials with different types for JOINT and WEIGHT', function() { var gltf = { - accessors: { - jointAccessor_0: { + accessors: [ + { componentType: WebGLConstants.FLOAT, type: 'VEC4' - }, - weightAccessor_0: { + }, { componentType: WebGLConstants.FLOAT, type: 'VEC4' - }, - jointAccessor_1: { + }, { componentType: WebGLConstants.FLOAT, type: 'MAT3' - }, - weightAccessor_1: { + }, { componentType: WebGLConstants.FLOAT, type: 'MAT3' } - }, + ], extensionsUsed: [ 'KHR_materials_common' ], - materials: { - material: { + materials: [ + { extensions: { KHR_materials_common: { jointCount: 14, @@ -259,35 +256,34 @@ describe('processModelMaterialsCommon', function() { } } } - }, - meshes: { - meshVec4: { + ], + meshes: [ + { primitives: [{ attributes: { - JOINT: 'jointAccessor_0', - WEIGHT: 'weightAccessor_0' + JOINT: 0, + WEIGHT: 1 }, - material: 'material' + material: 0 }] - }, - meshMat3: { + }, { primitives: [{ attributes: { - JOINT: 'jointAccessor_1', - WEIGHT: 'weightAccessor_1' + JOINT: 2, + WEIGHT: 3 }, - material: 'material' + material: 0 }] } - } + ] }; addDefaults(gltf); addPipelineExtras(gltf); processModelMaterialsCommon(gltf); var meshes = gltf.meshes; - var primitiveVec4 = meshes.meshVec4.primitives[0]; - var primitiveMat3 = meshes.meshMat3.primitives[0]; + var primitiveVec4 = meshes[0].primitives[0]; + var primitiveMat3 = meshes[1].primitives[0]; var materialVec4Id = primitiveVec4.material; var materialMat3Id = primitiveMat3.material; expect(materialVec4Id).not.toEqual(materialMat3Id); From 94ee8e5e5d49369412539ea84443a60ba2499376 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 12:04:44 -0400 Subject: [PATCH 35/47] Removed riggedSimpleUnoptimized --- .../riggedSimpleUnoptimized/riggedSimple.bin | Bin 10468 -> 0 bytes .../riggedSimpleUnoptimized/riggedSimple.glb | Bin 18745 -> 0 bytes .../riggedSimpleUnoptimized/riggedSimple.gltf | 620 ------------------ .../riggedSimple0FS.glsl | 24 - .../riggedSimple0VS.glsl | 19 - .../riggedSimple_Embedded.gltf | 588 ----------------- 6 files changed, 1251 deletions(-) delete mode 100644 specs/data/riggedSimpleUnoptimized/riggedSimple.bin delete mode 100644 specs/data/riggedSimpleUnoptimized/riggedSimple.glb delete mode 100644 specs/data/riggedSimpleUnoptimized/riggedSimple.gltf delete mode 100644 specs/data/riggedSimpleUnoptimized/riggedSimple0FS.glsl delete mode 100644 specs/data/riggedSimpleUnoptimized/riggedSimple0VS.glsl delete mode 100644 specs/data/riggedSimpleUnoptimized/riggedSimple_Embedded.gltf diff --git a/specs/data/riggedSimpleUnoptimized/riggedSimple.bin b/specs/data/riggedSimpleUnoptimized/riggedSimple.bin deleted file mode 100644 index 4a7b5453f7f21935edfe01cadea2ea9fb26e5a9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10468 zcmeHL3vgA{72QCH5ko}2ks_rSW1xtEyZ|A*djkO?f+!GB3}uv$UJ4bsHxS~CwE`CGRBVTi7MOO_%+S&g9cF>X}Nl)nmE0Dg3&6gtV%ai-0AAau#T0iLzf8H$?P$S~B`S{_ENt>h8Z-BO052kG)C`q5lQ zpf^orB>L1?MxkeoWHkDhCS%acR2hrDHju~A;}jW(ekaR#^gc-*2jjZ(1il5ooJNvP zBUz`BqSI)g(@526r0Fyo=`^IFnb^&}^YF9`I~ZT0*{2|82A=a-nXXU5N>8Yz0LthNZ=rl&DsU~5#kiKp zQe4ZRqTceH`~cVU@RrL8XltdsfbU+iN> zacu@>0coUa?jx%8QDyPWQfoJsYs25YdY@a=GSOtxsQ7oZj$@z`BpByDt=- zhx_|6hx?%De((lhI{l&O&hQ3eY7aos9pOEMc|Hh5w}&?va~=dmXTmGS{D(l%ZQ%`r zE`~zUt>HZay*vy>w}kg7bTk}_ZVqoG^fdyCZVYcUbT&5T5&V_kr{hXX%dcVp`bMOARSl7=+o^!?yJLV^+AM^g2lZcnXK#q#H+`!I?t#U}XANs}wvm5e@%PEU z&CPGH-heY>Ue4+r%&gD6o$OD*8k8qy%NlAXdF*Gv8n_NF{vOmY(%Vb!LB$_h?B+VS z`!z>1chAq%{s*kV#7{sCudP4G`39_k>%Rs*YiM|?+M{+@1J|h+@}>{IJ~cD7@O`hk zwnkkCU)JcKgvL&Pp*_)c@MTZ@N@&vVl|6UP-)MLuI2xUY{r8vE9QQUX)}H&@p!v~{;#t~u{K-{y>S&Ai9J#|5r~{#4rUNv;Ez zy{fd|x7=&q$;317ZRRrX_ABY!?!P@3dtUY&sU0(4d+zbtFq*No#Jxsiw)U9IXwudy z6=3wtoF>NBJauQZ4a`gD1+l)#MXeb<125(bnzP9mb7r~MoMmDf4Fm7ed%%7_kmv4_ z`9YUEKaKu;Xr1B&2eGDeqhep6>(v~*2B}Ih;^|?;}Pp(kH!Pr zMGl`FfbAlOPkeB3!O16|&t9ADPJOz_uf{s~>i-&{R-fm?XuhysZa|xj7(Qnl z{+mKeWjRsb<6h}oG%4`z|qfthxwm!u;b6yxjcu9QhuGe z*)@|dVeV|-NNd3;A=?-Tur?MM9G|9gLKbiMKUu67^a rfBW9{iF3X0<8xf^di&eyp?Z>|WtD(Gh diff --git a/specs/data/riggedSimpleUnoptimized/riggedSimple.glb b/specs/data/riggedSimpleUnoptimized/riggedSimple.glb deleted file mode 100644 index f442af824e006bd1ffcb302c9ea1de5c613eaed2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18745 zcmeHO4RBo5b-ozmIF9WQejP$wb>ld)vsT{QefuX{`z*_{5ZJPjWCIaqd6J%_#k(u9 zyRt0{VH0Zp(g1<*lZ1xAvNGVvHr)8LR&kD)<=>SbcqVp)i~; z1RBQ!?VGlxn)6w!IGVRpEn}HY2HL$I@+XzeqT@WcfI-?KY+Hv{GdZnCfi7$94>b1ZK|N?R zL}C#wmPqKagcghG(cS2!F!!v}gY>VKfQZ_z)|Rjbc}SZRay=0O7Bz5l0IxM9@DmLs z;*p3Ri6jgoSffd=x>KWfU9C16GM$6r*qj^;#|^)OoPE<%(vuynAr#faiC7{Yi)w~$ zAUax5b3M`;V&QmH(-ZMfBoU5;!76lffhvA4t&O=QC~9aYf?xN-ofcg#ooyDgKQ%Kz z{{+`V@tN6rkZ{-K+7C0VA_d|3O?t!>(j9A4XTyf#R#6)m9 zZNC_5ltsh)WrPl;+Fod(kXXtq=@q6<<#XwxS35QCXbg>*}n$)qNh;BabP2{F>hx_GsW~sCT;gOXGVss zKw~jKYE#efKstj{0M0ZcX$-x{?rqzOA$zfGVSz`B-hizgCB)N24b`I!UudeAbhv>= zrvWN1IIlC+o6cGJvD6^WQ&3O)=&g2ckXHC`TJ z6E+gjuur{mcb-*!JV9FlRlOe3u&q<|he*HUZ8apyR&iD%I4AgQXht+%ORKUWoLwtz z&^*X>EfFIQIVgD!{h2}*#g^2{=dCf3QAdx=pRUJZ*d&bRi9h{T(P|9RO%>-h+)2_F z?F7aH+r$N}kLzq4iTn8dK8HIbMyb8DG}wJZx%8Ez)aBMSVx^TCwYfek+ndHg8Ji4# zj0n;}s6Rb0Fj~N%9xyhBL`O6|q#KF2judGP(J&pta0H7cjCec}MpFnOFwh)LXwgty zi*Pk|HeGPIujnoerE}>V4*fWmg8_vRyKgjOVY0zi1e%0){>4Zx1cD&kz;J6d$cpTE7mqZ?6>4;)fB6a@nv+dH>4Z&jOdm<ZjqAj2b1YqrcBI@HX_yg^`?o*Wnxa5osp z;ezKxJ_I2@`-ak){=7|Rb7wz?{6K9!?VRPEq-i+Q*Qh~Mgvr$iGkjNALo>hQV#pQ4 z*t&E$d=fiIp+#J|Yd+;HrWr8<(+U$S7Dm;LjkJLJqC~nCZd2TNkMQY$CMz< zfkAQ(_PFZS@i_<>B4(}`Cl(1TP>t=zFvWoJ9PT;b*&)M=D$kFj@mT znBnlhItwr(ssJxZ?c9;-rqj*9a6Ze|RNSuzajM|cP1K!Jm%4291gsRF4S-;!au{o6 zcy(mBfRzS!b!y*drw50M0hk-eTZ36Frd>l8o?K$m=hK6Oc7Ioz&TiV4E{NmaU$pnv z7TDFrp%wbD1Hs^ad%(hGql;hC^g%Pn>*+vh#k$cW{AR{U|WRxfg{aQ987G zZaBe!y}xMZXx-+6Yuw1HH)Eizaf9Ydx5p?v^BDEt01{46? zkNA(+Sdou+6;0=8&t`AJP(I38>t}dgt*oMeBc_70^vY#cOdbi8r{29sb06F*zUNVi ziMyL1W}~xQs|0NX52iA;F;I)NjRC=4#Lj!ncJ~DeS)x&hxtjxjNA-5^?{Vf3VqdVc zR<4-t1831@?KEk~IzQ=-hsOYYX47C?k1Dl--t03jJpYFjO~QvP0%TFv5#X?0gjc$QQZd ztfNS1brpqjJnnJUDm!QO(y^!~l)z>@gc~K@m_~DHT8TN!M^i4<0jTk2C&}=T-qT4{^@mparMY+Ppw({Iv@Y_ zht@V-x%05uw)2#Yr0--=rmr)0%gCRXT8V$#5)poMA_1(i8>6?CP)gQTP(fZTx`&oF^{OIbu+vaZXJ??C$<9JKo2@|k zBs&M?Q|w%nPqURMf57Tc{*VPwKEqa_e3q?7`5dc9S;N+%e4YhS*0BbZFE9j&Zm%*JnqZ_36(o{dF38;f~1mhfyW<=I%yvvDfV#%VkoXYg#C z#j~-3XX6~6jdOW6R`P7r@oWTmHdgU$tmfIM=h;}xvk~OkXyDnP7-`6Zf$uP4XCM>p zC^4Rm1kc8L4_2fsL}g`0Qi*@fl+W z@EJ!wo7h!s0-vkdL3|FeYw-CJbS9xWjn5v`vd~7l3S7@#jMsGGiYh1%!eC#(d<{pe_f%NrU@@8)9cHa9fu4gmqZ9v`1*}VmfPT=}{fzeA)>jh6OFnSSc{orpO7`*_s zEr_@cX4B81%JRY6j(q26Tk;2IjPv^98z!5=N8T>?9elY|e{3?j>)H%&@BX2gd}rd# zaya}qrN2!qH$V4_Zr=W;@#W;@yIv|UTJcipKNd#JHx@>CyRq)EBue>`O+P8ce$j1W z3~z^Q5@X873qLABxA~D{lV!pH-AULe-}DbhOTc0R6K@BW zHaO;6-%0MiuC4UntDfQV$KV6Cll*V4pKSX1_ns^bKtK5)^?w3B+>$AAJa57WY8QBt zi?4c=<0l`eo$#NIvS{&lxxeHCwF`ff_l6!S0eg~cP&?@+AO7;}2TK&sAHxS~e+O6y z(~CcTpky9^Itze@h?mL6dTgNWyOOfV6P~6%H+eH z;fDx+MZsSt{B?cJ{9tT<3w)Bhhy0i#j`>_P&=@cpMVdS zmYyW+mBash_T$tJ?B!!Gu73RL)ja+c@WvteNol-J zcB8L2ww{IV`lW{{<{msG4|_?e2ljZK^nd)V`+5Bl=!OkmuZQkWzVQmLKLh;IN5T&q zyj}Gj@<}NVJxQqt`jb?I-K4Y&JV}X%bYCdqM!NNzS4#YD3`w3aNj-#>>ZDu7hwRE2 z5+3rIWPqP?#OvzXMZU;2P0h8+8I@Nm_f$@*yd}O!ZmaxP=ZHFw)VZe4M|IAs^IcsN z)OAB$TWIde`A+j&&T(p!>lpBu(3?bjj;QM-wL>q(>WI4D(pb4BlRmj_lP$TnPsejL z{%T&-e5rXP?#TSAdG~Weaz^D6jg=fzxkt7nCsnQz10 z-O<~YyzssQ6@7BFX~9#^CGS|ahs#`g+hp>Evoe)`d~USq=q1a{$8PGXJOcT1{&Sgm z?pSx_8ptnxGi;(%o`%k`#|#st^5FBMO^`J)hRZ|N#279Q-6m|52?KPSuu&%cz+wVZ znehDj+Xu}26>a6CXa`BBPr$B_Pb%_Bk{9}uivA?&7kEs{&4+4LMazOZt-!m!`j~eC$&`-G{AB4XZ@`2<#mhY+Tf8x31rd2%t74kvE zzd}9`9^wLVg76bx2)BqouZ#GTyv$cc=8L$a()7m`za ztPp14Efa3SO!_1z377M8h~uhN7jfo1r+&o0LipidS#sVPN59o)5Z?Mp&$X2go;F@- zxn?Pz7ch4Fy9X=JqyF#zGFiUwnoMQkmzHj5i7&78{=A#lX?{q~x11cQP&oh@>L)pp zr*Sl%>ZF@&kbcrlHb}o{Pg1*(Pm;XQV{*HWev|YI47^=n<8^`GRPdXmAMHul;O&r4 z!iJ+WzTAWjsow;CuAkaqgSV3`jS=`w(k1Yl3Vv$mehGQ*uh3Hw_(?yH59ub~s9oUU zb%E23Kk27?qw_sq{{Z5^bLi;x&IQHRamk##;Lwv&&+ix>;P9Ul(>YfRs{Gq0)yD8H zJM;l#Q+*~x-s@A&Y%<^e+2N#$wOVIvzJESG^Zb~8etg*T$!~AAYybT9U(YuF{qFyL z+ke0Pnb+sNpUlT&J|61+VV)1aZ$5alQTxh|(JwXM?~jQ0dOkkhc=)gWzsKjp_SbK3 zwrhX<)oZm*dOqlDzl{&t-n@PZ!J-ZX8Vn(s`M*u1QqV2kd%@dkqaE!1%+$;XFj> zqF!qV)>VruBaqjU(i>bU#SN}myh1AtDZYpv=u^X0wc@^Vi?LEG7nT=jm+E-Cyg<9q z(y)K*K;7CVL}h<{|8TM12}O{?LSEt@kgp+c2|o`4AM*L8Iz@xOOWG$<*(amo=*SQD z)~$6_Six$Q>Tq7YMvr87)+!Ra<=f3Yq21ojFgn$jm%Y6-)b|4PR002s%#f(TYz~C}x&kj& zBlZ$%!+ykF!H2&bs~7$?>|aA* Date: Tue, 21 Mar 2017 12:08:07 -0400 Subject: [PATCH 36/47] Delete generateTangentsBitangents models --- ...iumTexturedBoxTest_TangentsBitangents.gltf | 313 ------------------ 1 file changed, 313 deletions(-) delete mode 100644 specs/data/generateTangentsBitangents/CesiumTexturedBoxTest_TangentsBitangents.gltf diff --git a/specs/data/generateTangentsBitangents/CesiumTexturedBoxTest_TangentsBitangents.gltf b/specs/data/generateTangentsBitangents/CesiumTexturedBoxTest_TangentsBitangents.gltf deleted file mode 100644 index 91df1d0e..00000000 --- a/specs/data/generateTangentsBitangents/CesiumTexturedBoxTest_TangentsBitangents.gltf +++ /dev/null @@ -1,313 +0,0 @@ -{ - "accessors": { - "accessor_21": { - "bufferView": "bufferView_1", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR", - "min": [ - 0 - ], - "max": [ - 23 - ] - }, - "accessor_23": { - "bufferView": "bufferView_0", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 0.5, - 0.5, - 0.5 - ], - "min": [ - -0.5, - -0.5, - -0.5 - ], - "type": "VEC3" - }, - "accessor_25": { - "bufferView": "bufferView_0", - "byteOffset": 288, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 1, - 1, - 1 - ], - "min": [ - -1, - -1, - -1 - ], - "type": "VEC3" - }, - "accessor_27": { - "bufferView": "bufferView_0", - "byteOffset": 576, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 6, - 1 - ], - "min": [ - 0, - 0 - ], - "type": "VEC2" - }, - "accessor_tangent": { - "bufferView": "bufferView_0", - "byteOffset": 768, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "type": "VEC3", - "min": [ - -1, - 0, - 0 - ], - "max": [ - 1, - 0, - 1 - ] - }, - "accessor_bitangent": { - "bufferView": "bufferView_0", - "byteOffset": 1056, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "type": "VEC3", - "min": [ - 0, - -1, - 0 - ], - "max": [ - 0, - 1, - 1 - ] - } - }, - "animations": {}, - "asset": { - "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", - "premultipliedAlpha": true, - "profile": { - "api": "WebGL", - "version": "1.0.2" - }, - "version": "1.0" - }, - "bufferViews": { - "bufferView_0": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 1344, - "byteOffset": 0, - "target": 34962 - }, - "bufferView_1": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 1344, - "target": 34963 - } - }, - "buffers": { - "CesiumTexturedBoxTest": { - "type": "arraybuffer", - "byteLength": 1416, - "uri": "data:application/octet-stream;base64,AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAIAAAIA/AAAAAAAAAIAAAIA/AAAAAAAAAIAAAIA/AAAAAAAAAIAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA" - } - }, - "images": { - "Image0001": { - "name": "Image0001", - "uri": "data:image/png;base64,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" - } - }, - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001", - "shininess": 256, - "specular": [ - 0.2, - 0.2, - 0.2, - 1 - ] - } - } - }, - "meshes": { - "Geometry-mesh002": { - "name": "Mesh", - "primitives": [ - { - "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27", - "TANGENT": "accessor_tangent", - "BITANGENT": "accessor_bitangent" - }, - "indices": "accessor_21", - "material": "Effect-Texture", - "mode": 4 - } - ] - } - }, - "nodes": { - "rootNode": { - "children": [], - "meshes": [ - "Geometry-mesh002" - ], - "matrix": [ - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1 - ] - } - }, - "programs": { - "program_0": { - "attributes": [ - "a_normal", - "a_position", - "a_texcoord0" - ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" - } - }, - "samplers": { - "sampler_0": { - "magFilter": 9729, - "minFilter": 9987, - "wrapS": 10497, - "wrapT": 10497 - } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { - "nodes": [ - "rootNode" - ] - } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Owp2YXJ5aW5nIHZlYzMgdl9ub3JtYWw7CnZhcnlpbmcgdmVjMiB2X3RleGNvb3JkMDsKdW5pZm9ybSBzYW1wbGVyMkQgdV9kaWZmdXNlOwp1bmlmb3JtIHZlYzQgdV9zcGVjdWxhcjsKdW5pZm9ybSBmbG9hdCB1X3NoaW5pbmVzczsKdm9pZCBtYWluKHZvaWQpIHsKdmVjMyBub3JtYWwgPSBub3JtYWxpemUodl9ub3JtYWwpOwp2ZWM0IGNvbG9yID0gdmVjNCgwLiwgMC4sIDAuLCAwLik7CnZlYzQgZGlmZnVzZSA9IHZlYzQoMC4sIDAuLCAwLiwgMS4pOwp2ZWM0IHNwZWN1bGFyOwpkaWZmdXNlID0gdGV4dHVyZTJEKHVfZGlmZnVzZSwgdl90ZXhjb29yZDApOwpzcGVjdWxhciA9IHVfc3BlY3VsYXI7CmRpZmZ1c2UueHl6ICo9IG1heChkb3Qobm9ybWFsLHZlYzMoMC4sMC4sMS4pKSwgMC4pOwpjb2xvci54eXogKz0gZGlmZnVzZS54eXo7CmNvbG9yID0gdmVjNChjb2xvci5yZ2IgKiBkaWZmdXNlLmEsIGRpZmZ1c2UuYSk7CmdsX0ZyYWdDb2xvciA9IGNvbG9yOwp9Cg==" - }, - "CesiumTexturedBoxTest0VS": { - "type": 35633, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0OwphdHRyaWJ1dGUgdmVjMyBhX3Bvc2l0aW9uOwphdHRyaWJ1dGUgdmVjMyBhX25vcm1hbDsKdmFyeWluZyB2ZWMzIHZfbm9ybWFsOwp1bmlmb3JtIG1hdDMgdV9ub3JtYWxNYXRyaXg7CnVuaWZvcm0gbWF0NCB1X21vZGVsVmlld01hdHJpeDsKdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsKYXR0cmlidXRlIHZlYzIgYV90ZXhjb29yZDA7CnZhcnlpbmcgdmVjMiB2X3RleGNvb3JkMDsKdm9pZCBtYWluKHZvaWQpIHsKdmVjNCBwb3MgPSB1X21vZGVsVmlld01hdHJpeCAqIHZlYzQoYV9wb3NpdGlvbiwxLjApOwp2X25vcm1hbCA9IHVfbm9ybWFsTWF0cml4ICogYV9ub3JtYWw7CnZfdGV4Y29vcmQwID0gYV90ZXhjb29yZDA7CmdsX1Bvc2l0aW9uID0gdV9wcm9qZWN0aW9uTWF0cml4ICogcG9zOwp9Cg==" - } - }, - "skins": {}, - "techniques": { - "technique0": { - "attributes": { - "a_normal": "normal", - "a_position": "position", - "a_texcoord0": "texcoord0" - }, - "parameters": { - "diffuse": { - "type": 35678 - }, - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "normal": { - "semantic": "NORMAL", - "type": 35665 - }, - "normalMatrix": { - "semantic": "MODELVIEWINVERSETRANSPOSE", - "type": 35675 - }, - "position": { - "semantic": "POSITION", - "type": 35665 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - }, - "shininess": { - "type": 5126 - }, - "specular": { - "type": 35666 - }, - "texcoord0": { - "semantic": "TEXCOORD_0", - "type": 35664 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_diffuse": "diffuse", - "u_modelViewMatrix": "modelViewMatrix", - "u_normalMatrix": "normalMatrix", - "u_projectionMatrix": "projectionMatrix", - "u_shininess": "shininess", - "u_specular": "specular" - } - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 - } - }, - "extensionsUsed": [], - "cameras": {} -} From 9fc99cc97216f495c7152247244feca41545c058 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 12:11:09 -0400 Subject: [PATCH 37/47] Don't look for slots in array, just append --- lib/addToArray.js | 7 ------- lib/getAvailableArraySlot.js | 16 ---------------- 2 files changed, 23 deletions(-) delete mode 100644 lib/getAvailableArraySlot.js diff --git a/lib/addToArray.js b/lib/addToArray.js index ef53949e..63311e35 100644 --- a/lib/addToArray.js +++ b/lib/addToArray.js @@ -1,14 +1,7 @@ 'use strict'; -var getAvailableArraySlot = require('./getAvailableArraySlot'); - module.exports = addToArray; function addToArray(array, element) { - var index = getAvailableArraySlot(array); - if (index >= array.length) { array.push(element); return array.length - 1; - } - array[index] = element; - return index; } \ No newline at end of file diff --git a/lib/getAvailableArraySlot.js b/lib/getAvailableArraySlot.js deleted file mode 100644 index 9e912ac2..00000000 --- a/lib/getAvailableArraySlot.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; -var Cesium = require('cesium'); - -var defined = Cesium.defined; - -module.exports = getAvailableArraySlot; - -function getAvailableArraySlot(array) { - var arrayLength = array.length; - for (var i = 0; i < arrayLength; i++) { - if (!defined(array[i])) { - return i; - } - } - return arrayLength; -} \ No newline at end of file From d1724392670ac215a431e5dcdf6e64e62def096f Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 12:58:19 -0400 Subject: [PATCH 38/47] Small fixes from testing --- lib/MergeDuplicateProperties.js | 5 ++--- lib/Pipeline.js | 6 +++++- lib/combineNodes.js | 5 +++-- lib/loadGltfUris.js | 25 ++++++++++++++++++++++--- lib/updateVersion.js | 25 +++++++++++++++++++++++-- 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/lib/MergeDuplicateProperties.js b/lib/MergeDuplicateProperties.js index 1d5548b9..02903e0c 100644 --- a/lib/MergeDuplicateProperties.js +++ b/lib/MergeDuplicateProperties.js @@ -3,10 +3,10 @@ var Cesium = require('cesium'); var clone = require('clone'); var bufferEqual = require('buffer-equal'); var deepEqual = require('deep-equal'); - var byteLengthForComponentType = require('./byteLengthForComponentType'); var getAccessorByteStride = require('./getAccessorByteStride'); var numberOfComponentsForType = require('./numberOfComponentsForType'); +var Remove = require('./Remove'); var defined = Cesium.defined; @@ -48,7 +48,6 @@ MergeDuplicateProperties.mergeAll = function(gltf) { * @see loadGltfUris */ MergeDuplicateProperties.mergeAccessors = function(gltf) { - var accessors = gltf.accessors; var duplicateMapping = createDuplicateMapping(gltf); // Use the duplicate mapping to merge the accessors for (var accessorId in duplicateMapping) { @@ -62,7 +61,7 @@ MergeDuplicateProperties.mergeAccessors = function(gltf) { } replaceAccessorIdInstances(gltf, duplicateId, accessorId); delete duplicateMapping[duplicateId]; - delete accessors[duplicateId]; + Remove.accessor(gltf, duplicateId); } } } diff --git a/lib/Pipeline.js b/lib/Pipeline.js index 4587197c..d19d6291 100644 --- a/lib/Pipeline.js +++ b/lib/Pipeline.js @@ -28,8 +28,10 @@ var readGltf = require('./readGltf'); var removeDuplicatePrimitives = require('./removeDuplicatePrimitives'); var removeNormals = require('./removeNormals'); var removePipelineExtras = require('./removePipelineExtras'); +var removeUnusedVertices = require('./removeUnusedVertices'); var quantizeAttributes = require('./quantizeAttributes'); var updateVersion = require('./updateVersion'); +var uninterleaveAndPackBuffers = require('./uninterleaveAndPackBuffers'); var writeGltf = require('./writeGltf'); var writeBinaryGltf = require('./writeBinaryGltf'); var writeSource = require('./writeSource'); @@ -58,7 +60,6 @@ function Pipeline() {} */ Pipeline.processJSON = function(gltf, options) { options = defaultValue(options, {}); - addPipelineExtras(gltf); return loadGltfUris(gltf, options) .then(function(gltf) { return Pipeline.processJSONWithExtras(gltf, options); @@ -89,6 +90,7 @@ Pipeline.processJSONWithExtras = function(gltfWithExtras, options) { options = defaultValue(options, {}); updateVersion(gltfWithExtras, options); + addPipelineExtras(gltfWithExtras); addDefaults(gltfWithExtras, options); processModelMaterialsCommon(gltfWithExtras, options); @@ -177,6 +179,8 @@ Pipeline.processJSONWithExtras = function(gltfWithExtras, options) { console.log(getStatistics(gltfWithExtras).toString() + '\n'); } + removeUnusedVertices(gltfWithExtras); + uninterleaveAndPackBuffers(gltfWithExtras); return gltfWithExtras; }); }; diff --git a/lib/combineNodes.js b/lib/combineNodes.js index 0c3804ad..ebbc72f5 100644 --- a/lib/combineNodes.js +++ b/lib/combineNodes.js @@ -129,7 +129,8 @@ function mergeChildrenIntoNode(gltf, nodeId, meshesToNodes, meshesToMeshes, excl if (!Matrix4.equals(transform, Matrix4.IDENTITY)) { PrimitiveHelpers.transformPrimitives(gltf, primitives, transform); } - var nodeMesh = node.mesh; + var nodeMeshId = node.mesh; + var nodeMesh = meshes[nodeMeshId]; if (!defined(nodeMesh)) { nodeMesh = { primitives: [], @@ -137,7 +138,7 @@ function mergeChildrenIntoNode(gltf, nodeId, meshesToNodes, meshesToMeshes, excl _pipeline: {} } }; - var nodeMeshId = addToArray(meshes, nodeMesh); + nodeMeshId = addToArray(meshes, nodeMesh); meshesToNodes[nodeMeshId] = [nodeId]; meshesToMeshes[nodeMeshId] = []; node.mesh = nodeMeshId; diff --git a/lib/loadGltfUris.js b/lib/loadGltfUris.js index 4565690d..b4cb9ca0 100644 --- a/lib/loadGltfUris.js +++ b/lib/loadGltfUris.js @@ -29,11 +29,30 @@ function loadGltfUris(gltf, options) { options = defaultValue(options, {}); var basePath = defaultValue(options.basePath, ''); // Buffers need to be loaded first because images and shader may resolve to bufferViews - return loadURIs(gltf, gltf.buffers, 'buffers', basePath) + var buffers = gltf.buffers; + // glTF 1.0 compatibility + if (defined(buffers) && !Array.isArray(buffers)) { + buffers = Object.keys(buffers).map(function(key) { + return buffers[key]; + }); + } + var images = gltf.images; + if (defined(images) && !Array.isArray(images)){ + images = Object.keys(images).map(function(key) { + return images[key]; + }); + } + var shaders = gltf.shaders; + if (defined(shaders) && !Array.isArray(shaders)) { + shaders = Object.keys(shaders).map(function(key) { + return shaders[key]; + }); + } + return loadURIs(gltf, buffers, 'buffers', basePath) .then(function() { var loadPromises = [ - loadURIs(gltf, gltf.images, 'images', basePath), - loadURIs(gltf, gltf.shaders, 'shaders', basePath) + loadURIs(gltf, images, 'images', basePath), + loadURIs(gltf, shaders, 'shaders', basePath) ]; // Read sources for compressed textures diff --git a/lib/updateVersion.js b/lib/updateVersion.js index f535fbb0..830ebe1f 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -54,7 +54,6 @@ function updateVersion(gltf, options) { var updateFunction = updateFunctions[version]; while (defined(updateFunction)) { - version = gltf.asset.version; if (version === targetVersion) { break; } @@ -315,7 +314,10 @@ function objectsToArrays(gltf) { node.mesh = globalMapping.meshes[meshes[0]]; for (i = 1; i < meshesLength; i++) { var meshNode = { - mesh: globalMapping.meshes[meshes[i]] + mesh: globalMapping.meshes[meshes[i]], + extras: { + _pipeline: {} + } }; var meshNodeId = addToArray(gltf.nodes, meshNode); if (!defined(children)) { @@ -397,6 +399,25 @@ function objectsToArrays(gltf) { material.values[name] = [globalMapping.textures[value]]; } }); + var extensions = material.extensions; + if (defined(extensions)) { + var materialsCommon = extensions.KHR_materials_common; + if (defined(materialsCommon)) { + ForEach.materialValue(materialsCommon, function(value, name) { + if (Array.isArray(value)) { + if (value.length === 1) { + var textureId = value[0]; + if (typeof textureId === 'string') { + value[0] = globalMapping.textures[textureId]; + } + } + } + else if (typeof value === 'string') { + materialsCommon.values[name] = [globalMapping.textures[value]]; + } + }); + } + } }); ForEach.image(gltf, function(image) { var extensions = image.extensions; From d4ccb411522806cb326e58d3f7122476641e1ac2 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 16:21:55 -0400 Subject: [PATCH 39/47] More fixes --- lib/MergeDuplicateProperties.js | 59 +++++++++++----------------- lib/Pipeline.js | 2 +- lib/cesiumGeometryToGltfPrimitive.js | 4 -- lib/createAccessor.js | 1 - lib/removeDuplicatePrimitives.js | 13 +++++- 5 files changed, 36 insertions(+), 43 deletions(-) diff --git a/lib/MergeDuplicateProperties.js b/lib/MergeDuplicateProperties.js index 02903e0c..6e0c7d55 100644 --- a/lib/MergeDuplicateProperties.js +++ b/lib/MergeDuplicateProperties.js @@ -4,9 +4,10 @@ var clone = require('clone'); var bufferEqual = require('buffer-equal'); var deepEqual = require('deep-equal'); var byteLengthForComponentType = require('./byteLengthForComponentType'); +var ForEach = require('./ForEach'); var getAccessorByteStride = require('./getAccessorByteStride'); var numberOfComponentsForType = require('./numberOfComponentsForType'); -var Remove = require('./Remove'); +var RemoveUnusedProperties = require('./RemoveUnusedProperties'); var defined = Cesium.defined; @@ -52,6 +53,7 @@ MergeDuplicateProperties.mergeAccessors = function(gltf) { // Use the duplicate mapping to merge the accessors for (var accessorId in duplicateMapping) { if (duplicateMapping.hasOwnProperty(accessorId)) { + accessorId = parseInt(accessorId); var duplicates = duplicateMapping[accessorId]; for (var i = 0; i < duplicates.length; i++) { var duplicateId = duplicates[i]; @@ -60,53 +62,38 @@ MergeDuplicateProperties.mergeAccessors = function(gltf) { duplicates.concat(metaDuplicates); } replaceAccessorIdInstances(gltf, duplicateId, accessorId); - delete duplicateMapping[duplicateId]; - Remove.accessor(gltf, duplicateId); } } } + RemoveUnusedProperties.removeAccessors(gltf); return gltf; }; function replaceAccessorIdInstances(gltf, accessorId, newAccessorId) { - var meshes = gltf.meshes; - for (var meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { - var mesh = meshes[meshId]; - var primitives = mesh.primitives; - var primitivesLength = primitives.length; - for (var i = 0; i < primitivesLength; i++) { - var primitive = primitives[i]; - var indices = primitive.indices; - if (indices === accessorId) { - primitive.indices = newAccessorId; - } - var attributes = primitive.attributes; - for (var attribute in attributes) { - if (attributes.hasOwnProperty(attribute)) { - var attributeAccessorId = attributes[attribute]; - if (attributeAccessorId === accessorId) { - attributes[attribute] = newAccessorId; - } - } - } + ForEach.mesh(gltf, function(mesh) { + ForEach.meshPrimitives(mesh, function (primitive) { + var indices = primitive.indices; + if (indices === accessorId) { + primitive.indices = newAccessorId; } - } - } + ForEach.meshPrimitiveAttributes(primitive, function (attributeAccessorId, semantic) { + if (attributeAccessorId === accessorId) { + primitive.attributes[semantic] = newAccessorId; + } + }); + }); + }); } function createDuplicateMapping(gltf) { var accessors = gltf.accessors; var bufferViews = gltf.bufferViews; var buffers = gltf.buffers; - var accessorIdArray = Object.keys(accessors); var duplicateMapping = {}; - for (var i = 0; i < accessorIdArray.length; i++) { - var iAccessorId = accessorIdArray[i]; - var iAccessor = accessors[iAccessorId]; - for (var j = i+1; j < accessorIdArray.length; j++) { - var jAccessorId = accessorIdArray[j]; - var jAccessor = accessors[jAccessorId]; + for (var i = 0; i < accessors.length; i++) { + var iAccessor = accessors[i]; + for (var j = i+1; j < accessors.length; j++) { + var jAccessor = accessors[j]; if (accessorPropertiesMatch(iAccessor, jAccessor)) { var iBufferViewId = iAccessor.bufferView; var iBufferView = bufferViews[iBufferViewId]; @@ -141,12 +128,12 @@ function createDuplicateMapping(gltf) { jByteOffset += jByteStride; } if (accessorsMatch) { - var mapping = duplicateMapping[iAccessorId]; + var mapping = duplicateMapping[i]; if (!defined(mapping)) { mapping = []; - duplicateMapping[iAccessorId] = mapping; + duplicateMapping[i] = mapping; } - mapping.push(jAccessorId); + mapping.push(j); } } } diff --git a/lib/Pipeline.js b/lib/Pipeline.js index d19d6291..a9229424 100644 --- a/lib/Pipeline.js +++ b/lib/Pipeline.js @@ -114,6 +114,7 @@ Pipeline.processJSONWithExtras = function(gltfWithExtras, options) { } if (!shouldPreserve) { mergeDuplicateVertices(gltfWithExtras); + removeUnusedVertices(gltfWithExtras); MergeDuplicateProperties.mergeAll(gltfWithExtras); RemoveUnusedProperties.removeAll(gltfWithExtras); removeDuplicatePrimitives(gltfWithExtras); @@ -179,7 +180,6 @@ Pipeline.processJSONWithExtras = function(gltfWithExtras, options) { console.log(getStatistics(gltfWithExtras).toString() + '\n'); } - removeUnusedVertices(gltfWithExtras); uninterleaveAndPackBuffers(gltfWithExtras); return gltfWithExtras; }); diff --git a/lib/cesiumGeometryToGltfPrimitive.js b/lib/cesiumGeometryToGltfPrimitive.js index 95f9de15..a6fd9510 100644 --- a/lib/cesiumGeometryToGltfPrimitive.js +++ b/lib/cesiumGeometryToGltfPrimitive.js @@ -4,8 +4,6 @@ var Cesium = require('cesium'); var createAccessor = require('./createAccessor'); var findAccessorMinMax = require('./findAccessorMinMax'); var getPrimitiveAttributeSemantics = require('./getPrimitiveAttributeSemantics'); -var mergeBuffers = require('./mergeBuffers'); -var uninterleaveAndPackBuffers = require('./uninterleaveAndPackBuffers'); var writeAccessor = require('./writeAccessor'); var DeveloperError = Cesium.DeveloperError; @@ -88,6 +86,4 @@ function cesiumGeometryToGltfPrimitive(gltf, primitive, geometry) { var indicesId = primitive.indices; var indicesAccessor = gltf.accessors[indicesId]; writeAccessor(gltf, indicesAccessor, geometry.indices); - mergeBuffers(gltf); - uninterleaveAndPackBuffers(gltf); } diff --git a/lib/createAccessor.js b/lib/createAccessor.js index d81a8742..b7d74f28 100644 --- a/lib/createAccessor.js +++ b/lib/createAccessor.js @@ -1,6 +1,5 @@ 'use strict'; var Cesium = require('cesium'); - var addToArray = require('./addToArray'); var byteLengthForComponentType = require('./byteLengthForComponentType'); var findAccessorMinMax = require('./findAccessorMinMax'); diff --git a/lib/removeDuplicatePrimitives.js b/lib/removeDuplicatePrimitives.js index 86ccd951..685c5f9d 100644 --- a/lib/removeDuplicatePrimitives.js +++ b/lib/removeDuplicatePrimitives.js @@ -86,7 +86,18 @@ function removeDuplicatesFromTraversal(gltf, seenPrimitives, primitivesCount, pr for (var k = 0; k < nodeIdsLength; k++) { var nodeId = nodeIds[k]; var node = nodes[nodeId]; - node.meshes.push(splitMeshId); + if (!defined(node.mesh)) { + node.mesh = splitMeshId; + } else { + var meshNode = { + mesh: splitMeshId, + extras: { + _pipeline: {} + } + }; + var meshNodeId = addToArray(nodes, meshNode); + node.children.push(meshNodeId); + } } } } From edee4676b9adce0880bd251ab00411596ba0e00b Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 17:57:44 -0400 Subject: [PATCH 40/47] A few test fixes and byteStride -> bufferView --- lib/AccessorReader.js | 2 +- lib/MergeDuplicateProperties.js | 147 ++++++----- lib/addDefaults.js | 6 +- lib/compressTextureCoordinates.js | 4 +- lib/createAccessorUsageTables.js | 2 +- lib/findAccessorMinMax.js | 2 +- lib/getAccessorByteStride.js | 10 +- lib/mergeDuplicateVertices.js | 6 +- lib/octEncodeNormals.js | 4 +- lib/removeUnusedVertices.js | 2 +- lib/updateVersion.js | 21 ++ specs/lib/MergeDuplicatePropertiesSpec.js | 258 +++++++++----------- specs/lib/addDefaultsSpec.js | 16 -- specs/lib/compressIntegerAccessorsSpec.js | 7 - specs/lib/compressTextureCoordinatesSpec.js | 4 - specs/lib/findAccessorMinMaxSpec.js | 2 +- specs/lib/generateTangentsBitangentsSpec.js | 3 + 17 files changed, 232 insertions(+), 264 deletions(-) diff --git a/lib/AccessorReader.js b/lib/AccessorReader.js index 634690ec..e16fbee1 100644 --- a/lib/AccessorReader.js +++ b/lib/AccessorReader.js @@ -33,7 +33,7 @@ function AccessorReader(gltf, accessor) { this.accessor = accessor; this.byteOffset = accessor.byteOffset + bufferView.byteOffset; - this.byteStride = getAccessorByteStride(accessor); + this.byteStride = getAccessorByteStride(gltf, accessor); this.componentType = accessor.componentType; this.numberOfComponents = numberOfComponentsForType(accessor.type); this.count = accessor.count; diff --git a/lib/MergeDuplicateProperties.js b/lib/MergeDuplicateProperties.js index 6e0c7d55..8ae43bcb 100644 --- a/lib/MergeDuplicateProperties.js +++ b/lib/MergeDuplicateProperties.js @@ -101,7 +101,7 @@ function createDuplicateMapping(gltf) { var iBuffer = buffers[iBufferId]; var iBufferSource = iBuffer.extras._pipeline.source; var iByteOffset = iAccessor.byteOffset + iBufferView.byteOffset; - var iByteStride = getAccessorByteStride(iAccessor); + var iByteStride = getAccessorByteStride(gltf, iAccessor); var count = iAccessor.count; var elementByteLength = byteLengthForComponentType(iAccessor.componentType) * numberOfComponentsForType(iAccessor.type); @@ -111,7 +111,7 @@ function createDuplicateMapping(gltf) { var jBuffer = buffers[jBufferId]; var jBufferSource = jBuffer.extras._pipeline.source; var jByteOffset = jAccessor.byteOffset + jBufferView.byteOffset; - var jByteStride = getAccessorByteStride(jAccessor); + var jByteStride = getAccessorByteStride(gltf, jAccessor); var accessorsMatch = true; for (var k = 0; k < count; k++) { @@ -160,7 +160,7 @@ MergeDuplicateProperties.mergeShaders = function(gltf) { var shaderIdMapping = {}; var uniqueShadersByType = {}; for (var i = 0; i < shaderIdsLength; i++) { - var shaderId = shaderIds[i]; + var shaderId = parseInt(shaderIds[i]); var shader = shaders[shaderId]; var type = shader.type; var uniqueShaders = uniqueShadersByType[type]; @@ -188,22 +188,18 @@ MergeDuplicateProperties.mergeShaders = function(gltf) { }; function remapShaders(gltf, shaderIdMapping) { - var programs = gltf.programs; - for (var programId in programs) { - if (programs.hasOwnProperty(programId)) { - var program = programs[programId]; - var fragmentShaderId = program.fragmentShader; - var vertexShaderId = program.vertexShader; - var mappedFragmentShaderId = shaderIdMapping[fragmentShaderId]; - var mappedVertexShaderId = shaderIdMapping[vertexShaderId]; - if (defined(mappedFragmentShaderId)) { - program.fragmentShader = mappedFragmentShaderId; - } - if (defined(mappedVertexShaderId)) { - program.vertexShader = mappedVertexShaderId; - } + ForEach.program(gltf, function(program) { + var fragmentShaderId = program.fragmentShader; + var vertexShaderId = program.vertexShader; + var mappedFragmentShaderId = shaderIdMapping[fragmentShaderId]; + var mappedVertexShaderId = shaderIdMapping[vertexShaderId]; + if (defined(mappedFragmentShaderId)) { + program.fragmentShader = mappedFragmentShaderId; } - } + if (defined(mappedVertexShaderId)) { + program.vertexShader = mappedVertexShaderId; + } + }); } function shaderEquals(shaderOne, shaderTwo) { @@ -224,28 +220,26 @@ MergeDuplicateProperties.mergePrograms = function(gltf) { var programIdMapping = {}; var uniqueProgramIds = []; var uniquePrograms = {}; - for (var programId in programs) { - if (programs.hasOwnProperty(programId)) { - var program = clone(programs[programId]); - delete program.name; - delete program.extras; - var uniqueProgramIdsLength = uniqueProgramIds.length; - var unique = true; - for (var i = 0; i < uniqueProgramIdsLength; i++) { - var uniqueProgramId = uniqueProgramIds[i]; - var uniqueProgram = programs[uniqueProgramId]; - if (deepEqual(program, uniqueProgram)) { - programIdMapping[programId] = uniqueProgramId; - unique = false; - break; - } - } - if (unique) { - uniqueProgramIds.push(programId); - uniquePrograms[programId] = program; + ForEach.program(gltf, function(program, programId) { + program = clone(program); + delete program.name; + delete program.extras; + var uniqueProgramIdsLength = uniqueProgramIds.length; + var unique = true; + for (var i = 0; i < uniqueProgramIdsLength; i++) { + var uniqueProgramId = uniqueProgramIds[i]; + var uniqueProgram = programs[uniqueProgramId]; + if (deepEqual(program, uniqueProgram)) { + programIdMapping[programId] = uniqueProgramId; + unique = false; + break; } } - } + if (unique) { + uniqueProgramIds.push(programId); + uniquePrograms[programId] = program; + } + }); remapPrograms(gltf, programIdMapping); }; @@ -274,28 +268,26 @@ MergeDuplicateProperties.mergeTechniques = function(gltf) { var techniqueIdMapping = {}; var uniqueTechniqueIds = []; var uniqueTechniques = {}; - for (var techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { - var technique = clone(techniques[techniqueId]); - delete technique.name; - delete technique.extras; - var uniqueTechniqueIdsLength = uniqueTechniqueIds.length; - var unique = true; - for (var i = 0; i < uniqueTechniqueIdsLength; i++) { - var uniqueTechniqueId = uniqueTechniqueIds[i]; - var uniqueTechnique = techniques[uniqueTechniqueId]; - if (deepEqual(technique, uniqueTechnique)) { - techniqueIdMapping[techniqueId] = uniqueTechniqueId; - unique = false; - break; - } - } - if (unique) { - uniqueTechniqueIds.push(techniqueId); - uniqueTechniques[techniqueId] = technique; + ForEach.technique(gltf, function(technique, techniqueId) { + technique = clone(technique); + delete technique.name; + delete technique.extras; + var uniqueTechniqueIdsLength = uniqueTechniqueIds.length; + var unique = true; + for (var i = 0; i < uniqueTechniqueIdsLength; i++) { + var uniqueTechniqueId = uniqueTechniqueIds[i]; + var uniqueTechnique = techniques[uniqueTechniqueId]; + if (deepEqual(technique, uniqueTechnique)) { + techniqueIdMapping[techniqueId] = uniqueTechniqueId; + unique = false; + break; } } - } + if (unique) { + uniqueTechniqueIds.push(techniqueId); + uniqueTechniques[techniqueId] = technique; + } + }); remapTechniques(gltf,techniqueIdMapping); }; @@ -320,32 +312,29 @@ function remapTechniques(gltf, techniqueIdMapping) { * @returns {Object} The glTF with merged duplicate materials. */ MergeDuplicateProperties.mergeMaterials = function(gltf) { - var materials = gltf.materials; var materialIdMapping = {}; var uniqueMaterialIds = []; var uniqueMaterials = {}; - for (var materialId in materials) { - if (materials.hasOwnProperty(materialId)) { - var material = clone(materials[materialId]); - delete material.name; - delete material.extras; - var uniqueMaterialIdsLength = uniqueMaterialIds.length; - var unique = true; - for (var i = 0; i < uniqueMaterialIdsLength; i++) { - var uniqueMaterialId = uniqueMaterialIds[i]; - var uniqueMaterial = uniqueMaterials[uniqueMaterialId]; - if (deepEqual(material, uniqueMaterial)) { - materialIdMapping[materialId] = uniqueMaterialId; - unique = false; - break; - } - } - if (unique) { - uniqueMaterialIds.push(materialId); - uniqueMaterials[materialId] = material; + ForEach.material(gltf, function(material, materialId) { + material = clone(material); + delete material.name; + delete material.extras; + var uniqueMaterialIdsLength = uniqueMaterialIds.length; + var unique = true; + for (var i = 0; i < uniqueMaterialIdsLength; i++) { + var uniqueMaterialId = uniqueMaterialIds[i]; + var uniqueMaterial = uniqueMaterials[uniqueMaterialId]; + if (deepEqual(material, uniqueMaterial)) { + materialIdMapping[materialId] = uniqueMaterialId; + unique = false; + break; } } - } + if (unique) { + uniqueMaterialIds.push(materialId); + uniqueMaterials[materialId] = material; + } + }); remapMaterials(gltf, materialIdMapping); }; diff --git a/lib/addDefaults.js b/lib/addDefaults.js index 1bf47e3e..d3a5aa67 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -10,11 +10,7 @@ var WebGLConstants = Cesium.WebGLConstants; module.exports = addDefaults; var gltfTemplate = { - accessors : [ - { - byteStride : 0 - } - ], + accessors: [], animations : [ { channels : [], diff --git a/lib/compressTextureCoordinates.js b/lib/compressTextureCoordinates.js index abf7b765..a8c3cc33 100644 --- a/lib/compressTextureCoordinates.js +++ b/lib/compressTextureCoordinates.js @@ -49,7 +49,7 @@ function compressTextureCoordinates(gltf) { var bufferId = bufferView.buffer; var buffer = buffers[bufferId]; var source = buffer.extras._pipeline.source; - var byteStride = getAccessorByteStride(accessor); + var byteStride = getAccessorByteStride(gltf, accessor); var byteOffset = accessor.byteOffset + bufferView.byteOffset; var componentType = accessor.componentType; var newComponentType = WebGLConstants.FLOAT; @@ -67,7 +67,7 @@ function compressTextureCoordinates(gltf) { writeBufferComponent(source, newComponentType, compressed, byteOffset); byteOffset += byteStride; } - accessor.byteStride = byteStride; + bufferView.byteStride = byteStride; accessor.componentType = newComponentType; accessor.type = 'SCALAR'; var minMax = findAccessorMinMax(gltf, accessor); diff --git a/lib/createAccessorUsageTables.js b/lib/createAccessorUsageTables.js index 223a79b2..03140d47 100644 --- a/lib/createAccessorUsageTables.js +++ b/lib/createAccessorUsageTables.js @@ -56,7 +56,7 @@ function markUsageForIndexAccessor(gltf, accessor, usage) { var buffer = buffers[bufferId]; var source = buffer.extras._pipeline.source; var byteOffset = accessor.byteOffset + bufferView.byteOffset; - var byteStride = getAccessorByteStride(accessor); + var byteStride = getAccessorByteStride(gltf, accessor); for (var i = 0; i < accessor.count; i++) { var index = readBufferComponent(source, accessor.componentType, byteOffset + i * byteStride); if (index > usage.length) { diff --git a/lib/findAccessorMinMax.js b/lib/findAccessorMinMax.js index 1da6e2db..e13a12d2 100644 --- a/lib/findAccessorMinMax.js +++ b/lib/findAccessorMinMax.js @@ -36,7 +36,7 @@ function findAccessorMinMax(gltf, accessor) { var source = buffer.extras._pipeline.source; var count = accessor.count; - var byteStride = getAccessorByteStride(accessor); + var byteStride = getAccessorByteStride(gltf, accessor); var byteOffset = accessor.byteOffset + bufferView.byteOffset; var componentType = accessor.componentType; diff --git a/lib/getAccessorByteStride.js b/lib/getAccessorByteStride.js index 68003eef..f691e5d3 100644 --- a/lib/getAccessorByteStride.js +++ b/lib/getAccessorByteStride.js @@ -1,7 +1,10 @@ 'use strict'; +var Cesium = require('cesium'); var byteLengthForComponentType = require('./byteLengthForComponentType'); var numberOfComponentsForType = require('./numberOfComponentsForType'); +var defined = Cesium.defined; + module.exports = getAccessorByteStride; /** @@ -11,9 +14,10 @@ module.exports = getAccessorByteStride; * @param {Object} accessor The accessor. * @returns {Number} The byte stride of the accessor. */ -function getAccessorByteStride(accessor) { - if (accessor.byteStride > 0) { - return accessor.byteStride; +function getAccessorByteStride(gltf, accessor) { + var bufferView = gltf.bufferViews[accessor.bufferView]; + if (defined(bufferView.byteStride) && bufferView.byteStride > 0) { + return bufferView.byteStride; } return byteLengthForComponentType(accessor.componentType) * numberOfComponentsForType(accessor.type); } \ No newline at end of file diff --git a/lib/mergeDuplicateVertices.js b/lib/mergeDuplicateVertices.js index 1ff64447..5832bace 100644 --- a/lib/mergeDuplicateVertices.js +++ b/lib/mergeDuplicateVertices.js @@ -49,7 +49,7 @@ function mergeDuplicateVerticesFromMapping(gltf, indexAccessors) { var bufferId = bufferView.buffer; var buffer = buffers[bufferId]; var source = buffer.extras._pipeline.source; - var byteStride = getAccessorByteStride(accessor); + var byteStride = getAccessorByteStride(gltf, accessor); var byteOffset = accessor.byteOffset + bufferView.byteOffset; var numIndices = accessor.count; var duplicateMapping = indexAccessors[indexAccessorId]; @@ -93,7 +93,7 @@ function findDuplicateVerticesInMesh(gltf, mesh, indexAccessors) { attributeBufferInfo[attribute] = { buffer: attributeBufferId, byteOffset: attributeBufferView.byteOffset + attributeAccessor.byteOffset, - byteStride: getAccessorByteStride(attributeAccessor), + byteStride: getAccessorByteStride(gltf, attributeAccessor), componentType: attributeAccessor.componentType, elementByteLength: byteLengthForComponentType(attributeAccessor.componentType) * numberOfComponentsForType(attributeAccessor.type), source: attributeBuffer.extras._pipeline.source @@ -104,7 +104,7 @@ function findDuplicateVerticesInMesh(gltf, mesh, indexAccessors) { var indexBufferView = bufferViews[indexBufferViewId]; var indexBufferId = indexBufferView.buffer; var indexBuffer = buffers[indexBufferId]; - var indexByteStride = getAccessorByteStride(indexAccessor); + var indexByteStride = getAccessorByteStride(gltf, indexAccessor); var indexComponentType = indexAccessor.componentType; var indexSource = indexBuffer.extras._pipeline.source; var indexByteOffset = indexAccessor.byteOffset + indexBufferView.byteOffset; diff --git a/lib/octEncodeNormals.js b/lib/octEncodeNormals.js index a01d5ecc..57ba391d 100644 --- a/lib/octEncodeNormals.js +++ b/lib/octEncodeNormals.js @@ -50,7 +50,7 @@ function octEncodeNormals(gltf) { var bufferId = bufferView.buffer; var buffer = buffers[bufferId]; var source = buffer.extras._pipeline.source; - var byteStride = getAccessorByteStride(accessor); + var byteStride = getAccessorByteStride(gltf, accessor); var byteOffset = accessor.byteOffset + bufferView.byteOffset; var componentType = accessor.componentType; var newComponentType = WebGLConstants.UNSIGNED_BYTE; @@ -72,7 +72,7 @@ function octEncodeNormals(gltf) { writeBufferComponent(source, newComponentType, octEncodedVector.y, byteOffset + newComponentByteLength); byteOffset += byteStride; } - accessor.byteStride = byteStride; + bufferView.byteStride = byteStride; accessor.componentType = newComponentType; accessor.type = 'VEC2'; var minMax = findAccessorMinMax(gltf, accessor); diff --git a/lib/removeUnusedVertices.js b/lib/removeUnusedVertices.js index b3c23e88..22cd1cf8 100644 --- a/lib/removeUnusedVertices.js +++ b/lib/removeUnusedVertices.js @@ -96,7 +96,7 @@ function accessorWriteFromTo(gltf, accessor, fromIndex, toIndex) { var source = buffer.extras._pipeline.source; var byteOffset = bufferView.byteOffset + accessor.byteOffset; - var byteStride = getAccessorByteStride(accessor); + var byteStride = getAccessorByteStride(gltf, accessor); var componentByteLength = byteLengthForComponentType(accessor.componentType); var numberOfComponents = numberOfComponentsForType(accessor.type); diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 830ebe1f..e93b676e 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -8,6 +8,7 @@ var Cartesian3 = Cesium.Cartesian3; var CesiumMath = Cesium.Math; var Quaternion = Cesium.Quaternion; var WebGLConstants = Cesium.WebGLConstants; +var clone = Cesium.clone; var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; @@ -642,6 +643,24 @@ function requireByteLength(gltf) { }); } +function moveByteStrideToBufferView(gltf) { + ForEach.accessor(gltf, function(accessor) { + if (defined(accessor.byteStride)) { + var byteStride = accessor.byteStride; + if (byteStride !== 0) { + var bufferView = gltf.bufferViews[accessor.bufferView]; + if (defined(bufferView.byteStride) && bufferView.byteStride !== byteStride) { + // another accessor uses this with a different byte stride + bufferView = clone(bufferView); + accessor.bufferView = addToArray(gltf.bufferViews, bufferView); + } + bufferView.byteStride = byteStride; + } + delete accessor.byteStride; + } + }); +} + function requireAccessorMinMax(gltf) { ForEach.accessor(gltf, function(accessor) { if (!defined(accessor.min) || !defined(accessor.max)) { @@ -692,6 +711,8 @@ function glTF10to20(gltf) { requireKnownExtensions(gltf); // bufferView.byteLength and buffer.byteLength are required requireByteLength(gltf); + // byteStride moved from accessor to bufferView + moveByteStrideToBufferView(gltf); // accessor.min and accessor.max must be defined requireAccessorMinMax(gltf); // buffer.type is unnecessary and should be removed diff --git a/specs/lib/MergeDuplicatePropertiesSpec.js b/specs/lib/MergeDuplicatePropertiesSpec.js index eac574e9..ea20b7f6 100644 --- a/specs/lib/MergeDuplicatePropertiesSpec.js +++ b/specs/lib/MergeDuplicatePropertiesSpec.js @@ -10,130 +10,123 @@ describe('MergeDuplicateProperties', function() { var mergeAccessors = MergeDuplicateProperties.mergeAccessors; describe('mergeAccessors', function() { var testGltf = { - accessors: { - accessorA: { - bufferView: 'bufferView', + accessors: [ + { + bufferView: 0, byteOffset: 0, - byteStride: 0, componentType: WebGLConstants.BYTE, count: 3, type: 'SCALAR' - }, - accessorB: { - bufferView: 'bufferView', + }, { + bufferView: 0, byteOffset: 3, - byteStride: 0, componentType: WebGLConstants.BYTE, count: 3, type: 'SCALAR' } - }, - bufferViews: { - bufferView: { - buffer: 'buffer', + ], + bufferViews: [ + { + buffer: 0, byteOffset: 0 } - }, - buffers: { - buffer: { - type: 'arraybuffer', + ], + buffers: [ + { extras : { _pipeline : {} } } - }, - meshes: { - meshA: { + ], + meshes: [ + { primitives : [ { attributes: { - TEST: 'accessorA' + TEST: 0 } } ] - }, - meshB: { + }, { primitives : [ { attributes: { - TEST: 'accessorB' + TEST: 1 } } ] } - } + ] }; it('merges a single duplicate accessor', function () { var buffer = new Buffer([1, 2, 3, 1, 2, 3]); var gltf = clone(testGltf); - var gltfBuffer = gltf.buffers.buffer; + var gltfBuffer = gltf.buffers[0]; gltfBuffer.extras._pipeline.source = buffer; gltfBuffer.byteLength = buffer.length; - gltf.bufferViews.bufferView.byteLength = buffer.length; + gltf.bufferViews[0].byteLength = buffer.length; mergeAccessors(gltf); - expect(Object.keys(gltf.accessors).length).toEqual(1); - expect(gltf.meshes.meshA.primitives[0].attributes.TEST).toEqual(gltf.meshes.meshB.primitives[0].attributes.TEST); + expect(gltf.accessors.length).toEqual(1); + expect(gltf.meshes[0].primitives[0].attributes.TEST).toEqual(gltf.meshes[1].primitives[0].attributes.TEST); }); it ('merges multiple duplicate accessors', function () { var buffer = new Buffer([1, 2, 3, 1, 2, 3, 1, 2, 3]); var gltf = clone(testGltf); - var gltfBuffer = gltf.buffers.buffer; + var gltfBuffer = gltf.buffers[0]; gltfBuffer.extras._pipeline.source = buffer; gltfBuffer.byteLength = buffer.length; - gltf.bufferViews.bufferView.byteLength = buffer.length; - gltf.accessors.accessorC = { - bufferView: 'bufferView', + gltf.bufferViews[0].byteLength = buffer.length; + gltf.accessors.push({ + bufferView: 0, byteOffset: 6, - byteStride: 0, componentType: WebGLConstants.BYTE, count: 3, type: 'SCALAR' - }; - gltf.meshes.meshC = { + }); + gltf.meshes.push({ primitives : [ { attributes : { - TEST: 'accessorC' + TEST: 2 } } ] - }; + }); mergeAccessors(gltf); - expect(Object.keys(gltf.accessors).length).toEqual(1); - expect(gltf.meshes.meshA.primitives[0].attributes.TEST).toEqual(gltf.meshes.meshB.primitives[0].attributes.TEST); - expect(gltf.meshes.meshA.primitives[0].attributes.TEST).toEqual(gltf.meshes.meshC.primitives[0].attributes.TEST); + expect(gltf.accessors.length).toEqual(1); + expect(gltf.meshes[0].primitives[0].attributes.TEST).toEqual(gltf.meshes[1].primitives[0].attributes.TEST); + expect(gltf.meshes[0].primitives[0].attributes.TEST).toEqual(gltf.meshes[2].primitives[0].attributes.TEST); }); it ('leaves a non-duplicate accessor alone', function () { var buffer = new Buffer([1, 2, 3, 1, 2, 3, 3, 2, 1]); var gltf = clone(testGltf); - var gltfBuffer = gltf.buffers.buffer; + var gltfBuffer = gltf.buffers[0]; gltfBuffer.extras._pipeline.source = buffer; gltfBuffer.byteLength = buffer.length; - gltf.bufferViews.bufferView.byteLength = buffer.length; - gltf.accessors.accessorC = { - bufferView: 'bufferView', + gltf.bufferViews[0].byteLength = buffer.length; + gltf.accessors.push({ + bufferView: 0, byteOffset: 6, - byteStride: 0, componentType: WebGLConstants.BYTE, count: 3, type: 'SCALAR' - }; - gltf.meshes.meshC = { + }); + gltf.meshes.push({ primitives : [ { attributes : { - TEST: 'accessorC' + TEST: 2 } } ] - }; + }); mergeAccessors(gltf); - expect(Object.keys(gltf.accessors).length).toEqual(2); - expect(gltf.meshes.meshA.primitives[0].attributes.TEST).toEqual(gltf.meshes.meshB.primitives[0].attributes.TEST); - expect(gltf.meshes.meshA.primitives[0].attributes.TEST).not.toEqual(gltf.meshes.meshC.primitives[0].attributes.TEST); + expect(gltf.accessors.length).toEqual(2); + expect(gltf.meshes[0].primitives[0].attributes.TEST).toEqual(gltf.meshes[1].primitives[0].attributes.TEST); + expect(gltf.meshes[0].primitives[0].attributes.TEST).not.toEqual(gltf.meshes[2].primitives[0].attributes.TEST); }); }); @@ -143,42 +136,38 @@ describe('MergeDuplicateProperties', function() { var testShaderBufferTwo = new Buffer('test shader two', 'utf8'); it('merges duplicate shaders', function() { var gltf = { - programs : { - programOne : { - fragmentShader : 'FSOne', - vertexShader : 'VSOne' - }, - programTwo : { - fragmentShader : 'FSTwo', - vertexShader : 'VSTwo' + programs : [ + { + fragmentShader : 1, + vertexShader : 0 + }, { + fragmentShader : 3, + vertexShader : 2 } - }, - shaders : { - VSOne : { + ], + shaders : [ + { type : WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { source : testShaderBufferOne } } - }, - FSOne : { + }, { type : WebGLConstants.FRAGMENT_SHADER, extras : { _pipeline : { source : testShaderBufferOne } } - }, - VSTwo : { + }, { type : WebGLConstants.VERTEX_SHADER, extras : { _pipeline : { source : testShaderBufferTwo } } - }, - FSTwo : { + }, { type : WebGLConstants.FRAGMENT_SHADER, extras : { _pipeline : { @@ -186,14 +175,14 @@ describe('MergeDuplicateProperties', function() { } } } - } + ] }; mergeShaders(gltf); var programs = gltf.programs; - expect(programs.programOne.fragmentShader).toBe('FSOne'); - expect(programs.programOne.vertexShader).toBe('VSOne'); - expect(programs.programTwo.fragmentShader).toBe('FSOne'); - expect(programs.programTwo.vertexShader).toBe('VSTwo'); + expect(programs[0].fragmentShader).toBe(1); + expect(programs[0].vertexShader).toBe(0); + expect(programs[1].fragmentShader).toBe(1); + expect(programs[1].vertexShader).toBe(2); }); }); @@ -201,37 +190,35 @@ describe('MergeDuplicateProperties', function() { describe('mergePrograms', function() { it('merges duplicate programs', function() { var gltf = { - programs: { - programOne: { - fragmentShader: 'FSOne', - vertexShader: 'VSOne' - }, - programTwo: { - fragmentShader: 'FSOne', - vertexShader: 'VSOne' - }, - programThree: { - fragmentShader: 'FSOne', - vertexShader: 'VSTwo' + programs: [ + { + fragmentShader: 0, + vertexShader: 1 + }, { + fragmentShader: 0, + vertexShader: 1 + }, { + fragmentShader: 0, + vertexShader: 2 } - }, - techniques: { - techniqueOne: { - program: 'programOne' + ], + techniques: [ + { + program: 0 }, - techniqueTwo: { - program: 'programTwo' + { + program: 1 }, - techniqueThree: { - program: 'programThree' + { + program: 2 } - } + ] }; mergePrograms(gltf); var techniques = gltf.techniques; - expect(techniques.techniqueOne.program).toBe('programOne'); - expect(techniques.techniqueTwo.program).toBe('programOne'); - expect(techniques.techniqueThree.program).toBe('programThree'); + expect(techniques[0].program).toBe(0); + expect(techniques[1].program).toBe(0); + expect(techniques[2].program).toBe(2); }); }); @@ -239,46 +226,44 @@ describe('MergeDuplicateProperties', function() { describe('mergeTechniques', function() { it('merges duplicate techniques', function() { var gltf = { - techniques : { - techniqueOne : { + techniques : [ + { key : 'value', arrayOf : ['values'], nested : { key : 'value' } }, - techniqueTwo : { + { key : 'value', arrayOf : ['different', 'values'], nested : { key : 'value' } }, - techniqueThree : { + { key : 'value', arrayOf : ['values'], nested : { key : 'value' } } - }, - materials : { - materialOne : { - technique : 'techniqueOne' - }, - materialTwo : { - technique : 'techniqueTwo' - }, - materialThree : { - technique : 'techniqueThree' + ], + materials : [ + { + technique : 0 + }, { + technique : 1 + }, { + technique : 2 } - } + ] }; mergeTechniques(gltf); var materials = gltf.materials; - expect(materials.materialOne.technique).toBe('techniqueOne'); - expect(materials.materialTwo.technique).toBe('techniqueTwo'); - expect(materials.materialThree.technique).toBe('techniqueOne'); + expect(materials[0].technique).toBe(0); + expect(materials[1].technique).toBe(1); + expect(materials[2].technique).toBe(0); }); }); @@ -286,62 +271,59 @@ describe('MergeDuplicateProperties', function() { describe('mergeMaterials', function() { it('merges duplicate materials', function() { var gltf = { - meshes : { - meshOne : { + meshes : [ + { primitives : [ { - material : 'materialOne' + material : 0 }, { - material : 'materialThree' + material : 2 } ] - }, - meshTwo : { + }, { primitives : [ { - material : 'materialTwo' + material : 1 }, { - material : 'materialThree' + material : 2 } ] } - }, - materials : { - materialOne : { + ], + materials : [ + { key : 'value', arrayOf : ['values'], nested : { key : 'value' } - }, - materialTwo : { + }, { key : 'value', arrayOf : ['different', 'values'], nested : { key : 'value' } - }, - materialThree : { + }, { key : 'value', arrayOf : ['values'], nested : { key : 'value' } } - } + ] }; mergeMaterials(gltf); var meshes = gltf.meshes; - var meshOne = meshes.meshOne; + var meshOne = meshes[0]; var meshOnePrimitives = meshOne.primitives; - expect(meshOnePrimitives[0].material).toBe('materialOne'); - expect(meshOnePrimitives[1].material).toBe('materialOne'); - var meshTwo = meshes.meshTwo; + expect(meshOnePrimitives[0].material).toBe(0); + expect(meshOnePrimitives[1].material).toBe(0); + var meshTwo = meshes[1]; var meshTwoPrimitives = meshTwo.primitives; - expect(meshTwoPrimitives[0].material).toBe('materialTwo'); - expect(meshTwoPrimitives[1].material).toBe('materialOne'); + expect(meshTwoPrimitives[0].material).toBe(1); + expect(meshTwoPrimitives[1].material).toBe(0); }); }); }); \ No newline at end of file diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index 38aa9f13..99e270f5 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -18,22 +18,6 @@ var transparentImageUri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAA var gltfTransparentPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestTransparent.gltf'; describe('addDefaults', function() { - it('Adds accessor properties', function() { - var gltf = { - "accessors": [{ - "bufferView": 0, - "byteOffset": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR" - }] - }; - - addDefaults(gltf); - var accessor = gltf.accessors[0]; - expect(accessor.byteStride).toEqual(0); - }); - it('Adds animation properties', function() { var gltf = { "animations": [{ diff --git a/specs/lib/compressIntegerAccessorsSpec.js b/specs/lib/compressIntegerAccessorsSpec.js index 9d23268d..5b593227 100644 --- a/specs/lib/compressIntegerAccessorsSpec.js +++ b/specs/lib/compressIntegerAccessorsSpec.js @@ -17,7 +17,6 @@ var testGltf = { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.BYTE, count : 3, type : 'SCALAR', @@ -25,7 +24,6 @@ var testGltf = { }, { bufferView : 1, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_BYTE, count : 3, type : 'SCALAR', @@ -33,7 +31,6 @@ var testGltf = { }, { bufferView : 2, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : 3, type : 'SCALAR', @@ -41,7 +38,6 @@ var testGltf = { }, { bufferView : 3, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : 3, type : 'SCALAR', @@ -49,7 +45,6 @@ var testGltf = { }, { bufferView : 4, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : 3, type : 'SCALAR', @@ -57,7 +52,6 @@ var testGltf = { }, { bufferView : 5, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : 3, type : 'SCALAR', @@ -65,7 +59,6 @@ var testGltf = { }, { bufferView : 6, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.SHORT, count : 3, type : 'SCALAR', diff --git a/specs/lib/compressTextureCoordinatesSpec.js b/specs/lib/compressTextureCoordinatesSpec.js index 4d7f3790..d9ccb6ce 100644 --- a/specs/lib/compressTextureCoordinatesSpec.js +++ b/specs/lib/compressTextureCoordinatesSpec.js @@ -17,7 +17,6 @@ describe('compressTextureCoordinates', function() { accessors : [ { byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, @@ -140,7 +139,6 @@ describe('compressTextureCoordinates', function() { accessors : [ { byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, @@ -153,7 +151,6 @@ describe('compressTextureCoordinates', function() { type : 'VEC2' }, { byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, @@ -166,7 +163,6 @@ describe('compressTextureCoordinates', function() { type : 'VEC2' }, { byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, diff --git a/specs/lib/findAccessorMinMaxSpec.js b/specs/lib/findAccessorMinMaxSpec.js index aaf58732..7d59dbeb 100644 --- a/specs/lib/findAccessorMinMaxSpec.js +++ b/specs/lib/findAccessorMinMaxSpec.js @@ -74,7 +74,7 @@ describe('findAccessorMinMax', function() { var gltfBufferView = gltf.bufferViews.bufferView; gltfBufferView.byteLength = source.length; var gltfAccessor = gltf.accessors.accessor; - gltfAccessor.byteStride = 24; + gltfBufferView.byteStride = 24; var minMax = findAccessorMinMax(gltf, gltfAccessor); expect(minMax.min).toEqual(expectMin); diff --git a/specs/lib/generateTangentsBitangentsSpec.js b/specs/lib/generateTangentsBitangentsSpec.js index 1bd9e140..f3703f20 100644 --- a/specs/lib/generateTangentsBitangentsSpec.js +++ b/specs/lib/generateTangentsBitangentsSpec.js @@ -2,6 +2,7 @@ var Cesium = require('cesium'); var clone = require('clone'); var generateTangentsBitangents = require('../../lib/generateTangentsBitangents'); +var uninterleaveAndPackBuffers = require('../../lib/uninterleaveAndPackBuffers'); var WebGLConstants = Cesium.WebGLConstants; @@ -90,6 +91,7 @@ describe('generateTangentsBitangents', function(){ var byteLengthBefore = gltf.buffers[0].byteLength; generateTangentsBitangents(gltf); + uninterleaveAndPackBuffers(gltf); var attributes = gltf.meshes[0].primitives[0].attributes; var byteLengthAfter = gltf.buffers[0].byteLength; @@ -118,6 +120,7 @@ describe('generateTangentsBitangents', function(){ }; var gltfCopy = clone(gltf); generateTangentsBitangents(gltf); + uninterleaveAndPackBuffers(gltf); expect(gltf.meshes).toEqual(gltfCopy.meshes); }); From 2e7519e16c34176d6f62b8dcbb8017a020a2f58e Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 18:00:51 -0400 Subject: [PATCH 41/47] A few more test fixes --- specs/lib/combinePrimitivesSpec.js | 16 ---------------- specs/lib/removeUnusedVerticesSpec.js | 8 -------- specs/lib/uninterleaveAndPackBuffersSpec.js | 3 +-- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/specs/lib/combinePrimitivesSpec.js b/specs/lib/combinePrimitivesSpec.js index 3d7441ba..f9c35e98 100644 --- a/specs/lib/combinePrimitivesSpec.js +++ b/specs/lib/combinePrimitivesSpec.js @@ -23,7 +23,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayOneA.length, type : 'SCALAR', @@ -32,7 +31,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayTwoA.length, type : 'SCALAR', @@ -101,7 +99,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayOneA.length, type : 'SCALAR', @@ -110,7 +107,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayTwoA.length, type : 'SCALAR', @@ -119,7 +115,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length + bufferTwoA.length, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesOne.length, type : 'SCALAR', @@ -128,7 +123,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length + bufferTwoA.length + bufferIndicesOne.length, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesOne.length, type : 'SCALAR' @@ -197,7 +191,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayOneA.length, type : 'SCALAR', @@ -206,7 +199,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesOne.length, type : 'SCALAR', @@ -215,7 +207,6 @@ describe('combinePrimitives', function() { { bufferView: 0, byteOffset: bufferOneA.length + bufferIndicesOne.length, - byteStride: 0, componentType: WebGLConstants.UNSIGNED_SHORT, count: indicesOne.length, type: 'SCALAR', @@ -287,7 +278,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayOneA.length, type : 'SCALAR', @@ -296,7 +286,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : arrayTwoB.length, type : 'SCALAR', @@ -305,7 +294,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length + bufferTwoB.length, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesOne.length, type : 'SCALAR', @@ -314,7 +302,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length + bufferTwoB.length + bufferIndicesOne.length, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesTwo.length, type : 'SCALAR', @@ -323,7 +310,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : bufferOneA.length + bufferTwoB.length + bufferIndicesOne.length + bufferIndicesTwo.length, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indicesThree.length, type : 'SCALAR', @@ -559,7 +545,6 @@ describe('combinePrimitives', function() { var quarterOverflowAccessor = { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : valueCount, type : 'SCALAR' @@ -575,7 +560,6 @@ describe('combinePrimitives', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : smallerValueCount, type : 'SCALAR' diff --git a/specs/lib/removeUnusedVerticesSpec.js b/specs/lib/removeUnusedVerticesSpec.js index a1827c4d..50a7ccbc 100644 --- a/specs/lib/removeUnusedVerticesSpec.js +++ b/specs/lib/removeUnusedVerticesSpec.js @@ -19,13 +19,11 @@ describe('removeUnusedVertices', function() { accessors : [ { byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : 5123, type : 'SCALAR' }, { - byteStride : 0, bufferView : 1, componentType : 5126, count : 3, @@ -33,7 +31,6 @@ describe('removeUnusedVertices', function() { type : 'VEC3' }, { - byteStride : 0, bufferView : 1, componentType : 5123, count : 3, @@ -41,7 +38,6 @@ describe('removeUnusedVertices', function() { type : 'VEC2' }, { - byteStride : 0, bufferView : 1, componentType : 5123, count : 3, @@ -302,28 +298,24 @@ describe('removeUnusedVertices', function() { accessors : [ { bufferView : 0, - byteStride : 0, byteOffset : 0, componentType : 5126, count : 5, type : 'VEC3' }, { bufferView : 1, - byteStride : 0, byteOffset : 0, componentType : 5126, count : 5, type : 'VEC3' }, { bufferView : 2, - byteStride : 0, byteOffset : 0, componentType : 5123, count : 9, type : 'SCALAR' }, { bufferView : 3, - byteStride : 0, byteOffset : 0, componentType : 5123, count : 7, diff --git a/specs/lib/uninterleaveAndPackBuffersSpec.js b/specs/lib/uninterleaveAndPackBuffersSpec.js index 9d3cf65c..d5cf14b3 100644 --- a/specs/lib/uninterleaveAndPackBuffersSpec.js +++ b/specs/lib/uninterleaveAndPackBuffersSpec.js @@ -13,7 +13,6 @@ describe('uninterleaveAndPackBuffers', function() { { bufferView : 0, byteOffset : 0, - byteStride : 18, componentType : 5126, count : 3, type : 'VEC3' @@ -21,7 +20,6 @@ describe('uninterleaveAndPackBuffers', function() { { bufferView : 0, byteOffset : 12, - byteStride : 18, componentType : 5123, count : 3, type : 'VEC2' @@ -48,6 +46,7 @@ describe('uninterleaveAndPackBuffers', function() { buffer : 0, byteLength : 48, byteOffset : 0, + byteStride: 18, target : 34962 }, { From 684c2723b4cf04cb0f4d665535b336f6168d3c10 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 18:16:58 -0400 Subject: [PATCH 42/47] Missed a function --- lib/AccessorReader.js | 8 +- lib/changeAccessorComponentType.js | 30 +++---- lib/getUniqueId.js | 29 ------- specs/lib/changeAccessorComponentTypeSpec.js | 89 ++++++++++---------- specs/lib/getUniqueIdSpec.js | 84 ------------------ 5 files changed, 61 insertions(+), 179 deletions(-) delete mode 100644 lib/getUniqueId.js delete mode 100644 specs/lib/getUniqueIdSpec.js diff --git a/lib/AccessorReader.js b/lib/AccessorReader.js index e16fbee1..0a1e69d9 100644 --- a/lib/AccessorReader.js +++ b/lib/AccessorReader.js @@ -1,13 +1,14 @@ 'use strict'; var Cesium = require('cesium'); -var defaultValue = Cesium.defaultValue; - var byteLengthForComponentType = require('./byteLengthForComponentType'); var getAccessorByteStride = require('./getAccessorByteStride'); var numberOfComponentsForType = require('./numberOfComponentsForType'); var readBufferComponent = require('./readBufferComponent'); var writeBufferComponent = require('./writeBufferComponent'); +var defaultValue = Cesium.defaultValue; +var defined = Cesium.defined; + module.exports = AccessorReader; /** @@ -32,6 +33,7 @@ function AccessorReader(gltf, accessor) { var buffer = buffers[bufferId]; this.accessor = accessor; + this.bufferView = bufferView; this.byteOffset = accessor.byteOffset + bufferView.byteOffset; this.byteStride = getAccessorByteStride(gltf, accessor); this.componentType = accessor.componentType; @@ -85,7 +87,7 @@ AccessorReader.prototype.write = function(data, componentType, dataOffset) { dataOffset = defaultValue(dataOffset, 0); var componentByteLength = byteLengthForComponentType(componentType); var byteStride = this.byteStride; - if (this.accessor.byteStride === 0 && componentType !== this.componentType) { + if ((!defined(this.bufferView.byteStride) || this.bufferView.byteStride === 0) && componentType !== this.componentType) { byteStride = byteLengthForComponentType(componentType) * this.numberOfComponents; } for (var i = 0; i < this.numberOfComponents; i++) { diff --git a/lib/changeAccessorComponentType.js b/lib/changeAccessorComponentType.js index 0e1997d5..2e8afc10 100644 --- a/lib/changeAccessorComponentType.js +++ b/lib/changeAccessorComponentType.js @@ -1,9 +1,8 @@ 'use strict'; var Cesium = require('cesium'); - var AccessorReader = require('./AccessorReader'); +var addToArray = require('./addToArray'); var byteLengthForComponentType = require('./byteLengthForComponentType'); -var getUniqueId = require('./getUniqueId'); var numberOfComponentsForType = require('./numberOfComponentsForType'); var writeBufferComponent = require('./writeBufferComponent'); @@ -60,21 +59,8 @@ function changeAccessorComponentType(gltf, accessor, newComponentType) { accessor.componentType = newComponentType; if (defined(writeBuffer)) { - var newBufferViewId = getUniqueId(gltf, 'bufferView'); - var newBufferId = getUniqueId(gltf, 'buffer'); - accessor.bufferView = newBufferViewId; accessor.byteOffset = 0; - accessor.byteStride = 0; - bufferViews[newBufferViewId] = { - buffer: newBufferId, - byteLength: writeBuffer.length, - byteOffset: 0, - target: bufferView.target, - extras: { - _pipeline: {} - } - }; - buffers[newBufferId] = { + var newBufferId = addToArray(buffers, { byteLength: writeBuffer.length, type: buffer.type, extras: { @@ -82,7 +68,17 @@ function changeAccessorComponentType(gltf, accessor, newComponentType) { source: writeBuffer } } - }; + }); + var newBufferViewId = addToArray(bufferViews, { + buffer: newBufferId, + byteLength: writeBuffer.length, + byteOffset: 0, + target: bufferView.target, + extras: { + _pipeline: {} + } + }); + accessor.bufferView = newBufferViewId; } } return gltf; diff --git a/lib/getUniqueId.js b/lib/getUniqueId.js deleted file mode 100644 index 3ff93adf..00000000 --- a/lib/getUniqueId.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; -var Cesium = require('cesium'); -var defined = Cesium.defined; - -module.exports = getUniqueId; - -/** - * Given a prefix for a new ID, checks the glTF asset for matching prefixes in top-level objects with IDs and returns a unique ID. - * - * @param {Object} gltf A javascript object containing a glTF asset. - * @param {String} prefix The string to try to use as the id. - * @returns {String} A unique id beginning with prefix. - */ -function getUniqueId(gltf, prefix) { - var id = prefix; - var appendIndex = 0; - for (var topLevelGroupId in gltf) { - if (gltf.hasOwnProperty(topLevelGroupId)) { - var topLevelGroup = gltf[topLevelGroupId]; - var match = topLevelGroup[id]; - while (defined(match)) { - id = prefix + '_' + appendIndex; - match = topLevelGroup[id]; - appendIndex++; - } - } - } - return id; -} \ No newline at end of file diff --git a/specs/lib/changeAccessorComponentTypeSpec.js b/specs/lib/changeAccessorComponentTypeSpec.js index dd2959b1..7da51c7c 100644 --- a/specs/lib/changeAccessorComponentTypeSpec.js +++ b/specs/lib/changeAccessorComponentTypeSpec.js @@ -8,13 +8,13 @@ var WebGLConstants = Cesium.WebGLConstants; describe('changeAccessorComponentType', function() { it('does nothing if the accessor is already the target componentType', function() { var gltf = { - accessors : { - accessor : { + accessors : [ + { componentType: WebGLConstants.FLOAT } - } + ] }; - var accessor = gltf.accessors.accessor; + var accessor = gltf.accessors[0]; changeAccessorComponentType(gltf, accessor, WebGLConstants.FLOAT); expect(accessor.componentType).toBe(WebGLConstants.FLOAT); }); @@ -23,25 +23,24 @@ describe('changeAccessorComponentType', function() { var data = new Uint16Array([0, 1, 2, 3, 4, 5]); var dataBuffer = new Buffer(data.buffer); var gltf = { - accessors : { - accessor : { - bufferView : 'bufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : data.length, type : "SCALAR" } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : dataBuffer.length, byteOffset : 0 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength: dataBuffer.length, extras: { _pipeline: { @@ -49,12 +48,12 @@ describe('changeAccessorComponentType', function() { } } } - } + ] }; - var accessor = gltf.accessors.accessor; + var accessor = gltf.accessors[0]; changeAccessorComponentType(gltf, accessor, WebGLConstants.UNSIGNED_BYTE); expect(accessor.componentType).toBe(WebGLConstants.UNSIGNED_BYTE); - expect(Object.keys(gltf.buffers).length).toBe(1); + expect(gltf.buffers.length).toBe(1); var accessorReader = new AccessorReader(gltf, accessor); var components = []; while (!accessorReader.pastEnd()) { @@ -68,25 +67,24 @@ describe('changeAccessorComponentType', function() { var data = new Float32Array([0, 1, 2, 3, 4, 5]); var dataBuffer = new Buffer(data.buffer); var gltf = { - accessors : { - accessor : { - bufferView : 'bufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : data.length, type : "SCALAR" } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : dataBuffer.length, byteOffset : 0 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength: dataBuffer.length, extras: { _pipeline: { @@ -94,12 +92,12 @@ describe('changeAccessorComponentType', function() { } } } - } + ] }; - var accessor = gltf.accessors.accessor; + var accessor = gltf.accessors[0]; changeAccessorComponentType(gltf, accessor, WebGLConstants.UNSIGNED_INT); expect(accessor.componentType).toBe(WebGLConstants.UNSIGNED_INT); - expect(Object.keys(gltf.buffers).length).toBe(1); + expect(gltf.buffers.length).toBe(1); var accessorReader = new AccessorReader(gltf, accessor); var components = []; while (!accessorReader.pastEnd()) { @@ -113,25 +111,24 @@ describe('changeAccessorComponentType', function() { var data = new Uint16Array([0, 1, 2, 3, 4, 5]); var dataBuffer = new Buffer(data.buffer); var gltf = { - accessors : { - accessor : { - bufferView : 'bufferView', + accessors : [ + { + bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : data.length, type : "SCALAR" } - }, - bufferViews : { - bufferView : { - buffer : 'buffer', + ], + bufferViews : [ + { + buffer : 0, byteLength : dataBuffer.length, byteOffset : 0 } - }, - buffers : { - buffer : { + ], + buffers : [ + { byteLength: dataBuffer.length, extras: { _pipeline: { @@ -139,12 +136,12 @@ describe('changeAccessorComponentType', function() { } } } - } + ] }; - var accessor = gltf.accessors.accessor; + var accessor = gltf.accessors[0]; changeAccessorComponentType(gltf, accessor, WebGLConstants.UNSIGNED_INT); expect(accessor.componentType).toBe(WebGLConstants.UNSIGNED_INT); - expect(Object.keys(gltf.buffers).length).toBe(2); + expect(gltf.buffers.length).toBe(2); var accessorReader = new AccessorReader(gltf, accessor); var components = []; while (!accessorReader.pastEnd()) { diff --git a/specs/lib/getUniqueIdSpec.js b/specs/lib/getUniqueIdSpec.js deleted file mode 100644 index 268d61f2..00000000 --- a/specs/lib/getUniqueIdSpec.js +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; -var getUniqueId = require('../../lib/getUniqueId'); - -describe('getUniqueId', function() { - var gltf = { - "accessors": { - "accessor": { - "bufferView": "bufferView_137" - }, - "accessor_0": { - "bufferView": "bufferView_137" - }, - "accessor_1": { - "bufferView": "bufferView_138" - } - }, - "buffers": { - "bufferId": { - "accessor": {} - } - }, - "materials": { - "blinn-1": {}, - "lambert-1": {} - } - }; - - var allIdentifiersGltf = { - "nodes": { - "id" : {} - }, - "skins": { - "id_0": {} - }, - "cameras": { - "id_1": {} - }, - "meshes": { - "id_2": {} - }, - "accessors": { - "id_3": {} - }, - "materials": { - "id_4": {} - }, - "bufferViews": { - "id_5": {} - }, - "techniques": { - "id_6": {} - }, - "textures": { - "id_7": {} - }, - "buffers": { - "id_8": {} - }, - "programs": { - "id_9": {} - }, - "images": { - "id_10": {} - }, - "samplers": { - "id_11": {} - }, - "shaders": { - "id_12": {} - } - }; - - it('locates IDs in the top level objects of the gltf and adjusts accordingly', function() { - expect(getUniqueId(gltf, 'accessor')).toEqual('accessor_2'); - }); - - it('does not modify the prefix if the prefix does not occur in top level objects of the gltf', function() { - expect(getUniqueId(gltf, 'uniqueId')).toEqual('uniqueId'); - }); - - it('can identify instances of the prefix across different top level objects', function() { - expect(getUniqueId(allIdentifiersGltf, 'id')).toEqual('id_13'); - }); -}); From d4264334a1d07d5e75dcf3daf33a5005d9d55eae Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Tue, 21 Mar 2017 18:21:07 -0400 Subject: [PATCH 43/47] Removed vestigial byteStride references --- specs/lib/RemoveUnusedPropertiesSpec.js | 2 -- specs/lib/combineNodesSpec.js | 7 ------- specs/lib/findAccessorMinMaxSpec.js | 1 - specs/lib/mergeDuplicateVerticesSpec.js | 10 +--------- specs/lib/octEncodeNormalsSpec.js | 4 ---- specs/lib/quantizeAttributesSpec.js | 4 +--- specs/lib/uninterleaveAndPackBuffersSpec.js | 1 - specs/lib/updateVersionSpec.js | 1 - 8 files changed, 2 insertions(+), 28 deletions(-) diff --git a/specs/lib/RemoveUnusedPropertiesSpec.js b/specs/lib/RemoveUnusedPropertiesSpec.js index 10684322..c593ab2b 100644 --- a/specs/lib/RemoveUnusedPropertiesSpec.js +++ b/specs/lib/RemoveUnusedPropertiesSpec.js @@ -557,7 +557,6 @@ describe('RemoveUnusedProperties', function() { { bufferView: 1, byteOffset: 0, - byteStride: 0, componentType: 5123, count: 36, type: 'SCALAR' @@ -589,7 +588,6 @@ describe('RemoveUnusedProperties', function() { { bufferView: 0, byteOffset: 0, - byteStride: 0, componentType: 5123, count: 36, type: 'SCALAR' diff --git a/specs/lib/combineNodesSpec.js b/specs/lib/combineNodesSpec.js index 908ae5b0..325a59ab 100644 --- a/specs/lib/combineNodesSpec.js +++ b/specs/lib/combineNodesSpec.js @@ -215,7 +215,6 @@ describe('combineNodes', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : positions.length / 3, type : "VEC3" @@ -223,7 +222,6 @@ describe('combineNodes', function() { { bufferView : 0, byteOffset : normalsBuffer.length, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : normals.length / 3, type : "VEC3" @@ -231,7 +229,6 @@ describe('combineNodes', function() { { bufferView : 1, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indices.length, type : "SCALAR" @@ -337,7 +334,6 @@ describe('combineNodes', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : positions.length / 3, type : "VEC3" @@ -345,7 +341,6 @@ describe('combineNodes', function() { { bufferView : 0, byteOffset : normalsBuffer.length, - byteStride : 0, componentType : WebGLConstants.FLOAT, count : normals.length / 3, type : "VEC3" @@ -353,7 +348,6 @@ describe('combineNodes', function() { { bufferView : 1, byteOffset : 0, - byteStride : 0, componentType : WebGLConstants.UNSIGNED_SHORT, count : indices.length, type : "SCALAR" @@ -361,7 +355,6 @@ describe('combineNodes', function() { { bufferView: 1, byteOffset: indicesBuffer.length, - byteStride: 0, componentType: WebGLConstants.UNSIGNED_SHORT, count: overlappedIndices.length, type: "SCALAR" diff --git a/specs/lib/findAccessorMinMaxSpec.js b/specs/lib/findAccessorMinMaxSpec.js index 7d59dbeb..60b0dee9 100644 --- a/specs/lib/findAccessorMinMaxSpec.js +++ b/specs/lib/findAccessorMinMaxSpec.js @@ -45,7 +45,6 @@ describe('findAccessorMinMax', function() { var gltfBufferView = gltf.bufferViews.bufferView; gltfBufferView.byteLength = source.length; var gltfAccessor = gltf.accessors.accessor; - gltfAccessor.byteStride = 0; var minMax = findAccessorMinMax(gltf, gltfAccessor); expect(minMax.min).toEqual(expectMin); diff --git a/specs/lib/mergeDuplicateVerticesSpec.js b/specs/lib/mergeDuplicateVerticesSpec.js index 15bd80e1..8ce1ceac 100644 --- a/specs/lib/mergeDuplicateVerticesSpec.js +++ b/specs/lib/mergeDuplicateVerticesSpec.js @@ -14,21 +14,18 @@ describe('mergeDuplicateVertices', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : 5126, count : 5, type : 'VEC3' }, { bufferView : 1, byteOffset : 0, - byteStride : 0, componentType : 5123, count : 5, type : 'VEC2' }, { - bufferView : 2, + bufferView : 2, byteOffset : 0, - byteStride : 0, componentType : 5123, count : 9, type : 'SCALAR' @@ -114,35 +111,30 @@ describe('mergeDuplicateVertices', function() { { bufferView : 0, byteOffset : 0, - byteStride : 0, componentType : 5126, count : 5, type : 'VEC3' }, { bufferView : 1, byteOffset : 0, - byteStride : 0, componentType : 5126, count : 5, type : 'VEC3' }, { bufferView : 2, byteOffset : 0, - byteStride : 0, componentType : 5123, count : 5, type : 'VEC2' }, { bufferView : 3, byteOffset : 0, - byteStride : 0, componentType : 5123, count : 5, type : 'VEC2' }, { bufferView : 4, byteOffset : 0, - byteStride : 0, componentType : 5123, count : 9, type : 'SCALAR' diff --git a/specs/lib/octEncodeNormalsSpec.js b/specs/lib/octEncodeNormalsSpec.js index 8a09b00b..4ae1b3a4 100644 --- a/specs/lib/octEncodeNormalsSpec.js +++ b/specs/lib/octEncodeNormalsSpec.js @@ -18,7 +18,6 @@ describe('octEncodeNormals', function() { accessors : [ { byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, @@ -133,7 +132,6 @@ describe('octEncodeNormals', function() { var gltf = { accessors : [{ byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, @@ -146,7 +144,6 @@ describe('octEncodeNormals', function() { type : 'VEC3' }, { byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, @@ -159,7 +156,6 @@ describe('octEncodeNormals', function() { type : 'VEC3' },{ byteOffset : 0, - byteStride : 0, bufferView : 0, componentType : WebGLConstants.FLOAT, count : 3, diff --git a/specs/lib/quantizeAttributesSpec.js b/specs/lib/quantizeAttributesSpec.js index 1f850a53..f9ff6853 100644 --- a/specs/lib/quantizeAttributesSpec.js +++ b/specs/lib/quantizeAttributesSpec.js @@ -13,7 +13,6 @@ describe('quantizeAttributes', function() { // Interleaved accessors in bufferView_0 bufferView : 0, byteOffset : 0, - byteStride : 18, componentType : 5126, count : 3, min : [-1.0, -1.0, -1.0], @@ -22,7 +21,6 @@ describe('quantizeAttributes', function() { }, { bufferView : 0, byteOffset : 12, - byteStride : 18, componentType : 5123, count : 3, min : [-1.0, -1.0, -1.0], @@ -32,7 +30,6 @@ describe('quantizeAttributes', function() { // Block accessors in bufferView_1 bufferView : 1, byteOffset : 0, - byteStride : 12, componentType : 5126, count : 3, min : [-1.0, -1.0, -1.0], @@ -83,6 +80,7 @@ describe('quantizeAttributes', function() { buffer : 0, byteLength : 48, byteOffset : 0, + byteStride : 18, target : 34962 }, { diff --git a/specs/lib/uninterleaveAndPackBuffersSpec.js b/specs/lib/uninterleaveAndPackBuffersSpec.js index d5cf14b3..3234a85c 100644 --- a/specs/lib/uninterleaveAndPackBuffersSpec.js +++ b/specs/lib/uninterleaveAndPackBuffersSpec.js @@ -28,7 +28,6 @@ describe('uninterleaveAndPackBuffers', function() { { bufferView : 1, byteOffset : 0, - byteStride : 12, componentType : 5126, count : 3, type : 'VEC3' diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index 3164923c..ad740b75 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -234,7 +234,6 @@ describe('updateVersion', function() { accessors: { accessor: { byteOffset: 0, - byteStride: 0, bufferView: 'bufferView', componentType: WebGLConstants.SHORT, count: 6, From a35e5f7f212a00f49bbf7d39aac6733ab256362e Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 22 Mar 2017 16:02:04 -0400 Subject: [PATCH 44/47] Some fixes from cesium changes --- lib/combineNodes.js | 4 ++-- lib/parseBinaryGltf.js | 4 ++++ lib/updateVersion.js | 49 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/lib/combineNodes.js b/lib/combineNodes.js index ebbc72f5..cc87eab5 100644 --- a/lib/combineNodes.js +++ b/lib/combineNodes.js @@ -77,7 +77,7 @@ function getAnimationTargets(gltf, targets) { var channelsLength = channels.length; for (var channelId = 0; channelId < channelsLength; channelId++) { var channel = channels[channelId]; - targets[channel.target.id] = true; + targets[channel.target.node] = true; } } } @@ -222,7 +222,7 @@ function isFixedNode(gltf, nodeId, exclude) { if (defined(node.jointName)) { return true; } - if (defined(node.skeletons) && node.skeletons.length > 0) { + if (defined(node.skeleton)) { return true; } return defined(node.skin); diff --git a/lib/parseBinaryGltf.js b/lib/parseBinaryGltf.js index f929d7ef..89e84af1 100644 --- a/lib/parseBinaryGltf.js +++ b/lib/parseBinaryGltf.js @@ -54,6 +54,10 @@ function parseBinaryGltf(data) { buffers = gltf.buffers; if (defined(buffers) && Object.keys(buffers).length > 0) { var binaryGltfBuffer = buffers.binary_glTF; + // In some older models, the binary glTF buffer is named KHR_binary_glTF + if (!defined(binaryGltfBuffer)) { + binaryGltfBuffer = buffers.KHR_binary_glTF; + } if (defined(binaryGltfBuffer)) { binaryGltfBuffer.extras = { _pipeline: { diff --git a/lib/updateVersion.js b/lib/updateVersion.js index e93b676e..2e56b637 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -224,7 +224,20 @@ function objectToArray(object, mapping) { function objectsToArrays(gltf) { var i; - var globalMapping = {}; + var globalMapping = { + accessors: {}, + animations: {}, + bufferViews: {}, + buffers: {}, + cameras: {}, + materials: {}, + meshes: {}, + nodes: {}, + programs: {}, + shaders: {}, + skins: {}, + techniques: {} + }; // Convert top level objects to arrays for (var topLevelId in gltf) { if (gltf.hasOwnProperty(topLevelId) && topLevelId !== 'extras' && topLevelId !== 'asset') { @@ -233,6 +246,11 @@ function objectsToArrays(gltf) { if (typeof(object) === 'object' && !Array.isArray(object)) { gltf[topLevelId] = objectToArray(object, objectMapping); globalMapping[topLevelId] = objectMapping; + if (topLevelId === 'animations') { + objectMapping = {}; + object.samplers = objectToArray(object.samplers, objectMapping); + globalMapping[topLevelId].samplers = objectMapping; + } } } } @@ -275,11 +293,25 @@ function objectsToArrays(gltf) { if (defined(technique.program)) { technique.program = globalMapping.programs[technique.program]; } - }); - ForEach.material(gltf, function(material) { - if (defined(material.technique)) { - material.technique = globalMapping.techniques[material.technique]; - } + ForEach.techniqueParameter(technique, function(parameter) { + if (defined(parameter.node)) { + parameter.node = globalMapping.nodes[parameter.node]; + } + var value = parameter.value; + if (defined(value)) { + if (Array.isArray(value)) { + if (value.length === 1) { + var textureId = value[0]; + if (typeof textureId === 'string') { + value[0] = globalMapping.textures[textureId]; + } + } + } + else if (typeof value === 'string') { + parameter.value = [globalMapping.textures[value]]; + } + } + }); }); ForEach.mesh(gltf, function(mesh) { ForEach.meshPrimitives(mesh, function(primitive) { @@ -381,12 +413,15 @@ function objectsToArrays(gltf) { channel.sampler = samplerMapping[channel.sampler]; var target = channel.target; if (defined(target)) { - target.node = globalMapping.nodes[target.node]; + target.node = globalMapping.nodes[target.id]; } } } }); ForEach.material(gltf, function(material) { + if (defined(material.technique)) { + material.technique = globalMapping.techniques[material.technique]; + } ForEach.materialValue(material, function(value, name) { if (Array.isArray(value)) { if (value.length === 1) { From 7492f5724e6f2ed8b76c0fb3a0cb13ec89cb4166 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Wed, 22 Mar 2017 16:02:12 -0400 Subject: [PATCH 45/47] Fixed cesium dependency list --- gulpfile.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index a089bbea..da431bae 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -277,17 +277,21 @@ gulp.task('build-cesium', function () { var outputDir = 'dist/cesium'; var files = [ 'addDefaults.js', + 'addExtensionsRequired.js', 'addExtensionsUsed.js', 'addPipelineExtras.js', + 'addToArray.js', 'byteLengthForComponentType.js', 'findAccessorMinMax.js', + 'ForEach.js', 'getAccessorByteStride.js', 'getStatistics.js', - 'getUniqueId.js', 'numberOfComponentsForType.js', 'parseBinaryGltf.js', 'processModelMaterialsCommon.js', 'removePipelineExtras.js', + 'removeExtensionsRequired.js', + 'removeExtensionsUsed.js', 'techniqueParameterForSemantic.js', 'updateVersion.js' ]; From ab6daeee13e4abc6450082f45b5009e25a23de11 Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Sun, 2 Apr 2017 19:38:43 -0400 Subject: [PATCH 46/47] Fixed some plurality issues --- lib/ForEach.js | 16 ++++++++-------- lib/MergeDuplicateProperties.js | 4 ++-- lib/PrimitiveHelpers.js | 2 +- lib/Remove.js | 8 ++++---- lib/RemoveUnusedProperties.js | 12 ++++++------ lib/createAccessorUsageTables.js | 2 +- lib/generateTangentsBitangents.js | 2 +- lib/getBinaryGltf.js | 2 +- lib/getStatistics.js | 4 ++-- lib/mergeDuplicateVertices.js | 2 +- lib/optimizeForVertexCache.js | 4 ++-- lib/processModelMaterialsCommon.js | 4 ++-- lib/quantizeAttributes.js | 4 ++-- lib/updateVersion.js | 14 +++++++------- lib/writeSource.js | 2 +- 15 files changed, 41 insertions(+), 41 deletions(-) diff --git a/lib/ForEach.js b/lib/ForEach.js index f594a923..e4880ea9 100644 --- a/lib/ForEach.js +++ b/lib/ForEach.js @@ -13,7 +13,7 @@ module.exports = ForEach; */ function ForEach() {} -ForEach.arrayOfObjects = function(arrayOfObjects, handler) { +ForEach.object = function(arrayOfObjects, handler) { if (defined(arrayOfObjects)) { for (var i = 0; i < arrayOfObjects.length; i++) { var object = arrayOfObjects[i]; @@ -25,7 +25,7 @@ ForEach.arrayOfObjects = function(arrayOfObjects, handler) { ForEach.topLevel = function(gltf, name, handler) { var arrayOfObjects = gltf[name]; - ForEach.arrayOfObjects(arrayOfObjects, handler); + ForEach.object(arrayOfObjects, handler); }; ForEach.accessor = function(gltf, handler) { @@ -34,8 +34,8 @@ ForEach.accessor = function(gltf, handler) { ForEach.accessorWithSemantic = function(gltf, semantic, handler) { ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { - ForEach.meshPrimitiveAttributes(primitive, function(accessorId, attributeSemantic) { + ForEach.meshPrimitive(mesh, function(primitive) { + ForEach.meshPrimitiveAttribute(primitive, function(accessorId, attributeSemantic) { if (attributeSemantic.indexOf(semantic) === 0) { handler(accessorId, attributeSemantic, primitive); } @@ -48,10 +48,10 @@ ForEach.animation = function(gltf, handler) { ForEach.topLevel(gltf, 'animations', handler); }; -ForEach.animationSamplers = function(animation, handler) { +ForEach.animationSampler = function(animation, handler) { var samplers = animation.samplers; if (defined(samplers)) { - ForEach.arrayOfObjects(samplers, handler); + ForEach.object(samplers, handler); } }; @@ -90,7 +90,7 @@ ForEach.mesh = function(gltf, handler) { ForEach.topLevel(gltf, 'meshes', handler); }; -ForEach.meshPrimitives = function(mesh, handler) { +ForEach.meshPrimitive = function(mesh, handler) { var primitives = mesh.primitives; if (defined(primitives)) { var primitivesLength = primitives.length; @@ -101,7 +101,7 @@ ForEach.meshPrimitives = function(mesh, handler) { } }; -ForEach.meshPrimitiveAttributes = function(primitive, handler) { +ForEach.meshPrimitiveAttribute = function(primitive, handler) { var attributes = primitive.attributes; if (defined(attributes)) { for (var semantic in attributes) { diff --git a/lib/MergeDuplicateProperties.js b/lib/MergeDuplicateProperties.js index 8ae43bcb..2e7d78df 100644 --- a/lib/MergeDuplicateProperties.js +++ b/lib/MergeDuplicateProperties.js @@ -71,12 +71,12 @@ MergeDuplicateProperties.mergeAccessors = function(gltf) { function replaceAccessorIdInstances(gltf, accessorId, newAccessorId) { ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function (primitive) { + ForEach.meshPrimitive(mesh, function (primitive) { var indices = primitive.indices; if (indices === accessorId) { primitive.indices = newAccessorId; } - ForEach.meshPrimitiveAttributes(primitive, function (attributeAccessorId, semantic) { + ForEach.meshPrimitiveAttribute(primitive, function (attributeAccessorId, semantic) { if (attributeAccessorId === accessorId) { primitive.attributes[semantic] = newAccessorId; } diff --git a/lib/PrimitiveHelpers.js b/lib/PrimitiveHelpers.js index c2161c92..ff8b300b 100644 --- a/lib/PrimitiveHelpers.js +++ b/lib/PrimitiveHelpers.js @@ -242,7 +242,7 @@ function getPrimitiveConflicts(primitives, primitive) { function getAllPrimitives(gltf) { var primitives = []; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { primitives.push(primitive); }); }); diff --git a/lib/Remove.js b/lib/Remove.js index e5378eaf..ef888055 100644 --- a/lib/Remove.js +++ b/lib/Remove.js @@ -21,8 +21,8 @@ Remove.accessor = function(gltf, accessorId) { accessors.splice(accessorId, 1); ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { - ForEach.meshPrimitiveAttributes(primitive, function(attributeAccessorId, semantic) { + ForEach.meshPrimitive(mesh, function(primitive) { + ForEach.meshPrimitiveAttribute(primitive, function(attributeAccessorId, semantic) { if (attributeAccessorId > accessorId) { primitive.attributes[semantic]--; } @@ -41,7 +41,7 @@ Remove.accessor = function(gltf, accessorId) { }); ForEach.animation(gltf, function(animation) { - ForEach.animationSamplers(animation, function(sampler) { + ForEach.animationSampler(animation, function(sampler) { if (defined(sampler.input) && sampler.input > accessorId) { sampler.input--; } @@ -106,7 +106,7 @@ Remove.material = function(gltf, materialId) { materials.splice(materialId, 1); ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { if (defined(primitive.material) && primitive.material > materialId) { primitive.material--; } diff --git a/lib/RemoveUnusedProperties.js b/lib/RemoveUnusedProperties.js index 57b7efa5..3d039c7a 100644 --- a/lib/RemoveUnusedProperties.js +++ b/lib/RemoveUnusedProperties.js @@ -155,8 +155,8 @@ RemoveUnusedProperties.removeAccessors = function(gltf) { var usedAccessorIds = {}; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { - ForEach.meshPrimitiveAttributes(primitive, function(accessorId) { + ForEach.meshPrimitive(mesh, function(primitive) { + ForEach.meshPrimitiveAttribute(primitive, function(accessorId) { usedAccessorIds[accessorId] = true; }); var indices = primitive.indices; @@ -173,7 +173,7 @@ RemoveUnusedProperties.removeAccessors = function(gltf) { }); ForEach.animation(gltf, function(animation) { - ForEach.animationSamplers(animation, function(sampler) { + ForEach.animationSampler(animation, function(sampler) { if (defined(sampler.input)) { usedAccessorIds[sampler.input] = true; } @@ -197,7 +197,7 @@ RemoveUnusedProperties.removeMaterials = function(gltf) { var usedMaterialIds = {}; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { if (defined(primitive.material)) { usedMaterialIds[primitive.material] = true; } @@ -386,11 +386,11 @@ RemoveUnusedProperties.removePrimitiveAttributes = function(gltf) { var techniques = gltf.techniques; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { var usedAttributes = {}; var hasAttributes = false; /* jshint unused:vars */ - ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { usedAttributes[semantic] = false; hasAttributes = true; }); diff --git a/lib/createAccessorUsageTables.js b/lib/createAccessorUsageTables.js index 03140d47..c3301b97 100644 --- a/lib/createAccessorUsageTables.js +++ b/lib/createAccessorUsageTables.js @@ -80,7 +80,7 @@ function createAccessorUsageTables(gltf) { var tableIndex; var i; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { var attributes = primitive.attributes; var indexAccessorId = primitive.indices; if (defined(indexAccessorId)) { diff --git a/lib/generateTangentsBitangents.js b/lib/generateTangentsBitangents.js index bf914a10..675cb878 100644 --- a/lib/generateTangentsBitangents.js +++ b/lib/generateTangentsBitangents.js @@ -23,7 +23,7 @@ module.exports = generateTangentsBitangents; */ function generateTangentsBitangents(gltf) { ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { var positionAccessorId = primitive.attributes.POSITION; var normalAccessorId = primitive.attributes.NORMAL; var texcoordAccessorId = primitive.attributes.TEXCOORD_0; diff --git a/lib/getBinaryGltf.js b/lib/getBinaryGltf.js index cdea87ea..449cc94b 100644 --- a/lib/getBinaryGltf.js +++ b/lib/getBinaryGltf.js @@ -18,7 +18,7 @@ function updateBinaryObject(gltf, objects, hasMimeType) { hasMimeType = defaultValue(hasMimeType, false); var buffer = gltf.buffers[0]; var bufferPipelineExtras = buffer.extras._pipeline; - ForEach.arrayOfObjects(objects, function(object) { + ForEach.object(objects, function(object) { var pipelineExtras = object.extras._pipeline; var source = pipelineExtras.source; var bufferView = { diff --git a/lib/getStatistics.js b/lib/getStatistics.js index 982b17a0..bb68c1a7 100644 --- a/lib/getStatistics.js +++ b/lib/getStatistics.js @@ -67,7 +67,7 @@ function isDataUri(uri) { function getAllPrimitives(gltf) { var primitives = []; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { primitives.push(primitive); }); }); @@ -84,7 +84,7 @@ function getBuffersSize(gltf) { function getNumberOfExternalProperties(property) { var count = 0; - ForEach.arrayOfObjects(property, function(object) { + ForEach.object(property, function(object) { var uri = object.uri; if (defined(uri) && !isDataUri(uri)) { count++; diff --git a/lib/mergeDuplicateVertices.js b/lib/mergeDuplicateVertices.js index 5832bace..96e971de 100644 --- a/lib/mergeDuplicateVertices.js +++ b/lib/mergeDuplicateVertices.js @@ -68,7 +68,7 @@ function findDuplicateVerticesInMesh(gltf, mesh, indexAccessors) { var accessors = gltf.accessors; var buffers = gltf.buffers; var bufferViews = gltf.bufferViews; - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { var indexAccessorId = primitive.indices; var attribute; if (defined(indexAccessorId)) { diff --git a/lib/optimizeForVertexCache.js b/lib/optimizeForVertexCache.js index ab25be73..6c7094ca 100644 --- a/lib/optimizeForVertexCache.js +++ b/lib/optimizeForVertexCache.js @@ -14,7 +14,7 @@ module.exports = optimizeForVertexCache; function createIndicesToAttributeDictionary(gltf) { var dictionary = {}; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { var indicesId = primitive.indices; var primitivesOfIndicesId; if (!dictionary[indicesId]) { @@ -73,7 +73,7 @@ function optimizeForVertexCache(gltf, cacheSize) { var primitive; var geometry; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { if (defined(primitive.indices)) { geometry = gltfPrimitiveToCesiumGeometry(gltf, primitive); GeometryPipeline.reorderForPostVertexCache(geometry, cacheSize); diff --git a/lib/processModelMaterialsCommon.js b/lib/processModelMaterialsCommon.js index de7044fe..09cea61f 100644 --- a/lib/processModelMaterialsCommon.js +++ b/lib/processModelMaterialsCommon.js @@ -815,7 +815,7 @@ function ensureSemanticExistenceForPrimitive(gltf, primitive) { function ensureSemanticExistence(gltf) { ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { ensureSemanticExistenceForPrimitive(gltf, primitive); }); }); @@ -825,7 +825,7 @@ function splitIncompatibleSkins(gltf) { var accessors = gltf.accessors; var materials = gltf.materials; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { var materialId = primitive.material; var material = materials[materialId]; diff --git a/lib/quantizeAttributes.js b/lib/quantizeAttributes.js index 499f221f..29189c8e 100644 --- a/lib/quantizeAttributes.js +++ b/lib/quantizeAttributes.js @@ -194,8 +194,8 @@ function getAllQuantizableAttributes(gltf, validSemantics, excludeSemantics) { var visitedAccessors = {}; var accessorAttributes = {}; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { - ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + ForEach.meshPrimitive(mesh, function(primitive) { + ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { if ((!defined(validSemantics) && !defined(excludeSemantics)) || isSemanticValid(semantic, validSemantics, excludeSemantics)) { if (!defined(visitedAccessors[accessorId])) { diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 2e56b637..bb44ac4b 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -314,11 +314,11 @@ function objectsToArrays(gltf) { }); }); ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { if (defined(primitive.indices)) { primitive.indices = globalMapping.accessors[primitive.indices]; } - ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { primitive.attributes[semantic] = globalMapping.accessors[accessorId]; }); if (defined(primitive.material)) { @@ -401,7 +401,7 @@ function objectsToArrays(gltf) { ForEach.animation(gltf, function(animation) { var samplerMapping = {}; animation.samplers = objectToArray(animation.samplers, samplerMapping); - ForEach.animationSamplers(animation, function(sampler) { + ForEach.animationSampler(animation, function(sampler) { sampler.input = globalMapping.accessors[sampler.input]; sampler.output = globalMapping.accessors[sampler.output]; }); @@ -522,8 +522,8 @@ function makeMaterialValuesArrays(gltf) { function requireAttributeSetIndex(gltf) { ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { - ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + ForEach.meshPrimitive(mesh, function(primitive) { + ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { if (semantic === 'TEXCOORD') { primitive.attributes.TEXCOORD_0 = accessorId; } else if (semantic === 'COLOR') { @@ -559,9 +559,9 @@ var knownSemantics = { function underscoreApplicationSpecificSemantics(gltf) { var mappedSemantics = {}; ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitives(mesh, function(primitive) { + ForEach.meshPrimitive(mesh, function(primitive) { /* jshint unused:vars */ - ForEach.meshPrimitiveAttributes(primitive, function(accessorId, semantic) { + ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { if (semantic.charAt(0) !== '_') { var setIndex = semantic.search(/_[0-9]+/g); var strippedSemantic = semantic; diff --git a/lib/writeSource.js b/lib/writeSource.js index 678974f0..a1654b04 100644 --- a/lib/writeSource.js +++ b/lib/writeSource.js @@ -24,7 +24,7 @@ function writeSource(arrayOfObjects, name, basePath, options) { var embed = defaultValue(options.embed, true); var embedImage = defaultValue(options.embedImage, true); var promises = []; - ForEach.arrayOfObjects(arrayOfObjects, function(object, i) { + ForEach.object(arrayOfObjects, function(object, i) { if (defined(object.extras._pipeline.source)) { var pipelineExtras = object.extras._pipeline; var source = pipelineExtras.source; From 34d1c6735f70c5efe8738c602283ac59665ec52f Mon Sep 17 00:00:00 2001 From: lasalvavida Date: Sun, 2 Apr 2017 19:42:57 -0400 Subject: [PATCH 47/47] Add KHR_technique_webgl extensions if there are techniques --- lib/updateVersion.js | 26 ++++++++++++++++++-------- specs/lib/updateVersionSpec.js | 6 ++++-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/updateVersion.js b/lib/updateVersion.js index bb44ac4b..91eae7d9 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -1,5 +1,6 @@ 'use strict'; var Cesium = require('cesium'); +var addExtensionsRequired = require('./addExtensionsRequired'); var addToArray = require('./addToArray'); var ForEach = require('./ForEach'); var findAccessorMinMax = require('./findAccessorMinMax'); @@ -719,17 +720,24 @@ function stripTechniqueAttributeValues(gltf) { function stripTechniqueParameterCount(gltf) { ForEach.technique(gltf, function(technique) { - ForEach.techniqueParameter(technique, function(parameter) { - if (defined(parameter.count)) { - var semantic = parameter.semantic; - if (!defined(semantic) || (semantic !== 'JOINTMATRIX' && semantic.indexOf('_') !== 0)) { - delete parameter.count; - } - } - }); + ForEach.techniqueParameter(technique, function(parameter) { + if (defined(parameter.count)) { + var semantic = parameter.semantic; + if (!defined(semantic) || (semantic !== 'JOINTMATRIX' && semantic.indexOf('_') !== 0)) { + delete parameter.count; + } + } + }); }); } +function addKHRTechniqueExtension(gltf) { + var techniques = gltf.techniques; + if (defined(techniques) && techniques.length > 0) { + addExtensionsRequired(gltf, 'KHR_technique_webgl'); + } +} + function glTF10to20(gltf) { if (!defined(gltf.asset)) { gltf.asset = {}; @@ -770,4 +778,6 @@ function glTF10to20(gltf) { stripTechniqueAttributeValues(gltf); // only techniques with a JOINTMATRIX or application specific semantic may have a defined count property stripTechniqueParameterCount(gltf); + // add KHR_technique_webgl extension + addKHRTechniqueExtension(gltf); } diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index ad740b75..109f2f48 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -312,12 +312,14 @@ describe('updateVersion', function() { expect(extensionsUsed).toEqual([ 'KHR_materials_common', 'WEB3D_quantized_attributes', - 'UNKOWN_EXTENSION' + 'UNKOWN_EXTENSION', + 'KHR_technique_webgl' ]); var extensionsRequired = gltf.extensionsRequired; expect(extensionsRequired).toEqual([ 'KHR_materials_common', - 'WEB3D_quantized_attributes' + 'WEB3D_quantized_attributes', + 'KHR_technique_webgl' ]); var animation = gltf.animations[0]; var sampler = animation.samplers[0];