mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 02:31:13 +02:00
Merge pull request #14562 from zfox23/portalPrototype
Add a "Portal" mode to the Secondary Camera
This commit is contained in:
commit
735be62271
3 changed files with 110 additions and 3 deletions
|
@ -5565,7 +5565,44 @@ void Application::updateSecondaryCameraViewFrustum() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewFrustum secondaryViewFrustum;
|
ViewFrustum secondaryViewFrustum;
|
||||||
if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) {
|
if (camera->portalProjection && !camera->attachedEntityId.isNull() && !camera->portalEntranceEntityId.isNull()) {
|
||||||
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
|
EntityItemPointer portalEntrance = qApp->getEntities()->getTree()->findEntityByID(camera->portalEntranceEntityId);
|
||||||
|
EntityItemPointer portalExit = qApp->getEntities()->getTree()->findEntityByID(camera->attachedEntityId);
|
||||||
|
|
||||||
|
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 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f));
|
||||||
|
mainCameraPositionPortalEntrance = vec3(-mainCameraPositionPortalEntrance.x, mainCameraPositionPortalEntrance.y,
|
||||||
|
-mainCameraPositionPortalEntrance.z);
|
||||||
|
glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f));
|
||||||
|
|
||||||
|
secondaryViewFrustum.setPosition(portalExitCameraPositionWorld);
|
||||||
|
secondaryViewFrustum.setOrientation(portalExitPropertiesRotation);
|
||||||
|
|
||||||
|
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()) {
|
||||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId);
|
auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId);
|
||||||
glm::vec3 mirrorPropertiesPosition = entityProperties.getPosition();
|
glm::vec3 mirrorPropertiesPosition = entityProperties.getPosition();
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -40,7 +41,60 @@ public:
|
||||||
_farClipPlaneDistance = config.farClipPlaneDistance;
|
_farClipPlaneDistance = config.farClipPlaneDistance;
|
||||||
_textureWidth = config.textureWidth;
|
_textureWidth = config.textureWidth;
|
||||||
_textureHeight = config.textureHeight;
|
_textureHeight = config.textureHeight;
|
||||||
_mirrorProjection = config.mirrorProjection;
|
_mirrorProjection = config.mirrorProjection;
|
||||||
|
_portalProjection = config.portalProjection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPortalProjection(ViewFrustum& srcViewFrustum) {
|
||||||
|
if (_portalEntranceEntityId.isNull() || _attachedEntityId.isNull()) {
|
||||||
|
qWarning() << "ERROR: Cannot set portal projection for SecondaryCamera without an attachedEntityId AND portalEntranceEntityId set.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityItemPointer portalEntrance = qApp->getEntities()->getTree()->findEntityByID(_portalEntranceEntityId);
|
||||||
|
if (!portalEntrance) {
|
||||||
|
qWarning() << "ERROR: Cannot get EntityItemPointer for portalEntrance.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f));
|
||||||
|
mainCameraPositionPortalEntrance = vec3(-mainCameraPositionPortalEntrance.x, mainCameraPositionPortalEntrance.y,
|
||||||
|
-mainCameraPositionPortalEntrance.z);
|
||||||
|
glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f));
|
||||||
|
|
||||||
|
srcViewFrustum.setPosition(portalExitCameraPositionWorld);
|
||||||
|
srcViewFrustum.setOrientation(portalExitPropertiesRotation);
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMirrorProjection(ViewFrustum& srcViewFrustum) {
|
void setMirrorProjection(ViewFrustum& srcViewFrustum) {
|
||||||
|
@ -109,7 +163,17 @@ public:
|
||||||
|
|
||||||
auto srcViewFrustum = args->getViewFrustum();
|
auto srcViewFrustum = args->getViewFrustum();
|
||||||
if (_mirrorProjection) {
|
if (_mirrorProjection) {
|
||||||
setMirrorProjection(srcViewFrustum);
|
if (_portalProjection) {
|
||||||
|
qWarning() << "ERROR: You can't set both _portalProjection and _mirrorProjection";
|
||||||
|
} else {
|
||||||
|
setMirrorProjection(srcViewFrustum);
|
||||||
|
}
|
||||||
|
} else if (_portalProjection) {
|
||||||
|
if (_mirrorProjection) {
|
||||||
|
qWarning() << "ERROR: You can't set both _portalProjection and _mirrorProjection";
|
||||||
|
} else {
|
||||||
|
setPortalProjection(srcViewFrustum);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!_attachedEntityId.isNull()) {
|
if (!_attachedEntityId.isNull()) {
|
||||||
EntityItemPointer attachedEntity = qApp->getEntities()->getTree()->findEntityByID(_attachedEntityId);
|
EntityItemPointer attachedEntity = qApp->getEntities()->getTree()->findEntityByID(_attachedEntityId);
|
||||||
|
@ -141,6 +205,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;
|
||||||
|
@ -149,6 +214,7 @@ private:
|
||||||
int _textureWidth;
|
int _textureWidth;
|
||||||
int _textureHeight;
|
int _textureHeight;
|
||||||
bool _mirrorProjection;
|
bool _mirrorProjection;
|
||||||
|
bool _portalProjection;
|
||||||
EntityPropertyFlags _attachedEntityPropertyFlags;
|
EntityPropertyFlags _attachedEntityPropertyFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,14 +20,17 @@
|
||||||
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.
|
||||||
Q_PROPERTY(float nearClipPlaneDistance MEMBER nearClipPlaneDistance NOTIFY dirty) // Secondary camera's near clip plane distance. In meters.
|
Q_PROPERTY(float nearClipPlaneDistance MEMBER nearClipPlaneDistance NOTIFY dirty) // Secondary camera's near clip plane distance. In meters.
|
||||||
Q_PROPERTY(float farClipPlaneDistance MEMBER farClipPlaneDistance NOTIFY dirty) // Secondary camera's far clip plane distance. In meters.
|
Q_PROPERTY(float farClipPlaneDistance MEMBER farClipPlaneDistance NOTIFY dirty) // Secondary camera's far clip plane distance. In meters.
|
||||||
Q_PROPERTY(bool mirrorProjection MEMBER mirrorProjection NOTIFY dirty) // Flag to use attached mirror entity to build frustum for the mirror and set mirrored camera position/orientation.
|
Q_PROPERTY(bool mirrorProjection MEMBER mirrorProjection NOTIFY dirty) // Flag to use attached mirror entity to build frustum for the mirror and set mirrored 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 };
|
||||||
|
@ -36,6 +39,7 @@ public:
|
||||||
int textureWidth { TextureCache::DEFAULT_SPECTATOR_CAM_WIDTH };
|
int textureWidth { TextureCache::DEFAULT_SPECTATOR_CAM_WIDTH };
|
||||||
int textureHeight { TextureCache::DEFAULT_SPECTATOR_CAM_HEIGHT };
|
int textureHeight { TextureCache::DEFAULT_SPECTATOR_CAM_HEIGHT };
|
||||||
bool mirrorProjection { false };
|
bool mirrorProjection { false };
|
||||||
|
bool portalProjection { false };
|
||||||
|
|
||||||
SecondaryCameraJobConfig() : render::Task::Config(false) {}
|
SecondaryCameraJobConfig() : render::Task::Config(false) {}
|
||||||
signals:
|
signals:
|
||||||
|
|
Loading…
Reference in a new issue