我在three.js中構建一個應用程序,但是我在性能方面遇到了實際問題。這部分的申請是基於Voxel Painter example。在我的版本中,用戶點擊單元格以開始放置,拖動光標到他們希望結束放置的位置,然後點擊結束。Three.js性能非常緩慢使用onMouseMove與RayCaster
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();
}
當用戶移動鼠標在上面的代碼被稱爲(也有在主應用程序許多buildmodes,但我這裏不包括它們)。這個函數只是獲取一個起點和終點,在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 - 通過單擊一個單元格,將光標拖到網格的另一端,並觀察填充單元所用的時間,可以看到問題。
預先感謝您,這真是不得已而爲之。
非常有說服力的解決方案,很好。 – jdmdevdotnet
非常好的解決方案,但是將該片段添加到我的onDocumentMouseMove(event)函數的頂部,並將我的代碼放在底下,似乎沒有幫助@ Brandon.Blanchyard – user3329161
運行代碼時出現了一些這些錯誤。 未捕獲的ReferenceError:isVectorEqual不是在placeCorridor定義 (3dblueprint.uk/:239) 在HTMLDocument.onDocumentMouseDown(3dblueprint.uk/:216) –