Skip to content

Commit

Permalink
Cleanup draco model loading
Browse files Browse the repository at this point in the history
  • Loading branch information
ggetz committed Mar 7, 2018
1 parent a727dc6 commit 395f0c7
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 36 deletions.
67 changes: 38 additions & 29 deletions Source/Scene/Model.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
define([
'../Core/arraySlice',
'../Core/BoundingSphere',
'../Core/Cartesian2',
'../Core/Cartesian3',
Expand Down Expand Up @@ -77,6 +78,7 @@ define([
'./SceneMode',
'./ShadowMode'
], function(
arraySlice,
BoundingSphere,
Cartesian2,
Cartesian3,
Expand Down Expand Up @@ -1308,10 +1310,14 @@ define([

///////////////////////////////////////////////////////////////////////////

function getFailedLoadFunction(model, type, path) {
return function() {
function getFailedLoadFunction(model, type, path, message) {
return function(error) {
model._state = ModelState.FAILED;
model._readyPromise.reject(new RuntimeError('Failed to load ' + type + ': ' + path));
var message = 'Failed to load ' + type + ': ' + path;
if (defined(error)) {
message += '\n' + error.message;
}
model._readyPromise.reject(new RuntimeError(message));
};
}

Expand Down Expand Up @@ -4105,6 +4111,25 @@ define([
};
}

function scheduleDecodingTask (decoderTaskProcessor, model, loadResources, context) {
var taskData = loadResources.primitivesToDecode.peek();
if (!defined(taskData)) {
// All primitives are processing
return;
}

var promise = decoderTaskProcessor.scheduleTask(taskData, [taskData.array.buffer]);
if (!defined(promise)) {
// Cannot schedule another task this frame
return;
}

loadResources.finishedDecoding = false;
loadResources.primitivesToDecode.dequeue();
return promise.then(addDecodededBuffers(taskData, model, context))
.otherwise(getFailedLoadFunction(model, 'model', model.basePath));
}

function parseDraco(model, context) {
if (!defined(model.extensionsRequired['KHR_draco_mesh_compression'])
|| !defined(model.extensionsUsed['KHR_draco_mesh_compression'])) {
Expand Down Expand Up @@ -4133,14 +4158,13 @@ define([
}

var bufferView = gltf.bufferViews[compressionData.bufferView];
var rawBuffer = gltf.buffers[bufferView.buffer];
var data = rawBuffer.extras._pipeline.source;
data = data.slice(0, data.length);
var typedArray = gltf.buffers[bufferView.buffer].extras._pipeline.source;
typedArray = arraySlice(typedArray, bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength);

loadResources.primitivesToDecode.enqueue({
mesh : meshId,
primitive : primitiveId,
array : data,
array : typedArray,
bufferView : bufferView,
compressedAttributes : compressionData.attributes
});
Expand All @@ -4149,38 +4173,23 @@ define([
}

var decoderTaskProcessor = Model._getDecoderTaskProcessor();
var taskData = loadResources.primitivesToDecode.peek();
var decodingPromises = [];
var promise;

if (defined(taskData)) {
promise = decoderTaskProcessor.scheduleTask(taskData, [taskData.array.buffer]);
}

var promise = scheduleDecodingTask(decoderTaskProcessor, model, loadResources, context);
while (defined(promise)) {
loadResources.finishedDecoding = false;
loadResources.primitivesToDecode.dequeue();
var decodedPromise = promise.then(addDecodededBuffers(taskData, model, context))
.otherwise(function (error) {
model._state = ModelState.FAILED;
model._readyPromise.reject(new RuntimeError('Failed to load model: ' + model.basePath + '\n' + error.message));
});

decodingPromises.push(decodedPromise);

promise = undefined;
taskData = loadResources.primitivesToDecode.peek();
if (defined(taskData)) {
promise = decoderTaskProcessor.scheduleTask(taskData, [taskData.array.buffer]);
}
decodingPromises.push(promise);
promise = scheduleDecodingTask(decoderTaskProcessor, model, loadResources, context);
}

when.all(decodingPromises).then(function () {
loadResources.finishedDecoding = true;
});
}

Model._maxDecodingConcurrency = Math.max(FeatureDetection.hardwareConcurrency - 1, 1); // Maximum concurrency to use wehn deocding draco models
// Maximum concurrency to use when deocding draco models
Model._maxDecodingConcurrency = Math.max(FeatureDetection.hardwareConcurrency - 1, 1);

// Exposed for testing purposes
Model._decoderTaskProcessor = undefined;
Model._getDecoderTaskProcessor = function () {
if (!defined(Model._decoderTaskProcessor)) {
Expand Down
11 changes: 4 additions & 7 deletions Source/Workers/decodeDraco.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
define([
'../Core/arraySlice',
'../Core/ComponentDatatype',
'../Core/defined',
'../Core/IndexDatatype',
'../Core/RuntimeError',
'../ThirdParty/draco-decoder-gltf',
'./createTaskProcessorWorker'
], function(
arraySlice,
ComponentDatatype,
defined,
IndexDatatype,
Expand Down Expand Up @@ -60,7 +58,8 @@ define([
dracoDecoder.GetAttributeFloatForAllPoints(dracoGeometry, attribute, attributeData);
}

for (var i = 0; i < vertexArray.length; ++i) {
var vertexArrayLength = vertexArray.length;
for (var i = 0; i < vertexArrayLength; ++i) {
vertexArray[i] = attributeData.GetValue(i);
}

Expand All @@ -82,16 +81,14 @@ define([
return decodedAttributeData;
}

function decodeDracoPrimitive(parameters, transferableObjects) {
function decodeDracoPrimitive(parameters) {
if (!defined(dracoDecoder)) {
dracoDecoder = new draco.Decoder();
}

var bufferView = parameters.bufferView;
var typedArray = arraySlice(parameters.array, bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength);

var buffer = new draco.DecoderBuffer();
buffer.Init(typedArray, bufferView.byteLength);
buffer.Init(parameters.array, bufferView.byteLength);

var geometryType = dracoDecoder.GetEncodedGeometryType(buffer);
if (geometryType !== draco.TRIANGULAR_MESH) {
Expand Down

0 comments on commit 395f0c7

Please sign in to comment.