source: OGRE/trunk/ogrenew/Samples/CubeMapping/include/CubeMapping.h @ 657

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

added ogre dependencies and patched ogre sources

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        CubeMapping.h
18    \brief
19        Specialisation of OGRE's framework application to show the
20        cube mapping feature where a wrap-around environment is reflected
21        off of an object.
22                Extended with Perlin noise to show we can.
23*/
24
25#include "ExampleApplication.h"
26
27#define ENTITY_NAME "CubeMappedEntity"
28#define MESH_NAME "CubeMappedMesh"
29
30#define MATERIAL_NAME "Examples/SceneCubeMap2"
31#define SKYBOX_MATERIAL "Examples/SceneSkyBox2"
32
33/* ==================================================================== */
34/*    Perlin Noise data and algorithms - copied from Perlin himself :)  */
35/* ==================================================================== */
36#define lerp(t,a,b) ( (a)+(t)*((b)-(a)) )
37#define fade(t) ( (t)*(t)*(t)*(t)*((t)*((t)*6-15)+10) )
38double grad(int hash, double x, double y, double z) {
39        int h = hash & 15;                      // CONVERT LO 4 BITS OF HASH CODE
40        double u = h<8||h==12||h==13 ? x : y,   // INTO 12 GRADIENT DIRECTIONS.
41                v = h<4||h==12||h==13 ? y : z;
42        return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
43}
44int p[512]={
45        151,160,137,91,90,15,
46        131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
47        190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
48        88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
49        77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
50        102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
51        135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
52        5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
53        223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
54        129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
55        251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
56        49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
57        138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
58
59        151,160,137,91,90,15,
60        131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
61        190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
62        88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
63        77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
64        102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
65        135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
66        5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
67        223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
68        129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
69        251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
70        49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
71        138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
72        };
73
74double noise3(double x, double y, double z) {
75        int X = ((int)floor(x)) & 255,                  // FIND UNIT CUBE THAT
76                Y = ((int)floor(y)) & 255,                  // CONTAINS POINT.
77                Z = ((int)floor(z)) & 255;
78        x -= floor(x);                                // FIND RELATIVE X,Y,Z
79        y -= floor(y);                                // OF POINT IN CUBE.
80        z -= floor(z);
81        double u = fade(x),                                // COMPUTE FADE CURVES
82                v = fade(y),                                // FOR EACH OF X,Y,Z.
83                w = fade(z);
84        int A = p[X  ]+Y, AA = p[A]+Z, AB = p[A+1]+Z,      // HASH COORDINATES OF
85                B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;      // THE 8 CUBE CORNERS,
86
87        return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ),  // AND ADD
88                                                grad(p[BA  ], x-1, y  , z   )), // BLENDED
89                                        lerp(u, grad(p[AB  ], x  , y-1, z   ),  // RESULTS
90                                                grad(p[BB  ], x-1, y-1, z   ))),// FROM  8
91                                lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  // CORNERS
92                                                grad(p[BA+1], x-1, y  , z-1 )), // OF CUBE
93                                        lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
94                                                grad(p[BB+1], x-1, y-1, z-1 ))));
95}
96
97/* ==================================================================== */
98/*                                 Main part                            */
99/* ==================================================================== */
100
101class CubeMapListener : public ExampleFrameListener
102{
103private:
104        // main variables
105        Real tm ;
106        Real timeoutDelay ;
107        SceneManager *mSceneMgr ;
108        SceneNode *objectNode ;
109
110        // mesh-specific data
111        MeshPtr originalMesh ;
112        MeshPtr clonedMesh ;
113
114        Entity *objectEntity ;
115        std::vector<MaterialPtr> clonedMaterials ;
116
117        // configuration
118        Real displacement ;
119        Real density ;
120        Real timeDensity ;
121        bool noiseOn ;
122        size_t currentMeshIndex ;
123        StringVector availableMeshes ;
124        size_t currentLBXindex ;
125        LayerBlendOperationEx currentLBX ;
126        size_t currentCubeMapIndex ;
127        StringVector availableCubeMaps ;
128        MaterialPtr material ;
129       
130        void _updatePositionNoise(int numVertices, float *dstVertices,
131                float *defaultVertices)
132        {
133                for(int i=0;i<3*numVertices;i+=3) {
134                        double n = 1 + displacement * noise3(
135                                defaultVertices[i]/density + tm,
136                                defaultVertices[i+1]/density + tm,
137                                defaultVertices[i+2]/density + tm);
138                        dstVertices[i+0] = defaultVertices[i] * n ;
139                        dstVertices[i+1] = defaultVertices[i+1] * n ;
140                        dstVertices[i+2] = defaultVertices[i+2] * n ;
141                }
142        }
143       
144        float* _normalsGetCleared(VertexData *vertexData)
145        {
146                const VertexElement *normVE = vertexData->
147                        vertexDeclaration->findElementBySemantic(VES_NORMAL);
148                HardwareVertexBufferSharedPtr normHVB = vertexData->
149                        vertexBufferBinding->getBuffer(normVE->getSource());
150                float* normals = (float*) normHVB->lock(0, normHVB->getSizeInBytes(),
151                        HardwareBuffer::HBL_DISCARD);
152                memset(normals, 0, normHVB->getSizeInBytes());
153                return normals;
154        }
155       
156        void _normalsSaveNormalized(VertexData *vertexData, float *normals)
157        {
158                const VertexElement *normVE = vertexData->
159                        vertexDeclaration->findElementBySemantic(VES_NORMAL);
160                HardwareVertexBufferSharedPtr normHVB = vertexData->
161                        vertexBufferBinding->getBuffer(normVE->getSource());
162                size_t numVertices = normHVB->getNumVertices();
163                for(size_t i=0;i<numVertices;i++, normals+=3) {
164                        Vector3 n(normals[0], normals[1], normals[2]);
165                        n.normalise();
166                        normals[0] = n.x ;
167                        normals[1] = n.y ;
168                        normals[2] = n.z ;
169                }
170                normHVB->unlock();
171        }
172       
173        void _updateVertexDataNoiseAndNormals(
174                        VertexData *dstData,
175                        VertexData *orgData,
176                        IndexData *indexData,
177                        float *normals)
178        {
179                size_t i ;
180               
181                // Find destination vertex buffer
182                const VertexElement *dstVEPos = dstData->
183                        vertexDeclaration->findElementBySemantic(VES_POSITION);
184                HardwareVertexBufferSharedPtr dstHVBPos = dstData->
185                        vertexBufferBinding->getBuffer(dstVEPos->getSource());
186                // Find source vertex buffer
187                const VertexElement *orgVEPos = orgData->
188                        vertexDeclaration->findElementBySemantic(VES_POSITION);
189                HardwareVertexBufferSharedPtr orgHVBPos = orgData->
190                        vertexBufferBinding->getBuffer(orgVEPos->getSource());
191                // Lock these buffers
192                float *dstDataPos = (float*) dstHVBPos->lock(0, dstHVBPos->getSizeInBytes(),
193                        HardwareBuffer::HBL_DISCARD);
194                float *orgDataPos = (float*) orgHVBPos->lock(0, orgHVBPos->getSizeInBytes(),
195                        HardwareBuffer::HBL_READ_ONLY);
196                // make noise
197                size_t numVertices = orgHVBPos->getNumVertices();
198                for(i=0;i<3*numVertices;i+=3) {
199                        double n = 1 + displacement * noise3(
200                                orgDataPos[i]/density + tm,
201                                orgDataPos[i+1]/density + tm,
202                                orgDataPos[i+2]/density + tm);
203                        dstDataPos[i+0] = orgDataPos[i] * n ;
204                        dstDataPos[i+1] = orgDataPos[i+1] * n ;
205                        dstDataPos[i+2] = orgDataPos[i+2] * n ;
206                }
207                // Unlock original position buffer
208                orgHVBPos->unlock();
209
210                // calculate normals
211                HardwareIndexBufferSharedPtr indexHB = indexData->indexBuffer ;
212                unsigned short * vertexIndices = (unsigned short*) indexHB->lock(
213                        0, indexHB->getSizeInBytes(), HardwareBuffer::HBL_READ_ONLY);
214                size_t numFaces = indexData->indexCount / 3 ;
215                for(i=0 ; i<numFaces ; i++, vertexIndices+=3) {
216                        //~ int p0 = 0;
217                        //~ int p1 = 1;
218                        //~ int p2 = 2;
219                        int p0 = vertexIndices[0] ;
220                        int p1 = vertexIndices[1] ;
221                        int p2 = vertexIndices[2] ;
222
223                        //~ Vector3 v0(10,0,20);
224                        //~ Vector3 v1(30,0,20);
225                        //~ Vector3 v2(20,-1,50);
226                        Vector3 v0(dstDataPos[3*p0], dstDataPos[3*p0+1], dstDataPos[3*p0+2]);
227                        Vector3 v1(dstDataPos[3*p1], dstDataPos[3*p1+1], dstDataPos[3*p1+2]);
228                        Vector3 v2(dstDataPos[3*p2], dstDataPos[3*p2+1], dstDataPos[3*p2+2]);
229
230                        Vector3 diff1 = v1 - v2 ;
231                        Vector3 diff2 = v1 - v0 ;
232                        Vector3 fn = diff1.crossProduct(diff2);
233#define _ADD_VECTOR_TO_REALS(ptr,vec) { *(ptr)+=vec.x; *((ptr)+1)+=vec.y; *((ptr)+2)+=vec.z; }
234                        _ADD_VECTOR_TO_REALS(normals+3*p0, fn);
235                        _ADD_VECTOR_TO_REALS(normals+3*p1, fn);
236                        _ADD_VECTOR_TO_REALS(normals+3*p2, fn);
237#undef _ADD_VECTOR_TO_REALS
238                }
239                indexHB->unlock();
240
241                // Unlock destination position buffer
242                dstHVBPos->unlock();
243        }
244
245        void updateNoise()
246        {
247                float *sharedNormals = 0 ;
248                for(int m=0;m<clonedMesh->getNumSubMeshes();m++) { // for each subMesh
249                        SubMesh *subMesh = clonedMesh->getSubMesh(m);
250                        SubMesh *orgSubMesh = originalMesh->getSubMesh(m);
251                        if (subMesh->useSharedVertices) {
252                                if (!sharedNormals) { // first of shared
253                                        sharedNormals = _normalsGetCleared(clonedMesh->sharedVertexData);
254                                }
255                                _updateVertexDataNoiseAndNormals(
256                                        clonedMesh->sharedVertexData,
257                                        originalMesh->sharedVertexData,
258                                        subMesh->indexData,
259                                        sharedNormals);
260                        } else {
261                                float* normals = _normalsGetCleared(subMesh->vertexData);
262                                _updateVertexDataNoiseAndNormals(
263                                        subMesh->vertexData,
264                                        orgSubMesh->vertexData,
265                                        subMesh->indexData,
266                                        normals);
267                                _normalsSaveNormalized(subMesh->vertexData, normals);
268                        }
269                }
270                if (sharedNormals) {
271                        _normalsSaveNormalized(clonedMesh->sharedVertexData, sharedNormals);
272                }
273        }
274
275        void clearEntity()
276        {
277                // delete cloned materials
278                for(unsigned int m=0;m<clonedMaterials.size();m++) {
279                        MaterialManager::getSingleton().remove(clonedMaterials[m]->getHandle()) ;
280                }
281                clonedMaterials.clear();
282               
283                // detach and destroy entity
284                objectNode->detachAllObjects();
285                mSceneMgr->removeEntity(ENTITY_NAME);
286               
287                // destroy mesh as well, to reset its geometry
288                MeshManager::getSingleton().remove(clonedMesh->getHandle());
289               
290                objectEntity = 0 ;
291        }
292       
293        VertexData* _prepareVertexData(VertexData *orgVD)
294        {
295                if (!orgVD)
296                        return 0 ;
297
298        // Hacky bit: reorganise vertex buffers to a buffer-per-element
299        // Since this demo was written a while back to assume that
300        // Really this demo should be replaced with a vertex program noise
301        // distortion, but left the software for now since it's nice for older
302        // card owners
303        VertexDeclaration* newDecl = orgVD->vertexDeclaration->clone();
304        const VertexDeclaration::VertexElementList& elems = newDecl->getElements();
305        VertexDeclaration::VertexElementList::const_iterator di;
306        unsigned short buf = 0;
307        for (di = elems.begin(); di != elems.end(); ++di)
308        {
309            newDecl->modifyElement(buf, buf, 0, di->getType(), di->getSemantic(), di->getIndex());
310            buf++;
311        }
312        orgVD->reorganiseBuffers(newDecl);
313
314
315                VertexData* newVD = new VertexData();
316                // copy things that do not change
317                newVD->vertexCount = orgVD->vertexCount ;
318                newVD->vertexStart = orgVD->vertexStart ;
319                // now copy vertex buffers, looking in the declarations
320                VertexDeclaration* newVDecl = newVD->vertexDeclaration ;
321                VertexBufferBinding* newVBind = newVD->vertexBufferBinding ;
322                // note: I assume various semantics are not shared among buffers
323                const VertexDeclaration::VertexElementList& orgVEL = orgVD->vertexDeclaration->getElements() ;
324                VertexDeclaration::VertexElementList::const_iterator veli, velend;
325                velend = orgVEL.end();
326                // For each declaration, prepare buffer
327                for( veli = orgVEL.begin() ; veli != velend ; ++veli)
328                {
329                        VertexElementSemantic ves = (*veli).getSemantic();
330                        int source = (*veli).getSource() ;
331                        HardwareVertexBufferSharedPtr orgBuf = orgVD->vertexBufferBinding->
332                                getBuffer( source );
333                        // check usage for the new buffer
334                        bool dynamic = false ;
335                        switch(ves) {
336                                case VES_NORMAL :
337                                case VES_POSITION :
338                                        dynamic = true ;
339                                        break ;
340                                case VES_BLEND_INDICES :
341                                case VES_BLEND_WEIGHTS :
342                                case VES_DIFFUSE :
343                                case VES_SPECULAR :
344                                case VES_TEXTURE_COORDINATES :
345                                default :
346                                        dynamic = false ;
347                                        break ;
348                        }
349                        if (dynamic) { // create a new dynamic buffer with write access
350                                HardwareVertexBufferSharedPtr newBuf =
351                                        HardwareBufferManager::getSingleton().createVertexBuffer(
352                                                orgBuf->getVertexSize(), orgBuf->getNumVertices(),
353                                                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,
354                                                //~ HardwareBuffer::HBU_DYNAMIC,
355                                                true
356                                                //~ false
357                                                );
358                                newBuf->copyData(*orgBuf, 0, 0, orgBuf->getSizeInBytes(), true);
359                                newVBind->setBinding( source, newBuf );
360                        } else { // use the old one
361                                newVBind->setBinding( source, orgBuf );
362                        }
363                        // add element for declaration
364                        newVDecl->addElement(source, (*veli).getOffset(), (*veli).getType(),
365                                ves, (*veli).getIndex());
366                }
367                return newVD;
368        }
369       
370        void prepareClonedMesh()
371        {
372                // we create new Mesh based on the original one, but changing
373                // HBU flags (inside _prepareVertexData)
374                clonedMesh = MeshManager::getSingleton().createManual(MESH_NAME,
375            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
376                clonedMesh->_setBounds(originalMesh->getBounds());
377                clonedMesh->_setBoundingSphereRadius(originalMesh->getBoundingSphereRadius());
378                //~ if (originalMesh->sharedVertexData)
379                        //~ clonedMesh->sharedVertexData = originalMesh->sharedVertexData->clone();
380                clonedMesh->sharedVertexData =
381                        _prepareVertexData(originalMesh->sharedVertexData);
382                for(int sm=0;sm<originalMesh->getNumSubMeshes();sm++) {
383                        SubMesh *orgSM = originalMesh->getSubMesh(sm);
384                        SubMesh *newSM = clonedMesh->createSubMesh();
385                        if (orgSM->isMatInitialised()) {
386                                newSM->setMaterialName(orgSM->getMaterialName());
387                        }
388                        newSM->useSharedVertices = orgSM->useSharedVertices ;
389                        // prepare vertex data
390                        newSM->vertexData = _prepareVertexData(orgSM->vertexData);
391                        // reuse index data
392                        newSM->indexData->indexBuffer = orgSM->indexData->indexBuffer ;
393                        newSM->indexData->indexStart = orgSM->indexData->indexStart ;
394                        newSM->indexData->indexCount = orgSM->indexData->indexCount ;
395                }
396        }
397
398        void prepareEntity(const String& meshName)
399        {
400                if (objectEntity) {
401                        clearEntity();
402                }
403               
404                // load mesh if necessary - note, I assume this is the only point
405                // Mesh can get loaded, since I want to make sure about its HBU etc.
406                originalMesh = MeshManager::getSingleton().getByName(meshName);
407                if (originalMesh.isNull()) {
408                        originalMesh = MeshManager::getSingleton().load(meshName,
409                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
410                                HardwareBuffer::HBU_STATIC_WRITE_ONLY,
411                                HardwareBuffer::HBU_STATIC_WRITE_ONLY,
412                                true, true); //so we can still read it
413                        if (originalMesh.isNull()) {
414                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
415                                        "Can't find a mesh: '"+meshName+"'",
416                                        "CubeMapListener::prepareEntity");
417                        }
418                }
419               
420               
421                prepareClonedMesh();
422
423        // create an entity based on cloned mesh
424                objectEntity = mSceneMgr->createEntity( ENTITY_NAME, MESH_NAME);
425        objectEntity->setMaterialName( material->getName() );
426        Pass* pass = material->getTechnique(0)->getPass(0);
427               
428                // go through subentities and set materials as required
429                for(int m=0;m<clonedMesh->getNumSubMeshes();m++) {
430                        SubMesh *subMesh = clonedMesh->getSubMesh(m);
431                        SubEntity *subEntity = objectEntity->getSubEntity(m);
432                        // check if this submesh has material set
433                        if (subMesh->isMatInitialised()) {
434                                const String& matName = subMesh->getMaterialName();
435                                MaterialPtr subMat =
436                    MaterialManager::getSingleton().getByName(matName);
437                                if (!subMat.isNull()) { // clone material, add layers from global material
438                                        subMat->load();
439                                        MaterialPtr cloned = subMat->clone(
440                                                "CubeMapTempMaterial#"+StringConverter::toString(m));
441                    Pass* clonedPass = cloned->getTechnique(0)->getPass(0);
442                                        // can't help it - have to do it :)
443                                        if (meshName=="knot.mesh") {
444                                                for(size_t tl=0;tl<clonedPass->getNumTextureUnitStates();tl++) {
445                                                        TextureUnitState *tlayer = clonedPass->getTextureUnitState(tl);
446                                                        tlayer->setScrollAnimation(1.0 , 0);
447                                                }
448                                        }
449                                        // add layers
450                                        for(size_t tl=0;tl<pass->getNumTextureUnitStates();tl++) {
451                                                TextureUnitState *orgTL = pass->getTextureUnitState(tl);
452                                                TextureUnitState *newTL = clonedPass->createTextureUnitState(
453                                                        orgTL->getTextureName());
454                                                *newTL = *orgTL ;
455                                                newTL->setColourOperationEx(currentLBX);
456                                        }
457                                        subEntity->setMaterialName(cloned->getName());
458                                        clonedMaterials.push_back(cloned);
459                                }
460                        }
461                }
462
463                objectNode->attachObject(objectEntity);
464               
465                // update noise to avoid one frame w/o noise
466                if (noiseOn)
467                        updateNoise();
468        }
469       
470        void updateInfoDisplacement()
471        {
472                OverlayManager::getSingleton().getOverlayElement("Example/CubeMapping/Displacement")
473                        ->setCaption("[1/2] Displacement: "+StringConverter::toString(displacement));           
474        }
475        void updateInfoDensity()
476        {
477                OverlayManager::getSingleton().getOverlayElement("Example/CubeMapping/Density")
478                        ->setCaption("[3/4] Noise density: "+StringConverter::toString(density));               
479        }
480        void updateInfoTimeDensity()
481        {
482                OverlayManager::getSingleton().getOverlayElement("Example/CubeMapping/TimeDensity")
483                        ->setCaption("[5/6] Time density: "+StringConverter::toString(timeDensity));
484        }
485        void setObject()
486        {
487                currentMeshIndex %= availableMeshes.size();
488                const String& meshName = availableMeshes[currentMeshIndex];
489                printf("Switching to object: %s\n", meshName.c_str());
490                prepareEntity(meshName);
491                OverlayManager::getSingleton().getOverlayElement("Example/CubeMapping/Object")
492                        ->setCaption("[O] Object: "+meshName);
493        }
494        void setNoiseOn()
495        {
496                OverlayManager::getSingleton().getOverlayElement("Example/CubeMapping/Noise")
497                        ->setCaption(String("[N] Noise: ")+ ((noiseOn)?"on":"off") );           
498        }
499        void setMaterialBlending()
500        {
501                currentLBXindex %= 5;
502                String lbxName ;
503#define _LAZYERU_(a,b,c) case a : currentLBX = b ; lbxName = c ; break ;
504                switch (currentLBXindex) {
505                        _LAZYERU_(0, LBX_ADD, "ADD")
506                        _LAZYERU_(1, LBX_MODULATE, "MODULATE")
507                        _LAZYERU_(2, LBX_MODULATE_X2, "MODULATE X2")
508                        _LAZYERU_(3, LBX_MODULATE_X4, "MODULATE X4")
509                        _LAZYERU_(4, LBX_SOURCE1, "SOURCE1")
510                        _LAZYERU_(5, LBX_SOURCE2, "SOURCE2")
511                        // more?
512                }
513#undef _LAZYERU_               
514                // reset entities, materials and so on
515                prepareEntity(availableMeshes[currentMeshIndex]);
516                OverlayManager::getSingleton().getOverlayElement("Example/CubeMapping/Material")
517                        ->setCaption("[M] Material blend:"+lbxName);
518        }
519        void setCubeMap()
520        {
521                currentCubeMapIndex %= availableCubeMaps.size();
522                unsigned int i ;
523                String cubeMapName = availableCubeMaps[currentCubeMapIndex];
524                Pass *pass = material->getTechnique(0)->getPass(0);
525                for(i=0;i<(int)pass->getTextureUnitState(0)->getNumFrames();i++) {
526                        String oldTexName = pass->getTextureUnitState(0)->
527                                getFrameTextureName(i);
528                        TexturePtr oldTex = TextureManager::getSingleton().getByName(oldTexName);
529                        TextureManager::getSingleton().remove(oldTexName);
530                }
531                pass->getTextureUnitState(0)->setCubicTextureName(cubeMapName, true);
532               
533                MaterialPtr mat2 =
534                        MaterialManager::getSingleton().getByName(SKYBOX_MATERIAL);
535        Pass* pass2 = mat2->getTechnique(0)->getPass(0);
536                for(i=0;i<(int)pass2->getTextureUnitState(0)->getNumFrames();i++) {
537                        String oldTexName = pass2->getTextureUnitState(0)->
538                                getFrameTextureName(i);
539                        TexturePtr oldTex = TextureManager::getSingleton().getByName(oldTexName);
540                        TextureManager::getSingleton().remove(oldTexName);
541                }
542                pass2->getTextureUnitState(0)->setCubicTextureName(cubeMapName, false);
543
544                mSceneMgr->setSkyBox(true, SKYBOX_MATERIAL );
545
546                prepareEntity(availableMeshes[currentMeshIndex]);
547                OverlayManager::getSingleton().getOverlayElement("Example/CubeMapping/CubeMap")
548                        ->setCaption("[C] CubeMap:"+cubeMapName);
549        }
550       
551#define RANDOM_FROM(a,b) (((float)(rand() & 65535)) / 65536.0f * ((b)-(a)) + (a))
552        void goRandom()
553        {
554                displacement = RANDOM_FROM(0.0f, 1.0f);
555                updateInfoDisplacement();
556
557                density = RANDOM_FROM(1.0f, 300.0f);
558                updateInfoDensity();
559               
560                timeDensity = RANDOM_FROM(1.0f, 10.0f);
561                updateInfoTimeDensity();
562        }
563       
564#define MEDIA_FILENAME "media.cfg"
565        void readConfig()
566        {
567        std::string media_filename(MEDIA_FILENAME);
568#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
569        media_filename = bundlePath() + "/Contents/Resources/" + media_filename;
570#endif
571                ConfigFile cfg;
572                cfg.load( media_filename );
573                availableMeshes = cfg.getMultiSetting("Mesh");
574                availableCubeMaps = cfg.getMultiSetting("CubeMap");
575        }
576       
577public:
578    CubeMapListener(RenderWindow* win, Camera* cam,
579                        SceneManager *sceneMgr, SceneNode *objectNode)
580        : ExampleFrameListener(win, cam)
581    {
582                this->mSceneMgr = sceneMgr ;
583                this->objectNode = objectNode ;
584
585                tm = 0 ;
586                timeoutDelay = 0 ;
587                displacement = 0.1f;
588                density = 50.0f;
589                timeDensity = 5.0f;
590                objectEntity = 0 ;
591               
592                material = MaterialManager::getSingleton().getByName(MATERIAL_NAME);
593
594                if (material.isNull()) {
595                        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND,
596                                "Can't find material: "+String(MATERIAL_NAME),
597                                "CubeMapListener::CubeMapListener");
598                }
599               
600                readConfig();
601
602                currentMeshIndex = 0 ;
603                setObject();
604               
605                currentLBXindex = 0 ;
606                setMaterialBlending();
607               
608                currentCubeMapIndex = 0 ;
609                setCubeMap();
610               
611                noiseOn = true ;
612                setNoiseOn();
613
614                updateInfoDisplacement();
615                updateInfoDensity();
616                updateInfoTimeDensity();
617    }
618    virtual bool frameStarted(const FrameEvent& evt)
619    {
620                tm += evt.timeSinceLastFrame / timeDensity ;
621
622                if (noiseOn)
623                        updateNoise();
624
625        // Call default
626        return ExampleFrameListener::frameStarted(evt);
627    }
628        virtual bool processUnbufferedKeyInput(const FrameEvent& evt)
629    {
630                bool retval = ExampleFrameListener::processUnbufferedKeyInput(evt);
631
632                Real changeSpeed = evt.timeSinceLastFrame ;
633               
634                // adjust keyboard speed with SHIFT (increase) and CONTROL (decrease)
635                if (mInputDevice->isKeyDown(KC_LSHIFT) || mInputDevice->isKeyDown(KC_RSHIFT)) {
636                        changeSpeed *= 10.0f ;
637                }
638                if (mInputDevice->isKeyDown(KC_LCONTROL)) {
639                        changeSpeed /= 10.0f ;
640                }
641               
642#define ADJUST_RANGE(_value,_keyPlus,_keyMinus,_minVal,_maxVal,_change,_macro) {\
643        if (mInputDevice->isKeyDown(_keyPlus)) \
644                { _value+=_change ; if (_value>=_maxVal) _value = _maxVal ; _macro ; } ; \
645        if (mInputDevice->isKeyDown(_keyMinus)) \
646                { _value-=_change; if (_value<=_minVal) _value = _minVal ; _macro ; } ; \
647}
648               
649                ADJUST_RANGE(displacement, KC_2, KC_1, -2, 2, 0.1f*changeSpeed, updateInfoDisplacement()) ;
650
651                ADJUST_RANGE(density, KC_4, KC_3, 0.1, 500, 10.0f*changeSpeed, updateInfoDensity()) ;
652
653                ADJUST_RANGE(timeDensity, KC_6, KC_5, 1, 10, 1.0f*changeSpeed, updateInfoTimeDensity()) ;
654
655#define SWITCH_VALUE(_key,_timeDelay, _macro) { \
656                if (mInputDevice->isKeyDown(_key) && timeoutDelay==0) { \
657                        timeoutDelay = _timeDelay ; _macro ;} }
658       
659                timeoutDelay-=evt.timeSinceLastFrame ;
660                if (timeoutDelay<=0)
661                        timeoutDelay = 0;
662
663                SWITCH_VALUE(KC_O, 0.5f, currentMeshIndex++ ; setObject());
664
665                SWITCH_VALUE(KC_N, 0.5f, noiseOn = !noiseOn ; setNoiseOn());
666
667                SWITCH_VALUE(KC_M, 0.5f, currentLBXindex++ ; setMaterialBlending());
668
669                SWITCH_VALUE(KC_C, 0.5f, currentCubeMapIndex++ ; setCubeMap());
670               
671                SWITCH_VALUE(KC_SPACE, 0.5f, goRandom());
672
673                return retval ;
674        }
675} ;
676
677class CubeMapApplication : public ExampleApplication
678{
679public:
680    CubeMapApplication() {}
681
682protected:
683        SceneNode *objectNode;
684
685    // Just override the mandatory create scene method
686    void createScene(void)
687    {
688        // First check that cube mapping is supported
689        if (!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_CUBEMAPPING))
690        {
691            OGRE_EXCEPT(1, "Your card does not support cube mapping, so cannot "
692                "run this demo. Sorry!",
693                "CubeMapApplication::createScene");
694        }
695
696        // Set ambient light
697        mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
698
699        // Create a skybox
700        mSceneMgr->setSkyBox(true, SKYBOX_MATERIAL );
701
702        // Create a light
703        Light* l = mSceneMgr->createLight("MainLight");
704        // Accept default settings: point light, white diffuse, just set position
705        // NB I could attach the light to a SceneNode if I wanted it to move automatically with
706        //  other objects, but I don't
707        l->setPosition(20,80,50);
708
709        objectNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
710
711                // show overlay
712                Overlay* overlay = OverlayManager::getSingleton().getByName("Example/CubeMappingOverlay");   
713                overlay->show();
714        }
715
716    void createFrameListener(void)
717    {
718        mFrameListener= new CubeMapListener(mWindow, mCamera, mSceneMgr, objectNode);
719        mRoot->addFrameListener(mFrameListener);
720    }
721};
Note: See TracBrowser for help on using the repository browser.