-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdraco.js
More file actions
126 lines (106 loc) · 3.03 KB
/
Copy pathdraco.js
File metadata and controls
126 lines (106 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { loadArrayBuffer } from "pex-io";
import WorkerPool from "./worker-pool.js";
let workerPool;
// Decoder API
let transcoderPending;
const getWorkerStringUrl = (transcoder, worker) => {
const str = `
${transcoder}
${worker}
DracoWorker()
`;
return URL.createObjectURL(new Blob([str]));
};
// TODO: draco_decoder.js only
const getTranscoder = async (transcoderPath) =>
transcoderPending ||
Promise.all([
getWorkerStringUrl(
await (await fetch(`${transcoderPath}draco_wasm_wrapper.js`)).text(),
await (await (await fetch(`${transcoderPath}draco-worker.js`)).text())
.replace("module.exports = DracoWorker", "")
.replace("export default DracoWorker;", ""),
// DracoWorker.toString()
),
await (await fetch(`${transcoderPath}draco_decoder.wasm`)).arrayBuffer(),
]);
function loadGeometry(buffer, taskConfig) {
const taskKey = JSON.stringify(taskConfig);
const cachedTask = workerPool.hasTask(taskKey, buffer);
if (cachedTask) return cachedTask;
let worker;
let taskId;
const geometryPending = workerPool
.getWorker(transcoderPending, buffer.byteLength)
.then((workerData) => {
({ worker, taskId } = workerData);
return new Promise((resolve, reject) => {
worker._callbacks[taskId] = { resolve, reject };
worker.postMessage({ type: "decode", id: taskId, taskConfig, buffer }, [
buffer,
]);
});
})
.then(({ geometry }) => geometry);
// Remove task from the task list.
geometryPending
.catch(() => true)
.then(() => {
if (worker && taskId) {
workerPool.releaseTask(worker, taskId);
}
});
// Cache the task result.
workerPool.taskCache.set(buffer, {
key: taskKey,
promise: geometryPending,
});
return geometryPending;
}
/**
* @typedef DracoOptions
* @property {string} [transcoderPath='assets/decoders/draco/']
* @property {object} [transcodeConfig={}]
* @property {number} [workerLimit=4]
* @property {object} [workerConfig={}]
*/
/**
* Load a draco file or array buffer as a texture
* @alias module:pex-loaders.loadDraco
* @param {string | ArrayBuffer} urlOrArrayBuffer
* @param {DracoOptions} [options]
* @returns {Promise<object>}
*/
async function loadDraco(
urlOrArrayBuffer,
{
transcoderPath = "assets/decoders/draco/",
transcodeConfig = {
attributeIDs: {
positions: "POSITION",
normals: "NORMAL",
texCoords: "TEX_COORD",
colors: "COLOR",
},
attributeTypes: {
positions: "Float32Array",
normals: "Float32Array",
texCoords: "Float32Array",
colors: "Float32Array",
},
useUniqueIDs: false,
},
workerLimit,
workerConfig,
} = {},
) {
if (!workerPool) workerPool = new WorkerPool(workerLimit, workerConfig);
transcoderPending = getTranscoder(transcoderPath);
return await loadGeometry(
urlOrArrayBuffer instanceof ArrayBuffer
? urlOrArrayBuffer
: await loadArrayBuffer(urlOrArrayBuffer),
transcodeConfig,
);
}
export default loadDraco;