diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 30b9ef205b..856b6a1c00 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -258,11 +258,11 @@ bool OctreeQueryNode::updateCurrentViewFrustum() { float originalFOV = getCameraFov(); float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND; - newestViewFrustum.setFieldOfView(wideFOV); // hack - newestViewFrustum.setAspectRatio(getCameraAspectRatio()); - newestViewFrustum.setNearClip(getCameraNearClip()); - newestViewFrustum.setFarClip(getCameraFarClip()); - newestViewFrustum.setEyeOffsetPosition(getCameraEyeOffsetPosition()); + newestViewFrustum.setProjection(glm::perspective( + glm::radians(wideFOV), // hack + getCameraAspectRatio(), + getCameraNearClip(), + getCameraFarClip())); // if there has been a change, then recalculate if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) { diff --git a/examples/example/games/airHockey.js b/examples/example/games/airHockey.js index abacc05a9b..a703f379bc 100644 --- a/examples/example/games/airHockey.js +++ b/examples/example/games/airHockey.js @@ -392,6 +392,13 @@ function scriptEnding() { Overlays.deleteOverlay(spawnButton); Overlays.deleteOverlay(deleteButton); + + //We only want to delete everything if we've spawned them first. + //Otherwise we'll throw an error- if we have edge1 we've spawned them all. + if(!edge1){ + return; + } + Entities.editEntity(edge1, { locked: false }); @@ -418,7 +425,6 @@ function scriptEnding() { }); - Entities.deleteEntity(edge1); Entities.deleteEntity(edge2); Entities.deleteEntity(edge3a); diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index de8bbbb80b..00a4e7f61d 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -23,6 +23,8 @@ const GRAVITY = {x: 0, y: -2.8, z: 0}; const DENSITY = 2000; const DAMPING_FACTOR = 0.98; const ANGULAR_DAMPING_FACTOR = 0.8; +const FRICTION = 0.99; +const RESTITUTION = 0.0; const SPAWN_DISTANCE = 3; const BLOCK_YAW_OFFSET = 45; const BUTTON_DIMENSIONS = {width: 49, height: 49}; @@ -110,6 +112,8 @@ function resetBlocks() { rotation: Quat.multiply(layerRotation, offsetRot), collisionsWillMove: true, damping: DAMPING_FACTOR, + restitution: RESTITUTION, + friction: FRICTION, angularDamping: ANGULAR_DAMPING_FACTOR, gravity: GRAVITY, density: DENSITY diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 0e3494bff8..a2ff71d010 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -284,7 +284,7 @@ var elModelOriginalTextures = document.getElementById("property-model-original-textures"); var elWebSections = document.querySelectorAll(".web-section"); - allSections.push(elModelSections); + allSections.push(elWebSections); var elWebSourceURL = document.getElementById("property-web-source-url"); var elTextSections = document.querySelectorAll(".text-section"); @@ -481,7 +481,7 @@ elModelTextures.value = properties.textures; elModelOriginalTextures.value = properties.originalTextures; } else if (properties.type == "Web") { - for (var i = 0; i < elTextSections.length; i++) { + for (var i = 0; i < elWebSections.length; i++) { elWebSections[i].style.display = 'block'; } diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index f3ea18aef3..1790767bec 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1213,7 +1213,7 @@ SelectionDisplay = (function () { rotation: rotation, visible: true, }); - var distance = (properties.dimensions.z / 2) * Math.tan(properties.cutoff * (Math.PI / 180)); + var distance = (properties.dimensions.z / 2) * Math.sin(properties.cutoff * (Math.PI / 180)); Overlays.editOverlay(grabberSpotLightL, { position: EdgeNL, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 37ee116f40..8e23dd8f38 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -19,6 +19,7 @@ #include #include #include +#include // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" @@ -339,7 +340,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _aboutToQuit(false), _notifiedPacketVersionMismatchThisDomain(false), _domainConnectionRefusals(QList()), - _maxOctreePPS(maxOctreePacketsPerSecond.get()) + _maxOctreePPS(maxOctreePacketsPerSecond.get()), + _lastFaceTrackerUpdate(0) { setInstance(this); #ifdef Q_OS_WIN @@ -974,12 +976,11 @@ void Application::showEditEntitiesHelp() { void Application::resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size) { if (OculusManager::isConnected()) { - OculusManager::configureCamera(camera, size.x, size.y); + OculusManager::configureCamera(camera); } else if (TV3DManager::isConnected()) { TV3DManager::configureCamera(camera, size.x, size.y); } else { - camera.setAspectRatio((float)size.x / size.y); - camera.setFieldOfView(_fieldOfView.get()); + camera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), (float)size.x / size.y, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); } } @@ -993,7 +994,7 @@ void Application::resizeGL() { renderSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); } if (_renderResolution == toGlm(renderSize)) { - return; + return; } _renderResolution = toGlm(renderSize); @@ -1020,25 +1021,15 @@ void Application::updateProjectionMatrix() { } void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); + _projectionMatrix = camera.getProjection(); - float left, right, bottom, top, nearVal, farVal; - glm::vec4 nearClipPlane, farClipPlane; + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(glm::value_ptr(_projectionMatrix)); // Tell our viewFrustum about this change, using the application camera if (updateViewFrustum) { loadViewFrustum(camera, _viewFrustum); - _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - } else { - ViewFrustum tempViewFrustum; - loadViewFrustum(camera, tempViewFrustum); - tempViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - } - glFrustum(left, right, bottom, top, nearVal, farVal); - - // save matrix - glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat*)&_projectionMatrix); + } glMatrixMode(GL_MODELVIEW); } @@ -1259,6 +1250,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } break; +#if 0 case Qt::Key_I: if (isShifted) { _myCamera.setEyeOffsetOrientation(glm::normalize( @@ -1323,6 +1315,8 @@ void Application::keyPressEvent(QKeyEvent* event) { } updateProjectionMatrix(); break; +#endif + case Qt::Key_H: if (isShifted) { Menu::getInstance()->triggerOption(MenuOption::Mirror); @@ -2413,7 +2407,27 @@ void Application::update(float deltaTime) { FaceTracker* tracker = getActiveFaceTracker(); if (tracker && !tracker->isMuted()) { tracker->update(deltaTime); + + // Auto-mute microphone after losing face tracking? + if (tracker->isTracking()) { + _lastFaceTrackerUpdate = usecTimestampNow(); + } else { + const quint64 MUTE_MICROPHONE_AFTER_USECS = 5000000; //5 secs + Menu* menu = Menu::getInstance(); + if (menu->isOptionChecked(MenuOption::AutoMuteAudio) && !menu->isOptionChecked(MenuOption::MuteAudio)) { + if (_lastFaceTrackerUpdate > 0 + && ((usecTimestampNow() - _lastFaceTrackerUpdate) > MUTE_MICROPHONE_AFTER_USECS)) { + menu->triggerOption(MenuOption::MuteAudio); + _lastFaceTrackerUpdate = 0; + } + } else { + _lastFaceTrackerUpdate = 0; + } + } + } else { + _lastFaceTrackerUpdate = 0; } + SixenseManager::getInstance().update(deltaTime); JoystickScriptingInterface::getInstance().update(); } @@ -2461,7 +2475,6 @@ void Application::update(float deltaTime) { if (_physicsEngine.hasOutgoingChanges()) { _entitySimulation.lock(); _entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID()); - _entitySimulation.handleCollisionEvents(_physicsEngine.getCollisionEvents()); _entitySimulation.unlock(); _physicsEngine.dumpStatsIfNecessary(); } @@ -2469,9 +2482,11 @@ void Application::update(float deltaTime) { if (!_aboutToQuit) { PerformanceTimer perfTimer("entities"); - // NOTE: the _entities.update() call below will wait for lock + // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk deadlock.) + _entitySimulation.handleCollisionEvents(_physicsEngine.getCollisionEvents()); + // NOTE: the _entities.update() call below will wait for lock // and will simulate entity motion (the EntityTree has been given an EntitySimulation). - _entities.update(); // update the models... + _entities.update(); // update the models... } { @@ -2641,7 +2656,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node _octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio()); _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); - _octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); + _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); auto lodManager = DependencyManager::get(); _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); @@ -2845,25 +2860,11 @@ QRect Application::getDesirableApplicationGeometry() { // void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { // We will use these below, from either the camera or head vectors calculated above - glm::vec3 position(camera.getPosition()); - float fov = camera.getFieldOfView(); // degrees - float nearClip = camera.getNearClip(); - float farClip = camera.getFarClip(); - float aspectRatio = camera.getAspectRatio(); - - glm::quat rotation = camera.getRotation(); + viewFrustum.setProjection(camera.getProjection()); // Set the viewFrustum up with the correct position and orientation of the camera - viewFrustum.setPosition(position); - viewFrustum.setOrientation(rotation); - - // Also make sure it's got the correct lens details from the camera - viewFrustum.setAspectRatio(aspectRatio); - viewFrustum.setFieldOfView(fov); // degrees - viewFrustum.setNearClip(nearClip); - viewFrustum.setFarClip(farClip); - viewFrustum.setEyeOffsetPosition(camera.getEyeOffsetPosition()); - viewFrustum.setEyeOffsetOrientation(camera.getEyeOffsetOrientation()); + viewFrustum.setPosition(camera.getPosition()); + viewFrustum.setOrientation(camera.getRotation()); // Ask the ViewFrustum class to calculate our corners viewFrustum.calculate(); @@ -2964,13 +2965,7 @@ void Application::updateShadowMap() { glm::vec3 shadowFrustumCenter = rotation * ((minima + maxima) * 0.5f); _shadowViewFrustum.setPosition(shadowFrustumCenter); _shadowViewFrustum.setOrientation(rotation); - _shadowViewFrustum.setOrthographic(true); - _shadowViewFrustum.setWidth(maxima.x - minima.x); - _shadowViewFrustum.setHeight(maxima.y - minima.y); - _shadowViewFrustum.setNearClip(minima.z); - _shadowViewFrustum.setFarClip(maxima.z); - _shadowViewFrustum.setEyeOffsetPosition(glm::vec3()); - _shadowViewFrustum.setEyeOffsetOrientation(glm::quat()); + _shadowViewFrustum.setProjection(glm::ortho(minima.x, maxima.x, minima.y, maxima.y, minima.z, maxima.z)); _shadowViewFrustum.calculate(); glMatrixMode(GL_PROJECTION); @@ -3168,12 +3163,6 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs glFrontFace(GL_CCW); } - glm::vec3 eyeOffsetPos = theCamera.getEyeOffsetPosition(); - glm::quat eyeOffsetOrient = theCamera.getEyeOffsetOrientation(); - glm::vec3 eyeOffsetAxis = glm::axis(eyeOffsetOrient); - glRotatef(-glm::degrees(glm::angle(eyeOffsetOrient)), eyeOffsetAxis.x, eyeOffsetAxis.y, eyeOffsetAxis.z); - glTranslatef(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z); - // transform view according to theCamera // could be myCamera (if in normal mode) // or could be viewFrustumOffsetCamera if in offset mode @@ -3191,8 +3180,6 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs Transform viewTransform; viewTransform.setTranslation(theCamera.getPosition()); viewTransform.setRotation(rotation); - viewTransform.postTranslate(eyeOffsetPos); - viewTransform.postRotate(eyeOffsetOrient); if (theCamera.getMode() == CAMERA_MODE_MIRROR) { viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); } @@ -3286,7 +3273,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs // finally render the starfield if (hasStars) { - _stars.render(theCamera.getFieldOfView(), theCamera.getAspectRatio(), theCamera.getNearClip(), alpha); + _stars.render(_displayViewFrustum.getFieldOfView(), _displayViewFrustum.getAspectRatio(), _displayViewFrustum.getNearClip(), alpha); } // draw the sky dome @@ -3520,15 +3507,16 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { // Grab current viewport to reset it at the end int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); + float aspect = (float)region.width() / region.height(); + float fov = MIRROR_FIELD_OF_VIEW; // bool eyeRelativeCamera = false; if (billboard) { - _mirrorCamera.setFieldOfView(BILLBOARD_FIELD_OF_VIEW); // degees + fov = BILLBOARD_FIELD_OF_VIEW; // degees _mirrorCamera.setPosition(_myAvatar->getPosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { - _mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees _mirrorCamera.setPosition(_myAvatar->getChestPosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); @@ -3549,12 +3537,10 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further // investigated in order to adapt the technique while fixing the head rendering issue, // but the complexity of the hack suggests that a better approach - _mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); } - _mirrorCamera.setAspectRatio((float)region.width() / region.height()); - + _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); // set the bounds of rear mirror view diff --git a/interface/src/Application.h b/interface/src/Application.h index 83fc74aed4..2226c97b99 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -668,6 +668,8 @@ private: glm::uvec2 _renderResolution; int _maxOctreePPS = DEFAULT_MAX_OCTREE_PPS; + + quint64 _lastFaceTrackerUpdate; }; #endif // hifi_Application_h diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 1016d60ccf..e501b91dea 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -48,10 +48,7 @@ QString modeToString(CameraMode mode) { Camera::Camera() : _mode(CAMERA_MODE_THIRD_PERSON), _position(0.0f, 0.0f, 0.0f), - _fieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES), - _aspectRatio(16.0f/9.0f), - _nearClip(DEFAULT_NEAR_CLIP), // default - _farClip(DEFAULT_FAR_CLIP), // default + _projection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), 16.0f/9.0f, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)), _hmdPosition(), _hmdRotation(), _isKeepLookingAt(false), @@ -91,32 +88,13 @@ void Camera::setHmdRotation(const glm::quat& hmdRotation) { } } -float Camera::getFarClip() const { - return (_farClip < std::numeric_limits::max()) - ? _farClip - : std::numeric_limits::max() - 1; -} - void Camera::setMode(CameraMode mode) { _mode = mode; emit modeUpdated(modeToString(mode)); } - -void Camera::setFieldOfView(float f) { - _fieldOfView = f; -} - -void Camera::setAspectRatio(float a) { - _aspectRatio = a; -} - -void Camera::setNearClip(float n) { - _nearClip = n; -} - -void Camera::setFarClip(float f) { - _farClip = f; +void Camera::setProjection(const glm::mat4& projection) { + _projection = projection; } PickRay Camera::computePickRay(float x, float y) { diff --git a/interface/src/Camera.h b/interface/src/Camera.h index e06e12f7dc..fc1dbcaf00 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -44,35 +44,24 @@ public: void update( float deltaTime ); void setRotation(const glm::quat& rotation); + void setProjection(const glm::mat4 & projection); void setHmdPosition(const glm::vec3& hmdPosition); void setHmdRotation(const glm::quat& hmdRotation); - void setMode(CameraMode m); - void setFieldOfView(float f); - void setAspectRatio(float a); - void setNearClip(float n); - void setFarClip(float f); - void setEyeOffsetPosition(const glm::vec3& p) { _eyeOffsetPosition = p; } - void setEyeOffsetOrientation(const glm::quat& o) { _eyeOffsetOrientation = o; } glm::quat getRotation() const { return _rotation * _hmdRotation; } + const glm::mat4& getProjection() const { return _projection; } const glm::vec3& getHmdPosition() const { return _hmdPosition; } const glm::quat& getHmdRotation() const { return _hmdRotation; } - CameraMode getMode() const { return _mode; } - float getFieldOfView() const { return _fieldOfView; } - float getAspectRatio() const { return _aspectRatio; } - float getNearClip() const { return _nearClip; } - float getFarClip() const; - const glm::vec3& getEyeOffsetPosition() const { return _eyeOffsetPosition; } - const glm::quat& getEyeOffsetOrientation() const { return _eyeOffsetOrientation; } + public slots: QString getModeString() const; void setModeString(const QString& mode); glm::vec3 getPosition() const { return _position + _hmdPosition; } void setPosition(const glm::vec3& position); - + void setOrientation(const glm::quat& orientation) { setRotation(orientation); } glm::quat getOrientation() const { return getRotation(); } @@ -95,13 +84,8 @@ signals: private: CameraMode _mode; glm::vec3 _position; - float _fieldOfView; // degrees - float _aspectRatio; - float _nearClip; - float _farClip; - glm::vec3 _eyeOffsetPosition; - glm::quat _eyeOffsetOrientation; glm::quat _rotation; + glm::mat4 _projection; glm::vec3 _hmdPosition; glm::quat _hmdRotation; bool _isKeepLookingAt; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 95877b92c4..ddd581fe53 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -407,6 +407,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::MuteFaceTracking, Qt::CTRL | Qt::SHIFT | Qt::Key_F, true, // DDE face tracking is on by default qApp, SLOT(toggleFaceTrackerMute())); + addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::AutoMuteAudio, 0, true); #endif auto avatarManager = DependencyManager::get(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 435df47487..12ec312a56 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -147,6 +147,7 @@ namespace MenuOption { const QString AudioScopeTwentyFrames = "Twenty"; const QString AudioStats = "Audio Stats"; const QString AudioStatsShowInjectedStreams = "Audio Stats Show Injected Streams"; + const QString AutoMuteAudio = "Auto Mute Microphone"; const QString AvatarReceiveStats = "Show Receive Stats"; const QString BandwidthDetails = "Bandwidth Details"; const QString BinaryEyelidControl = "Binary Eyelid Control"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index fe4485b5db..e573110157 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -862,7 +862,7 @@ void MyAvatar::updateLookAtTargetAvatar() { glm::vec3 lookForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FRONT; glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); - float smallestAngleTo = glm::radians(Application::getInstance()->getCamera()->getFieldOfView()) / 2.0f; + float smallestAngleTo = glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES) / 2.0f; const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f; const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 30165624af..f37007894b 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -293,6 +293,10 @@ void DdeFaceTracker::reset() { } bool DdeFaceTracker::isActive() const { + return (_ddeProcess != NULL); +} + +bool DdeFaceTracker::isTracking() const { static const quint64 ACTIVE_TIMEOUT_USECS = 3000000; //3 secs return (usecTimestampNow() - _lastReceiveTimestamp < ACTIVE_TIMEOUT_USECS); } diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index c44de897e9..b3318d0cb0 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -33,7 +33,7 @@ public: virtual void reset(); virtual bool isActive() const; - virtual bool isTracking() const { return isActive(); } + virtual bool isTracking() const; float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); } float getRightBlink() const { return getBlendshapeCoefficient(_rightBlinkIndex); } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 99b196849f..3ceb2fd079 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -184,7 +184,7 @@ void OculusManager::connect() { if (!_camera) { _camera = new Camera; - configureCamera(*_camera, 0, 0); // no need to use screen dimensions; they're ignored + configureCamera(*_camera); // no need to use screen dimensions; they're ignored } #ifdef OVR_CLIENT_DISTORTION if (!_programInitialized) { @@ -449,9 +449,19 @@ void OculusManager::endFrameTiming() { } //Sets the camera FoV and aspect ratio -void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenHeight) { - camera.setAspectRatio(_renderTargetSize.w * 0.5f / _renderTargetSize.h); - camera.setFieldOfView(atan(_eyeFov[0].UpTan) * DEGREES_PER_RADIAN * 2.0f); +void OculusManager::configureCamera(Camera& camera) { + ovrFovPort fov; + if (_activeEye == ovrEye_Count) { + // When not rendering, provide a FOV encompasing both eyes + fov = _eyeFov[0]; + fov.RightTan = _eyeFov[1].RightTan; + } else { + // When rendering, provide the exact FOV + fov = _eyeFov[_activeEye]; + } + // Convert the FOV to the correct projection matrix + glm::mat4 projection = toGlm(ovrMatrix4f_Projection(fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded)); + camera.setProjection(projection); } //Displays everything for the oculus, frame timing must be active @@ -538,7 +548,8 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glm::quat orientation; glm::vec3 trackerPosition; - + auto deviceSize = qApp->getDeviceSize(); + ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); ovrVector3f ovrHeadPosition = ts.HeadPose.ThePose.Position; @@ -576,9 +587,11 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati whichCamera.setHmdPosition(trackerPosition); whichCamera.setHmdRotation(orientation); + // Update our camera to what the application camera is doing _camera->setRotation(whichCamera.getRotation()); _camera->setPosition(whichCamera.getPosition()); + configureCamera(*_camera); // Store the latest left and right eye render locations for things that need to know glm::vec3 thisEyePosition = position + trackerPosition + @@ -589,25 +602,17 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati _camera->update(1.0f / Application::getInstance()->getFps()); glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - const ovrFovPort& port = _eyeFov[_activeEye]; - float nearClip = whichCamera.getNearClip(), farClip = whichCamera.getFarClip(); - glFrustum(-nearClip * port.LeftTan, nearClip * port.RightTan, -nearClip * port.DownTan, - nearClip * port.UpTan, nearClip, farClip); - - ovrRecti & vp = _eyeTextures[eye].Header.RenderViewport; - vp.Size.h = _recommendedTexSize.h * _offscreenRenderScale; - vp.Size.w = _recommendedTexSize.w * _offscreenRenderScale; - - glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h); + glLoadMatrixf(glm::value_ptr(_camera->getProjection())); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - // HACK: instead of passing the stereo eye offset directly in the matrix, pass it in the camera offset - //glTranslatef(_eyeRenderDesc[eye].ViewAdjust.x, _eyeRenderDesc[eye].ViewAdjust.y, _eyeRenderDesc[eye].ViewAdjust.z); + ovrRecti & vp = _eyeTextures[eye].Header.RenderViewport; + vp.Size.h = _recommendedTexSize.h * _offscreenRenderScale; + vp.Size.w = _recommendedTexSize.w * _offscreenRenderScale; + + glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h); - _camera->setEyeOffsetPosition(glm::vec3(-_eyeRenderDesc[eye].HmdToEyeViewOffset.x, -_eyeRenderDesc[eye].HmdToEyeViewOffset.y, -_eyeRenderDesc[eye].HmdToEyeViewOffset.z)); qApp->displaySide(*_camera, false, RenderArgs::MONO); qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera); }); @@ -630,7 +635,6 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glPopMatrix(); // restore our normal viewport - auto deviceSize = qApp->getDeviceSize(); glViewport(0, 0, deviceSize.width(), deviceSize.height()); #if 0 @@ -644,16 +648,22 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati //Wait till time-warp to reduce latency ovr_WaitTillTime(_hmdFrameTiming.TimewarpPointSeconds); +#ifdef DEBUG_RENDER_WITHOUT_DISTORTION + auto fboSize = finalFbo->getSize(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); + glBlitFramebuffer( + 0, 0, fboSize.x, fboSize.y, + 0, 0, deviceSize.width(), deviceSize.height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); +#else //Clear the color buffer to ensure that there isnt any residual color //Left over from when OR was not connected. glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0))); - //Renders the distorted mesh onto the screen renderDistortionMesh(eyeRenderPose); - glBindTexture(GL_TEXTURE_2D, 0); +#endif glCanvas->swapBuffers(); #else diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index e41c6e8f9b..a6c3bbf4d5 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -60,7 +60,7 @@ public: static void beginFrameTiming(); static void endFrameTiming(); static bool allowSwap(); - static void configureCamera(Camera& camera, int screenWidth, int screenHeight); + static void configureCamera(Camera& camera); static void display(QGLWidget * glCanvas, const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera); static void reset(); diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 751a3d16bb..530b3d30d6 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -43,9 +43,9 @@ void TV3DManager::connect() { void TV3DManager::setFrustum(Camera& whichCamera) { const double DTR = 0.0174532925; // degree to radians const double IOD = 0.05; //intraocular distance - double fovy = whichCamera.getFieldOfView(); // field of view in y-axis - double nearZ = whichCamera.getNearClip(); // near clipping plane - double screenZ = Application::getInstance()->getViewFrustum()->getFocalLength(); // screen projection plane + double fovy = DEFAULT_FIELD_OF_VIEW_DEGREES; // field of view in y-axis + double nearZ = DEFAULT_NEAR_CLIP; // near clipping plane + double screenZ = 0.25f; // screen projection plane double top = nearZ * tan(DTR * fovy / 2.0); //sets top of frustum based on fovy and near clipping plane double right = _aspect * top; // sets right of frustum based on aspect ratio @@ -81,8 +81,8 @@ void TV3DManager::configureCamera(Camera& whichCamera, int screenWidth, int scre } void TV3DManager::display(Camera& whichCamera) { - double nearZ = whichCamera.getNearClip(); // near clipping plane - double farZ = whichCamera.getFarClip(); // far clipping plane + double nearZ = DEFAULT_NEAR_CLIP; // near clipping plane + double farZ = DEFAULT_FAR_CLIP; // far clipping plane // left eye portal int portalX = 0; @@ -95,7 +95,7 @@ void TV3DManager::display(Camera& whichCamera) { DependencyManager::get()->prepare(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - + Camera eyeCamera; eyeCamera.setRotation(whichCamera.getRotation()); eyeCamera.setPosition(whichCamera.getPosition()); @@ -118,7 +118,6 @@ void TV3DManager::display(Camera& whichCamera) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0)); qApp->displaySide(eyeCamera, false, RenderArgs::MONO); qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov); _activeEye = NULL; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index bacd6eb56e..e8627e655a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1174,8 +1174,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons if (!_tree || _shuttingDown) { return; } - // Don't respond to small continuous contacts. It causes deadlocks when locking the entityTree. - // Note that any entity script is likely to Entities.getEntityProperties(), which locks the tree. + // Don't respond to small continuous contacts. const float COLLISION_MINUMUM_PENETRATION = 0.005; if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) { return; @@ -1183,16 +1182,9 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons // See if we should play sounds EntityTree* entityTree = static_cast(_tree); - if (!entityTree->tryLockForRead()) { - // I don't know why this can happen, but if it does, - // the consequences are a deadlock, so bail. - qCDebug(entitiesrenderer) << "NOTICE: skipping collision type " << collision.type << " penetration " << glm::length(collision.penetration); - return; - } const QUuid& myNodeID = DependencyManager::get()->getSessionUUID(); playEntityCollisionSound(myNodeID, entityTree, idA, collision); playEntityCollisionSound(myNodeID, entityTree, idB, collision); - entityTree->unlock(); // And now the entity scripts QScriptValue entityScriptA = loadEntityScript(idA); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 3afd930ab0..bcbec4e67e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -25,7 +25,6 @@ #include "EntityTreeRenderer.h" -const int FIXED_FONT_POINT_SIZE = 40; const float DPI = 30.47; const float METERS_TO_INCHES = 39.3701; @@ -161,7 +160,6 @@ void RenderableWebEntityItem::render(RenderArgs* args) { glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - float alpha = 1.0f; static const glm::vec2 texMin(0); static const glm::vec2 texMax(1); glm::vec2 topLeft(-halfDimensions.x, -halfDimensions.y); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index fd3d0e9361..61b25fd7de 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -64,7 +64,7 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(isSpotlight, false), CONSTRUCT_PROPERTY(intensity, 1.0f), CONSTRUCT_PROPERTY(exponent, 0.0f), - CONSTRUCT_PROPERTY(cutoff, PI), + CONSTRUCT_PROPERTY(cutoff, ENTITY_ITEM_DEFAULT_CUTOFF), CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED), CONSTRUCT_PROPERTY(textures, ""), CONSTRUCT_PROPERTY(animationSettings, ""), diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index b33e6de1ac..c3dea91daa 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -64,6 +64,8 @@ const float ENTITY_ITEM_DEFAULT_FRICTION = 0.5f; const bool ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS = false; const bool ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE = false; +const float ENTITY_ITEM_DEFAULT_CUTOFF = PI / 2; + const QString ENTITY_ITEM_DEFAULT_NAME = QString(""); #endif // hifi_EntityItemPropertiesDefaults_h diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index a66cb56bd2..fa09c9bd60 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -46,7 +46,7 @@ void LightEntityItem::setDimensions(const glm::vec3& value) { // If we are a spotlight, treat the z value as our radius or length, and // recalculate the x/y dimensions to properly encapsulate the spotlight. const float length = value.z; - const float width = length * glm::tan(glm::radians(_cutoff)); + const float width = length * glm::sin(glm::radians(_cutoff)); _dimensions = glm::vec3(width, width, length); } else { float maxDimension = glm::max(value.x, value.y, value.z); @@ -73,7 +73,7 @@ void LightEntityItem::setIsSpotlight(bool value) { if (_isSpotlight) { const float length = _dimensions.z; - const float width = length * glm::tan(glm::radians(_cutoff)); + const float width = length * glm::sin(glm::radians(_cutoff)); _dimensions = glm::vec3(width, width, length); } else { float maxDimension = glm::max(_dimensions.x, _dimensions.y, _dimensions.z); @@ -89,7 +89,7 @@ void LightEntityItem::setCutoff(float value) { // If we are a spotlight, adjusting the cutoff will affect the area we encapsulate, // so update the dimensions to reflect this. const float length = _dimensions.z; - const float width = length * glm::tan(glm::radians(_cutoff)); + const float width = length * glm::sin(glm::radians(_cutoff)); _dimensions = glm::vec3(width, width, length); } } diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index 0da694833a..90840854ad 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -20,10 +20,7 @@ OctreeHeadlessViewer::OctreeHeadlessViewer() : _boundaryLevelAdjust(0), _maxPacketsPerSecond(DEFAULT_MAX_OCTREE_PPS) { - _viewFrustum.setFieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES); - _viewFrustum.setAspectRatio(DEFAULT_ASPECT_RATIO); - _viewFrustum.setNearClip(DEFAULT_NEAR_CLIP); - _viewFrustum.setFarClip(DEFAULT_FAR_CLIP); + _viewFrustum.setProjection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), DEFAULT_ASPECT_RATIO, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); } OctreeHeadlessViewer::~OctreeHeadlessViewer() { @@ -67,7 +64,8 @@ void OctreeHeadlessViewer::queryOctree() { _octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio()); _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); - _octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); + _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); + _octreeQuery.setOctreeSizeScale(getVoxelSizeScale()); _octreeQuery.setBoundaryLevelAdjust(getBoundaryLevelAdjust()); diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 11ed24799d..2694314b57 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include @@ -37,6 +37,36 @@ void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) { _direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f)); } +// Order cooresponds to the order defined in the BoxVertex enum. +static const glm::vec4 NDC_VALUES[8] = { + glm::vec4(-1, -1, -1, 1), + glm::vec4(1, -1, -1, 1), + glm::vec4(1, 1, -1, 1), + glm::vec4(-1, 1, -1, 1), + glm::vec4(-1, -1, 1, 1), + glm::vec4(1, -1, 1, 1), + glm::vec4(1, 1, 1, 1), + glm::vec4(-1, 1, 1, 1), +}; + +void ViewFrustum::setProjection(const glm::mat4& projection) { + _projection = projection; + _inverseProjection = glm::inverse(projection); + + // compute our dimensions the usual way + for (int i = 0; i < 8; ++i) { + _corners[i] = _inverseProjection * NDC_VALUES[i]; + _corners[i] /= _corners[i].w; + } + _nearClip = -_corners[BOTTOM_LEFT_NEAR].z; + _farClip = -_corners[BOTTOM_LEFT_FAR].z; + _aspectRatio = (_corners[TOP_RIGHT_NEAR].x - _corners[BOTTOM_LEFT_NEAR].x) / + (_corners[TOP_RIGHT_NEAR].y - _corners[BOTTOM_LEFT_NEAR].y); + glm::vec3 right = glm::normalize(glm::vec3(_corners[TOP_RIGHT_NEAR])); + glm::vec3 left = glm::normalize(glm::vec3(_corners[TOP_LEFT_NEAR])); + _fieldOfView = abs(glm::degrees(glm::angle(right, left))); +} + // ViewFrustum::calculateViewFrustum() // // Description: this will calculate the view frustum bounds for a given position and direction @@ -45,48 +75,16 @@ void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) { // http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/ // void ViewFrustum::calculate() { - if (_orthographic) { - calculateOrthographic(); - return; - } - - // 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)); + glm::mat4 worldMatrix = glm::translate(_position) * glm::mat4(glm::mat3(_right, _up, -_direction)); + glm::vec4 v; + for (int i = 0; i < 8; ++i) { + v = worldMatrix * _corners[i]; + v /= v.w; + _cornersWorld[i] = glm::vec3(v); + } // compute the six planes // The planes are defined such that the normal points towards the inside of the view frustum. @@ -99,73 +97,26 @@ void ViewFrustum::calculate() { // 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); + _planes[TOP_PLANE].set3Points(_cornersWorld[TOP_RIGHT_NEAR], _cornersWorld[TOP_LEFT_NEAR], _cornersWorld[TOP_LEFT_FAR]); + _planes[BOTTOM_PLANE].set3Points(_cornersWorld[BOTTOM_LEFT_NEAR], _cornersWorld[BOTTOM_RIGHT_NEAR], _cornersWorld[BOTTOM_RIGHT_FAR]); + _planes[LEFT_PLANE].set3Points(_cornersWorld[BOTTOM_LEFT_NEAR], _cornersWorld[BOTTOM_LEFT_FAR], _cornersWorld[TOP_LEFT_FAR]); + _planes[RIGHT_PLANE].set3Points(_cornersWorld[BOTTOM_RIGHT_FAR], _cornersWorld[BOTTOM_RIGHT_NEAR], _cornersWorld[TOP_RIGHT_FAR]); + _planes[NEAR_PLANE].set3Points(_cornersWorld[BOTTOM_RIGHT_NEAR], _cornersWorld[BOTTOM_LEFT_NEAR], _cornersWorld[TOP_LEFT_NEAR]); + _planes[FAR_PLANE].set3Points(_cornersWorld[BOTTOM_LEFT_FAR], _cornersWorld[BOTTOM_RIGHT_FAR], _cornersWorld[TOP_RIGHT_FAR]); // Also calculate our projection matrix in case people want to project points... // Projection matrix : Field of View, ratio, display range : near to far - const float CLIP_NUDGE = 1.0f; - float farClip = (_farClip != _nearClip) ? _farClip : _nearClip + CLIP_NUDGE; // don't allow near and far to be equal - glm::mat4 projection = glm::perspective(_fieldOfView, _aspectRatio, _nearClip, farClip); glm::vec3 lookAt = _position + _direction; glm::mat4 view = glm::lookAt(_position, lookAt, _up); // Our ModelViewProjection : multiplication of our 3 matrices (note: model is identity, so we can drop it) - _ourModelViewProjectionMatrix = projection * view; // Remember, matrix multiplication is the other way around + _ourModelViewProjectionMatrix = _projection * view; // Remember, matrix multiplication is the other way around // Set up our keyhole bounding box... glm::vec3 corner = _position - _keyholeRadius; _keyholeBoundingCube = AACube(corner,(_keyholeRadius * 2.0f)); } -void ViewFrustum::calculateOrthographic() { - float halfWidth = _width * 0.5f; - float halfHeight = _height * 0.5f; - - // find the corners of the view box in 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(-halfWidth, halfHeight, -_farClip, 1.0f)); - _farTopRight = glm::vec3(worldMatrix * glm::vec4(halfWidth, halfHeight, -_farClip, 1.0f)); - _farBottomLeft = glm::vec3(worldMatrix * glm::vec4(-halfWidth, -halfHeight, -_farClip, 1.0f)); - _farBottomRight = glm::vec3(worldMatrix * glm::vec4(halfWidth, -halfHeight, -_farClip, 1.0f)); - _nearTopLeft = glm::vec3(worldMatrix * glm::vec4(-halfWidth, halfHeight, -_nearClip, 1.0f)); - _nearTopRight = glm::vec3(worldMatrix * glm::vec4(halfWidth, halfHeight, -_nearClip, 1.0f)); - _nearBottomLeft = glm::vec3(worldMatrix * glm::vec4(-halfWidth, -halfHeight, -_nearClip, 1.0f)); - _nearBottomRight = glm::vec3(worldMatrix * glm::vec4(halfWidth, -halfHeight, -_nearClip, 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)); - - _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); - - // Also calculate our projection matrix in case people want to project points... - // Projection matrix : Field of View, ratio, display range : near to far - glm::mat4 projection = glm::ortho(-halfWidth, halfWidth, -halfHeight, halfHeight, _nearClip, _farClip); - glm::vec3 lookAt = _position + _direction; - glm::mat4 view = glm::lookAt(_position, lookAt, _up); - - // Our ModelViewProjection : multiplication of our 3 matrices (note: model is identity, so we can drop it) - _ourModelViewProjectionMatrix = projection * view; // Remember, matrix multiplication is the other way around - - // Set up our keyhole bounding box... - glm::vec3 corner = _position - _keyholeRadius; - _keyholeBoundingCube = AACube(corner, (_keyholeRadius * 2.0f)); -} - //enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; const char* ViewFrustum::debugPlaneName (int plane) const { switch (plane) { @@ -305,7 +256,6 @@ ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const return keyholeResult; // escape early will be the value from checking the keyhole } } - return regularResult; } @@ -429,9 +379,7 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const { testMatches(compareTo._aspectRatio, _aspectRatio) && testMatches(compareTo._nearClip, _nearClip) && testMatches(compareTo._farClip, _farClip) && - testMatches(compareTo._focalLength, _focalLength) && - testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition) && - testMatches(compareTo._eyeOffsetOrientation, _eyeOffsetOrientation); + testMatches(compareTo._focalLength, _focalLength); if (!result && debug) { qCDebug(octree, "ViewFrustum::matches()... result=%s", debug::valueOf(result)); @@ -466,15 +414,6 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const { qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f", (testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"), compareTo._focalLength, _focalLength); - qCDebug(octree, "%s -- compareTo._eyeOffsetPosition=%f,%f,%f _eyeOffsetPosition=%f,%f,%f", - (testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition) ? "MATCHES " : "NO MATCH"), - compareTo._eyeOffsetPosition.x, compareTo._eyeOffsetPosition.y, compareTo._eyeOffsetPosition.z, - _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z); - qCDebug(octree, "%s -- compareTo._eyeOffsetOrientation=%f,%f,%f,%f _eyeOffsetOrientation=%f,%f,%f,%f", - (testMatches(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; } @@ -485,9 +424,6 @@ bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const const float POSITION_SIMILAR_ENOUGH = 5.0f; // 5 meters float positionDistance = glm::distance(_position, compareTo._position); - const float EYEOFFSET_POSITION_SIMILAR_ENOUGH = 0.15f; // 0.15 meters - float eyeOffsetpositionDistance = glm::distance(_eyeOffsetPosition, compareTo._eyeOffsetPosition); - // Compute the angular distance between the two orientations const float ORIENTATION_SIMILAR_ENOUGH = 10.0f; // 10 degrees in any direction glm::quat dQOrientation = _orientation * glm::inverse(compareTo._orientation); @@ -496,23 +432,14 @@ bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const angleOrientation = 0.0f; } - glm::quat dQEyeOffsetOrientation = _eyeOffsetOrientation * glm::inverse(compareTo._eyeOffsetOrientation); - float angleEyeOffsetOrientation = compareTo._eyeOffsetOrientation == _eyeOffsetOrientation - ? 0.0f : glm::degrees(glm::angle(dQEyeOffsetOrientation)); - if (isNaN(angleEyeOffsetOrientation)) { - angleEyeOffsetOrientation = 0.0f; - } - bool result = - testMatches(0, positionDistance, POSITION_SIMILAR_ENOUGH) && - testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) && + testMatches(0, positionDistance, POSITION_SIMILAR_ENOUGH) && + testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) && testMatches(compareTo._fieldOfView, _fieldOfView) && testMatches(compareTo._aspectRatio, _aspectRatio) && testMatches(compareTo._nearClip, _nearClip) && testMatches(compareTo._farClip, _farClip) && - testMatches(compareTo._focalLength, _focalLength) && - testMatches(0, eyeOffsetpositionDistance, EYEOFFSET_POSITION_SIMILAR_ENOUGH) && - testMatches(0, angleEyeOffsetOrientation, ORIENTATION_SIMILAR_ENOUGH); + testMatches(compareTo._focalLength, _focalLength); if (!result && debug) { @@ -529,7 +456,7 @@ bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const qCDebug(octree, "%s -- angleOrientation=%f", (testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"), angleOrientation); - + qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f", (testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"), compareTo._fieldOfView, _fieldOfView); @@ -545,19 +472,6 @@ bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f", (testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"), compareTo._focalLength, _focalLength); - - qCDebug(octree, "%s -- compareTo._eyeOffsetPosition=%f,%f,%f _eyeOffsetPosition=%f,%f,%f", - (testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"), - compareTo._eyeOffsetPosition.x, compareTo._eyeOffsetPosition.y, compareTo._eyeOffsetPosition.z, - _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z); - - qCDebug(octree, "%s -- eyeOffsetpositionDistance=%f", - (testMatches(0,eyeOffsetpositionDistance, EYEOFFSET_POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"), - eyeOffsetpositionDistance); - - qCDebug(octree, "%s -- angleEyeOffsetOrientation=%f", - (testMatches(0, angleEyeOffsetOrientation, ORIENTATION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"), - angleEyeOffsetOrientation); } return result; } @@ -570,39 +484,19 @@ PickRay ViewFrustum::computePickRay(float x, float y) { } void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const { - origin = _nearTopLeft + x * (_nearTopRight - _nearTopLeft) + y * (_nearBottomLeft - _nearTopLeft); - direction = glm::normalize(origin - (_position + _orientation * _eyeOffsetPosition)); + origin = _cornersWorld[TOP_LEFT_NEAR] + x * (_cornersWorld[TOP_RIGHT_NEAR] - _cornersWorld[TOP_LEFT_NEAR]) + + y * (_cornersWorld[BOTTOM_LEFT_NEAR] - _cornersWorld[TOP_LEFT_NEAR]); + direction = glm::normalize(origin - _position); } void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearValue, float& farValue, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { - // compute our dimensions the usual way - float hheight = _nearClip * tanf(_fieldOfView * 0.5f * RADIANS_PER_DEGREE); - float hwidth = _aspectRatio * hheight; - if (isOrthographic()) { - hheight = getHeight(); - hwidth = getWidth(); - } - - // 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 nearValue = FLT_MAX; farValue = -FLT_MAX; for (int i = 0; i < 8; i++) { - nearValue = min(nearValue, -corners[i].z); - farValue = max(farValue, -corners[i].z); + nearValue = min(nearValue, -_corners[i].z); + farValue = max(farValue, -_corners[i].z); } // make sure the near clip isn't too small to be valid @@ -610,9 +504,9 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom nearValue = max(MIN_NEAR, nearValue); // 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])); + glm::vec4 normal = 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])); // compute the focal proportion (zero is near clip, one is far clip) float focalProportion = (_focalLength - _nearClip) / (_farClip - _nearClip); @@ -623,7 +517,7 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom bottom = FLT_MAX; top = -FLT_MAX; for (int i = 0; i < 4; i++) { - glm::vec4 corner = glm::mix(corners[i], corners[i + 4], focalProportion); + glm::vec4 corner = glm::mix(_corners[i], _corners[i + 4], focalProportion); glm::vec4 intersection = corner * (-nearValue / corner.z); left = min(left, intersection.x); right = max(right, intersection.x); @@ -644,9 +538,6 @@ void ViewFrustum::printDebugDetails() const { qCDebug(octree, "_nearClip=%f", _nearClip); qCDebug(octree, "_farClip=%f", _farClip); qCDebug(octree, "_focalLength=%f", _focalLength); - qCDebug(octree, "_eyeOffsetPosition=%f,%f,%f", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z ); - qCDebug(octree, "_eyeOffsetOrientation=%f,%f,%f,%f", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y, _eyeOffsetOrientation.z, - _eyeOffsetOrientation.w ); } glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const { @@ -846,20 +737,7 @@ float ViewFrustum::distanceToCamera(const glm::vec3& point) const { } void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { - if (isOrthographic()) { - glm::vec3 frustumCenter = glm::inverse( _orientation) * _position; - - proj = glm::ortho(frustumCenter.x -0.5f * getWidth(), - frustumCenter.x +0.5f * getWidth(), - frustumCenter.y -0.5f * getHeight(), - frustumCenter.y +0.5f * getHeight(), - -getFarClip(), -getNearClip()); - } else { - float left, right, bottom, top, near, far; - glm::vec4 clip0, clip1; - computeOffAxisFrustum(left, right, bottom, top, near, far, clip0, clip1); - proj = glm::perspective(glm::radians(getFieldOfView()), getAspectRatio(), getNearClip(), getFarClip()); - } + proj = _projection; } void ViewFrustum::evalViewTransform(Transform& view) const { diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 5b20126293..0422120e51 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -50,19 +50,11 @@ public: const glm::vec3& getRight() const { return _right; } // setters for lens attributes - void setOrthographic(bool orthographic) { _orthographic = orthographic; } - void setWidth(float width) { _width = width; } - void setHeight(float height) { _height = height; } - 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 setFocalLength(float length) { _focalLength = length; } - void setEyeOffsetPosition(const glm::vec3& p) { _eyeOffsetPosition = p; } - void setEyeOffsetOrientation(const glm::quat& o) { _eyeOffsetOrientation = o; } + void setProjection(const glm::mat4 & projection); + void getFocalLength(float focalLength) { _focalLength = focalLength; } // getters for lens attributes - bool isOrthographic() const { return _orthographic; } + const glm::mat4 getProjection() const { return _projection; }; float getWidth() const { return _width; } float getHeight() const { return _height; } float getFieldOfView() const { return _fieldOfView; } @@ -70,23 +62,16 @@ public: float getNearClip() const { return _nearClip; } float getFarClip() const { return _farClip; } float getFocalLength() const { return _focalLength; } - 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& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; } + const glm::vec3& getFarTopRight() const { return _cornersWorld[TOP_RIGHT_FAR]; } + const glm::vec3& getFarBottomLeft() const { return _cornersWorld[BOTTOM_LEFT_FAR]; } + const glm::vec3& getFarBottomRight() const { return _cornersWorld[BOTTOM_RIGHT_FAR]; } - const glm::vec3& getFarTopLeft() const { return _farTopLeft; } - const glm::vec3& getFarTopRight() const { return _farTopRight; } - const glm::vec3& getFarBottomLeft() const { return _farBottomLeft; } - const glm::vec3& getFarBottomRight() const { return _farBottomRight; } - - const glm::vec3& getNearTopLeft() const { return _nearTopLeft; } - const glm::vec3& getNearTopRight() const { return _nearTopRight; } - const glm::vec3& getNearBottomLeft() const { return _nearBottomLeft; } - const glm::vec3& getNearBottomRight() const { return _nearBottomRight; } + const glm::vec3& getNearTopLeft() const { return _cornersWorld[TOP_LEFT_NEAR]; } + const glm::vec3& getNearTopRight() const { return _cornersWorld[TOP_RIGHT_NEAR]; } + const glm::vec3& getNearBottomLeft() const { return _cornersWorld[BOTTOM_LEFT_NEAR]; } + const glm::vec3& getNearBottomRight() const { return _cornersWorld[BOTTOM_RIGHT_NEAR]; } // get/set for keyhole attribute void setKeyholeRadius(float keyholdRadius) { _keyholeRadius = keyholdRadius; } @@ -132,49 +117,33 @@ private: ViewFrustum::location cubeInKeyhole(const AACube& cube) const; ViewFrustum::location boxInKeyhole(const AABox& box) const; - void calculateOrthographic(); - // camera location/orientation attributes - glm::vec3 _position = glm::vec3(0.0f); // the position in world-frame - glm::quat _orientation = glm::quat(); + glm::vec3 _position; // the position in world-frame + glm::quat _orientation; + + // Lens attributes + glm::mat4 _projection; // calculated for orientation glm::vec3 _direction = IDENTITY_FRONT; glm::vec3 _up = IDENTITY_UP; glm::vec3 _right = IDENTITY_RIGHT; - // Lens attributes - bool _orthographic = false; + // keyhole attributes + float _keyholeRadius = DEFAULT_KEYHOLE_RADIUS; + AACube _keyholeBoundingCube; + + // Calculated values + glm::mat4 _inverseProjection; float _width = 1.0f; float _height = 1.0f; float _aspectRatio = 1.0f; float _nearClip = DEFAULT_NEAR_CLIP; float _farClip = DEFAULT_FAR_CLIP; float _focalLength = 0.25f; - glm::vec3 _eyeOffsetPosition = glm::vec3(0.0f); - glm::quat _eyeOffsetOrientation = glm::quat(); - - // in Degrees, doesn't apply to HMD like Oculus float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES; - - // keyhole attributes - float _keyholeRadius = DEFAULT_KEYHOLE_RADIUS; - AACube _keyholeBoundingCube; - - - // Calculated values - glm::vec3 _offsetPosition = glm::vec3(0.0f); - glm::vec3 _offsetDirection = glm::vec3(0.0f); - glm::vec3 _offsetUp = glm::vec3(0.0f); - glm::vec3 _offsetRight = glm::vec3(0.0f); - glm::vec3 _farTopLeft = glm::vec3(0.0f); - glm::vec3 _farTopRight = glm::vec3(0.0f); - glm::vec3 _farBottomLeft = glm::vec3(0.0f); - glm::vec3 _farBottomRight = glm::vec3(0.0f); - glm::vec3 _nearTopLeft = glm::vec3(0.0f); - glm::vec3 _nearTopRight = glm::vec3(0.0f); - glm::vec3 _nearBottomLeft = glm::vec3(0.0f); - glm::vec3 _nearBottomRight = glm::vec3(0.0f); + glm::vec4 _corners[8]; + glm::vec3 _cornersWorld[8]; enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; ::Plane _planes[6]; // How will this be used?