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

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

added ogre dependencies and patched ogre sources

Line 
1// Dynamic texturing demo
2//
3// Feel free to use this for anything you want (Wumpus, OGRE Team 2004). This file is public domain.
4// Uses the Grey-Scott diffusion reaction process, a nice overview of the parameter space can be seen at
5//   http://www.cacr.caltech.edu/ismap/image.html
6//
7// Some very cool effects can be reached with some combinations of parameters, varying the parameters
8// during growth gives even more curious things.
9//
10// Use 1-8 to change parameters, and 0 to reset to initial conditions
11
12#include "ExampleApplication.h"
13#include <OgreTexture.h>
14#include <OgreHardwarePixelBuffer.h>
15#include <OgreTextureManager.h>
16#include <OgreLogManager.h>
17#include <sstream>
18TexturePtr ptex;
19HardwarePixelBufferSharedPtr buffer;
20Overlay* overlay;
21static const int reactorExtent = 130; // must be 2^N + 2
22uint32 clut[1024];
23AnimationState *swim;
24// Nano fixed point library
25#define FROMFLOAT(X) ((int)((X)*((float)(1<<16))))
26#define TOFLOAT(X) ((float)((X)/((float)(1<<16))))
27#define MULT(X,Y) (((X)*(Y))>>16)
28ColourValue HSVtoRGB( float h, float s, float v )
29{
30        int i;
31        ColourValue rv(0.0f, 0.0f, 0.0f, 1.0f);
32        float f, p, q, t;
33        h = fmodf(h, 360.0f);
34        h /= 60.0f;                     // sector 0 to 5
35        i = (int)floor( h );
36        f = h - i;                      // factorial part of h
37        p = v * ( 1.0f - s );
38        q = v * ( 1.0f - s * f );
39        t = v * ( 1.0f - s * ( 1.0f - f ) );
40       
41        switch( i ) {
42                case 0: rv.r = v;       rv.g = t;       rv.b = p;       break;
43                case 1: rv.r = q;       rv.g = v;       rv.b = p;       break;
44                case 2: rv.r = p;       rv.g = v;       rv.b = t;       break;
45                case 3: rv.r = p;       rv.g = q;       rv.b = v;       break;
46                case 4: rv.r = t;       rv.g = p;       rv.b = v;       break;
47                default:        rv.r = v;       rv.g = p;       rv.b = q;       break;
48        }
49        return rv;
50}
51class DynTexFrameListener : public ExampleFrameListener
52{
53private:
54    static float fDefDim;
55    static float fDefVel;
56        float tim;
57       
58        int *chemical[2];
59        int *delta[2];
60        size_t mSize;
61        int dt,hdiv0,hdiv1; // diffusion parameters
62        int F,k; // reaction parameters
63
64        bool rpressed;
65public:
66    DynTexFrameListener(RenderWindow* win, Camera* cam) : ExampleFrameListener( win, cam )
67    {
68                tim = 0;
69                rpressed = false;
70                // Create  colour lookup
71                for(unsigned int col=0; col<1024; col++)
72                {
73                        ColourValue c;
74                        c = HSVtoRGB((1.0f-col/1024.0f)*90.0f+225.0f, 0.9f, 0.75f+0.25f*(1.0f-col/1024.0f));
75                        c.a = 1.0f - col/1024.0f;
76                        PixelUtil::packColour(c, PF_A8R8G8B8, &clut[col]);
77                }
78                // Setup
79                LogManager::getSingleton().logMessage("Creating chemical containment");
80                mSize = reactorExtent*reactorExtent;
81                chemical[0] = new int [mSize];
82                chemical[1] = new int [mSize];
83                delta[0] = new int [mSize];
84                delta[1] = new int [mSize];
85               
86                dt = FROMFLOAT(2.0f);
87                hdiv0 = FROMFLOAT(2.0E-5f/(2.0f*0.01f*0.01f)); // a / (2.0f*h*h); -- really diffusion rate
88                hdiv1 = FROMFLOAT(1.0E-5f/(2.0f*0.01f*0.01f)); // a / (2.0f*h*h); -- really diffusion rate
89                //k = FROMFLOAT(0.056f);
90                //F = FROMFLOAT(0.020f);
91                k = FROMFLOAT(0.0619f);
92                F = FROMFLOAT(0.0316f);
93               
94                resetReactor();
95                fireUpReactor();
96                updateInfoParamF();
97                updateInfoParamK();
98                updateInfoParamA0();
99                updateInfoParamA1();
100               
101                LogManager::getSingleton().logMessage("Cthulhu dawn");
102    }
103        void resetReactor()
104        {
105                LogManager::getSingleton().logMessage("Facilitating neutral start up conditions");
106                for(unsigned int x=0; x<mSize; x++)
107                {
108                        chemical[0][x] = FROMFLOAT(1.0f);
109                        chemical[1][x] = FROMFLOAT(0.0f);
110                }
111        }
112        void fireUpReactor()
113        {
114                LogManager::getSingleton().logMessage("Warning: reactor is being fired up");
115                int center = reactorExtent/2;
116                for(unsigned int x=center-10; x<center+10; x++)
117                {
118                        for(unsigned int y=center-10; y<center+10; y++)
119                        {
120                                chemical[0][y*reactorExtent+x] = FROMFLOAT(0.5f) + rand()%FROMFLOAT(0.1);
121                                chemical[1][y*reactorExtent+x] = FROMFLOAT(0.25f) + rand()%FROMFLOAT(0.1);
122                        }
123                }
124                LogManager::getSingleton().logMessage("Warning: reaction has begun");
125        }
126       
127        void runStep()
128        {
129                unsigned int x, y;
130                for(x=0; x<mSize; x++)
131                {
132                        delta[0][x] = 0;
133                        delta[1][x] = 0;
134                }
135                // Boundary conditions
136                unsigned int idx;
137                idx = 0;
138                for(y=0; y<reactorExtent; y++)
139                {
140                        chemical[0][idx] = chemical[0][idx+reactorExtent-2];
141                        chemical[0][idx+reactorExtent-1] = chemical[0][idx+1];
142                        chemical[1][idx] = chemical[1][idx+reactorExtent-2];
143                        chemical[1][idx+reactorExtent-1] = chemical[1][idx+1];
144                        idx += reactorExtent;
145                }
146                unsigned int skip = reactorExtent*(reactorExtent-1);
147                for(y=0; y<reactorExtent; y++)
148                {
149                        chemical[0][y] = chemical[0][y + skip - reactorExtent];
150                        chemical[0][y + skip] = chemical[0][y + reactorExtent];
151                        chemical[1][y] = chemical[1][y + skip - reactorExtent];
152                        chemical[1][y + skip] = chemical[1][y + reactorExtent];
153                }
154                // Diffusion
155                idx = reactorExtent+1;
156                for(y=0; y<reactorExtent-2; y++)
157                {
158                        for(x=0; x<reactorExtent-2; x++)
159                        {
160                                delta[0][idx] += MULT(chemical[0][idx-reactorExtent] + chemical[0][idx-1]
161                                                                -4*chemical[0][idx] + chemical[0][idx+1]
162                                                                +chemical[0][idx+reactorExtent], hdiv0);
163                                delta[1][idx] += MULT(chemical[1][idx-reactorExtent] + chemical[1][idx-1]
164                                                                -4*chemical[1][idx] + chemical[1][idx+1]
165                                                                +chemical[1][idx+reactorExtent], hdiv1);
166                                idx++;
167                        }
168                        idx += 2;
169                }
170                // Reaction (Grey-Scott)
171                idx = reactorExtent+1;
172                int U,V;
173
174                for(y=0; y<reactorExtent-2; y++)
175                {
176                        for(x=0; x<reactorExtent-2; x++)
177                        {                       
178                                U = chemical[0][idx]; V = chemical[1][idx];
179                                int UVV = MULT(MULT(U,V),V);
180                                delta[0][idx] += -UVV + MULT(F,(1<<16)-U);
181                                delta[1][idx] += UVV - MULT(F+k,V);
182                                idx++;
183                        }
184                        idx += 2;
185                }
186                // Update concentrations
187                for(x=0; x<mSize; x++)
188                {
189                        chemical[0][x] += MULT(delta[0][x], dt);
190                        chemical[1][x] += MULT(delta[1][x], dt);
191                }
192        }
193
194        void buildTexture()
195        {
196                buffer->lock(HardwareBuffer::HBL_DISCARD);
197                const PixelBox &pb = buffer->getCurrentLock();
198                unsigned int idx = reactorExtent+1;
199                for(unsigned int y=0; y<(reactorExtent-2); y++) {
200                        uint32 *data = static_cast<uint32*>(pb.data) + y*pb.rowPitch;
201                        int *chem = &chemical[0][idx];
202                        for(unsigned int x=0; x<(reactorExtent-2); x++) {
203                                data[x] = clut[(chem[x]>>6)&1023];
204                        }
205                        idx += reactorExtent;
206                }
207                buffer->unlock();
208        }
209        // GUI updaters
210        void updateInfoParamK()
211        {
212                OverlayManager::getSingleton().getOverlayElement("Example/DynTex/Param_K") \
213                        ->setCaption("[1/2]k: "+StringConverter::toString(TOFLOAT(k)));         
214        }
215        void updateInfoParamF()
216        {
217                OverlayManager::getSingleton().getOverlayElement("Example/DynTex/Param_F") \
218                        ->setCaption("[3/4]F: "+StringConverter::toString(TOFLOAT(F)));         
219        }
220        void updateInfoParamA0()
221        {
222                // Diffusion rate for chemical 1
223                OverlayManager::getSingleton().getOverlayElement("Example/DynTex/Param_A0") \
224                        ->setCaption("[5/6]Diffusion 1: "+StringConverter::toString(TOFLOAT(hdiv0)));           
225        }
226        void updateInfoParamA1()
227        {
228                // Diffusion rate for chemical 2
229                OverlayManager::getSingleton().getOverlayElement("Example/DynTex/Param_A1") \
230                        ->setCaption("[7/8]Diffusion 2: "+StringConverter::toString(TOFLOAT(hdiv1)));           
231        }
232
233    bool frameStarted( const FrameEvent& evt )
234    {
235        bool bOK = ExampleFrameListener::frameStarted( evt );
236               
237        if( mInputDevice->isKeyDown( KC_1 ) ) {
238                k -= FROMFLOAT(0.005f*evt.timeSinceLastFrame);
239                        updateInfoParamK();
240                }
241        if( mInputDevice->isKeyDown( KC_2 ) ) {
242                k += FROMFLOAT(0.005f*evt.timeSinceLastFrame);
243                        updateInfoParamK();
244                }
245        if( mInputDevice->isKeyDown( KC_3 ) ) {
246                F -= FROMFLOAT(0.005f*evt.timeSinceLastFrame);
247                        updateInfoParamF();
248                }
249        if( mInputDevice->isKeyDown( KC_4 ) ) {
250                F += FROMFLOAT(0.005f*evt.timeSinceLastFrame);
251                        updateInfoParamF();
252                }
253        if( mInputDevice->isKeyDown( KC_5 ) ) {
254                hdiv0 -= FROMFLOAT(0.005f*evt.timeSinceLastFrame);
255                        updateInfoParamA0();
256                }
257        if( mInputDevice->isKeyDown( KC_6 ) ) {
258                hdiv0 += FROMFLOAT(0.005f*evt.timeSinceLastFrame);
259                        updateInfoParamA0();
260                }
261        if( mInputDevice->isKeyDown( KC_7 ) ) {
262                hdiv1 -= FROMFLOAT(0.005f*evt.timeSinceLastFrame);
263                        updateInfoParamA1();
264                }
265        if( mInputDevice->isKeyDown( KC_8 ) ) {
266                hdiv1 += FROMFLOAT(0.005f*evt.timeSinceLastFrame);
267                        updateInfoParamA1();
268                }
269
270                if( mInputDevice->isKeyDown( KC_0 ) && !rpressed ) {
271                        // Reset 0
272                        resetReactor();
273                        fireUpReactor();
274                        rpressed = true;
275                } else {
276                        rpressed = false;
277                }
278                for(int x=0; x<10; x++)
279                        runStep();
280                buildTexture();
281                swim->addTime(evt.timeSinceLastFrame);
282
283        return bOK;
284    }
285
286        virtual ~DynTexFrameListener(void)
287    {
288                delete [] chemical[0];
289        delete [] chemical[1];
290                delete [] delta[0];
291                delete [] delta[1];
292    }
293};
294
295float DynTexFrameListener::fDefDim = 25.0f;
296float DynTexFrameListener::fDefVel = 50.0f;
297
298class DynTexApplication : public ExampleApplication
299{
300public:
301    DynTexApplication() {}
302
303protected:
304       
305       
306    virtual void createFrameListener(void)
307    {
308        mFrameListener= new DynTexFrameListener(mWindow, mCamera);
309        mFrameListener->showDebugOverlay(true);
310        mRoot->addFrameListener(mFrameListener);
311    }
312
313
314        virtual void createViewports(void)
315    {
316                // Create one viewport, entire window
317        Viewport* vp = mWindow->addViewport(mCamera);
318        vp->setBackgroundColour(ColourValue(0,0,0));
319
320        // Alter the camera aspect ratio to match the viewport
321        mCamera->setAspectRatio(
322            Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
323    }
324
325    // Just override the mandatory create scene method
326    void createScene(void)
327    {
328        // Create dynamic texture
329                ptex = TextureManager::getSingleton().createManual(
330                        "DynaTex","General", TEX_TYPE_2D, reactorExtent-2, reactorExtent-2, 0, PF_A8R8G8B8,
331                        TU_DYNAMIC_WRITE_ONLY);
332                buffer = ptex->getBuffer(0, 0);
333
334                // Set ambient light
335        mSceneMgr->setAmbientLight(ColourValue(0.6, 0.6, 0.6));
336                mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 50 );
337
338        //mRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR, ColourValue(255,255,255,0));
339
340        // Create a light
341        Light* l = mSceneMgr->createLight("MainLight");
342        l->setDiffuseColour(0.75, 0.75, 0.80);
343                l->setSpecularColour(0.9, 0.9, 1);
344        l->setPosition(-100,80,50);
345                mSceneMgr->getRootSceneNode()->attachObject(l);
346
347                       
348        Entity *planeEnt = mSceneMgr->createEntity("TexPlane1", Ogre::SceneManager::PT_PLANE);
349        // Give the plane a texture
350        planeEnt->setMaterialName("Examples/DynaTest");
351
352        SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-100,-40,-100));
353        node->attachObject(planeEnt);
354                node->setScale(3.0f, 3.0f, 3.0f);
355
356        // Create objects
357        SceneNode *blaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200,0,50));
358        Entity *ent2 = mSceneMgr->createEntity( "knot", "knot.mesh" );
359                ent2->setMaterialName("Examples/DynaTest4");
360        blaNode->attachObject( ent2 );
361               
362                blaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(200,-90,50));
363        ent2 = mSceneMgr->createEntity( "knot2", "knot.mesh" );
364                ent2->setMaterialName("Examples/DynaTest2");
365        blaNode->attachObject( ent2 );
366        blaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-110,200,50));
367               
368                // Cloaked fish
369        ent2 = mSceneMgr->createEntity( "knot3", "fish.mesh" );
370                ent2->setMaterialName("Examples/DynaTest3");
371                swim = ent2->getAnimationState("swim");
372                swim->setEnabled(true);
373        blaNode->attachObject( ent2 );
374                blaNode->setScale(50.0f, 50.0f, 50.0f);
375               
376               
377                //TextureManager::getSingleton().getByName("RustySteel.jpg");
378               
379               
380                std::stringstream d;
381                d << "HardwarePixelBuffer " << buffer->getWidth() << " " << buffer->getHeight() << " " << buffer->getDepth();
382                LogManager::getSingleton().logMessage(d.str());
383               
384                buffer->lock(HardwareBuffer::HBL_NORMAL);
385                const PixelBox &pb = buffer->getCurrentLock();
386                d.str("");
387                d << "PixelBox " << pb.getWidth() << " " << pb.getHeight() << " " << pb.getDepth() << " " << pb.rowPitch << " " << pb.slicePitch << " " << pb.data << " " << PixelUtil::getFormatName(pb.format);
388                LogManager::getSingleton().logMessage(d.str());
389                buffer->unlock();
390               
391                // show GUI
392                overlay = OverlayManager::getSingleton().getByName("Example/DynTexOverlay");   
393                overlay->show();
394    }
395
396        void destroyScene(void)
397        {
398                // Free resource pointers before shutdown
399                ptex.setNull();
400                buffer.setNull();
401        }
402
403};
404
405#ifdef __cplusplus
406extern "C" {
407#endif
408
409#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
410#define WIN32_LEAN_AND_MEAN
411#include "windows.h"
412
413INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
414#else
415int main(int argc, char *argv[])
416#endif
417{
418    // Create application object
419    DynTexApplication app;
420
421    SET_TERM_HANDLER;
422   
423    try {
424        app.go();
425    } catch( Ogre::Exception& e ) {
426#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
427        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
428#else
429        std::cerr << "An exception has occured: " <<
430            e.getFullDescription().c_str() << std::endl;
431#endif
432    }
433
434    return 0;
435}
436
437#ifdef __cplusplus
438}
439#endif
Note: See TracBrowser for help on using the repository browser.