[2221] | 1 | |
---|
| 2 | /////////////////////////////////////////////////////////////////////////// |
---|
| 3 | // |
---|
| 4 | // Realistic rain real-time simulation program |
---|
| 5 | // |
---|
| 6 | // Pierre Rousseau |
---|
| 7 | // |
---|
| 8 | /////////////////////////////////////////////////////////////////////////// |
---|
| 9 | // |
---|
| 10 | // Main camera, and external events (mouse/keyboard) handling |
---|
| 11 | // |
---|
| 12 | /////////////////////////////////////////////////////////////////////////// |
---|
| 13 | |
---|
| 14 | |
---|
| 15 | |
---|
| 16 | #include "RainCloseDropsParticles.h" |
---|
| 17 | #include "RainFrameListener.h" |
---|
| 18 | #include <OgreHardwarePixelBuffer.h> |
---|
| 19 | using namespace std; |
---|
| 20 | |
---|
| 21 | |
---|
| 22 | extern float startPos[3]; |
---|
| 23 | |
---|
| 24 | // don't go below the ground with this |
---|
| 25 | extern RaySceneQuery* raySceneQuery; |
---|
| 26 | |
---|
| 27 | |
---|
| 28 | RainFrameListener::RainFrameListener(RenderWindow* win, Camera* cam, SceneNode* ViewNode, SceneNode* CameraNode, CloseDropsParticles *syst) : ExampleFrameListener(win, cam) |
---|
| 29 | { |
---|
| 30 | mViewNode = ViewNode; |
---|
| 31 | mCameraNode = CameraNode; |
---|
| 32 | mRainSystem = syst; |
---|
| 33 | timer = 0.0; |
---|
| 34 | mWindow->setAutoUpdated(false); |
---|
| 35 | |
---|
| 36 | Overlay * mRainOverlay = OverlayManager::getSingleton().getByName("RainOverlay"); |
---|
| 37 | mRainOverlay->show(); |
---|
| 38 | |
---|
| 39 | showDebugOverlay(false); // useless as we defined our own overlay |
---|
| 40 | } |
---|
| 41 | |
---|
| 42 | |
---|
| 43 | |
---|
| 44 | void RainFrameListener::updateStats(void) |
---|
| 45 | { |
---|
| 46 | static String currFps = "FPS : "; |
---|
| 47 | // update stats when necessary |
---|
| 48 | try |
---|
| 49 | { |
---|
| 50 | OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("RainCurrFps"); |
---|
| 51 | |
---|
| 52 | const RenderTarget::FrameStats& stats = mWindow->getStatistics(); |
---|
| 53 | |
---|
| 54 | guiCurr->setCaption(currFps + StringConverter::toString(stats.lastFPS)); |
---|
| 55 | } |
---|
| 56 | catch(...) |
---|
| 57 | { |
---|
| 58 | // ignore |
---|
| 59 | } |
---|
| 60 | } |
---|
| 61 | |
---|
| 62 | |
---|
| 63 | void RainFrameListener::displayMessage(String text) |
---|
| 64 | { |
---|
| 65 | try |
---|
| 66 | { |
---|
| 67 | OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("RainCurrFps"); |
---|
| 68 | guiCurr->setCaption(text); |
---|
| 69 | } |
---|
| 70 | catch(...) |
---|
| 71 | { |
---|
| 72 | // ignore |
---|
| 73 | } |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | |
---|
| 77 | bool RainFrameListener::frameStarted(const FrameEvent& evt) |
---|
| 78 | { |
---|
| 79 | static bool usePrimaryPositionTexture = true; |
---|
| 80 | static bool capture = false; |
---|
| 81 | static bool stopDrop = false; |
---|
| 82 | static int numScreenshot=0; |
---|
| 83 | static bool firstFrame = true; |
---|
| 84 | static bool showOverlay = true; |
---|
| 85 | Real moveFactor; |
---|
| 86 | |
---|
| 87 | #ifdef SNOW |
---|
| 88 | |
---|
| 89 | static float fallSpeed = 0.1; |
---|
| 90 | static float windForce = 0.02; |
---|
| 91 | #else |
---|
| 92 | |
---|
| 93 | static float fallSpeed = 0.7; |
---|
| 94 | static float windForce = 0.0; |
---|
| 95 | #endif |
---|
| 96 | |
---|
| 97 | |
---|
| 98 | if (firstFrame) |
---|
| 99 | { |
---|
| 100 | mRainSystem->definePosTextureAndBackup(); |
---|
| 101 | firstFrame = false; |
---|
| 102 | |
---|
| 103 | // give initial values to the shader parameters |
---|
| 104 | Vector3 camPos = mViewNode->getWorldPosition(); |
---|
| 105 | Vector3 viewPos( (camPos.x - PARTICLES_MIN_X) / float(PARTICLES_MAX_X - PARTICLES_MIN_X), |
---|
| 106 | (camPos.y - PARTICLES_MIN_Y) / float(PARTICLES_MAX_Y - PARTICLES_MIN_Y), |
---|
| 107 | (camPos.z - PARTICLES_MIN_Z) / float(PARTICLES_MAX_Z - PARTICLES_MIN_Z) ); |
---|
| 108 | Vector3 viewDir(0.0, 0.0, 1.0); |
---|
| 109 | Vector3 fallVect(windForce, -fallSpeed, 0.0); |
---|
| 110 | Vector3 boxMin(VIS_PARTICLE_BOX_MIN_X, VIS_PARTICLE_BOX_MIN_Y, VIS_PARTICLE_BOX_MIN_Z); |
---|
| 111 | Vector3 boxMax(VIS_PARTICLE_BOX_MAX_X, VIS_PARTICLE_BOX_MAX_Y, VIS_PARTICLE_BOX_MAX_Z); |
---|
| 112 | Vector3 lastMove( 0.0, 0.0, 0.0 ); |
---|
| 113 | |
---|
| 114 | Vector3 randomMove((rand() % 100 ) / 1000.0 - 0.05, (rand() % 100 ) / 1000.0 - 0.05, (rand() % 100 ) / 1000.0 - 0.05); |
---|
| 115 | |
---|
| 116 | mRainSystem->updateShaderParameters(0.015, mRainSystem->mRainWidth, mRainSystem->mRainStreaksHeight, mRainSystem->getLightManagerPtr()->getLightCount(), viewPos, viewDir, fallVect, boxMin, boxMax, lastMove, randomMove, 1); |
---|
| 117 | |
---|
| 118 | // the control overlay is for debugging purposes : uncomment if you wish to see a dynamic texture, such as the particle's position texture. |
---|
| 119 | //mRainSystem->makeControlOverlay(); |
---|
| 120 | } |
---|
| 121 | else |
---|
| 122 | { |
---|
| 123 | // set the active position texture |
---|
| 124 | mRainSystem->showPositionBillboards(); |
---|
| 125 | mRainSystem->updatePositionTexture(usePrimaryPositionTexture); |
---|
| 126 | mRainSystem->hidePositionBillboards(); |
---|
| 127 | |
---|
| 128 | usePrimaryPositionTexture = !usePrimaryPositionTexture; |
---|
| 129 | //update random factor |
---|
| 130 | mRainSystem->updateRandomMove(Vector3((rand() % 100 ) / 1000.0 - 0.05, (rand() % 100 ) / 1000.0 - 0.05, (rand() % 100 ) / 1000.0 - 0.05)); |
---|
| 131 | } |
---|
| 132 | |
---|
| 133 | |
---|
| 134 | |
---|
| 135 | |
---|
| 136 | |
---|
| 137 | if (capture) |
---|
| 138 | { |
---|
| 139 | moveFactor = evt.timeSinceLastFrame * 10.0; |
---|
| 140 | |
---|
| 141 | // set framerate to 30 fps |
---|
| 142 | mRainSystem->updateTimeSinceLastFrame(1.0 / 30.0); |
---|
| 143 | } |
---|
| 144 | else |
---|
| 145 | { |
---|
| 146 | // tell the stat overlay to update |
---|
| 147 | updateStats(); |
---|
| 148 | |
---|
| 149 | // update time since last frame |
---|
| 150 | mRainSystem->updateTimeSinceLastFrame(evt.timeSinceLastFrame); |
---|
| 151 | |
---|
| 152 | moveFactor = evt.timeSinceLastFrame * 80.0; |
---|
| 153 | } |
---|
| 154 | |
---|
| 155 | timer -= evt.timeSinceLastFrame; |
---|
| 156 | |
---|
| 157 | |
---|
| 158 | |
---|
| 159 | mInputDevice->capture(); |
---|
| 160 | |
---|
| 161 | ///////////////////////////////////////////////// |
---|
| 162 | ///////////////////////////////////////////////// |
---|
| 163 | // translations |
---|
| 164 | ///////////////////////////////////////////////// |
---|
| 165 | ///////////////////////////////////////////////// |
---|
| 166 | |
---|
| 167 | // save the previous position |
---|
| 168 | Vector3 oldViewPos = mViewNode->getWorldPosition(); |
---|
| 169 | |
---|
| 170 | if (mInputDevice->isKeyDown(Ogre::KC_UP) || mInputDevice->isKeyDown(Ogre::KC_NUMPAD8)) |
---|
| 171 | { |
---|
| 172 | mViewNode->translate(0.0, 0.0, -moveFactor, Ogre::Node::TS_LOCAL); |
---|
| 173 | } |
---|
| 174 | |
---|
| 175 | if (mInputDevice->isKeyDown(Ogre::KC_DOWN) || mInputDevice->isKeyDown(Ogre::KC_NUMPAD5)) |
---|
| 176 | { |
---|
| 177 | mViewNode->translate(0.0, 0.0, moveFactor, Ogre::Node::TS_LOCAL); |
---|
| 178 | } |
---|
| 179 | |
---|
| 180 | // keep the feets on the ground |
---|
| 181 | static Ray updateRay; |
---|
| 182 | updateRay.setOrigin(mViewNode->getPosition()); |
---|
| 183 | updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y); |
---|
| 184 | raySceneQuery->setRay(updateRay); |
---|
| 185 | raySceneQuery->setQueryMask(0x80000000); |
---|
| 186 | RaySceneQueryResult& qryResult = raySceneQuery->execute(); |
---|
| 187 | RaySceneQueryResult::iterator i = qryResult.begin(); |
---|
| 188 | if (i != qryResult.end() && i->worldFragment) |
---|
| 189 | { |
---|
| 190 | SceneQuery::WorldFragment* wf = i->worldFragment; |
---|
| 191 | mViewNode->setPosition(mViewNode->getPosition().x, i->worldFragment->singleIntersection.y + HAUTEUR_OBSERVATEUR, mViewNode->getPosition().z); |
---|
| 192 | } |
---|
| 193 | |
---|
| 194 | |
---|
| 195 | // in case the user moved, update his position |
---|
| 196 | Vector3 camPos = mViewNode->getWorldPosition(); |
---|
| 197 | mRainSystem->updateViewPos(camPos); |
---|
| 198 | |
---|
| 199 | |
---|
| 200 | ///////////////////////////////////////////////// |
---|
| 201 | ///////////////////////////////////////////////// |
---|
| 202 | // rotations |
---|
| 203 | ///////////////////////////////////////////////// |
---|
| 204 | ///////////////////////////////////////////////// |
---|
| 205 | Real rotX = -mInputDevice->getMouseRelativeX(); |
---|
| 206 | Real rotY = -mInputDevice->getMouseRelativeY(); |
---|
| 207 | |
---|
| 208 | Vector3 oldViewDir = mViewNode->getOrientation().zAxis(); |
---|
| 209 | |
---|
| 210 | mViewNode->yaw(Ogre::Radian(rotX * evt.timeSinceLastFrame / (capture ? 100.0 : 1.0)), Ogre::Node::TS_WORLD); |
---|
| 211 | mCameraNode->pitch(-Ogre::Radian(rotY * evt.timeSinceLastFrame / (capture ? 100.0 : 1.0)), Ogre::Node::TS_LOCAL); |
---|
| 212 | |
---|
| 213 | // get the orientation for the update shader |
---|
| 214 | Vector3 newViewDir = mViewNode->getOrientation().zAxis(); |
---|
| 215 | |
---|
| 216 | Vector3 lastMove( (camPos.x - oldViewPos.x) / float(VIS_PARTICLE_BOX_MAX_X - VIS_PARTICLE_BOX_MIN_X) - (newViewDir.x - oldViewDir.x)/2.0, |
---|
| 217 | (camPos.y - oldViewPos.y) / float(VIS_PARTICLE_BOX_MAX_Y - VIS_PARTICLE_BOX_MIN_Y), |
---|
| 218 | (camPos.z - oldViewPos.z) / float(VIS_PARTICLE_BOX_MAX_Z - VIS_PARTICLE_BOX_MIN_Z) - (newViewDir.z - oldViewDir.z)/2.0 ); |
---|
| 219 | mRainSystem->updateLastMove(lastMove); |
---|
| 220 | |
---|
| 221 | mRainSystem->updateViewDir(newViewDir); |
---|
| 222 | |
---|
| 223 | |
---|
| 224 | ///////////////////////////////////////////////////////////////////////////////////// |
---|
| 225 | ///////////////////////////////////////////////////////////////////////////////////// |
---|
| 226 | // |
---|
| 227 | // react to user input (keyboard) |
---|
| 228 | // |
---|
| 229 | ///////////////////////////////////////////////////////////////////////////////////// |
---|
| 230 | ///////////////////////////////////////////////////////////////////////////////////// |
---|
| 231 | |
---|
| 232 | |
---|
| 233 | // pause the system |
---|
| 234 | if (mInputDevice->isKeyDown(KC_SPACE) && timer <= 0) |
---|
| 235 | { |
---|
| 236 | stopDrop = ! stopDrop; |
---|
| 237 | if (stopDrop) |
---|
| 238 | displayMessage("Pause"); |
---|
| 239 | else |
---|
| 240 | displayMessage(" "); |
---|
| 241 | |
---|
| 242 | timer = 0.5; |
---|
| 243 | |
---|
| 244 | // update fall vector |
---|
| 245 | mRainSystem->updateFallVector(Vector3(stopDrop?0.0:windForce, stopDrop?0.0:-fallSpeed, 0.0)); |
---|
| 246 | } |
---|
| 247 | |
---|
| 248 | |
---|
| 249 | |
---|
| 250 | // modifying particle size |
---|
| 251 | |
---|
| 252 | if (mInputDevice->isKeyDown(KC_ADD) && timer <= 0) |
---|
| 253 | { |
---|
| 254 | mRainSystem->mRainWidth += 0.05; |
---|
| 255 | displayMessage("Radius : " + StringConverter::toString(mRainSystem->mRainWidth * 5.0f)); |
---|
| 256 | std::cout << "Radius : " << mRainSystem->mRainWidth * 5.0f << std::endl; |
---|
| 257 | #ifndef SNOW |
---|
| 258 | |
---|
| 259 | if (mRainSystem->mRainWidth <= 0.901) |
---|
| 260 | { |
---|
| 261 | String nom_masque="masques/masque_" + StringConverter::toString(mRainSystem->mRainWidth * 5.0f) + "_.tga"; |
---|
| 262 | static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(RAIN_MATERIAL_NAME))->getTechnique (0)->getPass (0)->getTextureUnitState (2)->setTextureName(nom_masque); |
---|
| 263 | } |
---|
| 264 | #endif |
---|
| 265 | timer = 0.1; |
---|
| 266 | |
---|
| 267 | // update the size |
---|
| 268 | mRainSystem->updateRainBilboardSideLength(mRainSystem->mRainWidth); |
---|
| 269 | } |
---|
| 270 | |
---|
| 271 | if (mInputDevice->isKeyDown(KC_SUBTRACT) && timer <= 0) |
---|
| 272 | { |
---|
| 273 | if (mRainSystem->mRainWidth > 0.051) |
---|
| 274 | { |
---|
| 275 | mRainSystem->mRainWidth -= 0.05; |
---|
| 276 | displayMessage("Radius : " + StringConverter::toString(mRainSystem->mRainWidth * 5.0f)); |
---|
| 277 | std::cout << "Radius : " << mRainSystem->mRainWidth * 5.0f << std::endl; |
---|
| 278 | #ifndef SNOW |
---|
| 279 | |
---|
| 280 | if (mRainSystem->mRainWidth <= 0.9 && mRainSystem->mRainWidth >= 0.14) |
---|
| 281 | { |
---|
| 282 | String nom_masque="masques/masque_" + StringConverter::toString(mRainSystem->mRainWidth * 5.0f) + "_.tga"; |
---|
| 283 | static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(RAIN_MATERIAL_NAME))->getTechnique (0)->getPass (0)->getTextureUnitState (2)->setTextureName(nom_masque); |
---|
| 284 | } |
---|
| 285 | #endif |
---|
| 286 | |
---|
| 287 | } |
---|
| 288 | timer = 0.1; |
---|
| 289 | |
---|
| 290 | // update the size |
---|
| 291 | mRainSystem->updateRainBilboardSideLength(mRainSystem->mRainWidth); |
---|
| 292 | } |
---|
| 293 | |
---|
| 294 | |
---|
| 295 | |
---|
| 296 | // press 'S' to accelerate, and 'Q' to slow down |
---|
| 297 | if (mInputDevice->isKeyDown(KC_S)) |
---|
| 298 | { |
---|
| 299 | displayMessage("Accelerating"); |
---|
| 300 | fallSpeed += 0.002; |
---|
| 301 | std::cout << "fallSpeed : " << fallSpeed << std::endl; |
---|
| 302 | |
---|
| 303 | // update fall vector |
---|
| 304 | mRainSystem->updateFallVector(Vector3(stopDrop?0.0:windForce, stopDrop?0.0:-fallSpeed, 0.0)); |
---|
| 305 | } |
---|
| 306 | if (mInputDevice->isKeyDown(KC_Q)) |
---|
| 307 | { |
---|
| 308 | if (fallSpeed > 0.05) |
---|
| 309 | { |
---|
| 310 | displayMessage("Slowing"); |
---|
| 311 | fallSpeed -= 0.002; |
---|
| 312 | } |
---|
| 313 | std::cout << "fallSpeed : " << fallSpeed << std::endl; |
---|
| 314 | |
---|
| 315 | // update fall vector |
---|
| 316 | mRainSystem->updateFallVector(Vector3(stopDrop?0.0:windForce, stopDrop?0.0:-fallSpeed, 0.0)); |
---|
| 317 | } |
---|
| 318 | |
---|
| 319 | // wind handling ('W' key) |
---|
| 320 | if (mInputDevice->isKeyDown(KC_W)) |
---|
| 321 | { |
---|
| 322 | if (mInputDevice->isKeyDown(KC_LSHIFT) || mInputDevice->isKeyDown(KC_RSHIFT)) |
---|
| 323 | { |
---|
| 324 | displayMessage("Decreasing wind"); |
---|
| 325 | windForce -= 0.001; |
---|
| 326 | } |
---|
| 327 | else |
---|
| 328 | { |
---|
| 329 | displayMessage("Increasing wind"); |
---|
| 330 | windForce += 0.001; |
---|
| 331 | } |
---|
| 332 | std::cout << "wind : " << windForce << std::endl; |
---|
| 333 | |
---|
| 334 | // update fall vector |
---|
| 335 | mRainSystem->updateFallVector(Vector3(stopDrop?0.0:windForce, stopDrop?0.0:-fallSpeed, 0.0)); |
---|
| 336 | } |
---|
| 337 | |
---|
| 338 | |
---|
| 339 | // erase text |
---|
| 340 | if (mInputDevice->isKeyDown(KC_E)) |
---|
| 341 | { |
---|
| 342 | displayMessage(" "); |
---|
| 343 | } |
---|
| 344 | |
---|
| 345 | // show / hide the calimero overlay |
---|
| 346 | if (mInputDevice->isKeyDown(KC_O) && timer <= 0) |
---|
| 347 | { |
---|
| 348 | showOverlay = ! showOverlay; |
---|
| 349 | if (showOverlay) |
---|
| 350 | OverlayManager::getSingleton().getByName("RainOverlay")->show(); |
---|
| 351 | else |
---|
| 352 | OverlayManager::getSingleton().getByName("RainOverlay")->hide(); |
---|
| 353 | |
---|
| 354 | timer = 0.5; |
---|
| 355 | } |
---|
| 356 | |
---|
| 357 | |
---|
| 358 | // we can capture a screenshot |
---|
| 359 | |
---|
| 360 | mWindow->update(); |
---|
| 361 | |
---|
| 362 | if (mInputDevice->isKeyDown(KC_SYSRQ) && timer <= 0) |
---|
| 363 | { |
---|
| 364 | String tmp; |
---|
| 365 | |
---|
| 366 | String padding = (numScreenshot<10) ? "000" : ( (numScreenshot<100) ? "00" : ((numScreenshot<1000) ? "0" : "" ) ) ; |
---|
| 367 | tmp = "screenshot_" + padding; |
---|
| 368 | tmp += StringConverter::toString(numScreenshot++) + ".jpg"; |
---|
| 369 | mWindow->writeContentsToFile(tmp); |
---|
| 370 | timer = 0.5; |
---|
| 371 | } |
---|
| 372 | |
---|
| 373 | // on enregistre |
---|
| 374 | if (mInputDevice->isKeyDown(Ogre::KC_C) && timer <= 0) |
---|
| 375 | { |
---|
| 376 | displayMessage(" "); |
---|
| 377 | capture = !capture; |
---|
| 378 | timer = 0.5; |
---|
| 379 | } |
---|
| 380 | if (capture) |
---|
| 381 | { |
---|
| 382 | String tmp; |
---|
| 383 | |
---|
| 384 | String padding = (numScreenshot<10) ? "000" : ( (numScreenshot<100) ? "00" : ((numScreenshot<1000) ? "0" : "" ) ) ; |
---|
| 385 | tmp = "Capture_" + padding; |
---|
| 386 | tmp += StringConverter::toString(numScreenshot++) + ".jpg"; |
---|
| 387 | |
---|
| 388 | mWindow->writeContentsToFile(tmp); |
---|
| 389 | } |
---|
| 390 | |
---|
| 391 | // end of program |
---|
| 392 | |
---|
| 393 | if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE)) |
---|
| 394 | return false; |
---|
| 395 | |
---|
| 396 | return true; |
---|
| 397 | } |
---|
| 398 | |
---|
| 399 | |
---|
| 400 | |
---|
| 401 | |
---|
| 402 | bool RainFrameListener::frameEnded(const FrameEvent& evt) |
---|
| 403 | { |
---|
| 404 | return ExampleFrameListener::frameEnded(evt); |
---|
| 405 | } |
---|
| 406 | |
---|