Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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