How to determine if plane is in Three.js camera Frustum
Asked Answered
E

2

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.

Esmaria answered 1/6, 2012 at 23:41 Comment(0)
B
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 ) );
Brachiopod answered 2/6, 2012 at 0:38 Comment(3)
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)Marxist
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!Hawken
@Brachiopod 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.Floodlight
M
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;
}
Meetinghouse answered 3/4, 2015 at 0:47 Comment(2)
Have you tried raising an issue or creating a PR for this? This is super useful!Mitre
@Mitre 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 PRsMeetinghouse

© 2022 - 2024 — McMap. All rights reserved.