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 }