diff --git a/src/framework/parsers/draco-decoder.js b/src/framework/parsers/draco-decoder.js index c456c4b329a..72c1f96b96f 100644 --- a/src/framework/parsers/draco-decoder.js +++ b/src/framework/parsers/draco-decoder.js @@ -34,7 +34,8 @@ class JobQueue { if (callback) { callback(data.error, { indices: data.indices, - vertices: data.vertices + vertices: data.vertices, + attributes: data.attributes }); } this.jobCallbacks.delete(data.jobId); diff --git a/src/framework/parsers/draco-worker.js b/src/framework/parsers/draco-worker.js index 7bde4daad66..12c7867881d 100644 --- a/src/framework/parsers/draco-worker.js +++ b/src/framework/parsers/draco-worker.js @@ -158,6 +158,9 @@ function DracoWorker(jsUrl, wasmUrl) { return (attributeOrder[a.attribute_type()] ?? attributeOrder.length) - (attributeOrder[b.attribute_type()] ?? attributeOrder.length); }); + // store attribute order by unique_id + result.attributes = attributes.map(a => a.unique_id()); + // calculate total vertex size and attribute offsets let totalVertexSize = 0; const offsets = attributes.map((a) => { @@ -226,7 +229,8 @@ function DracoWorker(jsUrl, wasmUrl) { jobId: data.jobId, error: result.error, indices: result.indices, - vertices: result.vertices + vertices: result.vertices, + attributes: result.attributes }, [result.indices, result.vertices].filter(t => t != null)); }; diff --git a/src/framework/parsers/glb-parser.js b/src/framework/parsers/glb-parser.js index 1807fcdf634..bdb208796a9 100644 --- a/src/framework/parsers/glb-parser.js +++ b/src/framework/parsers/glb-parser.js @@ -704,13 +704,6 @@ const createDracoMesh = (device, primitive, accessors, bufferViews, meshVariants }); } - // sort vertex elements by engine-ideal order - vertexDesc.sort((lhs, rhs) => { - return attributeOrder[lhs.semantic] - attributeOrder[rhs.semantic]; - }); - - const vertexFormat = new VertexFormat(device, vertexDesc); - promises.push(new Promise((resolve, reject) => { // decode draco data const dracoExt = primitive.extensions.KHR_draco_mesh_compression; @@ -719,6 +712,19 @@ const createDracoMesh = (device, primitive, accessors, bufferViews, meshVariants console.log(err); reject(err); } else { + // worker reports order of attributes as array of attribute unique_id + const order = { }; + for (const [name, index] of Object.entries(dracoExt.attributes)) { + order[gltfToEngineSemanticMap[name]] = decompressedData.attributes.indexOf(index); + } + + // order vertexDesc + vertexDesc.sort((a, b) => { + return order[a.semantic] - order[b.semantic]; + }); + + const vertexFormat = new VertexFormat(device, vertexDesc); + // create vertex buffer const numVertices = decompressedData.vertices.byteLength / vertexFormat.size; const indexFormat = numVertices <= 65535 ? INDEXFORMAT_UINT16 : INDEXFORMAT_UINT32;