Skip to content

Commit

Permalink
Merge pull request #167 from AnalyticalGraphicsInc/uint32-indices
Browse files Browse the repository at this point in the history
Added utility for changing accessor componentType
  • Loading branch information
lilleyse authored Sep 1, 2016
2 parents 2defe2d + e4104c9 commit 65ea22a
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 7 deletions.
89 changes: 89 additions & 0 deletions lib/changeAccessorComponentType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use strict';
var Cesium = require('cesium');

var AccessorReader = require('./AccessorReader');
var byteLengthForComponentType = require('./byteLengthForComponentType');
var getUniqueId = require('./getUniqueId');
var numberOfComponentsForType = require('./numberOfComponentsForType');
var writeBufferComponent = require('./writeBufferComponent');

var defined = Cesium.defined;

module.exports = changeAccessorComponentType;

/**
* Changes the component type of a specified accessor.
* If the new component type is smaller than the old one, it will be written in place on the buffer.
* If it is larger, a new buffer will be created and written.
*
* The data is copied as-is, so it must be within the bounds of the target data type.
*
* The glTF asset must be initialized for the pipeline.
*
* @param {Object} gltf A javascript object containing a glTF asset.
* @param {Object} accessor A glTF accessor to be changed.
* @param {Integer} newComponentType The componentType to change to from WebGLConstants.
* @returns {Object} The glTF with the accessor's componentType changed.
*
* @see addPipelineExtras
* @see loadGltfUris
*/
function changeAccessorComponentType(gltf, accessor, newComponentType) {
var componentType = accessor.componentType;
if (componentType !== newComponentType) {
var bufferViews = gltf.bufferViews;
var buffers = gltf.buffers;
var bufferViewId = accessor.bufferView;
var bufferView = bufferViews[bufferViewId];
var bufferId = bufferView.buffer;
var buffer = buffers[bufferId];
var componentByteLength = byteLengthForComponentType(componentType);
var newComponentByteLength = byteLengthForComponentType(newComponentType);
var numberOfComponents = numberOfComponentsForType(accessor.type);
var writeBuffer;
if (newComponentByteLength > componentByteLength) {
writeBuffer = new Buffer(accessor.count * numberOfComponents * newComponentByteLength);
}
var accessorReader = new AccessorReader(gltf, accessor);
var components = [];
while (accessorReader.hasNext()) {
accessorReader.read(components);
if (defined(writeBuffer)) {
for (var i = 0; i < numberOfComponents; i++) {
writeBufferComponent(writeBuffer, newComponentType, components[i], accessorReader.index * newComponentByteLength * numberOfComponents + i * newComponentByteLength);
}
} else {
accessorReader.write(components, newComponentType);
}
accessorReader.next();
}
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] = {
byteLength: writeBuffer.length,
type: buffer.type,
extras: {
_pipeline: {
source: writeBuffer
}
}
};
}
}
return gltf;
}
9 changes: 2 additions & 7 deletions lib/compressIntegerAccessors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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');
Expand Down Expand Up @@ -80,13 +81,7 @@ function compressIntegerAccessor(gltf, primitive, accessorId, matchedSemantic) {
if (bufferView.target === WebGLConstants.ARRAY_BUFFER) {
var newComponentType = canCompressAccessor(gltf, accessorReader);
if (defined(newComponentType)) {
accessorReader.reset();
var components = [];
while (defined(accessorReader.read(components))) {
accessorReader.write(components, newComponentType);
accessorReader.next();
}
accessor.componentType = newComponentType;
changeAccessorComponentType(gltf, accessor, newComponentType);
}
}
}
Expand Down
156 changes: 156 additions & 0 deletions specs/lib/changeAccessorComponentTypeSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
'use strict';
var Cesium = require('cesium');
var AccessorReader = require('../../lib/AccessorReader');
var changeAccessorComponentType = require('../../lib/changeAccessorComponentType');

var WebGLConstants = Cesium.WebGLConstants;

