Correctly update secondary camera frustum

This commit is contained in:
Clement 2018-04-18 17:52:15 -07:00
parent fea49744ed
commit 4c90763236
2 changed files with 75 additions and 19 deletions

View file

@ -5179,6 +5179,78 @@ void Application::updateDialogs(float deltaTime) const {
}
}
void Application::updateSecondaryCameraViewFrustum() {
// TODO: Fix this by modeling the way the secondary camera works on how the main camera works
// ie. Use a camera object stored in the game logic and informs the Engine on where the secondary
// camera should be.
// Code based on SecondaryCameraJob
auto renderConfig = _renderEngine->getConfiguration();
assert(renderConfig);
auto camera = dynamic_cast<SecondaryCameraJobConfig*>(renderConfig->getConfig("SecondaryCamera"));
assert(camera);
if (!camera->isEnabled()) {
_hasSecondaryViewFrustum = false;
return;
}
if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
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;
// setup mirror from world as inverse of world from mirror transformation using inverted x and z for mirrored image
// TODO: we are assuming here that UP is world y-axis
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);
// get mirror camera position by reflecting main camera position's z coordinate in mirror space
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));
// set frustum position to be mirrored camera and set orientation to mirror's adjusted rotation
glm::quat mirrorCameraOrientation = glm::quat_cast(worldFromMirrorRotation);
_secondaryViewFrustum.setPosition(mirrorCameraPositionWorld);
_secondaryViewFrustum.setOrientation(mirrorCameraOrientation);
// 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;
glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance);
_secondaryViewFrustum.setProjection(frustum);
} else {
if (!camera->attachedEntityId.isNull()) {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId);
_secondaryViewFrustum.setPosition(entityProperties.getPosition());
_secondaryViewFrustum.setOrientation(entityProperties.getRotation());
} else {
_secondaryViewFrustum.setPosition(camera->position);
_secondaryViewFrustum.setOrientation(camera->orientation);
}
float aspectRatio = (float)camera->textureWidth / (float)camera->textureHeight;
_secondaryViewFrustum.setProjection(camera->vFoV,
aspectRatio,
camera->nearClipPlaneDistance,
camera->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.
_secondaryViewFrustum.calculate();
_hasSecondaryViewFrustum = true;
}
static bool domainLoadingInProgress = false;
void Application::update(float deltaTime) {
@ -5533,28 +5605,10 @@ void Application::update(float deltaTime) {
QMutexLocker viewLocker(&_viewMutex);
_myCamera.loadViewFrustum(_viewFrustum);
// TODO: Fix this by modeling the way the secondary camera works on how the main camera works
// ie. Use a camera object stored in the game logic and informs the Engine on where the secondary
// camera should be.
auto renderConfig = _renderEngine->getConfiguration();
assert(renderConfig);
auto secondaryCamera = dynamic_cast<SecondaryCameraJobConfig*>(renderConfig->getConfig("SecondaryCamera"));
assert(secondaryCamera);
if (secondaryCamera->isEnabled()) {
_secondaryViewFrustum.setPosition(secondaryCamera->position);
_secondaryViewFrustum.setOrientation(secondaryCamera->orientation);
_secondaryViewFrustum.setProjection(secondaryCamera->vFoV,
secondaryCamera->textureWidth / secondaryCamera->textureHeight,
secondaryCamera->nearClipPlaneDistance,
secondaryCamera->farClipPlaneDistance);
_secondaryViewFrustum.calculate();
_hasSecondaryViewFrustum = true;
} else {
_hasSecondaryViewFrustum = false;
}
updateSecondaryCameraViewFrustum();
}
quint64 now = usecTimestampNow();

View file

@ -149,6 +149,8 @@ public:
void initializeRenderEngine();
void initializeUi();
void updateSecondaryCameraViewFrustum();
void updateCamera(RenderArgs& renderArgs, float deltaTime);
void paintGL();
void resizeGL();