Reputation: 294
so i have been experimenting with ray casting in three js but i ran into terrible performance issues in Firefox and chrome (but something else is causing chromes camera to rubber band even though its a small local game) anyways when i add this code to the animate loop
var intersects = raycaster.intersectObjects(sceneObjects);
if (intersects.length > 0) {
var firstIntersectedObject = intersects[0];
console.log(intersects[0].object.userData)
console.log(intersects[0].object.userData.glow )
if (intersects[0].object.userData.glow === 'true'){
console.log("GLOW")
}else{
console.log("NO!")
}
//intersects[0].object.material.wireframe = true
// this will give you the first intersected Object if there are multiple.
}
my game starts to get all laggy and i have no idea why any pointers
Upvotes: 2
Views: 2378
Reputation: 3883
Don't raycast on every frame, instead you should have it raycast on an interval. You can use setTimeout
or setInterval
or check the timing in the update loop.
onUpdate() {
// Code that runs once per frame
// Check that we've waited long enough to raycast
if (Date.now() - this.lastRaycast > this.raycastInterval && this.qRaycast) {
this.handleRaycast();
this.lastRaycast = Date.now();
this.qRaycast = false;
}
requestAnimationFrame( () => this.onUpdate() );
}
I also only queue up raycasts when the mouse moves (no reason to keep raycasting if the mouse isn't moving) and because I have panning in my project, I disable raycast during panning movements to prevent any jitter during movement.
// Event Handlers
// Record mouse position for raycast
onMouseMove(e) {
this.mouse.x = (e.clientX / window.innerWidth ) * 2 - 1;
this.mouse.y = -((e.clientY - 50) / window.innerHeight ) * 2 + 1;
// If we are panning, don't queue a raycast
this.qRaycast = !this.mouseState.held;
}
// My app has panning, and we don't wanna keep raycasting during pan
onMouseDown(e) {
this.mouseState.lastClick = Date.now();
this.mouseState.clicked = false;
this.mouseState.held = true;
}
onMouseUp(e) {
this.mouseState.held = false;
}
then we handle the raycast:
// Like lasers, but virtual.
handleRaycast() {
let hits = null;
let hitcount = 0;
if (UI.raycast && meshObj) {
this.raygun.setFromCamera(this.mouse, this.camera);
hits = this.raygun.intersectObject(meshObj, false);
hitcount = hits.length;
}
if (hitcount > 0) {
// Do stuff with the raycast here
}
}
If you are still having performance issues, then you might wanna look into breaking down that loop function so that after XXms it breaks to let the UI update, and then continues updating on the next frame:
For example, I sort through all hits and find the point that is closest to the mouse:
// Optimization
let startTime = 0;
let maxTime = 75; // max time in ms
let dist = 1;
let hitIndex;
let i = 0;
function findClosest() {
return new Promise((resolve) => {
function loop() {
startTime = performance.now();
while (i < hitcount) {
// Break loop after maxTime
let currentTime = performance.now();
if ((currentTime - startTime) > maxTime) {
console.log('Loop exceeded max time: ' +
(currentTime - startTime).toFixed(3) );
startTime = currentTime;
break;
}
// I am finding the raycast point that is closest to the cursor
dist = hits[i].distanceToRay;
if (dist < smallestDist) {
smallestDist = dist;
smallestPointIndex = hits[i].index;
}
i++;
}
if (i < hitcount) {
// Allow the UI to update, then loop
setTimeout(loop, 1);
} else {
resolve(smallestPointIndex);
}
}
loop();
});
}
findClosest().then(result => {
// do something with the result here
}
Also the comments were good suggestions also to reduce the number of objects you are raycasting to.
Upvotes: 5