00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 #include "CaelumPrecompiled.h"
00022 #include "PrecipitationController.h"
00023 
00024 using namespace Ogre;
00025 
00026 namespace Caelum
00027 {
00028     const String PrecipitationController::COMPOSITOR_NAME = "Caelum/PrecipitationCompositor";
00029     const String PrecipitationController::MATERIAL_NAME =   "Caelum/PrecipitationMaterial";
00030 
00031     const PrecipitationPresetParams PrecipitationPresets[] = {
00032         { Ogre::ColourValue(0.8, 0.8, 0.8, 1), 0.95, "precipitation_drizzle.png" },
00033         { Ogre::ColourValue(0.8, 0.8, 0.8, 1), 0.85, "precipitation_rain.png" },
00034         { Ogre::ColourValue(0.8, 0.8, 0.8, 1), 0.12, "precipitation_snow.png" },
00035         { Ogre::ColourValue(0.8, 0.8, 0.8, 1), 0.33, "precipitation_snowgrains.png" },
00036         { Ogre::ColourValue(0.8, 0.8, 0.8, 1), 0.70, "precipitation_icecrystals.png" },
00037         { Ogre::ColourValue(0.8, 0.8, 0.8, 1), 0.78, "precipitation_icepellets.png" },
00038         { Ogre::ColourValue(0.8, 0.8, 0.8, 1), 0.74, "precipitation_hail.png" },
00039         { Ogre::ColourValue(0.8, 0.8, 0.8, 1), 0.70, "precipitation_smallhail.png" }
00040     };
00041 
00042     PrecipitationController::PrecipitationController(
00043             Ogre::SceneManager *sceneMgr)
00044     {
00045         Ogre::String uniqueId = Ogre::StringConverter::toString((size_t)this);
00046         mSceneMgr = sceneMgr;
00047 
00048         setAutoDisableThreshold (0.001);
00049         mCameraSpeedScale = Ogre::Vector3::UNIT_SCALE;
00050 
00051         setIntensity (0);
00052         setWindSpeed (Ogre::Vector3(0, 0, 0));
00053         mInternalTime = 0;
00054         mSecondsSinceLastFrame = 0;
00055         mFallingDirection = Ogre::Vector3::NEGATIVE_UNIT_Y;
00056 
00057         setPresetType (PRECTYPE_RAIN);
00058         
00059         update (0, Ogre::ColourValue(0, 0, 0, 0));
00060     }
00061 
00062     PrecipitationController::~PrecipitationController () {
00063         destroyAllViewportInstances ();
00064     }
00065 
00066     void PrecipitationController::setTextureName (const Ogre::String& textureName) {
00067         mPresetType = PRECTYPE_CUSTOM;
00068         mTextureName = textureName;
00069     }
00070     
00071     const Ogre::String PrecipitationController::getTextureName () const {
00072         return mTextureName;
00073     }
00074 
00075     void PrecipitationController::setSpeed (Real speed) {
00076         mPresetType = PRECTYPE_CUSTOM;
00077         mSpeed = speed;
00078     }
00079 
00080     Real PrecipitationController::getSpeed () const {
00081         return mSpeed;
00082     }
00083 
00084     void PrecipitationController::setColour (const Ogre::ColourValue& color) {
00085         mPresetType = PRECTYPE_CUSTOM;
00086         mColour = color;
00087     }
00088     
00089     const Ogre::ColourValue PrecipitationController::getColour () const {
00090         return mColour;
00091     }
00092 
00093     bool PrecipitationController::isPresetType (PrecipitationType type) {
00094         return PRECTYPE_DRIZZLE <= type && type <= PRECTYPE_SMALLHAIL;
00095     }
00096 
00097     const PrecipitationPresetParams& PrecipitationController::getPresetParams (PrecipitationType type) {
00098         assert(isPresetType(type));
00099         return PrecipitationPresets[type];
00100     }
00101 
00102     void PrecipitationController::setParams (const PrecipitationPresetParams& params) {
00103         setColour (params.Colour);
00104         setSpeed (params.Speed);
00105         setTextureName (params.Name);
00106     }
00107 
00108     void PrecipitationController::setPresetType (PrecipitationType type) {
00109         setParams (getPresetParams (type));
00110         mPresetType = type;
00111     }
00112 
00113     PrecipitationType PrecipitationController::getPresetType () const {
00114         return mPresetType;
00115     }
00116 
00117     void PrecipitationController::setWindSpeed (const Ogre::Vector3& value) {
00118         mWindSpeed = value;
00119     }
00120 
00121     const Ogre::Vector3 PrecipitationController::getWindSpeed () const {
00122         return mWindSpeed;
00123     }
00124 
00125     void PrecipitationController::setIntensity (Real intensity) {
00126         mIntensity = intensity;
00127     }
00128 
00129     Real PrecipitationController::getIntensity () const {
00130         return mIntensity;
00131     }
00132 
00133     void PrecipitationController::update (Real secondsSinceLastFrame, Ogre::ColourValue colour) {
00134         mSecondsSinceLastFrame = secondsSinceLastFrame;
00135         mInternalTime += mSecondsSinceLastFrame;
00136         mSceneColour = colour;
00137 
00138         ViewportInstanceMap::const_iterator it;
00139         ViewportInstanceMap::const_iterator begin = mViewportInstanceMap.begin ();
00140         ViewportInstanceMap::const_iterator end = mViewportInstanceMap.end ();
00141         for (it = begin; it != end; ++it) {
00142             it->second->_update ();
00143         }
00144     }
00145 
00146     void PrecipitationController::setManualCameraSpeed (const Ogre::Vector3& value) {
00147         ViewportInstanceMap::const_iterator it;
00148         ViewportInstanceMap::const_iterator begin = mViewportInstanceMap.begin();
00149         ViewportInstanceMap::const_iterator end = mViewportInstanceMap.end();
00150         for (it = begin; it != end; ++it) {
00151             it->second->setManualCameraSpeed(value);
00152         }
00153     }
00154 
00155     void PrecipitationController::setAutoCameraSpeed() {
00156         ViewportInstanceMap::const_iterator it;
00157         ViewportInstanceMap::const_iterator begin = mViewportInstanceMap.begin();
00158         ViewportInstanceMap::const_iterator end = mViewportInstanceMap.end();
00159         for (it = begin; it != end; ++it) {
00160             it->second->setAutoCameraSpeed();
00161         }
00162     }
00163 
00164     void PrecipitationController::_updateMaterialParams(
00165             const Ogre::MaterialPtr& mat,
00166             const Ogre::Camera* cam,
00167             const Ogre::Vector3& camSpeed) 
00168     {       
00169         
00170         Real appTime = static_cast<Real>(fmod(mInternalTime, static_cast<Real>(4523.893416f)));
00171 
00172         Ogre::GpuProgramParametersSharedPtr fpParams =
00173                 mat->getBestTechnique ()->getPass (0)->getFragmentProgramParameters ();
00174 
00175         fpParams->setIgnoreMissingParams(true);
00176         Real sceneLum = (mSceneColour.r + mSceneColour.g + mSceneColour.b) / 3;
00177         mSceneColour.r = mSceneColour.g = mSceneColour.b = sceneLum;            
00178         fpParams->setNamedConstant("precColor", mSceneColour * mColour);
00179         fpParams->setNamedConstant("intensity", mIntensity);
00180         fpParams->setNamedConstant("dropSpeed", 0);     
00181 
00182         Ogre::Vector3 corner1, corner2, corner3, corner4;
00183 
00184         corner1 = cam->getCameraToViewportRay(0, 0).getDirection();
00185         corner2 = cam->getCameraToViewportRay(1, 0).getDirection();
00186         corner3 = cam->getCameraToViewportRay(0, 1).getDirection();
00187         corner4 = cam->getCameraToViewportRay(1, 1).getDirection();
00188 
00189         Ogre::Vector3 precDir =
00190                 mSpeed * mFallingDirection +
00191                 mWindSpeed -
00192                 camSpeed * mCameraSpeedScale;
00193         Ogre::Quaternion quat = precDir.getRotationTo(Ogre::Vector3(0, -1, 0));
00194 
00195         corner1 = quat * corner1;
00196         corner2 = quat * corner2;
00197         corner3 = quat * corner3;
00198         corner4 = quat * corner4;
00199 
00200         fpParams->setNamedConstant("corner1", corner1);
00201         fpParams->setNamedConstant("corner2", corner2);
00202         fpParams->setNamedConstant("corner3", corner3);
00203         fpParams->setNamedConstant("corner4", corner4);     
00204         
00205         float fallSpeed = precDir.length();
00206 
00207         fpParams->setNamedConstant("deltaX",
00208             Ogre::Vector3(sin(appTime) + 4.33, cos(appTime * 1.5) + 5.26,
00209                 cos(appTime * 2.5)) * fallSpeed / 10 + 88.001);
00210         fpParams->setNamedConstant("deltaY",
00211             Ogre::Vector3(0.6, 1.0, 1.4) * fallSpeed * appTime);
00212 
00213         if (mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->getTextureName() != mTextureName) {
00214             mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName(mTextureName);
00215         }
00216     }
00217 
00218     PrecipitationInstance::PrecipitationInstance
00219     (
00220         PrecipitationController* parent,
00221         Ogre::Viewport* viewport
00222     ):
00223         mParent(parent),
00224         mViewport(viewport),
00225         mCompInst(0),
00226         mLastCamera(0),
00227         mLastCameraPosition(Vector3::ZERO),
00228         mCameraSpeed(Vector3::ZERO),
00229         mAutoCameraSpeed(true)
00230     {
00231         createCompositor ();
00232     }
00233 
00234     PrecipitationInstance::~PrecipitationInstance ()
00235     {
00236         destroyCompositor();
00237     }
00238 
00239     void PrecipitationInstance::createCompositor ()
00240     {
00241         
00242         if (mCompInst) {
00243             return;
00244         }
00245 
00246         Ogre::CompositorManager* compMgr = Ogre::CompositorManager::getSingletonPtr();
00247         
00248         
00249         mCompInst = compMgr->addCompositor(mViewport, PrecipitationController::COMPOSITOR_NAME);
00250         assert(mCompInst);
00251         mCompInst->setEnabled (false);
00252         mCompInst->addListener (this);
00253     }
00254 
00255     void PrecipitationInstance::destroyCompositor ()
00256     {
00257         
00258         if (mCompInst == 0) {
00259             return;
00260         }
00261 
00262         Ogre::CompositorManager* compMgr = Ogre::CompositorManager::getSingletonPtr();
00263 
00264         
00265         mCompInst->removeListener (this);
00266         compMgr->removeCompositor(mViewport, PrecipitationController::COMPOSITOR_NAME);
00267         mCompInst = 0;
00268     }
00269 
00270     void PrecipitationInstance::notifyMaterialSetup(uint pass_id, Ogre::MaterialPtr &mat)
00271     {
00272         
00273     }
00274 
00275     void PrecipitationInstance::notifyMaterialRender(uint pass_id, Ogre::MaterialPtr &mat)
00276     {
00277         if (mAutoCameraSpeed) {
00278             Ogre::Camera* cam = mViewport->getCamera();
00279             Ogre::Vector3 camPos = cam->getDerivedPosition();
00280             if (cam != mLastCamera) {
00281                 mCameraSpeed = Ogre::Vector3::ZERO;
00282             } else {
00283                 Real timeDiff = mParent->getSecondsSinceLastFrame ();
00284                 Ogre::Vector3 posDiff = camPos - mLastCameraPosition;
00285 
00286                 
00287                 if (timeDiff > 1e-10) {
00288                     mCameraSpeed = posDiff / timeDiff;
00289                 } else {
00290                     
00291                 }
00292 
00293                 
00294 
00295 
00296 
00297 
00298 
00299 
00300             }
00301             mLastCamera = cam;
00302             mLastCameraPosition = camPos;
00303         }
00304         mParent->_updateMaterialParams (mat, mViewport->getCamera(), mCameraSpeed);
00305     }
00306 
00307     bool PrecipitationInstance::getAutoCameraSpeed () {
00308         return mAutoCameraSpeed;
00309     }
00310 
00311     void PrecipitationInstance::setAutoCameraSpeed () {
00312         mAutoCameraSpeed = true;
00313         mCameraSpeed = Ogre::Vector3::ZERO;
00314         mLastCamera = 0;
00315     }
00316 
00317     void PrecipitationInstance::setManualCameraSpeed (const Ogre::Vector3& value) {
00318         mAutoCameraSpeed = false;
00319         mCameraSpeed = value;
00320     }
00321 
00322     const Ogre::Vector3 PrecipitationInstance::getCameraSpeed () {
00323         return mCameraSpeed;
00324     }
00325 
00326     bool PrecipitationInstance::shouldBeEnabled () const {
00327         return mParent->getAutoDisableThreshold () < 0 ||
00328                mParent->getIntensity () > mParent->getAutoDisableThreshold ();
00329     }
00330 
00331     void PrecipitationInstance::_update ()
00332     {
00333         mCompInst->setEnabled (shouldBeEnabled ());
00334     }
00335 
00336     PrecipitationInstance* PrecipitationController::createViewportInstance (Ogre::Viewport* vp)
00337     {
00338         ViewportInstanceMap::const_iterator it = mViewportInstanceMap.find (vp);
00339         if (it == mViewportInstanceMap.end()) {
00340             std::auto_ptr<PrecipitationInstance> inst (new PrecipitationInstance(this, vp));
00341             mViewportInstanceMap.insert (std::make_pair (vp, inst.get()));
00342             
00343             return inst.release();
00344         } else {
00345             return it->second;
00346         }
00347     }
00348     
00349     PrecipitationInstance* PrecipitationController::getViewportInstance(Ogre::Viewport* vp) {
00350         ViewportInstanceMap::iterator it = mViewportInstanceMap.find (vp);
00351         if (it != mViewportInstanceMap.end ()) {
00352             return it->second;
00353         } else {
00354             return 0;
00355         }
00356     }
00357 
00358     void PrecipitationController::destroyViewportInstance (Viewport* vp)
00359     {
00360         ViewportInstanceMap::iterator it = mViewportInstanceMap.find (vp);
00361         if (it != mViewportInstanceMap.end ()) {
00362             PrecipitationInstance* inst = it->second;
00363             delete inst;
00364             mViewportInstanceMap.erase (it);
00365         }
00366     }
00367 
00368     void PrecipitationController::destroyAllViewportInstances () {
00369         ViewportInstanceMap::const_iterator it;
00370         ViewportInstanceMap::const_iterator begin = mViewportInstanceMap.begin();
00371         ViewportInstanceMap::const_iterator end = mViewportInstanceMap.end();
00372         for (it = begin; it != end; ++it) {
00373             assert(it->first == it->second->getViewport ());
00374             delete it->second;
00375         }
00376         mViewportInstanceMap.clear ();
00377     }
00378 }