Commit 539a7592 authored by Frédéric Larue's avatar Frédéric Larue
Browse files

Frustum culling added for rendering / selection z-buffer generation / picking.

parent 61467097
/*
* (c) LSIIT, UMR CNRS/UdS
* Authors: F. Larue.
*
* See licence.txt for additional information.
*/
#include "Frustum.h"
#include <iostream>
void Frustum::UpdateFrustumPlanes( const QMatrix4x4& V, const QMatrix4x4& P )
{
float n = P(2,3) / (P(2,2)-1.0f);
float f = P(2,3) / (P(2,2)+1.0f);
float l = (P(0,2)-1.0f) / P(0,0);
float r = (P(0,2)+1.0f) / P(0,0);
float b = (P(1,2)-1.0f) / P(1,1);
float t = (P(1,2)+1.0f) / P(1,1);
QVector3D center( -V(0,0)*V(0,3) - V(1,0)*V(1,3) - V(2,0)*V(2,3),
-V(0,1)*V(0,3) - V(1,1)*V(1,3) - V(2,1)*V(2,3),
-V(0,2)*V(0,3) - V(1,2)*V(1,3) - V(2,2)*V(2,3) );
QVector3D right( V(0,0), V(0,1), V(0,2) );
QVector3D top ( V(1,0), V(1,1), V(1,2) );
QVector3D front( -V(2,0), -V(2,1), -V(2,2) );
// Near plane.
m_Planes[NEAR_PLANE].n = front;
m_Planes[NEAR_PLANE].d0 = -QVector3D::dotProduct( front, center ) - n;
// Far plane.
m_Planes[FAR_PLANE].n = -front;
m_Planes[FAR_PLANE].d0 = QVector3D::dotProduct( front, center ) + f;
// Left plane.
m_Planes[LEFT_PLANE].n = QVector3D::crossProduct( front + l*right, top );
m_Planes[LEFT_PLANE].d0 = -QVector3D::dotProduct( m_Planes[LEFT_PLANE].n, center );
// Right plane.
m_Planes[RIGHT_PLANE].n = QVector3D::crossProduct( top, front + r*right );
m_Planes[RIGHT_PLANE].d0 = -QVector3D::dotProduct( m_Planes[RIGHT_PLANE].n, center );
// Bottom plane.
m_Planes[BOTTOM_PLANE].n = QVector3D::crossProduct( right, front + b*top );
m_Planes[BOTTOM_PLANE].d0 = -QVector3D::dotProduct( m_Planes[BOTTOM_PLANE].n, center );
// Top plane.
m_Planes[TOP_PLANE].n = QVector3D::crossProduct( front + t*top, right );
m_Planes[TOP_PLANE].d0 = -QVector3D::dotProduct( m_Planes[TOP_PLANE].n, center );
}
bool Frustum::IsOutside( const Box3f& box, const QMatrix4x4& model ) const
{
Box3f::CornerSet corners;
box.Corners( corners );
for( auto &c : corners )
c = model.map( c );
for( int i=0; i<PLANE_COUNT; ++i )
{
uint32_t nBack = 0;
for( auto &c : corners )
{
float distToPlane = QVector3D::dotProduct( m_Planes[i].n, c ) + m_Planes[i].d0;
nBack += ((* (uint32_t*) &distToPlane) >> 31);
}
if( nBack == 8 )
return true;
}
return false;
}
/*
* (c) LSIIT, UMR CNRS/UdS
* Authors: F. Larue.
*
* See licence.txt for additional information.
*/
#ifndef __GLVIEWER__FRUSTUM_H__
#define __GLVIEWER__FRUSTUM_H__
#include <QtGui>
#include "Box.h"
class Frustum
{
enum PlaneId
{
NEAR_PLANE ,
FAR_PLANE ,
LEFT_PLANE ,
RIGHT_PLANE ,
BOTTOM_PLANE ,
TOP_PLANE ,
PLANE_COUNT ,
};
struct Plane
{
QVector3D n;
float d0;
};
Plane m_Planes[PLANE_COUNT];
public:
void UpdateFrustumPlanes( const QMatrix4x4& V, const QMatrix4x4& P );
bool IsOutside( const Box3f& box, const QMatrix4x4& model ) const;
};
#endif //__GLVIEWER__FRUSTUM_H__
......@@ -942,6 +942,8 @@ void GLViewer::paintGL()
m_ViewProjectionMatrixInverse = m_ViewMatrixInverse * m_ProjectionMatrixInverse;
m_PixelToRayMatrix = viewRotationMatrixInverse() * projectionMatrixInverse();
m_Frustum.UpdateFrustumPlanes( m_ViewMatrix, m_ProjectionMatrix );
}
// Setup the OpenGL transforms and viewport.
......@@ -961,17 +963,19 @@ void GLViewer::paintGL()
// Display the scene content by increasing priority.
for( PriorityMap::iterator dlist=m_DisplayablesByPriority.begin(); dlist!=m_DisplayablesByPriority.end(); ++dlist )
for( DisplayableList::iterator dinfo=dlist->second.begin(); dinfo!=dlist->second.end(); ++dinfo )
{
glPushMatrix();
glMultMatrixf( (*dinfo)->GetTransform().data() );
glPushAttrib( GL_ALL_ATTRIB_BITS );
(*dinfo)->displayable->onDisplay( *(*dinfo)->displayable->getSource()->GetDisplayOptions() );
displayLabel( (*dinfo)->displayable );
if( (*dinfo)->selectionMgr )
(*dinfo)->selectionMgr->onDisplay( this );
glPopAttrib();
glPopMatrix();
}
if( !m_Frustum.IsOutside( (*dinfo)->boundingBox, (*dinfo)->GetTransform() ) )
{
glPushMatrix();
glMultMatrixf( (*dinfo)->GetTransform().data() );
glPushAttrib( GL_ALL_ATTRIB_BITS );
(*dinfo)->displayable->onDisplay( *(*dinfo)->displayable->getSource()->GetDisplayOptions() );
displayLabel( (*dinfo)->displayable );
if( (*dinfo)->selectionMgr )
(*dinfo)->selectionMgr->onDisplay( this );
glPopAttrib();
glPopMatrix();
}
// Finalize the rendering.
releaseScene();
......@@ -1274,12 +1278,13 @@ void GLViewer::updateSelectionZBuffer()
for( PriorityMap::iterator dlist=m_DisplayablesByPriority.begin(); dlist!=m_DisplayablesByPriority.end(); ++dlist )
for( DisplayableList::iterator dinfo=dlist->second.begin(); dinfo!=dlist->second.end(); ++dinfo )
{
m_ZBufferShader.SetUniform( "fullTransformMatrix", (viewProjectionMatrix() * (*dinfo)->GetTransform()).data() );
glPushAttrib( GL_ALL_ATTRIB_BITS );
(*dinfo)->displayable->onPicking( *(*dinfo)->displayable->getSource()->GetDisplayOptions(), m_ZBufferShader, "vertexPosition" );
glPopAttrib();
}
if( !m_Frustum.IsOutside( (*dinfo)->boundingBox, (*dinfo)->GetTransform() ) )
{
m_ZBufferShader.SetUniform( "fullTransformMatrix", (viewProjectionMatrix() * (*dinfo)->GetTransform()).data() );
glPushAttrib( GL_ALL_ATTRIB_BITS );
(*dinfo)->displayable->onPicking( *(*dinfo)->displayable->getSource()->GetDisplayOptions(), m_ZBufferShader, "vertexPosition" );
glPopAttrib();
}
// Finalize the rendering.
......@@ -2157,6 +2162,9 @@ bool GLViewer::getPickedPoint( const float x,
for( DisplayableMap::iterator d=m_Displayables.begin(); d!=m_Displayables.end(); ++d )
{
if( m_Frustum.IsOutside( d->second.boundingBox, d->second.GetTransform() ) )
continue;
QMatrix4x4 cameraToBox = d->second.GetTransform().inverted();
QVector3D localRayOrig = cameraToBox.map( rayOrig );
QVector3D localRayDir = cameraToBox.mapVector( rayDir );
......@@ -2397,7 +2405,7 @@ void GLViewer::setSelectionEnabled( bool enabled )
m_SelectionEnabled = enabled;
setCursor( enabled? QCursor(Qt::CrossCursor) : QCursor(Qt::ArrowCursor) );
//setMouseTracking( enabled );
setMouseTracking( enabled );
if( enabled )
{
......
......@@ -16,6 +16,7 @@
#include "MetricGrid.h"
#include "PickedPoint.h"
#include "UIData.h"
#include "Frustum.h"
class InfoBarManager;
class Panel;
......@@ -157,6 +158,8 @@ protected:
QMatrix4x4 m_ViewProjectionMatrixInverse;
QMatrix4x4 m_PixelToRayMatrix;
Frustum m_Frustum;
/*****************************\
| Constructor(s) / destructor |
\*****************************/
......@@ -244,7 +247,7 @@ public:
inline QVector3D viewpointLocation() const
{
QMatrix4x4 R = viewMatrix();
const QMatrix4x4& R = viewMatrix();
return R.transposed().mapVector( -R.column(3).toVector3D() );
}
inline QVector3D pixelRay( int px, int py ) const
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment