之前一直想研究一下web Workers多线程处理,页面中使用web Workers大家可以转弯去web Workers多线程看一下如何使用。
这篇文章主要实现的是Three.js和web Workers一次简单的结合。本来想实现通过web Workers实现加载的,可惜Three.js使用了过多的window方法,而web Workers线程内是无法获取到window对象,所以,这次实现案例就写的是在web Workers里面更新当前场景内所有立方体的位置信息的方法。
虽然这次的案例比较简单,只是开篇的,后期我们可以将运算工作量很大的代码放到多线程内,主线程的交互不受影响,web Workers只要将计算得出的结果返回主线程即可。
小姐姐模型是页面正常的案例
在模型加载完成时,将创建一个web Workers线程,在worker线程内处理周围立方体的位置。
主要不同的代码就是预创建了一个供worker处理的数组:
//生成一千个立方体
let group = new THREE.Group();
let arr = []; //生成一个速度的数组
for(let i=0; i<1000; i++){
group.add(randomCube());
arr.push({
speed:Math.random(),
y:-3
});
}
scene.add(group);
和在模型加载成功后,我们创建worker对象:
//创建gltf加载器
var loader = new THREE.GLTFLoader();
loader.load('marie/scene.gltf', function (gltf) {
console.log(gltf);
gltf.scene.scale.set(.1, .1, .1);
gltf.scene.traverse(function (child) {
if (child.isMesh) {
child.frustumCulled = false;
child.castShadow = true;
}
});
scene.add(gltf.scene);
var obj = gltf.scene; //获取到模型对象
meshHelper = new THREE.SkeletonHelper(obj);
//scene.add(meshHelper);
mixer = new THREE.AnimationMixer(obj);
action = mixer.clipAction(gltf.animations[0]);
action.play();
//在模型加载完成后,链接worker线程
myWorker.postMessage(arr);
myWorker.onmessage = function (e) {
for(let i=0; i<e.data.length; i++){
group.children[i].position.y = e.data[i].y;
}
}
});
然后worker对象在接收到处理好的y轴坐标信息,再将每个立方体的位置修改一下。
接下来就是worker线程内的逻辑运算,案例运算也比较简单,就是数组创建的时候都设置了一个速度,每一帧都加上这一个速度然后到一定高度以后,再返回默认位置:
onmessage = function (e) {
let arr = e.data;
//更新数组位置信息
setInterval(function () {
for (let i = 0; i < arr.length; i++) {
arr[i].y += arr[i].speed;
if (arr[i].y >= 80) {
arr[i].y = -3;
}
}
postMessage(arr);
}, 1000 / 60);
};
每次数组运算完成后,再通过postMessage方法传递到主线程,供three使用。
案例地址:https://www.wjceo.com/blog/threejs2/2018-12-21/182.html