mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
alternate approach to mirror projection wip
This commit is contained in:
parent
ea38b32dea
commit
6466a05740
2 changed files with 84 additions and 7 deletions
|
@ -14,6 +14,9 @@
|
|||
#include <TextureCache.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <EntityScriptingInterface.h>
|
||||
#include <EntityTree.h>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
#include <DebugDraw.h>
|
||||
|
||||
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
|
||||
|
||||
|
@ -48,6 +51,63 @@ public:
|
|||
_farClipPlaneDistance = config.farClipPlaneDistance;
|
||||
_textureWidth = config.textureWidth;
|
||||
_textureHeight = config.textureHeight;
|
||||
_mirrorProjection = config.mirrorProjection;
|
||||
}
|
||||
|
||||
void setMirrorProjection(ViewFrustum& srcViewFrustum) {
|
||||
if (_attachedEntityId.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec3 mainCamPos = qApp->getCamera().getPosition();
|
||||
|
||||
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_attachedEntityId, _attachedEntityPropertyFlags);
|
||||
glm::vec3 mirrorPropsPos = entityProperties.getPosition();
|
||||
glm::quat mirrorPropsRot = entityProperties.getRotation();
|
||||
glm::vec3 mirrorPropsDim = entityProperties.getDimensions();
|
||||
|
||||
// get mirrored camera's position and rotation reflected about the mirror plane
|
||||
glm::vec3 mirrorLocalPos = mirrorPropsRot * glm::vec3(0.f, 0.f, 0.f);
|
||||
glm::vec3 mirrorWorldPos = mirrorPropsPos + mirrorLocalPos;
|
||||
glm::vec3 mirrorToHeadVec = mainCamPos - mirrorWorldPos;
|
||||
glm::vec3 zLocalVecNormalized = mirrorPropsRot * Vectors::UNIT_Z;
|
||||
float distanceFromMirror = glm::dot(zLocalVecNormalized, mirrorToHeadVec);
|
||||
glm::vec3 eyePos = mainCamPos - (2.f * distanceFromMirror * zLocalVecNormalized);
|
||||
glm::quat eyeOrientation = glm::inverse(glm::lookAt(eyePos, mirrorWorldPos, mirrorPropsRot * Vectors::UP));
|
||||
srcViewFrustum.setPosition(eyePos);
|
||||
srcViewFrustum.setOrientation(eyeOrientation);
|
||||
|
||||
// setup world from mirrored camera transformation matrix
|
||||
glm::mat4 worldFromEyeRot = glm::mat4_cast(eyeOrientation);
|
||||
glm::mat4 worldFromEyeTrans = glm::translate(eyePos);
|
||||
glm::mat4 worldFromEye = worldFromEyeTrans * worldFromEyeRot;
|
||||
|
||||
// setup mirror from world inverse of world from mirror transformation matrices
|
||||
glm::mat4 worldFromMirrorRot = glm::mat4_cast(mirrorPropsRot) * glm::scale(vec3(-1.f, 1.f, -1.f));
|
||||
glm::mat4 worldFromMirrorTrans = glm::translate(mirrorWorldPos);
|
||||
glm::mat4 worldFromMirror = worldFromMirrorTrans * worldFromMirrorRot;
|
||||
glm::mat4 mirrorFromWorld = glm::inverse(worldFromMirror);
|
||||
|
||||
glm::mat4 mirrorFromEye = mirrorFromWorld * worldFromEye;
|
||||
glm::vec4 mirrorCenterPos = vec4(mirrorFromEye[3]);
|
||||
mirrorFromEye[3] = vec4(0.f, 0.f, 0.f, 1.f);
|
||||
|
||||
float n = mirrorCenterPos.z + mirrorPropsDim.z * 2.f;
|
||||
float f = _farClipPlaneDistance;
|
||||
float r = -mirrorCenterPos.x + mirrorPropsDim.x / 2.f;
|
||||
float l = -mirrorCenterPos.x - mirrorPropsDim.x / 2.f;
|
||||
float t = mirrorCenterPos.y + mirrorPropsDim.y / 2.f;
|
||||
float b = mirrorCenterPos.y - mirrorPropsDim.y / 2.f;
|
||||
|
||||
glm::mat4 frustum = glm::frustum(l, r, b, t, n, f);
|
||||
glm::mat4 projection = frustum * mirrorFromEye;
|
||||
srcViewFrustum.setProjection(projection);
|
||||
|
||||
glm::vec3 mirrorCenterPos3World = transformPoint(worldFromMirror, glm::vec3(mirrorCenterPos));
|
||||
qDebug() << "mirrorCenterPos3World " << mirrorCenterPos3World.x << " , " << mirrorCenterPos3World.y << " , " << mirrorCenterPos3World.z;
|
||||
qDebug() << "mirrorWorldPos " << mirrorWorldPos.x << " , " << mirrorWorldPos.y << " , " << mirrorWorldPos.z;
|
||||
DebugDraw::getInstance().drawRay(mirrorCenterPos3World, mirrorCenterPos3World + glm::vec3(0.f, 5.f, 0.f), glm::vec4(0.f, 1.f, 0.f, 1.f)); // green
|
||||
DebugDraw::getInstance().drawRay(mirrorWorldPos, mirrorWorldPos + glm::vec3(0.f, 5.f, 0.f), glm::vec4(1.f, 0.5f, 0.f, 1.f)); // orange
|
||||
}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, RenderArgsPointer& cachedArgs) {
|
||||
|
@ -71,20 +131,34 @@ public:
|
|||
});
|
||||
|
||||
auto srcViewFrustum = args->getViewFrustum();
|
||||
if (!_attachedEntityId.isNull()) {
|
||||
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_attachedEntityId, _attachedEntityPropertyFlags);
|
||||
srcViewFrustum.setPosition(entityProperties.getPosition());
|
||||
srcViewFrustum.setOrientation(entityProperties.getRotation());
|
||||
if (_mirrorProjection && !_attachedEntityId.isNull()) {
|
||||
setMirrorProjection(srcViewFrustum);
|
||||
} else {
|
||||
srcViewFrustum.setPosition(_position);
|
||||
srcViewFrustum.setOrientation(_orientation);
|
||||
if (!_attachedEntityId.isNull()) {
|
||||
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_attachedEntityId, _attachedEntityPropertyFlags);
|
||||
srcViewFrustum.setPosition(entityProperties.getPosition());
|
||||
srcViewFrustum.setOrientation(entityProperties.getRotation());
|
||||
}
|
||||
else {
|
||||
srcViewFrustum.setPosition(_position);
|
||||
srcViewFrustum.setOrientation(_orientation);
|
||||
}
|
||||
srcViewFrustum.setProjection(glm::perspective(glm::radians(_vFoV), ((float)args->_viewport.z / (float)args->_viewport.w), _nearClipPlaneDistance, _farClipPlaneDistance));
|
||||
}
|
||||
srcViewFrustum.setProjection(glm::perspective(glm::radians(_vFoV), ((float)args->_viewport.z / (float)args->_viewport.w), _nearClipPlaneDistance, _farClipPlaneDistance));
|
||||
// Without calculating the bound planes, the secondary camera will use the same culling frustum as the main camera,
|
||||
// which is not what we want here.
|
||||
srcViewFrustum.calculate();
|
||||
args->pushViewFrustum(srcViewFrustum);
|
||||
cachedArgs = _cachedArgsPointer;
|
||||
|
||||
glm::vec3 dirNorm = glm::normalize(srcViewFrustum.getDirection());
|
||||
glm::vec3 nearPos = srcViewFrustum.getPosition() + dirNorm * srcViewFrustum.getNearClip();
|
||||
|
||||
DebugDraw::getInstance().drawRay(srcViewFrustum.getPosition(), srcViewFrustum.getPosition() + dirNorm * srcViewFrustum.getNearClip(), glm::vec4(1.f, 0.f, 0.f, 1.f)); // red
|
||||
DebugDraw::getInstance().drawRay(nearPos, nearPos + srcViewFrustum.getRight(), glm::vec4(0.f, 0.f, 1.f, 1.f)); // blue
|
||||
DebugDraw::getInstance().drawRay(nearPos, nearPos + srcViewFrustum.getUp(), glm::vec4(0.5f, 0.f, 1.f, 1.f)); // purple
|
||||
|
||||
srcViewFrustum.printDebugDetails();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +175,7 @@ private:
|
|||
float _farClipPlaneDistance;
|
||||
int _textureWidth;
|
||||
int _textureHeight;
|
||||
bool _mirrorProjection;
|
||||
EntityPropertyFlags _attachedEntityPropertyFlags;
|
||||
QSharedPointer<EntityScriptingInterface> _entityScriptingInterface;
|
||||
};
|
||||
|
|
|
@ -35,6 +35,7 @@ class SecondaryCameraJobConfig : public render::Task::Config { // Exposes second
|
|||
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 farClipPlaneDistance MEMBER farClipPlaneDistance NOTIFY dirty) // Secondary camera's far clip plane distance. In meters.
|
||||
Q_PROPERTY(bool mirrorProjection MEMBER mirrorProjection NOTIFY dirty) // Flag to apply oblique near-plane clipping using perspective projection from attached mirror entity
|
||||
public:
|
||||
QUuid attachedEntityId;
|
||||
glm::vec3 position;
|
||||
|
@ -44,6 +45,7 @@ public:
|
|||
float farClipPlaneDistance { DEFAULT_FAR_CLIP };
|
||||
int textureWidth { TextureCache::DEFAULT_SPECTATOR_CAM_WIDTH };
|
||||
int textureHeight { TextureCache::DEFAULT_SPECTATOR_CAM_HEIGHT };
|
||||
bool mirrorProjection { false };
|
||||
|
||||
SecondaryCameraJobConfig() : render::Task::Config(false) {}
|
||||
signals:
|
||||
|
|
Loading…
Reference in a new issue