123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "gui/3d/guiTSControl.h"
- #include "gui/core/guiOffscreenCanvas.h"
- #include "console/engineAPI.h"
- #include "scene/sceneManager.h"
- #include "lighting/lightManager.h"
- #include "gfx/sim/debugDraw.h"
- #include "gfx/gfxTransformSaver.h"
- #include "gfx/screenshot.h"
- #include "math/mathUtils.h"
- #include "gui/core/guiCanvas.h"
- #include "scene/reflectionManager.h"
- #include "postFx/postEffectManager.h"
- #include "gfx/gfxTransformSaver.h"
- #include "gfx/gfxDrawUtil.h"
- #include "gfx/gfxDebugEvent.h"
- #include "core/stream/fileStream.h"
- #include "platform/output/IDisplayDevice.h"
- #include "T3D/gameBase/extended/extendedMove.h"
- #define TS_OVERLAY_SCREEN_WIDTH 0.75
- IMPLEMENT_CONOBJECT( GuiTSCtrl );
- ConsoleDocClass( GuiTSCtrl,
- "@brief Abstract base class for controls that render 3D scenes.\n\n"
-
- "GuiTSCtrl is the base class for controls that render 3D camera views in Torque. The class itself "
- "does not implement a concrete scene rendering. Use GuiObjectView to display invidiual shapes in "
- "the Gui and GameTSCtrl to render full scenes.\n\n"
-
- "@see GameTSCtrl\n"
- "@see GuiObjectView\n"
- "@ingroup Gui3D\n"
- );
- U32 GuiTSCtrl::smFrameCount = 0;
- bool GuiTSCtrl::smUseLatestDisplayTransform = true;
- Vector<GuiTSCtrl*> GuiTSCtrl::smAwakeTSCtrls;
- ImplementEnumType( GuiTSRenderStyles,
- "Style of rendering for a GuiTSCtrl.\n\n"
- "@ingroup Gui3D" )
- { GuiTSCtrl::RenderStyleStandard, "standard" },
- { GuiTSCtrl::RenderStyleStereoSideBySide, "stereo side by side" },
- { GuiTSCtrl::RenderStyleStereoSeparate, "stereo separate" },
- EndImplementEnumType;
- //-----------------------------------------------------------------------------
- namespace
- {
- void _drawLine( const Point3F &p0, const Point3F &p1, const ColorI &color, F32 width )
- {
- F32 x1, x2, y1, y2, z1, z2;
- x1 = p0.x;
- y1 = p0.y;
- z1 = p0.z;
- x2 = p1.x;
- y2 = p1.y;
- z2 = p1.z;
- //
- // Convert Line a----------b
- //
- // Into Quad v0---------v1
- // a b
- // v2---------v3
- //
- Point2F start(x1, y1);
- Point2F end(x2, y2);
- Point2F perp, lineVec;
- // handle degenerate case where point a = b
- if(x1 == x2 && y1 == y2)
- {
- perp.set(0.0f, width * 0.5f);
- lineVec.set(0.1f, 0.0f);
- }
- else
- {
- perp.set(start.y - end.y, end.x - start.x);
- lineVec.set(end.x - start.x, end.y - start.y);
- perp.normalize(width * 0.5f);
- lineVec.normalize(0.1f);
- }
- start -= lineVec;
- end += lineVec;
- GFXVertexBufferHandle<GFXVertexPCT> verts(GFX, 4, GFXBufferTypeVolatile);
- verts.lock();
- verts[0].point.set( start.x+perp.x, start.y+perp.y, z1 );
- verts[1].point.set( end.x+perp.x, end.y+perp.y, z2 );
- verts[2].point.set( start.x-perp.x, start.y-perp.y, z1 );
- verts[3].point.set( end.x-perp.x, end.y-perp.y, z2 );
- verts[0].color = color;
- verts[1].color = color;
- verts[2].color = color;
- verts[3].color = color;
- verts.unlock();
- GFX->setVertexBuffer( verts );
- GFXStateBlockDesc desc;
- desc.setCullMode(GFXCullNone);
- desc.setZReadWrite(false);
- desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
- GFX->setStateBlockByDesc( desc );
- GFX->setupGenericShaders();
- GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
- }
- }
- //-----------------------------------------------------------------------------
- GuiTSCtrl::GuiTSCtrl()
- {
- mCameraZRot = 0;
- mForceFOV = 0;
- mReflectPriority = 1.0f;
- mRenderStyle = RenderStyleStandard;
- mSaveModelview.identity();
- mSaveProjection.identity();
- mSaveViewport.set( 0, 0, 10, 10 );
- mSaveWorldToScreenScale.set( 0, 0 );
- mLastCameraQuery.cameraMatrix.identity();
- mLastCameraQuery.fov = 45.0f;
- mLastCameraQuery.object = NULL;
- mLastCameraQuery.farPlane = 10.0f;
- mLastCameraQuery.nearPlane = 0.01f;
- mLastCameraQuery.hasFovPort = false;
- mLastCameraQuery.hasStereoTargets = false;
- mLastCameraQuery.ortho = false;
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::initPersistFields()
- {
- addGroup( "Camera" );
-
- addField("cameraZRot", TypeF32, Offset(mCameraZRot, GuiTSCtrl),
- "Z rotation angle of camera." );
- addField("forceFOV", TypeF32, Offset(mForceFOV, GuiTSCtrl),
- "The vertical field of view in degrees or zero to use the normal camera FOV." );
-
- endGroup( "Camera" );
-
- addGroup( "Rendering" );
-
- addField( "reflectPriority", TypeF32, Offset( mReflectPriority, GuiTSCtrl ),
- "The share of the per-frame reflection update work this control's rendering should run.\n"
- "The reflect update priorities of all visible GuiTSCtrls are added together and each control is assigned "
- "a share of the per-frame reflection update time according to its percentage of the total priority value." );
- addField("renderStyle", TYPEID< RenderStyles >(), Offset(mRenderStyle, GuiTSCtrl),
- "Indicates how this control should render its contents." );
- endGroup( "Rendering" );
-
- Parent::initPersistFields();
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::consoleInit()
- {
- Con::addVariable("$TSControl::frameCount", TypeS32, &smFrameCount, "The number of frames that have been rendered since this control was created.\n"
- "@ingroup Rendering\n");
- Con::addVariable("$TSControl::useLatestDisplayTransform", TypeBool, &smUseLatestDisplayTransform, "Use the latest view transform when rendering stereo instead of the one calculated by the last move.\n"
- "@ingroup Rendering\n");
- }
- //-----------------------------------------------------------------------------
- bool GuiTSCtrl::onWake()
- {
- if ( !Parent::onWake() )
- return false;
- // Add ourselves to the active viewport list.
- AssertFatal( !smAwakeTSCtrls.contains( this ),
- "GuiTSCtrl::onWake - This control is already in the awake list!" );
- smAwakeTSCtrls.push_back( this );
- // For VR
- mLastCameraQuery.drawCanvas = getRoot();
- return true;
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::onSleep()
- {
- Parent::onSleep();
- AssertFatal( smAwakeTSCtrls.contains( this ),
- "GuiTSCtrl::onSleep - This control is not in the awake list!" );
- smAwakeTSCtrls.remove( this );
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::onPreRender()
- {
- setUpdate();
- }
- //-----------------------------------------------------------------------------
- bool GuiTSCtrl::processCameraQuery(CameraQuery *)
- {
- return false;
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::renderWorld(const RectI& /*updateRect*/)
- {
- }
- //-----------------------------------------------------------------------------
- F32 GuiTSCtrl::projectRadius( F32 dist, F32 radius ) const
- {
- // Fixup any negative or zero distance so we
- // don't get a divide by zero.
- dist = dist > 0.0f ? dist : 0.001f;
- return ( radius / dist ) * mSaveWorldToScreenScale.y;
- }
- //-----------------------------------------------------------------------------
- bool GuiTSCtrl::project( const Point3F &pt, Point3F *dest ) const
- {
- return MathUtils::mProjectWorldToScreen(pt,dest,mSaveViewport,mSaveModelview,mSaveProjection);
- }
- //-----------------------------------------------------------------------------
- bool GuiTSCtrl::unproject( const Point3F &pt, Point3F *dest ) const
- {
- MathUtils::mProjectScreenToWorld(pt,dest,mSaveViewport,mSaveModelview,mSaveProjection,mLastCameraQuery.farPlane,mLastCameraQuery.nearPlane);
- return true;
- }
- //-----------------------------------------------------------------------------
- F32 GuiTSCtrl::calculateViewDistance(F32 radius)
- {
- F32 fov = mLastCameraQuery.fov;
- F32 wwidth;
- F32 wheight;
- F32 renderWidth = (mRenderStyle == RenderStyleStereoSideBySide) ? F32(getWidth())*0.5f : F32(getWidth());
- F32 renderHeight = F32(getHeight());
- 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;
- }
- // Now determine if we should use the width
- // fov or height fov.
- //
- // If the window is taller than it is wide, use the
- // width fov to keep the object completely in view.
- if (wheight > wwidth)
- fov = mAtan( wwidth / mLastCameraQuery.nearPlane ) * 2.0f;
- return radius / mTan(fov / 2.0f);
- }
- //-----------------------------------------------------------------------------
- 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::_internalRender(RectI guiViewport, RectI renderViewport, Frustum &frustum)
- {
- GFXTransformSaver saver;
- Point2I renderSize = renderViewport.extent;
- GFXTarget *origTarget = GFX->getActiveRenderTarget();
- S32 origStereoTarget = GFX->getCurrentStereoTarget();
- if (mForceFOV != 0)
- mLastCameraQuery.fov = mDegToRad(mForceFOV);
- if (mCameraZRot)
- {
- MatrixF rotMat(EulerF(0, 0, mDegToRad(mCameraZRot)));
- mLastCameraQuery.cameraMatrix.mul(rotMat);
- }
- if (mReflectPriority > 0)
- {
- // Get the total reflection priority.
- F32 totalPriority = 0;
- for (U32 i = 0; i < smAwakeTSCtrls.size(); i++)
- if (smAwakeTSCtrls[i]->isVisible())
- totalPriority += smAwakeTSCtrls[i]->mReflectPriority;
- REFLECTMGR->update(mReflectPriority / totalPriority,
- renderSize,
- mLastCameraQuery);
- }
- GFX->setActiveRenderTarget(origTarget);
- GFX->setCurrentStereoTarget(origStereoTarget);
- GFX->setViewport(renderViewport);
- // Clear the zBuffer so GUI doesn't hose object rendering accidentally
- GFX->clear(GFXClearZBuffer, ColorI(20, 20, 20), 1.0f, 0);
- GFX->setFrustum(frustum);
- mSaveProjection = GFX->getProjectionMatrix();
- if (mLastCameraQuery.ortho)
- {
- mOrthoWidth = frustum.getWidth();
- mOrthoHeight = frustum.getHeight();
- }
- // We're going to be displaying this render at size of this control in
- // pixels - let the scene know so that it can calculate e.g. reflections
- // correctly for that final display result.
- gClientSceneGraph->setDisplayTargetResolution(renderSize);
- // Set the GFX world matrix to the world-to-camera transform, but don't
- // change the cameraMatrix in mLastCameraQuery. This is because
- // mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world
- // transform. In-place invert would save a copy but mess up any GUIs that
- // depend on that value.
- MatrixF worldToCamera = mLastCameraQuery.cameraMatrix;
- worldToCamera.inverse();
- GFX->setWorldMatrix(worldToCamera);
- mSaveProjection = GFX->getProjectionMatrix();
- mSaveModelview = GFX->getWorldMatrix();
- mSaveViewport = guiViewport;
- mSaveWorldToScreenScale = GFX->getWorldToScreenScale();
- mSaveFrustum = GFX->getFrustum();
- mSaveFrustum.setTransform(mLastCameraQuery.cameraMatrix);
- // Set the default non-clip projection as some
- // objects depend on this even in non-reflect cases.
- gClientSceneGraph->setNonClipProjection(mSaveProjection);
- // Give the post effect manager the worldToCamera, and cameraToScreen matrices
- PFXMGR->setFrameMatrices(mSaveModelview, mSaveProjection);
- renderWorld(guiViewport);
- DebugDrawer* debugDraw = DebugDrawer::get();
- if (mRenderStyle == RenderStyleStereoSideBySide && debugDraw->willDraw())
- {
- // For SBS we need to render over each viewport
- Frustum frustum;
- GFX->setViewport(mLastCameraQuery.stereoViewports[0]);
- MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]);
- GFX->setFrustum(frustum);
- debugDraw->render(false);
- GFX->setViewport(mLastCameraQuery.stereoViewports[1]);
- MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[1]);
- GFX->setFrustum(frustum);
- debugDraw->render();
- }
- else
- {
- debugDraw->render();
- }
- saver.restore();
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
- {
- // Save the current transforms so we can restore
- // it for child control rendering below.
- GFXTransformSaver saver;
- bool renderingToTarget = false;
- mLastCameraQuery.displayDevice = NULL;
- if (!processCameraQuery(&mLastCameraQuery))
- {
- // We have no camera, but render the GUI children
- // anyway. This makes editing GuiTSCtrl derived
- // controls easier in the GuiEditor.
- renderChildControls(offset, updateRect);
- return;
- }
- // jamesu - currently a little bit of a hack. Ideally we need to ditch the viewports in the query data and just rely on the display device
- if (mLastCameraQuery.displayDevice)
- {
- if (mRenderStyle == RenderStyleStereoSideBySide)
- {
- mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_StereoSideBySide);
- }
- else if (mRenderStyle == RenderStyleStereoSeparate)
- {
- mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_StereoSeparate);
- }
- else
- {
- mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_Standard);
- }
- // The connection's display device may want to set the eye offset
- if (mLastCameraQuery.displayDevice->providesEyeOffsets())
- {
- mLastCameraQuery.displayDevice->getEyeOffsets(mLastCameraQuery.eyeOffset);
- }
- // Grab field of view for both eyes
- if (mLastCameraQuery.displayDevice->providesFovPorts())
- {
- mLastCameraQuery.displayDevice->getFovPorts(mLastCameraQuery.fovPort);
- mLastCameraQuery.hasFovPort = true;
- }
- mLastCameraQuery.displayDevice->getStereoViewports(mLastCameraQuery.stereoViewports);
- mLastCameraQuery.displayDevice->getStereoTargets(mLastCameraQuery.stereoTargets);
- mLastCameraQuery.hasStereoTargets = mLastCameraQuery.stereoTargets[0];
- }
- GFXTargetRef origTarget = GFX->getActiveRenderTarget();
- U32 origStyle = GFX->getCurrentRenderStyle();
- // Set up the appropriate render style
- Point2I renderSize = getExtent();
- Frustum frustum;
- mLastCameraQuery.currentEye = -1;
- if (mRenderStyle == RenderStyleStereoSideBySide)
- {
- GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide);
- GFX->setStereoEyeOffsets(mLastCameraQuery.eyeOffset);
- GFX->setStereoHeadTransform(mLastCameraQuery.headMatrix);
- 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);
- MatrixF myTransforms[2];
- Frustum frustum;
- if (smUseLatestDisplayTransform)
- {
- // Use the view matrix determined from the display device
- myTransforms[0] = mLastCameraQuery.eyeTransforms[0];
- myTransforms[1] = mLastCameraQuery.eyeTransforms[1];
- }
- else
- {
- // Use the view matrix determined from the control object
- myTransforms[0] = mLastCameraQuery.cameraMatrix;
- myTransforms[1] = mLastCameraQuery.cameraMatrix;
- mLastCameraQuery.headMatrix = mLastCameraQuery.cameraMatrix; // override head
- QuatF qrot = mLastCameraQuery.cameraMatrix;
- Point3F pos = mLastCameraQuery.cameraMatrix.getPosition();
- Point3F rotEyePos;
- myTransforms[0].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[0], &rotEyePos));
- myTransforms[1].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[1], &rotEyePos));
- }
- GFX->setStereoEyeTransforms(myTransforms);
- // Allow render size to originate from the render target
- if (mLastCameraQuery.stereoTargets[0])
- {
- renderSize = mLastCameraQuery.stereoTargets[0]->getSize();
- renderingToTarget = true;
- }
- // NOTE: these calculations are essentially overridden later by the fov port settings when rendering each eye.
- MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]);
- GFX->activateStereoTarget(-1);
- _internalRender(RectI(updateRect.point, updateRect.extent), RectI(Point2I(0,0), renderSize), frustum);
-
- // Notify device we've rendered the right, thus the last stereo frame.
- GFX->getDeviceEventSignal().trigger(GFXDevice::deRightStereoFrameRendered);
- // Render preview
- if (mLastCameraQuery.displayDevice)
- {
- GFXTexHandle previewTexture = mLastCameraQuery.displayDevice->getPreviewTexture();
- if (!previewTexture.isNull())
- {
- GFX->setActiveRenderTarget(origTarget);
- GFX->setCurrentRenderStyle(origStyle);
- GFX->setClipRect(updateRect);
- renderDisplayPreview(updateRect, previewTexture);
- }
- }
- }
- else if (mRenderStyle == RenderStyleStereoSeparate && mLastCameraQuery.displayDevice)
- {
- // In this case we render the scene twice to different render targets, then
- // render the final composite view
- GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSeparate);
- GFX->setStereoEyeOffsets(mLastCameraQuery.eyeOffset);
- GFX->setStereoHeadTransform(mLastCameraQuery.headMatrix);
- GFX->setStereoFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes
- GFX->setSteroViewports(mLastCameraQuery.stereoViewports);
- GFX->setStereoTargets(mLastCameraQuery.stereoTargets);
- MatrixF myTransforms[2];
- if (smUseLatestDisplayTransform)
- {
- // Use the view matrix determined from the display device
- myTransforms[0] = mLastCameraQuery.eyeTransforms[0];
- myTransforms[1] = mLastCameraQuery.eyeTransforms[1];
- }
- else
- {
- // Use the view matrix determined from the control object
- myTransforms[0] = mLastCameraQuery.cameraMatrix;
- myTransforms[1] = mLastCameraQuery.cameraMatrix;
- QuatF qrot = mLastCameraQuery.cameraMatrix;
- Point3F pos = mLastCameraQuery.cameraMatrix.getPosition();
- Point3F rotEyePos;
- myTransforms[0].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[0], &rotEyePos));
- myTransforms[1].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[1], &rotEyePos));
- }
- MatrixF origMatrix = mLastCameraQuery.cameraMatrix;
- // Left
- MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]);
- mLastCameraQuery.cameraMatrix = myTransforms[0];
- frustum.update();
- GFX->activateStereoTarget(0);
- mLastCameraQuery.currentEye = 0;
- GFX->beginField();
- _internalRender(RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), frustum);
- GFX->getDeviceEventSignal().trigger(GFXDevice::deLeftStereoFrameRendered);
- GFX->endField();
- // Right
- GFX->activateStereoTarget(1);
- mLastCameraQuery.currentEye = 1;
- MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[1]);
- mLastCameraQuery.cameraMatrix = myTransforms[1];
- frustum.update();
- GFX->beginField();
- _internalRender(RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[1]->getSize()), RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), frustum);
- GFX->getDeviceEventSignal().trigger(GFXDevice::deRightStereoFrameRendered);
- GFX->endField();
- mLastCameraQuery.cameraMatrix = origMatrix;
- // Render preview
- if (mLastCameraQuery.displayDevice)
- {
- GFXTexHandle previewTexture = mLastCameraQuery.displayDevice->getPreviewTexture();
- if (!previewTexture.isNull())
- {
- GFX->setActiveRenderTarget(origTarget);
- GFX->setCurrentRenderStyle(origStyle);
- GFX->setClipRect(updateRect);
- renderDisplayPreview(updateRect, previewTexture);
- }
- }
- }
- 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);
- F32 bottom = wheight - vscale * (updateRect.point.y + updateRect.extent.y - offset.y);
- frustum.set(mLastCameraQuery.ortho, left, right, top, bottom, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane);
- // Manipulate the frustum for tiled screenshots
- const bool screenShotMode = gScreenShot && gScreenShot->isPending();
- if (screenShotMode)
- {
- gScreenShot->tileFrustum(frustum);
- GFX->setViewMatrix(MatrixF::Identity);
- }
- RectI tempRect = updateRect;
- _internalRender(tempRect, tempRect, frustum);
- }
- // TODO: Some render to sort of overlay system?
- // Allow subclasses to render 2D elements.
- GFX->setActiveRenderTarget(origTarget);
- GFX->setCurrentRenderStyle(origStyle);
- GFX->setClipRect(updateRect);
- renderGui(offset, updateRect);
- if (shouldRenderChildControls())
- {
- renderChildControls(offset, updateRect);
- }
- smFrameCount++;
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::drawLine( Point3F p0, Point3F p1, const ColorI &color, F32 width )
- {
- if ( !mSaveFrustum.clipSegment( p0, p1 ) )
- return;
- MathUtils::mProjectWorldToScreen( p0, &p0, mSaveViewport, mSaveModelview, mSaveProjection );
- MathUtils::mProjectWorldToScreen( p1, &p1, mSaveViewport, mSaveModelview, mSaveProjection );
- p0.x = mClampF( p0.x, 0.0f, mSaveViewport.extent.x );
- p0.y = mClampF( p0.y, 0.0f, mSaveViewport.extent.y );
- p1.x = mClampF( p1.x, 0.0f, mSaveViewport.extent.x );
- p1.y = mClampF( p1.y, 0.0f, mSaveViewport.extent.y );
- p0.z = p1.z = 0.0f;
- _drawLine( p0, p1, color, width );
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::drawLineList( const Vector<Point3F> &points, const ColorI color, F32 width )
- {
- for ( S32 i = 0; i < points.size() - 1; i++ )
- drawLine( points[i], points[i+1], color, width );
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::setStereoGui(GuiOffscreenCanvas *canvas)
- {
- mStereoGuiTarget = canvas ? canvas->getTarget() : NULL;
- mStereoCanvas = canvas;
- }
- //-----------------------------------------------------------------------------
- void GuiTSCtrl::renderDisplayPreview(const RectI &updateRect, GFXTexHandle &previewTexture)
- {
- GFX->setWorldMatrix(MatrixF(1));
- GFX->setViewMatrix(MatrixF::Identity);
- GFX->setClipRect(updateRect);
- GFX->getDrawUtil()->drawRectFill(RectI(Point2I(0, 0), Point2I(1024, 768)), ColorI::BLACK);
- GFX->getDrawUtil()->drawRect(RectI(Point2I(0, 0), Point2I(1024, 768)), ColorI::RED);
- if (!mStereoPreviewVB.getPointer())
- {
- mStereoPreviewVB.set(GFX, 4, GFXBufferTypeStatic);
- GFXVertexPCT *verts = mStereoPreviewVB.lock(0, 4);
- F32 texLeft = 0.0f;
- F32 texRight = 1.0f;
- F32 texTop = 0.0f;
- F32 texBottom = 1.0f;
- F32 rectWidth = updateRect.extent.x;
- F32 rectHeight = updateRect.extent.y;
- F32 screenLeft = 0;
- F32 screenRight = rectWidth;
- F32 screenTop = 0;
- F32 screenBottom = rectHeight;
- const F32 fillConv = 0.0f;
- verts[0].point.set(screenLeft - fillConv, screenTop - fillConv, 0.f);
- verts[1].point.set(screenRight - fillConv, screenTop - fillConv, 0.f);
- verts[2].point.set(screenLeft - fillConv, screenBottom - fillConv, 0.f);
- verts[3].point.set(screenRight - fillConv, screenBottom - fillConv, 0.f);
- verts[0].color = verts[1].color = verts[2].color = verts[3].color = ColorI(255, 255, 255, 255);
- verts[0].texCoord.set(texLeft, texTop);
- verts[1].texCoord.set(texRight, texTop);
- verts[2].texCoord.set(texLeft, texBottom);
- verts[3].texCoord.set(texRight, texBottom);
- mStereoPreviewVB.unlock();
- }
- if (!mStereoPreviewSB.getPointer())
- {
- // DrawBitmapStretchSR
- GFXStateBlockDesc bitmapStretchSR;
- bitmapStretchSR.setCullMode(GFXCullNone);
- bitmapStretchSR.setZReadWrite(false, false);
- bitmapStretchSR.setBlend(false, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
- bitmapStretchSR.samplersDefined = true;
- bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getClampLinear();
- bitmapStretchSR.samplers[0].minFilter = GFXTextureFilterPoint;
- bitmapStretchSR.samplers[0].mipFilter = GFXTextureFilterPoint;
- bitmapStretchSR.samplers[0].magFilter = GFXTextureFilterPoint;
- mStereoPreviewSB = GFX->createStateBlock(bitmapStretchSR);
- }
- GFX->setVertexBuffer(mStereoPreviewVB);
- GFX->setStateBlock(mStereoPreviewSB);
- GFX->setTexture(0, previewTexture);
- GFX->setupGenericShaders(GFXDevice::GSModColorTexture);
- GFX->drawPrimitive(GFXTriangleStrip, 0, 2);
- }
- //=============================================================================
- // Console Methods.
- //=============================================================================
- // MARK: ---- Console Methods ----
- //-----------------------------------------------------------------------------
- DefineEngineMethod( GuiTSCtrl, unproject, Point3F, ( Point3F screenPosition ),,
- "Transform 3D screen-space coordinates (x, y, depth) to world space.\n"
- "This method can be, for example, used to find the world-space position relating to the current mouse cursor position.\n"
- "@param screenPosition The x/y position on the screen plus the depth from the screen-plane outwards.\n"
- "@return The world-space position corresponding to the given screen-space coordinates." )
- {
- Point3F worldPos;
- object->unproject( screenPosition, &worldPos );
- return worldPos;
- }
- //-----------------------------------------------------------------------------
- DefineEngineMethod( GuiTSCtrl, project, Point3F, ( Point3F worldPosition ),,
- "Transform world-space coordinates to screen-space (x, y, depth) coordinates.\n"
- "@param worldPosition The world-space position to transform to screen-space.\n"
- "@return The " )
- {
- Point3F screenPos;
- object->project( worldPosition, &screenPos );
- return screenPos;
- }
- //-----------------------------------------------------------------------------
- DefineEngineMethod( GuiTSCtrl, getWorldToScreenScale, Point2F, (),,
- "Get the ratio between world-space units and pixels.\n"
- "@return The amount of world-space units covered by the extent of a single pixel." )
- {
- return object->getWorldToScreenScale();
- }
- //-----------------------------------------------------------------------------
- DefineEngineMethod( GuiTSCtrl, calculateViewDistance, F32, ( F32 radius ),,
- "Given the camera's current FOV, get the distance from the camera's viewpoint at which the given radius will fit in the render area.\n"
- "@param radius Radius in world-space units which should fit in the view.\n"
- "@return The distance from the viewpoint at which the given radius would be fully visible." )
- {
- return object->calculateViewDistance( radius );
- }
- DefineEngineMethod( GuiTSCtrl, setStereoGui, void, ( GuiOffscreenCanvas* canvas ),,
- "Sets the current stereo texture to an offscreen canvas\n"
- "@param canvas The desired canvas." )
- {
- object->setStereoGui(canvas);
- }
|