00001
00007 #include "SO3DynamicCubeMap.h"
00008 #include "SO3Material.h"
00009 #include "../SO3SceneGraph/SO3Scene.h"
00010 #include "../SO3Renderer/SO3Root.h"
00011 #include "../SO3Renderer/SO3Window.h"
00012
00013 namespace SO3
00014 {
00015
00016 SDynamicCubeMap::SDynamicCubeMap() : SNode(0, "", SNode::DYNAMIC_CUBE_MAP_ID)
00017 {
00018
00019 }
00020
00021 SDynamicCubeMap::SDynamicCubeMap(SScene* parent, std::string dynamicCubeMapName) : SNode(parent, dynamicCubeMapName, SNode::DYNAMIC_CUBE_MAP_ID)
00022 {
00023 if(!Ogre::Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(Ogre::RSC_CUBEMAPPING))
00024 OGRE_EXCEPT(Ogre::Exception::ERR_NOT_IMPLEMENTED, "Your graphics card does not support cube mapping, so you cannot use this functionnality!", "SDynamicCubeMap::SDynamicCubeMap");
00025
00026
00027 cubeMapScheme = dynamicCubeMapName + "_SO3_DynamicCubeMap_Scheme";
00028 material.setNull();
00029 textureUnitState = 0;
00030 oldTextureName = "";
00031 size = 256;
00032 state = false;
00033 autoUpdate = false;
00034 needUpdate = false;
00035 renderingEnable = false;
00036
00037
00038 cubeMapCamera = currentScene->GetOgreScenePointer()->createCamera("camera_"+cubeMapScheme);
00039 cubeMapCamera->setFOVy(Ogre::Degree(90));
00040 cubeMapCamera->setAspectRatio(1);
00041 cubeMapCamera->setFixedYawAxis(false);
00042 cubeMapCamera->setNearClipDistance(Ogre::Real(0.001));
00043 O3SceneNode->attachObject(cubeMapCamera);
00044
00045
00046 _CreateCubeMapTexture(size);
00047
00048
00049 materialTransparent = Ogre::MaterialManager::getSingleton().create("SO3_Material_" + cubeMapScheme, SO3_INTERNAL_DYNAMIC_RESOURCE_GROUP);
00050 materialTransparent->getTechnique(0)->setColourWriteEnabled(false);
00051 materialTransparent->getTechnique(0)->setDepthCheckEnabled(false);
00052 materialTransparent->getTechnique(0)->setDepthWriteEnabled(false);
00053
00054
00055 Ogre::Root::getSingleton().addFrameListener(this);
00056
00057 const SWindowMap windowListCopy = currentScene->GetParent()->GetRenderWindowList();
00058 SWindowMap::const_iterator iWindowList = windowListCopy.begin();
00059 while (iWindowList != windowListCopy.end())
00060 {
00061 Ogre::WindowEventUtilities::addWindowEventListener(const_cast <Ogre::RenderWindow*> (iWindowList->second->GetOgreRenderWindowPointer()), this);
00062 iWindowList++;
00063 }
00064 }
00065
00066 SDynamicCubeMap::~SDynamicCubeMap()
00067 {
00068 SetEnable(false);
00069
00070 DisableRendering();
00071
00072
00073 if(!autoUpdate)
00074 {
00075
00076 const SWindowMap windowListCopy = currentScene->GetParent()->GetRenderWindowList();
00077 SWindowMap::const_iterator iWindowList = windowListCopy.begin();
00078 while (iWindowList != windowListCopy.end())
00079 {
00080 Ogre::WindowEventUtilities::removeWindowEventListener(const_cast <Ogre::RenderWindow*> (iWindowList->second->GetOgreRenderWindowPointer()), this);
00081 iWindowList++;
00082 }
00083
00084
00085 Ogre::Root::getSingleton().removeFrameListener(this);
00086 }
00087
00088
00089 _DeleteCubeMapTexture();
00090
00091
00092 Ogre::MaterialManager::getSingleton().remove(materialTransparent->getHandle());
00093 materialTransparent.setNull();
00094
00095
00096 O3SceneNode->detachObject(cubeMapCamera);
00097 currentScene->GetOgreScenePointer()->destroyCamera(cubeMapCamera);
00098 }
00099
00100 void SDynamicCubeMap::SetSize(unsigned int newSize)
00101 {
00102 if (size != newSize)
00103 {
00104
00105 double result = log((double)newSize)/log((double)2.0);
00106 double fractpart, intpart;
00107 fractpart = modf(result, &intpart);
00108 if (fractpart==0)
00109 {
00110 bool savedState = state;
00111
00112
00113 SetEnable(false);
00114
00115 _CreateCubeMapTexture(newSize);
00116 size = newSize;
00117 SetEnable(savedState);
00118 }
00119 else
00120 {
00121 OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Cube map texture size must be a power of 2 number!", "SDynamicCubeMap::SetSize");
00122 }
00123 }
00124 }
00125
00126 unsigned int SDynamicCubeMap::GetSize()
00127 {
00128 return size;
00129 }
00130
00131 void SDynamicCubeMap::SetMaterial(SMaterial* targetMaterial, int targetTechnique, int targetPass, int targetTextureUnit)
00132 {
00133 if (targetMaterial != 0)
00134 {
00135 Ogre::MaterialPtr tmpMaterial = targetMaterial->getOgreMaterialPointer();
00136 Ogre::Pass* tmpPass = tmpMaterial->getTechnique(targetTechnique)->getPass(targetPass);
00137
00138 bool savedState = state;
00139 SetEnable(false);
00140 material = tmpMaterial;
00141
00142
00143 int numTextureUnits = tmpPass->getNumTextureUnitStates();
00144
00145 if ((numTextureUnits>0) && (targetTextureUnit<numTextureUnits))
00146 {
00147 Ogre::TextureUnitState* tmpTextureUnitState = tmpPass->getTextureUnitState(targetTextureUnit);
00148 if((tmpTextureUnitState != 0) && ((textureUnitState == 0) || (textureUnitState != tmpTextureUnitState)))
00149 {
00150 textureUnitState = tmpTextureUnitState;
00151 }
00152 }
00153 else
00154 {
00155 textureUnitState = 0;
00156 }
00157 SetEnable(savedState);
00158 }
00159 }
00160
00161 void SDynamicCubeMap::SetTextureUnit()
00162 {
00163 if (textureUnitState != 0)
00164 {
00165 oldTextureName = textureUnitState->getTextureName();
00166 textureUnitState->setCubicTextureName("texture_"+cubeMapScheme, true);
00167 }
00168 }
00169
00170 void SDynamicCubeMap::ResetTextureUnit()
00171 {
00172 if (textureUnitState != 0)
00173 {
00174 textureUnitState->setCubicTextureName(oldTextureName, true);
00175 }
00176 oldTextureName = "";
00177 }
00178
00179 void SDynamicCubeMap::SetEnable(bool newState)
00180 {
00181 if (!cubeMapTexture.isNull())
00182 {
00183 DisableRendering();
00184 if ((newState == true) && (state == false))
00185 {
00186 state = true;
00187 SetTextureUnit();
00188 needUpdate = true;
00189
00190 if(autoUpdate)
00191 EnableRendering();
00192 }
00193 else if ((newState == false) && (state == true))
00194 {
00195 state = false;
00196 needUpdate = false;
00197 ResetTextureUnit();
00198 }
00199 }
00200 }
00201
00202 bool SDynamicCubeMap::GetEnable()
00203 {
00204 return state;
00205 }
00206
00207 void SDynamicCubeMap::SetAutoUpdate(bool newAutoUpdateValue)
00208 {
00209 if ((newAutoUpdateValue == true) && (autoUpdate == false))
00210 {
00211
00212 const SWindowMap windowListCopy = currentScene->GetParent()->GetRenderWindowList();
00213 SWindowMap::const_iterator iWindowList = windowListCopy.begin();
00214 while (iWindowList != windowListCopy.end())
00215 {
00216 Ogre::WindowEventUtilities::removeWindowEventListener(const_cast <Ogre::RenderWindow*> (iWindowList->second->GetOgreRenderWindowPointer()), this);
00217 iWindowList++;
00218 }
00219
00220
00221 Ogre::Root::getSingleton().removeFrameListener(this);
00222
00223 autoUpdate = true;
00224 EnableRendering();
00225 }
00226 else if ((newAutoUpdateValue == false) && (autoUpdate == true))
00227 {
00228 autoUpdate = false;
00229 DisableRendering();
00230
00231
00232 Ogre::Root::getSingleton().addFrameListener(this);
00233
00234 const SWindowMap windowListCopy = currentScene->GetParent()->GetRenderWindowList();
00235 SWindowMap::const_iterator iWindowList = windowListCopy.begin();
00236 while (iWindowList != windowListCopy.end())
00237 {
00238 Ogre::WindowEventUtilities::addWindowEventListener(const_cast <Ogre::RenderWindow*> (iWindowList->second->GetOgreRenderWindowPointer()), this);
00239 iWindowList++;
00240 }
00241 }
00242 }
00243
00244 bool SDynamicCubeMap::GetAutoUpdate()
00245 {
00246 return autoUpdate;
00247 }
00248
00249 void SDynamicCubeMap::Update()
00250 {
00251 needUpdate = true;
00252 }
00253
00254 void SDynamicCubeMap::EnableRendering()
00255 {
00256 if(!renderingEnable)
00257 {
00258 for (unsigned int i = 0; i < 6; i++)
00259 {
00260 cubeMapTargets[i]->setAutoUpdated(true);
00261 cubeMapTargets[i]->addListener(this);
00262 }
00263
00264 Ogre::MaterialManager::getSingleton().addListener(this);
00265 renderingEnable = true;
00266 }
00267 }
00268
00269 void SDynamicCubeMap::DisableRendering()
00270 {
00271 if(renderingEnable)
00272 {
00273 for (unsigned int i = 0; i < 6; i++)
00274 {
00275 cubeMapTargets[i]->setAutoUpdated(false);
00276 cubeMapTargets[i]->removeListener(this);
00277 }
00278
00279 Ogre::MaterialManager::getSingleton().removeListener(this);
00280 renderingEnable = false;
00281 }
00282 }
00283
00284 void SDynamicCubeMap::_CreateCubeMapTexture(unsigned int newSize)
00285 {
00286 _DeleteCubeMapTexture();
00287 try
00288 {
00289 cubeMapTexture = Ogre::TextureManager::getSingleton().createManual("texture_"+cubeMapScheme, SO3_INTERNAL_DYNAMIC_READABLE_RESOURCE_GROUP, Ogre::TEX_TYPE_CUBE_MAP, newSize, newSize, Ogre::MIP_DEFAULT, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET|Ogre::TU_AUTOMIPMAP, this);
00290
00291
00292 for (unsigned int i = 0; i < 6; i++)
00293 {
00294 cubeMapTargets[i] = cubeMapTexture->getBuffer(i)->getRenderTarget();
00295
00296 cubeMapTargets[i]->setAutoUpdated(false);
00297
00298 Ogre::Viewport* viewport = cubeMapTargets[i]->addViewport(cubeMapCamera);
00299 viewport->setOverlaysEnabled(false);
00300 viewport->setMaterialScheme(cubeMapScheme);
00301 }
00302 }
00303 catch (Ogre::Exception &e)
00304 {
00305 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("An exception has occurred: "+ e.getDescription());
00306 cubeMapTexture.setNull();
00307 }
00308 }
00309
00310 void SDynamicCubeMap::_DeleteCubeMapTexture()
00311 {
00312 if (!cubeMapTexture.isNull())
00313 {
00314 Ogre::TextureManager::getSingleton().remove(cubeMapTexture->getHandle());
00315 cubeMapTexture.setNull();
00316 }
00317 }
00318
00319 void SDynamicCubeMap::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
00320 {
00321
00322 cubeMapCamera->setOrientation((cubeMapCamera->getParentSceneNode()->_getDerivedOrientation().Inverse() * Ogre::Quaternion::IDENTITY));
00323 if (evt.source == cubeMapTargets[0])
00324 cubeMapCamera->yaw(Ogre::Degree(-90));
00325 else if (evt.source == cubeMapTargets[1])
00326 cubeMapCamera->yaw(Ogre::Degree(90));
00327 else if (evt.source == cubeMapTargets[2])
00328 cubeMapCamera->pitch(Ogre::Degree(90));
00329 else if (evt.source == cubeMapTargets[3])
00330 cubeMapCamera->pitch(Ogre::Degree(-90));
00331 else if (evt.source == cubeMapTargets[5])
00332 cubeMapCamera->yaw(Ogre::Degree(180));
00333 }
00334
00335 void SDynamicCubeMap::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
00336 {
00337
00338 }
00339
00340 Ogre::Technique* SDynamicCubeMap::handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, const Ogre::Renderable* rend)
00341 {
00342 if ((schemeName == cubeMapScheme)&&(originalMaterial == material.get()))
00343 {
00344
00345 return materialTransparent->getTechnique(0);
00346 }
00347 return 0;
00348 }
00349
00350 bool SDynamicCubeMap::frameStarted(const Ogre::FrameEvent& evt)
00351 {
00352 if(state && needUpdate)
00353 EnableRendering();
00354
00355 return true;
00356 }
00357
00358 bool SDynamicCubeMap::frameEnded(const Ogre::FrameEvent& evt)
00359 {
00360 if (state && needUpdate)
00361 {
00362 DisableRendering();
00363 needUpdate = false;
00364 }
00365 return true;
00366 }
00367
00368 void SDynamicCubeMap::loadResource(Ogre::Resource* resource)
00369 {
00370 Ogre::Texture* tex = static_cast<Ogre::Texture*>(resource);
00371
00372 tex->setTextureType(Ogre::TEX_TYPE_CUBE_MAP);
00373 tex->setWidth(size);
00374 tex->setHeight(size);
00375 tex->setFormat(Ogre::PF_R8G8B8);
00376 tex->setUsage(Ogre::TU_RENDERTARGET|Ogre::TU_AUTOMIPMAP);
00377 tex->createInternalResources();
00378 }
00379
00380 void SDynamicCubeMap::windowResized(Ogre::RenderWindow* rw)
00381 {
00382 Update();
00383 }
00384
00385 }