SO3Engine
SO3DynamicCubeMap.cpp
Go to the documentation of this file.
1
11#include "SO3Renderer/SO3Root.h"
13
14#include <OgreDepthBuffer.h>
15
16namespace SO3
17{
18
19 SDynamicCubeMap::SDynamicCubeMap() : SNode(0, "", SNode::DYNAMIC_CUBE_MAP_ID)
20 {
21 // Forbiden (private)
22 }
23
24 SDynamicCubeMap::SDynamicCubeMap(SScene* parent, const std::string& dynamicCubeMapName) : SNode(parent, dynamicCubeMapName, SNode::DYNAMIC_CUBE_MAP_ID)
25 {
26 // Store the scheme that we will use to hide objects we dont want on the cubeMap.
27 cubeMapScheme = dynamicCubeMapName + "_SO3_DynamicCubeMap_Scheme";
28 material.reset();
29 size = 256;
30 state = false;
31 autoUpdate = false;
32 needUpdate = false;
33 needTextureUpdate = false;
34 renderingEnable = false;
35 techIndex = 0;
36 passIndex = 0;
37 unitIndex = 0;
38
39 // create the camera used to render to our cubemap
40 cubeMapCamera = currentScene->GetOgreScenePointer()->createCamera("camera_" + cubeMapScheme);
41 camNode = currentScene->GetOgreScenePointer()->createSceneNode();
42 camNode->attachObject(cubeMapCamera);
43 O3SceneNode->addChild(camNode);
44
45 cubeMapCamera->setFOVy(Ogre::Degree(90));
46 cubeMapCamera->setAspectRatio(1);
47 cubeMapCamera->setNearClipDistance(Ogre::Real(0.001));
48
49 // create our dynamic cube map texture
50 _CreateCubeMapTexture(size);
51
52 // Create a new transparent material and set a transparent technique
53 materialTransparent = Ogre::MaterialManager::getSingleton().create("SO3_Material_" + cubeMapScheme, SO3_INTERNAL_DYNAMIC_RESOURCE_GROUP);
54 materialTransparent->getTechnique(0)->setColourWriteEnabled(false);
55 materialTransparent->getTechnique(0)->setDepthCheckEnabled(false);
56 materialTransparent->getTechnique(0)->setDepthWriteEnabled(false);
57 materialTransparent->getTechnique(0)->getPass(0)->setName("SO3/TRANSPARENT/CUBEMAP");
58 materialTransparent->getTechnique(0)->getPass(0)->setVertexProgram("SO3/Internal/Default_nolight_vp");
59 materialTransparent->getTechnique(0)->getPass(0)->setFragmentProgram("SO3/Internal/Default_fp");
60 materialTransparent->load();
61
62 // Add frame listener
63 Ogre::Root::getSingleton().addFrameListener(this);
64 }
65
67 {
68 SetEnable(false);
69 // disable first
70 DisableRendering();
71
72 // remove frame listener for update on window events if autoUpdate is disable
73 if (!autoUpdate)
74 {
75 // Remove frame listener
76 Ogre::Root::getSingleton().removeFrameListener(this);
77 }
78
79 // Delete the cubeMap texture.
80 _DeleteCubeMapTexture();
81
82 //update generated materials
83 SRoot::getSingletonPtr()->RemoveGeneratedMaterial(materialTransparent.get());
84
85 Ogre::MaterialManager::getSingleton().remove(materialTransparent->getHandle());
86 materialTransparent.reset();
87
88 // Destroy the camera
89 currentScene->GetOgreScenePointer()->destroyCamera(cubeMapCamera);
90 currentScene->GetOgreScenePointer()->destroySceneNode(camNode);
91 }
92
93 void SDynamicCubeMap::SetSize(const unsigned int& newSize)
94 {
95 if (size != newSize)
96 {
97 // is new size valid (2^n)?
98 double result = log((double)newSize) / log((double)2.0);
99 double fractpart, intpart;
100 fractpart = modf(result, &intpart);
101 if (fractpart == 0)
102 {
103 bool savedState = state;
104
105 // Remove the render target listeners.
106 SetEnable(false);
107
108 _CreateCubeMapTexture(newSize);
109 size = newSize;
110 SetEnable(savedState);
111 }
112 else
113 {
114 OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Cube map texture size must be a power of 2 number!", "SDynamicCubeMap::SetSize");
115 }
116 }
117 }
118
120 {
121 return size;
122 }
123
124 void SDynamicCubeMap::SetMaterial(SMaterial* targetMaterial, const int& targetTechnique, const int& targetPass, const int& targetTextureUnit)
125 {
126 if (targetMaterial != 0)
127 {
128 bool savedState = state;
129 SetEnable(false);
130 material = targetMaterial->getOgreMaterialPointer();
131 techIndex = targetTechnique;
132 passIndex = targetPass;
133 unitIndex = targetTextureUnit;
134 SetEnable(savedState);
135 }
136 }
137
138 void SDynamicCubeMap::SetTextureUnit()
139 {
140 if (!material)
141 return;
142
143 Ogre::Material::Techniques suptechs = material->getSupportedTechniques();
144 Ogre::Material::Techniques techs = material->getTechniques();
145
146 if (techIndex >= techs.size() || (suptechs.size() == 0))
147 return;
148
149 Ogre::Technique::Passes matPasses;
150 Ogre::Pass* tmpPass = 0;
151 const Ogre::RenderSystemCapabilities* caps = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getCapabilities();
152 if (caps && caps->hasCapability(Ogre::RSC_FIXED_FUNCTION) == false)
153 {
154 matPasses = suptechs[0]->getPasses();
155 if (passIndex >= matPasses.size())
156 return;
157
158 tmpPass = matPasses[passIndex];
159 }
160 else
161 {
162 matPasses = techs[techIndex]->getPasses();
163 if (techIndex >= matPasses.size())
164 return;
165
166 tmpPass = matPasses[techIndex];
167 }
168
169 // Check if the targetTextureUnit is inbound
170 Ogre::TextureUnitState* texState = 0;
171 Ogre::Pass::TextureUnitStates texs = tmpPass->getTextureUnitStates();
172 if ((texs.size() > 0) && (unitIndex < texs.size()))
173 texState = texs[unitIndex];
174
175 if (texState != 0)
176 {
177 oldTexture = texState->_getTexturePtr();
178 texState->setTexture(cubeMapTexture);
179
180 Ogre::Any bindedSPass = tmpPass->getUserObjectBindings().getUserAny("SPass");
181 if (bindedSPass.has_value())
182 {
183 SPass* pass = Ogre::any_cast<SPass*> (bindedSPass);
184 pass->BuildShader();
185 }
187 }
188 }
189
190 void SDynamicCubeMap::ResetTextureUnit()
191 {
192 if (!material)
193 return;
194
195 Ogre::Material::Techniques suptechs = material->getSupportedTechniques();
196 Ogre::Material::Techniques techs = material->getTechniques();
197
198 if (techIndex >= techs.size() || (suptechs.size() == 0))
199 return;
200
201 Ogre::Technique::Passes matPasses;
202 Ogre::Pass* tmpPass = 0;
203 const Ogre::RenderSystemCapabilities* caps = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getCapabilities();
204 if (caps && caps->hasCapability(Ogre::RSC_FIXED_FUNCTION) == false)
205 {
206 matPasses = suptechs[0]->getPasses();
207 if (passIndex >= matPasses.size())
208 return;
209
210 tmpPass = matPasses[passIndex];
211 }
212 else
213 {
214 matPasses = techs[techIndex]->getPasses();
215 if (techIndex >= matPasses.size())
216 return;
217
218 tmpPass = matPasses[techIndex];
219 }
220
221 // Check if the targetTextureUnit is inbound
222 Ogre::TextureUnitState* texState = 0;
223 Ogre::Pass::TextureUnitStates texs = tmpPass->getTextureUnitStates();
224 if ((texs.size() > 0) && (unitIndex < texs.size()))
225 texState = texs[unitIndex];
226
227 if (texState != 0)
228 {
229 if (!oldTexture)
230 texState->setBlank();
231 else
232 texState->setTexture(oldTexture);
233
234 Ogre::Any bindedSPass = tmpPass->getUserObjectBindings().getUserAny("SPass");
235 if (bindedSPass.has_value())
236 {
237 SPass* pass = Ogre::any_cast<SPass*> (bindedSPass);
238 pass->BuildShader();
239 }
240
242 }
243 oldTexture.reset();
244 }
245
246 void SDynamicCubeMap::SetEnable(const bool& newState)
247 {
248 if (cubeMapTexture)
249 {
250 if (!material)
251 return;
252
253 DisableRendering();
254 if ((newState == true) && (state == false))
255 {
256 state = true;
257 SetTextureUnit();
258 needUpdate = true;
259
260 if (autoUpdate)
261 EnableRendering();
262 }
263 else if ((newState == false) && (state == true))
264 {
265 state = false;
266 needUpdate = false;
267 ResetTextureUnit();
268 }
269 }
270 }
271
273 {
274 return state;
275 }
276
277 void SDynamicCubeMap::SetAutoUpdate(const bool& newAutoUpdateValue)
278 {
279 if ((newAutoUpdateValue == true) && (autoUpdate == false))
280 {
281 // Remove frame listener
282 Ogre::Root::getSingleton().removeFrameListener(this);
283
284 autoUpdate = true;
285 renderingEnable = false;
286 EnableRendering();
287 }
288 else if ((newAutoUpdateValue == false) && (autoUpdate == true))
289 {
290 autoUpdate = false;
291 DisableRendering();
292
293 // Add frame listener
294 Ogre::Root::getSingleton().addFrameListener(this);
295 }
296 }
297
299 {
300 return autoUpdate;
301 }
302
304 {
305 needUpdate = true;
306 }
307
308 void SDynamicCubeMap::EnableRendering()
309 {
310 if (!renderingEnable && cubeMapTexture)
311 {
312 for (unsigned int i = 0; i < 6; i++)
313 {
314 if (cubeMapTargets[i])
315 {
316 cubeMapTargets[i]->setAutoUpdated(true);
317 cubeMapTargets[i]->addListener(this);
318 }
319 }
320
321 Ogre::MaterialManager::getSingleton().addListener(this);
322 renderingEnable = true;
323 }
324 }
325
326 void SDynamicCubeMap::DisableRendering()
327 {
328 if (renderingEnable && cubeMapTexture)
329 {
330 for (unsigned int i = 0; i < 6; i++)
331 {
332 if (cubeMapTargets[i])
333 {
334 cubeMapTargets[i]->setAutoUpdated(false);
335 cubeMapTargets[i]->removeListener(this);
336 }
337 }
338
339 Ogre::MaterialManager::getSingleton().removeListener(this);
340 renderingEnable = false;
341 }
342 }
343
344 void SDynamicCubeMap::_CreateCubeMapTexture(const unsigned int& newSize)
345 {
346 _DeleteCubeMapTexture();
347 try
348 {
349 Ogre::PixelFormat rttformat;
351 cubeMapTexture = Ogre::TextureManager::getSingleton().createManual("texture_" + cubeMapScheme, SO3_INTERNAL_DYNAMIC_READABLE_RESOURCE_GROUP, Ogre::TEX_TYPE_CUBE_MAP, newSize, newSize, 0, rttformat, Ogre::TU_RENDERTARGET);
352
353 for (unsigned int i = 0; i < 6; i++)
354 {
355 cubeMapTargets[i] = cubeMapTexture->getBuffer(i)->getRenderTarget();
356 cubeMapTargets[i]->removeAllViewports();
357
358 //$BB when cubemap is created disabled and never enabled the auto update keep on true and take a lots of fps for nothing
359 cubeMapTargets[i]->setAutoUpdated(false);
360#if defined (RPI)
361 cubeMapTargets[i]->setDepthBufferPool(Ogre::DepthBuffer::POOL_NO_DEPTH);
362#endif
363
364 Ogre::Viewport* viewport = cubeMapTargets[i]->addViewport(cubeMapCamera);
365 viewport->setOverlaysEnabled(false);
366 viewport->setMaterialScheme(cubeMapScheme);
367 }
368 }
369 catch (Ogre::Exception &e)
370 {
371 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("An exception has occurred: " + e.getDescription());
372 cubeMapTexture.reset();
373 }
374 }
375
376 void SDynamicCubeMap::_DeleteCubeMapTexture()
377 {
378 if (cubeMapTexture)
379 {
380 // IMPORTANT! Do not forget to detach the target, otherwise, the texture will not be deleted cause TexturePtr ref count still will be > 1
381 for (unsigned int i = 0; i < 6; i++)
382 {
383 cubeMapTargets[i]->removeAllViewports();
384 Ogre::Root::getSingleton().detachRenderTarget(cubeMapTargets[i]);
385 cubeMapTargets[i] = 0;
386 }
387
388 Ogre::TextureManager::getSingleton().remove(cubeMapTexture->getHandle());
389 cubeMapTexture.reset();
390 }
391 }
392
393 void SDynamicCubeMap::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
394 {
395 // point the camera in the right direction based on which face of the cubemap this is
396 camNode->setOrientation((camNode->getParentSceneNode()->_getDerivedOrientation().Inverse() * Ogre::Quaternion::IDENTITY));
397 if (evt.source == cubeMapTargets[0])
398 camNode->yaw(Ogre::Degree(-90));
399 else if (evt.source == cubeMapTargets[1])
400 camNode->yaw(Ogre::Degree(90));
401 else if (evt.source == cubeMapTargets[2])
402 camNode->pitch(Ogre::Degree(90));
403 else if (evt.source == cubeMapTargets[3])
404 camNode->pitch(Ogre::Degree(-90));
405 else if (evt.source == cubeMapTargets[5])
406 camNode->yaw(Ogre::Degree(180));
407 }
408
409 void SDynamicCubeMap::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
410 {
411 }
412
413 Ogre::Technique* SDynamicCubeMap::handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, const Ogre::Renderable* rend)
414 {
415 Ogre::Material::Techniques suptechs = materialTransparent->getTechniques();
416 if ((cubeMapScheme == schemeName) && (originalMaterial == material.get()) && (suptechs.size() > 0))
417 {
418 // Set a transparent technique
419 return suptechs[0];
420 }
421
422 return 0;
423 }
424
425 bool SDynamicCubeMap::frameStarted(const Ogre::FrameEvent& evt)
426 {
427 if (state && needUpdate)
428 {
429 if (needTextureUpdate)
430 {
431 _CreateCubeMapTexture(size);
432 needTextureUpdate = false;
433 }
434
435 EnableRendering();
436 }
437
438 return true;
439 }
440
441 bool SDynamicCubeMap::frameEnded(const Ogre::FrameEvent& evt)
442 {
443 if (state && needUpdate)
444 {
445 DisableRendering();
446 needUpdate = false;
447 }
448 return true;
449 }
450
451 void SDynamicCubeMap::windowResized(Ogre::RenderWindow* rw)
452 {
453 Update();
454 }
455
456}
void SetEnable(const bool &newState)
virtual void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
virtual void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
virtual bool frameEnded(const Ogre::FrameEvent &evt)
void SetMaterial(SMaterial *targetMaterial, const int &targetTechnique, const int &targetPass, const int &targetTextureUnit)
void SetSize(const unsigned int &newSize)
virtual bool frameStarted(const Ogre::FrameEvent &evt)
void SetAutoUpdate(const bool &newAutoUpdateValue)
virtual Ogre::Technique * handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String &schemeName, Ogre::Material *originalMaterial, unsigned short lodIndex, const Ogre::Renderable *rend)
virtual void windowResized(Ogre::RenderWindow *rw)
Ogre::MaterialPtr getOgreMaterialPointer()
SScene * currentScene
Definition SO3NodeScol.h:68
Ogre::SceneNode * O3SceneNode
Definition SO3NodeScol.h:69
bool GetRttPixelFormat(Ogre::PixelFormat &format, bool alpha=false, bool floattex=false)
Definition SO3Root.cpp:650
Ogre::RenderSystem * GetOgreRenderSystem()
Definition SO3Root.cpp:865
void RemoveGeneratedMaterial(Ogre::Material *mat)
Definition SO3Root.cpp:2343
static SRoot & getSingleton()
Definition SO3Root.cpp:116
static SRoot * getSingletonPtr()
Definition SO3Root.cpp:111
Ogre::SceneManager * GetOgreScenePointer()
Definition SO3Scene.cpp:449