I have been tinkering around with Three.js and I have a canvas I'd like to use as kind of a GUI. For that I have to check if an object is in the camera frustum.
My current code:
camera.updateMatrix();
camera.updateMatrixWorld();
const frustum = new THREE.Frustum();
const projScreenMatrix = new THREE.Matrix4();
projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
frustum.setFromProjectionMatrix( camera.projectionMatrix );
if(frustum.containsPoint( mesh.position )){
// stuff happens...
};
frustum.containsPoint()
keeps returning false
. What am I doing wrong here?
I have been tinkering around with Three.js and I have a canvas I'd like to use as kind of a GUI. For that I have to check if an object is in the camera frustum.
My current code:
camera.updateMatrix();
camera.updateMatrixWorld();
const frustum = new THREE.Frustum();
const projScreenMatrix = new THREE.Matrix4();
projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
frustum.setFromProjectionMatrix( camera.projectionMatrix );
if(frustum.containsPoint( mesh.position )){
// stuff happens...
};
frustum.containsPoint()
keeps returning false
. What am I doing wrong here?
-
A
Frustum
takes 6Plane
s as arguments, you're not providing anything. That's probably why it doesn't work. – Leeft Commented Jul 22, 2014 at 7:10 - So how would i go about cloning the camera frustum? – Kevin Kuyl Commented Jul 22, 2014 at 7:40
- An example of that is in this answer: stackoverflow./questions/10858599/… – Leeft Commented Jul 22, 2014 at 7:56
4 Answers
Reset to default 9Your code is using
frustum.setFromMatrix( camera.projectionMatrix );
But that isn't the matrix you want. Instead use:
frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ) );
as answered in How to determine if plane is in Three.js camera Frustum
Three.js is doing view frustum Culling internally and only rendering when in camera frustum. Assuming that your Boundig Volumes are calculated correct, you can track weather a renderable Object3D is inside the camera view frustum when Object3D.onBeforeRender callback is called in your current frame
Here is what I did to find if a mesh is in camera view (within 100ms):
mesh.onBeforeRender = function() {
if (mesh.userData.inViewID) clearTimeout(mesh.userData.inViewID);
mesh.userData.inViewID = setTimeout(()=>{
mesh.userData.inView = false;
console.log("out of view");
}, 100);
if (!mesh.userData.inView) {
mesh.userData.inView = true;
console.log("in view");
}
}
now in version r166 the code has changed slightly so I add an update.
const frustum = new THREE.Frustum();
camera.updateMatrix();
camera.updateMatrixWorld();
mesh.updateMatrix();
mesh.updateMatrixWorld();
frustum.setFromProjectionMatrix(
new THREE.Matrix4().multiplyMatrices(
camera.projectionMatrix,
camera.matrixWorldInverse
)
);
const intesectedMesh = frustum.intersectsObject(mesh);
if(intesectedMesh){
//Do something
}
Regards