From d2d5132f7243e93e1fa0b2b650278daa64c02d3d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 7 Nov 2018 14:51:19 -0800 Subject: [PATCH] It's working! --- interface/src/Application.cpp | 47 ++++++++++++---------- interface/src/SecondaryCamera.cpp | 66 ++++++++++++++++++------------- interface/src/SecondaryCamera.h | 2 + 3 files changed, 67 insertions(+), 48 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a950030965..926df2943e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5585,32 +5585,39 @@ void Application::updateSecondaryCameraViewFrustum() { } ViewFrustum secondaryViewFrustum; - if (camera->portalProjection && !camera->attachedEntityId.isNull()) { + if (camera->portalProjection && !camera->attachedEntityId.isNull() && !camera->portalEntranceEntityId.isNull()) { auto entityScriptingInterface = DependencyManager::get(); - auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId); - glm::vec3 mirrorPropertiesPosition = entityProperties.getPosition(); - glm::quat mirrorPropertiesRotation = entityProperties.getRotation(); - glm::vec3 mirrorPropertiesDimensions = entityProperties.getDimensions(); - glm::vec3 halfMirrorPropertiesDimensions = 0.5f * mirrorPropertiesDimensions; + EntityItemPointer portalEntrance = qApp->getEntities()->getTree()->findEntityByID(camera->portalEntranceEntityId); + EntityItemPointer portalExit = qApp->getEntities()->getTree()->findEntityByID(camera->attachedEntityId); - glm::mat4 worldFromMirrorRotation = glm::mat4_cast(mirrorPropertiesRotation) * glm::scale(vec3(1.0f, 1.0f, 1.0f)); - glm::mat4 worldFromMirrorTranslation = glm::translate(mirrorPropertiesPosition); - glm::mat4 worldFromMirror = worldFromMirrorTranslation * worldFromMirrorRotation; - glm::mat4 mirrorFromWorld = glm::inverse(worldFromMirror); + glm::vec3 portalEntrancePropertiesPosition = portalEntrance->getWorldPosition(); + glm::quat portalEntrancePropertiesRotation = portalEntrance->getWorldOrientation(); + glm::mat4 worldFromPortalEntranceRotation = glm::mat4_cast(portalEntrancePropertiesRotation); + glm::mat4 worldFromPortalEntranceTranslation = glm::translate(portalEntrancePropertiesPosition); + glm::mat4 worldFromPortalEntrance = worldFromPortalEntranceTranslation * worldFromPortalEntranceRotation; + glm::mat4 portalEntranceFromWorld = glm::inverse(worldFromPortalEntrance); + + glm::vec3 portalExitPropertiesPosition = portalExit->getWorldPosition(); + glm::quat portalExitPropertiesRotation = portalExit->getWorldOrientation(); + glm::vec3 portalExitPropertiesDimensions = portalExit->getScaledDimensions(); + glm::vec3 halfPortalExitPropertiesDimensions = 0.5f * portalExitPropertiesDimensions; + + glm::mat4 worldFromPortalExitRotation = glm::mat4_cast(portalExitPropertiesRotation); + glm::mat4 worldFromPortalExitTranslation = glm::translate(portalExitPropertiesPosition); + glm::mat4 worldFromPortalExit = worldFromPortalExitTranslation * worldFromPortalExitRotation; glm::vec3 mainCameraPositionWorld = getCamera().getPosition(); - glm::vec3 mainCameraPositionMirror = vec3(mirrorFromWorld * vec4(mainCameraPositionWorld, 1.0f)); - glm::vec3 mirrorCameraPositionMirror = vec3(mainCameraPositionMirror.x, mainCameraPositionMirror.y, - mainCameraPositionMirror.z); - glm::vec3 mirrorCameraPositionWorld = vec3(worldFromMirror * vec4(mirrorCameraPositionMirror, 1.0f)); + glm::vec3 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f)); + glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f)); - glm::quat mirrorCameraOrientation = glm::quat_cast(worldFromMirrorRotation); - secondaryViewFrustum.setPosition(mirrorCameraPositionWorld); - secondaryViewFrustum.setOrientation(mirrorCameraOrientation); + secondaryViewFrustum.setPosition(portalExitCameraPositionWorld); + secondaryViewFrustum.setOrientation(portalExitPropertiesRotation); - float nearClip = mirrorCameraPositionMirror.z + mirrorPropertiesDimensions.z * 2.0f; - glm::vec3 upperRight = halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; - glm::vec3 bottomLeft = -halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; + float nearClip = mainCameraPositionPortalEntrance.z + portalExitPropertiesDimensions.z * 2.0f; + // `mainCameraPositionPortalEntrance` should technically be `mainCameraPositionPortalExit`, + // but the values are the same. + glm::vec3 upperRight = halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; + glm::vec3 bottomLeft = -halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance); secondaryViewFrustum.setProjection(frustum); } else if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) { diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 6d60b6ba43..ea485ebf40 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -33,6 +33,7 @@ public: void configure(const Config& config) { _attachedEntityId = config.attachedEntityId; + _portalEntranceEntityId = config.portalEntranceEntityId; _position = config.position; _orientation = config.orientation; _vFoV = config.vFoV; @@ -45,43 +46,51 @@ public: } void setPortalProjection(ViewFrustum& srcViewFrustum) { - if (_attachedEntityId.isNull()) { - qWarning() << "ERROR: Cannot set mirror projection for SecondaryCamera without an attachedEntityId set."; - return; - } - EntityItemPointer attachedEntity = qApp->getEntities()->getTree()->findEntityByID(_attachedEntityId); - - if (!attachedEntity) { - qWarning() << "ERROR: Cannot get EntityItemPointer for _attachedEntityId."; + if (_portalEntranceEntityId.isNull() || _attachedEntityId.isNull()) { + qWarning() << "ERROR: Cannot set portal projection for SecondaryCamera without an attachedEntityId AND portalEntranceEntityId set."; return; } - glm::vec3 mirrorPropertiesPosition = attachedEntity->getWorldPosition(); - glm::quat mirrorPropertiesRotation = attachedEntity->getWorldOrientation(); - glm::vec3 mirrorPropertiesDimensions = attachedEntity->getScaledDimensions(); - glm::vec3 halfMirrorPropertiesDimensions = 0.5f * mirrorPropertiesDimensions; + EntityItemPointer portalEntrance = qApp->getEntities()->getTree()->findEntityByID(_portalEntranceEntityId); + if (!portalEntrance) { + qWarning() << "ERROR: Cannot get EntityItemPointer for portalEntrance."; + return; + } - glm::mat4 worldFromMirrorRotation = glm::mat4_cast(mirrorPropertiesRotation); - glm::mat4 worldFromMirrorTranslation = glm::translate(mirrorPropertiesPosition); - glm::mat4 worldFromMirror = worldFromMirrorTranslation * worldFromMirrorRotation; - glm::mat4 mirrorFromWorld = glm::inverse(worldFromMirror); + EntityItemPointer portalExit = qApp->getEntities()->getTree()->findEntityByID(_attachedEntityId); + if (!portalExit) { + qWarning() << "ERROR: Cannot get EntityItemPointer for portalExit."; + return; + } + glm::vec3 portalEntrancePropertiesPosition = portalEntrance->getWorldPosition(); + glm::quat portalEntrancePropertiesRotation = portalEntrance->getWorldOrientation(); + glm::mat4 worldFromPortalEntranceRotation = glm::mat4_cast(portalEntrancePropertiesRotation); + glm::mat4 worldFromPortalEntranceTranslation = glm::translate(portalEntrancePropertiesPosition); + glm::mat4 worldFromPortalEntrance = worldFromPortalEntranceTranslation * worldFromPortalEntranceRotation; + glm::mat4 portalEntranceFromWorld = glm::inverse(worldFromPortalEntrance); + + glm::vec3 portalExitPropertiesPosition = portalExit->getWorldPosition(); + glm::quat portalExitPropertiesRotation = portalExit->getWorldOrientation(); + glm::vec3 portalExitPropertiesDimensions = portalExit->getScaledDimensions(); + glm::vec3 halfPortalExitPropertiesDimensions = 0.5f * portalExitPropertiesDimensions; + + glm::mat4 worldFromPortalExitRotation = glm::mat4_cast(portalExitPropertiesRotation); + glm::mat4 worldFromPortalExitTranslation = glm::translate(portalExitPropertiesPosition); + glm::mat4 worldFromPortalExit = worldFromPortalExitTranslation * worldFromPortalExitRotation; glm::vec3 mainCameraPositionWorld = qApp->getCamera().getPosition(); - glm::vec3 mainCameraPositionMirror = vec3(mirrorFromWorld * vec4(mainCameraPositionWorld, 1.0f)); - glm::vec3 mirrorCameraPositionMirror = vec3(mainCameraPositionMirror.x, mainCameraPositionMirror.y, - mainCameraPositionMirror.z); - glm::vec3 mirrorCameraPositionWorld = vec3(worldFromMirror * vec4(mirrorCameraPositionMirror, 1.0f)); + glm::vec3 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f)); + glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f)); - // set frustum position to be mirrored camera and set orientation to mirror's adjusted rotation - glm::quat mirrorCameraOrientation = glm::quat_cast(worldFromMirrorRotation); - srcViewFrustum.setPosition(mirrorCameraPositionWorld); - srcViewFrustum.setOrientation(mirrorCameraOrientation); + srcViewFrustum.setPosition(portalExitCameraPositionWorld); + srcViewFrustum.setOrientation(portalExitPropertiesRotation); - // build frustum using mirror space translation of mirrored camera - float nearClip = mirrorCameraPositionMirror.z + mirrorPropertiesDimensions.z * 2.0f; - glm::vec3 upperRight = halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; - glm::vec3 bottomLeft = -halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; + float nearClip = mainCameraPositionPortalEntrance.z + portalExitPropertiesDimensions.z * 2.0f; + // `mainCameraPositionPortalEntrance` should technically be `mainCameraPositionPortalExit`, + // but the values are the same. + glm::vec3 upperRight = halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; + glm::vec3 bottomLeft = -halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, _farClipPlaneDistance); srcViewFrustum.setProjection(frustum); } @@ -194,6 +203,7 @@ protected: private: QUuid _attachedEntityId; + QUuid _portalEntranceEntityId; glm::vec3 _position; glm::quat _orientation; float _vFoV; diff --git a/interface/src/SecondaryCamera.h b/interface/src/SecondaryCamera.h index 7382c2322e..941ccc5f93 100644 --- a/interface/src/SecondaryCamera.h +++ b/interface/src/SecondaryCamera.h @@ -20,6 +20,7 @@ class SecondaryCameraJobConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript. Q_OBJECT Q_PROPERTY(QUuid attachedEntityId MEMBER attachedEntityId NOTIFY dirty) // entity whose properties define camera position and orientation + Q_PROPERTY(QUuid portalEntranceEntityId MEMBER portalEntranceEntityId NOTIFY dirty) // entity whose properties define a portal's entrance position and orientation Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition) // of viewpoint to render from Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation) // of viewpoint to render from Q_PROPERTY(float vFoV MEMBER vFoV NOTIFY dirty) // Secondary camera's vertical field of view. In degrees. @@ -29,6 +30,7 @@ class SecondaryCameraJobConfig : public render::Task::Config { // Exposes second Q_PROPERTY(bool portalProjection MEMBER portalProjection NOTIFY dirty) // Flag to use attached portal entity to build frustum for the portal and set portal camera position/orientation. public: QUuid attachedEntityId; + QUuid portalEntranceEntityId; glm::vec3 position; glm::quat orientation; float vFoV { DEFAULT_FIELD_OF_VIEW_DEGREES };