source: OGRE/trunk/ogrenew/Samples/Water/src/Water.cpp @ 657

Revision 657, 21.2 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10You may use this sample code for anything you like, it is not covered by the
11LGPL like the rest of the engine.
12-----------------------------------------------------------------------------
13*/
14/* Static water simulation by eru
15 * Started 29.05.2003, 20:54:37
16 */
17#include "ExampleApplication.h"
18#include "OgreBillboardParticleRenderer.h"
19#include "WaterMesh.h"
20
21#include <iostream>
22
23AnimationState* mAnimState;
24
25// Mesh stuff
26#define MESH_NAME "WaterMesh"
27#define ENTITY_NAME "WaterEntity"
28#define MATERIAL_PREFIX "Examples/Water"
29#define MATERIAL_NAME "Examples/Water0"
30#define COMPLEXITY 64           // watch out - number of polys is 2*ACCURACY*ACCURACY !
31#define PLANE_SIZE 3000.0f
32#define CIRCLES_MATERIAL "Examples/Water/Circles"
33
34/* Some global variables */
35SceneNode *headNode ;
36Overlay* waterOverlay ;
37ParticleSystem *particleSystem ;
38ParticleEmitter *particleEmitter ;
39SceneManager *sceneMgr ;
40
41void prepareCircleMaterial()
42{
43        char *bmap = new char[256 * 256 * 4] ;
44        memset(bmap, 127, 256 * 256 * 4);
45        for(int b=0;b<16;b++) {
46                int x0 = b % 4 ;
47                int y0 = b >> 2 ;
48                Real radius = 4.0f + 1.4 * (float) b ;
49                for(int x=0;x<64;x++) {
50                        for(int y=0;y<64;y++) {
51                                Real dist = Math::Sqrt((x-32)*(x-32)+(y-32)*(y-32)); // 0..ca.45
52                                dist = fabs(dist -radius -2) / 2.0f ;
53                                dist = dist * 255.0f;
54                                if (dist>255)
55                                        dist=255 ;
56                                int colour = 255-(int)dist ;
57                                colour = (int)( ((Real)(15-b))/15.0f * (Real) colour );
58                               
59                                bmap[4*(256*(y+64*y0)+x+64*x0)+0]=colour ;
60                                bmap[4*(256*(y+64*y0)+x+64*x0)+1]=colour ;
61                                bmap[4*(256*(y+64*y0)+x+64*x0)+2]=colour ;
62                                bmap[4*(256*(y+64*y0)+x+64*x0)+3]=colour ;
63                        }
64                }
65        }
66       
67        DataStreamPtr imgstream(new MemoryDataStream(bmap, 256 * 256 * 4));
68        //~ Image img;
69        //~ img.loadRawData( imgstream, 256, 256, PF_A8R8G8B8 );
70        //~ TextureManager::getSingleton().loadImage( CIRCLES_MATERIAL , img );
71        TextureManager::getSingleton().loadRawData(CIRCLES_MATERIAL,
72        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
73                imgstream, 256, 256, PF_A8R8G8B8);
74        MaterialPtr material =
75                MaterialManager::getSingleton().create( CIRCLES_MATERIAL,
76        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
77        TextureUnitState *texLayer = material->getTechnique(0)->getPass(0)->createTextureUnitState( CIRCLES_MATERIAL );
78        texLayer->setTextureAddressingMode( TextureUnitState::TAM_CLAMP );     
79        material->setSceneBlending( SBT_ADD );
80        material->setDepthWriteEnabled( false ) ;
81    material->load();
82    // finished with bmap so release the memory
83    delete [] bmap;
84}
85
86
87/* =========================================================================*/
88/*               WaterCircle class                                          */
89/* =========================================================================*/
90#define CIRCLE_SIZE 500.0
91#define CIRCLE_TIME 0.5f
92class WaterCircle
93{
94private:
95        String name ;
96        SceneNode *node ;
97        MeshPtr mesh ;
98        SubMesh *subMesh ;
99        Entity *entity ;
100        Real tm ;
101        static bool first ;
102        // some buffers shared by all circles
103        static HardwareVertexBufferSharedPtr posnormVertexBuffer ;
104        static HardwareIndexBufferSharedPtr indexBuffer ; // indices for 2 faces
105        static HardwareVertexBufferSharedPtr *texcoordsVertexBuffers ;
106       
107        float *texBufData;
108        void _prepareMesh()
109        {
110                int i,lvl ;
111               
112                mesh = MeshManager::getSingleton().createManual(name,
113            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) ;
114                subMesh = mesh->createSubMesh();
115                subMesh->useSharedVertices=false;
116
117                int numFaces = 2 ;
118                int numVertices = 4 ;
119
120                if (first) { // first Circle, create some static common data
121                        first = false ;
122                       
123                        // static buffer for position and normals
124                        posnormVertexBuffer =
125                                HardwareBufferManager::getSingleton().createVertexBuffer(
126                                        6*sizeof(float), // size of one vertex data
127                                        4, // number of vertices
128                                        HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage
129                                        false); // no shadow buffer
130                        float *posnormBufData = (float*) posnormVertexBuffer->
131                                lock(HardwareBuffer::HBL_DISCARD);
132                        for(i=0;i<numVertices;i++) {
133                                posnormBufData[6*i+0]=((Real)(i%2)-0.5f)*CIRCLE_SIZE; // pos X
134                                posnormBufData[6*i+1]=0; // pos Y
135                                posnormBufData[6*i+2]=((Real)(i/2)-0.5f)*CIRCLE_SIZE; // pos Z
136                                posnormBufData[6*i+3]=0 ; // normal X
137                                posnormBufData[6*i+4]=1 ; // normal Y
138                                posnormBufData[6*i+5]=0 ; // normal Z
139                        }
140                        posnormVertexBuffer->unlock();
141
142                        // static buffers for 16 sets of texture coordinates
143                        texcoordsVertexBuffers = new HardwareVertexBufferSharedPtr[16];
144                        for(lvl=0;lvl<16;lvl++) {
145                                texcoordsVertexBuffers[lvl] =
146                                        HardwareBufferManager::getSingleton().createVertexBuffer(
147                                                2*sizeof(float), // size of one vertex data
148                                                numVertices, // number of vertices
149                                                HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage
150                                                false); // no shadow buffer
151                                float *texcoordsBufData = (float*) texcoordsVertexBuffers[lvl]->
152                                        lock(HardwareBuffer::HBL_DISCARD);
153                                float x0 = (Real)(lvl % 4) * 0.25 ;
154                                float y0 = (Real)(lvl / 4) * 0.25 ;
155                                y0 = 0.75-y0 ; // upside down
156                                for(i=0;i<4;i++) {
157                                        texcoordsBufData[i*2 + 0]=
158                                                x0 + 0.25 * (Real)(i%2) ;
159                                        texcoordsBufData[i*2 + 1]=
160                                                y0 + 0.25 * (Real)(i/2) ;
161                                }
162                                texcoordsVertexBuffers[lvl]->unlock();
163                        }
164
165                        // Index buffer for 2 faces
166                        unsigned short faces[6] = {2,1,0,  2,3,1};
167                        indexBuffer =
168                                HardwareBufferManager::getSingleton().createIndexBuffer(
169                                        HardwareIndexBuffer::IT_16BIT,
170                                        6,
171                                        HardwareBuffer::HBU_STATIC_WRITE_ONLY);
172                        indexBuffer->writeData(0,
173                                indexBuffer->getSizeInBytes(),
174                                faces,
175                                true); // true?
176                }
177               
178                // Initialize vertex data
179                subMesh->vertexData = new VertexData();
180                subMesh->vertexData->vertexStart = 0;
181                subMesh->vertexData->vertexCount = 4;
182                // first, set vertex buffer bindings
183                VertexBufferBinding *vbind = subMesh->vertexData->vertexBufferBinding ;
184                vbind->setBinding(0, posnormVertexBuffer);
185                vbind->setBinding(1, texcoordsVertexBuffers[0]);
186                // now, set vertex buffer declaration
187                VertexDeclaration *vdecl = subMesh->vertexData->vertexDeclaration ;
188                vdecl->addElement(0, 0, VET_FLOAT3, VES_POSITION);
189                vdecl->addElement(0, 3*sizeof(float), VET_FLOAT3, VES_NORMAL);
190                vdecl->addElement(1, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
191               
192                // Initialize index data
193                subMesh->indexData->indexBuffer = indexBuffer;
194                subMesh->indexData->indexStart = 0;
195                subMesh->indexData->indexCount = 6;
196               
197                // set mesh bounds
198                AxisAlignedBox circleBounds(-CIRCLE_SIZE/2.0f, 0, -CIRCLE_SIZE/2.0f,
199                        CIRCLE_SIZE/2.0f, 0, CIRCLE_SIZE/2.0f);
200                mesh->_setBounds(circleBounds);
201        mesh->load();
202        mesh->touch();
203        }
204public:
205        int lvl ;
206        void setTextureLevel()
207        {
208                subMesh->vertexData->vertexBufferBinding->setBinding(1, texcoordsVertexBuffers[lvl]);
209        }
210        WaterCircle(const String& name, Real x, Real y)
211        {
212                this->name = name ;
213                _prepareMesh();
214                node = static_cast<SceneNode*> (sceneMgr->getRootSceneNode()->createChild(name));
215                node->translate(x*(PLANE_SIZE/COMPLEXITY), 10, y*(PLANE_SIZE/COMPLEXITY));
216                entity = sceneMgr->createEntity(name, name);
217                entity->setMaterialName(CIRCLES_MATERIAL);
218                node->attachObject(entity);
219                tm = 0 ;
220                lvl = 0 ;
221                setTextureLevel();
222        }
223        ~WaterCircle()
224        {
225                MeshManager::getSingleton().remove(mesh->getHandle());
226                sceneMgr->removeEntity(entity->getName());
227                static_cast<SceneNode*> (sceneMgr->getRootSceneNode())->removeChild(node->getName());
228        }
229        void animate(Real timeSinceLastFrame)
230        {
231                int lastlvl = lvl ;
232                tm += timeSinceLastFrame ;
233                lvl = (int) ( (Real)(tm)/CIRCLE_TIME * 16 );
234                if (lvl<16 && lvl!=lastlvl) {
235                        setTextureLevel();
236                }
237        }
238        static void clearStaticBuffers()
239        {
240                posnormVertexBuffer = HardwareVertexBufferSharedPtr() ;
241                indexBuffer = HardwareIndexBufferSharedPtr() ;
242                for(int i=0;i<16;i++) {
243                        texcoordsVertexBuffers[i] = HardwareVertexBufferSharedPtr() ;
244                }
245                delete [] texcoordsVertexBuffers;
246        }
247} ;
248bool WaterCircle::first = true ;
249HardwareVertexBufferSharedPtr WaterCircle::posnormVertexBuffer =
250        HardwareVertexBufferSharedPtr() ;
251HardwareIndexBufferSharedPtr WaterCircle::indexBuffer =
252        HardwareIndexBufferSharedPtr() ;
253HardwareVertexBufferSharedPtr* WaterCircle::texcoordsVertexBuffers = 0 ;
254
255/* =========================================================================*/
256/*               WaterListener class                                          */
257/* =========================================================================*/
258// Event handler
259class WaterListener: public ExampleFrameListener
260{
261protected:
262        WaterMesh *waterMesh ;
263        Entity *waterEntity ;
264        int materialNumber ;
265        bool skyBoxOn ;
266        Real timeoutDelay ;
267
268#define RAIN_HEIGHT_RANDOM 5
269#define RAIN_HEIGHT_CONSTANT 5
270       
271
272        typedef std::vector<WaterCircle*> WaterCircles ;
273        WaterCircles circles ;
274       
275        void processCircles(Real timeSinceLastFrame)
276        {
277                for(unsigned int i=0;i<circles.size();i++) {
278                        circles[i]->animate(timeSinceLastFrame);
279                }
280                bool found ;
281                do {
282                        found = false ;
283                        for(WaterCircles::iterator it = circles.begin() ;
284                                        it != circles.end();
285                                        ++it) {
286                                if ((*it)->lvl>=16) {
287                                        delete (*it);
288                                        circles.erase(it);
289                                        found = true ;
290                                        break ;
291                                }
292                        }
293                } while (found) ;
294        }
295
296        void processParticles()
297        {
298                static int pindex = 0 ;
299                ParticleIterator pit = particleSystem->_getIterator() ;
300                while(!pit.end()) {
301                        Particle *particle = pit.getNext();
302                        Vector3 ppos = particle->position;
303                        if (ppos.y<=0 && particle->timeToLive>0) { // hits the water!
304                                // delete particle
305                                particle->timeToLive = 0.0f;
306                                // push the water
307                                float x = ppos.x / PLANE_SIZE * COMPLEXITY ;
308                                float y = ppos.z / PLANE_SIZE * COMPLEXITY ;
309                                float h = rand() % RAIN_HEIGHT_RANDOM + RAIN_HEIGHT_CONSTANT ;
310                                if (x<1) x=1 ;
311                                if (x>COMPLEXITY-1) x=COMPLEXITY-1;
312                                if (y<1) y=1 ;
313                                if (y>COMPLEXITY-1) y=COMPLEXITY-1;
314                                waterMesh->push(x,y,-h) ;
315                                WaterCircle *circle = new WaterCircle(
316                                        "Circle#"+StringConverter::toString(pindex++),
317                                        x, y);
318                                circles.push_back(circle);
319                        }
320                }
321        }
322       
323        /** Head animation */
324        Real headDepth ;
325        void animateHead(Real timeSinceLastFrame)
326        {
327                // sine track? :)
328                static double sines[4] = {0,100,200,300};
329                static const double adds[4] = {0.3,-1.6,1.1,0.5};
330                static Vector3 oldPos = Vector3::UNIT_Z;
331                for(int i=0;i<4;i++) {
332                        sines[i]+=adds[i]*timeSinceLastFrame;
333                }
334                Real tx = ((sin(sines[0]) + sin(sines[1])) / 4 + 0.5 ) * (float)(COMPLEXITY-2) + 1 ;
335                Real ty = ((sin(sines[2]) + sin(sines[3])) / 4 + 0.5 ) * (float)(COMPLEXITY-2) + 1 ;
336                waterMesh->push(tx,ty, -headDepth);
337                Real step = PLANE_SIZE / COMPLEXITY ;
338                headNode->resetToInitialState();
339                headNode->scale(3,3,3);
340                Vector3 newPos = Vector3(step*tx, headDepth, step*ty);
341                Vector3 diffPos = newPos - oldPos ;
342                Quaternion headRotation = Vector3::UNIT_Z.getRotationTo(diffPos);
343                oldPos = newPos ;
344                headNode->translate(newPos);
345                headNode->rotate(headRotation);
346        }
347       
348        // GUI updaters
349        void updateInfoParamC()
350        {
351                OverlayManager::getSingleton().getOverlayElement("Example/Water/Param_C") \
352                        ->setCaption("[1/2]Ripple speed: "+StringConverter::toString(waterMesh->PARAM_C));             
353        }
354        void updateInfoParamD()
355        {
356                OverlayManager::getSingleton().getOverlayElement("Example/Water/Param_D") \
357                        ->setCaption("[3/4]Distance: "+StringConverter::toString(waterMesh->PARAM_D));         
358        }
359        void updateInfoParamU()
360        {
361                OverlayManager::getSingleton().getOverlayElement("Example/Water/Param_U") \
362                        ->setCaption("[5/6]Viscosity: "+StringConverter::toString(waterMesh->PARAM_U));         
363        }
364        void updateInfoParamT()
365        {
366                OverlayManager::getSingleton().getOverlayElement("Example/Water/Param_T") \
367                        ->setCaption("[7/8]Frame time: "+StringConverter::toString(waterMesh->PARAM_T));               
368        }
369        void updateInfoNormals()
370        {
371                OverlayManager::getSingleton().getOverlayElement("Example/Water/Normals") \
372                        ->setCaption(String("[N]Normals: ")+((waterMesh->useFakeNormals)?"fake":"real"));
373        }
374        void switchNormals()
375        {
376                waterMesh->useFakeNormals = !waterMesh->useFakeNormals ;
377                updateInfoNormals() ;
378        }
379        void updateInfoHeadDepth()
380        {
381                OverlayManager::getSingleton().getOverlayElement("Example/Water/Depth") \
382                        ->setCaption(String("[U/J]Head depth: ")+StringConverter::toString(headDepth));
383        }
384        void updateInfoSkyBox()
385        {
386                OverlayManager::getSingleton().getOverlayElement("Example/Water/SkyBox")
387                        ->setCaption(String("[B]SkyBox: ")+String((skyBoxOn)?"On":"Off") );
388        }
389        void updateMaterial()
390        {
391                String materialName = MATERIAL_PREFIX+StringConverter::toString(materialNumber);
392                MaterialPtr material = MaterialManager::getSingleton().getByName(materialName);
393                if (material.isNull())
394        {
395                        if(materialNumber)
396            {
397                                materialNumber = 0 ;
398                                updateMaterial();
399                                return ;
400                        }
401            else
402            {
403                                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
404                                        "Material "+materialName+"doesn't exist!",
405                                        "WaterListener::updateMaterial");
406                        }
407                }
408                waterEntity->setMaterialName(materialName);
409                OverlayManager::getSingleton().getOverlayElement("Example/Water/Material") \
410                        ->setCaption(String("[M]Material: ")+materialName);
411        }
412
413        void switchMaterial()
414        {
415                materialNumber++;
416                updateMaterial();
417        }
418        void switchSkyBox()
419        {
420                skyBoxOn = !skyBoxOn;
421                sceneMgr->setSkyBox(skyBoxOn, "Examples/SceneSkyBox2");
422                updateInfoSkyBox();
423        }
424
425public:
426    WaterListener(RenderWindow* win, Camera* cam,
427                WaterMesh *waterMesh, Entity *waterEntity)
428        : ExampleFrameListener(win, cam)
429    {
430                this->waterMesh = waterMesh ;
431                this->waterEntity = waterEntity ;
432                materialNumber = 8;
433                timeoutDelay = 0.0f;
434                headDepth = 2.0f;
435                skyBoxOn = false ;
436               
437                updateMaterial();
438                updateInfoParamC();
439                updateInfoParamD();
440                updateInfoParamU();
441                updateInfoParamT();
442                updateInfoNormals();
443                updateInfoHeadDepth();
444                updateInfoSkyBox();
445    }
446
447        virtual ~WaterListener ()
448        {
449                // If when you finish the application is still raining there
450                // are water circles that are still being processed
451                unsigned int activeCircles = this->circles.size ();
452               
453                // Kill the active water circles
454                for (unsigned int i = 0; i < activeCircles; i++)
455                        delete (this->circles[i]);
456        }
457 
458    bool frameStarted(const FrameEvent& evt)
459    {
460                bool retval = ExampleFrameListener::frameStarted(evt);
461        mAnimState->addTime(evt.timeSinceLastFrame);
462               
463                // process keyboard events
464                mInputDevice->capture();
465                Real changeSpeed = evt.timeSinceLastFrame ;
466               
467                // adjust keyboard speed with SHIFT (increase) and CONTROL (decrease)
468                if (mInputDevice->isKeyDown(KC_LSHIFT) || mInputDevice->isKeyDown(KC_RSHIFT)) {
469                        changeSpeed *= 10.0f ;
470                }
471                if (mInputDevice->isKeyDown(KC_LCONTROL)) {
472                        changeSpeed /= 10.0f ;
473                }
474               
475                // rain
476                processCircles(evt.timeSinceLastFrame);
477                if (mInputDevice->isKeyDown(KC_SPACE)) {
478                        particleEmitter->setEmissionRate(20.0f);
479                } else {
480                        particleEmitter->setEmissionRate(0.0f);
481                }
482                processParticles();
483
484                // adjust values (some macros for faster change         
485#define ADJUST_RANGE(_value,_keyPlus,_keyMinus,_minVal,_maxVal,_change,_macro) {\
486        if (mInputDevice->isKeyDown(_keyPlus)) \
487                { _value+=_change ; if (_value>=_maxVal) _value = _maxVal ; _macro ; } ; \
488        if (mInputDevice->isKeyDown(_keyMinus)) \
489                { _value-=_change; if (_value<=_minVal) _value = _minVal ; _macro ; } ; \
490}
491
492                ADJUST_RANGE(headDepth, KC_U, KC_J, 0, 10, 0.5*changeSpeed, updateInfoHeadDepth()) ;
493
494                ADJUST_RANGE(waterMesh->PARAM_C, KC_2, KC_1, 0, 10, 0.1f*changeSpeed, updateInfoParamC()) ;
495
496                ADJUST_RANGE(waterMesh->PARAM_D, KC_4, KC_3, 0.1, 10, 0.1f*changeSpeed, updateInfoParamD()) ;
497
498                ADJUST_RANGE(waterMesh->PARAM_U, KC_6, KC_5, -2, 10, 0.1f*changeSpeed, updateInfoParamU()) ;
499
500                ADJUST_RANGE(waterMesh->PARAM_T, KC_8, KC_7, 0, 10, 0.1f*changeSpeed, updateInfoParamT()) ;
501
502                timeoutDelay-=evt.timeSinceLastFrame ;
503                if (timeoutDelay<=0)
504                        timeoutDelay = 0;
505
506#define SWITCH_VALUE(_key,_timeDelay, _macro) { \
507                if (mInputDevice->isKeyDown(_key) && timeoutDelay==0) { \
508                        timeoutDelay = _timeDelay ; _macro ;} }
509       
510                SWITCH_VALUE(KC_N, 0.5f, switchNormals());
511                       
512                SWITCH_VALUE(KC_M, 0.5f, switchMaterial());
513
514                SWITCH_VALUE(KC_B, 0.5f, switchSkyBox());
515                       
516                animateHead(evt.timeSinceLastFrame);
517                       
518                waterMesh->updateMesh(evt.timeSinceLastFrame);
519                       
520                // check if we are exiting, if so, clear static HardwareBuffers to avoid
521                // segfault
522                if (!retval)
523                        WaterCircle::clearStaticBuffers();
524
525        // return result from default
526                return retval ;
527    }
528};
529
530class WaterApplication : public ExampleApplication
531{
532public:
533    WaterApplication()
534        : waterMesh(0)
535    {
536   
537    }
538
539    ~WaterApplication() { 
540        delete waterMesh;
541    }
542
543protected:
544        WaterMesh *waterMesh ;
545        Entity *waterEntity ;
546
547// Just override the mandatory create scene method
548    void createScene(void)
549    {
550                sceneMgr = mSceneMgr ;
551        // Set ambient light
552        mSceneMgr->setAmbientLight(ColourValue(0.75, 0.75, 0.75));
553
554        // Create a light
555        Light* l = mSceneMgr->createLight("MainLight");
556        // Accept default settings: point light, white diffuse, just set position
557        // NB I could attach the light to a SceneNode if I wanted it to move automatically with
558        //  other objects, but I don't
559        l->setPosition(200,300,100);
560
561                // Create water mesh and entity
562                waterMesh = new WaterMesh(MESH_NAME, PLANE_SIZE, COMPLEXITY);
563                waterEntity = mSceneMgr->createEntity(ENTITY_NAME,
564                        MESH_NAME);
565                //~ waterEntity->setMaterialName(MATERIAL_NAME);
566                SceneNode *waterNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
567                waterNode->attachObject(waterEntity);
568
569        // Add a head, give it it's own node
570        headNode = waterNode->createChildSceneNode();
571        Entity *ent = mSceneMgr->createEntity("head", "ogrehead.mesh");
572        headNode->attachObject(ent);
573
574                // Make sure the camera track this node
575        //~ mCamera->setAutoTracking(true, headNode);
576
577                // Create the camera node, set its position & attach camera
578        SceneNode* camNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
579                camNode->translate(0, 500, PLANE_SIZE);
580                camNode->yaw(Degree(-45));
581        camNode->attachObject(mCamera);
582               
583                // Create light node
584        SceneNode* lightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
585                lightNode->attachObject(l);
586
587        // set up spline animation of light node
588        Animation* anim = mSceneMgr->createAnimation("WaterLight", 20);
589                AnimationTrack *track ;
590        KeyFrame *key ;
591                // create a random spline for light
592                track = anim->createTrack(0, lightNode);
593                key = track->createKeyFrame(0);
594                for(int ff=1;ff<=19;ff++) {
595                        key = track->createKeyFrame(ff);
596                        Vector3 lpos (
597                                rand()%(int)PLANE_SIZE , //- PLANE_SIZE/2,
598                                rand()%300+100,
599                                rand()%(int)PLANE_SIZE //- PLANE_SIZE/2
600                                );
601                        key->setTranslate(lpos);
602                }
603                key = track->createKeyFrame(20);
604               
605        // Create a new animation state to track this
606        mAnimState = mSceneMgr->createAnimationState("WaterLight");
607        mAnimState->setEnabled(true);
608
609        // Put in a bit of fog for the hell of it
610        //mSceneMgr->setFog(FOG_EXP, ColourValue::White, 0.0002);
611
612                // show overlay
613                waterOverlay = OverlayManager::getSingleton().getByName("Example/WaterOverlay");   
614                waterOverlay->show();
615               
616        // Let there be rain
617        particleSystem = ParticleSystemManager::getSingleton().createSystem("rain",
618            "Examples/Water/Rain");
619                particleEmitter = particleSystem->getEmitter(0);
620        SceneNode* rNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
621        rNode->translate(PLANE_SIZE/2.0f, 3000, PLANE_SIZE/2.0f);
622        rNode->attachObject(particleSystem);
623        // Fast-forward the rain so it looks more natural
624        particleSystem->fastForward(20);
625                // It can't be set in .particle file, and we need it ;)
626                static_cast<BillboardParticleRenderer*>(particleSystem->getRenderer())->setBillboardOrigin(BBO_BOTTOM_CENTER);
627               
628                prepareCircleMaterial();
629        }
630
631    // Create new frame listener
632    void createFrameListener(void)
633    {
634        mFrameListener= new WaterListener(mWindow, mCamera, waterMesh, waterEntity);
635        mRoot->addFrameListener(mFrameListener);
636    }
637
638};
639
640
641
642#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
643#define WIN32_LEAN_AND_MEAN
644#include "windows.h"
645#endif
646
647#ifdef __cplusplus
648extern "C" {
649#endif
650
651#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
652INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
653#else
654int main(int argc, char **argv)
655#endif
656{
657    // Create application object
658    WaterApplication app;
659       
660        srand(time(0));
661
662    try {
663        app.go();
664    } catch( Exception& e ) {
665#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
666        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
667#else
668        std::cerr << "An exception has occured: " << e.getFullDescription();
669#endif
670    }
671
672    return 0;
673}
674
675#ifdef __cplusplus
676}
677#endif
Note: See TracBrowser for help on using the repository browser.