Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 13.2 KB
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        using namespace OIS;
236        if( ExampleFrameListener::frameStarted( evt ) == false )
237                return false;
238               
239        if( mKeyboard->isKeyDown( KC_1 ) ) {
240                k -= FROMFLOAT(0.005f*evt.timeSinceLastFrame);
241                        updateInfoParamK();
242                }
243        if( mKeyboard->isKeyDown( KC_2 ) ) {
244                k += FROMFLOAT(0.005f*evt.timeSinceLastFrame);
245                        updateInfoParamK();
246                }
247        if( mKeyboard->isKeyDown( KC_3 ) ) {
248                F -= FROMFLOAT(0.005f*evt.timeSinceLastFrame);
249                        updateInfoParamF();
250                }
251        if( mKeyboard->isKeyDown( KC_4 ) ) {
252                F += FROMFLOAT(0.005f*evt.timeSinceLastFrame);
253                        updateInfoParamF();
254                }
255        if( mKeyboard->isKeyDown( KC_5 ) ) {
256                hdiv0 -= FROMFLOAT(0.005f*evt.timeSinceLastFrame);
257                        updateInfoParamA0();
258                }
259        if( mKeyboard->isKeyDown( KC_6 ) ) {
260                hdiv0 += FROMFLOAT(0.005f*evt.timeSinceLastFrame);
261                        updateInfoParamA0();
262                }
263        if( mKeyboard->isKeyDown( KC_7 ) ) {
264                hdiv1 -= FROMFLOAT(0.005f*evt.timeSinceLastFrame);
265                        updateInfoParamA1();
266                }
267        if( mKeyboard->isKeyDown( KC_8 ) ) {
268                hdiv1 += FROMFLOAT(0.005f*evt.timeSinceLastFrame);
269                        updateInfoParamA1();
270                }
271
272                if( mKeyboard->isKeyDown( KC_0 ) && !rpressed ) {
273                        // Reset 0
274                        resetReactor();
275                        fireUpReactor();
276                        rpressed = true;
277                } else {
278                        rpressed = false;
279                }
280                for(int x=0; x<10; x++)
281                        runStep();
282                buildTexture();
283                swim->addTime(evt.timeSinceLastFrame);
284
285        return true;
286    }
287
288        virtual ~DynTexFrameListener(void)
289    {
290                delete [] chemical[0];
291        delete [] chemical[1];
292                delete [] delta[0];
293                delete [] delta[1];
294    }
295};
296
297float DynTexFrameListener::fDefDim = 25.0f;
298float DynTexFrameListener::fDefVel = 50.0f;
299
300class DynTexApplication : public ExampleApplication
301{
302public:
303    DynTexApplication() {}
304
305protected:
306       
307       
308    virtual void createFrameListener(void)
309    {
310        mFrameListener= new DynTexFrameListener(mWindow, mCamera);
311        mFrameListener->showDebugOverlay(true);
312        mRoot->addFrameListener(mFrameListener);
313    }
314
315
316        virtual void createViewports(void)
317    {
318                // Create one viewport, entire window
319        Viewport* vp = mWindow->addViewport(mCamera);
320        vp->setBackgroundColour(ColourValue(0,0,0));
321
322        // Alter the camera aspect ratio to match the viewport
323        mCamera->setAspectRatio(
324            Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
325    }
326
327    // Just override the mandatory create scene method
328    void createScene(void)
329    {
330        // Create dynamic texture
331                ptex = TextureManager::getSingleton().createManual(
332                        "DynaTex","General", TEX_TYPE_2D, reactorExtent-2, reactorExtent-2, 0, PF_A8R8G8B8, 
333                        TU_DYNAMIC_WRITE_ONLY);
334                buffer = ptex->getBuffer(0, 0);
335
336                // Set ambient light
337        mSceneMgr->setAmbientLight(ColourValue(0.6, 0.6, 0.6));
338                mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 50 );
339
340        //mRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR, ColourValue(255,255,255,0));
341
342        // Create a light
343        Light* l = mSceneMgr->createLight("MainLight");
344        l->setDiffuseColour(0.75, 0.75, 0.80);
345                l->setSpecularColour(0.9, 0.9, 1);
346        l->setPosition(-100,80,50);
347                mSceneMgr->getRootSceneNode()->attachObject(l);
348
349                       
350        Entity *planeEnt = mSceneMgr->createEntity("TexPlane1", Ogre::SceneManager::PT_PLANE);
351        // Give the plane a texture
352        planeEnt->setMaterialName("Examples/DynaTest");
353
354        SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-100,-40,-100));
355        node->attachObject(planeEnt);
356                node->setScale(3.0f, 3.0f, 3.0f);
357
358        // Create objects
359        SceneNode *blaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200,0,50));
360        Entity *ent2 = mSceneMgr->createEntity( "knot", "knot.mesh" );
361                ent2->setMaterialName("Examples/DynaTest4");
362        blaNode->attachObject( ent2 );
363               
364                blaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(200,-90,50));
365        ent2 = mSceneMgr->createEntity( "knot2", "knot.mesh" );
366                ent2->setMaterialName("Examples/DynaTest2");
367        blaNode->attachObject( ent2 );
368        blaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-110,200,50));
369               
370                // Cloaked fish
371        ent2 = mSceneMgr->createEntity( "knot3", "fish.mesh" );
372                ent2->setMaterialName("Examples/DynaTest3");
373                swim = ent2->getAnimationState("swim");
374                swim->setEnabled(true);
375        blaNode->attachObject( ent2 );
376                blaNode->setScale(50.0f, 50.0f, 50.0f);
377               
378               
379                //TextureManager::getSingleton().getByName("RustySteel.jpg");
380               
381               
382                std::stringstream d;
383                d << "HardwarePixelBuffer " << buffer->getWidth() << " " << buffer->getHeight() << " " << buffer->getDepth();
384                LogManager::getSingleton().logMessage(d.str());
385               
386                buffer->lock(HardwareBuffer::HBL_NORMAL);
387                const PixelBox &pb = buffer->getCurrentLock();
388                d.str("");
389                d << "PixelBox " << pb.getWidth() << " " << pb.getHeight() << " " << pb.getDepth() << " " << pb.rowPitch << " " << pb.slicePitch << " " << pb.data << " " << PixelUtil::getFormatName(pb.format);
390                LogManager::getSingleton().logMessage(d.str());
391                buffer->unlock();
392               
393                // show GUI
394                overlay = OverlayManager::getSingleton().getByName("Example/DynTexOverlay");   
395                overlay->show();
396    }
397
398        void destroyScene(void)
399        {
400                // Free resource pointers before shutdown
401                ptex.setNull();
402                buffer.setNull();
403        }
404
405};
406
407#ifdef __cplusplus
408extern "C" {
409#endif
410
411#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
412#define WIN32_LEAN_AND_MEAN
413#include "windows.h"
414
415INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
416#else
417int main(int argc, char *argv[])
418#endif
419{
420    // Create application object
421    DynTexApplication app;
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.