Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/Samples/Grass/src/Grass.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 13.6 KB
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-2006 Torus Knot Software Ltd
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 (mKeyboard->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) * 5;
142                        offset.z = Math::Sin(zpos) * 5;
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                if( ExampleFrameListener::frameStarted(evt) == false )
170                        return false;
171
172                static Real timeDelay = 0;
173                timeDelay -= evt.timeSinceLastFrame;
174
175                if (mAnimState)
176                        mAnimState->addTime(evt.timeSinceLastFrame);
177
178                KEY_PRESSED(OIS::KC_B, 1, 
179                        mShowBBs = !mShowBBs;
180                        mSceneManager->showBoundingBoxes(mShowBBs);
181                        )
182
183                waveGrass(evt.timeSinceLastFrame);
184
185                return true;
186        }
187};
188
189
190
191class Grass_Application : public ExampleApplication
192{
193public:
194    Grass_Application() {}
195       
196protected:
197        SceneNode *mpObjsNode; // the node wich will hold our entities
198
199        void createGrassMesh()
200        {
201                // Each grass section is 3 planes at 60 degrees to each other
202                // Normals point straight up to simulate correct lighting
203                MeshPtr msh = MeshManager::getSingleton().createManual(GRASS_MESH_NAME, 
204                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
205                SubMesh* sm = msh->createSubMesh();
206                sm->useSharedVertices = false;
207                sm->vertexData = new VertexData();
208                sm->vertexData->vertexStart = 0;
209                sm->vertexData->vertexCount = 12;
210                VertexDeclaration* dcl = sm->vertexData->vertexDeclaration;
211                size_t offset = 0;
212                dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
213                offset += VertexElement::getTypeSize(VET_FLOAT3);
214                dcl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
215                offset += VertexElement::getTypeSize(VET_FLOAT3);
216                dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
217                offset += VertexElement::getTypeSize(VET_FLOAT2);
218
219                HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()
220                        .createVertexBuffer(
221                                offset, 12, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
222                float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
223                Vector3 baseVec(GRASS_WIDTH/2, 0, 0);
224                Vector3 vec = baseVec;
225                Quaternion rot;
226                rot.FromAngleAxis(Degree(60), Vector3::UNIT_Y);
227                int i;
228                for (i = 0; i < 3; ++i)
229                {
230                        // position
231                        *pReal++ = -vec.x;
232                        *pReal++ = GRASS_HEIGHT;
233                        *pReal++ = -vec.z;
234                        // normal
235                        *pReal++ = 0;
236                        *pReal++ = 1;
237                        *pReal++ = 0;
238                        // uv
239                        *pReal++ = 0;
240                        *pReal++ = 0;
241
242                        // position
243                        *pReal++ = vec.x;
244                        *pReal++ = GRASS_HEIGHT;
245                        *pReal++ = vec.z;
246                        // normal
247                        *pReal++ = 0;
248                        *pReal++ = 1;
249                        *pReal++ = 0;
250                        // uv
251                        *pReal++ = 1;
252                        *pReal++ = 0;
253
254                        // position
255                        *pReal++ = -vec.x;
256                        *pReal++ = 0;
257                        *pReal++ = -vec.z;
258                        // normal
259                        *pReal++ = 0;
260                        *pReal++ = 1;
261                        *pReal++ = 0;
262                        // uv
263                        *pReal++ = 0;
264                        *pReal++ = 1;
265
266                        // position
267                        *pReal++ = vec.x;
268                        *pReal++ = 0;
269                        *pReal++ = vec.z;
270                        // normal
271                        *pReal++ = 0;
272                        *pReal++ = 1;
273                        *pReal++ = 0;
274                        // uv
275                        *pReal++ = 1;
276                        *pReal++ = 1;
277
278                        vec = rot * vec;
279                }
280                vbuf->unlock();
281                sm->vertexData->vertexBufferBinding->setBinding(0, vbuf);
282                sm->indexData->indexCount = 6*3;
283                sm->indexData->indexBuffer = HardwareBufferManager::getSingleton()
284                        .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 6*3,
285                                HardwareBuffer::HBU_STATIC_WRITE_ONLY);
286                uint16* pI = static_cast<uint16*>(
287                        sm->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
288                for (i = 0; i < 3; ++i)
289                {
290                        int off = i*4;
291                        *pI++ = 0 + off;
292                        *pI++ = 3 + off;
293                        *pI++ = 1 + off;
294
295                        *pI++ = 0 + off;
296                        *pI++ = 2 + off;
297                        *pI++ = 3 + off;
298                }
299
300                sm->indexData->indexBuffer->unlock();
301
302                sm->setMaterialName(GRASS_MATERIAL);
303                msh->load();
304
305        }
306
307        void setupLighting()
308        {
309                // Set ambient light
310                mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
311                // Point light, movable, reddish
312                mLight = mSceneMgr->createLight("Light2");
313                mLight->setDiffuseColour(mMinLightColour);
314                mLight->setSpecularColour(1, 1, 1);
315                mLight->setAttenuation(8000,1,0.0005,0);
316
317                // Create light node
318                mLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(
319                        "MovingLightNode");
320                mLightNode->attachObject(mLight);
321                // create billboard set
322                BillboardSet* bbs = mSceneMgr->createBillboardSet("lightbbs", 1);
323                bbs->setMaterialName("Examples/Flare");
324                Billboard* bb = bbs->createBillboard(0,0,0,mMinLightColour);
325                // attach
326                mLightNode->attachObject(bbs);
327
328                // create controller, after this is will get updated on its own
329                ControllerFunctionRealPtr func = ControllerFunctionRealPtr(
330                        new WaveformControllerFunction(Ogre::WFT_SINE, 0.0, 0.5));
331                ControllerManager& contMgr = ControllerManager::getSingleton();
332                ControllerValueRealPtr val = ControllerValueRealPtr(
333                        new LightWibbler(mLight, bb, mMinLightColour, mMaxLightColour, 
334                        mMinFlareSize, mMaxFlareSize));
335                Controller<Real>* controller = contMgr.createController(
336                        contMgr.getFrameTimeSource(), val, func);
337
338                //mLight->setPosition(Vector3(300,250,-300));
339                mLightNode->setPosition(Vector3(300,250,-300));
340
341
342                // Create a track for the light
343                Animation* anim = mSceneMgr->createAnimation("LightTrack", 20);
344                // Spline it for nice curves
345                anim->setInterpolationMode(Animation::IM_SPLINE);
346                // Create a track to animate the camera's node
347                NodeAnimationTrack* track = anim->createNodeTrack(0, mLightNode);
348                // Setup keyframes
349                TransformKeyFrame* key = track->createNodeKeyFrame(0); // A startposition
350                key->setTranslate(Vector3(300,550,-300));
351                key = track->createNodeKeyFrame(2);//B
352                key->setTranslate(Vector3(150,600,-250));
353                key = track->createNodeKeyFrame(4);//C
354                key->setTranslate(Vector3(-150,650,-100));
355                key = track->createNodeKeyFrame(6);//D
356                key->setTranslate(Vector3(-400,500,-200));
357                key = track->createNodeKeyFrame(8);//E
358                key->setTranslate(Vector3(-200,500,-400));
359                key = track->createNodeKeyFrame(10);//F
360                key->setTranslate(Vector3(-100,450,-200));
361                key = track->createNodeKeyFrame(12);//G
362                key->setTranslate(Vector3(-100,400,180));
363                key = track->createNodeKeyFrame(14);//H
364                key->setTranslate(Vector3(0,250,600));
365                key = track->createNodeKeyFrame(16);//I
366                key->setTranslate(Vector3(100,650,100));
367                key = track->createNodeKeyFrame(18);//J
368                key->setTranslate(Vector3(250,600,0));
369                key = track->createNodeKeyFrame(20);//K == A
370                key->setTranslate(Vector3(300,550,-300));
371                // Create a new animation state to track this
372                mAnimState = mSceneMgr->createAnimationState("LightTrack");
373                mAnimState->setEnabled(true);
374        }
375
376        void createScene(void)
377    {
378
379                mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox");
380
381                setupLighting();
382
383
384                Plane plane;
385                plane.normal = Vector3::UNIT_Y;
386                plane.d = 0;
387                MeshManager::getSingleton().createPlane("Myplane",
388                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
389                        14500,14500,10,10,true,1,50,50,Vector3::UNIT_Z);
390                Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
391                pPlaneEnt->setMaterialName("Examples/GrassFloor");
392                pPlaneEnt->setCastShadows(false);
393                mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
394
395                Vector3 minV(-2000,0,-2000);
396                Vector3 maxV(2000,0,2000);
397
398
399                createGrassMesh();
400
401                Entity* e = mSceneMgr->createEntity("1", GRASS_MESH_NAME);
402
403                StaticGeometry* s = mSceneMgr->createStaticGeometry("bing");
404                s->setRegionDimensions(Vector3(1000,1000,1000));
405                // Set the region origin so the centre is at 0 world
406                s->setOrigin(Vector3(-500, 500, -500));
407
408                for (int x = -1950; x < 1950; x += 150)
409                {
410                        for (int z = -1950; z < 1950; z += 150)
411                        {
412                                Vector3 pos(
413                                        x + Math::RangeRandom(-25, 25), 
414                                        0, 
415                                        z + Math::RangeRandom(-25, 25));
416                                Quaternion orientation;
417                                orientation.FromAngleAxis(
418                                        Degree(Math::RangeRandom(0, 359)),
419                                        Vector3::UNIT_Y);
420                                Vector3 scale(
421                                        1, Math::RangeRandom(0.85, 1.15), 1);
422                                s->addEntity(e, pos, orientation, scale);
423                        }
424
425                }
426
427                s->build();
428                mStaticGeom = s;
429
430                // Put an Ogre head in the middle
431                MeshPtr m = MeshManager::getSingleton().load("ogrehead.mesh", 
432                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
433                unsigned short src, dest;
434                if (!m->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
435                {
436                        m->buildTangentVectors(VES_TANGENT, src, dest);
437                }
438                e = mSceneMgr->createEntity("head", "ogrehead.mesh");
439                e->setMaterialName("Examples/OffsetMapping/Specular");
440                SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
441                headNode->attachObject(e);
442                headNode->setScale(7,7,7);
443                headNode->setPosition(0,200,0);
444                e->setNormaliseNormals(true);
445                mCamera->move(Vector3(0,350,0));
446        }
447
448    // Create new frame listener
449    void createFrameListener(void)
450    {
451        mFrameListener= new GrassListener(mWindow, mCamera, mSceneMgr);
452        mRoot->addFrameListener(mFrameListener);
453    }
454};
455
456#ifdef __cplusplus
457extern "C" {
458#endif
459
460#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
461INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
462#else
463int main(int argc, char **argv)
464#endif
465{
466    // Create application object
467    Grass_Application app;
468
469    try {
470        app.go();
471    } catch( Exception& e ) {
472#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
473        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
474#else
475        std::cerr << "An exception has occured: " << e.getFullDescription();
476#endif
477    }
478
479    return 0;
480}
481
482#ifdef __cplusplus
483}
484#endif
485
Note: See TracBrowser for help on using the repository browser.