diff --git a/Engine/source/T3D/gameFunctions.cpp b/Engine/source/T3D/gameFunctions.cpp index 5128e3087..873074a4b 100644 --- a/Engine/source/T3D/gameFunctions.cpp +++ b/Engine/source/T3D/gameFunctions.cpp @@ -349,7 +349,13 @@ bool GameProcessCameraQuery(CameraQuery *query) // Provide some default values query->projectionOffset = Point2F::Zero; - + query->stereoTargets[0] = 0; + query->stereoTargets[1] = 0; + query->eyeOffset[0] = Point3F::Zero; + query->eyeOffset[1] = Point3F::Zero; + query->hasFovPort = false; + query->hasStereoTargets = false; + F32 cameraFov = 0.0f; bool fovSet = false; @@ -383,6 +389,7 @@ bool GameProcessCameraQuery(CameraQuery *query) { display->getFovPorts(query->fovPort); fovSet = true; + query->hasFovPort = true; } // Grab the latest overriding render view transforms @@ -391,6 +398,11 @@ bool GameProcessCameraQuery(CameraQuery *query) display->getStereoViewports(query->stereoViewports); display->getStereoTargets(query->stereoTargets); } + else + { + query->eyeTransforms[0] = query->cameraMatrix; + query->eyeTransforms[1] = query->cameraMatrix; + } // Use the connection's FOV settings if requried if(!connection->getControlCameraFov(&cameraFov)) diff --git a/Engine/source/gfx/gfxDevice.h b/Engine/source/gfx/gfxDevice.h index e26c76d9c..61c1a562f 100644 --- a/Engine/source/gfx/gfxDevice.h +++ b/Engine/source/gfx/gfxDevice.h @@ -354,10 +354,10 @@ public: void setStereoEyeTransforms(MatrixF *transforms) { dMemcpy(mStereoEyeTransforms, transforms, sizeof(mStereoEyeTransforms)); dMemcpy(mInverseStereoEyeTransforms, transforms, sizeof(mInverseStereoEyeTransforms)); mInverseStereoEyeTransforms[0].inverse(); mInverseStereoEyeTransforms[1].inverse(); } /// Set the current eye offset used during stereo rendering. Assumes NumStereoPorts are available. - void setFovPort(const FovPort *ports) { dMemcpy(mFovPorts, ports, sizeof(mFovPorts)); } + void setStereoFovPort(const FovPort *ports) { dMemcpy(mFovPorts, ports, sizeof(mFovPorts)); } /// Get the current eye offset used during stereo rendering - const FovPort* getSteroFovPort() { return mFovPorts; } + const FovPort* getStereoFovPort() { return mFovPorts; } /// Sets stereo viewports void setSteroViewports(const RectI *ports) { dMemcpy(mStereoViewports, ports, sizeof(RectI) * NumStereoPorts); } diff --git a/Engine/source/gui/3d/guiTSControl.cpp b/Engine/source/gui/3d/guiTSControl.cpp index cdff62437..285be625f 100644 --- a/Engine/source/gui/3d/guiTSControl.cpp +++ b/Engine/source/gui/3d/guiTSControl.cpp @@ -159,6 +159,8 @@ GuiTSCtrl::GuiTSCtrl() mLastCameraQuery.nearPlane = 0.01f; mLastCameraQuery.projectionOffset = Point2F::Zero; + mLastCameraQuery.hasFovPort = false; + mLastCameraQuery.hasStereoTargets = false; mLastCameraQuery.ortho = false; } @@ -312,6 +314,46 @@ F32 GuiTSCtrl::calculateViewDistance(F32 radius) //----------------------------------------------------------------------------- +static FovPort CalculateFovPortForCanvas(const RectI viewport, const CameraQuery &cameraQuery) +{ + F32 wwidth; + F32 wheight; + F32 renderWidth = viewport.extent.x; + F32 renderHeight = viewport.extent.y; + F32 aspectRatio = renderWidth / renderHeight; + + // Use the FOV to calculate the viewport height scale + // then generate the width scale from the aspect ratio. + if(!cameraQuery.ortho) + { + wheight = /*cameraQuery.nearPlane * */ mTan(cameraQuery.fov / 2.0f); + wwidth = aspectRatio * wheight; + } + else + { + wheight = cameraQuery.fov; + wwidth = aspectRatio * wheight; + } + + F32 hscale = wwidth * 2.0f / renderWidth; + F32 vscale = wheight * 2.0f / renderHeight; + + F32 left = 0.0f * hscale - wwidth; + F32 right = renderWidth * hscale - wwidth; + F32 top = wheight - vscale * 0.0f; + F32 bottom = wheight - vscale * renderHeight; + + FovPort fovPort; + fovPort.upTan = top; + fovPort.downTan = -bottom; + fovPort.leftTan = -left; + fovPort.rightTan = right; + + return fovPort; +} + +//----------------------------------------------------------------------------- + void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) { // Save the current transforms so we can restore @@ -340,7 +382,25 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide); GFX->setCurrentProjectionOffset(mLastCameraQuery.projectionOffset); GFX->setStereoEyeOffsets(mLastCameraQuery.eyeOffset); - GFX->setFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes + + if (!mLastCameraQuery.hasStereoTargets) + { + // Need to calculate our current viewport here + mLastCameraQuery.stereoViewports[0] = updateRect; + mLastCameraQuery.stereoViewports[0].extent.x /= 2; + mLastCameraQuery.stereoViewports[1] = mLastCameraQuery.stereoViewports[0]; + mLastCameraQuery.stereoViewports[1].point.x += mLastCameraQuery.stereoViewports[1].extent.x; + } + + if (!mLastCameraQuery.hasFovPort) + { + // Need to make our own fovPort + mLastCameraQuery.fovPort[0] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[0], mLastCameraQuery); + mLastCameraQuery.fovPort[1] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[1], mLastCameraQuery); + } + + GFX->setStereoFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes + GFX->setSteroViewports(mLastCameraQuery.stereoViewports); GFX->setStereoTargets(mLastCameraQuery.stereoTargets); @@ -402,29 +462,6 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) mLastCameraQuery.cameraMatrix.mul(rotMat); } - // set up the camera and viewport stuff: - F32 wwidth; - F32 wheight; - F32 renderWidth = F32(renderSize.x); - F32 renderHeight = F32(renderSize.y); - F32 aspectRatio = renderWidth / renderHeight; - - // Use the FOV to calculate the viewport height scale - // then generate the width scale from the aspect ratio. - if(!mLastCameraQuery.ortho) - { - wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f); - wwidth = aspectRatio * wheight; - } - else - { - wheight = mLastCameraQuery.fov; - wwidth = aspectRatio * wheight; - } - - F32 hscale = wwidth * 2.0f / renderWidth; - F32 vscale = wheight * 2.0f / renderHeight; - Frustum frustum; if(mRenderStyle == RenderStyleStereoSideBySide) { @@ -433,6 +470,29 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) } else { + // set up the camera and viewport stuff: + F32 wwidth; + F32 wheight; + F32 renderWidth = F32(renderSize.x); + F32 renderHeight = F32(renderSize.y); + F32 aspectRatio = renderWidth / renderHeight; + + // Use the FOV to calculate the viewport height scale + // then generate the width scale from the aspect ratio. + if(!mLastCameraQuery.ortho) + { + wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f); + wwidth = aspectRatio * wheight; + } + else + { + wheight = mLastCameraQuery.fov; + wwidth = aspectRatio * wheight; + } + + F32 hscale = wwidth * 2.0f / renderWidth; + F32 vscale = wheight * 2.0f / renderHeight; + F32 left = (updateRect.point.x - offset.x) * hscale - wwidth; F32 right = (updateRect.point.x + updateRect.extent.x - offset.x) * hscale - wwidth; F32 top = wheight - vscale * (updateRect.point.y - offset.y); @@ -516,7 +576,7 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) Frustum originalFrustum = GFX->getFrustum(); GFXTextureObject *texObject = mStereoGuiTarget->getTexture(0); - const FovPort *currentFovPort = GFX->getSteroFovPort(); + const FovPort *currentFovPort = GFX->getStereoFovPort(); const MatrixF *eyeTransforms = GFX->getStereoEyeTransforms(); const MatrixF *worldEyeTransforms = GFX->getInverseStereoEyeTransforms(); const Point3F *eyeOffset = GFX->getStereoEyeOffsets(); diff --git a/Engine/source/gui/3d/guiTSControl.h b/Engine/source/gui/3d/guiTSControl.h index 0fe305183..493b7c03d 100644 --- a/Engine/source/gui/3d/guiTSControl.h +++ b/Engine/source/gui/3d/guiTSControl.h @@ -49,6 +49,8 @@ struct CameraQuery Point3F eyeOffset[2]; MatrixF eyeTransforms[2]; bool ortho; + bool hasFovPort; + bool hasStereoTargets; MatrixF cameraMatrix; RectI stereoViewports[2]; // destination viewports GFXTextureTarget* stereoTargets[2]; diff --git a/Engine/source/scene/reflector.cpp b/Engine/source/scene/reflector.cpp index 2c9b5feb2..254839813 100644 --- a/Engine/source/scene/reflector.cpp +++ b/Engine/source/scene/reflector.cpp @@ -606,7 +606,7 @@ void PlaneReflector::updateReflection( const ReflectParams ¶ms ) RectI originalVP = GFX->getViewport(); Point2F projOffset = GFX->getCurrentProjectionOffset(); - const FovPort *currentFovPort = GFX->getSteroFovPort(); + const FovPort *currentFovPort = GFX->getStereoFovPort(); MatrixF inverseEyeTransforms[2]; // Calculate world transforms for eyes diff --git a/Engine/source/scene/sceneManager.cpp b/Engine/source/scene/sceneManager.cpp index f7c17996d..0bb85784b 100644 --- a/Engine/source/scene/sceneManager.cpp +++ b/Engine/source/scene/sceneManager.cpp @@ -240,7 +240,7 @@ void SceneManager::renderScene( SceneRenderState* renderState, U32 objectMask, S Frustum originalFrustum = GFX->getFrustum(); Point2F projOffset = GFX->getCurrentProjectionOffset(); - const FovPort *currentFovPort = GFX->getSteroFovPort(); + const FovPort *currentFovPort = GFX->getStereoFovPort(); const MatrixF *eyeTransforms = GFX->getStereoEyeTransforms(); const MatrixF *worldEyeTransforms = GFX->getInverseStereoEyeTransforms();