11

I am having a hard time making a function that returns true if a plane is inside of the camera's view frustrum. I found this post, on github, but the recipe always returns false whether or not the object is in the frustum.

Anyone already implemented this intelligently? Much thanks.

meawoppl
  • 2,714
  • 1
  • 23
  • 30

2 Answers2

19

Maybe the matrices are not updated?

camera.updateMatrix(); // make sure camera's local matrix is updated
camera.updateMatrixWorld(); // make sure camera's world matrix is updated
camera.matrixWorldInverse.getInverse( camera.matrixWorld );

plane.updateMatrix(); // make sure plane's local matrix is updated
plane.updateMatrixWorld(); // make sure plane's world matrix is updated

var frustum = new THREE.Frustum();
frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ) );
alert( frustum.contains( plane ) );
Matthias
  • 13,607
  • 9
  • 44
  • 60
mrdoob
  • 19,334
  • 4
  • 63
  • 62
  • 2
    I want to know if the frustum contains a whole cube, but it's not working using this method... what method can I use? (I don't see any listed in the [documentation](http://threejs.org/docs/#Reference/Math/Frustum)) – CodyBugstein Nov 10 '13 at 12:42
  • You could take a canvas snapshot of the object at that point in time to get a planar perspective of the object. Find the lines that make up that polygon snapshot. You already know the coordinates of the cameras frutum matrix. Now you have a polygon inside, or outside/overlapping of another polygon. Use a "Polygon in Polygon" detection algorithm aka sweep-line algorithm to get what you need! – Dan Kanze Oct 01 '16 at 22:49
  • @mrdoob why not to add a prop "inFrustum" as proposed in the answer below? This way we can use the frustum test status from the previous frame,without recalc it all again. – Michael IV Jun 01 '18 at 10:55
6

Correct me if I'm wrong, but why to calculate frustum second time?

I'm working on a complex project and the accepted answer is not the best solution for me. I see no point of recalculating what aleady was calculated. For my purpose I modified my copy of three.js by raising a flag if something was detected in frustum or not. Later just check on your object if object.inFrustum === true

Below following line

if ( webglObjects && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) {

add

object.inFrustum = true;

also where the if block ends add an oposite flag

else {
    object.inFrustum = false;
}

My final result in r70 which works perfectly:

if ( webglObjects && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) {

    object.inFrustum = true; // The line to add

    for ( var i = 0, l = webglObjects.length; i < l; i ++ ) {

        var webglObject = webglObjects[i];

        unrollBufferMaterial( webglObject );

        webglObject.render = true;

        if ( _this.sortObjects === true ) {

            _vector3.setFromMatrixPosition( object.matrixWorld );
            _vector3.applyProjection( _projScreenMatrix );

            webglObject.z = _vector3.z;

        }

    }

} else { // Create second condition like that
    object.inFrustum = false;
}
Pawel
  • 16,093
  • 5
  • 70
  • 73
  • 1
    Have you tried raising an issue or creating a PR for this? This is super useful! – hpalu Apr 14 '19 at 12:41
  • @hpalu thanks but I think it's dependent on camera and might be considered too broad when set on an object. Maybe the parameter should be called "inPreviousFrameFrustum". I have so many little changes in my THREE repo fork that I really should start making some PRs – Pawel Apr 15 '19 at 21:24