00001
00007 #include "SO3DynamicReflectionMap.h"
00008 #include "SO3Material.h"
00009 #include "../SO3SceneGraph/SO3Scene.h"
00010 #include "../SO3SceneGraph/SO3Camera.h"
00011 #include "../SO3Renderer/SO3Root.h"
00012 #include "../SO3Renderer/SO3Window.h"
00013 #include "../SO3Renderer/SO3Viewport.h"
00014
00015 namespace SO3
00016 {
00017
00018 SDynamicReflectionMap::SDynamicReflectionMap() : SNode(0, "", SNode::DYNAMIC_REFLECTION_MAP_ID)
00019 {
00020
00021 }
00022
00023 SDynamicReflectionMap::SDynamicReflectionMap(SScene* parent, SViewPort* viewport, std::string dynamicReflectionMapName) : SNode(parent, dynamicReflectionMapName, SNode::DYNAMIC_REFLECTION_MAP_ID)
00024 {
00025
00026 reflectionMapScheme = dynamicReflectionMapName + "_SO3_DynamicReflectionMap_Scheme";
00027 material.setNull();
00028 textureUnitState = 0;
00029 oldTextureName = "";
00030 size = 256;
00031 revertClipPlane = false;
00032 state = false;
00033 renderingEnable = false;
00034 flipClipPlane = false;
00035
00036 reflectionMapViewport = viewport;
00037
00038
00039 reflectionMapPlane = new Ogre::MovablePlane("reflectionPlane"+reflectionMapScheme);
00040 reflectionMapPlane->redefine(Ogre::Vector3::UNIT_Y, Ogre::Vector3::ZERO);
00041 O3SceneNode->attachObject(reflectionMapPlane);
00042 reflectionMapPlane->setVisible(false);
00043
00044
00045 cameraClipPlane = new Ogre::MovablePlane("CameraClipPlane"+reflectionMapScheme);
00046 cameraClipPlane->redefine(Ogre::Vector3::UNIT_Y, Ogre::Vector3::ZERO);
00047 O3SceneNode->attachObject(cameraClipPlane);
00048 cameraClipPlane->setVisible(false);
00049
00050
00051 reflectionMapCamera = currentScene->GetOgreScenePointer()->createCamera("camera_"+reflectionMapScheme);
00052 reflectionMapCamera->setFOVy(Ogre::Degree(45));
00053 reflectionMapCamera->setAspectRatio(1);
00054 reflectionMapCamera->setFixedYawAxis(false);
00055 reflectionMapCamera->setNearClipDistance(Ogre::Real(0.001));
00056
00057
00058 reflectionMapCamera->enableReflection(reflectionMapPlane);
00059
00060
00061 reflectionMapCamera->enableCustomNearClipPlane(cameraClipPlane);
00062
00063
00064 _CreateReflectionMapTexture(size);
00065
00066
00067 materialTransparent = Ogre::MaterialManager::getSingleton().create("SO3_Material_" + reflectionMapScheme, SO3_INTERNAL_DYNAMIC_RESOURCE_GROUP);
00068 materialTransparent->getTechnique(0)->setColourWriteEnabled(false);
00069 materialTransparent->getTechnique(0)->setDepthCheckEnabled(false);
00070 materialTransparent->getTechnique(0)->setDepthWriteEnabled(false);
00071 }
00072
00073 SDynamicReflectionMap::~SDynamicReflectionMap()
00074 {
00075
00076 SetEnable(false);
00077
00078
00079 _DeleteReflectionMapTexture();
00080
00081
00082 Ogre::MaterialManager::getSingleton().remove(materialTransparent->getHandle());
00083 materialTransparent.setNull();
00084 reflectionMapCamera->disableCustomNearClipPlane();
00085 reflectionMapCamera->disableReflection();
00086
00087 O3SceneNode->detachObject(reflectionMapCamera);
00088 currentScene->GetOgreScenePointer()->destroyCamera(reflectionMapCamera);
00089
00090 O3SceneNode->detachObject(reflectionMapPlane);
00091 SAFE_DELETE(reflectionMapPlane);
00092
00093 O3SceneNode->detachObject(cameraClipPlane);
00094 SAFE_DELETE(cameraClipPlane);
00095 }
00096
00097 void SDynamicReflectionMap::SetSize(unsigned int newSize)
00098 {
00099 if (size != newSize)
00100 {
00101
00102 double result = log((double)newSize)/log((double)2.0);
00103 double fractpart, intpart;
00104 fractpart = modf(result, &intpart);
00105 if (fractpart==0)
00106 {
00107 bool savedState = state;
00108
00109
00110 SetEnable(false);
00111
00112 _CreateReflectionMapTexture(newSize);
00113 size = newSize;
00114
00115 SetEnable(savedState);
00116 }
00117 else
00118 {
00119 OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Reflection map texture size must be a power of 2 number!", "SDynamicReflectionMap::SetSize");
00120 }
00121 }
00122 }
00123
00124 unsigned int SDynamicReflectionMap::GetSize()
00125 {
00126 return size;
00127 }
00128
00129 void SDynamicReflectionMap::SetMaterial(SMaterial* targetMaterial, int targetTechnique, int targetPass, int targetTextureUnit)
00130 {
00131 if (targetMaterial != 0)
00132 {
00133 Ogre::MaterialPtr tmpMaterial = targetMaterial->getOgreMaterialPointer();
00134 Ogre::Pass* tmpPass = tmpMaterial->getTechnique(targetTechnique)->getPass(targetPass);
00135
00136 bool savedState = state;
00137 SetEnable(false);
00138 material = tmpMaterial;
00139
00140
00141 int numTextureUnits = tmpPass->getNumTextureUnitStates();
00142
00143 if ((numTextureUnits>0) && (targetTextureUnit<numTextureUnits))
00144 {
00145 Ogre::TextureUnitState* tmpTextureUnitState = tmpPass->getTextureUnitState(targetTextureUnit);
00146 if((tmpTextureUnitState != 0) && ((textureUnitState == 0) || (textureUnitState != tmpTextureUnitState)))
00147 {
00148 textureUnitState = tmpTextureUnitState;
00149 }
00150 }
00151 else
00152 {
00153 textureUnitState = 0;
00154 }
00155 SetEnable(savedState);
00156 }
00157 }
00158
00159 void SDynamicReflectionMap::SetTextureUnit()
00160 {
00161 if (textureUnitState != 0)
00162 {
00163 oldTextureName = textureUnitState->getTextureName();
00164 oldTextureType = textureUnitState->getTextureType();
00165 oldAdressingMode = textureUnitState->getTextureAddressingMode();
00166
00167 textureUnitState->setTextureName("texture_"+reflectionMapScheme);
00168 textureUnitState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
00169 textureUnitState->setProjectiveTexturing(true, reflectionMapCamera);
00170 }
00171 }
00172
00173 void SDynamicReflectionMap::ResetTextureUnit()
00174 {
00175 if (textureUnitState != 0)
00176 {
00177 textureUnitState->setProjectiveTexturing(false);
00178 textureUnitState->setTextureAddressingMode(oldAdressingMode);
00179 textureUnitState->setTextureName(oldTextureName, oldTextureType);
00180 }
00181 oldTextureName = "";
00182 }
00183
00184 void SDynamicReflectionMap::SetEnable(bool newState)
00185 {
00186 if (!reflectionMapTexture.isNull())
00187 {
00188 if ((newState == true) && (state == false))
00189 {
00190 state = true;
00191 SetTextureUnit();
00192 EnableRendering();
00193 }
00194 else if ((newState == false) && (state == true))
00195 {
00196 DisableRendering();
00197 state = false;
00198 ResetTextureUnit();
00199 }
00200 }
00201 }
00202
00203 bool SDynamicReflectionMap::GetEnable()
00204 {
00205 return state;
00206 }
00207
00208 void SDynamicReflectionMap::FlipPlane(bool newFlip)
00209 {
00210 if (newFlip != flipClipPlane)
00211 {
00212 flipClipPlane = newFlip;
00213
00214
00215 reflectionMapCamera->disableCustomNearClipPlane();
00216 reflectionMapCamera->disableReflection();
00217
00218
00219 O3SceneNode->detachObject(cameraClipPlane);
00220 SAFE_DELETE(cameraClipPlane);
00221
00222
00223 O3SceneNode->detachObject(reflectionMapPlane);
00224 SAFE_DELETE(reflectionMapPlane);
00225
00226
00227 cameraClipPlane = new Ogre::MovablePlane("CameraClipPlane"+reflectionMapScheme);
00228 cameraClipPlane->redefine(((flipClipPlane && !revertClipPlane) || (revertClipPlane && !flipClipPlane)) ? (Ogre::Vector3::NEGATIVE_UNIT_Y) : (Ogre::Vector3::UNIT_Y), Ogre::Vector3::ZERO);
00229 O3SceneNode->attachObject(cameraClipPlane);
00230
00231 cameraClipPlane->setVisible(false);
00232
00233
00234 reflectionMapPlane = new Ogre::MovablePlane("reflectionPlane"+reflectionMapScheme);
00235 reflectionMapPlane->redefine(flipClipPlane ? (Ogre::Vector3::NEGATIVE_UNIT_Y) : (Ogre::Vector3::UNIT_Y), Ogre::Vector3::ZERO);
00236 O3SceneNode->attachObject(reflectionMapPlane);
00237 cameraClipPlane->setVisible(false);
00238
00239
00240 reflectionMapCamera->enableCustomNearClipPlane(cameraClipPlane);
00241
00242
00243 if (!revertClipPlane)
00244 reflectionMapCamera->enableReflection(reflectionMapPlane);
00245 }
00246 }
00247
00248 void SDynamicReflectionMap::SetRevertClipPlane(bool newRevertClipPlaneValue)
00249 {
00250 if (newRevertClipPlaneValue != revertClipPlane)
00251 {
00252 revertClipPlane = newRevertClipPlaneValue;
00253
00254
00255 reflectionMapCamera->disableCustomNearClipPlane();
00256
00257
00258 O3SceneNode->detachObject(cameraClipPlane);
00259 SAFE_DELETE(cameraClipPlane);
00260
00261
00262 cameraClipPlane = new Ogre::MovablePlane("CameraClipPlane"+reflectionMapScheme);
00263 cameraClipPlane->redefine(revertClipPlane ? (- Ogre::Vector3::UNIT_Y) : (Ogre::Vector3::UNIT_Y), Ogre::Vector3::ZERO);
00264 O3SceneNode->attachObject(cameraClipPlane);
00265 cameraClipPlane->setVisible(false);
00266
00267
00268 reflectionMapCamera->enableCustomNearClipPlane(cameraClipPlane);
00269
00270
00271 if (revertClipPlane)
00272 reflectionMapCamera->disableReflection();
00273 else
00274 reflectionMapCamera->enableReflection(reflectionMapPlane);
00275 }
00276 }
00277
00278 bool SDynamicReflectionMap::GetRevertClipPlane()
00279 {
00280 return revertClipPlane;
00281 }
00282
00283
00284 void SDynamicReflectionMap::EnableRendering()
00285 {
00286 if(!renderingEnable)
00287 {
00288 reflectionMapTargets->addListener(this);
00289 reflectionMapTargets->setAutoUpdated(true);
00290
00291 Ogre::MaterialManager::getSingleton().addListener(this);
00292 renderingEnable = true;
00293 }
00294 }
00295
00296 void SDynamicReflectionMap::DisableRendering()
00297 {
00298 if(renderingEnable)
00299 {
00300 reflectionMapTargets->removeListener(this);
00301 reflectionMapTargets->setAutoUpdated(false);
00302
00303 Ogre::MaterialManager::getSingleton().removeListener(this);
00304 renderingEnable = false;
00305 }
00306 }
00307
00308 void SDynamicReflectionMap::_CreateReflectionMapTexture(unsigned int newSize)
00309 {
00310 _DeleteReflectionMapTexture();
00311 try
00312 {
00313 reflectionMapTexture = Ogre::TextureManager::getSingleton().createManual("texture_"+reflectionMapScheme, SO3_INTERNAL_DYNAMIC_READABLE_RESOURCE_GROUP, Ogre::TEX_TYPE_2D, newSize, newSize, Ogre::MIP_DEFAULT, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET|Ogre::TU_AUTOMIPMAP, this);
00314
00315 reflectionMapTargets = reflectionMapTexture->getBuffer()->getRenderTarget();
00316
00317 Ogre::Viewport* viewport = reflectionMapTargets->addViewport(reflectionMapCamera);
00318 viewport->setOverlaysEnabled(false);
00319 viewport->setMaterialScheme(reflectionMapScheme);
00320 }
00321 catch (Ogre::Exception &e)
00322 {
00323 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("An exception has occurred: "+ e.getDescription());
00324 reflectionMapTexture.setNull();
00325 }
00326 }
00327
00328 void SDynamicReflectionMap::_DeleteReflectionMapTexture()
00329 {
00330 if (!reflectionMapTexture.isNull())
00331 {
00332 Ogre::TextureManager::getSingleton().remove(reflectionMapTexture->getHandle());
00333 reflectionMapTexture.setNull();
00334 }
00335 }
00336
00337 void SDynamicReflectionMap::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
00338 {
00339
00340 SCamera* camera = reflectionMapViewport->GetCamera();
00341
00342
00343 reflectionMapCamera->setPosition(camera->GetGlobalPosition());
00344 reflectionMapCamera->setOrientation(camera->GetGlobalOrientation());
00345 reflectionMapCamera->setFOVy(camera->GetOgreCameraPointer()->getFOVy());
00346 reflectionMapCamera->setNearClipDistance(camera->GetNearClipDistance());
00347 reflectionMapCamera->setFarClipDistance(camera->GetFarClipDistance());
00348 reflectionMapCamera->setAspectRatio(camera->GetOgreCameraPointer()->getAspectRatio());
00349
00350
00351 if (reflectionMapPlane->getSide((GetTransformationMatrix().inverse() * camera->GetTransformationMatrix()).getTrans()) == Ogre::Plane::NEGATIVE_SIDE)
00352 FlipPlane(!flipClipPlane);
00353 }
00354
00355 void SDynamicReflectionMap::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
00356 {
00357 }
00358
00359 Ogre::Technique* SDynamicReflectionMap::handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, const Ogre::Renderable* rend)
00360 {
00361 if ((schemeName == reflectionMapScheme)&&(originalMaterial == material.get()))
00362 {
00363
00364 return materialTransparent->getTechnique(0);
00365 }
00366 return 0;
00367 }
00368
00369 void SDynamicReflectionMap::loadResource(Ogre::Resource* resource)
00370 {
00371 Ogre::Texture* tex = static_cast<Ogre::Texture*>(resource);
00372
00373 tex->setTextureType(Ogre::TEX_TYPE_2D);
00374 tex->setWidth(size);
00375 tex->setHeight(size);
00376 tex->setFormat(Ogre::PF_R8G8B8);
00377 tex->setUsage(Ogre::TU_RENDERTARGET|Ogre::TU_AUTOMIPMAP);
00378 tex->createInternalResources();
00379 }
00380
00381 }