describe('changeAccessorComponentType', function() {
it('does nothing if the accessor is already the target componentType', function() {
var gltf = {
accessors : {
accessor : {
componentType: WebGLConstants.FLOAT
}
}
};
var accessor = gltf.accessors.accessor;
changeAccessorComponentType(gltf, accessor, WebGLConstants.FLOAT);
expect(accessor.componentType).toBe(WebGLConstants.FLOAT);
});

it('overwrites the existing data if the target component type is smaller', function() {
var data = new Uint16Array([0, 1, 2, 3, 4, 5]);
var dataBuffer = new Buffer(data.buffer);
var gltf = {
accessors : {
accessor : {
bufferView : 'bufferView',
byteOffset : 0,
byteStride : 0,
componentType : WebGLConstants.UNSIGNED_SHORT,
count : data.length,
type : "SCALAR"
}
},
bufferViews : {
bufferView : {
buffer : 'buffer',
byteLength : dataBuffer.length,
byteOffset : 0
}
},
buffers : {
buffer : {
byteLength: dataBuffer.length,
extras: {
_pipeline: {
source: dataBuffer
}
}
}
}
};
var accessor = gltf.accessors.accessor;
changeAccessorComponentType(gltf, accessor, WebGLConstants.UNSIGNED_BYTE);
expect(accessor.componentType).toBe(WebGLConstants.UNSIGNED_BYTE);
expect(Object.keys(gltf.buffers).length).toBe(1);
var accessorReader = new AccessorReader(gltf, accessor);
var components = [];
while (accessorReader.hasNext()) {
accessorReader.read(components);
expect(components[0]).toBe(accessorReader.index);
accessorReader.next();
}
});

it('overwrites the existing data if the target component type is the same size', function() {
var data = new Float32Array([0, 1, 2, 3, 4, 5]);
var dataBuffer = new Buffer(data.buffer);
var gltf = {
accessors : {
accessor : {
bufferView : 'bufferView',
byteOffset : 0,
byteStride : 0,
componentType : WebGLConstants.FLOAT,
count : data.length,
type : "SCALAR"
}
},
bufferViews : {
bufferView : {
buffer : 'buffer',
byteLength : dataBuffer.length,
byteOffset : 0
}
},
buffers : {
buffer : {
byteLength: dataBuffer.length,
extras: {
_pipeline: {
source: dataBuffer
}
}
}
}
};
var accessor = gltf.accessors.accessor;
changeAccessorComponentType(gltf, accessor, WebGLConstants.UNSIGNED_INT);
expect(accessor.componentType).toBe(WebGLConstants.UNSIGNED_INT);
expect(Object.keys(gltf.buffers).length).toBe(1);
var accessorReader = new AccessorReader(gltf, accessor);
var components = [];
while (accessorReader.hasNext()) {
accessorReader.read(components);
expect(components[0]).toBe(accessorReader.index);
accessorReader.next();
}
});

it('creates a new buffer if the target component type is larger', function() {
var data = new Uint16Array([0, 1, 2, 3, 4, 5]);
var dataBuffer = new Buffer(data.buffer);
var gltf = {
accessors : {
accessor : {
bufferView : 'bufferView',
byteOffset : 0,
byteStride : 0,
componentType : WebGLConstants.UNSIGNED_SHORT,
count : data.length,
type : "SCALAR"
}
},
bufferViews : {
bufferView : {
buffer : 'buffer',
byteLength : dataBuffer.length,
byteOffset : 0
}
},
buffers : {
buffer : {
byteLength: dataBuffer.length,
extras: {
_pipeline: {
source: dataBuffer
}
}
}
}
};
var accessor = gltf.accessors.accessor;
changeAccessorComponentType(gltf, accessor, WebGLConstants.UNSIGNED_INT);
expect(accessor.componentType).toBe(WebGLConstants.UNSIGNED_INT);
expect(Object.keys(gltf.buffers).length).toBe(2);
var accessorReader = new AccessorReader(gltf, accessor);
var components = [];
while (accessorReader.hasNext()) {
accessorReader.read(components);
expect(components[0]).toBe(accessorReader.index);
accessorReader.next();
}
});
});

0 comments on commit 65ea22a

Please sign in to comment.