SO3Engine
SO3StereoManager.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source is part of the Stereoscopy manager for OGRE
4 (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6-----------------------------------------------------------------------------
7* Copyright (c) 2008, Mathieu Le Ber, AXYZ-IMAGES
8* All rights reserved.
9*
10* Redistribution and use in source and binary forms, with or without
11* modification, are permitted provided that the following conditions are met:
12* * Redistributions of source code must retain the above copyright
13* notice, this list of conditions and the following disclaimer.
14* * Redistributions in binary form must reproduce the above copyright
15* notice, this list of conditions and the following disclaimer in the
16* documentation and/or other materials provided with the distribution.
17* * Neither the name of the AXYZ-IMAGES nor the
18* names of its contributors may be used to endorse or promote products
19* derived from this software without specific prior written permission.
20*
21* THIS SOFTWARE IS PROVIDED BY Mathieu Le Ber ''AS IS'' AND ANY
22* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24* DISCLAIMED. IN NO EVENT SHALL Mathieu Le Ber BE LIABLE FOR ANY
25* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31-----------------------------------------------------------------------------
32// Heavily modified by OS3D Team.
33*/
34
36#include "SO3Renderer/SO3Root.h"
42
43#include <vector>
44#include <limits>
45#include "Ogre.h"
46#include <OgreBitwise.h>
47#include <OgreDepthBuffer.h>
48
49#ifdef _WIN32
50# ifndef SO3_USE_DX11
51 #include "OgreD3D9RenderWindow.h"
52#else
53 #include "OgreD3D11Texture.h"
54 #include "OgreD3D11RenderWindow.h"
55# endif
56#endif
57
58extern int getBufferStereoBeforeUpdateEvent(struct Mmachine*, SCOL_PTR_TYPE, SCOL_PTR_TYPE);
59extern int getBufferStereoUpdateParametersEvent(struct Mmachine*, SCOL_PTR_TYPE, SCOL_PTR_TYPE);
60extern int getBufferStereoUpdatedEvent(struct Mmachine*, SCOL_PTR_TYPE, SCOL_PTR_TYPE);
61namespace SO3
62{
63
64 //TODO remove viewportt / render target reference, this can be destroy by ogre
65 //add a list of main compositors std::map<std::string, bool>, reloadCompositors set compositorState ?
66StereoManager::StereoManager(SWindow* buffer) : mBuffer(buffer),
67 mStereoMode(SO3_NONE_STEREO),
68 mEyesSpacing(0.06f),
69 mIsCustomProjection(false),
70 mIsCustomOffset(false),
71 mIsCustomRatio(false),
72 mIsCustomFOV(false),
73 mIsCustomDistortion(false),
74 mIsCustomChromAbCorrection(false),
75 mRotateView(false),
76 mHasExternalWindow(false),
77 mExternalWindow(0),
78 mExternalViewport(0),
79 mWindowPos(SO3::SPoint<int>(0, 0)),
80 mWindowSise(SO3::SPoint<int>(1280, 800)),
81 mCenterOffset(0.0f),
82 mRatio(1.0f),
83 mLeftUVScale(Ogre::Vector2::UNIT_SCALE),
84 mLeftUVOffset(Ogre::Vector2::ZERO),
85 mRightUVScale(Ogre::Vector2::UNIT_SCALE),
86 mRightUVOffset(Ogre::Vector2::ZERO),
87 mLeftRenderTextureSize(SO3::SPoint<int>(1, 1)),
88 mRightRenderTextureSize(SO3::SPoint<int>(1, 1)),
89 mLeftCustomProjection(Ogre::Matrix4::IDENTITY),
90 mRightCustomProjection(Ogre::Matrix4::IDENTITY),
91 mLeftStartWarpMatrix(Ogre::Matrix4::IDENTITY),
92 mLeftEndWarpMatrix(Ogre::Matrix4::IDENTITY),
93 mRightStartWarpMatrix(Ogre::Matrix4::IDENTITY),
94 mRightEndWarpMatrix(Ogre::Matrix4::IDENTITY),
95 mRightMask(~((Ogre::uint32)0)),
96 mLeftMask(~((Ogre::uint32)0)),
97 mDeviceLostListener(0)
98{
99 mAvailableModes[SO3_ANAGLYPH_RC_STEREO] = "Stereo/RedCyanAnaglyph";
100 mAvailableModes[SO3_ANAGLYPH_YB_STEREO] = "Stereo/YellowBlueAnaglyph";
101 mAvailableModes[SO3_INTERLACED_H_STEREO] = "Stereo/HorizontalInterlace";
102 mAvailableModes[SO3_INTERLACED_V_STEREO] = "Stereo/VerticalInterlace";
103 mAvailableModes[SO3_INTERLACED_CB_STEREO] = "Stereo/CheckboardInterlace";
104 mAvailableModes[SO3_SIDE_BY_SIDE_STEREO] = "Stereo/SideBySide";
105 mAvailableModes[SO3_CARDBOARD_STEREO] = "Stereo/Oculus";
106 mAvailableModes[SO3_UP_DOWN_STEREO] = "Stereo/UpDown";
107 mAvailableModes[SO3_QUAD_BUFFER_STEREO] = ""; // No compositor for quad buffer mode.
108 mAvailableModes[SO3_OCULUS_STEREO] = "Stereo/Oculus"; // previous value Stereo/Oculus
109 mAvailableModes[SO3_OCULUS2_STEREO] = "Stereo/Oculus";
110 mAvailableModes[SO3_OPENVR_STEREO] = "Stereo/stMono";
111 mAvailableModes[SO3_OCULUSM_STEREO] = "Stereo/stMono";
112 mAvailableModes[SO3_OPENXR_STEREO] = "Stereo/stMono";
113 mAvailableModes[SO3_NONE_STEREO] = ""; // Obviously no compositor if no stereo mode selected!
114 mAvailableModes[SO3_MONO_STEREO] = "Stereo/Mono";
115}
116
121
123{
124 return mStereoMode;
125}
126
128{
129 // Reset the stereo mode without touching the external window mode.
130 if(mStereoMode != SO3_NONE_STEREO)
131 {
132 // If the stereo technique uses a compositor
133 if(!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO))
134 {
135 // Remove device lost listener
136 Ogre::Root::getSingleton().getRenderSystem()->removeListener(mDeviceLostListener);
137 SAFE_DELETE(mDeviceLostListener);
138 }
139
140 StereoViewports::iterator iStereoViewport = stereoViewports.begin();
141 while(iStereoViewport != stereoViewports.end())
142 {
143 ShutdownViewport(iStereoViewport->first, iStereoViewport->second);
144 iStereoViewport++;
145 }
146
147 //if the quad buffer is not available we change to NONE
148 if ((mStereoMode == SO3_QUAD_BUFFER_STEREO) && (SRoot::getSingleton().GetQuadBufferEnable() == false))
149 {
150 mStereoMode = SO3_NONE_STEREO;
151 return;
152 }
153
154 if (stereoViewports.empty())
155 return;
156
157 iStereoViewport = stereoViewports.begin();
158 while(iStereoViewport != stereoViewports.end())
159 {
160 InitializeViewport(iStereoViewport->first, iStereoViewport->second);
161 iStereoViewport++;
162 }
163
164 // If the stereo technique uses a compositor
165 if(!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO))
166 {
167 // Add a device lost listener (not needed for OpenGL Quad buffer).
168 mDeviceLostListener = new DeviceLostListener(this);
169 Ogre::Root::getSingleton().getRenderSystem()->addListener(mDeviceLostListener);
170 }
171 }
172}
173
175{
176 if(mStereoMode != newStereoMode)
177 {
178 // Shutdown the old stereo mode.
179 if(mStereoMode != SO3_NONE_STEREO)
180 {
181 // If the stereo technique uses a compositor
182 if(!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO))
183 {
184 // Remove device lost listener
185 Ogre::Root::getSingleton().getRenderSystem()->removeListener(mDeviceLostListener);
186 SAFE_DELETE(mDeviceLostListener);
187 }
188
189 StereoViewports::iterator iStereoViewport = stereoViewports.begin();
190 while(iStereoViewport != stereoViewports.end())
191 {
192 ShutdownViewport(iStereoViewport->first, iStereoViewport->second);
193 iStereoViewport++;
194 }
195 }
196
197 // Activating the new stereo mode
198 mStereoMode = newStereoMode;
199 if (mStereoMode != SO3_NONE_STEREO)
200 {
201 //if the quad buffer is not available we change to NONE
202 if ((mStereoMode == SO3_QUAD_BUFFER_STEREO) && (SRoot::getSingleton().GetQuadBufferEnable() == false))
203 {
204 mStereoMode = SO3_NONE_STEREO;
205 return;
206 }
207
208 if (stereoViewports.empty())
209 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("StereoManager::SetStereoMode : At least one viewport must be registered\n");
210
211 StereoViewports::iterator iStereoViewport = stereoViewports.begin();
212 while(iStereoViewport != stereoViewports.end())
213 {
214 InitializeViewport(iStereoViewport->first, iStereoViewport->second);
215 iStereoViewport++;
216 }
217
218 // If the stereo technique uses a compositor
219 if(!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO))
220 {
221 // Add a device lost listener (not needed for OpenGL Quad buffer).
222 mDeviceLostListener = new DeviceLostListener(this);
223 Ogre::Root::getSingleton().getRenderSystem()->addListener(mDeviceLostListener);
224 }
225 }
226 }
227}
228
229bool StereoManager::UpdateStereoCompositorState(Ogre::Viewport* ogreViewportInstance, const Ogre::String compname, bool state)
230{
231 bool ret = false;
232 if(mStereoMode != SO3_NONE_STEREO && (!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO)))
233 {
234 StereoViewports::iterator iOgreViewports = stereoViewports.find(ogreViewportInstance);
235 if(iOgreViewports != stereoViewports.end())
236 {
237 StereoViewportData* viewportData = iOgreViewports->second;
238 viewportData->mCompList[compname] = state;
239
240 Ogre::CompositorManager &compositorManager = Ogre::CompositorManager::getSingleton();
241 if(viewportData->mLastLeftViewport && compositorManager.hasCompositorChain(viewportData->mLastLeftViewport))
242 {
243 Ogre::CompositorChain* chain = compositorManager.getCompositorChain(viewportData->mLastLeftViewport);
244 Ogre::CompositorInstance* compInstance = chain->getCompositor(compname);
245
246 if (compInstance)
247 {
248 compInstance->setEnabled(state);
249 ret = true;
250 }
251 }
252
253 if(viewportData->mLastRightViewport && compositorManager.hasCompositorChain(viewportData->mLastRightViewport))
254 {
255 Ogre::CompositorChain* chain = compositorManager.getCompositorChain(viewportData->mLastRightViewport);
256 Ogre::CompositorInstance* compInstance = chain->getCompositor(compname);
257
258 if (compInstance)
259 {
260 compInstance->setEnabled(state);
261 ret = true;
262 }
263 }
264 }
265 }
266
267 return ret;
268}
269
270void StereoManager::RestoreStereoCamera(Ogre::Viewport* ogreViewportInstance)
271{
272 if(mStereoMode != SO3_NONE_STEREO)
273 {
274 StereoViewports::iterator iOgreViewports = stereoViewports.find(ogreViewportInstance);
275 if(iOgreViewports != stereoViewports.end())
276 {
277 StereoViewportData* viewportData = iOgreViewports->second;
278
279 if (!viewportData->mCamera)
280 return;
281
282 if(!mIsCustomProjection)
283 {
284 viewportData->mCamera->setFrustumOffset(viewportData->mOldOffset);
285 }
286
287 viewportData->mCamera->setCustomProjectionMatrix(viewportData->mOldUseCustomMatrix, viewportData->mOldMatrix);
288 viewportData->mCamera->setAspectRatio(viewportData->mOldRatio);
289 viewportData->mCamera->setFOVy(viewportData->mOldFOV);
290
291 if((mStereoMode != SO3_MONO_STEREO) && (!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO)))
292 viewportData->mCamera->getParentSceneNode()->setPosition(viewportData->mOldPos);
293
294 viewportData->mCamera->resetFrustumExtents();
295
296 //hack to restore correct frustrum
297 try
298 {
299 ogreViewportInstance->setCamera(viewportData->mCamera);
300 ogreViewportInstance->_updateDimensions();
301 }
302 catch(Ogre::Exception&) //error can appen on compositor resources creation if the device is not ready
303 {
304 }
305
306 viewportData->mCamera = 0;
307 }
308 }
309}
310
311void StereoManager::UpdateStereoCamera(Ogre::Viewport* ogreViewportInstance, Ogre::Camera* camera)
312{
313 if(mStereoMode != SO3_NONE_STEREO)
314 {
315 StereoViewports::iterator iOgreViewports = stereoViewports.find(ogreViewportInstance);
316 if(iOgreViewports != stereoViewports.end())
317 {
318 StereoViewportData* viewportData = iOgreViewports->second;
319
320 if (mStereoMode != SO3_QUAD_BUFFER_STEREO) //keep the current camera on viewport
321 ogreViewportInstance->setCamera(viewportData->mStereoCamera);
322
323 SScene* scene = SRoot::getSingletonPtr()->GetScene(viewportData->mScene->getName());
324 if (scene && scene->GetEnvironment())
325 {
326 scene->GetEnvironment()->UnregisterCamera(viewportData->mCamera);
327 scene->GetEnvironment()->UnregisterCamera(viewportData->mStereoCamera);
328 }
329
330 viewportData->mCamera = camera;
331 if(!viewportData->mCamera)
332 return;
333
334 viewportData->mScene = camera->getSceneManager();
335 viewportData->mOldRatio = camera->getAspectRatio();
336 viewportData->mOldOffset = camera->getFrustumOffset();
337 viewportData->mOldPos = camera->getParentSceneNode()->getPosition();
338 viewportData->mOldFOV = camera->getFOVy();
339 viewportData->mOldMatrix = camera->getProjectionMatrix();
340 viewportData->mOldUseCustomMatrix = camera->isCustomProjectionMatrixEnabled();
341 Ogre::Real offset = 0.0f;
342
343 if (mStereoMode != SO3_MONO_STEREO)
344 offset = (viewportData->mFlipEyes ? (-0.5f) : (0.5f)) * GetEyesSpacing();
345
346 if (viewportData->mLastLeftViewport)
347 viewportData->mLastLeftViewport->setCamera(viewportData->mCamera);
348
349 if (viewportData->mLastRightViewport)
350 viewportData->mLastRightViewport->setCamera(viewportData->mCamera);
351
352 if (mIsCustomRatio)
353 {
354 viewportData->mCamera->setAspectRatio(mRatio);
355 }
356
357 if (mIsCustomFOV)
358 {
359 viewportData->mCamera->setFOVy(mFOV);
360 }
361
362 if(!mIsCustomProjection)
363 {
364 // get base matrix with fov set
365 viewportData->mBaseCameraMatrix = camera->getProjectionMatrix();
366
367 if (mIsCustomOffset)
368 {
369 Ogre::Matrix4 proj = Ogre::Matrix4::IDENTITY;
370 proj.setTrans(Ogre::Vector3(-mCenterOffset * (viewportData->mFlipEyes ? (-1) : 1), 0, 0));
371 viewportData->mCamera->setCustomProjectionMatrix(true, proj * viewportData->mBaseCameraMatrix);
372 //viewportData->mCamera->setFrustumOffset(viewportData->mOldOffset - Ogre::Vector2(-mCenterOffset, 0));
373 }
374 else if (offset != 0.0f)
375 {
376 viewportData->mCamera->setFrustumOffset(viewportData->mOldOffset + Ogre::Vector2(offset, 0));
377 }
378 }
379 else
380 {
381 viewportData->mCamera->setCustomProjectionMatrix(true, mLeftCustomProjection);
382 }
383
384 if ((mStereoMode != SO3_MONO_STEREO) && (!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO)))
385 {
386 viewportData->mCamera->getParentSceneNode()->setPosition(viewportData->mOldPos + (offset * (viewportData->mCamera->getParentSceneNode()->getOrientation() * Ogre::Vector3::UNIT_X)));
387 }
388 }
389 }
390}
391
392void StereoManager::UpdateStereoCameraMatrix(Ogre::Viewport* ogreViewportInstance, Ogre::Camera* camera)
393{
394 if(!camera)
395 return;
396
397 StereoViewports::iterator iOgreViewports = stereoViewports.find(ogreViewportInstance);
398 if(iOgreViewports != stereoViewports.end())
399 {
400 StereoViewportData* viewportData = iOgreViewports->second;
401 viewportData->mOldMatrix = camera->getProjectionMatrix();
402 viewportData->mOldUseCustomMatrix = camera->isCustomProjectionMatrixEnabled();
403
404 if(mStereoMode != SO3_NONE_STEREO)
405 {
406 if (mIsCustomRatio)
407 {
408 viewportData->mCamera->setAspectRatio(mRatio);
409 }
410
411 if (mIsCustomFOV)
412 {
413 viewportData->mCamera->setFOVy(mFOV);
414 }
415 }
416
417 // get base matrix with fov set
418 viewportData->mBaseCameraMatrix = camera->getProjectionMatrix();
419 }
420}
421
423{
424 StereoViewports::iterator iOgreViewports = stereoViewports.find(viewportInstance->GetOgreViewPortPointer());
425 if(iOgreViewports != stereoViewports.end())
426 return;
427
428 StereoViewportData* viewportData = new StereoViewportData();
429 stereoViewports.insert(StereoViewports::value_type(viewportInstance->GetOgreViewPortPointer(), viewportData));
430
431 InitializeViewport(viewportInstance->GetOgreViewPortPointer(), stereoViewports[viewportInstance->GetOgreViewPortPointer()]);
432}
433
435{
436 StereoViewports::iterator iOgreViewports = stereoViewports.find(viewportInstance->GetOgreViewPortPointer());
437 if(iOgreViewports != stereoViewports.end())
438 {
439 ShutdownViewport(viewportInstance->GetOgreViewPortPointer(), iOgreViewports->second);
440 SAFE_DELETE(iOgreViewports->second);
441 stereoViewports.erase(iOgreViewports);
442 }
443}
444
445bool StereoManager::IsViewportRegistered(Ogre::Viewport* ogreViewportInstance)
446{
447 StereoViewports::iterator iOgreViewports = stereoViewports.find(ogreViewportInstance);
448 if(iOgreViewports != stereoViewports.end())
449 return true;
450 else
451 return false;
452}
453
454void StereoManager::SynchViewportSetup(SViewPort* viewportInstance, bool overlay, bool shadow)
455{
456 Ogre::Viewport* viewport = viewportInstance->GetOgreViewPortPointer();
457 StereoViewports::iterator iOgreViewport = stereoViewports.find(viewport);
458 if (iOgreViewport == stereoViewports.end())
459 return;
460
461 StereoViewportData* viewportData = iOgreViewport->second;
462
463 Ogre::Viewport* stereoLeftViewport = 0;
464 Ogre::Viewport* stereoRightViewport = 0;
465
466 Ogre::uint32 mask = viewport->getVisibilityMask();
467
468 if (overlay)
469 viewportData->mOverlayEnable = viewport->getOverlaysEnabled();
470
471 if (shadow)
472 viewportData->mShadowEnable = viewport->getShadowsEnabled();
473
474 viewportData->mSkyEnable = viewport->getSkiesEnabled();
475 viewportData->mMaterialScheme = viewport->getMaterialScheme();
476 viewportData->mMask = mask;
477 viewportData->mBackgroundColor = viewport->getBackgroundColour();
478 viewportData->mOldBackgroundColor = viewport->getBackgroundColour();
479
480 if ((mStereoMode != SO3_MONO_STEREO) && (mStereoMode != SO3_NONE_STEREO))
481 {
482 viewport->setOverlaysEnabled(false);
483 viewport->setShadowsEnabled(false);
484 }
485
486 // viewport from RTT
487 if (viewportData->mLeftRenderTexture)
488 {
489 stereoLeftViewport = viewportData->mLeftRenderTexture->getBuffer()->getRenderTarget()->getViewport(0);
490 if (stereoLeftViewport)
491 {
492 stereoLeftViewport->setOverlaysEnabled(viewportData->mOverlayEnable);
493 stereoLeftViewport->setShadowsEnabled(viewportData->mShadowEnable);
494 stereoLeftViewport->setVisibilityMask(viewportData->mMask);
495 stereoLeftViewport->setBackgroundColour(viewportData->mBackgroundColor);
496 stereoLeftViewport->setSkiesEnabled(viewportData->mSkyEnable);
497 stereoLeftViewport->setMaterialScheme(viewportData->mMaterialScheme);
498 }
499 }
500
501 if (mStereoMode != SO3_MONO_STEREO && viewportData->mRightRenderTexture)
502 {
503 stereoRightViewport = viewportData->mRightRenderTexture->getBuffer()->getRenderTarget()->getViewport(0);
504 if (stereoRightViewport)
505 {
506 stereoRightViewport->setShadowsEnabled(viewportData->mShadowEnable);
507 stereoRightViewport->setOverlaysEnabled(viewportData->mOverlayEnable);
508 stereoRightViewport->setVisibilityMask(viewportData->mMask);
509 stereoRightViewport->setBackgroundColour(viewportData->mBackgroundColor);
510 stereoRightViewport->setSkiesEnabled(viewportData->mSkyEnable);
511 stereoRightViewport->setMaterialScheme(viewportData->mMaterialScheme);
512 }
513 }
514}
515
516void StereoManager::InitializeViewport(Ogre::Viewport* viewport, StereoViewportData* viewportData)
517{
518 viewportData->mOriginalViewport = viewport;
519
520 Ogre::Camera* camera = viewport->getCamera();
521 if(!camera)
522 return;
523
524 // Register camera shifting listeners.
525 try
526 {
527 if(mStereoMode != SO3_NONE_STEREO)
528 {
529 viewportData->mCamera = camera;
530 viewportData->mScene = camera->getSceneManager();
531
532 viewportData->mOriginalViewportSize = Ogre::Vector2(viewport->getActualWidth(), viewport->getActualHeight());
533
534 if (mStereoMode == SO3_OCULUSM_STEREO)
535 viewport->setDimensions(0.0f, 0.0f, 2.0f / (float)viewport->getActualWidth(), 2.0f / (float)viewport->getActualHeight());
536
537#ifdef ANDROID
538 if (mStereoMode == SO3_OPENXR_STEREO)
539 viewport->setDimensions(0.0f, 0.0f, 2.0f / (float)viewport->getActualWidth(), 2.0f / (float)viewport->getActualHeight());
540#endif
541
542 // If the stereo technique uses a compositor
543 if(!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO))
544 {
545 viewportData->mStereoScene = Ogre::Root::getSingletonPtr()->createSceneManager(Ogre::SMT_DEFAULT, SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/SCENE") + Ogre::StringConverter::toString(viewport->getZOrder() + 1));
546 Ogre::AxisAlignedBox octreeBox(-1, -1, -1, 1, 1, 1);
547 int octreeDepth = 0;
548 viewportData->mStereoScene->setOption("Size", &octreeBox);
549 viewportData->mStereoScene->setOption("Depth", &octreeDepth);
550
551 Ogre::RenderQueue* rq = viewportData->mStereoScene->getRenderQueue();
552 rq->getQueueGroup(Ogre::RENDER_QUEUE_WORLD_GEOMETRY_1)->setShadowsEnabled(false);
553 rq->getQueueGroup(Ogre::RENDER_QUEUE_WORLD_GEOMETRY_2)->setShadowsEnabled(false);
554 rq->getQueueGroup(Ogre::RENDER_QUEUE_MAIN)->setShadowsEnabled(false);
555
556 viewportData->mStereoCamera = viewportData->mStereoScene->createCamera(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/CAMERA") + Ogre::StringConverter::toString(viewport->getZOrder() + 1));
557 viewportData->mStereoCamera->setFarClipDistance(100.0f);
558 viewportData->mStereoCamera->setNearClipDistance(0.1f);
559 viewportData->mStereoCamera->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
560 viewportData->mStereoCamera->setOrthoWindow(2.0f, 2.0f);
561
562 if (mExternalWindow && (mExternalWindow->getNumViewports() == 0))
563 {
564 mExternalViewport = mExternalWindow->addViewport(viewportData->mStereoCamera);
565 mExternalViewport->setMaterialScheme(viewport->getMaterialScheme());
566 }
567
568 if (mRotateView)
569 viewportData->mStereoCameraNode->roll(Ogre::Degree(-90));
570
571 viewportData->mStereoScene->getRootSceneNode()->attachObject(viewportData->mStereoCamera);
572 InitializeListeners(viewport, viewportData);
573
574 viewportData->viewportListener = new StereoViewportListener(this, viewportData);
575 viewportData->frameListener = new StereoFrameListener(this, viewportData);
576
577 if (mExternalWindow)
578 mExternalWindow->addListener(viewportData->viewportListener);
579 mBuffer->GetOgreRenderWindowPointer()->addListener(viewportData->viewportListener);
580
581 Ogre::Root::getSingletonPtr()->addFrameListener(viewportData->frameListener);
582
583 // Create mesh or compositor instance on the viewport, and activate it.
584 InitializeStereo(viewport, viewportData);
585 }
586 else if (mAvailableModes[mStereoMode].empty()) // quad buffer
587 {
588 viewportData->mFlipEyes = true;
589 }
590
591 UpdateStereoCamera(viewport, camera);
592 }
593 }
594 catch(Ogre::Exception& e)
595 {
596 std::string mess(e.what());
597
598 //error
599 0;
600 }
601}
602
603void StereoManager::ShutdownViewport(Ogre::Viewport* viewport, StereoViewportData* viewportData)
604{
605 // If the stereo technique uses a compositor
606 if(!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO))
607 {
608 // Deactivate the compositor instance and destroy it.
609 ShutdownStereo(viewport, viewportData);
610
611 ShutdownListeners(viewport, viewportData);
612 try
613 {
614 if (mExternalViewport)
615 {
616 mExternalWindow->removeViewport(mExternalViewport->getZOrder());
617 mExternalViewport = 0;
618 }
619
620 if (viewportData->mStereoScene)
621 {
622 Ogre::Root::getSingletonPtr()->destroySceneManager(viewportData->mStereoScene);
623 }
624 }
625 catch(Ogre::Exception&)
626 {
627 // update failed maybe D3D device lost
628 }
629
630 if (viewportData->viewportListener && mBuffer)
631 {
632 if (mExternalWindow)
633 mExternalWindow->removeListener(viewportData->viewportListener);
634
635 mBuffer->GetOgreRenderWindowPointer()->removeListener(viewportData->viewportListener);
636 }
637 SAFE_DELETE(viewportData->viewportListener);
638
639 if (viewportData->frameListener)
640 Ogre::Root::getSingletonPtr()->removeFrameListener(viewportData->frameListener);
641
642 SAFE_DELETE(viewportData->frameListener);
643 }
644
645 //reset camera
646 if (!viewportData->mCamera)
647 return;
648
649 if(mStereoMode != SO3_NONE_STEREO)
650 {
651 RestoreStereoCamera(viewport);
652
653 //restore overlays
654 SWidgetManager* wmanager = SWidgetManager::getSingletonPtr();
655 SWidgetManager::WidgetList wlist = wmanager->GetWidgetList();
656 for (SWidgetManager::WidgetList::const_iterator wIt = wlist.begin(); wIt != wlist.end(); wIt++)
657 {
658 SWidget* widget = (wIt->second);
659 if (widget->GetIsOverlayed() || widget->GetIs2DRect())
660 {
661 if (mIsCustomRatio || !mAvailableModes[mStereoMode].empty())
662 {
663 widget->SetScale(1.0, 1.0);
664
665 widget->SetLeftOffset(0.0f);
666 widget->SetTopOffset(0.0f);
667 }
668 }
669 }
670 }
671}
672
673void StereoManager::ReleaseRttTarget(StereoViewportData* viewportData)
674{
675 Ogre::CompositorManager &compositorManager = Ogre::CompositorManager::getSingleton();
676 if (!viewportData->mScene)
677 return;
678
679 SScene* scene = SRoot::getSingletonPtr()->GetScene(viewportData->mScene->getName());
680
681 //clear compositor resources
682 if(viewportData->mLastLeftViewport)
683 {
684 viewportData->mLastLeftViewport->getTarget()->removeListener(viewportData->leftCameraListener);
685
686 if (scene && scene->GetEnvironment())
687 {
688 if (scene->GetEnvironment()->GetWater())
689 scene->GetEnvironment()->GetWater()->RemoveViewport(viewportData->mLastLeftViewport);
690
691 if (scene->GetEnvironment()->GetSky())
692 scene->GetEnvironment()->GetSky()->RemoveViewport(viewportData->mLastLeftViewport);
693 }
694
695 if (compositorManager.hasCompositorChain(viewportData->mLastLeftViewport))
696 {
697 Ogre::CompositorChain* chain = compositorManager.getCompositorChain(viewportData->mLastLeftViewport);
698 if (chain)
699 {
700 Ogre::CompositorChain::Instances instances = chain->getCompositorInstances();
701 for(unsigned int i = 0; i < instances.size(); i++)
702 {
703 Ogre::CompositorInstance *compositorInstance = instances.at(i);
704 Ogre::Compositor *compositor = compositorInstance->getCompositor();
705
706 //free ressources
707 compositorInstance->setAlive(false);
708 }
709 chain->removeAllCompositors();
710 compositorManager.removeCompositorChain(viewportData->mLastLeftViewport);
711 }
712 }
713 viewportData->mLastLeftViewport = 0;
714 }
715
716 if(viewportData->mLastRightViewport)
717 {
718 viewportData->mLastRightViewport->getTarget()->removeListener(viewportData->rightCameraListener);
719
720 if (scene && scene->GetEnvironment())
721 {
722 if (scene->GetEnvironment()->GetWater())
723 scene->GetEnvironment()->GetWater()->RemoveViewport(viewportData->mLastRightViewport);
724
725 if (scene->GetEnvironment()->GetSky())
726 scene->GetEnvironment()->GetSky()->RemoveViewport(viewportData->mLastRightViewport);
727 }
728
729 if (compositorManager.hasCompositorChain(viewportData->mLastRightViewport))
730 {
731 Ogre::CompositorChain* chain = compositorManager.getCompositorChain(viewportData->mLastRightViewport);
732 if (chain)
733 {
734 Ogre::CompositorChain::Instances instances = chain->getCompositorInstances();
735 for (unsigned int i = 0; i < instances.size(); i++)
736 {
737 Ogre::CompositorInstance *compositorInstance = instances.at(i);
738 Ogre::Compositor *compositor = compositorInstance->getCompositor();
739
740 //free ressources
741 compositorInstance->setAlive(false);
742 }
743 chain->removeAllCompositors();
744 compositorManager.removeCompositorChain(viewportData->mLastRightViewport);
745 }
746 }
747 viewportData->mLastRightViewport = 0;
748 }
749
750 try
751 {
752 if(viewportData->mLeftRenderTexture)
753 viewportData->mLeftRenderTexture->getBuffer()->getRenderTarget()->removeAllViewports();
754
755 if(viewportData->mRightRenderTexture)
756 viewportData->mRightRenderTexture->getBuffer()->getRenderTarget()->removeAllViewports();
757 }
758 catch(Ogre::Exception&)
759 {
760 // update failed maybe D3D device lost
761 }
762}
763
764void StereoManager::ConstructRttTarget(StereoViewportData* viewportData)
765{
766 Ogre::CompositorManager &compositorManager = Ogre::CompositorManager::getSingleton();
767 SScene* scene = SRoot::getSingletonPtr()->GetScene(viewportData->mScene->getName());
768
769 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
770 bool isD3D = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? true : false;
771
772 Ogre::Viewport* stereoLeftViewport = 0;
773 Ogre::Viewport* stereoRightViewport = 0;
774
775 // viewport from RTT
776 if (viewportData->mLeftRenderTexture)
777 {
778 stereoLeftViewport = viewportData->mLeftRenderTexture->getBuffer()->getRenderTarget()->addViewport(viewportData->mCamera);
779 stereoLeftViewport->setOverlaysEnabled(viewportData->mOverlayEnable);
780 stereoLeftViewport->setShadowsEnabled(viewportData->mShadowEnable);
781 stereoLeftViewport->setVisibilityMask(viewportData->mMask);
782 stereoLeftViewport->setBackgroundColour(viewportData->mBackgroundColor);
783 stereoLeftViewport->setSkiesEnabled(viewportData->mSkyEnable);
784 stereoLeftViewport->setMaterialScheme(viewportData->mMaterialScheme);
785 }
786
787 if (mStereoMode != SO3_MONO_STEREO && viewportData->mRightRenderTexture)
788 {
789 stereoRightViewport = viewportData->mRightRenderTexture->getBuffer()->getRenderTarget()->addViewport(viewportData->mCamera);
790 stereoRightViewport->setShadowsEnabled(viewportData->mShadowEnable);
791 stereoRightViewport->setOverlaysEnabled(viewportData->mOverlayEnable);
792 stereoRightViewport->setVisibilityMask(viewportData->mMask);
793 stereoRightViewport->setBackgroundColour(viewportData->mBackgroundColor);
794 stereoRightViewport->setSkiesEnabled(viewportData->mSkyEnable);
795 stereoRightViewport->setMaterialScheme(viewportData->mMaterialScheme);
796 }
797
798 //apply compositors
799 if (viewportData->mCompIndexList.size() > 0)
800 {
801 CompositorIndexList::iterator compIt = viewportData->mCompIndexList.begin();
802 CompositorIndexList::iterator compItEnd = viewportData->mCompIndexList.end();
803
804 while (compIt != compItEnd)
805 {
806 if (stereoLeftViewport)
807 {
808 compositorManager.addCompositor(stereoLeftViewport, *compIt);
809 compositorManager.setCompositorEnabled(stereoLeftViewport, *compIt, viewportData->mCompList[*compIt]);
810 }
811
812 if (mStereoMode != SO3_MONO_STEREO && stereoRightViewport)
813 {
814 compositorManager.addCompositor(stereoRightViewport, *compIt);
815 compositorManager.setCompositorEnabled(stereoRightViewport, *compIt, viewportData->mCompList[*compIt]);
816 }
817 ++compIt;
818 }
819 }
820
821 //flip Y
822 if ((mStereoMode == SO3_OPENXR_STEREO) && !isD3D)
823 {
824 compositorManager.addCompositor(stereoLeftViewport, "FlipVertically");
825 compositorManager.setCompositorEnabled(stereoLeftViewport, "FlipVertically", true);
826 compositorManager.addCompositor(stereoRightViewport, "FlipVertically");
827 compositorManager.setCompositorEnabled(stereoRightViewport, "FlipVertically", true);
828 }
829
830 if (scene && scene->GetEnvironment() && scene->GetEnvironment()->IsRegisteredViewport(viewportData->mOriginalViewport))
831 {
832 if (stereoLeftViewport)
833 {
834 if (scene->GetEnvironment()->GetWater() && scene->GetEnvironment()->GetWater()->GetEnable())
835 scene->GetEnvironment()->GetWater()->AddViewport(stereoLeftViewport);
836
837 if (scene->GetEnvironment()->GetSky() && scene->GetEnvironment()->GetSky()->GetEnable())
838 scene->GetEnvironment()->GetSky()->AddViewport(stereoLeftViewport);
839 }
840
841 if (stereoRightViewport)
842 {
843 if (scene->GetEnvironment()->GetWater() && scene->GetEnvironment()->GetWater()->GetEnable())
844 scene->GetEnvironment()->GetWater()->AddViewport(stereoRightViewport);
845
846 if (scene->GetEnvironment()->GetSky() && scene->GetEnvironment()->GetSky()->GetEnable())
847 scene->GetEnvironment()->GetSky()->AddViewport(stereoLeftViewport);
848 }
849 }
850
851 // add listener for stereo
852 if (stereoLeftViewport)
853 {
854 stereoLeftViewport->getTarget()->insertListener(viewportData->leftCameraListener);
855 viewportData->mLastLeftViewport = stereoLeftViewport;
856 }
857
858 if (mStereoMode != SO3_MONO_STEREO && stereoRightViewport)
859 {
860 stereoRightViewport->getTarget()->insertListener(viewportData->rightCameraListener);
861 viewportData->mLastRightViewport = stereoRightViewport;
862 }
863}
864
865void StereoManager::InitializeStereo(Ogre::Viewport* viewport, StereoViewportData* viewportData)
866{
867 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
868 bool isD3D = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? true : false;
869
870 //remove the viewport from hydrax
871 SScene* scene = SRoot::getSingletonPtr()->GetScene(viewportData->mScene->getName());
872 if (scene && scene->GetEnvironment() && scene->GetEnvironment()->IsRegisteredViewport(viewport))
873 {
874 if (scene->GetEnvironment()->GetWater())
875 scene->GetEnvironment()->GetWater()->RemoveViewport(viewport);
876
877 if (scene->GetEnvironment()->GetSky())
878 scene->GetEnvironment()->GetSky()->RemoveViewport(viewport);
879 }
880
881 // extract all the compositors added to the main viewport and attach them to the left/right vewports
882 Ogre::CompositorManager &compositorManager = Ogre::CompositorManager::getSingleton();
883 Ogre::CompositorChain* oldChain = 0;
884 if(compositorManager.hasCompositorChain(viewport))
885 oldChain = compositorManager.getCompositorChain(viewport);
886
887 //get current compositors
888 if (oldChain)
889 {
890 Ogre::CompositorChain::Instances instances = oldChain->getCompositorInstances();
891 for (unsigned int i = 0; i < instances.size(); i++)
892 {
893 Ogre::CompositorInstance *compositorInstance = instances.at(i);
894 Ogre::Compositor *compositor = compositorInstance->getCompositor();
895
896 //update list
897 viewportData->mCompList.insert(viewportData->mCompList.begin(), std::pair<std::string, bool>(compositor->getName(), compositorInstance->getEnabled()));
898 viewportData->mCompIndexList.push_back(compositor->getName());
899
900 // disable the compositors from the main viewport since they will be on the left/right vewports
901 oldChain->setCompositorEnabled(i, false);
902 }
903
904 // force update for shadows
905 compositorManager.getCompositorChain(viewport)->_markDirty();
906 }
907
908 // enable the overlays on the new viewports and disable them from the main viewport
909 Ogre::uint32 mask = viewport->getVisibilityMask();
910 viewportData->mOverlayEnable = viewport->getOverlaysEnabled();
911 viewportData->mShadowEnable = viewport->getShadowsEnabled();
912 viewportData->mSkyEnable = viewport->getSkiesEnabled();
913 viewportData->mMaterialScheme = viewport->getMaterialScheme();
914 viewportData->mMask = mask;
915 viewportData->mBackgroundColor = viewport->getBackgroundColour();
916 viewportData->mOldBackgroundColor = viewport->getBackgroundColour();
917
918 //if (!mAvailableModes[mStereoMode].empty() || (mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMode == SO3_OCULUS_STEREO))
919 // viewport->setBackgroundColour(Ogre::ColourValue::Black);
920
921 viewport->setOverlaysEnabled(false);
922 viewport->setShadowsEnabled(false);
923
924 if ((mStereoMode != SO3_OCULUS2_STEREO) && (mStereoMode != SO3_OCULUS_STEREO))
925 {
926 Ogre::MaterialPtr mat = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName(mAvailableModes[mStereoMode], SO3_INTERNAL_RESOURCE_GROUP));
927 if(!mat)
928 OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, mAvailableModes[mStereoMode] + " not found, missing StereoManager resources", "StereoManager::InitializeStereo");
929
930 viewportData->rttListener = new StereoRTTListener(this, viewportData);
931
932 int leftWidth = (mStereoMode == SO3_CARDBOARD_STEREO) ? viewport->getActualWidth() / 2 : viewport->getActualWidth();
933 int leftHeight = viewport->getActualHeight();
934 int rightWidth = (mStereoMode == SO3_CARDBOARD_STEREO) ? viewport->getActualWidth() / 2 : viewport->getActualWidth();
935 int rightHeight = viewport->getActualHeight();
936
937 /*
938#ifndef _WIN32
939 leftWidth = leftWidth / 2;
940 leftHeight = leftHeight / 2;
941 rightWidth = rightWidth / 2;
942 rightHeight = rightHeight / 2;
943#endif
944 */
945
946 if (mLeftRenderTextureSize.x != 1 && mRightRenderTextureSize.x != 1)
947 {
948 leftWidth = (mStereoMode == SO3_CARDBOARD_STEREO) ? mLeftRenderTextureSize.x / 2 : mLeftRenderTextureSize.x;
949 leftHeight = mLeftRenderTextureSize.y;
950 rightWidth = (mStereoMode == SO3_CARDBOARD_STEREO) ? mRightRenderTextureSize.x / 2 : mRightRenderTextureSize.x;
951 rightHeight = mRightRenderTextureSize.y;
952 }
953
954 //create textures
955 Ogre::PixelFormat rttFormat = (mStereoMode == SO3_OPENXR_STEREO) ? (isD3D ? Ogre::PF_R8G8B8A8 : Ogre::PF_SHORT_RGBA) : ((mStereoMode == SO3_OPENVR_STEREO) || (mStereoMode == SO3_OCULUSM_STEREO)) ? Ogre::PF_R8G8B8A8 : Ogre::PF_R8G8B8;
956
957 viewportData->mLeftRenderTexture = Ogre::TextureManager::getSingleton().createManual(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/LEFT/RTT") + Ogre::StringConverter::toString(viewport->getZOrder() + 1), SO3_INTERNAL_RESOURCE_GROUP, Ogre::TEX_TYPE_2D, leftWidth, leftHeight, 0, rttFormat, Ogre::TU_RENDERTARGET);
958 viewportData->mLeftRenderTexture->getBuffer()->getRenderTarget()->setAutoUpdated(false);
959
960 #if defined (RPI)
961 viewportData->mLeftRenderTexture->getBuffer()->getRenderTarget()->setDepthBufferPool(Ogre::DepthBuffer::POOL_NO_DEPTH);
962#endif
963 viewportData->mLeftRenderTexture->addListener(viewportData->rttListener);
964
965 if (mStereoMode != SO3_MONO_STEREO)
966 {
967 viewportData->mRightRenderTexture = Ogre::TextureManager::getSingleton().createManual(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/RIGHT/RTT") + Ogre::StringConverter::toString(viewport->getZOrder() + 1), SO3_INTERNAL_RESOURCE_GROUP, Ogre::TEX_TYPE_2D, rightWidth, rightHeight, 0, rttFormat, Ogre::TU_RENDERTARGET);
968 viewportData->mRightRenderTexture->getBuffer()->getRenderTarget()->setAutoUpdated(false);
969
970#if defined (RPI)
971 viewportData->mRightRenderTexture->getBuffer()->getRenderTarget()->setDepthBufferPool(Ogre::DepthBuffer::POOL_NO_DEPTH);
972#endif
973 viewportData->mRightRenderTexture->addListener(viewportData->rttListener);
974 }
975
976 //set textures on materials
977 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(viewportData->mLeftRenderTexture);
978
979 if (mStereoMode != SO3_MONO_STEREO)
980 mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTexture(viewportData->mRightRenderTexture);
981
982 //createnode
983 viewportData->mStereoCameraNode = viewportData->mStereoScene->createSceneNode(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/CAMERA/NODE") + Ogre::StringConverter::toString(viewport->getZOrder() + 1));
984 viewportData->mStereoScene->getRootSceneNode()->addChild(viewportData->mStereoCameraNode);
985
986 viewportData->mRect = new Ogre::Rectangle2D(true);
987 viewportData->mRect->setCastShadows(false);
988 viewportData->mRect->setMaterial(mat);
989 viewportData->mRect->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND);
990 viewportData->mStereoScene->getRootSceneNode()->attachObject(viewportData->mRect);
991 viewportData->mRect->setCorners(-1.0f, 1.0f, 1.0f, -1.0f);
992
993 //flip Y
994 if ((mStereoMode == SO3_OPENXR_STEREO) && !isD3D)
995 viewportData->mRect->setUVs(Ogre::Vector2::UNIT_Y, Ogre::Vector2::ZERO, Ogre::Vector2::UNIT_SCALE, Ogre::Vector2::UNIT_X);
996
997 // Use infinite AAB to always stay visible
998 Ogre::AxisAlignedBox aabInf;
999 aabInf.setInfinite();
1000 viewportData->mRect->setBoundingBox(aabInf);
1001 viewportData->mRect->setVisible(true);
1002
1003 /*if (mStereoMode == SO3_OCULUS_STEREO)
1004 {
1005 Ogre::GpuProgramParametersSharedPtr shaderParams = mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters();
1006 if (mIsCustomDistortion)
1007 {
1008 shaderParams->setNamedConstant("HmdWarpParam", mDistortion);
1009 }
1010
1011 if (mIsCustomChromAbCorrection)
1012 {
1013 shaderParams->setNamedConstant("ChromAbParam", mChromAbCorrection);
1014 }
1015
1016 if (mIsCustomOffset)
1017 {
1018 shaderParams->setNamedConstant("projOffset", mCenterOffset);
1019 }
1020 }*/
1021 }
1022 else
1023 {
1024 if (!mLeftMesh || !mRightMesh)
1025 return;
1026
1027 //TODO should copy materials in viewportData for multi instances
1028 //load materials
1029 Ogre::MaterialPtr leftmat = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName("Stereo/Oculus/Distortion/Left", SO3_INTERNAL_RESOURCE_GROUP));
1030 if(!leftmat)
1031 OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, mAvailableModes[mStereoMode] + " not found, missing StereoManager resources", "StereoManager::InitializeStereo");
1032
1033 Ogre::MaterialPtr rightmat = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName("Stereo/Oculus/Distortion/Right", SO3_INTERNAL_RESOURCE_GROUP));
1034 if(!leftmat)
1035 OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, mAvailableModes[mStereoMode] + " not found, missing StereoManager resources", "StereoManager::InitializeStereo");
1036
1037 Ogre::GpuProgramParametersSharedPtr leftShaderParams = leftmat->getTechnique(0)->getPass(0)->getVertexProgramParameters();
1038 leftShaderParams->setNamedConstant("eyeToSourceUVScale", mLeftUVScale);
1039 leftShaderParams->setNamedConstant("eyeToSourceUVOffset", mLeftUVOffset);
1040
1041 Ogre::GpuProgramParametersSharedPtr rightShaderParams = rightmat->getTechnique(0)->getPass(0)->getVertexProgramParameters();
1042 rightShaderParams->setNamedConstant("eyeToSourceUVScale", mRightUVScale);
1043 rightShaderParams->setNamedConstant("eyeToSourceUVOffset", mRightUVOffset);
1044
1045 viewportData->rttListener = new StereoRTTListener(this, viewportData);
1046
1047 //create textures
1048 Ogre::PixelFormat rttFormat = Ogre::PF_R8G8B8;
1049
1050 viewportData->mLeftRenderTexture = Ogre::TextureManager::getSingleton().createManual(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/LEFT/RTT") + Ogre::StringConverter::toString(viewport->getZOrder() + 1), SO3_INTERNAL_RESOURCE_GROUP, Ogre::TEX_TYPE_2D, mLeftRenderTextureSize.x, mLeftRenderTextureSize.y, 0, rttFormat, Ogre::TU_RENDERTARGET);
1051 viewportData->mRightRenderTexture = Ogre::TextureManager::getSingleton().createManual(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/RIGHT/RTT") + Ogre::StringConverter::toString(viewport->getZOrder() + 1), SO3_INTERNAL_RESOURCE_GROUP, Ogre::TEX_TYPE_2D, mRightRenderTextureSize.x, mRightRenderTextureSize.y, 0, rttFormat, Ogre::TU_RENDERTARGET);
1052 viewportData->mLeftRenderTexture->getBuffer()->getRenderTarget()->setAutoUpdated(false);
1053 viewportData->mRightRenderTexture->getBuffer()->getRenderTarget()->setAutoUpdated(false);
1054
1055#if defined (RPI)
1056 viewportData->mLeftRenderTexture->getBuffer()->getRenderTarget()->setDepthBufferPool(Ogre::DepthBuffer::POOL_NO_DEPTH);
1057 viewportData->mRightRenderTexture->getBuffer()->getRenderTarget()->setDepthBufferPool(Ogre::DepthBuffer::POOL_NO_DEPTH);
1058#endif
1059
1060 viewportData->mLeftRenderTexture->addListener(viewportData->rttListener);
1061 viewportData->mRightRenderTexture->addListener(viewportData->rttListener);
1062
1063 //set textures on materials
1064 leftmat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(viewportData->mLeftRenderTexture);
1065 rightmat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(viewportData->mRightRenderTexture);
1066
1067 //createnode
1068 viewportData->mStereoCameraNode = viewportData->mStereoScene->createSceneNode(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/CAMERA/NODE") + Ogre::StringConverter::toString(viewport->getZOrder() + 1));
1069 viewportData->mStereoScene->getRootSceneNode()->addChild(viewportData->mStereoCameraNode);
1070
1071 viewportData->mLeftEntity = viewportData->mStereoScene->createEntity(mLeftMesh);
1072 viewportData->mRightEntity = viewportData->mStereoScene->createEntity(mRightMesh);
1073 viewportData->mStereoCameraNode->attachObject(viewportData->mLeftEntity);
1074 viewportData->mStereoCameraNode->attachObject(viewportData->mRightEntity);
1075
1076 viewportData->mStereoCameraNode->setPosition(0.0f, 0.0f, -1.0f);
1077 viewportData->mStereoCameraNode->setScale(1.0f, 1.0f, -1.0f);
1078 }
1079
1080 ReleaseRttTarget(viewportData);
1081 ConstructRttTarget(viewportData);
1082}
1083
1084void StereoManager::ShutdownStereo(Ogre::Viewport* viewport, StereoViewportData* viewportData)
1085{
1086 if (mStereoMode == SO3_OCULUSM_STEREO)
1087 viewport->setDimensions(0.0f, 0.0f, 1.0f, 1.0f);
1088
1089#ifdef ANDROID
1090 if (mStereoMode == SO3_OPENXR_STEREO)
1091 viewport->setDimensions(0.0f, 0.0f, 1.0f, 1.0f);
1092#endif
1093
1094 ReleaseRttTarget(viewportData);
1095
1096 Ogre::CompositorManager &compositorManager = Ogre::CompositorManager::getSingleton();
1097 SScene* scene = SRoot::getSingletonPtr()->GetScene(viewportData->mScene->getName());
1098
1099 // put back the compositors on the main viewport
1100 Ogre::CompositorChain* mainChain = compositorManager.getCompositorChain(viewport);
1101 if (mainChain)
1102 {
1103 CompositorIndexList::iterator compIt = viewportData->mCompIndexList.begin();
1104 CompositorIndexList::iterator compItEnd = viewportData->mCompIndexList.end();
1105
1106 while (compIt != compItEnd)
1107 {
1108 Ogre::CompositorInstance* inst = mainChain->getCompositor(*compIt);
1109 if (inst)
1110 inst->setEnabled(viewportData->mCompList[*compIt]);
1111 ++compIt;
1112 }
1113
1114 mainChain->_markDirty();
1115 }
1116
1117 viewport->setOverlaysEnabled(viewportData->mOverlayEnable);
1118 viewport->setShadowsEnabled(viewportData->mShadowEnable);
1119 viewport->setBackgroundColour(viewportData->mBackgroundColor);
1120
1121 if (scene && scene->GetEnvironment() && scene->GetEnvironment()->IsRegisteredViewport(viewport))
1122 {
1123 if (scene->GetEnvironment()->GetWater() && scene->GetEnvironment()->GetWater()->GetEnable())
1124 scene->GetEnvironment()->GetWater()->AddViewport(viewport);
1125
1126 if (scene->GetEnvironment()->GetSky() && scene->GetEnvironment()->GetSky()->GetEnable())
1127 scene->GetEnvironment()->GetSky()->AddViewport(viewport);
1128 }
1129
1130 if (scene && scene->GetEnvironment())
1131 {
1132 scene->GetEnvironment()->UnregisterCamera(viewportData->mCamera);
1133 scene->GetEnvironment()->UnregisterCamera(viewportData->mStereoCamera);
1134 }
1135
1136 //Delete resources
1137 if (viewportData->mStereoScene)
1138 {
1139 if (viewportData->mLeftEntity)
1140 viewportData->mStereoScene->destroyEntity(viewportData->mLeftEntity);
1141 if (viewportData->mRightEntity)
1142 viewportData->mStereoScene->destroyEntity(viewportData->mRightEntity);
1143 }
1144
1145 viewportData->mLeftEntity = 0;
1146 viewportData->mRightEntity = 0;
1147
1148 if(viewportData->mLeftRenderTexture)
1149 {
1150 viewportData->mLeftRenderTexture->removeListener(viewportData->rttListener);
1151 viewportData->mLeftRenderTexture->unload();
1152 Ogre::TextureManager::getSingleton().remove(viewportData->mLeftRenderTexture->getHandle());
1153 viewportData->mLeftRenderTexture.reset();
1154 }
1155
1156 if(viewportData->mRightRenderTexture)
1157 {
1158 viewportData->mRightRenderTexture->removeListener(viewportData->rttListener);
1159 viewportData->mRightRenderTexture->unload();
1160 Ogre::TextureManager::getSingleton().remove(viewportData->mRightRenderTexture->getHandle());
1161 viewportData->mRightRenderTexture.reset();
1162 }
1163
1164 if (viewportData->mStereoCameraNode)
1165 {
1166 viewportData->mStereoCameraNode->detachAllObjects();
1167 viewportData->mStereoCameraNode = 0;
1168 }
1169
1170 if (viewportData->mRect)
1171 {
1172 viewportData->mRect->detachFromParent();
1173 delete(viewportData->mRect);
1174 viewportData->mRect = 0;
1175 }
1176
1177 SAFE_DELETE(viewportData->rttListener);
1178
1179 // No more compositor.
1180 viewportData->mCompList.clear();
1181 viewportData->mCompIndexList.clear();
1182}
1183
1184void StereoManager::InitializeListeners(Ogre::Viewport* viewport, StereoViewportData* viewportData)
1185{
1186 viewportData->leftCameraListener = new StereoCameraListener(this, viewportData->mFlipEyes ? false : true, viewport, viewportData);
1187
1188 if (mStereoMode != SO3_MONO_STEREO)
1189 viewportData->rightCameraListener = new StereoCameraListener(this, viewportData->mFlipEyes ? true : false, viewport, viewportData);
1190 else
1191 viewportData->rightCameraListener = 0;
1192}
1193
1194void StereoManager::ShutdownListeners(Ogre::Viewport* viewport, StereoViewportData* viewportData)
1195{
1196 SAFE_DELETE(viewportData->leftCameraListener);
1197 SAFE_DELETE(viewportData->rightCameraListener);
1198}
1199
1200//---------------------------- Stereo tuning ------------------------
1202{
1203 return mEyesSpacing;
1204}
1205
1207{
1208 mEyesSpacing = l;
1209}
1210
1211void StereoManager::SetCustomProjectonMatrices(bool enable, const Ogre::Matrix4& leftMatrix, const Ogre::Matrix4& rightMatrix)
1212{
1213 mIsCustomProjection = enable;
1214 mLeftCustomProjection = leftMatrix;
1215 mRightCustomProjection = rightMatrix;
1216}
1217
1218void StereoManager::SetTimeWarpMatrix(const Ogre::Matrix4 &leftStartMatrix, const Ogre::Matrix4 &leftEndMatrix, const Ogre::Matrix4 &rightStartMatrix, const Ogre::Matrix4 &rightEndMatrix)
1219{
1220 mLeftStartWarpMatrix = leftStartMatrix;
1221 mLeftEndWarpMatrix = leftEndMatrix;
1222 mRightStartWarpMatrix = rightStartMatrix;
1223 mRightEndWarpMatrix = rightEndMatrix;
1224}
1225
1226void StereoManager::GetCustomProjectonMatrices(bool& enabled, Ogre::Matrix4& leftMatrix, Ogre::Matrix4& rightMatrix) const
1227{
1228 enabled = mIsCustomProjection;
1229 leftMatrix = mLeftCustomProjection;
1230 rightMatrix = mRightCustomProjection;
1231}
1232
1233void StereoManager::SetStereoMeshUVConfig(Ogre::Vector2 leftuvscale, Ogre::Vector2 leftuvoffset, Ogre::Vector2 rightuvscale, Ogre::Vector2 rightuvoffset)
1234{
1235 mLeftUVScale = leftuvscale;
1236 mLeftUVOffset = leftuvoffset;
1237
1238 mRightUVScale = rightuvscale;
1239 mRightUVOffset = rightuvoffset;
1240}
1241
1243{
1244 if (leftsize.x <= 0 || leftsize.y <= 0 || rightsize.x <= 0 || rightsize.y <= 0)
1245 return;
1246
1247 StereoMode mode = GetStereoMode();
1248
1249 if (mode != SO3_NONE_STEREO)
1251
1252 /*
1253 Ogre::RenderSystem* ogreRenderSystem = SRoot::getSingleton().GetOgreRenderSystem();
1254 if (!ogreRenderSystem->getCapabilities()->hasCapability(Ogre::RSC_NON_POWER_OF_2_TEXTURES))
1255 {
1256 mLeftRenderTextureSize = SO3::SPoint<int> (Ogre::Bitwise::firstPO2From(static_cast <unsigned short>(leftsize.x)), Ogre::Bitwise::firstPO2From(static_cast <unsigned short>(leftsize.y)));
1257 mRightRenderTextureSize = SO3::SPoint<int> (Ogre::Bitwise::firstPO2From(static_cast <unsigned short>(rightsize.x)), Ogre::Bitwise::firstPO2From(static_cast <unsigned short>(rightsize.y)));
1258 }
1259 else
1260 {
1261 mLeftRenderTextureSize = leftsize;
1262 mRightRenderTextureSize = rightsize;
1263 }
1264 */
1265
1266 mLeftRenderTextureSize = leftsize;
1267 mRightRenderTextureSize = rightsize;
1268
1269 if (mode != SO3_NONE_STEREO)
1270 SetStereoMode(mode);
1271}
1272
1273std::array<SCOL_PTR_TYPE, 2> StereoManager::GetStereoTextures()
1274{
1275 std::array <SCOL_PTR_TYPE, 2> glid = { 0, 0 };
1276 StereoViewports::iterator iStereoViewport = stereoViewports.begin();
1277 if (iStereoViewport != stereoViewports.end())
1278 {
1279 StereoViewportData* viewportData = iStereoViewport->second;
1280
1281 if (viewportData->mLeftRenderTexture)
1282 {
1283#if defined(_WIN32) && defined(SO3_USE_DX11)
1284 if (SRoot::getSingleton().GetRenderSystem() == SRoot::SO3_DIRECTX11_RENDERER)
1285 glid[0] = (SCOL_PTR_TYPE)(static_cast<Ogre::D3D11Texture*>(viewportData->mLeftRenderTexture.get())->GetTex2D());
1286 else
1287#endif
1289 viewportData->mLeftRenderTexture->getCustomAttribute("GLID", &glid[0]);
1290 //TODO VULKAN
1291 }
1292
1293 if (viewportData->mRightRenderTexture)
1294 {
1295#if defined(_WIN32) && defined(SO3_USE_DX11)
1297 glid[1] = (SCOL_PTR_TYPE)(static_cast<Ogre::D3D11Texture*>(viewportData->mRightRenderTexture.get())->GetTex2D());
1298 else
1299#endif
1301 viewportData->mRightRenderTexture->getCustomAttribute("GLID", &glid[1]);
1302 //TODO VULKAN
1303 }
1304 }
1305 return glid;
1306}
1307
1308std::array<SO3::SPoint<int>, 2>StereoManager::GetStereoViewportSize()
1309{
1310 std::array <SO3::SPoint<int>, 2> vpsize = { SO3::SPoint<int>(0, 0), SO3::SPoint<int>(0, 0) };
1311 StereoViewports::iterator iStereoViewport = stereoViewports.begin();
1312 if (iStereoViewport != stereoViewports.end())
1313 {
1314 StereoViewportData* viewportData = iStereoViewport->second;
1315
1316 if (viewportData->mLeftRenderTexture)
1317 {
1318 vpsize[0].x = viewportData->mLeftRenderTexture->getWidth();
1319 vpsize[0].y = viewportData->mLeftRenderTexture->getHeight();
1320 }
1321
1322 if (viewportData->mRightRenderTexture)
1323 {
1324 vpsize[1].x = viewportData->mRightRenderTexture->getWidth();
1325 vpsize[1].y = viewportData->mRightRenderTexture->getHeight();
1326 }
1327 }
1328 return vpsize;
1329}
1330
1332{
1333 mHasExternalWindow = state;
1334 mWindowPos = pos;
1335 mWindowSise = size;
1336 mWindowMonitorIndex = index;
1337
1338 if(mHasExternalWindow && !mExternalWindow)
1339 {
1340 try
1341 {
1342 Ogre::NameValuePairList viewConfig;
1343 viewConfig["Resource Creation Policy"] = "Create on all devices";
1344 viewConfig["Multi device memory hint"] = "Auto hardware buffers management";
1345 viewConfig["vsync"] = "Yes";
1346 viewConfig["Use Multihead"] = "Auto";
1347 viewConfig["FSAAHint"] = "Quality";
1348 viewConfig["FSAA"] = "2";
1349 if (SRoot::getSingleton().GetRenderSystem() == SRoot::SO3_OPENGL_RENDERER)
1350 {
1351 viewConfig["left"] = Ogre::StringConverter::toString(mWindowPos.x);
1352 viewConfig["top"] = Ogre::StringConverter::toString(mWindowPos.y);
1353 }
1354 else
1355 {
1356 viewConfig["monitorIndex"] = Ogre::StringConverter::toString(mWindowMonitorIndex);
1357 }
1358 mExternalWindow = Ogre::Root::getSingleton().createRenderWindow("STEREO", mWindowSise.x, mWindowSise.y, true, &viewConfig);
1359 }
1360 catch(Ogre::Exception&)
1361 {
1362 // window already exist of monitor index do not exist ?
1363 }
1364 }
1365 else if (!mHasExternalWindow && mExternalWindow)
1366 {
1367 if (mExternalViewport)
1368 mExternalWindow->removeViewport(mExternalViewport->getZOrder());
1369
1370 SRoot::getSingleton().GetOgreRenderSystem()->destroyRenderWindow("STEREO");
1371 mExternalWindow = 0;
1372 mExternalViewport = 0;
1373 }
1374}
1375
1376void StereoManager::SetStereoMeshLeft(std::vector<Ogre::Vector3> vertices, std::vector<std::vector<Ogre::Vector2> > uvs, std::vector<Ogre::Real> vignetteColor, std::vector<Ogre::Real> warp, std::vector<int> indexs)
1377{
1378 if (mLeftMesh)
1379 {
1380 Ogre::MeshManager::getSingleton().remove(mLeftMesh->getHandle());
1381 mLeftMesh.reset();
1382 }
1383
1384 if (vertices.size() <= 0)
1385 return;
1386
1387 unsigned int nbUvs = (uvs.size() > 0) ? uvs[0].size() : 0;
1388
1389 mLeftMesh = Ogre::MeshManager::getSingleton().createManual(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/LEFT/MESH"), SO3_INTERNAL_RESOURCE_GROUP);
1390 mLeftMesh->sharedVertexData = new Ogre::VertexData();
1391 mLeftMesh->sharedVertexData->vertexCount = vertices.size();
1392 Ogre::VertexData* vdata = mLeftMesh->sharedVertexData;
1393
1394 // A VertexDeclaration declares the format of a set of vertex inputs,
1395 Ogre::VertexDeclaration* decl = vdata->vertexDeclaration;
1396 // A VertexBufferBinding records the state of all the vertex buffer bindings required to
1397 // provide a vertex declaration with the input data it needs for the vertex elements.
1398 Ogre::VertexBufferBinding* bind = vdata->vertexBufferBinding;
1399
1400 size_t vBufSegmentSize = 0;
1401 size_t texSegmentSize = 0;
1402
1403 // Create the vertex declaration (the format of vertices).
1404 // Add vertex position
1405 decl->addElement(0, vBufSegmentSize,Ogre::VET_FLOAT3,Ogre::VES_POSITION);
1406 vBufSegmentSize += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
1407
1408 // Add vertex colour
1409 decl->addElement(0, vBufSegmentSize, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
1410 vBufSegmentSize += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
1411
1412 // Add texture coordinates
1413 //use VET_FLOAT2 to make ogre able to generate tangent ^^
1414 int countTex = 0;
1415 for (unsigned int i = 0; i < nbUvs; i++)
1416 {
1417 decl->addElement(1, texSegmentSize, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, countTex);
1418 texSegmentSize += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
1419 countTex++;
1420 }
1421
1422 // Now create the vertex buffers.
1423 Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingletonPtr()
1424 ->createVertexBuffer(vBufSegmentSize, vdata->vertexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
1425 Ogre::HardwareVertexBufferSharedPtr texBuf = Ogre::HardwareBufferManager::getSingletonPtr()
1426 ->createVertexBuffer(texSegmentSize, vdata->vertexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
1427
1428 // Bind them.
1429 bind->setBinding(0, vbuf);
1430 bind->setBinding(1, texBuf);
1431
1432 // Lock them. pVert & pTexVert are pointers to the start of the hardware buffers.
1433 unsigned char* pVert = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
1434 unsigned char* pTexVert = static_cast<unsigned char*>(texBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
1435 Ogre::ARGB* pCol;
1436 float* pFloat;
1437
1438 // Get the element lists for the buffers.
1439 Ogre::VertexDeclaration::VertexElementList elems = decl->findElementsBySource(0);
1440 Ogre::VertexDeclaration::VertexElementList texElems = decl->findElementsBySource(1);
1441
1442 // Buffers are set up, so iterate the vertices.
1443 int iTexCoord = 0;
1444 for (unsigned int i = 0; i < vertices.size(); ++i)
1445 {
1446 Ogre::Vector3 v = vertices[i];
1447 Ogre::Real vignette = (i < vignetteColor.size()) ? vignetteColor[i] : 1.0f;
1448 Ogre::Real vwarp = (i < warp.size()) ? warp[i] : 0.0f;
1449 Ogre::ColourValue vc(vignette, vwarp, 1.0f, 1.0f);
1450 std::vector<Ogre::Vector2> vuvs;
1451 if (i < uvs.size())
1452 vuvs = uvs[i];
1453
1454 Ogre::VertexDeclaration::VertexElementList::const_iterator elemItr, elemEnd;
1455 elemEnd = elems.end();
1456 for (elemItr = elems.begin(); elemItr != elemEnd; ++elemItr)
1457 {
1458 // VertexElement corresponds to a part of a vertex definition eg. position, normal
1459 const Ogre::VertexElement& elem = *elemItr;
1460 switch (elem.getSemantic())
1461 {
1462 case Ogre::VES_POSITION:
1463 {
1464 elem.baseVertexPointerToElement(pVert, &pFloat);
1465 *pFloat++ = v.x;
1466 *pFloat++ = v.y;
1467 *pFloat++ = v.z;
1468 }
1469 break;
1470 break;
1471 case Ogre::VES_DIFFUSE:
1472 {
1473 elem.baseVertexPointerToElement(pVert, &pCol);
1474 *pCol = Ogre::VertexElement::convertColourValue(vc, Ogre::VertexElement::getBestColourVertexElementType());
1475 }
1476 break;
1477 default:
1478 break;
1479 } // Deal with an individual vertex element (position or normal).
1480 } // Loop positions and normals.
1481
1482 iTexCoord = 0;
1483 elemEnd = texElems.end();
1484 for (elemItr = texElems.begin(); elemItr != elemEnd; ++elemItr)
1485 {
1486 // VertexElement corresponds to a part of a vertex definition eg. tex coord
1487 const Ogre::VertexElement& elem = *elemItr;
1488 switch (elem.getSemantic())
1489 {
1490 case Ogre::VES_TEXTURE_COORDINATES:
1491 {
1492 elem.baseVertexPointerToElement(pTexVert, &pFloat);
1493 *pFloat++ = vuvs[iTexCoord].x;
1494 *pFloat++ = vuvs[iTexCoord].y;
1495 //*pFloat++ = vertex.lTexCoords[iTexCoord].z;
1496 iTexCoord++;
1497 }
1498 break;
1499 default:
1500 break;
1501 } // Deal with an individual vertex element (tex coords).
1502 } // Loop tex coords.
1503
1504 pVert += vbuf->getVertexSize();
1505 pTexVert += texBuf->getVertexSize();
1506 } // Loop vertices.
1507 vbuf->unlock();
1508 texBuf->unlock();
1509
1510 // Create a new submesh
1511 Ogre::SubMesh* pSubmesh = mLeftMesh->createSubMesh();
1512 pSubmesh->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
1513
1514 // Set material
1515 pSubmesh->setMaterialName(mAvailableModes[mStereoMode] + "/Left");
1516
1517 // Set use shared geometry flag
1518 pSubmesh->useSharedVertices = true;
1519
1520 pSubmesh->vertexData = new Ogre::VertexData();
1521 pSubmesh->vertexData->vertexCount = vertices.size();
1522
1523 // Create a new index buffer
1524 pSubmesh->indexData->indexCount = indexs.size();
1525 pSubmesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
1526 Ogre::HardwareIndexBuffer::IT_32BIT,
1527 pSubmesh->indexData->indexCount,
1528 Ogre::HardwareBuffer::HBU_STATIC);
1529
1530 // Fill the index buffer with faces data
1531 Ogre::uint32* pIdx = static_cast<Ogre::uint32*>(pSubmesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
1532 for (unsigned int i = 0; i < indexs.size(); i++)
1533 {
1534 *pIdx++ = static_cast<Ogre::uint32>(indexs[i]);
1535 }
1536 pSubmesh->indexData->indexBuffer->unlock();
1537
1538 mLeftMesh->_setBounds(Ogre::AxisAlignedBox::BOX_INFINITE, false);
1539 mLeftMesh->_setBoundingSphereRadius(100000.0f);
1540
1541 mLeftMesh->load();
1542}
1543
1544void StereoManager::SetStereoMeshRight(std::vector<Ogre::Vector3> vertices, std::vector<std::vector<Ogre::Vector2> > uvs, std::vector<Ogre::Real> vignetteColor, std::vector<Ogre::Real> warp, std::vector<int> indexs)
1545{
1546 if (mRightMesh)
1547 {
1548 Ogre::MeshManager::getSingleton().remove(mRightMesh->getHandle());
1549 mRightMesh.reset();
1550 }
1551
1552 if (vertices.size() <= 0)
1553 return;
1554
1555 unsigned int nbUvs = (uvs.size() > 0) ? uvs[0].size() : 0;
1556
1557 mRightMesh = Ogre::MeshManager::getSingleton().createManual(SO3_INTERNAL_RESOURCE_GROUP + Ogre::String("/STEREO/RIGHT/MESH"), SO3_INTERNAL_RESOURCE_GROUP);
1558 mRightMesh->sharedVertexData = new Ogre::VertexData();
1559 mRightMesh->sharedVertexData->vertexCount = vertices.size();
1560 Ogre::VertexData* vdata = mRightMesh->sharedVertexData;
1561
1562 // A VertexDeclaration declares the format of a set of vertex inputs,
1563 Ogre::VertexDeclaration* decl = vdata->vertexDeclaration;
1564 // A VertexBufferBinding records the state of all the vertex buffer bindings required to
1565 // provide a vertex declaration with the input data it needs for the vertex elements.
1566 Ogre::VertexBufferBinding* bind = vdata->vertexBufferBinding;
1567
1568 size_t vBufSegmentSize = 0;
1569 size_t texSegmentSize = 0;
1570
1571 // Create the vertex declaration (the format of vertices).
1572 // Add vertex position
1573 decl->addElement(0, vBufSegmentSize,Ogre::VET_FLOAT3,Ogre::VES_POSITION);
1574 vBufSegmentSize += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
1575
1576 // Add vertex colour
1577 decl->addElement(0, vBufSegmentSize, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
1578 vBufSegmentSize += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
1579
1580 // Add texture coordinates
1581 //use VET_FLOAT2 to make ogre able to generate tangent ^^
1582 int countTex = 0;
1583 for (unsigned int i = 0; i < nbUvs; i++)
1584 {
1585 decl->addElement(1, texSegmentSize, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, countTex);
1586 texSegmentSize += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
1587 countTex++;
1588 }
1589
1590 // Now create the vertex buffers.
1591 Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingletonPtr()
1592 ->createVertexBuffer(vBufSegmentSize, vdata->vertexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
1593 Ogre::HardwareVertexBufferSharedPtr texBuf = Ogre::HardwareBufferManager::getSingletonPtr()
1594 ->createVertexBuffer(texSegmentSize, vdata->vertexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
1595
1596 // Bind them.
1597 bind->setBinding(0, vbuf);
1598 bind->setBinding(1, texBuf);
1599
1600 // Lock them. pVert & pTexVert are pointers to the start of the hardware buffers.
1601 unsigned char* pVert = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
1602 unsigned char* pTexVert = static_cast<unsigned char*>(texBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
1603 Ogre::ARGB* pCol;
1604 float* pFloat;
1605
1606 // Get the element lists for the buffers.
1607 Ogre::VertexDeclaration::VertexElementList elems = decl->findElementsBySource(0);
1608 Ogre::VertexDeclaration::VertexElementList texElems = decl->findElementsBySource(1);
1609
1610 // Buffers are set up, so iterate the vertices.
1611 int iTexCoord = 0;
1612 for (unsigned int i = 0; i < vertices.size(); ++i)
1613 {
1614 Ogre::Vector3 v = vertices[i];
1615 Ogre::Real vignette = (i < vignetteColor.size()) ? vignetteColor[i] : 1.0f;
1616 Ogre::Real vwarp = (i < warp.size()) ? warp[i] : 0.0f;
1617 Ogre::ColourValue vc(vignette, vwarp, 1.0f, 1.0f);
1618 std::vector<Ogre::Vector2> vuvs;
1619 if (i < uvs.size())
1620 vuvs = uvs[i];
1621
1622 Ogre::VertexDeclaration::VertexElementList::const_iterator elemItr, elemEnd;
1623 elemEnd = elems.end();
1624 for (elemItr = elems.begin(); elemItr != elemEnd; ++elemItr)
1625 {
1626 // VertexElement corresponds to a part of a vertex definition eg. position, normal
1627 const Ogre::VertexElement& elem = *elemItr;
1628 switch (elem.getSemantic())
1629 {
1630 case Ogre::VES_POSITION:
1631 {
1632 elem.baseVertexPointerToElement(pVert, &pFloat);
1633 *pFloat++ = v.x;
1634 *pFloat++ = v.y;
1635 *pFloat++ = v.z;
1636 }
1637 break;
1638 break;
1639 case Ogre::VES_DIFFUSE:
1640 {
1641 elem.baseVertexPointerToElement(pVert, &pCol);
1642 *pCol = Ogre::VertexElement::convertColourValue(vc, Ogre::VertexElement::getBestColourVertexElementType());
1643 }
1644 break;
1645 default:
1646 break;
1647 } // Deal with an individual vertex element (position or normal).
1648 } // Loop positions and normals.
1649
1650 iTexCoord = 0;
1651 elemEnd = texElems.end();
1652 for (elemItr = texElems.begin(); elemItr != elemEnd; ++elemItr)
1653 {
1654 // VertexElement corresponds to a part of a vertex definition eg. tex coord
1655 const Ogre::VertexElement& elem = *elemItr;
1656 switch (elem.getSemantic())
1657 {
1658 case Ogre::VES_TEXTURE_COORDINATES:
1659 {
1660 elem.baseVertexPointerToElement(pTexVert, &pFloat);
1661 *pFloat++ = vuvs[iTexCoord].x;
1662 *pFloat++ = vuvs[iTexCoord].y;
1663 //*pFloat++ = vertex.lTexCoords[iTexCoord].z;
1664 iTexCoord++;
1665 }
1666 break;
1667 default:
1668 break;
1669 } // Deal with an individual vertex element (tex coords).
1670 } // Loop tex coords.
1671
1672 pVert += vbuf->getVertexSize();
1673 pTexVert += texBuf->getVertexSize();
1674 } // Loop vertices.
1675 vbuf->unlock();
1676 texBuf->unlock();
1677
1678 // Create a new submesh
1679 Ogre::SubMesh* pSubmesh = mRightMesh->createSubMesh();
1680 pSubmesh->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
1681
1682 // Set material
1683 pSubmesh->setMaterialName(mAvailableModes[mStereoMode] + "/Right");
1684
1685 // Set use shared geometry flag
1686 pSubmesh->useSharedVertices = true;
1687
1688 pSubmesh->vertexData = new Ogre::VertexData();
1689 pSubmesh->vertexData->vertexCount = vertices.size();
1690
1691 // Create a new index buffer
1692 pSubmesh->indexData->indexCount = indexs.size();
1693 pSubmesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
1694 Ogre::HardwareIndexBuffer::IT_32BIT,
1695 pSubmesh->indexData->indexCount,
1696 Ogre::HardwareBuffer::HBU_STATIC);
1697
1698 // Fill the index buffer with faces data
1699 Ogre::uint32* pIdx = static_cast<Ogre::uint32*>(pSubmesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
1700 for (unsigned int i = 0; i < indexs.size(); i++)
1701 {
1702 *pIdx++ = static_cast<Ogre::uint32>(indexs[i]);
1703 }
1704 pSubmesh->indexData->indexBuffer->unlock();
1705
1706 mRightMesh->_setBounds(Ogre::AxisAlignedBox::BOX_INFINITE, false);
1707 mRightMesh->_setBoundingSphereRadius(100000.0f);
1708
1709 mRightMesh->load();
1710}
1711
1713{
1714 StereoMode mode = GetStereoMode();
1715 if (mode != SO3_NONE_STEREO)
1717
1718 mIsCustomOffset = (offset == 0.0) ? false : true;
1719 mCenterOffset = offset;
1720
1721 if (mode != SO3_NONE_STEREO)
1722 SetStereoMode(mode);
1723}
1724
1726{
1727 StereoMode mode = GetStereoMode();
1728 if (mode != SO3_NONE_STEREO)
1730
1731 mIsCustomRatio = (ratio == 0.0) ? false : true;
1732 mRatio = ratio;
1733
1734 if (mode != SO3_NONE_STEREO)
1735 SetStereoMode(mode);
1736}
1737
1739{
1740 return mRatio;
1741}
1742
1744{
1745 StereoMode mode = GetStereoMode();
1746 if (mode != SO3_NONE_STEREO)
1748
1749 mIsCustomFOV = (fov == 0.0) ? false : true;
1750 mFOV = fov;
1751
1752 if (mode != SO3_NONE_STEREO)
1753 SetStereoMode(mode);
1754}
1755
1757{
1758 StereoMode mode = GetStereoMode();
1759 if (mode != SO3_NONE_STEREO)
1761
1762 mRotateView = state;
1763
1764 if (mode != SO3_NONE_STEREO)
1765 SetStereoMode(mode);
1766}
1767
1769{
1770 return mRotateView;
1771}
1772
1773void StereoManager::SetStereoChromaticAbCorrection(bool enable, Ogre::Vector4 chromAbC)
1774{
1775 StereoMode mode = GetStereoMode();
1776 if (mode != SO3_NONE_STEREO)
1778
1779 mChromAbCorrection = chromAbC;
1780
1781 mIsCustomChromAbCorrection = enable;
1782
1783 if (mode != SO3_NONE_STEREO)
1784 SetStereoMode(mode);
1785}
1786
1787void StereoManager::SetStereoDistortion(bool enable, Ogre::Vector4 dist)
1788{
1789 StereoMode mode = GetStereoMode();
1790 if (mode != SO3_NONE_STEREO)
1792
1793 mDistortion = dist;
1794 mIsCustomDistortion = enable;
1795
1796 if (mode != SO3_NONE_STEREO)
1797 SetStereoMode(mode);
1798}
1799
1800//-------------- Device Lost listener -------------------------------
1801StereoManager::DeviceLostListener::DeviceLostListener(StereoManager* stereoMgr) : mStereoMgr(stereoMgr)
1802{
1803}
1804
1805void StereoManager::DeviceLostListener::eventOccurred (const Ogre::String& eventName, const Ogre::NameValuePairList* parameters)
1806{
1807 if(eventName == "DeviceLost")
1808 {
1809 }
1810 else if(eventName == "DeviceRestored")
1811 {
1812 }
1813 else if(eventName == "BeforeDevicePresent")
1814 {
1815 /*StereoViewports::iterator iStereoViewport = mStereoMgr->stereoViewports.begin();
1816 while(iStereoViewport != mStereoMgr->stereoViewports.end())
1817 {
1818 StereoViewportData* viewportData = iStereoViewport->second;
1819 iStereoViewport++;
1820 }*/
1821 }
1822 else if(eventName == "AfterDevicePresent")
1823 {
1824 //scol callback
1825 //getBufferStereoUpdatedEvent(mm, (int)mStereoMgr->mBuffer, 0);
1826 }
1827}
1828
1829//-------------- Stereo Camera listener -------------------------------
1830StereoManager::StereoCameraListener::StereoCameraListener(StereoManager* stereoMgr, bool isLeftEye, Ogre::Viewport* originalViewport, StereoManager::StereoViewportData* stereoViewportData) : mStereoMgr(stereoMgr),
1831 mIsLeftEye(isLeftEye),
1832 viewportData(stereoViewportData),
1833 mOriginalViewport(originalViewport)
1834{
1835}
1836
1837void StereoManager::StereoCameraListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
1838{
1839 if (!viewportData->mCamera)
1840 return;
1841
1842 int texwidth = (mIsLeftEye) ? viewportData->mLeftRenderTexture->getWidth() : viewportData->mRightRenderTexture->getWidth();
1843 int texheight = (mIsLeftEye) ? viewportData->mLeftRenderTexture->getHeight() : viewportData->mRightRenderTexture->getHeight();
1844
1845 // force camera aspect ratio
1846 if (viewportData->mCamera->getAutoAspectRatio())
1847 {
1848 viewportData->mCamera->setAspectRatio((float)texwidth / (float)texheight);
1849
1850 if (mStereoMgr->GetStereoMode() == SO3_MONO_STEREO)
1851 mStereoMgr->mIsCustomRatio = false;
1852 }
1853 else if (mStereoMgr->mIsCustomRatio)
1854 {
1855 viewportData->mCamera->setAspectRatio(mStereoMgr->mRatio);
1856 }
1857
1858 Ogre::Real offset = (mIsLeftEye ? (-0.5f) : (0.5f)) * mStereoMgr->GetEyesSpacing();
1859 Ogre::Matrix4 baseMat = viewportData->mBaseCameraMatrix;
1860 Ogre::Real nearClip = viewportData->mCamera->getNearClipDistance();
1861 Ogre::Real farClip = viewportData->mCamera->getFarClipDistance();
1862 Ogre::Real focalLength = viewportData->mCamera->getFocalLength();
1863
1864 // getFov from camera or custom matrix
1865 Ogre::Radian fovY = viewportData->mCamera->getFOVy();
1866 Ogre::Real camspect = viewportData->mCamera->getAspectRatio();
1867
1868 if (viewportData->mOldUseCustomMatrix && offset != 0.0f)
1869 {
1870 fovY = 2.0 * atan(1.0 / viewportData->mOldMatrix[1][1]);
1871 camspect = viewportData->mOldMatrix[1][1] / viewportData->mOldMatrix[0][0];
1872 focalLength = viewportData->mOldMatrix[1][1];
1873 }
1874 else if (mStereoMgr->mIsCustomProjection)
1875 {
1876 Ogre::Matrix4 customMat = (mIsLeftEye) ? mStereoMgr->mLeftCustomProjection : mStereoMgr->mRightCustomProjection;
1877 fovY = 2.0 * atan(1.0 / customMat[1][1]);
1878 camspect = customMat[1][1] / customMat[0][0];
1879 focalLength = customMat[1][1];
1880 }
1881
1882 if (mStereoMgr->GetStereoMode() != SO3_MONO_STEREO)
1883 {
1884 // make the overlays readable for the eyes
1885 SWidgetManager* wmanager = SWidgetManager::getSingletonPtr();
1886 SWidgetManager::WidgetList wlist = wmanager->GetWidgetList();
1887 for (SWidgetManager::WidgetList::const_iterator wIt = wlist.begin(); wIt != wlist.end(); wIt++)
1888 {
1889 SWidget* widget = (wIt->second);
1890 if (widget->GetVisible())
1891 {
1892 if ((widget->GetIsOverlayed() || widget->GetIs2DRect()))
1893 {
1894 widget->SetCurrentViewport((mIsLeftEye) ? viewportData->mLastLeftViewport : viewportData->mLastRightViewport);
1895
1896 Ogre::Real dist = (widget->GetZOrder() == 0) ? farClip : nearClip + 10.0f - (10.0f * ((float)widget->GetZOrder() / 1000.0f));
1897 Ogre::Real hv = 2.0f * tanf (fovY.valueRadians() * 0.5f) * dist;
1898 Ogre::Real wv = hv * ((float)texwidth / (float)texheight);
1899 Ogre::Real woffset = (offset * wv * focalLength) / dist;
1900
1901 widget->SetLeftOffset((viewportData->mFlipEyes) ? woffset : -woffset);
1902
1903 //set the viewport back
1904 widget->SetCurrentViewport(viewportData->mOriginalViewport);
1905 }
1906
1907 widget->SetStereoEye(mIsLeftEye);
1908 }
1909 }
1910 }
1911
1912 if (viewportData->mOldUseCustomMatrix && offset != 0.0f)
1913 {
1914 Ogre::Matrix4 proj = Ogre::Matrix4::IDENTITY;
1915 proj.setTrans(Ogre::Vector3(-offset, 0, 0));
1916 viewportData->mCamera->setCustomProjectionMatrix(true, proj * viewportData->mOldMatrix);
1917 }
1918 else if (mStereoMgr->mIsCustomProjection)
1919 {
1920 Ogre::Matrix4 customMat = (mIsLeftEye) ? mStereoMgr->mLeftCustomProjection : mStereoMgr->mRightCustomProjection;
1921 //if (mStereoMgr->mStereoMode == SO3_OPENXR_STEREO)
1922 // customMat = customMat * Ogre::Matrix4(Ogre::Quaternion(Ogre::Degree(180.0f), Ogre::Vector3(0.0f, 0.0f, -1.0f)));
1923 viewportData->mCamera->setCustomProjectionMatrix(true, customMat);
1924 }
1925 else if (mStereoMgr->mIsCustomOffset)
1926 {
1927 Ogre::Matrix4 proj = Ogre::Matrix4::IDENTITY;
1928 proj.setTrans(Ogre::Vector3(-mStereoMgr->mCenterOffset * (mIsLeftEye ? (-1) : 1), 0, 0));
1929 viewportData->mCamera->setCustomProjectionMatrix(true, proj * baseMat);
1930
1931 /*Ogre::Vector2 fOffset = Ogre::Vector2(-mStereoMgr->mCenterOffset * (mIsLeftEye ? (-1) : 1), 0);
1932 viewportData->mCamera->setFrustumOffset(viewportData->mOldOffset - fOffset);*/
1933 }
1934 else if (offset != 0.0f)
1935 viewportData->mCamera->setFrustumOffset(viewportData->mOldOffset + Ogre::Vector2(offset, 0));
1936
1937 // If the stereo technique uses a compositor
1938 if((mStereoMgr->mStereoMode != SO3_MONO_STEREO) && (!mStereoMgr->mAvailableModes[mStereoMgr->mStereoMode].empty() || (mStereoMgr->mStereoMode == SO3_OCULUS2_STEREO)))
1939 {
1940 // Move the camera
1941 viewportData->mCamera->getParentSceneNode()->setPosition(viewportData->mOldPos + (offset * (viewportData->mCamera->getParentSceneNode()->getOrientation() * Ogre::Vector3::UNIT_X)));
1942 }
1943 viewportData->mCamera->resetFrustumExtents();
1944}
1945
1946void StereoManager::StereoCameraListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
1947{
1948 //restaure camera to center for buffer selector
1949 if (!viewportData->mCamera)
1950 return;
1951
1952 Ogre::Matrix4 baseMat = viewportData->mBaseCameraMatrix;
1953 Ogre::Real offset = 0.0f;
1954 if(!mStereoMgr->mIsCustomProjection)
1955 {
1956 if (mStereoMgr->mIsCustomOffset)
1957 {
1958 Ogre::Matrix4 proj = Ogre::Matrix4::IDENTITY;
1959 proj.setTrans(Ogre::Vector3(0.0, 0.0f, 0.0f));
1960 viewportData->mCamera->setCustomProjectionMatrix(true, proj * baseMat);
1961 }
1962 else if (offset != 0.0f)
1963 {
1964 viewportData->mCamera->setFrustumOffset(viewportData->mOldOffset + Ogre::Vector2(offset, 0));
1965 }
1966 }
1967 else
1968 viewportData->mCamera->setCustomProjectionMatrix(true, mStereoMgr->mLeftCustomProjection);
1969
1970 // If the stereo technique uses a compositor
1971 if((mStereoMgr->mStereoMode != SO3_MONO_STEREO) && (!mStereoMgr->mAvailableModes[mStereoMgr->mStereoMode].empty() || (mStereoMgr->mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMgr->mStereoMode == SO3_OCULUS_STEREO)))
1972 {
1973 // Move the camera
1974 viewportData->mCamera->getParentSceneNode()->setPosition(viewportData->mOldPos);
1975 }
1976}
1977
1978//-------------- Stereo Viewport listener -------------------------------
1979StereoManager::StereoViewportListener::StereoViewportListener(StereoManager* stereoMgr, StereoManager::StereoViewportData* stereoViewportData) : mStereoMgr(stereoMgr),
1980 viewportData(stereoViewportData)
1981{
1982}
1983
1984void StereoManager::StereoViewportListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
1985{
1986 //getBufferStereoBeforeUpdateEvent(mm, (int)mStereoMgr->mBuffer, 0);
1987
1988 //TODO check if the viewport size changed and update the RTT sizes when not oculus
1989 try
1990 {
1991 if (viewportData->mLeftRenderTexture)
1992 {
1993 viewportData->mLeftRenderTexture->getBuffer()->getRenderTarget()->update();
1994 }
1995
1996 if (viewportData->mRightRenderTexture)
1997 {
1998 viewportData->mRightRenderTexture->getBuffer()->getRenderTarget()->update();
1999 }
2000 }
2001 catch(Ogre::Exception&)
2002 {
2003 // update failed maybe D3D device lost
2004 }
2005
2006 //scol callback
2007 getBufferStereoUpdateParametersEvent(mm, SCOL_PTR mStereoMgr->mBuffer, 0);
2008 if ((mStereoMgr->mStereoMode == SO3_OCULUS2_STEREO) || (mStereoMgr->mStereoMode == SO3_OCULUS_STEREO))
2009 {
2010 try
2011 {
2012 Ogre::MaterialPtr leftmat = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName(mStereoMgr->mAvailableModes[mStereoMgr->mStereoMode] + "/Left", SO3_INTERNAL_RESOURCE_GROUP));
2013 if(leftmat)
2014 {
2015 Ogre::GpuProgramParametersSharedPtr leftShaderParams = leftmat->getTechnique(0)->getPass(0)->getVertexProgramParameters();
2016 leftShaderParams->setNamedConstant("eyeToSourceUVScale", mStereoMgr->mLeftUVScale);
2017 leftShaderParams->setNamedConstant("eyeToSourceUVOffset", mStereoMgr->mLeftUVOffset);
2018 leftShaderParams->setNamedConstant("eyeRotationStart", mStereoMgr->mLeftStartWarpMatrix);
2019 leftShaderParams->setNamedConstant("eyeRotationEnd", mStereoMgr->mLeftEndWarpMatrix);
2020 }
2021
2022 Ogre::MaterialPtr rightmat = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName(mStereoMgr->mAvailableModes[mStereoMgr->mStereoMode] + "/Right", SO3_INTERNAL_RESOURCE_GROUP));
2023 if(rightmat)
2024 {
2025 Ogre::GpuProgramParametersSharedPtr rightShaderParams = rightmat->getTechnique(0)->getPass(0)->getVertexProgramParameters();
2026 rightShaderParams->setNamedConstant("eyeToSourceUVScale", mStereoMgr->mRightUVScale);
2027 rightShaderParams->setNamedConstant("eyeToSourceUVOffset", mStereoMgr->mRightUVOffset);
2028 rightShaderParams->setNamedConstant("eyeRotationStart", mStereoMgr->mRightStartWarpMatrix);
2029 rightShaderParams->setNamedConstant("eyeRotationEnd", mStereoMgr->mRightEndWarpMatrix);
2030 }
2031 }
2032 catch(Ogre::Exception&)
2033 {
2034 }
2035 }
2036}
2037
2038void StereoManager::StereoViewportListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
2039{
2040 /*SRoot* scolRoot = SRoot::getSingletonPtr();
2041 if (scolRoot->GetRenderSystem() == SRoot::SO3_DIRECTX9_RENDERER)
2042 {
2043 Ogre::D3D9RenderWindow* rWindow = (Ogre::D3D9RenderWindow*)scolRoot->GetOgreRenderSystem()->getRenderTarget(evt.source->getName());
2044 rWindow->WaitUntilGpuIdle();
2045 }*/
2046
2047 /*viewportData->mOriginalViewport->setCamera(viewportData->mCamera);
2048 if (viewportData->mCamera->getAutoAspectRatio())
2049 {
2050 Ogre::Real ratio = (Ogre::Real)viewportData->mOriginalViewport->getActualWidth() / (Ogre::Real)viewportData->mOriginalViewport->getActualHeight();
2051
2052 viewportData->mCamera->setAspectRatio(ratio);
2053 }
2054
2055 if(mStereoMgr->mIsCustomProjection)
2056 viewportData->mCamera->setCustomProjectionMatrix(viewportData->mOldUseCustomMatrix, viewportData->mOldMatrix);*/
2057}
2058
2059//-------------- Stereo Frame listener -------------------------------
2060StereoManager::StereoFrameListener::StereoFrameListener(StereoManager* stereoMgr, StereoManager::StereoViewportData* stereoViewportData) : mStereoMgr(stereoMgr),
2061 viewportData(stereoViewportData)
2062{
2063}
2064
2065bool StereoManager::StereoFrameListener::frameStarted(const Ogre::FrameEvent& evt)
2066{
2067 viewportData->frameTime = evt.timeSinceLastFrame;
2068 getBufferStereoBeforeUpdateEvent(mm, SCOL_PTR mStereoMgr->mBuffer, 0);
2069 return true;
2070}
2071
2072bool StereoManager::StereoFrameListener::frameRenderingQueued(const Ogre::FrameEvent& evt)
2073{
2074 return true;
2075}
2076
2077bool StereoManager::StereoFrameListener::frameEnded(const Ogre::FrameEvent& evt)
2078{
2079 getBufferStereoUpdatedEvent(mm, SCOL_PTR mStereoMgr->mBuffer, 0);
2080
2081 return true;
2082}
2083
2084StereoManager::StereoRTTListener::StereoRTTListener(StereoManager* stereoMgr, StereoManager::StereoViewportData* stereoViewportData) : mStereoMgr(stereoMgr),
2085 viewportData(stereoViewportData)
2086{
2087}
2088
2089void StereoManager::StereoRTTListener::unloadingComplete(Ogre::Resource* resource)
2090{
2091 mStereoMgr->ReleaseRttTarget(viewportData);
2092}
2093
2094void StereoManager::StereoRTTListener::loadingComplete(Ogre::Resource* resource)
2095{
2096 mStereoMgr->ReleaseRttTarget(viewportData);
2097 mStereoMgr->ConstructRttTarget(viewportData);
2098}
2099
2100}
int getBufferStereoBeforeUpdateEvent(mmachine m, SCOL_PTR_TYPE id, SCOL_PTR_TYPE param)
Definition SO3SCOL.cpp:4654
int getBufferStereoUpdatedEvent(mmachine m, SCOL_PTR_TYPE id, SCOL_PTR_TYPE param)
Definition SO3SCOL.cpp:4684
int getBufferStereoUpdateParametersEvent(mmachine m, SCOL_PTR_TYPE id, SCOL_PTR_TYPE param)
Definition SO3SCOL.cpp:4669
mmachine mm
Definition SO3SCOL.cpp:109
int getBufferStereoUpdatedEvent(struct Mmachine *, SCOL_PTR_TYPE, SCOL_PTR_TYPE)
int getBufferStereoUpdateParametersEvent(struct Mmachine *, SCOL_PTR_TYPE, SCOL_PTR_TYPE)
int getBufferStereoBeforeUpdateEvent(struct Mmachine *, SCOL_PTR_TYPE, SCOL_PTR_TYPE)
void UnregisterCamera(Ogre::Camera *cam)
bool IsRegisteredViewport(SViewPort *targetViewport)
NUMERIC_TYPE y
Definition SO3Point.h:40
NUMERIC_TYPE x
Definition SO3Point.h:39
SScene * GetScene(const std::string &sceneName)
Definition SO3Root.cpp:551
RenderSystem GetRenderSystem()
Definition SO3Root.cpp:860
@ SO3_DIRECTX11_RENDERER
Definition SO3Root.h:79
@ SO3_OPENGL_RENDERER
Definition SO3Root.h:80
Ogre::RenderSystem * GetOgreRenderSystem()
Definition SO3Root.cpp:865
static SRoot & getSingleton()
Definition SO3Root.cpp:116
static SRoot * getSingletonPtr()
Definition SO3Root.cpp:111
SEnvironment * GetEnvironment() const
void RemoveViewport(Ogre::Viewport *viewport)
Definition SO3Sky.cpp:210
void AddViewport(Ogre::Viewport *viewport)
Definition SO3Sky.cpp:200
Ogre::Viewport * GetOgreViewPortPointer()
void AddViewport(Ogre::Viewport *viewport)
Definition SO3Water.cpp:309
void RemoveViewport(Ogre::Viewport *viewport)
Definition SO3Water.cpp:315
std::map< std::string, SWidget * > WidgetList
static SWidgetManager * getSingletonPtr()
Ogre::RenderWindow * GetOgreRenderWindowPointer()
void SetStereoMeshLeft(std::vector< Ogre::Vector3 > vertices, std::vector< std::vector< Ogre::Vector2 > > uvs, std::vector< Ogre::Real > vignetteColor, std::vector< Ogre::Real > warp, std::vector< int > indexs)
StereoMode GetStereoMode() const
void SetStereoFOVy(Ogre::Real fov)
std::array< SCOL_PTR_TYPE, 2 > GetStereoTextures()
void SetCustomProjectonMatrices(bool enable, const Ogre::Matrix4 &leftMatrix, const Ogre::Matrix4 &rightMatrix)
bool UpdateStereoCompositorState(Ogre::Viewport *ogreViewportInstance, const Ogre::String compname, bool state)
void SetStereoProjectionOffset(Ogre::Real offset)
friend class StereoCameraListener
void SetStereoDistortion(bool enable, Ogre::Vector4 dist)
void GetCustomProjectonMatrices(bool &enabled, Ogre::Matrix4 &leftMatrix, Ogre::Matrix4 &rightMatrix) const
Ogre::Real GetStereoAspectRatio()
void SetStereoMeshRttSize(SO3::SPoint< int > leftsize, SO3::SPoint< int > rightsize)
bool IsViewportRegistered(Ogre::Viewport *ogreViewportInstance)
void SetStereoChromaticAbCorrection(bool enable, Ogre::Vector4 chromAbC)
void SetStereoMode(const StereoMode &newStereoMode)
void SetStereoWindow(SO3::SPoint< int > pos, SO3::SPoint< int > size, int index, bool state)
Ogre::Real GetEyesSpacing() const
void UnregisterViewport(SViewPort *viewportInstance)
void ConstructRttTarget(StereoViewportData *viewportData)
void SetTimeWarpMatrix(const Ogre::Matrix4 &leftStartMatrix, const Ogre::Matrix4 &leftEndMatrix, const Ogre::Matrix4 &rightStartMatrix, const Ogre::Matrix4 &rightEndMatrix)
std::array< SO3::SPoint< int >, 2 > GetStereoViewportSize()
void ReleaseRttTarget(StereoViewportData *viewportData)
void SetStereoMeshRight(std::vector< Ogre::Vector3 > vertices, std::vector< std::vector< Ogre::Vector2 > > uvs, std::vector< Ogre::Real > vignetteColor, std::vector< Ogre::Real > warp, std::vector< int > indexs)
@ SO3_CARDBOARD_STEREO
Google card board.
@ SO3_QUAD_BUFFER_STEREO
OpenGL QuadBuffer.
@ SO3_INTERLACED_V_STEREO
Verticaly interlaced mode.
@ SO3_SIDE_BY_SIDE_STEREO
Side by side image.
@ SO3_ANAGLYPH_YB_STEREO
Anaglyph yellow/blue.
@ SO3_ANAGLYPH_RC_STEREO
Anaglyph red/cyan.
@ SO3_INTERLACED_CB_STEREO
Interlaced mode with a checkerboard pattern.
@ SO3_OCULUS2_STEREO
Oculus rift DK2.
@ SO3_OCULUS_STEREO
Oculus rift.
@ SO3_INTERLACED_H_STEREO
Horizontaly interlaced mode.
@ SO3_UP_DOWN_STEREO
Up/down image.
friend class DeviceLostListener
StereoManager(SWindow *buffer)
void SetStereoMeshUVConfig(Ogre::Vector2 leftuvscale, Ogre::Vector2 leftuvoffset, Ogre::Vector2 rightuvscale, Ogre::Vector2 rightuvoffset)
void UpdateStereoCamera(Ogre::Viewport *ogreViewportInstance, Ogre::Camera *camera)
void RestoreStereoCamera(Ogre::Viewport *ogreViewportInstance)
void RegisterViewport(SViewPort *viewportInstance)
void SynchViewportSetup(SViewPort *viewportInstance, bool overlay=false, bool shadow=false)
void SetEyesSpacing(Ogre::Real l)
void SetStereoAspectRatio(Ogre::Real ratio)
void UpdateStereoCameraMatrix(Ogre::Viewport *ogreViewportInstance, Ogre::Camera *camera)
void SetRotateView(bool state)