123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 |
- import ForEach from './ForEach.js'
- import hasExtension from './hasExtension.js'
- import defaultValue from '../../Core/defaultValue.js'
- import defined from '../../Core/defined.js'
- var allElementTypes = ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'];
- /**
- * Removes unused elements from gltf.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {String[]} [elementTypes=['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer']] Element types to be removed. Needs to be a subset of ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'], other items will be ignored.
- *
- * @private
- */
- function removeUnusedElements(gltf, elementTypes) {
- elementTypes = defaultValue(elementTypes, allElementTypes);
- allElementTypes.forEach(function(type) {
- if (elementTypes.indexOf(type) > -1) {
- removeUnusedElementsByType(gltf, type);
- }
- });
- return gltf;
- }
- var TypeToGltfElementName = {
- accessor: 'accessors',
- buffer: 'buffers',
- bufferView: 'bufferViews',
- node: 'nodes',
- material: 'materials',
- mesh: 'meshes'
- };
- function removeUnusedElementsByType(gltf, type) {
- var name = TypeToGltfElementName[type];
- var arrayOfObjects = gltf[name];
- if (defined(arrayOfObjects)) {
- var removed = 0;
- var usedIds = getListOfElementsIdsInUse[type](gltf);
- var length = arrayOfObjects.length;
- for (var i = 0; i < length; ++i) {
- if (!usedIds[i]) {
- Remove[type](gltf, i - removed);
- removed++;
- }
- }
- }
- }
- /**
- * 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
- *
- * @private
- */
- function Remove() {}
- Remove.accessor = function(gltf, accessorId) {
- var accessors = gltf.accessors;
- accessors.splice(accessorId, 1);
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- // Update accessor ids for the primitives.
- ForEach.meshPrimitiveAttribute(primitive, function(attributeAccessorId, semantic) {
- if (attributeAccessorId > accessorId) {
- primitive.attributes[semantic]--;
- }
- });
- // Update accessor ids for the targets.
- ForEach.meshPrimitiveTarget(primitive, function(target) {
- ForEach.meshPrimitiveTargetAttribute(target, function(attributeAccessorId, semantic) {
- if (attributeAccessorId > accessorId) {
- target[semantic]--;
- }
- });
- });
- var indices = primitive.indices;
- if (defined(indices) && indices > accessorId) {
- primitive.indices--;
- }
- });
- });
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.inverseBindMatrices) && skin.inverseBindMatrices > accessorId) {
- skin.inverseBindMatrices--;
- }
- });
- ForEach.animation(gltf, function(animation) {
- ForEach.animationSampler(animation, function(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);
- ForEach.bufferView(gltf, function(bufferView) {
- if (defined(bufferView.buffer) && bufferView.buffer > bufferId) {
- bufferView.buffer--;
- }
- });
- };
- Remove.bufferView = function(gltf, bufferViewId) {
- var bufferViews = gltf.bufferViews;
- bufferViews.splice(bufferViewId, 1);
- ForEach.accessor(gltf, function(accessor) {
- if (defined(accessor.bufferView) && accessor.bufferView > bufferViewId) {
- accessor.bufferView--;
- }
- });
- ForEach.shader(gltf, function(shader) {
- if (defined(shader.bufferView) && shader.bufferView > bufferViewId) {
- shader.bufferView--;
- }
- });
- ForEach.image(gltf, function(image) {
- if (defined(image.bufferView) && image.bufferView > bufferViewId) {
- image.bufferView--;
- }
- ForEach.compressedImage(image, function(compressedImage) {
- var compressedImageBufferView = compressedImage.bufferView;
- if (defined(compressedImageBufferView) && compressedImageBufferView > bufferViewId) {
- compressedImage.bufferView--;
- }
- });
- });
- if (hasExtension(gltf, 'KHR_draco_mesh_compression')) {
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.extensions) &&
- defined(primitive.extensions.KHR_draco_mesh_compression)) {
- if (primitive.extensions.KHR_draco_mesh_compression.bufferView > bufferViewId) {
- primitive.extensions.KHR_draco_mesh_compression.bufferView--;
- }
- }
- });
- });
- }
- };
- Remove.mesh = function(gltf, meshId) {
- var meshes = gltf.meshes;
- meshes.splice(meshId, 1);
- ForEach.node(gltf, function(node) {
- if (defined(node.mesh)) {
- if (node.mesh > meshId) {
- node.mesh--;
- } else if (node.mesh === meshId) {
- // Remove reference to deleted mesh
- delete node.mesh;
- }
- }
- });
- };
- Remove.node = function(gltf, nodeId) {
- var nodes = gltf.nodes;
- nodes.splice(nodeId, 1);
- // Shift all node references
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.skeleton) && skin.skeleton > nodeId) {
- skin.skeleton--;
- }
- skin.joints = skin.joints.map(function(x) {
- return x > nodeId ? x - 1 : x;
- });
- });
- ForEach.animation(gltf, function(animation) {
- ForEach.animationChannel(animation, function(channel) {
- if (defined(channel.target) && defined(channel.target.node) && (channel.target.node > nodeId)) {
- channel.target.node--;
- }
- });
- });
- ForEach.technique(gltf, function(technique) {
- ForEach.techniqueUniform(technique, function(uniform) {
- if (defined(uniform.node) && uniform.node > nodeId) {
- uniform.node--;
- }
- });
- });
- ForEach.node(gltf, function(node) {
- if (!defined(node.children)) {
- return;
- }
- node.children = node.children
- .filter(function(x) {
- return x !== nodeId; // Remove
- })
- .map(function(x) {
- return x > nodeId ? x - 1 : x; // Shift indices
- });
- });
- ForEach.scene(gltf, function(scene) {
- scene.nodes = scene.nodes
- .filter(function(x) {
- return x !== nodeId; // Remove
- })
- .map(function(x) {
- return x > nodeId ? x - 1 : x; // Shift indices
- });
- });
- };
- Remove.material = function(gltf, materialId) {
- var materials = gltf.materials;
- materials.splice(materialId, 1);
- // Shift other material ids
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.material) && primitive.material > materialId) {
- primitive.material--;
- }
- });
- });
- };
- /**
- * Contains functions for getting a list of element ids in use by the glTF asset.
- * @constructor
- *
- * @private
- */
- function getListOfElementsIdsInUse() {}
- getListOfElementsIdsInUse.accessor = function(gltf) {
- // Calculate accessor's that are currently in use.
- var usedAccessorIds = {};
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- ForEach.meshPrimitiveAttribute(primitive, function(accessorId) {
- usedAccessorIds[accessorId] = true;
- });
- ForEach.meshPrimitiveTarget(primitive, function(target) {
- ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) {
- usedAccessorIds[accessorId] = true;
- });
- });
- var indices = primitive.indices;
- if (defined(indices)) {
- usedAccessorIds[indices] = true;
- }
- });
- });
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.inverseBindMatrices)) {
- usedAccessorIds[skin.inverseBindMatrices] = true;
- }
- });
- ForEach.animation(gltf, function(animation) {
- ForEach.animationSampler(animation, function(sampler) {
- if (defined(sampler.input)) {
- usedAccessorIds[sampler.input] = true;
- }
- if (defined(sampler.output)) {
- usedAccessorIds[sampler.output] = true;
- }
- });
- });
- return usedAccessorIds;
- };
- getListOfElementsIdsInUse.buffer = function(gltf) {
- // Calculate buffer's that are currently in use.
- var usedBufferIds = {};
- ForEach.bufferView(gltf, function(bufferView) {
- if (defined(bufferView.buffer)) {
- usedBufferIds[bufferView.buffer] = true;
- }
- });
- return usedBufferIds;
- };
- getListOfElementsIdsInUse.bufferView = function(gltf) {
- // Calculate bufferView's that are currently in use.
- var usedBufferViewIds = {};
- ForEach.accessor(gltf, function(accessor) {
- if (defined(accessor.bufferView)) {
- usedBufferViewIds[accessor.bufferView] = true;
- }
- });
- ForEach.shader(gltf, function(shader) {
- if (defined(shader.bufferView)) {
- usedBufferViewIds[shader.bufferView] = true;
- }
- });
- ForEach.image(gltf, function(image) {
- if (defined(image.bufferView)) {
- usedBufferViewIds[image.bufferView] = true;
- }
- ForEach.compressedImage(image, function(compressedImage) {
- if (defined(compressedImage.bufferView)) {
- usedBufferViewIds[compressedImage.bufferView] = true;
- }
- });
- });
- if (hasExtension(gltf, 'KHR_draco_mesh_compression')) {
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.extensions) &&
- defined(primitive.extensions.KHR_draco_mesh_compression)) {
- usedBufferViewIds[primitive.extensions.KHR_draco_mesh_compression.bufferView] = true;
- }
- });
- });
- }
- return usedBufferViewIds;
- };
- getListOfElementsIdsInUse.mesh = function(gltf) {
- var usedMeshIds = {};
- ForEach.node(gltf, function(node) {
- if (defined(node.mesh && defined(gltf.meshes))) {
- var mesh = gltf.meshes[node.mesh];
- if (defined(mesh) && defined(mesh.primitives) && (mesh.primitives.length > 0)) {
- usedMeshIds[node.mesh] = true;
- }
- }
- });
- return usedMeshIds;
- };
- // Check if node is empty. It is considered empty if neither referencing
- // mesh, camera, extensions and has no children
- function nodeIsEmpty(gltf, node) {
- if (defined(node.mesh) || defined(node.camera) || defined(node.skin)
- || defined(node.weights) || defined(node.extras)
- || (defined(node.extensions) && node.extensions.length !== 0)) {
- return false;
- }
- // Empty if no children or children are all empty nodes
- return !defined(node.children)
- || node.children.filter(function(n) {
- return !nodeIsEmpty(gltf, gltf.nodes[n]);
- }).length === 0;
- }
- getListOfElementsIdsInUse.node = function(gltf) {
- var usedNodeIds = {};
- ForEach.node(gltf, function(node, nodeId) {
- if (!nodeIsEmpty(gltf, node)) {
- usedNodeIds[nodeId] = true;
- }
- });
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.skeleton)) {
- usedNodeIds[skin.skeleton] = true;
- }
- ForEach.skinJoint(skin, function(joint) {
- usedNodeIds[joint] = true;
- });
- });
- ForEach.animation(gltf, function(animation) {
- ForEach.animationChannel(animation, function(channel) {
- if (defined(channel.target) && defined(channel.target.node)) {
- usedNodeIds[channel.target.node] = true;
- }
- });
- });
- ForEach.technique(gltf, function(technique) {
- ForEach.techniqueUniform(technique, function(uniform) {
- if (defined(uniform.node)) {
- usedNodeIds[uniform.node] = true;
- }
- });
- });
- return usedNodeIds;
- };
- getListOfElementsIdsInUse.material = function(gltf) {
- var usedMaterialIds = {};
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.material)) {
- usedMaterialIds[primitive.material] = true;
- }
- });
- });
- return usedMaterialIds;
- };
- export default removeUnusedElements;
|