Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Heuristics for setup of near/far planes of camera
Based on terrain's active nodes, this should configure frustum depth
long enough not to clip away anything that should stay visible and
at the same time make good use of depth buffer (range not too large)
  • Loading branch information
wonder-sk committed Sep 15, 2017
1 parent 7d3cf22 commit 9ac3e9c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/3d/cameracontroller.cpp
Expand Up @@ -135,7 +135,9 @@ void CameraController::setCameraData( float x, float y, float dist, float pitch,
cd.yaw = yaw;

if ( mCamera )
{
cd.setCamera( mCamera );
}
}


Expand Down Expand Up @@ -217,6 +219,13 @@ void CameraController::frameTriggered( float dt )
}
}

if ( qIsNaN( cd.x ) || qIsNaN( cd.y ) )
{
// something went horribly wrong but we need to at least try to fix it somehow
qDebug() << "camera position got NaN!";
cd.x = cd.y = 0;
}

if ( cd.pitch > 80 )
cd.pitch = 80; // prevent going under the plane
if ( cd.pitch < 0 )
Expand All @@ -234,6 +243,9 @@ void CameraController::frameTriggered( float dt )
void CameraController::resetView()
{
setCameraData( 0, 0, 1000 );
// a basic setup to make frustum depth range long enough that it does not cull everything
mCamera->setNearPlane( 1 );
mCamera->setFarPlane( 10000 );

emit cameraChanged();
}
Expand Down
3 changes: 3 additions & 0 deletions src/3d/chunks/chunkedentity.h
Expand Up @@ -45,6 +45,9 @@ class ChunkedEntity : public Qt3DCore::QEntity
//! update already loaded nodes (add to the queue)
void updateNodes( const QList<ChunkNode *> &nodes, ChunkQueueJobFactory *updateJobFactory );

QList<ChunkNode *> getActiveNodes() const { return activeNodes; }
ChunkNode *getRootNode() const { return rootNode; }

protected:
void cancelActiveJob();

Expand Down
49 changes: 49 additions & 0 deletions src/3d/scene.cpp
Expand Up @@ -12,6 +12,7 @@
#include "aabb.h"
#include "qgsabstract3drenderer.h"
#include "cameracontroller.h"
#include "chunknode.h"
#include "qgsvectorlayer.h"
#include "map3d.h"
#include "terrain.h"
Expand Down Expand Up @@ -165,6 +166,54 @@ void Scene::onCameraChanged()
if ( entity->isEnabled() )
entity->update( _sceneState( mCameraController ) );
}

// Update near and far plane from the terrain.
// this needs to be done with great care as we have kind of circular dependency here:
// active nodes are culled based on the current frustum (which involves near + far plane)
// and then based on active nodes we set near and far plane.
//
// All of this is just heuristics assuming that all other stuff is being rendered somewhere
// around the area where the terrain is.
//
// Near/far plane is setup in order to make best use of the depth buffer to avoid:
// 1. precision errors - if the range is too great
// 2. unwanted clipping of scene - if the range is too small

if ( mTerrain )
{
Qt3DRender::QCamera *camera = cameraController()->camera();
QMatrix4x4 viewMatrix = camera->viewMatrix();
float near = 1e9;
float far = 0;

QList<ChunkNode *> activeNodes = mTerrain->getActiveNodes();
Q_FOREACH ( ChunkNode *node, activeNodes )
{
// project each corner of bbox to camera coordinates
// and determine closest and farthest point.
AABB bbox = node->bbox;
for ( int i = 0; i < 8; ++i )
{
QVector4D p( ( ( i >> 0 ) & 1 ) ? bbox.xMin : bbox.xMax,
( ( i >> 1 ) & 1 ) ? bbox.yMin : bbox.yMax,
( ( i >> 2 ) & 1 ) ? bbox.zMin : bbox.zMax, 1 );
QVector4D pc = viewMatrix * p;

float dst = -pc.z(); // in camera coordinates, x grows right, y grows down, z grows to the back
if ( dst < near )
near = dst;
if ( dst > far )
far = dst;
}
}
//qDebug() << "near/far" << near << far;
if ( near < 1 )
near = 1; // does not really make sense to use negative far plane (behind camera)

// set near/far plane - with some tolerance in front/behind expected near/far planes
camera->setFarPlane( far * 2 );
camera->setNearPlane( near / 2 );
}
}

void Scene::onFrameTriggered( float dt )
Expand Down

0 comments on commit 9ac3e9c

Please sign in to comment.