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:
- I obtain the limit of the rectangle in the 2D screen.
- 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.
- With these points I build 6 planes, which normal and distance will be the sides of the frustum.
- 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?