It's working!

This commit is contained in:
Zach Fox 2018-11-07 14:51:19 -08:00
parent 668e4aeafd
commit d2d5132f72
3 changed files with 67 additions and 48 deletions

View file

@ -5585,32 +5585,39 @@ void Application::updateSecondaryCameraViewFrustum() {
} }
ViewFrustum secondaryViewFrustum; ViewFrustum secondaryViewFrustum;
if (camera->portalProjection && !camera->attachedEntityId.isNull()) { if (camera->portalProjection && !camera->attachedEntityId.isNull() && !camera->portalEntranceEntityId.isNull()) {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId); EntityItemPointer portalEntrance = qApp->getEntities()->getTree()->findEntityByID(camera->portalEntranceEntityId);
glm::vec3 mirrorPropertiesPosition = entityProperties.getPosition(); EntityItemPointer portalExit = qApp->getEntities()->getTree()->findEntityByID(camera->attachedEntityId);
glm::quat mirrorPropertiesRotation = entityProperties.getRotation();
glm::vec3 mirrorPropertiesDimensions = entityProperties.getDimensions();
glm::vec3 halfMirrorPropertiesDimensions = 0.5f * mirrorPropertiesDimensions;
glm::mat4 worldFromMirrorRotation = glm::mat4_cast(mirrorPropertiesRotation) * glm::scale(vec3(1.0f, 1.0f, 1.0f)); glm::vec3 portalEntrancePropertiesPosition = portalEntrance->getWorldPosition();
glm::mat4 worldFromMirrorTranslation = glm::translate(mirrorPropertiesPosition); glm::quat portalEntrancePropertiesRotation = portalEntrance->getWorldOrientation();
glm::mat4 worldFromMirror = worldFromMirrorTranslation * worldFromMirrorRotation; glm::mat4 worldFromPortalEntranceRotation = glm::mat4_cast(portalEntrancePropertiesRotation);
glm::mat4 mirrorFromWorld = glm::inverse(worldFromMirror); 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 mainCameraPositionWorld = getCamera().getPosition();
glm::vec3 mainCameraPositionMirror = vec3(mirrorFromWorld * vec4(mainCameraPositionWorld, 1.0f)); glm::vec3 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f));
glm::vec3 mirrorCameraPositionMirror = vec3(mainCameraPositionMirror.x, mainCameraPositionMirror.y, glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f));
mainCameraPositionMirror.z);
glm::vec3 mirrorCameraPositionWorld = vec3(worldFromMirror * vec4(mirrorCameraPositionMirror, 1.0f));
glm::quat mirrorCameraOrientation = glm::quat_cast(worldFromMirrorRotation); secondaryViewFrustum.setPosition(portalExitCameraPositionWorld);
secondaryViewFrustum.setPosition(mirrorCameraPositionWorld); secondaryViewFrustum.setOrientation(portalExitPropertiesRotation);
secondaryViewFrustum.setOrientation(mirrorCameraOrientation);
float nearClip = mirrorCameraPositionMirror.z + mirrorPropertiesDimensions.z * 2.0f; float nearClip = mainCameraPositionPortalEntrance.z + portalExitPropertiesDimensions.z * 2.0f;
glm::vec3 upperRight = halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; // `mainCameraPositionPortalEntrance` should technically be `mainCameraPositionPortalExit`,
glm::vec3 bottomLeft = -halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; // 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); glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance);
secondaryViewFrustum.setProjection(frustum); secondaryViewFrustum.setProjection(frustum);
} else if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) { } else if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) {

View file

@ -33,6 +33,7 @@ public:
void configure(const Config& config) { void configure(const Config& config) {
_attachedEntityId = config.attachedEntityId; _attachedEntityId = config.attachedEntityId;
_portalEntranceEntityId = config.portalEntranceEntityId;
_position = config.position; _position = config.position;
_orientation = config.orientation; _orientation = config.orientation;
_vFoV = config.vFoV; _vFoV = config.vFoV;
@ -45,43 +46,51 @@ public:
} }
void setPortalProjection(ViewFrustum& srcViewFrustum) { void setPortalProjection(ViewFrustum& srcViewFrustum) {
if (_attachedEntityId.isNull()) { if (_portalEntranceEntityId.isNull() || _attachedEntityId.isNull()) {
qWarning() << "ERROR: Cannot set mirror projection for SecondaryCamera without an attachedEntityId set."; qWarning() << "ERROR: Cannot set portal projection for SecondaryCamera without an attachedEntityId AND portalEntranceEntityId set.";
return;
}
EntityItemPointer attachedEntity = qApp->getEntities()->getTree()->findEntityByID(_attachedEntityId);
if (!attachedEntity) {
qWarning() << "ERROR: Cannot get EntityItemPointer for _attachedEntityId.";
return; return;
} }
glm::vec3 mirrorPropertiesPosition = attachedEntity->getWorldPosition(); EntityItemPointer portalEntrance = qApp->getEntities()->getTree()->findEntityByID(_portalEntranceEntityId);
glm::quat mirrorPropertiesRotation = attachedEntity->getWorldOrientation(); if (!portalEntrance) {
glm::vec3 mirrorPropertiesDimensions = attachedEntity->getScaledDimensions(); qWarning() << "ERROR: Cannot get EntityItemPointer for portalEntrance.";
glm::vec3 halfMirrorPropertiesDimensions = 0.5f * mirrorPropertiesDimensions; return;
}
glm::mat4 worldFromMirrorRotation = glm::mat4_cast(mirrorPropertiesRotation); EntityItemPointer portalExit = qApp->getEntities()->getTree()->findEntityByID(_attachedEntityId);
glm::mat4 worldFromMirrorTranslation = glm::translate(mirrorPropertiesPosition); if (!portalExit) {
glm::mat4 worldFromMirror = worldFromMirrorTranslation * worldFromMirrorRotation; qWarning() << "ERROR: Cannot get EntityItemPointer for portalExit.";
glm::mat4 mirrorFromWorld = glm::inverse(worldFromMirror); 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 mainCameraPositionWorld = qApp->getCamera().getPosition();
glm::vec3 mainCameraPositionMirror = vec3(mirrorFromWorld * vec4(mainCameraPositionWorld, 1.0f)); glm::vec3 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f));
glm::vec3 mirrorCameraPositionMirror = vec3(mainCameraPositionMirror.x, mainCameraPositionMirror.y, glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f));
mainCameraPositionMirror.z);
glm::vec3 mirrorCameraPositionWorld = vec3(worldFromMirror * vec4(mirrorCameraPositionMirror, 1.0f));
// set frustum position to be mirrored camera and set orientation to mirror's adjusted rotation srcViewFrustum.setPosition(portalExitCameraPositionWorld);
glm::quat mirrorCameraOrientation = glm::quat_cast(worldFromMirrorRotation); srcViewFrustum.setOrientation(portalExitPropertiesRotation);
srcViewFrustum.setPosition(mirrorCameraPositionWorld);
srcViewFrustum.setOrientation(mirrorCameraOrientation);
// build frustum using mirror space translation of mirrored camera float nearClip = mainCameraPositionPortalEntrance.z + portalExitPropertiesDimensions.z * 2.0f;
float nearClip = mirrorCameraPositionMirror.z + mirrorPropertiesDimensions.z * 2.0f; // `mainCameraPositionPortalEntrance` should technically be `mainCameraPositionPortalExit`,
glm::vec3 upperRight = halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; // but the values are the same.
glm::vec3 bottomLeft = -halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; 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); glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, _farClipPlaneDistance);
srcViewFrustum.setProjection(frustum); srcViewFrustum.setProjection(frustum);
} }
@ -194,6 +203,7 @@ protected:
private: private:
QUuid _attachedEntityId; QUuid _attachedEntityId;
QUuid _portalEntranceEntityId;
glm::vec3 _position; glm::vec3 _position;
glm::quat _orientation; glm::quat _orientation;
float _vFoV; float _vFoV;

View file

@ -20,6 +20,7 @@
class SecondaryCameraJobConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript. class SecondaryCameraJobConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript.
Q_OBJECT Q_OBJECT
Q_PROPERTY(QUuid attachedEntityId MEMBER attachedEntityId NOTIFY dirty) // entity whose properties define camera position and orientation 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::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(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. 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. 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: public:
QUuid attachedEntityId; QUuid attachedEntityId;
QUuid portalEntranceEntityId;
glm::vec3 position; glm::vec3 position;
glm::quat orientation; glm::quat orientation;
float vFoV { DEFAULT_FIELD_OF_VIEW_DEGREES }; float vFoV { DEFAULT_FIELD_OF_VIEW_DEGREES };