我在three.js中构建一个应用程序,但是我遇到了性能问题。该部分应用程序基于Voxel Painter example。在我的版本中,用户点击一个单元格开始放置,将光标拖动到他们希望结束放置的位置,然后点击结束。
function onDocumentMouseMove(event) {
//set up mouse and raycaster
event.preventDefault();
mouse.set((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1);
raycaster.setFromCamera(mouse, camera);
switch (buildMode) {
case buildModes.CORRIDOR:
scene.add(rollOverFloor);
var intersects = raycaster.intersectObjects(gridObject);
if (intersects.length > 0) {
var intersect = intersects[0];
if (beginPlace == true) {
//store the intersection position
var endPlace = new THREE.Vector3(0, 0, 0);
endPlace.copy(intersect.point).add(intersect.face.normal);
endPlace.divideScalar(step).floor().multiplyScalar(step).addScalar(step / step);
endPlace.set(endPlace.x, 0, endPlace.z);
corridorDrag(endPlace);
}
//if user hasn't begun to place the wall
else {
//show temporary wall on grid
rollOverFloor.position.copy(intersect.point).add(intersect.face.normal);
rollOverFloor.position.divideScalar(step).floor().multiplyScalar(step).addScalar(step / step);
rollOverFloor.position.set(rollOverFloor.position.x, 0, rollOverFloor.position.z);
}
}
break;
}
render();
}
当用户移动鼠标时会调用上面的代码(主应用程序中有很多构建模式,但我没有在此处包含它们)。此函数只是获取起点和终点,corridorDrag()函数填充起点和终点之间的单元格:
function corridorDrag(endPlace) {
deleteFromScene(stateType.CORRIDOR_DRAG);
var startPoint = startPlace;
var endPoint = endPlace;
var zIntersect = new THREE.Vector3(startPoint.x, 0, endPoint.z);
var xIntersect = new THREE.Vector3(endPoint.x, 0, startPoint.z);
var differenceZ = Math.abs(startPlace.z - zIntersect.z);
var differenceX = Math.abs(startPlace.x - xIntersect.x);
var mergedGeometry = new THREE.Geometry();
for (var i = 0; i <= (differenceZ / step); i++) {
for (var j = 0; j <= (differenceX / step); j++) {
var x = startPlace.x;
var y = startPlace.y;
var z = startPlace.z;
if (endPoint.x <= (startPlace.x )) {
if (endPoint.z <= (startPlace.z)) {
x = x - (step * j);
z = z - (step * i);
}
else if (endPoint.z >= (startPlace.z)) {
x = x - (step * j);
z = z + (step * i);
}
} else if (endPoint.x >= (startPlace.x)) {
if (endPoint.z <= (startPlace.z)) {
x = x + (step * j);
z = z - (step * i);
}
else if (endPoint.z >= (startPlace.z)) {
x = x + (step * j);
z = z + (step * i);
}
}
floorGeometry.translate(x, y, z);
mergedGeometry.merge(floorGeometry);
floorGeometry.translate(-x, -y, -z);
}
}
var voxel = new THREE.Mesh(mergedGeometry, tempMaterial);
voxel.state = stateType.CORRIDOR_DRAG;
scene.add(voxel);
tempObjects.push(voxel);
}
首先,deleteFromScene()函数从场景中删除所有当前突出显示的单元格(见下文)。然后代码(我相信)应该创建一些网格,具体取决于起点和终点,并将它们添加到场景中。
function deleteFromScene(state) {
tempObjects = [];
var i = scene.children.length;
while (i--) {
if (scene.children[i].state != undefined)
if (scene.children[i].state == state)
scene.children.splice(i, 1);
}
}
正如我所说,它非常非常缓慢。它似乎也向渲染器添加了一个淫秽数量的顶点,如WebGLRenderer统计窗口中所示。我不知道它为什么要添加这么多顶点,但我假设它为什么渲染得这么慢。
The application can be viewed here - 通过单击一个单元格,将光标拖动到网格的另一端,并观察填充单元格所需的时间,可以看到问题。
提前谢谢,这真的是最后的手段。
答案 0 :(得分:3)
几年前,Twitter发布了更新。在此更新中,他们刚刚引入了无限滚动,并且在发布当天,更新导致用户浏览器崩溃。 Twitter工程师做了一些调查,发现崩溃是滚动事件每秒发射数百次的结果。
鼠标事件每秒会触发许多次,并且可能导致代码执行过于频繁,这会降低浏览器的速度,并且(在许多情况下)会导致代码崩溃。 Twitter(希望你)的解决方案很简单:轮询你的活动。
在mousemove事件处理程序中检查自上次移动事件以来它已经过了几毫秒。
var lastMove = Date.now();
function onDocumentMouseMove(event) {
if (Date.now() - lastMove < 31) { // 32 frames a second
return;
} else {
lastMove = Date.now();
}
// your code here
}
我希望有所帮助!