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

Revision 657, 13.5 KB checked in by mattausch, 18 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
15/**
16    \file
17        Grass.cpp
18    \brief
19        Specialisation of OGRE's framework application to show the
20        use of the StaticGeometry class to create 'baked' instances of
21                many meshes, to create effects like grass efficiently.
22**/
23
24#include "ExampleApplication.h"
25
26#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
27#define WIN32_LEAN_AND_MEAN
28#include "windows.h"
29#endif
30
31
32#define KEY_PRESSED(_key,_timeDelay, _macro) \
33{ \
34    if (mInputDevice->isKeyDown(_key) && timeDelay <= 0) \
35    { \
36                timeDelay = _timeDelay; \
37        _macro ; \
38    } \
39}
40
41#define GRASS_HEIGHT 300
42#define GRASS_WIDTH 250
43#define GRASS_MESH_NAME "grassblades"
44#define GRASS_MATERIAL "Examples/GrassBlades"
45#define OFFSET_PARAM 999
46
47Light* mLight;
48SceneNode* mLightNode = 0;
49AnimationState* mAnimState = 0;
50ColourValue mMinLightColour(0.5, 0.1, 0.0);
51ColourValue mMaxLightColour(1.0, 0.6, 0.0);
52Real mMinFlareSize = 40;
53Real mMaxFlareSize = 80;
54StaticGeometry* mStaticGeom;
55
56
57/** This class 'wibbles' the light and billboard */
58class LightWibbler : public ControllerValue<Real>
59{
60protected:
61        Light* mLight;
62        Billboard* mBillboard;
63        ColourValue mColourRange;
64        ColourValue mHalfColour;
65        Real mMinSize;
66        Real mSizeRange;
67        Real intensity;
68public:
69        LightWibbler(Light* light, Billboard* billboard, const ColourValue& minColour,
70                const ColourValue& maxColour, Real minSize, Real maxSize)
71        {
72                mLight = light;
73                mBillboard = billboard;
74                mColourRange.r = (maxColour.r - minColour.r) * 0.5;
75                mColourRange.g = (maxColour.g - minColour.g) * 0.5;
76                mColourRange.b = (maxColour.b - minColour.b) * 0.5;
77                mHalfColour = minColour + mColourRange;
78                mMinSize = minSize;
79                mSizeRange = maxSize - minSize;
80        }
81
82        virtual Real  getValue (void) const
83        {
84                return intensity;
85        }
86
87        virtual void  setValue (Real value)
88        {
89                intensity = value;
90
91                ColourValue newColour;
92
93                // Attenuate the brightness of the light
94                newColour.r = mHalfColour.r + (mColourRange.r * intensity);
95                newColour.g = mHalfColour.g + (mColourRange.g * intensity);
96                newColour.b = mHalfColour.b + (mColourRange.b * intensity);
97
98                mLight->setDiffuseColour(newColour);
99                mBillboard->setColour(newColour);
100                // set billboard size
101                Real newSize = mMinSize + (intensity * mSizeRange);
102                mBillboard->setDimensions(newSize, newSize);
103
104        }
105};
106
107class GrassListener : public ExampleFrameListener
108{
109protected:
110        SceneManager* mSceneManager;
111        bool mShowBBs;
112public:
113        GrassListener(RenderWindow* win, Camera* cam, SceneManager* sceneManager)
114                : ExampleFrameListener(win, cam),
115                mSceneManager(sceneManager), mShowBBs(false)
116        {
117        }
118
119
120        void waveGrass(Real timeElapsed)
121        {
122                static Real xinc = Math::PI * 0.4;
123                static Real zinc = Math::PI * 0.55;
124                static Real xpos = Math::RangeRandom(-Math::PI, Math::PI);
125                static Real zpos = Math::RangeRandom(-Math::PI, Math::PI);
126
127                xpos += xinc * timeElapsed;
128                zpos += zinc * timeElapsed;
129
130                // Update vertex program parameters by binding a value to each renderable
131                static Vector4 offset(0,0,0,0);
132
133                StaticGeometry::RegionIterator rit =  mStaticGeom->getRegionIterator();
134                while (rit.hasMoreElements())
135                {
136                        StaticGeometry::Region* reg = rit.getNext();
137
138                        // a little randomness
139                        xpos += reg->getCentre().x * 0.001;
140                        zpos += reg->getCentre().z * 0.001;
141                        offset.x = Math::Sin(xpos) * 0.05;
142                        offset.z = Math::Sin(zpos) * 0.05;
143
144                        StaticGeometry::Region::LODIterator lodit = reg->getLODIterator();
145                        while (lodit.hasMoreElements())
146                        {
147                                StaticGeometry::LODBucket* lod = lodit.getNext();
148                                StaticGeometry::LODBucket::MaterialIterator matit =
149                                        lod->getMaterialIterator();
150                                while (matit.hasMoreElements())
151                                {
152                                        StaticGeometry::MaterialBucket* mat = matit.getNext();
153                                        StaticGeometry::MaterialBucket::GeometryIterator geomit =
154                                                mat->getGeometryIterator();
155                                        while (geomit.hasMoreElements())
156                                        {
157                                                StaticGeometry::GeometryBucket* geom = geomit.getNext();
158                                                geom->setCustomParameter(OFFSET_PARAM, offset);
159
160                                        }
161                                }
162                        }
163                }
164
165        }
166
167        bool frameStarted(const FrameEvent& evt)
168        {
169                bool ok = ExampleFrameListener::frameStarted(evt);       
170
171                static Real timeDelay = 0;
172                timeDelay -= evt.timeSinceLastFrame;
173
174                if (mAnimState)
175                        mAnimState->addTime(evt.timeSinceLastFrame);
176
177                KEY_PRESSED(KC_B, 1,
178                        mShowBBs = !mShowBBs;
179                        mSceneManager->showBoundingBoxes(mShowBBs);
180                        )
181
182                waveGrass(evt.timeSinceLastFrame);
183
184                return ok;
185        }
186
187
188
189
190};
191
192
193
194class Grass_Application : public ExampleApplication
195{
196public:
197    Grass_Application() {}
198       
199protected:
200        SceneNode *mpObjsNode; // the node wich will hold our entities
201
202        void createGrassMesh()
203        {
204                // Each grass section is 3 planes at 60 degrees to each other
205                // Normals point straight up to simulate correct lighting
206                MeshPtr msh = MeshManager::getSingleton().createManual(GRASS_MESH_NAME,
207                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
208                SubMesh* sm = msh->createSubMesh();
209                sm->useSharedVertices = false;
210                sm->vertexData = new VertexData();
211                sm->vertexData->vertexStart = 0;
212                sm->vertexData->vertexCount = 12;
213                VertexDeclaration* dcl = sm->vertexData->vertexDeclaration;
214                size_t offset = 0;
215                dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
216                offset += VertexElement::getTypeSize(VET_FLOAT3);
217                dcl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
218                offset += VertexElement::getTypeSize(VET_FLOAT3);
219                dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
220                offset += VertexElement::getTypeSize(VET_FLOAT2);
221
222                HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()
223                        .createVertexBuffer(
224                                offset, 12, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
225                float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
226                Vector3 baseVec(GRASS_WIDTH/2, 0, 0);
227                Vector3 vec = baseVec;
228                Quaternion rot;
229                rot.FromAngleAxis(Degree(60), Vector3::UNIT_Y);
230                int i;
231                for (i = 0; i < 3; ++i)
232                {
233                        // position
234                        *pReal++ = -vec.x;
235                        *pReal++ = GRASS_HEIGHT;
236                        *pReal++ = -vec.z;
237                        // normal
238                        *pReal++ = 0;
239                        *pReal++ = 1;
240                        *pReal++ = 0;
241                        // uv
242                        *pReal++ = 0;
243                        *pReal++ = 0;
244
245                        // position
246                        *pReal++ = vec.x;
247                        *pReal++ = GRASS_HEIGHT;
248                        *pReal++ = vec.z;
249                        // normal
250                        *pReal++ = 0;
251                        *pReal++ = 1;
252                        *pReal++ = 0;
253                        // uv
254                        *pReal++ = 1;
255                        *pReal++ = 0;
256
257                        // position
258                        *pReal++ = -vec.x;
259                        *pReal++ = 0;
260                        *pReal++ = -vec.z;
261                        // normal
262                        *pReal++ = 0;
263                        *pReal++ = 1;
264                        *pReal++ = 0;
265                        // uv
266                        *pReal++ = 0;
267                        *pReal++ = 1;
268
269                        // position
270                        *pReal++ = vec.x;
271                        *pReal++ = 0;
272                        *pReal++ = vec.z;
273                        // normal
274                        *pReal++ = 0;
275                        *pReal++ = 1;
276                        *pReal++ = 0;
277                        // uv
278                        *pReal++ = 1;
279                        *pReal++ = 1;
280
281                        vec = rot * vec;
282                }
283                vbuf->unlock();
284                sm->vertexData->vertexBufferBinding->setBinding(0, vbuf);
285                sm->indexData->indexCount = 6*3;
286                sm->indexData->indexBuffer = HardwareBufferManager::getSingleton()
287                        .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 6*3,
288                                HardwareBuffer::HBU_STATIC_WRITE_ONLY);
289                uint16* pI = static_cast<uint16*>(
290                        sm->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
291                for (i = 0; i < 3; ++i)
292                {
293                        int off = i*4;
294                        *pI++ = 0 + off;
295                        *pI++ = 3 + off;
296                        *pI++ = 1 + off;
297
298                        *pI++ = 0 + off;
299                        *pI++ = 2 + off;
300                        *pI++ = 3 + off;
301                }
302
303                sm->indexData->indexBuffer->unlock();
304
305                sm->setMaterialName(GRASS_MATERIAL);
306                msh->load();
307
308        }
309
310        void setupLighting()
311        {
312                // Set ambient light
313                mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
314                // Point light, movable, reddish
315                mLight = mSceneMgr->createLight("Light2");
316                mLight->setDiffuseColour(mMinLightColour);
317                mLight->setSpecularColour(1, 1, 1);
318                mLight->setAttenuation(8000,1,0.0005,0);
319
320                // Create light node
321                mLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(
322                        "MovingLightNode");
323                mLightNode->attachObject(mLight);
324                // create billboard set
325                BillboardSet* bbs = mSceneMgr->createBillboardSet("lightbbs", 1);
326                bbs->setMaterialName("Examples/Flare");
327                Billboard* bb = bbs->createBillboard(0,0,0,mMinLightColour);
328                // attach
329                mLightNode->attachObject(bbs);
330
331                // create controller, after this is will get updated on its own
332                ControllerFunctionRealPtr func = ControllerFunctionRealPtr(
333                        new WaveformControllerFunction(Ogre::WFT_SINE, 0.0, 0.5));
334                ControllerManager& contMgr = ControllerManager::getSingleton();
335                ControllerValueRealPtr val = ControllerValueRealPtr(
336                        new LightWibbler(mLight, bb, mMinLightColour, mMaxLightColour,
337                        mMinFlareSize, mMaxFlareSize));
338                Controller<Real>* controller = contMgr.createController(
339                        contMgr.getFrameTimeSource(), val, func);
340
341                //mLight->setPosition(Vector3(300,250,-300));
342                mLightNode->setPosition(Vector3(300,250,-300));
343
344
345                // Create a track for the light
346                Animation* anim = mSceneMgr->createAnimation("LightTrack", 20);
347                // Spline it for nice curves
348                anim->setInterpolationMode(Animation::IM_SPLINE);
349                // Create a track to animate the camera's node
350                AnimationTrack* track = anim->createTrack(0, mLightNode);
351                // Setup keyframes
352                KeyFrame* key = track->createKeyFrame(0); // A startposition
353                key->setTranslate(Vector3(300,550,-300));
354                key = track->createKeyFrame(2);//B
355                key->setTranslate(Vector3(150,600,-250));
356                key = track->createKeyFrame(4);//C
357                key->setTranslate(Vector3(-150,650,-100));
358                key = track->createKeyFrame(6);//D
359                key->setTranslate(Vector3(-400,500,-200));
360                key = track->createKeyFrame(8);//E
361                key->setTranslate(Vector3(-200,500,-400));
362                key = track->createKeyFrame(10);//F
363                key->setTranslate(Vector3(-100,450,-200));
364                key = track->createKeyFrame(12);//G
365                key->setTranslate(Vector3(-100,400,180));
366                key = track->createKeyFrame(14);//H
367                key->setTranslate(Vector3(0,250,600));
368                key = track->createKeyFrame(16);//I
369                key->setTranslate(Vector3(100,650,100));
370                key = track->createKeyFrame(18);//J
371                key->setTranslate(Vector3(250,600,0));
372                key = track->createKeyFrame(20);//K == A
373                key->setTranslate(Vector3(300,550,-300));
374                // Create a new animation state to track this
375                mAnimState = mSceneMgr->createAnimationState("LightTrack");
376                mAnimState->setEnabled(true);
377        }
378
379        void createScene(void)
380    {
381
382                mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox");
383
384                setupLighting();
385
386
387                Plane plane;
388                plane.normal = Vector3::UNIT_Y;
389                plane.d = 0;
390                MeshManager::getSingleton().createPlane("Myplane",
391                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
392                        14500,14500,10,10,true,1,50,50,Vector3::UNIT_Z);
393                Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
394                pPlaneEnt->setMaterialName("Examples/GrassFloor");
395                pPlaneEnt->setCastShadows(false);
396                mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
397
398                Vector3 minV(-2000,0,-2000);
399                Vector3 maxV(2000,0,2000);
400
401
402                createGrassMesh();
403
404                Entity* e = mSceneMgr->createEntity("1", GRASS_MESH_NAME);
405
406                StaticGeometry* s = mSceneMgr->createStaticGeometry("bing");
407                s->setRegionDimensions(Vector3(1000,1000,1000));
408                // Set the region origin so the centre is at 0 world
409                s->setOrigin(Vector3(-500, 500, -500));
410
411                for (int x = -1950; x < 1950; x += 150)
412                {
413                        for (int z = -1950; z < 1950; z += 150)
414                        {
415                                Vector3 pos(
416                                        x + Math::RangeRandom(-25, 25),
417                                        0,
418                                        z + Math::RangeRandom(-25, 25));
419                                Quaternion orientation;
420                                orientation.FromAngleAxis(
421                                        Degree(Math::RangeRandom(0, 359)),
422                                        Vector3::UNIT_Y);
423                                Vector3 scale(
424                                        1, Math::RangeRandom(0.85, 1.15), 1);
425                                s->addEntity(e, pos, orientation, scale);
426                        }
427
428                }
429
430                s->build();
431                mStaticGeom = s;
432
433                // Put an Ogre head in the middle
434                MeshPtr m = MeshManager::getSingleton().load("ogrehead.mesh",
435                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
436                unsigned short src, dest;
437                if (!m->suggestTangentVectorBuildParams(src, dest))
438                {
439                        m->buildTangentVectors(src, dest);
440                }
441                e = mSceneMgr->createEntity("head", "ogrehead.mesh");
442                e->setMaterialName("Examples/OffsetMapping/Specular");
443                SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
444                headNode->attachObject(e);
445                headNode->setScale(7,7,7);
446                headNode->setPosition(0,200,0);
447                e->setNormaliseNormals(true);
448                mCamera->move(Vector3(0,350,0));
449        }
450
451    // Create new frame listener
452    void createFrameListener(void)
453    {
454        mFrameListener= new GrassListener(mWindow, mCamera, mSceneMgr);
455        mRoot->addFrameListener(mFrameListener);
456    }
457};
458
459#ifdef __cplusplus
460extern "C" {
461#endif
462
463#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
464INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
465#else
466int main(int argc, char **argv)
467#endif
468{
469    // Create application object
470    Grass_Application app;
471
472    try {
473        app.go();
474    } catch( Exception& e ) {
475#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
476        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
477#else
478        std::cerr << "An exception has occured: " << e.getFullDescription();
479#endif
480    }
481
482    return 0;
483}
484
485#ifdef __cplusplus
486}
487#endif
488
Note: See TracBrowser for help on using the repository browser.