Skip to content

Commit

Permalink
Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed Jun 8, 2019
1 parent e66fa77 commit 145640e
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 83 deletions.
15 changes: 15 additions & 0 deletions lib/ForEach.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,21 @@ ForEach.skin = function(gltf, handler) {
return ForEach.topLevel(gltf, 'skins', handler);
};

ForEach.skinJoint = function(skin, handler) {
const joints = skin.joints;
if (defined(joints)) {
const jointsLength = joints.length;
for (let i = 0; i < jointsLength; i++) {
const joint = joints[i];
const value = handler(joint);

if (defined(value)) {
return value;
}
}
}
};

ForEach.techniqueAttribute = function(technique, handler) {
const attributes = technique.attributes;
for (const attributeName in attributes) {
Expand Down
4 changes: 3 additions & 1 deletion lib/processGltf.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ function getStages(options) {
stages.push(compressDracoMeshes);
}
if (!options.keepUnusedElements) {
stages.push((gltf, options) => removeUnusedElements(gltf));
stages.push(function(gltf, options) {
removeUnusedElements(gltf);
});
}
return stages;
}
Expand Down
137 changes: 59 additions & 78 deletions lib/removeUnusedElements.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,25 @@ const Cesium = require('cesium');
const ForEach = require('./ForEach');
const hasExtension = require('./hasExtension');

const defaultValue = Cesium.defaultValue;
const defined = Cesium.defined;

module.exports = removeUnusedElements;

const allElementTypes = ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'];

/**
* Removes unused elements from gltf.
* This function currently only works for accessors, buffers, and bufferViews.
*
* @param {Object} gltf A javascript object containing a glTF asset.
* @param {Array<string>} elementTypes Element types to be removed. Needs to be a subset of
* ['node', 'mesh', 'material', 'accessor', 'bufferView', 'buffer'], other items
* will be ignored.
* @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) {
if(elementTypes === undefined) {
elementTypes = ['node', 'mesh', 'material', 'accessor', 'bufferView', 'buffer'];
}
['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'].forEach(function(type) {
if (elementTypes.includes(type)) {
elementTypes = defaultValue(elementTypes, allElementTypes);
allElementTypes.forEach(function(type) {
if (elementTypes.indexOf(type) > -1) {
removeUnusedElementsByType(gltf, type);
}
});
Expand Down Expand Up @@ -156,8 +154,8 @@ Remove.bufferView = function(gltf, bufferViewId) {
});

if (hasExtension(gltf, 'KHR_draco_mesh_compression')) {
ForEach.mesh(gltf, function (mesh) {
ForEach.meshPrimitive(mesh, function (primitive) {
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) {
Expand All @@ -173,13 +171,13 @@ Remove.mesh = function(gltf, meshId) {
const meshes = gltf.meshes;
meshes.splice(meshId, 1);

ForEach.node(gltf, function(n) {
if (defined(n.mesh)) {
if (n.mesh > meshId) {
--n.mesh;
} else if (n.mesh === meshId) {
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 n.mesh;
delete node.mesh;
}
}
});
Expand All @@ -190,42 +188,44 @@ Remove.node = function(gltf, nodeId) {
nodes.splice(nodeId, 1);

// Shift all node references
ForEach.skin(gltf, function(s) {
if (s.skeleton) {
s.skeleton -= s.skeleton > nodeId ? 1 : 0;
ForEach.skin(gltf, function(skin) {
if (defined(skin.skeleton) && skin.skeleton > nodeId) {
skin.skeleton--;
}

s.joints -= s.joints.map(function(x) {
skin.joints = skin.joints.map(function(x) {
return x > nodeId ? x - 1 : x;
});
});
ForEach.animation(gltf, function(animation) {
if(animation.target && animation.target.node) {
animation.target.node -= animation.target.node > nodeId ? 1 : 0;
}
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 -= uniform.node > nodeId ? 1 : 0;
if (defined(uniform.node) && uniform.node > nodeId) {
uniform.node--;
}
});
});
ForEach.node(gltf, function(n) {
if (!n.children) {
ForEach.node(gltf, function(node) {
if (!defined(node.children)) {
return;
}

n.children = n.children
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(s, i) {
s.nodes = s.nodes
ForEach.scene(gltf, function(scene) {
scene.nodes = scene.nodes
.filter(function(x) {
return x !== nodeId; // Remove
})
Expand All @@ -240,13 +240,13 @@ Remove.material = function(gltf, materialId) {
materials.splice(materialId, 1);

// Shift other material ids
ForEach.meshPrimitive(gltf, function(p) {
if (p.material > materialId) {
--p.material;
}
ForEach.mesh(gltf, function(mesh) {
ForEach.meshPrimitive(mesh, function(primitive) {
if (defined(primitive.material) && primitive.material > materialId) {
primitive.material--;
}
});
});

return gltf;
};

/**
Expand Down Expand Up @@ -354,29 +354,20 @@ getListOfElementsIdsInUse.bufferView = function(gltf) {

getListOfElementsIdsInUse.mesh = function(gltf) {
const usedMeshIds = {};
ForEach.mesh(gltf, function(mesh, i) {
if (!defined(mesh.primitives) || mesh.primitives.length === 0) {
usedMeshIds[i] = false;
}
});

ForEach.node(gltf, function(node, i) {
if (!defined(node.mesh)) {
return;
}
// Mesh marked as empty in previous step?
const meshIsEmpty = defined(usedMeshIds[node.mesh]);

if (!meshIsEmpty) {
usedMeshIds[node.mesh] = true;
ForEach.node(gltf, function(node) {
if (defined(node.mesh && defined(gltf.meshes))) {
const 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 */
// 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)
Expand All @@ -398,19 +389,21 @@ getListOfElementsIdsInUse.node = function(gltf) {
usedNodeIds[nodeId] = true;
}
});
ForEach.skin(gltf, function(s) {
if (s.skeleton) {
usedNodeIds[s.skeleton] = true;
ForEach.skin(gltf, function(skin) {
if (defined(skin.skeleton)) {
usedNodeIds[skin.skeleton] = true;
}

ForEach.joint(s, function(j) {
usedNodeIds[j] = true;
ForEach.skinJoint(skin, function(joint) {
usedNodeIds[joint] = true;
});
});
ForEach.animation(gltf, function(animation) {
if(animation.target && animation.target.node) {
usedNodeIds[animation.target.node] = true;
}
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) {
Expand All @@ -420,29 +413,17 @@ getListOfElementsIdsInUse.node = function(gltf) {
});
});

ForEach.animation(gltf, function(anim, animId) {
if (!defined(anim.channels)) {
return;
}

anim.channels.forEach(function(c) {
if (defined(c.target) && defined(c.target.node)) {
/* Keep all nodes that are being targeted
* by an animation */
usedNodeIds[c.target.node] = true;
}
});
});

return usedNodeIds;
};

getListOfElementsIdsInUse.material = function(gltf) {
const usedMaterialIds = {};

ForEach.mesh(gltf, function(mesh) {
ForEach.meshPrimitive(mesh, function(p) {
usedMaterialIds[p.material] = true;
ForEach.meshPrimitive(mesh, function(primitive) {
if (defined(primitive.material)) {
usedMaterialIds[primitive.material] = true;
}
});
});

Expand Down
8 changes: 4 additions & 4 deletions specs/lib/removeUnusedElementsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,13 +379,13 @@ describe('removeUnusedElements', () => {
expect(Object.keys(gltf)).toContain(k);
expect(gltf[k].length).toBe(remaining[k].length);

/* Check that at least the remaining elements are present */
ForEach.topLevel(gltf, k, (element, index) => {
// Check that at least the remaining elements are present
ForEach.topLevel(gltf, k, (element) => {
expect(remaining[k]).toContain(element.name);
});

/* Check that all the elements should actually remain */
remaining[k].forEach((name, index) => {
// Check that all the elements should actually remain
remaining[k].forEach((name) => {
expect(gltf[k].map(x => x.name)).toContain(name);
});
});
Expand Down

0 comments on commit 145640e

Please sign in to comment.