diff --git a/lib/ForEach.js b/lib/ForEach.js index 2e7b54f5..67204371 100644 --- a/lib/ForEach.js +++ b/lib/ForEach.js @@ -25,7 +25,11 @@ ForEach.objectLegacy = function(objects, handler) { for (var objectId in objects) { if (objects.hasOwnProperty(objectId)) { var object = objects[objectId]; - handler(object, objectId); + var value = handler(object, objectId); + + if (defined(value)) { + return value; + } } } } @@ -39,7 +43,11 @@ ForEach.object = function(arrayOfObjects, handler) { var length = arrayOfObjects.length; for (var i = 0; i < length; i++) { var object = arrayOfObjects[i]; - handler(object, i); + var value = handler(object, i); + + if (defined(value)) { + return value; + } } } }; @@ -51,31 +59,44 @@ ForEach.object = function(arrayOfObjects, handler) { ForEach.topLevel = function(gltf, name, handler) { var gltfProperty = gltf[name]; if (defined(gltfProperty) && !isArray(gltfProperty)) { - ForEach.objectLegacy(gltfProperty, handler); - } else { - ForEach.object(gltfProperty, handler); + return ForEach.objectLegacy(gltfProperty, handler); } + + return ForEach.object(gltfProperty, handler); }; ForEach.accessor = function(gltf, handler) { - ForEach.topLevel(gltf, 'accessors', handler); + return ForEach.topLevel(gltf, 'accessors', handler); }; ForEach.accessorWithSemantic = function(gltf, semantic, handler) { var visited = {}; - ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitive(mesh, function(primitive) { - ForEach.meshPrimitiveAttribute(primitive, function(accessorId, attributeSemantic) { + return ForEach.mesh(gltf, function(mesh) { + return ForEach.meshPrimitive(mesh, function(primitive) { + var value = ForEach.meshPrimitiveAttribute(primitive, function(accessorId, attributeSemantic) { if (attributeSemantic.indexOf(semantic) === 0 && !defined(visited[accessorId])) { visited[accessorId] = true; - handler(accessorId); + value = handler(accessorId); + + if (defined(value)) { + return value; + } } }); - ForEach.meshPrimitiveTarget(primitive, function(target) { - ForEach.meshPrimitiveTargetAttribute(target, function(accessorId, attributeSemantic) { + + if (defined(value)) { + return value; + } + + return ForEach.meshPrimitiveTarget(primitive, function(target) { + return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId, attributeSemantic) { if (attributeSemantic.indexOf(semantic) === 0 && !defined(visited[accessorId])) { visited[accessorId] = true; - handler(accessorId); + value = handler(accessorId); + + if (defined(value)) { + return value; + } } }); }); @@ -85,19 +106,32 @@ ForEach.accessorWithSemantic = function(gltf, semantic, handler) { ForEach.accessorContainingVertexAttributeData = function(gltf, handler) { var visited = {}; - ForEach.mesh(gltf, function(mesh) { - ForEach.meshPrimitive(mesh, function (primitive) { - ForEach.meshPrimitiveAttribute(primitive, function(accessorId) { + return ForEach.mesh(gltf, function(mesh) { + return ForEach.meshPrimitive(mesh, function(primitive) { + var value = ForEach.meshPrimitiveAttribute(primitive, function(accessorId) { if (!defined(visited[accessorId])) { visited[accessorId] = true; - handler(accessorId); + value = handler(accessorId); + + if (defined(value)) { + return value; + } } }); - ForEach.meshPrimitiveTarget(primitive, function(target) { - ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) { + + if (defined(value)) { + return value; + } + + return ForEach.meshPrimitiveTarget(primitive, function(target) { + return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) { if (!defined(visited[accessorId])) { visited[accessorId] = true; - handler(accessorId); + value = handler(accessorId); + + if (defined(value)) { + return value; + } } }); }); @@ -107,45 +141,49 @@ ForEach.accessorContainingVertexAttributeData = function(gltf, handler) { ForEach.accessorContainingIndexData = function(gltf, handler) { var visited = {}; - ForEach.mesh(gltf, function (mesh) { - ForEach.meshPrimitive(mesh, function (primitive) { + return ForEach.mesh(gltf, function(mesh) { + return ForEach.meshPrimitive(mesh, function(primitive) { var indices = primitive.indices; if (defined(indices) && !defined(visited[indices])) { visited[indices] = true; - handler(indices); + var value = handler(indices); + + if (defined(value)) { + return value; + } } }); }); }; ForEach.animation = function(gltf, handler) { - ForEach.topLevel(gltf, 'animations', handler); + return ForEach.topLevel(gltf, 'animations', handler); }; ForEach.animationChannel = function(animation, handler) { var channels = animation.channels; - ForEach.object(channels, handler); + return ForEach.object(channels, handler); }; ForEach.animationSampler = function(animation, handler) { var samplers = animation.samplers; - ForEach.object(samplers, handler); + return ForEach.object(samplers, handler); }; ForEach.buffer = function(gltf, handler) { - ForEach.topLevel(gltf, 'buffers', handler); + return ForEach.topLevel(gltf, 'buffers', handler); }; ForEach.bufferView = function(gltf, handler) { - ForEach.topLevel(gltf, 'bufferViews', handler); + return ForEach.topLevel(gltf, 'bufferViews', handler); }; ForEach.camera = function(gltf, handler) { - ForEach.topLevel(gltf, 'cameras', handler); + return ForEach.topLevel(gltf, 'cameras', handler); }; ForEach.image = function(gltf, handler) { - ForEach.topLevel(gltf, 'images', handler); + return ForEach.topLevel(gltf, 'images', handler); }; ForEach.compressedImage = function(image, handler) { @@ -154,14 +192,18 @@ ForEach.compressedImage = function(image, handler) { for (var type in compressedImages) { if (compressedImages.hasOwnProperty(type)) { var compressedImage = compressedImages[type]; - handler(compressedImage, type); + var value = handler(compressedImage, type); + + if (defined(value)) { + return value; + } } } } }; ForEach.material = function(gltf, handler) { - ForEach.topLevel(gltf, 'materials', handler); + return ForEach.topLevel(gltf, 'materials', handler); }; ForEach.materialValue = function(material, handler) { @@ -172,13 +214,17 @@ ForEach.materialValue = function(material, handler) { for (var name in values) { if (values.hasOwnProperty(name)) { - handler(values[name], name); + var value = handler(values[name], name); + + if (defined(value)) { + return value; + } } } }; ForEach.mesh = function(gltf, handler) { - ForEach.topLevel(gltf, 'meshes', handler); + return ForEach.topLevel(gltf, 'meshes', handler); }; ForEach.meshPrimitive = function(mesh, handler) { @@ -187,7 +233,11 @@ ForEach.meshPrimitive = function(mesh, handler) { var primitivesLength = primitives.length; for (var i = 0; i < primitivesLength; i++) { var primitive = primitives[i]; - handler(primitive, i); + var value = handler(primitive, i); + + if (defined(value)) { + return value; + } } } }; @@ -196,7 +246,11 @@ ForEach.meshPrimitiveAttribute = function(primitive, handler) { var attributes = primitive.attributes; for (var semantic in attributes) { if (attributes.hasOwnProperty(semantic)) { - handler(attributes[semantic], semantic); + var value = handler(attributes[semantic], semantic); + + if (defined(value)) { + return value; + } } } }; @@ -206,7 +260,11 @@ ForEach.meshPrimitiveTarget = function(primitive, handler) { if (defined(targets)) { var length = targets.length; for (var i = 0; i < length; ++i) { - handler(targets[i], i); + var value = handler(targets[i], i); + + if (defined(value)) { + return value; + } } } }; @@ -215,13 +273,17 @@ ForEach.meshPrimitiveTargetAttribute = function(target, handler) { for (var semantic in target) { if (target.hasOwnProperty(semantic)) { var accessorId = target[semantic]; - handler(accessorId, semantic); + var value = handler(accessorId, semantic); + + if (defined(value)) { + return value; + } } } }; ForEach.node = function(gltf, handler) { - ForEach.topLevel(gltf, 'nodes', handler); + return ForEach.topLevel(gltf, 'nodes', handler); }; ForEach.nodeInTree = function(gltf, nodeIds, handler) { @@ -232,10 +294,19 @@ ForEach.nodeInTree = function(gltf, nodeIds, handler) { var nodeId = nodeIds[i]; var node = nodes[nodeId]; if (defined(node)) { - handler(node, nodeId); + var value = handler(node, nodeId); + + if (defined(value)) { + return value; + } + var children = node.children; if (defined(children)) { - ForEach.nodeInTree(gltf, children, handler); + value = ForEach.nodeInTree(gltf, children, handler); + + if (defined(value)) { + return value; + } } } } @@ -245,43 +316,47 @@ ForEach.nodeInTree = function(gltf, nodeIds, handler) { ForEach.nodeInScene = function(gltf, scene, handler) { var sceneNodeIds = scene.nodes; if (defined(sceneNodeIds)) { - ForEach.nodeInTree(gltf, sceneNodeIds, handler); + return ForEach.nodeInTree(gltf, sceneNodeIds, handler); } }; ForEach.program = function(gltf, handler) { if (hasExtension(gltf, 'KHR_techniques_webgl')) { - ForEach.object(gltf.extensions.KHR_techniques_webgl.programs, handler); - } else { - ForEach.topLevel(gltf, 'programs', handler); + return ForEach.object(gltf.extensions.KHR_techniques_webgl.programs, handler); } + + return ForEach.topLevel(gltf, 'programs', handler); }; ForEach.sampler = function(gltf, handler) { - ForEach.topLevel(gltf, 'samplers', handler); + return ForEach.topLevel(gltf, 'samplers', handler); }; ForEach.scene = function(gltf, handler) { - ForEach.topLevel(gltf, 'scenes', handler); + return ForEach.topLevel(gltf, 'scenes', handler); }; ForEach.shader = function(gltf, handler) { if (hasExtension(gltf, 'KHR_techniques_webgl')) { - ForEach.object(gltf.extensions.KHR_techniques_webgl.shaders, handler); - } else { - ForEach.topLevel(gltf, 'shaders', handler); + return ForEach.object(gltf.extensions.KHR_techniques_webgl.shaders, handler); } + + return ForEach.topLevel(gltf, 'shaders', handler); }; ForEach.skin = function(gltf, handler) { - ForEach.topLevel(gltf, 'skins', handler); + return ForEach.topLevel(gltf, 'skins', handler); }; ForEach.techniqueAttribute = function(technique, handler) { var attributes = technique.attributes; for (var attributeName in attributes) { if (attributes.hasOwnProperty(attributeName)) { - handler(attributes[attributeName], attributeName); + var value = handler(attributes[attributeName], attributeName); + + if (defined(value)) { + return value; + } } } }; @@ -290,7 +365,11 @@ ForEach.techniqueUniform = function(technique, handler) { var uniforms = technique.uniforms; for (var uniformName in uniforms) { if (uniforms.hasOwnProperty(uniformName)) { - handler(uniforms[uniformName], uniformName); + var value = handler(uniforms[uniformName], uniformName); + + if (defined(value)) { + return value; + } } } }; @@ -299,19 +378,23 @@ ForEach.techniqueParameter = function(technique, handler) { var parameters = technique.parameters; for (var parameterName in parameters) { if (parameters.hasOwnProperty(parameterName)) { - handler(parameters[parameterName], parameterName); + var value = handler(parameters[parameterName], parameterName); + + if (defined(value)) { + return value; + } } } }; ForEach.technique = function(gltf, handler) { if (hasExtension(gltf, 'KHR_techniques_webgl')) { - ForEach.object(gltf.extensions.KHR_techniques_webgl.techniques, handler); - } else { - ForEach.topLevel(gltf, 'techniques', handler); + return ForEach.object(gltf.extensions.KHR_techniques_webgl.techniques, handler); } + + return ForEach.topLevel(gltf, 'techniques', handler); }; ForEach.texture = function(gltf, handler) { - ForEach.topLevel(gltf, 'textures', handler); + return ForEach.topLevel(gltf, 'textures', handler); }; diff --git a/lib/compressDracoMeshes.js b/lib/compressDracoMeshes.js index 4a926afd..8f89fb56 100644 --- a/lib/compressDracoMeshes.js +++ b/lib/compressDracoMeshes.js @@ -8,6 +8,7 @@ var ForEach = require('./ForEach'); var numberOfComponentsForType = require('./numberOfComponentsForType'); var readAccessorPacked = require('./readAccessorPacked'); var removeUnusedElements = require('./removeUnusedElements'); +var replaceWithDecompressedPrimitive = require('./replaceWithDecompressedPrimitive'); var splitPrimitives = require('./splitPrimitives'); var arrayFill = Cesium.arrayFill; @@ -183,16 +184,19 @@ function compressDracoMeshes(gltf, options) { encoder.SetEncodingMethod(encoderModule.MESH_SEQUENTIAL_ENCODING); } + encoder.SetTrackEncodedProperties(true); var encodedLength = encoder.EncodeMeshToDracoBuffer(mesh, encodedDracoDataArray); if (encodedLength <= 0) { throw new RuntimeError('Error: Draco encoding failed.'); } + var encodedPointsCount = encoder.GetNumberOfEncodedPoints(); + var encodedFacesCount = encoder.GetNumberOfEncodedFaces(); var encodedData = Buffer.alloc(encodedLength); for (var i = 0; i < encodedLength; ++i) { encodedData[i] = encodedDracoDataArray.GetValue(i); } - addCompressionExtensionToPrimitive(gltf, primitive, attributeToId, encodedLength, encodedData); + addCompressionExtensionToPrimitive(gltf, primitive, attributeToId, encodedLength, encodedData, encodedPointsCount, encodedFacesCount); encoderModule.destroy(encodedDracoDataArray); encoderModule.destroy(mesh); @@ -209,7 +213,7 @@ function compressDracoMeshes(gltf, options) { return gltf; } -function addCompressionExtensionToPrimitive(gltf, primitive, attributeToId, encodedLength, encodedData) { +function addCompressionExtensionToPrimitive(gltf, primitive, attributeToId, encodedLength, encodedData, encodedPointsCount, encodedFacesCount) { // Remove properties from accessors. // Remove indices bufferView. var indicesAccessor = clone(gltf.accessors[primitive.indices]); @@ -246,6 +250,8 @@ function addCompressionExtensionToPrimitive(gltf, primitive, attributeToId, enco bufferView: bufferViewId, attributes: attributeToId }; + + gltf = replaceWithDecompressedPrimitive(gltf, primitive, encodedPointsCount, encodedFacesCount); } function copyCompressedExtensionToPrimitive(primitive, compressedPrimitive) { @@ -295,4 +301,4 @@ compressDracoMeshes.defaults = { quantizeSkinBits: 12, quantizeGenericBits: 12, unifiedQuantization: false -}; \ No newline at end of file +}; diff --git a/lib/readAccessorPacked.js b/lib/readAccessorPacked.js index dd771830..63b52bec 100644 --- a/lib/readAccessorPacked.js +++ b/lib/readAccessorPacked.js @@ -1,7 +1,7 @@ 'use strict'; var Cesium = require('cesium'); var getAccessorByteStride = require('./getAccessorByteStride'); -var getComponentReader = require('./getComponentReader.js'); +var getComponentReader = require('./getComponentReader'); var numberOfComponentsForType = require('./numberOfComponentsForType'); var arrayFill = Cesium.arrayFill; diff --git a/lib/replaceWithDecompressedPrimitive.js b/lib/replaceWithDecompressedPrimitive.js new file mode 100644 index 00000000..0972bf8d --- /dev/null +++ b/lib/replaceWithDecompressedPrimitive.js @@ -0,0 +1,32 @@ +'use strict'; + +module.exports = replaceWithDecompressedPrimitive; + +/** + * Replace the accessor properties of the original primitive with the values from the decompressed primitive. + * + * @param {Object} gltf A javascript object containing a glTF asset. + * @param {Object} primitive A javascript object containing a glTF primitive. + * @param {Number} encodedPointsCount Number of points after the mesh is decompressed. + * @param {Number} encodedFacesCount Number of faces after the mesh is decompressed. + * @returns {Object} The glTF asset with the decompressed primitive. + * + * @private + */ +function replaceWithDecompressedPrimitive(gltf, primitive, encodedPointsCount, encodedFacesCount) { + // Add decompressed indices data to indices accessor. + var indicesAccessorId = primitive.indices; + var indicesAccessor = gltf.accessors[indicesAccessorId]; + indicesAccessor.count = encodedFacesCount * 3; + + var dracoAttributes = primitive.extensions.KHR_draco_mesh_compression.attributes; + for (var semantic in dracoAttributes) { + if (dracoAttributes.hasOwnProperty(semantic)) { + var gltfAttributeId = primitive.attributes[semantic]; + var attributeAccessor = gltf.accessors[gltfAttributeId]; + attributeAccessor.count = encodedPointsCount; + } + } + + return gltf; +} diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 65981369..b498775a 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -803,8 +803,9 @@ function moveByteStrideToBufferView(gltf) { removeUnusedElements(gltf); } -function requireAccessorMinMax(gltf) { - ForEach.accessor(gltf, function(accessor) { +function requirePositionAccessorMinMax(gltf) { + ForEach.accessorWithSemantic(gltf, 'POSITION', function(accessorId) { + var accessor = gltf.accessors[accessorId]; if (!defined(accessor.min) || !defined(accessor.max)) { var minMax = findAccessorMinMax(gltf, accessor); accessor.min = minMax.min; @@ -830,8 +831,8 @@ function glTF10to20(gltf) { requireByteLength(gltf); // byteStride moved from accessor to bufferView moveByteStrideToBufferView(gltf); - // accessor.min and accessor.max must be defined - requireAccessorMinMax(gltf); + // accessor.min and accessor.max must be defined for accessors containing POSITION attributes + requirePositionAccessorMinMax(gltf); // buffer.type is unnecessary and should be removed removeBufferType(gltf); // Remove format, internalFormat, target, and type diff --git a/lib/writeResources.js b/lib/writeResources.js index b72d560e..4792ec83 100644 --- a/lib/writeResources.js +++ b/lib/writeResources.js @@ -139,16 +139,14 @@ function writeBufferView(gltf, object) { } function getProgram(gltf, shaderIndex) { - var programInfo; - ForEach.program(gltf, function(program, index) { + return ForEach.program(gltf, function(program, index) { if (program.fragmentShader === shaderIndex || program.vertexShader === shaderIndex) { - programInfo = { + return { program: program, index: index }; } }); - return programInfo; } function getName(gltf, object, index, extension, options) { diff --git a/package.json b/package.json index e345e732..24a4f038 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "bluebird": "^3.5.1", "cesium": "^1.43.0", - "draco3d": "^1.3.0", + "draco3d": "^1.3.3", "fs-extra": "^5.0.0", "jimp": "^0.2.28", "mime": "^2.2.2", diff --git a/specs/lib/ForEachSpec.js b/specs/lib/ForEachSpec.js index 6aaa5196..2baa64c2 100644 --- a/specs/lib/ForEachSpec.js +++ b/specs/lib/ForEachSpec.js @@ -126,33 +126,56 @@ describe('ForEach', function() { ForEach.accessor(gltfAccessors, function(accessor, index) { expect(accessor.bufferView).toBe(index); }); + + var returnValue = ForEach.accessor(gltfAccessors, function(accessor, index) { + if (index === 1) { + return accessor; + } + }); + + expect(returnValue).toBe(gltfAccessors.accessors[1]); }); it('loops over accessor with semantic', function() { var positionAccessorLength = 0; - ForEach.accessorWithSemantic(gltfAccessors, 'POSITION', function(accessorId) { + var returnValue = ForEach.accessorWithSemantic(gltfAccessors, 'POSITION', function(accessorId) { expect(gltfAccessors.accessors[accessorId].bufferView).toBe(accessorId); positionAccessorLength++; + + if (positionAccessorLength === 5) { + return accessorId; + } }); expect(positionAccessorLength).toBe(5); + expect(returnValue).toBe(10); }); it('loops over accessors containing vertex data', function() { var vertexAccessorsLength = 0; - ForEach.accessorContainingVertexAttributeData(gltfAccessors, function(accessorId) { + var returnValue = ForEach.accessorContainingVertexAttributeData(gltfAccessors, function(accessorId) { expect(gltfAccessors.accessors[accessorId].bufferView).toBe(accessorId); vertexAccessorsLength++; + + if (vertexAccessorsLength === 10) { + return accessorId; + } }); expect(vertexAccessorsLength).toBe(10); + expect(returnValue).toBe(11); }); it('loops over accessors containing index data', function() { var indicesAccessorsLength = 0; - ForEach.accessorContainingIndexData(gltfAccessors, function(accessorId) { + var returnValue = ForEach.accessorContainingIndexData(gltfAccessors, function(accessorId) { expect(gltfAccessors.accessors[accessorId].bufferView).toBe(accessorId); indicesAccessorsLength++; + + if (indicesAccessorsLength === 2) { + return accessorId; + } }); expect(indicesAccessorsLength).toBe(2); + expect(returnValue).toBe(1); }); var gltfAnimations = { @@ -206,21 +229,39 @@ describe('ForEach', function() { }; it('loops over animations', function() { - ForEach.animation(gltfAnimations, function(animation, index) { + var returnValue = ForEach.animation(gltfAnimations, function(animation, index) { expect(animation.channels[0].target.node).toBe(index); + + if (index === 1) { + return animation; + } }); + + expect(returnValue).toBe(gltfAnimations.animations[1]); }); it('loops over animation channel', function() { - ForEach.animationChannel(gltfAnimations.animations[0], function(channel, index) { + var returnValue = ForEach.animationChannel(gltfAnimations.animations[0], function(channel, index) { expect(channel.sampler).toBe(index); + + if (index === 1) { + return channel; + } }); + + expect(returnValue).toBe(gltfAnimations.animations[0].channels[1]); }); it('loops over animation samplers', function() { - ForEach.animationSampler(gltfAnimations.animations[0], function(sampler, index) { + var returnValue = ForEach.animationSampler(gltfAnimations.animations[0], function(sampler, index) { expect(sampler.input).toBe(index); + + if (index === 1) { + return sampler; + } }); + + expect(returnValue).toBe(gltfAnimations.animations[0].samplers[1]); }); it('loops over buffers', function() { @@ -236,9 +277,13 @@ describe('ForEach', function() { } ] }; - ForEach.buffer(gltf, function(buffer, index) { + var returnValue = ForEach.buffer(gltf, function(buffer, index) { expect(buffer.uri).toBe(index + '.bin'); + if (index === 1) { + return buffer; + } }); + expect(returnValue).toBe(gltf.buffers[1]); }); it('loops over buffers (gltf 1.0)', function() { @@ -252,9 +297,13 @@ describe('ForEach', function() { } } }; - ForEach.buffer(gltf, function(buffer, name) { + var returnValue = ForEach.buffer(gltf, function(buffer, name) { expect(buffer.uri).toBe(name + '.bin'); + if (name === '1.bin') { + return buffer; + } }); + expect(returnValue).toBe(gltf.buffers[1]); }); it('loops over buffer views', function() { @@ -270,9 +319,13 @@ describe('ForEach', function() { } ] }; - ForEach.bufferView(gltf, function(bufferView, index) { + var returnValue = ForEach.bufferView(gltf, function(bufferView, index) { expect(bufferView.buffer).toBe(index); + if (index === 1) { + return bufferView; + } }); + expect(returnValue).toBe(gltf.bufferViews[1]); }); it('loops over cameras', function() { @@ -292,10 +345,14 @@ describe('ForEach', function() { } ] }; - ForEach.camera(gltf, function(camera, index) { + var returnValue = ForEach.camera(gltf, function(camera, index) { expect(camera.perspective.yfov).toBe(index); expect(camera.perspective.znear).toBe(index); + if (index === 1) { + return camera; + } }); + expect(returnValue).toBe(gltf.cameras[1]); }); it('loops over images', function() { @@ -309,9 +366,13 @@ describe('ForEach', function() { } ] }; - ForEach.image(gltf, function(image, index) { + var returnValue = ForEach.image(gltf, function(image, index) { expect(image.bufferView).toBe(index); + if (index === 1) { + return image; + } }); + expect(returnValue).toBe(gltf.images[1]); }); it('loops over images (gltf 1.0)', function() { @@ -325,9 +386,13 @@ describe('ForEach', function() { } } }; - ForEach.image(gltf, function(image, name) { + var returnValue = ForEach.image(gltf, function(image, name) { expect(image.uri).toBe(name + '.png'); + if (name === 'image1') { + return image; + } }); + expect(returnValue).toBe(gltf.images['image1']); }); it('loops over compressed images', function() { @@ -347,10 +412,13 @@ describe('ForEach', function() { } ] }; - - ForEach.compressedImage(gltf.images[0], function(compressedImage, type) { + var returnValue = ForEach.compressedImage(gltf.images[0], function(compressedImage, type) { expect(compressedImage.uri).toBe(type + '.ktx'); + if (type === 'etc1') { + return compressedImage; + } }); + expect(returnValue).toBe(gltf.images[0].extras.compressedImage3DTiles['etc1']); }); it('loops over materials', function() { @@ -364,9 +432,13 @@ describe('ForEach', function() { } ] }; - ForEach.material(gltf, function(material, index) { + var returnValue = ForEach.material(gltf, function(material, index) { expect(material.emissiveTexture).toBe(index); + if (index === 1) { + return material; + } }); + expect(returnValue).toBe(gltf.materials[1]); }); it('loops over material values', function () { @@ -392,12 +464,16 @@ describe('ForEach', function() { }; var count = 0; - ForEach.materialValue(material, function (value, uniformName) { + var returnValue = ForEach.materialValue(material, function (value, uniformName) { expect(value).toBeDefined(); expect(uniformName.indexOf('u_')).toBe(0); count++; + if (uniformName === 'u_specular') { + return value; + } }); expect(count).toBe(3); + expect(returnValue).toBe(material.extensions.KHR_techniques_webgl.values['u_specular']); }); it('loops over legacy material values', function () { @@ -418,11 +494,15 @@ describe('ForEach', function() { }; var count = 0; - ForEach.materialValue(material, function (value) { + var returnValue = ForEach.materialValue(material, function (value, materialId) { expect(value).toBeDefined(); count++; + if (materialId === 'specular') { + return value; + } }); expect(count).toBe(3); + expect(returnValue).toBe(material.values['specular']); }); it('loops over meshes', function() { @@ -451,9 +531,13 @@ describe('ForEach', function() { ] }; - ForEach.mesh(gltf, function(mesh, index) { + var returnValue = ForEach.mesh(gltf, function(mesh, index) { expect(mesh.primitives[0].attributes.POSITION).toBe(index); + if (index === 1) { + return mesh; + } }); + expect(returnValue).toBe(gltf.meshes[1]); }); var gltfPrimitives = { @@ -479,16 +563,24 @@ describe('ForEach', function() { it('loops over primitives', function() { var mesh = gltfPrimitives.meshes[0]; - ForEach.meshPrimitive(mesh, function(primitive, index) { + var returnValue = ForEach.meshPrimitive(mesh, function(primitive, index) { expect(primitive.attributes.POSITION).toBe(index); + if (index === 1) { + return primitive; + } }); + expect(returnValue).toBe(gltfPrimitives.meshes[0].primitives[1]); }); it('loops over attributes', function() { var primitive = gltfPrimitives.meshes[0].primitives[0]; - ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { + var returnValue = ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { expect(primitive.attributes[semantic]).toBe(accessorId); + if (semantic === 'NORMAL') { + return accessorId; + } }); + expect(returnValue).toBe(gltfPrimitives.meshes[0].primitives[0].attributes['NORMAL']); }); var gltfTargets = { @@ -518,16 +610,24 @@ describe('ForEach', function() { it('loops over targets', function() { var primitive = gltfTargets.meshes[0].primitives[0]; - ForEach.meshPrimitiveTarget(primitive, function(target, index) { + var returnValue = ForEach.meshPrimitiveTarget(primitive, function(target, index) { expect(target.POSITION).toBe(index); + if (index === 1) { + return target; + } }); + expect(returnValue).toBe(gltfTargets.meshes[0].primitives[0].targets[1]); }); it('loops over target attributes', function() { var target = gltfTargets.meshes[0].primitives[0].targets[0]; - ForEach.meshPrimitiveTargetAttribute(target, function(accessorId, semantic) { + var returnValue = ForEach.meshPrimitiveTargetAttribute(target, function(accessorId, semantic) { expect(target[semantic]).toBe(accessorId); + if (semantic === 'NORMAL') { + return accessorId; + } }); + expect(returnValue).toBe(gltfTargets.meshes[0].primitives[0].targets[0]['NORMAL']); }); var gltfNodes = { @@ -565,23 +665,33 @@ describe('ForEach', function() { it('loops over nodes', function() { var nodesLength = 0; - ForEach.node(gltfNodes, function(node, index) { + var returnValue = ForEach.node(gltfNodes, function(node, index) { expect(node.matrix[12]).toBe(index); nodesLength++; + + if (nodesLength === 6) { + return node; + } }); expect(nodesLength).toBe(6); + expect(returnValue).toBe(gltfNodes.nodes[5]); }); it('loops over nodes in tree', function() { var nodesInTree = 0; - ForEach.nodeInTree(gltfNodes, gltfNodes.scenes[0].nodes, function(node, index) { + var returnValue = ForEach.nodeInTree(gltfNodes, gltfNodes.scenes[0].nodes, function(node, index) { expect(node.matrix[12]).toBe(index); nodesInTree++; + + if (nodesInTree === 5) { + return node; + } }); expect(nodesInTree).toBe(5); + expect(returnValue).toBe(gltfNodes.nodes[2]); }); it('loops over nodes in scene', function() { @@ -592,13 +702,18 @@ describe('ForEach', function() { expect(node.matrix[12]).toBe(index); nodesInScene0++; }); - ForEach.nodeInScene(gltfNodes, gltfNodes.scenes[1], function(node, index) { + var returnValue = ForEach.nodeInScene(gltfNodes, gltfNodes.scenes[1], function(node, index) { expect(node.matrix[12]).toBe(index); nodesInScene1++; + + if (nodesInScene1 === 1) { + return node; + } }); expect(nodesInScene0).toBe(5); expect(nodesInScene1).toBe(1); + expect(returnValue).toBe(gltfNodes.nodes[3]); }); it('loops over samplers', function() { @@ -616,11 +731,17 @@ describe('ForEach', function() { ] }; var count = 0; - ForEach.sampler(gltf, function(sampler, index) { + var returnValue = ForEach.sampler(gltf, function(sampler, index) { expect(sampler.magFilter).toBe(filters[index]); expect(sampler.minFilter).toBe(filters[index]); expect(index).toBe(count++); + + if (index === 1) { + return sampler; + } }); + + expect(returnValue).toBe(gltf.samplers[1]); }); it('loops over scenes', function() { @@ -634,9 +755,14 @@ describe('ForEach', function() { } ] }; - ForEach.scene(gltf, function(scene, index) { + var returnValue = ForEach.scene(gltf, function(scene, index) { expect(scene.nodes[0]).toBe(index); + + if (index === 1) { + return scene; + } }); + expect(returnValue).toBe(gltf.scenes[1]); }); it('loops over shaders (gltf 1.0)', function() { @@ -652,9 +778,15 @@ describe('ForEach', function() { } } }; - ForEach.shader(gltf, function(shader, name) { + var returnValue = ForEach.shader(gltf, function(shader, name) { expect(shader.uri).toBe(name + '.glsl'); + + if (name === 'frag') { + return shader; + } }); + + expect(returnValue).toBe(gltf.shaders['frag']); }); it('loops over KHR_techniques_webgl shaders (gltf 2.0)', function () { @@ -679,11 +811,16 @@ describe('ForEach', function() { }; var count = 0; - ForEach.shader(gltf, function (shader) { + var returnValue = ForEach.shader(gltf, function (shader) { expect(shader.uri).toBe(shader.name + '.glsl'); count++; + + if (count === 2) { + return shader; + } }); expect(count).toBe(2); + expect(returnValue).toBe(gltf.extensions.KHR_techniques_webgl.shaders[1]); gltf = {}; @@ -716,12 +853,17 @@ describe('ForEach', function() { }; var count = 0; - ForEach.program(gltf, function (program) { + var returnValue = ForEach.program(gltf, function (program) { expect(program.fragmentShader).toBeDefined(); expect(program.vertexShader).toBeDefined(); count++; + + if (count === 2) { + return program; + } }); expect(count).toBe(2); + expect(returnValue).toBe(gltf.extensions.KHR_techniques_webgl.programs[1]); gltf = {}; @@ -747,12 +889,17 @@ describe('ForEach', function() { }; var count = 0; - ForEach.program(gltf, function (program) { + var returnValue = ForEach.program(gltf, function (program) { expect(program.fragmentShader).toBeDefined(); expect(program.vertexShader).toBeDefined(); count++; + + if (count === 2) { + return program; + } }); expect(count).toBe(2); + expect(returnValue).toBe(gltf.programs['program_1']); }); it('loops over KHR_techniques_webgl techniques (gltf 2.0)', function () { @@ -779,11 +926,16 @@ describe('ForEach', function() { }; var count = 0; - ForEach.technique(gltf, function (technique, index) { + var returnValue = ForEach.technique(gltf, function (technique, index) { expect(technique.name).toBe('technique' + index); count++; + + if (count === 2) { + return technique; + } }); expect(count).toBe(2); + expect(returnValue).toBe(gltf.extensions.KHR_techniques_webgl.techniques[1]); gltf = {}; @@ -811,11 +963,16 @@ describe('ForEach', function() { }; var count = 0; - ForEach.technique(gltf, function (technique) { + var returnValue = ForEach.technique(gltf, function (technique) { expect(technique.program).toBeDefined(); count++; + + if (count === 2) { + return technique; + } }); expect(count).toBe(2); + expect(returnValue).toBe(gltf.techniques['technique1']); }); it('loops over technique attributes', function () { @@ -837,13 +994,18 @@ describe('ForEach', function() { }; var count = 0; - ForEach.techniqueAttribute(technique, function (attribute, attributeName) { + var returnValue = ForEach.techniqueAttribute(technique, function (attribute, attributeName) { expect(attribute.semantic).toBeDefined(); expect(attributeName.indexOf('a_')).toBe(0); count++; + + if (count === 3) { + return attribute; + } }); expect(count).toBe(3); + expect(returnValue).toBe(technique.attributes['a_texcoord0']); }); it('loops over legacy technique attributes', function () { @@ -860,12 +1022,17 @@ describe('ForEach', function() { }; var count = 0; - ForEach.techniqueAttribute(technique, function (parameterName, attributeName) { + var returnValue = ForEach.techniqueAttribute(technique, function (parameterName, attributeName) { expect(parameterName).toBe(attributeName.substring(2)); count++; + + if (count === 3) { + return parameterName; + } }); expect(count).toBe(3); + expect(returnValue).toBe(technique.attributes['a_texcoord0']); }); it('loops over technique uniforms', function () { @@ -889,13 +1056,18 @@ describe('ForEach', function() { }; var count = 0; - ForEach.techniqueUniform(technique, function (uniform, uniformName) { + var returnValue = ForEach.techniqueUniform(technique, function (uniform, uniformName) { expect(uniform.type).toBeDefined(); expect(uniformName.indexOf('u_')).toBe(0); count++; + + if (count === 3) { + return uniform; + } }); expect(count).toBe(3); + expect(returnValue).toBe(technique.uniforms['u_normalMatrix']); }); it('loops over legacy technique uniforms', function () { @@ -912,12 +1084,17 @@ describe('ForEach', function() { }; var count = 0; - ForEach.techniqueUniform(technique, function (parameterName, uniformName) { + var returnValue = ForEach.techniqueUniform(technique, function (parameterName, uniformName) { expect(parameterName).toBe(uniformName.substring(2)); count++; + + if (count === 3) { + return parameterName; + } }); expect(count).toBe(3); + expect(returnValue).toBe(technique.uniforms['u_normalMatrix']); }); it('loops over legacy technique parameters', function () { @@ -942,13 +1119,18 @@ describe('ForEach', function() { }; var count = 0; - ForEach.techniqueParameter(technique, function (parameter, parameterName) { + var returnValue = ForEach.techniqueParameter(technique, function (parameter, parameterName) { expect(parameter.type).toBeDefined(); expect(parameterName).toBeDefined(); count++; + + if (count === 3) { + return parameter; + } }); expect(count).toBe(3); + expect(returnValue).toBe(technique.parameters['normal']); }); it('loops over each skin', function() { @@ -962,9 +1144,14 @@ describe('ForEach', function() { } ] }; - ForEach.skin(gltf, function(skin, index) { + var returnValue = ForEach.skin(gltf, function(skin, index) { expect(skin.joints[0]).toBe(index); + + if (index === 1) { + return skin; + } }); + expect(returnValue).toBe(gltf.skins[1]); }); it('loops over each texture', function() { @@ -978,8 +1165,13 @@ describe('ForEach', function() { } ] }; - ForEach.texture(gltf, function(texture, index) { + var returnValue = ForEach.texture(gltf, function(texture, index) { expect(texture.source).toBe(index); + + if (index === 1) { + return texture; + } }); + expect(returnValue).toBe(gltf.textures[1]); }); }); diff --git a/specs/lib/updateVersionSpec.js b/specs/lib/updateVersionSpec.js index 441f0433..88d85f03 100644 --- a/specs/lib/updateVersionSpec.js +++ b/specs/lib/updateVersionSpec.js @@ -653,8 +653,9 @@ describe('updateVersion', function() { var bufferView = gltf.bufferViews[0]; expect(bufferView.byteLength).toEqual(source.length); - // Min and max are added to all accessors - ForEach.accessor(gltf, function(accessor) { + // Min and max are added to all POSITION accessors + ForEach.accessorWithSemantic(gltf, 'POSITION', function(accessorId) { + var accessor = gltf.accessors[accessorId]; expect(accessor.min.length).toEqual(numberOfComponentsForType(accessor.type)); expect(accessor.max.length).toEqual(numberOfComponentsForType(accessor.type)); });