Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/Samples/Instancing/src/crowd.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 15.3 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-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        Crowd.cpp
18    \brief
19        Shows OGRE's bezier Crowd feature
20*/
21
22#include "crowd.h"
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
29#define WIN32_LEAN_AND_MEAN
30#include "windows.h"
31
32INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
33#else
34int main(int argc, char **argv)
35#endif
36{
37    // Create application object
38    CrowdApplication app;
39
40    try {
41        app.go();
42    } catch( Ogre::Exception& e ) {
43#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
44        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
45#else
46        std::cerr << "An exception has occured: " << e.getFullDescription();
47#endif
48    }
49
50
51    return 0;
52}
53#ifdef __cplusplus
54}
55#endif
56
57        CrowdListener::CrowdListener(RenderWindow* win, Camera* cam,CEGUI::Renderer* renderer, CrowdApplication*main)
58                : ExampleFrameListener(win, cam,false,true),
59                mRequestShutDown(false),
60                mLMBDown(false),
61                mRMBDown(false),
62                mAvgFrameTime(0.1),
63                mMain(main),
64                mBurnAmount(0)
65        { 
66                const GpuProgramManager::SyntaxCodes &syntaxCodes = GpuProgramManager::getSingleton().getSupportedSyntax();
67                for (GpuProgramManager::SyntaxCodes::const_iterator iter = syntaxCodes.begin();iter != syntaxCodes.end();++iter)
68                {
69                                LogManager::getSingleton().logMessage("supported syntax : "+(*iter));
70                }
71                mGUIRenderer=renderer;
72                numMesh = 160;
73                numRender = 0;
74                meshSelected = 0;
75                currentGeomOpt = INSTANCE_OPT;
76                createCurrentGeomOpt();
77
78                mMouse->setEventCallback(this);
79                mKeyboard->setEventCallback(this);
80
81                mGuiAvg   = CEGUI::WindowManager::getSingleton().getWindow("OPAverageFPS");
82                mGuiCurr  = CEGUI::WindowManager::getSingleton().getWindow("OPCurrentFPS");
83                mGuiBest  = CEGUI::WindowManager::getSingleton().getWindow("OPBestFPS");
84                mGuiWorst = CEGUI::WindowManager::getSingleton().getWindow("OPWorstFPS");
85                mGuiTris  = CEGUI::WindowManager::getSingleton().getWindow("OPTriCount");
86                mGuiDbg   = CEGUI::WindowManager::getSingleton().getWindow("OPDebugMsg");
87                mRoot     = CEGUI::WindowManager::getSingleton().getWindow("root");
88                mDebugOverlay->hide();
89                timer = new Ogre::Timer();
90                mLastTime = timer->getMicroseconds()/1000000.0f;
91
92        }
93        //-----------------------------------------------------------------------
94        CrowdListener::~CrowdListener()
95        {
96                destroyCurrentGeomOpt();
97                delete timer;
98        }
99        //-----------------------------------------------------------------------
100        bool CrowdListener::frameStarted(const FrameEvent& evt)
101        {
102
103                burnCPU();
104                std::vector <AnimationState*>::iterator it;
105                for(it=animations.begin();it!=animations.end();it++)
106                {
107                        (*it)->addTime(evt.timeSinceLastFrame);
108                }
109               
110                updateStats();
111
112                if(mRequestShutDown)
113                        return false;
114                const bool returnValue = ExampleFrameListener::frameStarted(evt);
115                // Call default
116                return returnValue;
117        }
118        //-----------------------------------------------------------------------
119        void CrowdListener::burnCPU(void)
120        {
121            double mStartTime = timer->getMicroseconds()/1000000.0f; //convert into seconds
122                double mCurTime =  mStartTime;
123                double mStopTime = mLastTime + mBurnAmount;
124                double mCPUUsage;
125
126                while( mCurTime < mStopTime )
127                {
128                        mCurTime = timer->getMicroseconds()/1000000.0f; //convert into seconds
129                }
130
131                if( mCurTime - mLastTime > 0.00001f )
132                        mCPUUsage = (mCurTime - mStartTime) / (mCurTime - mLastTime) * 100.0f;
133                else
134                        mCPUUsage = FLT_MAX;
135
136                mLastTime = timer->getMicroseconds()/1000000.0f; //convert into seconds
137                int time = mCPUUsage+0.5f;
138                if(mTimeUntilNextToggle<=0)
139                {
140                        //mDebugText="remaining for logic:"+ StringConverter::toString(time);
141                        mTimeUntilNextToggle=1;
142                }
143               
144        }
145        //-----------------------------------------------------------------------
146        void CrowdListener::destroyCurrentGeomOpt()
147        {
148                switch(currentGeomOpt)
149                {
150                        case INSTANCE_OPT:destroyInstanceGeom();break;
151                        case ENTITY_OPT: destroyEntityGeom ();break;
152                }
153        }
154        //-----------------------------------------------------------------------
155        void CrowdListener::createCurrentGeomOpt()
156        {
157                LogManager::getSingleton().logMessage("geom deleted");
158                objectCount=numMesh;
159                numRender=1;
160                while(objectCount>maxObjectsPerBatch)
161                {
162                        numRender++;
163                        objectCount-=maxObjectsPerBatch;
164                }
165       
166                assert (meshSelected < numTypeMeshes);
167                MeshPtr m = MeshManager::getSingleton ().getByName ("robot.mesh");
168                if (m.isNull ())
169                {
170                        m = MeshManager::getSingleton ().load ("robot.mesh", 
171                                ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
172                }
173                const Real radius = m->getBoundingSphereRadius ();
174
175                // could/should print on screen mesh name,
176                //optimisation type,
177                //mesh vertices num,
178                //32 bit or not,
179                //etC..
180
181
182                switch(currentGeomOpt)
183                {
184                        case INSTANCE_OPT:createInstanceGeom();break;
185                        case ENTITY_OPT: createEntityGeom ();break;
186                }
187
188        }
189        //-----------------------------------------------------------------------
190        void CrowdListener::createInstanceGeom()
191        {
192                if (Root::getSingleton ().getRenderSystem ()->getCapabilities ()->hasCapability (RSC_VERTEX_PROGRAM) == false)
193                {
194                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Your video card doesn't support batching", "Demo_Instance::createScene");
195                }
196
197                Entity *ent = mCamera->getSceneManager()->createEntity("robot","robot.mesh");   
198                setupInstancedMaterialToEntity(ent);
199
200                renderInstance.reserve(numRender);
201                renderInstance.resize(numRender);
202
203                //Load a mesh to read data from.       
204                InstancedGeometry* batch = new InstancedGeometry(mCamera->getSceneManager(), 
205                        "robots" );
206                batch->setCastShadows(true);
207
208        size_t i, k;
209
210                batch->setBatchInstanceDimensions (Vector3(1000000, 1000000, 1000000));
211                const size_t batchSize = (numMesh > maxObjectsPerBatch) ? maxObjectsPerBatch :numMesh;
212                for(i = 0; i < batchSize ; i++)
213                {
214                        batch->addEntity(ent, Vector3::ZERO);
215                }
216                batch->setOrigin(Vector3::ZERO);
217
218                batch->build();
219
220
221                for (k = 0; k < numRender-1; k++)
222                {
223                        batch->addBatchInstance();
224                }
225
226                i = 0,k = 0;
227                InstancedGeometry::BatchInstanceIterator regIt = batch->getBatchInstanceIterator();
228                size_t baseIndexForBatch = 0;
229                //create a RayQuery to get the terrain height
230                RaySceneQuery* raySceneQuery=mCamera->getSceneManager()->createRayQuery(Ray(Vector3(0,0,0), Vector3::NEGATIVE_UNIT_Y));
231                RaySceneQueryResult::iterator it;
232                RaySceneQueryResult& qryResult=raySceneQuery->execute();
233                while (regIt.hasMoreElements ())
234                {
235
236                        InstancedGeometry::BatchInstance *r = regIt.getNext();
237                        unsigned short objectCount;
238
239                        InstancedGeometry::InstancedObject **objects= r->getObjectsAsArray(objectCount);
240                        for(size_t j = 0; j < objectCount; j++)
241                        {
242                                Vector3 position;
243                               
244                                position.x=10*k+500;
245                                position.z=10*i+500;
246                                position.y=0;
247                                raySceneQuery->setRay (Ray(position, Vector3::UNIT_Y));
248                                raySceneQuery->execute();
249                it = qryResult.begin();
250
251                if (it != qryResult.end() && it->worldFragment)
252                                        position.y =  it->worldFragment->singleIntersection.y;
253                               
254                                                                               
255                                objects[j]->setPosition(position);
256                                objects[j]->setScale(Vector3(0.1,0.1,0.1));
257                                AnimationState*anim=objects[j]->getAnimationState("Walk");
258                                animations.push_back(anim);
259                                //offset the animation time, to show that all objects are independently animated.
260                                anim->setTimePosition(i+k);
261                                anim->setEnabled(true);
262                                k++;
263                        }
264
265                        if(k>14)
266                        {
267                                k=0;
268                            i++;
269                        }
270                        delete[] objects;       
271                }
272                batch->setVisible(true);
273                renderInstance[0] = batch;
274                mCamera->getSceneManager()->destroyQuery(raySceneQuery);
275                mCamera->getSceneManager()->destroyEntity (ent);
276        }
277        //-----------------------------------------------------------------------
278        void CrowdListener::destroyInstanceGeom()
279        {
280                delete renderInstance[0];
281                renderInstance.clear();
282                animations.clear();
283        }
284        void CrowdListener::setupInstancedMaterialToEntity(Entity*ent)
285        {
286                for (Ogre::uint i = 0; i < ent->getNumSubEntities(); ++i)
287                {
288                        SubEntity* se = ent->getSubEntity(i);
289                        String materialName= se->getMaterialName();
290                        se->setMaterialName(buildCrowdMaterial(materialName, ent->getSkeleton()->getNumBones()));
291                }
292        }
293        String CrowdListener::buildCrowdMaterial(const String &originalMaterialName,int numBones)
294        {
295
296                // already instanced ?
297                if (StringUtil::endsWith (originalMaterialName, "/instanced"))
298                        return originalMaterialName;
299
300                MaterialPtr originalMaterial = MaterialManager::getSingleton ().getByName (originalMaterialName);
301
302                // if originalMat doesn't exists use "Instancing" material name
303                const String instancedMaterialName (originalMaterial.isNull() ? "Instancing" : originalMaterialName + "/Instanced");
304                MaterialPtr  instancedMaterial = MaterialManager::getSingleton ().getByName (instancedMaterialName);
305
306                // already exists ?
307                if (instancedMaterial.isNull())
308                {
309                        instancedMaterial = originalMaterial->clone(instancedMaterialName);
310                        instancedMaterial->load();
311                        Technique::PassIterator pIt = instancedMaterial->getBestTechnique ()->getPassIterator();
312                        while (pIt.hasMoreElements())
313                        {
314
315                                Pass * const p = pIt.getNext();
316                                p->setVertexProgram("Crowd",true);
317                                p->setShadowCasterVertexProgram("CrowdShadowCaster");
318               
319                        }
320                }
321                instancedMaterial->load();
322                return instancedMaterialName;
323
324
325        }
326        //-----------------------------------------------------------------------
327        void CrowdListener::createEntityGeom()
328        {
329                size_t k = 0;
330                size_t y = 0;
331                renderEntity.reserve (numMesh);
332                renderEntity.resize (numMesh);
333                nodes.reserve (numMesh);
334                nodes.resize (numMesh);
335                //create a RayQuery to get the terrain height
336                RaySceneQuery* raySceneQuery=mCamera->getSceneManager()->createRayQuery(Ray(Vector3(0,0,0), Vector3::NEGATIVE_UNIT_Y));
337                RaySceneQueryResult::iterator it;
338                RaySceneQueryResult& qryResult=raySceneQuery->execute();
339                for (size_t i = 0; i < numMesh; i++)
340                {
341               
342                        Vector3 position;
343                               
344                        position.x=10*y+500;
345                        position.y=0;
346                        position.z=10*k+500;   
347
348                        raySceneQuery->setRay (Ray(position, Vector3::UNIT_Y));
349                        raySceneQuery->execute();
350            it = qryResult.begin();
351
352            if (it != qryResult.end() && it->worldFragment)
353                                position.y =  it->worldFragment->singleIntersection.y;
354
355                        nodes[i]=mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode("node"+StringConverter::toString(i));
356                        LogManager::getSingleton().logMessage(":"+nodes[i]->getName());
357                        renderEntity[i]=mCamera->getSceneManager()->createEntity("robot"+StringConverter::toString(i), "robot.mesh");   
358                nodes[i]->attachObject(renderEntity[i]);
359                        nodes[i]->setPosition(position);
360                        nodes[i]->setScale(Vector3(0.1,0.1,0.1));
361                        AnimationState*anim=renderEntity[i]->getAnimationState("Walk");
362                        animations.push_back(anim);
363                        anim->setTimePosition(y+k);
364                        anim->setEnabled(true);
365                        y++;
366                        if (y>14)
367                        {
368                                y=0;
369                                k++;
370                        }
371                }
372                mCamera->getSceneManager()->destroyQuery(raySceneQuery);
373
374
375        }
376        //-----------------------------------------------------------------------
377        void CrowdListener::destroyEntityGeom()
378        {
379                size_t i;
380                size_t j=0;
381                for (i=0;i<numMesh;i++)
382                {
383                        LogManager::getSingleton().logMessage(" " +nodes[i]->getName());
384                        LogManager::getSingleton().logMessage(StringConverter::toString(j)+":"+StringConverter::toString(j<numMesh));
385                        String name=nodes[i]->getName();
386                        mCamera->getSceneManager()->destroySceneNode(name);
387                        mCamera->getSceneManager()->destroyEntity(renderEntity[i]);
388                        j++;
389                }
390                animations.clear();
391
392
393
394        }
395        //-----------------------------------------------------------------------
396        bool CrowdListener::mouseMoved ( const OIS::MouseEvent &arg )
397        {
398
399                CEGUI::System::getSingleton().injectMouseMove( arg.state.X.rel, arg.state.Y.rel );
400                return true;
401        }       
402        //-----------------------------------------------------------------------
403   bool CrowdListener::mousePressed ( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
404   {
405       CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(id));
406                return true;
407   }
408        //-----------------------------------------------------------------------
409   bool CrowdListener::mouseReleased (const OIS::MouseEvent &arg, OIS::MouseButtonID id)
410   {
411           CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(id));
412                return true;
413   }
414
415   void CrowdListener::requestShutdown(void)
416   {
417           mRequestShutDown=true;
418   }
419   void CrowdListener::setCurrentGeometryOpt(CurrentGeomOpt opt)
420   {
421           currentGeomOpt=opt;
422   }
423   bool CrowdListener::handleMouseMove(const CEGUI::EventArgs& e)
424        {
425                using namespace CEGUI;
426
427                if( mLMBDown)
428                {
429                        int a =0;
430                        // rotate camera
431                        mRotX += Ogre::Degree(-((const MouseEventArgs&)e).moveDelta.d_x * mAvgFrameTime * 10.0);
432                        mRotY += Ogre::Degree(-((const MouseEventArgs&)e).moveDelta.d_y * mAvgFrameTime * 10.0);
433                        mCamera->yaw(mRotX);
434                        mCamera->pitch(mRotY);
435                        MouseCursor::getSingleton().setPosition( mLastMousePosition );
436                }
437                       
438
439         return true;
440        }
441        //--------------------------------------------------------------------------
442        bool CrowdListener::handleMouseButtonUp(const CEGUI::EventArgs& e)
443        {
444                using namespace CEGUI;
445
446               
447                if( ((const MouseEventArgs&)e).button == LeftButton )
448                {
449                        mLMBDown = false;
450                        MouseCursor::getSingleton().setPosition( mLastMousePosition );
451                        CEGUI::MouseCursor::getSingleton().show();
452                }
453
454
455                return true;
456        }
457
458        //--------------------------------------------------------------------------
459        bool CrowdListener::handleMouseButtonDown(const CEGUI::EventArgs& e)
460        {
461                using namespace CEGUI;
462
463               
464                if( ((const MouseEventArgs&)e).button == LeftButton )
465                {
466                        mLMBDown = true;
467                        mLastMousePosition=CEGUI::MouseCursor::getSingleton().getPosition();
468                        CEGUI::MouseCursor::getSingleton().hide();
469                }
470
471
472
473                return true;
474        }
475        //--------------------------------------------------------------------------
476        void CrowdListener::updateStats(void)
477        {
478                static CEGUI::String currFps = "Current FPS: ";
479                static CEGUI::String avgFps = "Average FPS: ";
480                static CEGUI::String bestFps = "Best FPS: ";
481                static CEGUI::String worstFps = "Worst FPS: ";
482                static CEGUI::String tris = "Triangle Count: ";
483
484
485                const Ogre::RenderTarget::FrameStats& stats = mMain->getRenderWindow()->getStatistics();
486       
487                mGuiAvg->setText(avgFps + Ogre::StringConverter::toString(stats.avgFPS));
488                mGuiCurr->setText(currFps + Ogre::StringConverter::toString(stats.lastFPS));
489                mGuiBest->setText(bestFps + Ogre::StringConverter::toString(stats.bestFPS)
490                        + " " + Ogre::StringConverter::toString(stats.bestFrameTime)+" ms");
491                mGuiWorst->setText(worstFps + Ogre::StringConverter::toString(stats.worstFPS)
492                        + " " + Ogre::StringConverter::toString(stats.worstFrameTime)+" ms");
493
494                mGuiTris->setText(tris + Ogre::StringConverter::toString(stats.triangleCount));
495                mAvgFrameTime = 1.0f/(stats.avgFPS + 1.0f);
496                if (mAvgFrameTime > 0.1f) mAvgFrameTime = 0.1f;
497
498        }
Note: See TracBrowser for help on using the repository browser.