Showing the changes to interface/src/SecondaryCamera.cpp (1 of 3 files). Show all
Unified · Split
| @@ -34,6 +34,7 @@ public: · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 35 | void configure(const Config& config) { |
| 36 | 36 | _attachedEntityId = config.attachedEntityId; |
| 37 | + _portalEntranceEntityId = config.portalEntranceEntityId; | |
| 37 | 38 | _position = config.position; |
| 38 | 39 | _orientation = config.orientation; |
| 39 | 40 | _vFoV = config.vFoV; |
| @@ -41,7 +42,60 @@ public: · 1 unmodified line | ||
| 41 | 42 | _farClipPlaneDistance = config.farClipPlaneDistance; |
| 42 | 43 | _textureWidth = config.textureWidth; |
| 43 | 44 | _textureHeight = config.textureHeight; |
| 44 | − _mirrorProjection = config.mirrorProjection; | |
| 45 | + _mirrorProjection = config.mirrorProjection; | |
| 46 | + _portalProjection = config.portalProjection; | |
| 47 | + } | |
| 48 | + | |
| 49 | + void setPortalProjection(ViewFrustum& srcViewFrustum) { | |
| 50 | + if (_portalEntranceEntityId.isNull() || _attachedEntityId.isNull()) { | |
| 51 | + qWarning() << "ERROR: Cannot set portal projection for SecondaryCamera without an attachedEntityId AND portalEntranceEntityId set."; | |
| 52 | + return; | |
| 53 | + } | |
| 54 | + | |
| 55 | + EntityItemPointer portalEntrance = qApp->getEntities()->getTree()->findEntityByID(_portalEntranceEntityId); | |
| 56 | + if (!portalEntrance) { | |
| 57 | + qWarning() << "ERROR: Cannot get EntityItemPointer for portalEntrance."; | |
| 58 | + return; | |
| 59 | + } | |
| 60 | + | |
| 61 | + EntityItemPointer portalExit = qApp->getEntities()->getTree()->findEntityByID(_attachedEntityId); | |
| 62 | + if (!portalExit) { | |
| 63 | + qWarning() << "ERROR: Cannot get EntityItemPointer for portalExit."; | |
| 64 | + return; | |
| 65 | + } | |
| 66 | + | |
| 67 | + glm::vec3 portalEntrancePropertiesPosition = portalEntrance->getWorldPosition(); | |
| 68 | + glm::quat portalEntrancePropertiesRotation = portalEntrance->getWorldOrientation(); | |
| 69 | + glm::mat4 worldFromPortalEntranceRotation = glm::mat4_cast(portalEntrancePropertiesRotation); | |
| 70 | + glm::mat4 worldFromPortalEntranceTranslation = glm::translate(portalEntrancePropertiesPosition); | |
| 71 | + glm::mat4 worldFromPortalEntrance = worldFromPortalEntranceTranslation * worldFromPortalEntranceRotation; | |
| 72 | + glm::mat4 portalEntranceFromWorld = glm::inverse(worldFromPortalEntrance); | |
| 73 | + | |
| 74 | + glm::vec3 portalExitPropertiesPosition = portalExit->getWorldPosition(); | |
| 75 | + glm::quat portalExitPropertiesRotation = portalExit->getWorldOrientation(); | |
| 76 | + glm::vec3 portalExitPropertiesDimensions = portalExit->getScaledDimensions(); | |
| 77 | + glm::vec3 halfPortalExitPropertiesDimensions = 0.5f * portalExitPropertiesDimensions; | |
| 78 | + | |
| 79 | + glm::mat4 worldFromPortalExitRotation = glm::mat4_cast(portalExitPropertiesRotation); | |
| 80 | + glm::mat4 worldFromPortalExitTranslation = glm::translate(portalExitPropertiesPosition); | |
| 81 | + glm::mat4 worldFromPortalExit = worldFromPortalExitTranslation * worldFromPortalExitRotation; | |
| 82 | + | |
| 83 | + glm::vec3 mainCameraPositionWorld = qApp->getCamera().getPosition(); | |
| 84 | + glm::vec3 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f)); | |
| 85 | + mainCameraPositionPortalEntrance = vec3(-mainCameraPositionPortalEntrance.x, mainCameraPositionPortalEntrance.y, | |
| 86 | + -mainCameraPositionPortalEntrance.z); | |
| 87 | + glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f)); | |
| 88 | + | |
| 89 | + srcViewFrustum.setPosition(portalExitCameraPositionWorld); | |
| 90 | + srcViewFrustum.setOrientation(portalExitPropertiesRotation); | |
| 91 | + | |
| 92 | + float nearClip = mainCameraPositionPortalEntrance.z + portalExitPropertiesDimensions.z * 2.0f; | |
| 93 | + // `mainCameraPositionPortalEntrance` should technically be `mainCameraPositionPortalExit`, | |
| 94 | + // but the values are the same. | |
| 95 | + glm::vec3 upperRight = halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; | |
| 96 | + glm::vec3 bottomLeft = -halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; | |
| 97 | + glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, _farClipPlaneDistance); | |
| 98 | + srcViewFrustum.setProjection(frustum); | |
| 45 | 99 | } |
| 46 | 100 | |
| 47 | 101 | void setMirrorProjection(ViewFrustum& srcViewFrustum) { |
| @@ -110,7 +164,17 @@ public: · 62 unmodified lines | ||
| 110 | 164 | |
| 111 | 165 | auto srcViewFrustum = args->getViewFrustum(); |
| 112 | 166 | if (_mirrorProjection) { |
| 113 | − setMirrorProjection(srcViewFrustum); | |
| 167 | + if (_portalProjection) { | |
| 168 | + qWarning() << "ERROR: You can't set both _portalProjection and _mirrorProjection"; | |
| 169 | + } else { | |
| 170 | + setMirrorProjection(srcViewFrustum); | |
| 171 | + } | |
| 172 | + } else if (_portalProjection) { | |
| 173 | + if (_mirrorProjection) { | |
| 174 | + qWarning() << "ERROR: You can't set both _portalProjection and _mirrorProjection"; | |
| 175 | + } else { | |
| 176 | + setPortalProjection(srcViewFrustum); | |
| 177 | + } | |
| 114 | 178 | } else { |
| 115 | 179 | if (!_attachedEntityId.isNull()) { |
| 116 | 180 | EntityItemPointer attachedEntity = qApp->getEntities()->getTree()->findEntityByID(_attachedEntityId); |
| @@ -142,6 +206,7 @@ protected: · 25 unmodified lines | ||
| 142 | 206 | |
| 143 | 207 | private: |
| 144 | 208 | QUuid _attachedEntityId; |
| 209 | + QUuid _portalEntranceEntityId; | |
| 145 | 210 | glm::vec3 _position; |
| 146 | 211 | glm::quat _orientation; |
| 147 | 212 | float _vFoV; |
| @@ -150,6 +215,7 @@ private: · 2 unmodified lines | ||
| 150 | 215 | int _textureWidth; |
| 151 | 216 | int _textureHeight; |
| 152 | 217 | bool _mirrorProjection; |
| 218 | + bool _portalProjection; | |
| 153 | 219 | EntityPropertyFlags _attachedEntityPropertyFlags; |
| 154 | 220 | }; |
| 155 | 221 | |