mirror of
https://github.com/lubosz/overte.git
synced 2025-04-09 05:03:52 +02:00
Merge pull request #354 from ey6es/master
Added support for off-axis projection (via eye offset position/orientation parameters in camera/frustum).
This commit is contained in:
commit
282ebbdcbb
11 changed files with 339 additions and 169 deletions
|
@ -18,6 +18,8 @@
|
|||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <QActionGroup>
|
||||
#include <QColorDialog>
|
||||
#include <QDesktopWidget>
|
||||
|
@ -356,6 +358,14 @@ void Application::paintGL() {
|
|||
whichCamera = _viewFrustumOffsetCamera;
|
||||
}
|
||||
|
||||
// transform by eye offset
|
||||
|
||||
glm::vec3 eyeOffsetPos = whichCamera.getEyeOffsetPosition();
|
||||
glm::quat eyeOffsetOrient = whichCamera.getEyeOffsetOrientation();
|
||||
glm::vec3 eyeOffsetAxis = glm::axis(eyeOffsetOrient);
|
||||
glRotatef(-glm::angle(eyeOffsetOrient), eyeOffsetAxis.x, eyeOffsetAxis.y, eyeOffsetAxis.z);
|
||||
glTranslatef(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z);
|
||||
|
||||
// transform view according to whichCamera
|
||||
// could be myCamera (if in normal mode)
|
||||
// or could be viewFrustumOffsetCamera if in offset mode
|
||||
|
@ -450,7 +460,11 @@ void Application::resizeGL(int width, int height) {
|
|||
}
|
||||
|
||||
// On window reshape, we need to tell OpenGL about our new setting
|
||||
gluPerspective(fov,aspectRatio,nearClip,farClip);
|
||||
float left, right, bottom, top, nearVal, farVal;
|
||||
glm::vec4 nearClipPlane, farClipPlane;
|
||||
loadViewFrustum(camera, _viewFrustum);
|
||||
_viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
glFrustum(left, right, bottom, top, nearVal, farVal);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
@ -594,6 +608,66 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
_myAvatar.setDriveKeys(shifted ? RIGHT : ROT_RIGHT, 1);
|
||||
break;
|
||||
|
||||
case Qt::Key_I:
|
||||
if (shifted) {
|
||||
_myCamera.setEyeOffsetOrientation(glm::normalize(
|
||||
glm::quat(glm::vec3(0.002f, 0, 0)) * _myCamera.getEyeOffsetOrientation()));
|
||||
} else {
|
||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0.001, 0));
|
||||
}
|
||||
resizeGL(_glWidget->width(), _glWidget->height());
|
||||
break;
|
||||
|
||||
case Qt::Key_K:
|
||||
if (shifted) {
|
||||
_myCamera.setEyeOffsetOrientation(glm::normalize(
|
||||
glm::quat(glm::vec3(-0.002f, 0, 0)) * _myCamera.getEyeOffsetOrientation()));
|
||||
} else {
|
||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, -0.001, 0));
|
||||
}
|
||||
resizeGL(_glWidget->width(), _glWidget->height());
|
||||
break;
|
||||
|
||||
case Qt::Key_J:
|
||||
if (shifted) {
|
||||
_myCamera.setEyeOffsetOrientation(glm::normalize(
|
||||
glm::quat(glm::vec3(0, 0.002f, 0)) * _myCamera.getEyeOffsetOrientation()));
|
||||
} else {
|
||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
|
||||
}
|
||||
resizeGL(_glWidget->width(), _glWidget->height());
|
||||
break;
|
||||
|
||||
case Qt::Key_M:
|
||||
if (shifted) {
|
||||
_myCamera.setEyeOffsetOrientation(glm::normalize(
|
||||
glm::quat(glm::vec3(0, -0.002f, 0)) * _myCamera.getEyeOffsetOrientation()));
|
||||
} else {
|
||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
|
||||
}
|
||||
resizeGL(_glWidget->width(), _glWidget->height());
|
||||
break;
|
||||
|
||||
case Qt::Key_U:
|
||||
if (shifted) {
|
||||
_myCamera.setEyeOffsetOrientation(glm::normalize(
|
||||
glm::quat(glm::vec3(0, 0, -0.002f)) * _myCamera.getEyeOffsetOrientation()));
|
||||
} else {
|
||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, -0.001));
|
||||
}
|
||||
resizeGL(_glWidget->width(), _glWidget->height());
|
||||
break;
|
||||
|
||||
case Qt::Key_Y:
|
||||
if (shifted) {
|
||||
_myCamera.setEyeOffsetOrientation(glm::normalize(
|
||||
glm::quat(glm::vec3(0, 0, 0.002f)) * _myCamera.getEyeOffsetOrientation()));
|
||||
} else {
|
||||
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, 0.001));
|
||||
}
|
||||
resizeGL(_glWidget->width(), _glWidget->height());
|
||||
break;
|
||||
|
||||
default:
|
||||
event->ignore();
|
||||
break;
|
||||
|
@ -1006,12 +1080,12 @@ void Application::doFalseRandomizeEveryOtherVoxelColors() {
|
|||
}
|
||||
|
||||
void Application::doFalseColorizeByDistance() {
|
||||
loadViewFrustum(_viewFrustum);
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
_voxels.falseColorizeDistanceFromView(&_viewFrustum);
|
||||
}
|
||||
|
||||
void Application::doFalseColorizeInView() {
|
||||
loadViewFrustum(_viewFrustum);
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
// we probably want to make sure the viewFrustum is initialized first
|
||||
_voxels.falseColorizeInView(&_viewFrustum);
|
||||
}
|
||||
|
@ -1312,7 +1386,7 @@ void Application::updateAvatar(float deltaTime) {
|
|||
// We could optimize this to not actually load the viewFrustum, since we don't
|
||||
// actually need to calculate the view frustum planes to send these details
|
||||
// to the server.
|
||||
loadViewFrustum(_viewFrustum);
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
_myAvatar.setCameraPosition(_viewFrustum.getPosition());
|
||||
_myAvatar.setCameraDirection(_viewFrustum.getDirection());
|
||||
_myAvatar.setCameraUp(_viewFrustum.getUp());
|
||||
|
@ -1364,7 +1438,7 @@ void Application::updateAvatar(float deltaTime) {
|
|||
// Description: this will load the view frustum bounds for EITHER the head
|
||||
// or the "myCamera".
|
||||
//
|
||||
void Application::loadViewFrustum(ViewFrustum& viewFrustum) {
|
||||
void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
|
||||
// We will use these below, from either the camera or head vectors calculated above
|
||||
glm::vec3 position;
|
||||
glm::vec3 direction;
|
||||
|
@ -1374,16 +1448,16 @@ void Application::loadViewFrustum(ViewFrustum& viewFrustum) {
|
|||
|
||||
// Camera or Head?
|
||||
if (_cameraFrustum->isChecked()) {
|
||||
position = _myCamera.getPosition();
|
||||
position = camera.getPosition();
|
||||
} else {
|
||||
position = _myAvatar.getHeadPosition();
|
||||
}
|
||||
|
||||
fov = _myCamera.getFieldOfView();
|
||||
nearClip = _myCamera.getNearClip();
|
||||
farClip = _myCamera.getFarClip();
|
||||
fov = camera.getFieldOfView();
|
||||
nearClip = camera.getNearClip();
|
||||
farClip = camera.getFarClip();
|
||||
|
||||
Orientation o = _myCamera.getOrientation();
|
||||
Orientation o = camera.getOrientation();
|
||||
|
||||
direction = o.getFront();
|
||||
up = o.getUp();
|
||||
|
@ -1408,6 +1482,8 @@ void Application::loadViewFrustum(ViewFrustum& viewFrustum) {
|
|||
viewFrustum.setFieldOfView(fov);
|
||||
viewFrustum.setNearClip(nearClip);
|
||||
viewFrustum.setFarClip(farClip);
|
||||
viewFrustum.setEyeOffsetPosition(camera.getEyeOffsetPosition());
|
||||
viewFrustum.setEyeOffsetOrientation(camera.getEyeOffsetOrientation());
|
||||
|
||||
// Ask the ViewFrustum class to calculate our corners
|
||||
viewFrustum.calculate();
|
||||
|
@ -1818,12 +1894,12 @@ void Application::displayStats() {
|
|||
// * Far Plane - draws only the far plane
|
||||
void Application::renderViewFrustum(ViewFrustum& viewFrustum) {
|
||||
// Load it with the latest details!
|
||||
loadViewFrustum(viewFrustum);
|
||||
loadViewFrustum(_myCamera, viewFrustum);
|
||||
|
||||
glm::vec3 position = viewFrustum.getPosition();
|
||||
glm::vec3 direction = viewFrustum.getDirection();
|
||||
glm::vec3 up = viewFrustum.getUp();
|
||||
glm::vec3 right = viewFrustum.getRight();
|
||||
glm::vec3 position = viewFrustum.getOffsetPosition();
|
||||
glm::vec3 direction = viewFrustum.getOffsetDirection();
|
||||
glm::vec3 up = viewFrustum.getOffsetUp();
|
||||
glm::vec3 right = viewFrustum.getOffsetRight();
|
||||
|
||||
// Get ready to draw some lines
|
||||
glDisable(GL_LIGHTING);
|
||||
|
|
|
@ -105,7 +105,7 @@ private:
|
|||
void init();
|
||||
|
||||
void updateAvatar(float deltaTime);
|
||||
void loadViewFrustum(ViewFrustum& viewFrustum);
|
||||
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
|
||||
|
||||
void displayOculus(Camera& whichCamera);
|
||||
void displaySide(Camera& whichCamera);
|
||||
|
|
|
@ -169,6 +169,16 @@ void Camera::setFarClip (float f) {
|
|||
_frustumNeedsReshape = true;
|
||||
}
|
||||
|
||||
void Camera::setEyeOffsetPosition (const glm::vec3& p) {
|
||||
_eyeOffsetPosition = p;
|
||||
_frustumNeedsReshape = true;
|
||||
}
|
||||
|
||||
void Camera::setEyeOffsetOrientation (const glm::quat& o) {
|
||||
_eyeOffsetOrientation = o;
|
||||
_frustumNeedsReshape = true;
|
||||
}
|
||||
|
||||
void Camera::initialize() {
|
||||
_needsToInitialize = true;
|
||||
_modeShift = 0.0;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "Orientation.h"
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
enum CameraMode
|
||||
{
|
||||
|
@ -34,8 +35,8 @@ public:
|
|||
|
||||
void initialize(); // instantly put the camera at the ideal position and rotation.
|
||||
|
||||
void update( float deltaTime );
|
||||
|
||||
void update( float deltaTime );
|
||||
|
||||
void setYaw ( float y ) { _yaw = y; }
|
||||
void setPitch ( float p ) { _pitch = p; }
|
||||
void setRoll ( float r ) { _roll = r; }
|
||||
|
@ -53,6 +54,8 @@ public:
|
|||
void setAspectRatio ( float a );
|
||||
void setNearClip ( float n );
|
||||
void setFarClip ( float f );
|
||||
void setEyeOffsetPosition ( const glm::vec3& p);
|
||||
void setEyeOffsetOrientation ( const glm::quat& o);
|
||||
|
||||
float getYaw () { return _yaw; }
|
||||
float getPitch () { return _pitch; }
|
||||
|
@ -64,31 +67,35 @@ public:
|
|||
float getAspectRatio() { return _aspectRatio; }
|
||||
float getNearClip () { return _nearClip; }
|
||||
float getFarClip () { return _farClip; }
|
||||
glm::vec3 getEyeOffsetPosition () { return _eyeOffsetPosition; }
|
||||
glm::quat getEyeOffsetOrientation () { return _eyeOffsetOrientation; }
|
||||
bool getFrustumNeedsReshape(); // call to find out if the view frustum needs to be reshaped
|
||||
void setFrustumWasReshaped(); // call this after reshaping the view frustum.
|
||||
|
||||
private:
|
||||
|
||||
bool _needsToInitialize;
|
||||
CameraMode _mode;
|
||||
CameraMode _mode;
|
||||
bool _frustumNeedsReshape;
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _idealPosition;
|
||||
glm::vec3 _targetPosition;
|
||||
float _fieldOfView;
|
||||
float _aspectRatio;
|
||||
float _nearClip;
|
||||
float _farClip;
|
||||
float _yaw;
|
||||
float _pitch;
|
||||
float _roll;
|
||||
float _upShift;
|
||||
float _idealYaw;
|
||||
float _idealPitch;
|
||||
float _idealRoll;
|
||||
float _distance;
|
||||
float _tightness;
|
||||
Orientation _orientation;
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _idealPosition;
|
||||
glm::vec3 _targetPosition;
|
||||
float _fieldOfView;
|
||||
float _aspectRatio;
|
||||
float _nearClip;
|
||||
float _farClip;
|
||||
glm::vec3 _eyeOffsetPosition;
|
||||
glm::quat _eyeOffsetOrientation;
|
||||
float _yaw;
|
||||
float _pitch;
|
||||
float _roll;
|
||||
float _upShift;
|
||||
float _idealYaw;
|
||||
float _idealPitch;
|
||||
float _idealRoll;
|
||||
float _distance;
|
||||
float _tightness;
|
||||
Orientation _orientation;
|
||||
float _modeShift;
|
||||
|
||||
CameraFollowingAttributes _attributes[NUM_CAMERA_MODES];
|
||||
|
|
|
@ -25,18 +25,8 @@ void Environment::renderAtmosphere(Camera& camera) {
|
|||
glPushMatrix();
|
||||
glTranslatef(getAtmosphereCenter().x, getAtmosphereCenter().y, getAtmosphereCenter().z);
|
||||
|
||||
// use the camera distance to reset the near and far distances to keep the atmosphere in the frustum
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
|
||||
float projection[16];
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, projection);
|
||||
glm::vec3 relativeCameraPos = camera.getPosition() - getAtmosphereCenter();
|
||||
float height = glm::length(relativeCameraPos);
|
||||
float near = camera.getNearClip(), far = height + getAtmosphereOuterRadius();
|
||||
projection[10] = (far + near) / (near - far);
|
||||
projection[14] = (2.0f * far * near) / (near - far);
|
||||
glLoadMatrixf(projection);
|
||||
|
||||
// use the appropriate shader depending on whether we're inside or outside
|
||||
ProgramObject* program;
|
||||
|
|
|
@ -638,11 +638,18 @@ void VoxelSystem::render() {
|
|||
_perlinModulateProgram->bind();
|
||||
glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID);
|
||||
|
||||
// for performance, disable blending and enable backface culling
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
// draw the number of voxels we have
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
||||
glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);
|
||||
glDrawElements(GL_TRIANGLES, 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
_perlinModulateProgram->release();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ const Glyph& TextRenderer::getGlyph(char c) {
|
|||
painter.setFont(_font);
|
||||
if (_effectType == SHADOW_EFFECT) {
|
||||
for (int i = 0; i < _effectThickness; i++) {
|
||||
painter.drawText(-bounds.x() - i, -bounds.y() + i, ch);
|
||||
painter.drawText(-bounds.x() - 1 - i, -bounds.y() + 1 + i, ch);
|
||||
}
|
||||
} else if (_effectType == OUTLINE_EFFECT) {
|
||||
QPainterPath path;
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
enum EffectType { NO_EFFECT, SHADOW_EFFECT, OUTLINE_EFFECT };
|
||||
|
||||
TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false,
|
||||
EffectType effect = NO_EFFECT, int effectThickness = 2);
|
||||
EffectType effect = NO_EFFECT, int effectThickness = 1);
|
||||
~TextRenderer();
|
||||
|
||||
const QFontMetrics& metrics() const { return _metrics; }
|
||||
|
|
|
@ -28,7 +28,7 @@ void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3
|
|||
|
||||
// this will be perpendicular to both lines
|
||||
_normal = glm::cross(linev1v2,linev1v3);
|
||||
glm::normalize(_normal);
|
||||
_normal = glm::normalize(_normal);
|
||||
|
||||
// this is a point on the plane
|
||||
_point = v2;
|
||||
|
|
|
@ -8,10 +8,16 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include "ViewFrustum.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "voxels_Log.h"
|
||||
|
||||
using voxels_lib::printLog;
|
||||
using namespace std;
|
||||
|
||||
ViewFrustum::ViewFrustum() :
|
||||
_position(glm::vec3(0,0,0)),
|
||||
|
@ -22,10 +28,6 @@ ViewFrustum::ViewFrustum() :
|
|||
_aspectRatio(1.0),
|
||||
_nearClip(0.1),
|
||||
_farClip(500.0),
|
||||
_nearHeight(0.0),
|
||||
_nearWidth(0.0),
|
||||
_farHeight(0.0),
|
||||
_farWidth(0.0),
|
||||
_farCenter(glm::vec3(0,0,0)),
|
||||
_farTopLeft(glm::vec3(0,0,0)),
|
||||
_farTopRight(glm::vec3(0,0,0)),
|
||||
|
@ -41,67 +43,68 @@ ViewFrustum::ViewFrustum() :
|
|||
// ViewFrustum::calculateViewFrustum()
|
||||
//
|
||||
// Description: this will calculate the view frustum bounds for a given position
|
||||
// and direction
|
||||
// and direction
|
||||
//
|
||||
// Notes on how/why this works:
|
||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/
|
||||
//
|
||||
void ViewFrustum::calculate() {
|
||||
// compute the off-axis frustum parameters as we would for glFrustum
|
||||
float left, right, bottom, top, nearVal, farVal;
|
||||
glm::vec4 nearClipPlane, farClipPlane;
|
||||
computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
|
||||
// start with the corners of the near frustum window
|
||||
glm::vec3 topLeft(left, top, -nearVal);
|
||||
glm::vec3 topRight(right, top, -nearVal);
|
||||
glm::vec3 bottomLeft(left, bottom, -nearVal);
|
||||
glm::vec3 bottomRight(right, bottom, -nearVal);
|
||||
|
||||
// find the intersections of the rays through the corners with the clip planes in view space,
|
||||
// then transform them to world space
|
||||
glm::mat4 worldMatrix = glm::translate(_position) * glm::mat4(glm::mat3(_right, _up, -_direction)) *
|
||||
glm::translate(_eyeOffsetPosition) * glm::mat4_cast(_eyeOffsetOrientation);
|
||||
_farTopLeft = glm::vec3(worldMatrix * glm::vec4(topLeft *
|
||||
(-farClipPlane.w / glm::dot(topLeft, glm::vec3(farClipPlane))), 1.0f));
|
||||
_farTopRight = glm::vec3(worldMatrix * glm::vec4(topRight *
|
||||
(-farClipPlane.w / glm::dot(topRight, glm::vec3(farClipPlane))), 1.0f));
|
||||
_farBottomLeft = glm::vec3(worldMatrix * glm::vec4(bottomLeft *
|
||||
(-farClipPlane.w / glm::dot(bottomLeft, glm::vec3(farClipPlane))), 1.0f));
|
||||
_farBottomRight = glm::vec3(worldMatrix * glm::vec4(bottomRight *
|
||||
(-farClipPlane.w / glm::dot(bottomRight, glm::vec3(farClipPlane))), 1.0f));
|
||||
_nearTopLeft = glm::vec3(worldMatrix * glm::vec4(topLeft *
|
||||
(-nearClipPlane.w / glm::dot(topLeft, glm::vec3(nearClipPlane))), 1.0f));
|
||||
_nearTopRight = glm::vec3(worldMatrix * glm::vec4(topRight *
|
||||
(-nearClipPlane.w / glm::dot(topRight, glm::vec3(nearClipPlane))), 1.0f));
|
||||
_nearBottomLeft = glm::vec3(worldMatrix * glm::vec4(bottomLeft *
|
||||
(-nearClipPlane.w / glm::dot(bottomLeft, glm::vec3(nearClipPlane))), 1.0f));
|
||||
_nearBottomRight = glm::vec3(worldMatrix * glm::vec4(bottomRight *
|
||||
(-nearClipPlane.w / glm::dot(bottomRight, glm::vec3(nearClipPlane))), 1.0f));
|
||||
|
||||
// compute the offset position and axes in world space
|
||||
_offsetPosition = glm::vec3(worldMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
_offsetDirection = glm::vec3(worldMatrix * glm::vec4(0.0f, 0.0f, -1.0f, 0.0f));
|
||||
_offsetUp = glm::vec3(worldMatrix * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
|
||||
_offsetRight = glm::vec3(worldMatrix * glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
|
||||
|
||||
// compute the six planes
|
||||
// The planes are defined such that the normal points towards the inside of the view frustum.
|
||||
// Testing if an object is inside the view frustum is performed by computing on which side of
|
||||
// the plane the object resides. This can be done computing the signed distance from the point
|
||||
// to the plane. If it is on the side that the normal is pointing, i.e. the signed distance
|
||||
// is positive, then it is on the right side of the respective plane. If an object is on the
|
||||
// right side of all six planes then the object is inside the frustum.
|
||||
|
||||
static const double PI_OVER_180 = 3.14159265359 / 180.0; // would be better if this was in a shared location
|
||||
|
||||
glm::vec3 front = _direction;
|
||||
|
||||
// Calculating field of view.
|
||||
float fovInRadians = _fieldOfView * PI_OVER_180;
|
||||
|
||||
float twoTimesTanHalfFOV = 2.0f * tan(fovInRadians/2.0f);
|
||||
|
||||
// Do we need this?
|
||||
//tang = (float)tan(ANG2RAD * angle * 0.5) ;
|
||||
|
||||
float nearClip = _nearClip;
|
||||
float farClip = _farClip;
|
||||
|
||||
_nearHeight = (twoTimesTanHalfFOV * nearClip);
|
||||
_nearWidth = _nearHeight * _aspectRatio;
|
||||
_farHeight = (twoTimesTanHalfFOV * farClip);
|
||||
_farWidth = _farHeight * _aspectRatio;
|
||||
|
||||
float farHalfHeight = (_farHeight * 0.5f);
|
||||
float farHalfWidth = (_farWidth * 0.5f);
|
||||
_farCenter = _position+front * farClip;
|
||||
_farTopLeft = _farCenter + (_up * farHalfHeight) - (_right * farHalfWidth);
|
||||
_farTopRight = _farCenter + (_up * farHalfHeight) + (_right * farHalfWidth);
|
||||
_farBottomLeft = _farCenter - (_up * farHalfHeight) - (_right * farHalfWidth);
|
||||
_farBottomRight = _farCenter - (_up * farHalfHeight) + (_right * farHalfWidth);
|
||||
|
||||
float nearHalfHeight = (_nearHeight * 0.5f);
|
||||
float nearHalfWidth = (_nearWidth * 0.5f);
|
||||
_nearCenter = _position+front * nearClip;
|
||||
_nearTopLeft = _nearCenter + (_up * nearHalfHeight) - (_right * nearHalfWidth);
|
||||
_nearTopRight = _nearCenter + (_up * nearHalfHeight) + (_right * nearHalfWidth);
|
||||
_nearBottomLeft = _nearCenter - (_up * nearHalfHeight) - (_right * nearHalfWidth);
|
||||
_nearBottomRight = _nearCenter - (_up * nearHalfHeight) + (_right * nearHalfWidth);
|
||||
|
||||
// compute the six planes
|
||||
// The planes are defined such that the normal points towards the inside of the view frustum.
|
||||
// Testing if an object is inside the view frustum is performed by computing on which side of
|
||||
// the plane the object resides. This can be done computing the signed distance from the point
|
||||
// to the plane. If it is on the side that the normal is pointing, i.e. the signed distance
|
||||
// is positive, then it is on the right side of the respective plane. If an object is on the
|
||||
// right side of all six planes then the object is inside the frustum.
|
||||
|
||||
// the function set3Points assumes that the points are given in counter clockwise order, assume you
|
||||
// are inside the frustum, facing the plane. Start with any point, and go counter clockwise for
|
||||
// three consecutive points
|
||||
|
||||
_planes[TOP_PLANE ].set3Points(_nearTopRight,_nearTopLeft,_farTopLeft);
|
||||
_planes[BOTTOM_PLANE].set3Points(_nearBottomLeft,_nearBottomRight,_farBottomRight);
|
||||
_planes[LEFT_PLANE ].set3Points(_nearBottomLeft,_farBottomLeft,_farTopLeft);
|
||||
_planes[RIGHT_PLANE ].set3Points(_farBottomRight,_nearBottomRight,_nearTopRight);
|
||||
_planes[NEAR_PLANE ].set3Points(_nearBottomRight,_nearBottomLeft,_nearTopLeft);
|
||||
_planes[FAR_PLANE ].set3Points(_farBottomLeft,_farBottomRight,_farTopRight);
|
||||
// the function set3Points assumes that the points are given in counter clockwise order, assume you
|
||||
// are inside the frustum, facing the plane. Start with any point, and go counter clockwise for
|
||||
// three consecutive points
|
||||
|
||||
_planes[TOP_PLANE ].set3Points(_nearTopRight,_nearTopLeft,_farTopLeft);
|
||||
_planes[BOTTOM_PLANE].set3Points(_nearBottomLeft,_nearBottomRight,_farBottomRight);
|
||||
_planes[LEFT_PLANE ].set3Points(_nearBottomLeft,_farBottomLeft,_farTopLeft);
|
||||
_planes[RIGHT_PLANE ].set3Points(_farBottomRight,_nearBottomRight,_nearTopRight);
|
||||
_planes[NEAR_PLANE ].set3Points(_nearBottomRight,_nearBottomLeft,_nearTopLeft);
|
||||
_planes[FAR_PLANE ].set3Points(_farBottomLeft,_farBottomRight,_farTopRight);
|
||||
|
||||
}
|
||||
|
||||
|
@ -113,34 +116,35 @@ void ViewFrustum::dump() const {
|
|||
printLog("right.x=%f, right.y=%f, right.z=%f\n", _right.x, _right.y, _right.z);
|
||||
|
||||
printLog("farDist=%f\n", _farClip);
|
||||
printLog("farHeight=%f\n", _farHeight);
|
||||
printLog("farWidth=%f\n", _farWidth);
|
||||
|
||||
printLog("nearDist=%f\n", _nearClip);
|
||||
printLog("nearHeight=%f\n", _nearHeight);
|
||||
printLog("nearWidth=%f\n", _nearWidth);
|
||||
|
||||
printLog("eyeOffsetPosition=%f,%f,%f\n", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z);
|
||||
|
||||
printLog("eyeOffsetOrientation=%f,%f,%f,%f\n", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y,
|
||||
_eyeOffsetOrientation.z, _eyeOffsetOrientation.w);
|
||||
|
||||
printLog("farCenter.x=%f, farCenter.y=%f, farCenter.z=%f\n",
|
||||
_farCenter.x, _farCenter.y, _farCenter.z);
|
||||
_farCenter.x, _farCenter.y, _farCenter.z);
|
||||
printLog("farTopLeft.x=%f, farTopLeft.y=%f, farTopLeft.z=%f\n",
|
||||
_farTopLeft.x, _farTopLeft.y, _farTopLeft.z);
|
||||
_farTopLeft.x, _farTopLeft.y, _farTopLeft.z);
|
||||
printLog("farTopRight.x=%f, farTopRight.y=%f, farTopRight.z=%f\n",
|
||||
_farTopRight.x, _farTopRight.y, _farTopRight.z);
|
||||
_farTopRight.x, _farTopRight.y, _farTopRight.z);
|
||||
printLog("farBottomLeft.x=%f, farBottomLeft.y=%f, farBottomLeft.z=%f\n",
|
||||
_farBottomLeft.x, _farBottomLeft.y, _farBottomLeft.z);
|
||||
_farBottomLeft.x, _farBottomLeft.y, _farBottomLeft.z);
|
||||
printLog("farBottomRight.x=%f, farBottomRight.y=%f, farBottomRight.z=%f\n",
|
||||
_farBottomRight.x, _farBottomRight.y, _farBottomRight.z);
|
||||
_farBottomRight.x, _farBottomRight.y, _farBottomRight.z);
|
||||
|
||||
printLog("nearCenter.x=%f, nearCenter.y=%f, nearCenter.z=%f\n",
|
||||
_nearCenter.x, _nearCenter.y, _nearCenter.z);
|
||||
_nearCenter.x, _nearCenter.y, _nearCenter.z);
|
||||
printLog("nearTopLeft.x=%f, nearTopLeft.y=%f, nearTopLeft.z=%f\n",
|
||||
_nearTopLeft.x, _nearTopLeft.y, _nearTopLeft.z);
|
||||
_nearTopLeft.x, _nearTopLeft.y, _nearTopLeft.z);
|
||||
printLog("nearTopRight.x=%f, nearTopRight.y=%f, nearTopRight.z=%f\n",
|
||||
_nearTopRight.x, _nearTopRight.y, _nearTopRight.z);
|
||||
_nearTopRight.x, _nearTopRight.y, _nearTopRight.z);
|
||||
printLog("nearBottomLeft.x=%f, nearBottomLeft.y=%f, nearBottomLeft.z=%f\n",
|
||||
_nearBottomLeft.x, _nearBottomLeft.y, _nearBottomLeft.z);
|
||||
_nearBottomLeft.x, _nearBottomLeft.y, _nearBottomLeft.z);
|
||||
printLog("nearBottomRight.x=%f, nearBottomRight.y=%f, nearBottomRight.z=%f\n",
|
||||
_nearBottomRight.x, _nearBottomRight.y, _nearBottomRight.z);
|
||||
_nearBottomRight.x, _nearBottomRight.y, _nearBottomRight.z);
|
||||
}
|
||||
|
||||
|
||||
|
@ -163,30 +167,30 @@ ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const
|
|||
//printf("ViewFrustum::pointInFrustum() point=%f,%f,%f\n",point.x,point.y,point.z);
|
||||
//dump();
|
||||
|
||||
ViewFrustum::location result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
float distance = _planes[i].distance(point);
|
||||
ViewFrustum::location result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
float distance = _planes[i].distance(point);
|
||||
|
||||
//printf("plane[%d] %s -- distance=%f \n",i,debugPlaneName(i),distance);
|
||||
|
||||
if (distance < 0) {
|
||||
return OUTSIDE;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
|
||||
if (distance < 0) {
|
||||
return OUTSIDE;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
|
||||
ViewFrustum::location result = INSIDE;
|
||||
float distance;
|
||||
for(int i=0; i < 6; i++) {
|
||||
distance = _planes[i].distance(center);
|
||||
if (distance < -radius)
|
||||
return OUTSIDE;
|
||||
else if (distance < radius)
|
||||
result = INTERSECT;
|
||||
}
|
||||
return(result);
|
||||
ViewFrustum::location result = INSIDE;
|
||||
float distance;
|
||||
for(int i=0; i < 6; i++) {
|
||||
distance = _planes[i].distance(center);
|
||||
if (distance < -radius)
|
||||
return OUTSIDE;
|
||||
else if (distance < radius)
|
||||
result = INTERSECT;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,8 +198,8 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
|||
|
||||
//printf("ViewFrustum::boxInFrustum() box.corner=%f,%f,%f x=%f\n",
|
||||
// box.getCorner().x,box.getCorner().y,box.getCorner().z,box.getSize().x);
|
||||
ViewFrustum::location result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
ViewFrustum::location result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
|
||||
//printf("plane[%d] -- point(%f,%f,%f) normal(%f,%f,%f) d=%f \n",i,
|
||||
// _planes[i].getPoint().x, _planes[i].getPoint().y, _planes[i].getPoint().z,
|
||||
|
@ -203,26 +207,26 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
|||
// _planes[i].getDCoefficient()
|
||||
//);
|
||||
|
||||
glm::vec3 normal = _planes[i].getNormal();
|
||||
glm::vec3 boxVertexP = box.getVertexP(normal);
|
||||
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
||||
glm::vec3 normal = _planes[i].getNormal();
|
||||
glm::vec3 boxVertexP = box.getVertexP(normal);
|
||||
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
||||
|
||||
glm::vec3 boxVertexN = box.getVertexN(normal);
|
||||
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
||||
|
||||
glm::vec3 boxVertexN = box.getVertexN(normal);
|
||||
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
||||
|
||||
//printf("plane[%d] normal=(%f,%f,%f) bVertexP=(%f,%f,%f) planeToBoxVertexPDistance=%f boxVertexN=(%f,%f,%f) planeToBoxVertexNDistance=%f\n",i,
|
||||
// normal.x,normal.y,normal.z,
|
||||
// boxVertexP.x,boxVertexP.y,boxVertexP.z,planeToBoxVertexPDistance,
|
||||
// boxVertexN.x,boxVertexN.y,boxVertexN.z,planeToBoxVertexNDistance
|
||||
// );
|
||||
|
||||
if (planeToBoxVertexPDistance < 0) {
|
||||
return OUTSIDE;
|
||||
} else if (planeToBoxVertexNDistance < 0) {
|
||||
result = INTERSECT;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
if (planeToBoxVertexPDistance < 0) {
|
||||
return OUTSIDE;
|
||||
} else if (planeToBoxVertexNDistance < 0) {
|
||||
result = INTERSECT;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
bool ViewFrustum::matches(const ViewFrustum& compareTo) const {
|
||||
|
@ -234,7 +238,9 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo) const {
|
|||
compareTo._fieldOfView == _fieldOfView &&
|
||||
compareTo._aspectRatio == _aspectRatio &&
|
||||
compareTo._nearClip == _nearClip &&
|
||||
compareTo._farClip == _farClip;
|
||||
compareTo._farClip == _farClip &&
|
||||
compareTo._eyeOffsetPosition == _eyeOffsetPosition &&
|
||||
compareTo._eyeOffsetOrientation == _eyeOffsetOrientation;
|
||||
|
||||
if (!result && debug) {
|
||||
printLog("ViewFrustum::matches()... result=%s\n", (result ? "yes" : "no"));
|
||||
|
@ -266,6 +272,15 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo) const {
|
|||
printLog("%s -- compareTo._farClip=%f _farClip=%f\n",
|
||||
(compareTo._farClip == _farClip ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._farClip, _farClip);
|
||||
printLog("%s -- compareTo._eyeOffsetPosition=%f,%f,%f _eyeOffsetPosition=%f,%f,%f\n",
|
||||
(compareTo._eyeOffsetPosition == _eyeOffsetPosition ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._eyeOffsetPosition.x, compareTo._eyeOffsetPosition.y, compareTo._eyeOffsetPosition.z,
|
||||
_eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z);
|
||||
printLog("%s -- compareTo._eyeOffsetOrientation=%f,%f,%f,%f _eyeOffsetOrientation=%f,%f,%f,%f\n",
|
||||
(compareTo._eyeOffsetOrientation == _eyeOffsetOrientation ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._eyeOffsetOrientation.x, compareTo._eyeOffsetOrientation.y,
|
||||
compareTo._eyeOffsetOrientation.z, compareTo._eyeOffsetOrientation.w,
|
||||
_eyeOffsetOrientation.x, _eyeOffsetOrientation.y, _eyeOffsetOrientation.z, _eyeOffsetOrientation.w);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -277,6 +292,51 @@ void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3&
|
|||
direction = glm::normalize(origin - _position);
|
||||
}
|
||||
|
||||
void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near, float& far,
|
||||
glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
|
||||
// compute our dimensions the usual way
|
||||
float hheight = _nearClip * tanf(_fieldOfView * 0.5f * PI_OVER_180);
|
||||
float hwidth = _aspectRatio * hheight;
|
||||
|
||||
// get our frustum corners in view space
|
||||
glm::mat4 eyeMatrix = glm::mat4_cast(glm::inverse(_eyeOffsetOrientation)) * glm::translate(-_eyeOffsetPosition);
|
||||
glm::vec4 corners[8];
|
||||
float farScale = _farClip / _nearClip;
|
||||
corners[0] = eyeMatrix * glm::vec4(-hwidth, -hheight, -_nearClip, 1.0f);
|
||||
corners[1] = eyeMatrix * glm::vec4(hwidth, -hheight, -_nearClip, 1.0f);
|
||||
corners[2] = eyeMatrix * glm::vec4(hwidth, hheight, -_nearClip, 1.0f);
|
||||
corners[3] = eyeMatrix * glm::vec4(-hwidth, hheight, -_nearClip, 1.0f);
|
||||
corners[4] = eyeMatrix * glm::vec4(-hwidth * farScale, -hheight * farScale, -_farClip, 1.0f);
|
||||
corners[5] = eyeMatrix * glm::vec4(hwidth * farScale, -hheight * farScale, -_farClip, 1.0f);
|
||||
corners[6] = eyeMatrix * glm::vec4(hwidth * farScale, hheight * farScale, -_farClip, 1.0f);
|
||||
corners[7] = eyeMatrix * glm::vec4(-hwidth * farScale, hheight * farScale, -_farClip, 1.0f);
|
||||
|
||||
// find the minimum and maximum z values, which will be our near and far clip distances
|
||||
near = FLT_MAX;
|
||||
far = -FLT_MAX;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
near = min(near, -corners[i].z);
|
||||
far = max(far, -corners[i].z);
|
||||
}
|
||||
|
||||
// get the near/far normal and use it to find the clip planes
|
||||
glm::vec4 normal = eyeMatrix * glm::vec4(0.0f, 0.0f, 1.0f, 0.0f);
|
||||
nearClipPlane = glm::vec4(-normal.x, -normal.y, -normal.z, glm::dot(normal, corners[0]));
|
||||
farClipPlane = glm::vec4(normal.x, normal.y, normal.z, -glm::dot(normal, corners[4]));
|
||||
|
||||
// get the extents at Z = -near
|
||||
left = FLT_MAX;
|
||||
right = -FLT_MAX;
|
||||
bottom = FLT_MAX;
|
||||
top = -FLT_MAX;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glm::vec4 intersection = corners[i] * (-near / corners[i].z);
|
||||
left = min(left, intersection.x);
|
||||
right = max(right, intersection.x);
|
||||
bottom = min(bottom, intersection.y);
|
||||
top = max(top, intersection.y);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewFrustum::printDebugDetails() const {
|
||||
printLog("ViewFrustum::printDebugDetails()... \n");
|
||||
|
@ -288,5 +348,8 @@ void ViewFrustum::printDebugDetails() const {
|
|||
printLog("_aspectRatio=%f\n", _aspectRatio);
|
||||
printLog("_nearClip=%f\n", _nearClip);
|
||||
printLog("_farClip=%f\n", _farClip);
|
||||
printLog("_eyeOffsetPosition=%f,%f,%f\n", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z );
|
||||
printLog("_eyeOffsetOrientation=%f,%f,%f,%f\n", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y, _eyeOffsetOrientation.z,
|
||||
_eyeOffsetOrientation.w );
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define __hifi__ViewFrustum__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include "Plane.h"
|
||||
#include "AABox.h"
|
||||
|
||||
|
@ -29,12 +30,14 @@ private:
|
|||
float _aspectRatio;
|
||||
float _nearClip;
|
||||
float _farClip;
|
||||
glm::vec3 _eyeOffsetPosition;
|
||||
glm::quat _eyeOffsetOrientation;
|
||||
|
||||
// Calculated values
|
||||
float _nearHeight;
|
||||
float _nearWidth;
|
||||
float _farHeight;
|
||||
float _farWidth;
|
||||
glm::vec3 _offsetPosition;
|
||||
glm::vec3 _offsetDirection;
|
||||
glm::vec3 _offsetUp;
|
||||
glm::vec3 _offsetRight;
|
||||
glm::vec3 _farCenter;
|
||||
glm::vec3 _farTopLeft;
|
||||
glm::vec3 _farTopRight;
|
||||
|
@ -63,16 +66,26 @@ public:
|
|||
const glm::vec3& getRight() const { return _right; };
|
||||
|
||||
// setters for lens attributes
|
||||
void setFieldOfView ( float f ) { _fieldOfView = f; }
|
||||
void setAspectRatio ( float a ) { _aspectRatio = a; }
|
||||
void setNearClip ( float n ) { _nearClip = n; }
|
||||
void setFarClip ( float f ) { _farClip = f; }
|
||||
void setFieldOfView ( float f ) { _fieldOfView = f; }
|
||||
void setAspectRatio ( float a ) { _aspectRatio = a; }
|
||||
void setNearClip ( float n ) { _nearClip = n; }
|
||||
void setFarClip ( float f ) { _farClip = f; }
|
||||
void setEyeOffsetPosition (const glm::vec3& p) { _eyeOffsetPosition = p; }
|
||||
void setEyeOffsetOrientation (const glm::quat& o) { _eyeOffsetOrientation = o; }
|
||||
|
||||
|
||||
// getters for lens attributes
|
||||
float getFieldOfView() const { return _fieldOfView; };
|
||||
float getAspectRatio() const { return _aspectRatio; };
|
||||
float getNearClip() const { return _nearClip; };
|
||||
float getFarClip() const { return _farClip; };
|
||||
float getFieldOfView() const { return _fieldOfView; };
|
||||
float getAspectRatio() const { return _aspectRatio; };
|
||||
float getNearClip() const { return _nearClip; };
|
||||
float getFarClip() const { return _farClip; };
|
||||
const glm::vec3& getEyeOffsetPosition() const { return _eyeOffsetPosition; };
|
||||
const glm::quat& getEyeOffsetOrientation() const { return _eyeOffsetOrientation;};
|
||||
|
||||
const glm::vec3& getOffsetPosition() const { return _offsetPosition; };
|
||||
const glm::vec3& getOffsetDirection() const { return _offsetDirection;};
|
||||
const glm::vec3& getOffsetUp() const { return _offsetUp; };
|
||||
const glm::vec3& getOffsetRight() const { return _offsetRight; };
|
||||
|
||||
const glm::vec3& getFarCenter() const { return _farCenter; };
|
||||
const glm::vec3& getFarTopLeft() const { return _farTopLeft; };
|
||||
|
@ -101,8 +114,12 @@ public:
|
|||
// some frustum comparisons
|
||||
bool matches(const ViewFrustum& compareTo) const;
|
||||
bool matches(const ViewFrustum* compareTo) const { return matches(*compareTo); };
|
||||
|
||||
void computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const;
|
||||
|
||||
void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near, float& far,
|
||||
glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
|
||||
|
||||
void printDebugDetails() const;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue