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