Torque3D Documentation / _generateds / guiTSControl.cpp

guiTSControl.cpp

Engine/source/gui/3d/guiTSControl.cpp

More...

Public Defines

Public Variables

Public Functions

ConsoleDocClass(GuiTSCtrl , "@brief Abstract base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> controls that <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> 3D <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scenes.\n\n</a>" "<a href="/coding/class/classguitsctrl/">GuiTSCtrl</a> is the base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> controls that <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> 3D camera views in Torque. The class itself " "does not implement <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> concrete scene rendering. Use <a href="/coding/class/classguiobjectview/">GuiObjectView</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display invidiual shapes in " "the Gui and <a href="/coding/class/classgametsctrl/">GameTSCtrl</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> full <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scenes.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameTSCtrl\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiObjectView\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Gui3D\n</a>" )
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 <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">area.\n</a>" " @param radius Radius in world-space units which should fit in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">view.\n</a>" " @return The distance from the viewpoint at which the given radius would be fully visible." )
DefineEngineMethod(GuiTSCtrl , getWorldToScreenScale , Point2F , () , "Get the ratio between world-space units and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@return The amount of world-space units covered by the extent of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single pixel." )
DefineEngineMethod(GuiTSCtrl , project , Point3F , (Point3F worldPosition) , "Transform world-space coordinates <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> screen-space (x, y, depth) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">coordinates.\n</a>" "@param worldPosition The world-space position <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> transform <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> screen-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">space.\n</a>" "@return The " )
DefineEngineMethod(GuiTSCtrl , setStereoGui , void , (GuiOffscreenCanvas *canvas) , "Sets the current stereo texture <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> an offscreen <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">canvas\n</a>" "@param canvas The desired canvas." )
DefineEngineMethod(GuiTSCtrl , unproject , Point3F , (Point3F screenPosition) , "Transform 3D screen-space coordinates (x, y, depth) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> world <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">space.\n</a>" "This method can be, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> example, used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> find the world-space position relating <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the current mouse <a href="/coding/file/sdlcursorcontroller_8cpp/#sdlcursorcontroller_8cpp_1a06e8dd1f849973ccc456f8553601e8b9">cursor</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">position.\n</a>" " @param screenPosition The x/y position on the screen plus the depth from the screen-plane <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">outwards.\n</a>" " @return The world-space position corresponding <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given screen-space coordinates." )
ImplementEnumType(GuiTSRenderStyles , "Style of rendering <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTSCtrl.\n\n</a>" "@ingroup Gui3D" )

Detailed Description

Public Defines

TS_OVERLAY_SCREEN_WIDTH() 0.75

Public Variables

 EndImplementEnumType 

Public Functions

CalculateFovPortForCanvas(const RectI viewport, const CameraQuery & cameraQuery)

ConsoleDocClass(GuiTSCtrl , "@brief Abstract base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> controls that <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> 3D <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scenes.\n\n</a>" "<a href="/coding/class/classguitsctrl/">GuiTSCtrl</a> is the base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> controls that <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> 3D camera views in Torque. The class itself " "does not implement <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> concrete scene rendering. Use <a href="/coding/class/classguiobjectview/">GuiObjectView</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display invidiual shapes in " "the Gui and <a href="/coding/class/classgametsctrl/">GameTSCtrl</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> full <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scenes.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameTSCtrl\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiObjectView\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Gui3D\n</a>" )

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 <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">area.\n</a>" " @param radius Radius in world-space units which should fit in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">view.\n</a>" " @return The distance from the viewpoint at which the given radius would be fully visible." )

DefineEngineMethod(GuiTSCtrl , getWorldToScreenScale , Point2F , () , "Get the ratio between world-space units and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@return The amount of world-space units covered by the extent of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single pixel." )

DefineEngineMethod(GuiTSCtrl , project , Point3F , (Point3F worldPosition) , "Transform world-space coordinates <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> screen-space (x, y, depth) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">coordinates.\n</a>" "@param worldPosition The world-space position <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> transform <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> screen-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">space.\n</a>" "@return The " )

DefineEngineMethod(GuiTSCtrl , setStereoGui , void , (GuiOffscreenCanvas *canvas) , "Sets the current stereo texture <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> an offscreen <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">canvas\n</a>" "@param canvas The desired canvas." )

DefineEngineMethod(GuiTSCtrl , unproject , Point3F , (Point3F screenPosition) , "Transform 3D screen-space coordinates (x, y, depth) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> world <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">space.\n</a>" "This method can be, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> example, used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> find the world-space position relating <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the current mouse <a href="/coding/file/sdlcursorcontroller_8cpp/#sdlcursorcontroller_8cpp_1a06e8dd1f849973ccc456f8553601e8b9">cursor</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">position.\n</a>" " @param screenPosition The x/y position on the screen plus the depth from the screen-plane <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">outwards.\n</a>" " @return The world-space position corresponding <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given screen-space coordinates." )

IMPLEMENT_CONOBJECT(GuiTSCtrl )

ImplementEnumType(GuiTSRenderStyles , "Style of rendering <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTSCtrl.\n\n</a>" "@ingroup Gui3D" )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "gui/3d/guiTSControl.h"
 26#include "gui/core/guiOffscreenCanvas.h"
 27
 28#include "console/engineAPI.h"
 29#include "scene/sceneManager.h"
 30#include "lighting/lightManager.h"
 31#include "gfx/sim/debugDraw.h"
 32#include "gfx/gfxTransformSaver.h"
 33#include "gfx/screenshot.h"
 34#include "math/mathUtils.h"
 35#include "gui/core/guiCanvas.h"
 36#include "scene/reflectionManager.h"
 37#include "postFx/postEffectManager.h"
 38#include "gfx/gfxTransformSaver.h"
 39#include "gfx/gfxDrawUtil.h"
 40#include "gfx/gfxDebugEvent.h"
 41#include "core/stream/fileStream.h"
 42#include "platform/output/IDisplayDevice.h"
 43#include "T3D/gameBase/extended/extendedMove.h"
 44
 45#define TS_OVERLAY_SCREEN_WIDTH 0.75
 46
 47IMPLEMENT_CONOBJECT( GuiTSCtrl );
 48
 49ConsoleDocClass( GuiTSCtrl,
 50   "@brief Abstract base class for controls that render 3D scenes.\n\n"
 51   
 52   "GuiTSCtrl is the base class for controls that render 3D camera views in Torque.  The class itself "
 53   "does not implement a concrete scene rendering.  Use GuiObjectView to display invidiual shapes in "
 54   "the Gui and GameTSCtrl to render full scenes.\n\n"
 55   
 56   "@see GameTSCtrl\n"
 57   "@see GuiObjectView\n"
 58   "@ingroup Gui3D\n"
 59);
 60
 61U32 GuiTSCtrl::smFrameCount = 0;
 62bool GuiTSCtrl::smUseLatestDisplayTransform = true;
 63Vector<GuiTSCtrl*> GuiTSCtrl::smAwakeTSCtrls;
 64
 65ImplementEnumType( GuiTSRenderStyles,
 66   "Style of rendering for a GuiTSCtrl.\n\n"
 67   "@ingroup Gui3D" )
 68   { GuiTSCtrl::RenderStyleStandard,         "standard"              },
 69   { GuiTSCtrl::RenderStyleStereoSideBySide, "stereo side by side"   },
 70   { GuiTSCtrl::RenderStyleStereoSeparate,   "stereo separate" },
 71EndImplementEnumType;
 72
 73//-----------------------------------------------------------------------------
 74
 75namespace 
 76{
 77   void _drawLine( const Point3F &p0, const Point3F &p1, const ColorI &color, F32 width )
 78   {
 79      F32 x1, x2, y1, y2, z1, z2;
 80
 81      x1 = p0.x;
 82      y1 = p0.y;
 83      z1 = p0.z;
 84      x2 = p1.x;
 85      y2 = p1.y;
 86      z2 = p1.z;
 87
 88      //
 89      // Convert Line   a----------b
 90      //
 91      // Into Quad      v0---------v1
 92      //                 a         b
 93      //                v2---------v3
 94      //
 95
 96      Point2F start(x1, y1);
 97      Point2F end(x2, y2);
 98      Point2F perp, lineVec;
 99
100      // handle degenerate case where point a = b
101      if(x1 == x2 && y1 == y2)
102      {
103         perp.set(0.0f, width * 0.5f);
104         lineVec.set(0.1f, 0.0f);
105      }
106      else
107      {
108         perp.set(start.y - end.y, end.x - start.x);
109         lineVec.set(end.x - start.x, end.y - start.y);
110         perp.normalize(width * 0.5f);
111         lineVec.normalize(0.1f);
112      }
113      start -= lineVec;
114      end   += lineVec;
115
116      GFXVertexBufferHandle<GFXVertexPCT> verts(GFX, 4, GFXBufferTypeVolatile);
117      verts.lock();
118
119      verts[0].point.set( start.x+perp.x, start.y+perp.y, z1 );
120      verts[1].point.set( end.x+perp.x, end.y+perp.y, z2 );
121      verts[2].point.set( start.x-perp.x, start.y-perp.y, z1 );
122      verts[3].point.set( end.x-perp.x, end.y-perp.y, z2 );
123
124      verts[0].color = color;
125      verts[1].color = color;
126      verts[2].color = color;
127      verts[3].color = color;
128
129      verts.unlock();
130      GFX->setVertexBuffer( verts );
131
132      GFXStateBlockDesc desc;
133      desc.setCullMode(GFXCullNone);
134      desc.setZReadWrite(false);
135      desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
136
137      GFX->setupGenericShaders();
138      GFX->setStateBlockByDesc( desc );      
139      GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
140   }
141}
142
143//-----------------------------------------------------------------------------
144
145GuiTSCtrl::GuiTSCtrl()
146{
147   mCameraZRot = 0;
148   mForceFOV = 0;
149   mReflectPriority = 1.0f;
150
151   mRenderStyle = RenderStyleStandard;
152
153   mSaveModelview.identity();
154   mSaveProjection.identity();
155   mSaveViewport.set( 0, 0, 10, 10 );
156   mSaveWorldToScreenScale.set( 0, 0 );
157
158   mLastCameraQuery.cameraMatrix.identity();
159   mLastCameraQuery.fov = 45.0f;
160   mLastCameraQuery.object = NULL;
161   mLastCameraQuery.farPlane = 10.0f;
162   mLastCameraQuery.nearPlane = 0.01f;
163
164   mLastCameraQuery.hasFovPort = false;
165   mLastCameraQuery.hasStereoTargets = false;
166
167   mLastCameraQuery.ortho = false;
168   mOrthoWidth = 0.1f;
169   mOrthoHeight = 0.1f;
170}
171
172//-----------------------------------------------------------------------------
173
174void GuiTSCtrl::initPersistFields()
175{
176   addGroup( "Camera" );
177   
178      addField("cameraZRot", TypeF32, Offset(mCameraZRot, GuiTSCtrl),
179         "Z rotation angle of camera." );
180      addField("forceFOV",   TypeF32, Offset(mForceFOV,   GuiTSCtrl),
181         "The vertical field of view in degrees or zero to use the normal camera FOV." );
182         
183   endGroup( "Camera" );
184   
185   addGroup( "Rendering" );
186   
187      addField( "reflectPriority", TypeF32, Offset( mReflectPriority, GuiTSCtrl ),
188         "The share of the per-frame reflection update work this control's rendering should run.\n"
189         "The reflect update priorities of all visible GuiTSCtrls are added together and each control is assigned "
190         "a share of the per-frame reflection update time according to its percentage of the total priority value." );
191
192      addField("renderStyle", TYPEID< RenderStyles >(), Offset(mRenderStyle, GuiTSCtrl),
193         "Indicates how this control should render its contents." );
194
195   endGroup( "Rendering" );
196   
197   Parent::initPersistFields();
198}
199
200//-----------------------------------------------------------------------------
201
202void GuiTSCtrl::consoleInit()
203{
204   Con::addVariable("$TSControl::frameCount", TypeS32, &smFrameCount, "The number of frames that have been rendered since this control was created.\n"
205      "@ingroup Rendering\n");
206   Con::addVariable("$TSControl::useLatestDisplayTransform", TypeBool, &smUseLatestDisplayTransform, "Use the latest view transform when rendering stereo instead of the one calculated by the last move.\n"
207      "@ingroup Rendering\n");
208}
209
210//-----------------------------------------------------------------------------
211
212bool GuiTSCtrl::onWake()
213{
214   if ( !Parent::onWake() )
215      return false;
216
217   // Add ourselves to the active viewport list.
218   AssertFatal( !smAwakeTSCtrls.contains( this ), 
219      "GuiTSCtrl::onWake - This control is already in the awake list!" );
220   smAwakeTSCtrls.push_back( this );
221
222   // For VR
223   mLastCameraQuery.drawCanvas = getRoot();
224
225   return true;
226}
227
228//-----------------------------------------------------------------------------
229
230void GuiTSCtrl::onSleep()
231{
232   Parent::onSleep();
233
234   AssertFatal( smAwakeTSCtrls.contains( this ), 
235      "GuiTSCtrl::onSleep - This control is not in the awake list!" );
236   smAwakeTSCtrls.remove( this );
237}
238
239//-----------------------------------------------------------------------------
240
241void GuiTSCtrl::onPreRender()
242{
243   setUpdate();
244}
245
246//-----------------------------------------------------------------------------
247
248bool GuiTSCtrl::processCameraQuery(CameraQuery *)
249{
250   return false;
251}
252
253//-----------------------------------------------------------------------------
254
255void GuiTSCtrl::renderWorld(const RectI& /*updateRect*/)
256{
257}
258
259//-----------------------------------------------------------------------------
260
261F32 GuiTSCtrl::projectRadius( F32 dist, F32 radius ) const
262{
263   // Fixup any negative or zero distance so we
264   // don't get a divide by zero.
265   dist = dist > 0.0f ? dist : 0.001f;
266   return ( radius / dist ) * mSaveWorldToScreenScale.y;   
267}
268
269//-----------------------------------------------------------------------------
270
271bool GuiTSCtrl::project( const Point3F &pt, Point3F *dest ) const
272{
273   return MathUtils::mProjectWorldToScreen(pt,dest,mSaveViewport,mSaveModelview,mSaveProjection);
274}
275
276//-----------------------------------------------------------------------------
277
278bool GuiTSCtrl::unproject( const Point3F &pt, Point3F *dest ) const
279{
280   MathUtils::mProjectScreenToWorld(pt,dest,mSaveViewport,mSaveModelview,mSaveProjection,mLastCameraQuery.farPlane,mLastCameraQuery.nearPlane);
281   return true;
282}
283
284//-----------------------------------------------------------------------------
285
286F32 GuiTSCtrl::calculateViewDistance(F32 radius)
287{
288   F32 fov = mLastCameraQuery.fov;
289   F32 wwidth;
290   F32 wheight;
291   F32 renderWidth = (mRenderStyle == RenderStyleStereoSideBySide) ? F32(getWidth())*0.5f : F32(getWidth());
292   F32 renderHeight = F32(getHeight());
293   F32 aspectRatio = renderWidth / renderHeight;
294   
295   // Use the FOV to calculate the viewport height scale
296   // then generate the width scale from the aspect ratio.
297   if(!mLastCameraQuery.ortho)
298   {
299      wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f);
300      wwidth = aspectRatio * wheight;
301   }
302   else
303   {
304      wheight = mLastCameraQuery.fov;
305      wwidth = aspectRatio * wheight;
306   }
307
308   // Now determine if we should use the width 
309   // fov or height fov.
310   //
311   // If the window is taller than it is wide, use the 
312   // width fov to keep the object completely in view.
313   if (wheight > wwidth)
314      fov = mAtan( wwidth / mLastCameraQuery.nearPlane ) * 2.0f;
315
316   return radius / mTan(fov / 2.0f);
317}
318
319//-----------------------------------------------------------------------------
320
321static FovPort CalculateFovPortForCanvas(const RectI viewport, const CameraQuery &cameraQuery)
322{
323   F32 wwidth;
324   F32 wheight;
325   F32 renderWidth = viewport.extent.x;
326   F32 renderHeight = viewport.extent.y;
327   F32 aspectRatio = renderWidth / renderHeight;
328
329   // Use the FOV to calculate the viewport height scale
330   // then generate the width scale from the aspect ratio.
331   if(!cameraQuery.ortho)
332   {
333      wheight = /*cameraQuery.nearPlane * */ mTan(cameraQuery.fov / 2.0f);
334      wwidth = aspectRatio * wheight;
335   }
336   else
337   {
338      wheight = cameraQuery.fov;
339      wwidth = aspectRatio * wheight;
340   }
341
342   F32 hscale = wwidth * 2.0f / renderWidth;
343   F32 vscale = wheight * 2.0f / renderHeight;
344
345   F32 left = 0.0f * hscale - wwidth;
346   F32 right = renderWidth * hscale - wwidth;
347   F32 top = wheight - vscale * 0.0f;
348   F32 bottom = wheight - vscale * renderHeight;
349
350   FovPort fovPort;
351   fovPort.upTan = top;
352   fovPort.downTan = -bottom;
353   fovPort.leftTan = -left;
354   fovPort.rightTan = right;
355
356   return fovPort;
357}
358
359void GuiTSCtrl::_internalRender(RectI guiViewport, RectI renderViewport, Frustum &frustum)
360{
361   GFXTransformSaver saver;
362   Point2I renderSize = renderViewport.extent;
363   GFXTarget *origTarget = GFX->getActiveRenderTarget();
364   S32 origStereoTarget = GFX->getCurrentStereoTarget();
365
366   if (mCameraZRot)
367   {
368      MatrixF rotMat(EulerF(0, 0, mDegToRad(mCameraZRot)));
369      mLastCameraQuery.cameraMatrix.mul(rotMat);
370   }
371
372   if (mReflectPriority > 0)
373   {
374      // Get the total reflection priority.
375      F32 totalPriority = 0;
376      for (U32 i = 0; i < smAwakeTSCtrls.size(); i++)
377         if (smAwakeTSCtrls[i]->isVisible())
378            totalPriority += smAwakeTSCtrls[i]->mReflectPriority;
379
380      REFLECTMGR->update(mReflectPriority / totalPriority,
381         renderSize,
382         mLastCameraQuery);
383   }
384
385   GFX->setActiveRenderTarget(origTarget);
386   GFX->setCurrentStereoTarget(origStereoTarget);
387   GFX->setViewport(renderViewport);
388
389   // Clear the zBuffer so GUI doesn't hose object rendering accidentally
390   GFX->clear(GFXClearZBuffer, ColorI(20, 20, 20), 1.0f, 0);
391
392   GFX->setFrustum(frustum);
393   mSaveProjection = GFX->getProjectionMatrix();
394
395   if (mLastCameraQuery.ortho)
396   {
397      mOrthoWidth = frustum.getWidth();
398      mOrthoHeight = frustum.getHeight();
399   }
400
401   // We're going to be displaying this render at size of this control in
402   // pixels - let the scene know so that it can calculate e.g. reflections
403   // correctly for that final display result.
404   gClientSceneGraph->setDisplayTargetResolution(renderSize);
405
406   // Set the GFX world matrix to the world-to-camera transform, but don't 
407   // change the cameraMatrix in mLastCameraQuery. This is because 
408   // mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world
409   // transform. In-place invert would save a copy but mess up any GUIs that
410   // depend on that value.
411   MatrixF worldToCamera = mLastCameraQuery.cameraMatrix;
412   worldToCamera.inverse();
413   GFX->setWorldMatrix(worldToCamera);
414
415   mSaveProjection = GFX->getProjectionMatrix();
416   mSaveModelview = GFX->getWorldMatrix();
417   mSaveViewport = guiViewport;
418   mSaveWorldToScreenScale = GFX->getWorldToScreenScale();
419   mSaveFrustum = GFX->getFrustum();
420   mSaveFrustum.setTransform(mLastCameraQuery.cameraMatrix);
421
422   // Set the default non-clip projection as some 
423   // objects depend on this even in non-reflect cases.
424   gClientSceneGraph->setNonClipProjection(mSaveProjection);
425
426   // Give the post effect manager the worldToCamera, and cameraToScreen matrices
427   PFXMGR->setFrameMatrices(mSaveModelview, mSaveProjection);
428
429   renderWorld(guiViewport);
430
431   DebugDrawer* debugDraw = DebugDrawer::get();
432   if (mRenderStyle == RenderStyleStereoSideBySide && debugDraw->willDraw())
433   {
434      // For SBS we need to render over each viewport
435      GFX->setViewport(mLastCameraQuery.stereoViewports[0]);
436      MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]);
437      GFX->setFrustum(frustum);
438      debugDraw->render(false);
439
440      GFX->setViewport(mLastCameraQuery.stereoViewports[1]);
441      MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[1]);
442      GFX->setFrustum(frustum);
443      debugDraw->render();
444   }
445   else
446   {
447      debugDraw->render();
448   }
449
450   saver.restore();
451}
452
453//-----------------------------------------------------------------------------
454
455void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
456{
457   // Save the current transforms so we can restore
458   // it for child control rendering below.
459   GFXTransformSaver saver;
460   bool renderingToTarget = false;
461
462   mLastCameraQuery.displayDevice = NULL;
463
464   if (!processCameraQuery(&mLastCameraQuery))
465   {
466      // We have no camera, but render the GUI children 
467      // anyway.  This makes editing GuiTSCtrl derived
468      // controls easier in the GuiEditor.
469      renderChildControls(offset, updateRect);
470      return;
471   }
472
473   // 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
474   if (mLastCameraQuery.displayDevice)
475   {
476      if (mRenderStyle == RenderStyleStereoSideBySide)
477      {
478         mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_StereoSideBySide);
479      }
480      else if (mRenderStyle == RenderStyleStereoSeparate)
481      {
482         mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_StereoSeparate);
483      }
484      else
485      {
486         mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_Standard);
487      }
488
489      // The connection's display device may want to set the eye offset
490      if (mLastCameraQuery.displayDevice->providesEyeOffsets())
491      {
492         mLastCameraQuery.displayDevice->getEyeOffsets(mLastCameraQuery.eyeOffset);
493      }
494
495      // Grab field of view for both eyes
496      if (mLastCameraQuery.displayDevice->providesFovPorts())
497      {
498         mLastCameraQuery.displayDevice->getFovPorts(mLastCameraQuery.fovPort);
499         mLastCameraQuery.hasFovPort = true;
500      }
501
502      mLastCameraQuery.displayDevice->getStereoViewports(mLastCameraQuery.stereoViewports);
503      mLastCameraQuery.displayDevice->getStereoTargets(mLastCameraQuery.stereoTargets);
504
505      mLastCameraQuery.hasStereoTargets = mLastCameraQuery.stereoTargets[0];
506   }
507
508   GFXTargetRef origTarget = GFX->getActiveRenderTarget();
509   U32 origStyle = GFX->getCurrentRenderStyle();
510
511   // Set up the appropriate render style
512   Point2I renderSize = getExtent();
513   Frustum frustum;
514
515   mLastCameraQuery.currentEye = -1;
516
517   if (mRenderStyle == RenderStyleStereoSideBySide)
518   {
519      GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide);
520      GFX->setStereoEyeOffsets(mLastCameraQuery.eyeOffset);
521      GFX->setStereoHeadTransform(mLastCameraQuery.headMatrix);
522
523      if (!mLastCameraQuery.hasStereoTargets)
524      {
525         // Need to calculate our current viewport here
526         mLastCameraQuery.stereoViewports[0] = updateRect;
527         mLastCameraQuery.stereoViewports[0].extent.x /= 2;
528         mLastCameraQuery.stereoViewports[1] = mLastCameraQuery.stereoViewports[0];
529         mLastCameraQuery.stereoViewports[1].point.x += mLastCameraQuery.stereoViewports[1].extent.x;
530      }
531
532      if (!mLastCameraQuery.hasFovPort)
533      {
534         // Need to make our own fovPort
535         mLastCameraQuery.fovPort[0] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[0], mLastCameraQuery);
536         mLastCameraQuery.fovPort[1] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[1], mLastCameraQuery);
537      }
538
539      GFX->setStereoFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes
540      GFX->setSteroViewports(mLastCameraQuery.stereoViewports);
541      GFX->setStereoTargets(mLastCameraQuery.stereoTargets);
542
543      MatrixF myTransforms[2];
544
545      if (smUseLatestDisplayTransform)
546      {
547         // Use the view matrix determined from the display device
548         myTransforms[0] = mLastCameraQuery.eyeTransforms[0];
549         myTransforms[1] = mLastCameraQuery.eyeTransforms[1];
550      }
551      else
552      {
553         // Use the view matrix determined from the control object
554         myTransforms[0] = mLastCameraQuery.cameraMatrix;
555         myTransforms[1] = mLastCameraQuery.cameraMatrix;
556         mLastCameraQuery.headMatrix = mLastCameraQuery.cameraMatrix; // override head
557
558         QuatF qrot = mLastCameraQuery.cameraMatrix;
559         Point3F pos = mLastCameraQuery.cameraMatrix.getPosition();
560         Point3F rotEyePos;
561
562         myTransforms[0].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[0], &rotEyePos));
563         myTransforms[1].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[1], &rotEyePos));
564      }
565
566      GFX->setStereoEyeTransforms(myTransforms);
567
568      // Allow render size to originate from the render target
569      if (mLastCameraQuery.stereoTargets[0])
570      {
571         renderSize = mLastCameraQuery.stereoTargets[0]->getSize();
572         renderingToTarget = true;
573      }
574
575      // NOTE: these calculations are essentially overridden later by the fov port settings when rendering each eye.
576      MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]);
577
578      GFX->activateStereoTarget(-1);
579      _internalRender(RectI(updateRect.point, updateRect.extent), RectI(Point2I(0,0), renderSize), frustum);
580     
581      // Notify device we've rendered the right, thus the last stereo frame.
582      GFX->getDeviceEventSignal().trigger(GFXDevice::deRightStereoFrameRendered);
583
584      // Render preview
585      if (mLastCameraQuery.displayDevice)
586      {
587         GFXTexHandle previewTexture = mLastCameraQuery.displayDevice->getPreviewTexture();
588         if (!previewTexture.isNull())
589         {
590            GFX->setActiveRenderTarget(origTarget);
591            GFX->setCurrentRenderStyle(origStyle);
592            GFX->setClipRect(updateRect);
593            renderDisplayPreview(updateRect, previewTexture);
594         }
595      }
596   }
597   else if (mRenderStyle == RenderStyleStereoSeparate && mLastCameraQuery.displayDevice)
598   {
599      // In this case we render the scene twice to different render targets, then
600      // render the final composite view 
601      GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSeparate);
602      GFX->setStereoEyeOffsets(mLastCameraQuery.eyeOffset);
603      GFX->setStereoHeadTransform(mLastCameraQuery.headMatrix);
604      GFX->setStereoFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes
605      GFX->setSteroViewports(mLastCameraQuery.stereoViewports);
606      GFX->setStereoTargets(mLastCameraQuery.stereoTargets);
607
608      MatrixF myTransforms[2];
609
610      if (smUseLatestDisplayTransform)
611      {
612         // Use the view matrix determined from the display device
613         myTransforms[0] = mLastCameraQuery.eyeTransforms[0];
614         myTransforms[1] = mLastCameraQuery.eyeTransforms[1];
615      }
616      else
617      {
618         // Use the view matrix determined from the control object
619         myTransforms[0] = mLastCameraQuery.cameraMatrix;
620         myTransforms[1] = mLastCameraQuery.cameraMatrix;
621
622         QuatF qrot = mLastCameraQuery.cameraMatrix;
623         Point3F pos = mLastCameraQuery.cameraMatrix.getPosition();
624         Point3F rotEyePos;
625
626         myTransforms[0].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[0], &rotEyePos));
627         myTransforms[1].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[1], &rotEyePos));
628      }
629
630      MatrixF origMatrix = mLastCameraQuery.cameraMatrix;
631
632      // Left
633      MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]);
634      mLastCameraQuery.cameraMatrix = myTransforms[0];
635      frustum.update();
636     GFX->activateStereoTarget(0);
637     mLastCameraQuery.currentEye = 0;
638     GFX->beginField();
639     _internalRender(RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), frustum);
640      GFX->getDeviceEventSignal().trigger(GFXDevice::deLeftStereoFrameRendered);
641     GFX->endField();
642
643      // Right
644     GFX->activateStereoTarget(1);
645     mLastCameraQuery.currentEye = 1;
646      MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[1]);
647      mLastCameraQuery.cameraMatrix = myTransforms[1];
648     frustum.update();
649     GFX->beginField();
650     _internalRender(RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[1]->getSize()), RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), frustum);
651     GFX->getDeviceEventSignal().trigger(GFXDevice::deRightStereoFrameRendered);
652     GFX->endField();
653
654      mLastCameraQuery.cameraMatrix = origMatrix;
655
656      // Render preview
657      if (mLastCameraQuery.displayDevice)
658      {
659         GFXTexHandle previewTexture = mLastCameraQuery.displayDevice->getPreviewTexture();
660         if (!previewTexture.isNull())
661         {
662            GFX->setActiveRenderTarget(origTarget);
663            GFX->setCurrentRenderStyle(origStyle);
664            GFX->setClipRect(updateRect);
665            renderDisplayPreview(updateRect, previewTexture);
666         }
667      }
668   }
669   else
670   {
671      // set up the camera and viewport stuff:
672      F32 wwidth;
673      F32 wheight;
674      F32 renderWidth = F32(renderSize.x);
675      F32 renderHeight = F32(renderSize.y);
676      F32 aspectRatio = renderWidth / renderHeight;
677
678      if (mForceFOV != 0)
679         mLastCameraQuery.fov = mDegToRad(mForceFOV);
680
681      // Use the FOV to calculate the viewport height scale
682      // then generate the width scale from the aspect ratio.
683      if (!mLastCameraQuery.ortho)
684      {
685         wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f);
686         wwidth = aspectRatio * wheight;
687      }
688      else
689      {
690         wheight = mLastCameraQuery.fov;
691         wwidth = aspectRatio * wheight;
692      }
693
694      F32 hscale = wwidth * 2.0f / renderWidth;
695      F32 vscale = wheight * 2.0f / renderHeight;
696
697      F32 left = (updateRect.point.x - offset.x) * hscale - wwidth;
698      F32 right = (updateRect.point.x + updateRect.extent.x - offset.x) * hscale - wwidth;
699      F32 top = wheight - vscale * (updateRect.point.y - offset.y);
700      F32 bottom = wheight - vscale * (updateRect.point.y + updateRect.extent.y - offset.y);
701
702      frustum.set(mLastCameraQuery.ortho, left, right, top, bottom, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane);
703
704      // Manipulate the frustum for tiled screenshots
705      const bool screenShotMode = gScreenShot && gScreenShot->isPending();
706      if (screenShotMode)
707      {
708         gScreenShot->tileFrustum(frustum);
709         GFX->setViewMatrix(MatrixF::Identity);
710      }
711
712      RectI tempRect = updateRect;
713      _internalRender(tempRect, tempRect, frustum);
714   }
715
716   // TODO: Some render to sort of overlay system?
717
718   // Allow subclasses to render 2D elements.
719   GFX->setActiveRenderTarget(origTarget);
720   GFX->setCurrentRenderStyle(origStyle);
721   GFX->setClipRect(updateRect);
722   renderGui(offset, updateRect);
723
724   if (shouldRenderChildControls())
725   {
726      renderChildControls(offset, updateRect);
727   }
728   smFrameCount++;
729}
730
731//-----------------------------------------------------------------------------
732
733void GuiTSCtrl::drawLine( Point3F p0, Point3F p1, const ColorI &color, F32 width )
734{   
735   if ( !mSaveFrustum.clipSegment( p0, p1 ) )
736      return;
737
738   MathUtils::mProjectWorldToScreen( p0, &p0, mSaveViewport, mSaveModelview, mSaveProjection );   
739   MathUtils::mProjectWorldToScreen( p1, &p1, mSaveViewport, mSaveModelview, mSaveProjection );   
740
741   p0.x = mClampF( p0.x, 0.0f, mSaveViewport.extent.x );
742   p0.y = mClampF( p0.y, 0.0f, mSaveViewport.extent.y );
743   p1.x = mClampF( p1.x, 0.0f, mSaveViewport.extent.x );
744   p1.y = mClampF( p1.y, 0.0f, mSaveViewport.extent.y );
745   p0.z = p1.z = 0.0f;
746
747   _drawLine( p0, p1, color, width );
748}
749
750//-----------------------------------------------------------------------------
751
752void GuiTSCtrl::drawLineList( const Vector<Point3F> &points, const ColorI color, F32 width )
753{
754   for ( S32 i = 0; i < points.size() - 1; i++ )
755      drawLine( points[i], points[i+1], color, width );
756}
757
758//-----------------------------------------------------------------------------
759
760void GuiTSCtrl::setStereoGui(GuiOffscreenCanvas *canvas)
761{
762   mStereoGuiTarget = canvas ? canvas->getTarget() : NULL;
763   mStereoCanvas = canvas;
764}
765
766
767//-----------------------------------------------------------------------------
768
769void GuiTSCtrl::renderDisplayPreview(const RectI &updateRect, GFXTexHandle &previewTexture)
770{
771   GFX->setWorldMatrix(MatrixF(1));
772   GFX->setViewMatrix(MatrixF::Identity);
773   GFX->setClipRect(updateRect);
774
775   GFX->getDrawUtil()->drawRectFill(RectI(Point2I(0, 0), Point2I(1024, 768)), ColorI::BLACK);
776   GFX->getDrawUtil()->drawRect(RectI(Point2I(0, 0), Point2I(1024, 768)), ColorI::RED);
777
778   if (!mStereoPreviewVB.getPointer())
779   {
780      mStereoPreviewVB.set(GFX, 4, GFXBufferTypeStatic);
781      GFXVertexPCT *verts = mStereoPreviewVB.lock(0, 4);
782
783      F32 texLeft = 0.0f;
784      F32 texRight = 1.0f;
785      F32 texTop = 0.0f;
786      F32 texBottom = 1.0f;
787
788      F32 rectWidth = updateRect.extent.x;
789      F32 rectHeight = updateRect.extent.y;
790
791      F32 screenLeft = 0;
792      F32 screenRight = rectWidth;
793      F32 screenTop = 0;
794      F32 screenBottom = rectHeight;
795
796      const F32 fillConv = 0.0f;
797      verts[0].point.set(screenLeft - fillConv, screenTop - fillConv, 0.f);
798      verts[1].point.set(screenRight - fillConv, screenTop - fillConv, 0.f);
799      verts[2].point.set(screenLeft - fillConv, screenBottom - fillConv, 0.f);
800      verts[3].point.set(screenRight - fillConv, screenBottom - fillConv, 0.f);
801
802      verts[0].color = verts[1].color = verts[2].color = verts[3].color = ColorI(255, 255, 255, 255);
803
804      verts[0].texCoord.set(texLeft, texTop);
805      verts[1].texCoord.set(texRight, texTop);
806      verts[2].texCoord.set(texLeft, texBottom);
807      verts[3].texCoord.set(texRight, texBottom);
808
809      mStereoPreviewVB.unlock();
810   }
811
812   if (!mStereoPreviewSB.getPointer())
813   {
814      // DrawBitmapStretchSR
815      GFXStateBlockDesc bitmapStretchSR;
816      bitmapStretchSR.setCullMode(GFXCullNone);
817      bitmapStretchSR.setZReadWrite(false, false);
818      bitmapStretchSR.setBlend(false, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
819      bitmapStretchSR.samplersDefined = true;
820
821      bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getClampLinear();
822      bitmapStretchSR.samplers[0].minFilter = GFXTextureFilterPoint;
823      bitmapStretchSR.samplers[0].mipFilter = GFXTextureFilterPoint;
824      bitmapStretchSR.samplers[0].magFilter = GFXTextureFilterPoint;
825
826      mStereoPreviewSB = GFX->createStateBlock(bitmapStretchSR);
827   }
828
829   GFX->setVertexBuffer(mStereoPreviewVB);
830   GFX->setStateBlock(mStereoPreviewSB);
831   GFX->setTexture(0, previewTexture);
832   GFX->setupGenericShaders(GFXDevice::GSModColorTexture);
833   GFX->drawPrimitive(GFXTriangleStrip, 0, 2);
834}
835
836//=============================================================================
837//    Console Methods.
838//=============================================================================
839// MARK: ---- Console Methods ----
840
841//-----------------------------------------------------------------------------
842
843DefineEngineMethod( GuiTSCtrl, unproject, Point3F, ( Point3F screenPosition ),,
844   "Transform 3D screen-space coordinates (x, y, depth) to world space.\n"
845   "This method can be, for example, used to find the world-space position relating to the current mouse cursor position.\n"
846   "@param screenPosition The x/y position on the screen plus the depth from the screen-plane outwards.\n"
847   "@return The world-space position corresponding to the given screen-space coordinates." )
848{
849   Point3F worldPos;
850   object->unproject( screenPosition, &worldPos );
851   return worldPos;
852}
853
854//-----------------------------------------------------------------------------
855
856DefineEngineMethod( GuiTSCtrl, project, Point3F, ( Point3F worldPosition ),,
857   "Transform world-space coordinates to screen-space (x, y, depth) coordinates.\n"
858   "@param worldPosition The world-space position to transform to screen-space.\n"
859   "@return The " )
860{
861   Point3F screenPos;
862   object->project( worldPosition, &screenPos );
863   return screenPos;
864}
865
866//-----------------------------------------------------------------------------
867
868DefineEngineMethod( GuiTSCtrl, getWorldToScreenScale, Point2F, (),,
869   "Get the ratio between world-space units and pixels.\n"
870   "@return The amount of world-space units covered by the extent of a single pixel." )
871{
872   return object->getWorldToScreenScale();
873}
874
875//-----------------------------------------------------------------------------
876
877DefineEngineMethod( GuiTSCtrl, calculateViewDistance, F32, ( F32 radius ),,
878   "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"
879   "@param radius Radius in world-space units which should fit in the view.\n"
880   "@return The distance from the viewpoint at which the given radius would be fully visible." )
881{
882   return object->calculateViewDistance( radius );
883}
884
885DefineEngineMethod( GuiTSCtrl, setStereoGui, void, ( GuiOffscreenCanvas* canvas ),,
886   "Sets the current stereo texture to an offscreen canvas\n"
887   "@param canvas The desired canvas." )
888{
889   object->setStereoGui(canvas);
890}
891