Problems building a frustum from 2D screen rectangle

Hi all,

I’m trying to do a object selection based in a 2D rectagle drawn in the screen.

The steps that I follow are the next:

  1. I obtain the limit of the rectangle in the 2D screen.
  2. I generate 8 points in world space ( 4 in the “near” plane and 4 in the “far” ) according the 2D coordinates of this rectangle with a function like glUnproject.
  3. With these points I build 6 planes, which normal and distance will be the sides of the frustum.
  4. With this frustum, I perform a octree selection of the objects in the scene ( it checks if the AABB is inside o partial inside in the frustum ).

Following the explained algorithm the selection only works if the objects are in the origin ( 0, 0, 0 ) of the scene, but I have noticed a strange behaviour, this is, if the object is not in the origin, the selection works reflected on X.

I have checked the normals and distances of each plane that form the frustum, and apparently are built right, ( the planes surrond the selection according the 2D rectangle ).

I’m almost certain that my problem is in the steps explained above, I put the function that I wrote:

Octree *oct = this->GetOctree();

if ( oct )
{
    Camera *cam = this->GetCamera();

    if ( cam )
    {
        GLfloat x0, y0, x1, y1;
        Vec3 l0, l1, l2, l3;
        Vec3 r0, r1, r2, r3;
        Mat4 projMat, viewMat;
        Frustum frustum;
        Viewport *viewport;

        cam->GenerateMats();

        // perspective projection matrix
        projMat = cam->GetProjMat();

        // view matrix ( inverse of camera model matrix )
        viewMat = cam->GetViewMat();

        viewport = cam->GetViewport();

		// 2D limits of the rectangle in the screen
        this->GetLimits( x0, y0, x1, y1 );

		// ToWorld is equal to gluUnproject

        // Generate the rectangle points in the NEAR plane
        Camera::ToWorld( projMat, viewMat, viewport, Vec3( x0, y0, 0.0f ), l0 );
        Camera::ToWorld( projMat, viewMat, viewport, Vec3( x1, y0, 0.0f ), r0 );
        Camera::ToWorld( projMat, viewMat, viewport, Vec3( x0, y1, 0.0f ), l2 );
        Camera::ToWorld( projMat, viewMat, viewport, Vec3( x1, y1, 0.0f ), r2 );

        // Generate the rectangle points in the FAR plane
        Camera::ToWorld( projMat, viewMat, viewport, Vec3( x0, y0, 1.0f ), l1 );
        Camera::ToWorld( projMat, viewMat, viewport, Vec3( x1, y0, 1.0f ), r1 );
        Camera::ToWorld( projMat, viewMat, viewport, Vec3( x0, y1, 1.0f ), l3 );
        Camera::ToWorld( projMat, viewMat, viewport, Vec3( x1, y1, 1.0f ), r3 );

        // LEFT / RIGHT
        frustum.SetSide( 0, Plane( l3, l1, l0 ) );
        frustum.SetSide( 1, Plane( r0, r1, r3 ) );

        // FRONT / BACK
        frustum.SetSide( 2, Plane( l0, r0, l2 ) );
        frustum.SetSide( 3, Plane( l3, r1, l1 ) );

        // BOTTOM / TOP
        frustum.SetSide( 4, Plane( l1, r0, l0 ) );
        frustum.SetSide( 5, Plane( l2, r2, l3 ) );

        NodeList result = OctreeSelector::Get( oct, frustum );

        for ( Node *node : result )
        {
            Print( node->GetName() );
        }
    }
}

So can somebody tell me if I’m wrong?

Wherever the bug is, it’s not in the code you posted.

1 Like

You are right, my problem was in the frustum test.

Thanks you.