Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation3/src/libraries/tools/bsp/OgreFramework.cpp @ 7142

Last change on this file since 7142 was 7073, checked in by landauf, 14 years ago

merged fps branch to presentation3

  • Property svn:eol-style set to native
File size: 231.2 KB
Line 
1//|||||||||||||||||||||||||||||||||||||||||||||||
2/*
3===========================================================================
4Copyright (C) 2010 Jared Prince
5
6This file is part of bsp-renderer source code.
7
8bsp-renderer is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
12
13bsp-renderer is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
20
21*/
22
23#include "OgreFramework.hpp"
24
25#include <io.h>
26#include <fcntl.h>      /* Needed only for _O_RDWR definition */
27#include <sys/stat.h>
28#include "Q3Map_misc.h" // safe pointer deletes
29
30
31
32//|||||||||||||||||||||||||||||||||||||||||||||||
33
34using namespace Ogre;
35
36//|||||||||||||||||||||||||||||||||||||||||||||||
37
38template<> OgreFramework* Ogre::Singleton<class OgreFramework>::ms_Singleton = 0;
39
40
41
42OgreFramework::OgreFramework()
43{
44
45        m_nNewCount=0 ;
46        ZeroMemory((void*)m_nNewCheck, sizeof(m_nNewCheck)) ;
47
48        m_MoveSpeed                     = 0.1;
49        m_RotateSpeed           = 0.3;
50
51        m_bShutDownOgre         = false;
52        m_iNumScreenShots       = 0;
53
54        m_pRoot                         = 0;
55        m_pSceneMgr                     = 0;
56        m_pRenderWnd            = 0;
57        m_pCamera                       = 0;
58        m_pViewport                     = 0;
59        m_pLog                          = 0;
60        m_pTimer                        = 0;
61
62        m_pInputMgr                     = 0;
63        m_pKeyboard                     = 0;
64        m_pMouse                        = 0;
65
66        m_pDebugOverlay         = 0;
67        m_pInfoOverlay          = 0;
68
69        //mRawFileManager=NULL ; // pointer for text file resource handler
70        m_pRawBspFile=NULL ;
71        m_bRawBspFileIsLoaded=false ;
72
73        // pointers for q3map stuff
74        m_TempMem=NULL ;
75        m_Q3Map=NULL ;
76       
77
78        m_pZoneMO=NULL ;
79        m_pZoneMesh=NULL ;
80        m_pZoneEntity=NULL ;
81        m_pZoneEntityMaterialType=NULL ;
82
83        int nPTex=0 ;
84        for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
85        {
86                m_pZoneEntityMaterial_Base[nPTex]=NULL ;
87                m_pZoneEntityMaterial_Fast[nPTex]=NULL ;
88        }
89
90        m_pZoneEntityMaterial_Black=NULL ;
91
92        m_pZoneEntityMaterial_DfShColour=NULL ;
93        m_pZoneEntityMaterial_Shadow=NULL ;
94        m_pZoneEntityMaterial_ShadeFront=NULL ;
95        m_pZoneEntityMaterial_ShadeBack=NULL ;
96        m_pZoneEntityMaterial_DfShPosition=NULL ;
97        m_pZoneEntityMaterial_DfShDiffuse=NULL ;
98        //m_pZoneEntityMaterial_DSNormal=NULL ;
99        m_pZoneEntityMaterial_DfShFuncTNB=NULL ;
100        m_pZoneEntityMaterial_DfShSpecular=NULL ;
101        m_pZoneEntityMaterial_DfShEmissive=NULL ;
102        //m_pZoneEntityMaterial_DfShData=NULL ;
103        m_pZoneEntityMaterial_DfShMix=NULL ;
104
105
106        /////////////////////////////////
107
108        m_nMaxEntity=0 ;
109        m_pEntityInfo=NULL ;
110        m_nMaxVisibleEntity=0 ;
111        m_pVisibleEntity=NULL ;
112        m_nMaxFrustumEntity=0 ;
113        m_pFrustumEntity=NULL ;
114
115
116        // debug light meshes
117        m_pLightMO=NULL ;
118        m_pPortalMO=NULL ;
119        m_pPortalNode=NULL ;
120
121        m_pCubeNode                     = 0;
122        m_pCubeEntity           = 0;
123
124        nMap=2 ;
125        m_nLoadToggle=0 ;
126        m_nJumpToggle=0 ;
127        m_nJumpVal=-1 ;
128
129       
130
131
132
133        m_nDebugA=0 ;
134        m_nDebugB=0 ;
135        m_nDebugC=0 ;
136        m_nRecurseCount=0 ;
137
138
139        m_nDebugLightBox=0 ;
140        m_nZoneCullingActive=1 ;
141       
142        m_nPortalDebug=0 ;
143        m_nPortalToggle=0 ;
144        m_nPortalState=1 ;
145
146        m_nKeyDown_Shift=0 ;
147        m_nKeyDown_Ctrl=0 ;
148
149
150
151        m_flStereoFrustumTweak=0.0f ;
152
153        m_nGoggleMode=GOGGLE_MODE_OFF ;
154        m_pGoggleL=NULL ;
155        m_pGoggleR=NULL ;
156        m_pNodeGoggles=NULL ;
157
158        // default goggle settings
159        m_flGoggleZPos=-250 ;
160        m_flGoggleXGap=0.0 ;
161        m_flGoggleXScale=1.0 ;
162        m_flGoggleYScale=1.0 ;
163
164        m_nMapLoaded=0 ;
165
166        m_nTime=0 ;
167
168       
169
170        ZeroMemory((void*)m_nFrameTime, sizeof(m_nFrameTime)) ;
171        m_nFrame=0 ;
172        m_nGotInput=0 ;
173
174        ZeroMemory((void*)m_nKeyToggle, sizeof(m_nKeyToggle)) ;
175
176//      OFBug.LogInit() ;
177
178        m_nRTTAssetsExist=0 ;
179       
180        m_nToggle=0 ;
181       
182        m_nFlashLight=0 ;
183
184
185
186        m_flAspectRatio=1.0f ;
187        m_flFOV=60.0f ;
188
189        // whether we are drawing the render or one of the info screens, such as wireframe or one of the deferred screens
190        m_nDisplayInfoMode=0 ;
191
192        m_nSpeedRender=0 ;
193
194        //m_nRenderHDR=0 ;
195
196        srand( (unsigned)time( NULL ) );
197
198}
199
200//|||||||||||||||||||||||||||||||||||||||||||||||
201
202OgreFramework::~OgreFramework()
203{
204//      OFBug.LogSave("OFBug.txt") ;
205
206        /*
207        char chMessage[1024] ;
208        int nFrame=0 ;
209        m_pLog->logMessage("   ");
210        m_pLog->logMessage("   Mircosecs:   Physics    Render    Ideal   Average    Pragma     Total");
211        m_pLog->logMessage("   ----------------------------------------");
212        for(nFrame=0 ; nFrame<MAXFRAME ; nFrame++)
213        {
214                //sprintf(chMessage, "   Frame %3i:  %8i  %8i  %8i", nFrame, m_nFrameTime[nFrame][0], m_nFrameTime[nFrame][1], m_nFrameTime[nFrame][2]) ;
215                sprintf(chMessage, "  Frame %3i:  %8i  %8i  %8i  %8i  %8i  %8i", nFrame, m_nFrameTime[nFrame][0], m_nFrameTime[nFrame][1], m_nFrameTime[nFrame][2], m_nFrameTime[nFrame][3], m_nFrameTime[nFrame][4], m_nFrameTime[nFrame][5]) ;
216                m_pLog->logMessage(chMessage);
217        }
218        m_pLog->logMessage("");
219        */
220
221        //UnloadMap(true) ;
222
223
224        //mRawFileManager->~RawFileManager() ; //!! is this correct? 
225        //DELETE_POINTER( mRawFileManager ) ;
226
227
228        DELETE_POINTER( m_pKeyboard );
229        DELETE_POINTER( m_pMouse );
230        OIS::InputManager::destroyInputSystem(m_pInputMgr);
231
232       
233        //DELETE_POINTER( m_pRoot );
234        //delete m_pRoot ;
235}
236
237
238
239//|||||||||||||||||||||||||||||||||||||||||||||||
240
241void OgreFramework::initOgre(Ogre::String wndTitle, OIS::KeyListener *pKeyListener, OIS::MouseListener *pMouseListener)
242{
243//      Ogre::LogManager* logMgr = new Ogre::LogManager();
244       
245        m_pLog = Ogre::LogManager::getSingleton().createLog("OgreLogfile.log", true, true, false);
246        m_pLog->setDebugOutputEnabled(true);
247       
248        m_pRoot = new Ogre::Root();
249
250        // our manager for the raw bsp
251        //mRawFileManager = new RawFileManager();
252        //ResourceGroupManager::getSingleton().createResourceGroup("Raw Bsp") ;
253
254       
255
256
257        m_pRoot->showConfigDialog();
258
259        if (!m_pRoot->restoreConfig() && !m_pRoot->showConfigDialog())
260        {
261                throw Exception(52, "User canceled the config dialog!", "Application::setupRenderSystem()");
262        }
263
264       
265        m_pRenderWnd = m_pRoot->initialise(true, wndTitle);
266
267        m_pSceneMgr = m_pRoot->createSceneManager(ST_GENERIC, "SceneManager");
268        m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.0, 0.0, 0.0));
269
270
271        m_pCamera = m_pSceneMgr->createCamera("Camera");
272        m_pCamera->setPosition(Vector3(0, 0, 0));
273        m_pCamera->lookAt(Vector3(0,0,0));
274        m_pCamera->setNearClipDistance(NEARCLIP);
275  m_pCamera->setFarClipDistance(FARCLIP);
276        m_pCamera->setFOVy( Degree(m_flFOV) ) ;
277
278        m_pCameraCopy = m_pSceneMgr->createCamera("CameraCopy");
279        m_pCameraCopy->setNearClipDistance(NEARCLIP);
280  m_pCameraCopy->setFarClipDistance(FARCLIP);
281
282
283       
284        m_pCameraNoJitter = m_pSceneMgr->createCamera("CameraNoJitter");
285
286
287       
288       
289
290        m_pViewport = m_pRenderWnd->addViewport(m_pCamera);
291
292        m_pViewport->setBackgroundColour(ColourValue(0.5, 0.5, 0.5, 1.0));
293
294        m_flAspectRatio= (float)m_pViewport->getActualWidth() / (float)m_pViewport->getActualHeight() ;
295
296        m_flGoggleAspectRatio=m_flAspectRatio ; // we use this to set up the Goggles
297        m_pCamera->setAspectRatio( Real(m_flAspectRatio) );
298        m_pCameraCopy->setAspectRatio(  Real(m_flAspectRatio) );
299       
300        m_pViewport->setCamera(m_pCamera);
301        m_pViewport->setClearEveryFrame(true);//, FBT_DEPTH) ;
302
303       
304
305
306        unsigned long hWnd = 0;
307    OIS::ParamList paramList;
308    m_pRenderWnd->getCustomAttribute("WINDOW", &hWnd);
309
310        paramList.insert(OIS::ParamList::value_type("WINDOW", Ogre::StringConverter::toString(hWnd)));
311
312        m_pInputMgr = OIS::InputManager::createInputSystem(paramList);
313
314  m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputMgr->createInputObject(OIS::OISKeyboard, true));
315        m_pMouse = static_cast<OIS::Mouse*>(m_pInputMgr->createInputObject(OIS::OISMouse, true));
316
317   
318        m_pMouse->getMouseState().height = m_pRenderWnd->getHeight();
319        m_pMouse->getMouseState().width  = m_pRenderWnd->getWidth();
320
321        if(pKeyListener == 0)
322                m_pKeyboard->setEventCallback(this);
323        else
324                m_pKeyboard->setEventCallback(pKeyListener);
325
326        if(pMouseListener == 0)
327                m_pMouse->setEventCallback(this);
328        else
329                m_pMouse->setEventCallback(pMouseListener);
330
331        SetupResourceLocations() ;
332
333        // D3D or OGL
334        if (Root::getSingleton().getRenderSystem()->getName().find("GL") != String::npos)
335                m_IsOpenGL = true;
336        else
337                m_IsOpenGL = false;
338
339
340
341
342
343        m_pTimer = new Ogre::Timer();
344        m_pTimer->reset();
345       
346
347       
348
349
350        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
351
352        Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
353       
354
355       
356
357       
358
359        m_nRTTWidth = m_pRenderWnd->getWidth() ;
360        m_nRTTHeight = m_pRenderWnd->getHeight() ;
361       
362
363        m_pRenderWnd->addListener(this);
364        m_pRenderWnd->setActive(true);
365
366
367        // default values, may be changed from the bzn.cfg file
368        m_nShadowMapSize=512 ;
369        m_nShadowRGBSize=512 ;
370        m_nColouredShadow=1 ;
371        m_nRenderHDR=1 ;
372        m_nMaxGPUQuery=1 ;
373       
374}
375
376void OgreFramework::FinalShutdown(void)
377{
378
379        //Ogre::ResourceGroupManager::getSingleton().shutdownAll();
380        //m_pRoot->destroySceneManager(m_pSceneMgr);
381        //m_pRoot->shutdown() ;
382        delete m_pRoot ;
383}
384
385void OgreFramework::AdditionalSetup()
386{
387
388        CreateRTTAssets() ;
389}
390
391
392void OgreFramework::SetupResourceLocations()
393{
394        Ogre::String secName, typeName, archName;
395        Ogre::ConfigFile cf;
396    cf.load("resources.cfg");
397
398        Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
399    while (seci.hasMoreElements())
400    {
401        secName = seci.peekNextKey();
402                Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
403        Ogre::ConfigFile::SettingsMultiMap::iterator i;
404        for (i = settings->begin(); i != settings->end(); ++i)
405        {
406            typeName = i->first;
407            archName = i->second;
408            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
409        }
410    }
411        Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
412}
413
414
415// create the textures, materials and miniscreens needed for the RTTs
416void OgreFramework::CreateRTTAssets()
417{
418       
419
420        // I originally had problems with OpenGL 2.1.1 suddenly running very slow if I had more than 12 RTT surfaces
421        // but that issue seems to have vanished, perhaps because all my surfaces are now FLOAT16_RGB or FLOAT16_RGBA.
422        // It doesn't like FLOAT32 surfaces, and it also didn't seem to like mixing R8G8B8 with FLOAT16, at least
423        // those configurations seem to have been problems in the past, so I try to keep everything FLOAT16_RGB where possible.
424
425        // I go through quite a few RTT surfaces, and I don't use MRT since I couldn't get it working.
426
427        MaterialManager::getSingleton().initialise() ;
428
429        // need our own resource group so that the RTTs dont get destroyed when we load a new level.
430        Ogre::ResourceGroupManager::getSingleton().createResourceGroup("RTTResources") ;
431
432        Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();       
433
434        int RTTWidth = m_nRTTWidth ;//m_pRenderWnd->getWidth() ;
435        int RTTHeight = m_nRTTHeight ; //m_pRenderWnd->getHeight() ;
436
437        int DSWidth = m_nRTTWidth ;
438        int DSHeight = m_nRTTHeight ;
439
440        int DSWidthB = m_nSpeedRender ? m_nRTTWidth/2 : m_nRTTWidth ;
441        int DSHeightB = m_nSpeedRender ? m_nRTTHeight/2 : m_nRTTHeight ;
442
443        int TEMPWidth = m_nRTTWidth ;
444        int TEMPHeight = m_nRTTHeight ;
445
446
447        Ogre::ColourValue ClearColour=Ogre::ColourValue(0,0,0,1) ; // clears alpha as well. for RGBA textures
448        //!! for now use alpha 1, since Ogre seems to force it to 1 anyway on shadow render.
449
450
451       
452       
453        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
454        // Shadow
455       
456        RTT_Texture_Shadow = Ogre::TextureManager::getSingleton().createManual("RttTex_Shadow",
457      "RTTResources", TEX_TYPE_2D, m_nShadowMapSize, m_nShadowMapSize, 0, PF_FLOAT16_RGB,
458      TU_RENDERTARGET);
459
460       
461        renderTexture_Shadow = RTT_Texture_Shadow->getBuffer()->getRenderTarget();
462        renderTexture_Shadow->addViewport(m_pCamera);
463        renderTexture_Shadow->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
464        renderTexture_Shadow->getViewport(0)->setBackgroundColour(ColourValue::White);
465        renderTexture_Shadow->getViewport(0)->setOverlaysEnabled(false);
466
467        RTT_Mat_Shadow = MaterialManager::getSingleton().create("RttMat_Shadow", "RTTResources");
468        RTT_Technique_Shadow = RTT_Mat_Shadow->createTechnique();
469        RTT_Technique_Shadow->createPass();
470        TextureUnitState* tState_Shadow = RTT_Mat_Shadow->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_Shadow");
471        tState_Shadow->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
472        RTT_Mat_Shadow->getTechnique(0)->getPass(0)->setLightingEnabled(false);
473        RTT_Mat_Shadow->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
474       
475        miniScreen_Shadow = new Ogre::Rectangle2D(true);
476        miniScreen_Shadow->setCorners(-1.0001, 1.0001, 1.0, -1.0);
477        miniScreen_Shadow->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
478        miniScreenNode_Shadow = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_Shadow");
479        miniScreenNode_Shadow->attachObject(miniScreen_Shadow);
480        miniScreen_Shadow->setMaterial("RttMat_Shadow");
481
482
483        if(m_nColouredShadow)
484        {
485                //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
486                // ShadeFront
487               
488                RTT_Texture_ShadeFront = Ogre::TextureManager::getSingleton().createManual("RttTex_ShadeFront",
489                                "RTTResources", TEX_TYPE_2D, m_nShadowRGBSize, m_nShadowRGBSize, 0, PF_FLOAT16_RGBA,
490                                TU_RENDERTARGET);
491
492               
493                renderTexture_ShadeFront = RTT_Texture_ShadeFront->getBuffer()->getRenderTarget();
494                renderTexture_ShadeFront->addViewport(m_pCamera);
495                renderTexture_ShadeFront->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH);
496                renderTexture_ShadeFront->getViewport(0)->setBackgroundColour(ColourValue::White);
497                renderTexture_ShadeFront->getViewport(0)->setOverlaysEnabled(false);
498
499                RTT_Mat_ShadeFront = MaterialManager::getSingleton().create("RttMat_ShadeFront", "RTTResources");
500                RTT_Technique_ShadeFront = RTT_Mat_ShadeFront->createTechnique();
501                RTT_Technique_ShadeFront->createPass();
502                TextureUnitState* tState_ShadeFront = RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_ShadeFront");
503                tState_ShadeFront->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
504                RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->setLightingEnabled(false);
505                RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
506               
507                miniScreen_ShadeFront = new Ogre::Rectangle2D(true);
508                miniScreen_ShadeFront->setCorners(-1.0001, 1.0001, 1.0, -1.0);
509                miniScreen_ShadeFront->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
510                miniScreenNode_ShadeFront = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_ShadeFront");
511                miniScreenNode_ShadeFront->attachObject(miniScreen_ShadeFront);
512                miniScreen_ShadeFront->setMaterial("RttMat_ShadeFront");
513               
514                //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
515                // ShadeBack
516               
517                RTT_Texture_ShadeBack = Ogre::TextureManager::getSingleton().createManual("RttTex_ShadeBack",
518                                "RTTResources", TEX_TYPE_2D, m_nShadowRGBSize, m_nShadowRGBSize, 0, PF_FLOAT16_RGBA,
519                                TU_RENDERTARGET);
520
521               
522                renderTexture_ShadeBack = RTT_Texture_ShadeBack->getBuffer()->getRenderTarget();
523                renderTexture_ShadeBack->addViewport(m_pCamera);
524                renderTexture_ShadeBack->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH);
525                renderTexture_ShadeBack->getViewport(0)->setBackgroundColour(ColourValue::White);
526                renderTexture_ShadeBack->getViewport(0)->setOverlaysEnabled(false);
527
528                RTT_Mat_ShadeBack = MaterialManager::getSingleton().create("RttMat_ShadeBack", "RTTResources");
529                RTT_Technique_ShadeBack = RTT_Mat_ShadeBack->createTechnique();
530                RTT_Technique_ShadeBack->createPass();
531                TextureUnitState* tState_ShadeBack = RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_ShadeBack");
532                tState_ShadeBack->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
533                RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->setLightingEnabled(false);
534                RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
535               
536                miniScreen_ShadeBack = new Ogre::Rectangle2D(true);
537                miniScreen_ShadeBack->setCorners(-1.0001, 1.0001, 1.0, -1.0);
538                miniScreen_ShadeBack->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
539                miniScreenNode_ShadeBack = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_ShadeBack");
540                miniScreenNode_ShadeBack->attachObject(miniScreen_ShadeBack);
541                miniScreen_ShadeBack->setMaterial("RttMat_ShadeBack");
542       
543        } // end if coloured shadows
544       
545       
546        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
547        // DfShPosition
548       
549        RTT_Texture_DfShPosition = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShPosition",
550      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
551      TU_RENDERTARGET);
552
553       
554        renderTexture_DfShPosition = RTT_Texture_DfShPosition->getBuffer()->getRenderTarget();
555        renderTexture_DfShPosition->addViewport(m_pCamera);
556        renderTexture_DfShPosition->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
557        renderTexture_DfShPosition->getViewport(0)->setBackgroundColour(ColourValue::Black);
558        renderTexture_DfShPosition->getViewport(0)->setOverlaysEnabled(false);
559
560        RTT_Mat_DfShPosition = MaterialManager::getSingleton().create("RttMat_DfShPosition", "RTTResources");
561        RTT_Technique_DfShPosition = RTT_Mat_DfShPosition->createTechnique();
562        RTT_Technique_DfShPosition->createPass();
563        TextureUnitState* tState_DfShPosition = RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShPosition");
564        tState_DfShPosition->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
565        RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->setLightingEnabled(false);
566        RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
567       
568       
569        //renderTexture_DfShPosition->addListener(this);
570
571        miniScreen_DfShPosition = new Ogre::Rectangle2D(true);
572        miniScreen_DfShPosition->setCorners(-1.0001, 1.0001, 1.0, -1.0);
573        miniScreen_DfShPosition->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
574        miniScreenNode_DfShPosition = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShPosition");
575        miniScreenNode_DfShPosition->attachObject(miniScreen_DfShPosition);
576        miniScreen_DfShPosition->setMaterial("RttMat_DfShPosition");
577       
578       
579
580        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
581        // DfShDiffuse
582       
583        RTT_Texture_DfShDiffuse = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShDiffuse",
584      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
585      TU_RENDERTARGET);
586
587       
588        renderTexture_DfShDiffuse = RTT_Texture_DfShDiffuse->getBuffer()->getRenderTarget();
589        renderTexture_DfShDiffuse->addViewport(m_pCamera);
590        renderTexture_DfShDiffuse->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
591        renderTexture_DfShDiffuse->getViewport(0)->setBackgroundColour(ColourValue::Black);
592        renderTexture_DfShDiffuse->getViewport(0)->setOverlaysEnabled(false);
593
594        RTT_Mat_DfShDiffuse = MaterialManager::getSingleton().create("RttMat_DfShDiffuse", "RTTResources");
595        RTT_Technique_DfShDiffuse = RTT_Mat_DfShDiffuse->createTechnique();
596        RTT_Technique_DfShDiffuse->createPass();
597        TextureUnitState* tState_DfShDiffuse = RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShDiffuse");
598        tState_DfShDiffuse->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
599        RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->setLightingEnabled(false);
600        RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
601       
602       
603        //renderTexture_DfShDiffuse->addListener(this);
604
605        miniScreen_DfShDiffuse = new Ogre::Rectangle2D(true);
606        miniScreen_DfShDiffuse->setCorners(-1.0001, 1.0001, 1.0, -1.0);
607        miniScreen_DfShDiffuse->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
608        miniScreenNode_DfShDiffuse = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShDiffuse");
609        miniScreenNode_DfShDiffuse->attachObject(miniScreen_DfShDiffuse);
610        miniScreen_DfShDiffuse->setMaterial("RttMat_DfShDiffuse");
611
612        /*
613        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
614        // DSNormal
615       
616        RTT_Texture_DSNormal = Ogre::TextureManager::getSingleton().createManual("RttTex_DSNormal",
617      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
618      TU_RENDERTARGET);
619
620       
621        renderTexture_DSNormal = RTT_Texture_DSNormal->getBuffer()->getRenderTarget();
622        renderTexture_DSNormal->addViewport(m_pCamera);
623        renderTexture_DSNormal->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
624        renderTexture_DSNormal->getViewport(0)->setBackgroundColour(ColourValue::Black);
625        renderTexture_DSNormal->getViewport(0)->setOverlaysEnabled(false);
626
627        RTT_Mat_DSNormal = MaterialManager::getSingleton().create("RttMat_DSNormal", "RTTResources");
628        RTT_Technique_DSNormal = RTT_Mat_DSNormal->createTechnique();
629        RTT_Technique_DSNormal->createPass();
630        TextureUnitState* tState_DSNormal = RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DSNormal");
631        tState_DSNormal->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
632        RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->setLightingEnabled(false);
633        RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
634       
635       
636       
637        //renderTexture_DSNormal->addListener(this);
638
639        miniScreen_DSNormal = new Ogre::Rectangle2D(true);
640        miniScreen_DSNormal->setCorners(-1.0001, 1.0001, 1.0, -1.0);
641        miniScreen_DSNormal->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
642        miniScreenNode_DSNormal = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DSNormal");
643        miniScreenNode_DSNormal->attachObject(miniScreen_DSNormal);
644        miniScreen_DSNormal->setMaterial("RttMat_DSNormal");
645       
646        */
647
648       
649        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
650        // DfShFuncTNB
651
652        RTT_Texture_DfShFuncTNB = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShFuncTNB",
653      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
654      TU_RENDERTARGET);
655
656       
657        renderTexture_DfShFuncTNB = RTT_Texture_DfShFuncTNB->getBuffer()->getRenderTarget();
658        renderTexture_DfShFuncTNB->addViewport(m_pCamera);
659        renderTexture_DfShFuncTNB->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
660        renderTexture_DfShFuncTNB->getViewport(0)->setBackgroundColour(ColourValue::Black);
661        renderTexture_DfShFuncTNB->getViewport(0)->setOverlaysEnabled(false);
662
663        RTT_Mat_DfShFuncTNB = MaterialManager::getSingleton().create("RttMat_DfShFuncTNB", "RTTResources");
664        RTT_Technique_DfShFuncTNB = RTT_Mat_DfShFuncTNB->createTechnique();
665        RTT_Technique_DfShFuncTNB->createPass();
666        TextureUnitState* tState_DfShFuncTNB = RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShFuncTNB");
667        tState_DfShFuncTNB->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
668        RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->setLightingEnabled(false);
669        RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
670       
671        //renderTexture_DfShFuncTNB->addListener(this);
672
673        miniScreen_DfShFuncTNB = new Ogre::Rectangle2D(true);
674        miniScreen_DfShFuncTNB->setCorners(-1.0001, 1.0001, 1.0, -1.0);
675        miniScreen_DfShFuncTNB->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
676        miniScreenNode_DfShFuncTNB = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShFuncTNB");
677        miniScreenNode_DfShFuncTNB->attachObject(miniScreen_DfShFuncTNB);
678        miniScreen_DfShFuncTNB->setMaterial("RttMat_DfShFuncTNB");
679
680       
681
682        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
683        // DfShSpecular
684
685        RTT_Texture_DfShSpecular = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShSpecular",
686      "RTTResources", TEX_TYPE_2D, DSWidthB, DSHeightB, 0, PF_FLOAT16_RGBA,
687      TU_RENDERTARGET);
688
689       
690        renderTexture_DfShSpecular = RTT_Texture_DfShSpecular->getBuffer()->getRenderTarget();
691        renderTexture_DfShSpecular->addViewport(m_pCamera);
692        renderTexture_DfShSpecular->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
693        renderTexture_DfShSpecular->getViewport(0)->setBackgroundColour(ColourValue::Black);
694        renderTexture_DfShSpecular->getViewport(0)->setOverlaysEnabled(false);
695
696        RTT_Mat_DfShSpecular = MaterialManager::getSingleton().create("RttMat_DfShSpecular", "RTTResources");
697        RTT_Technique_DfShSpecular = RTT_Mat_DfShSpecular->createTechnique();
698        RTT_Technique_DfShSpecular->createPass();
699        TextureUnitState* tState_DfShSpecular = RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShSpecular");
700        tState_DfShSpecular->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
701        RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setLightingEnabled(false);
702        if(m_nSpeedRender)
703                RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
704        else
705                RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
706       
707
708        //renderTexture_DfShSpecular->addListener(this);
709
710        miniScreen_DfShSpecular = new Ogre::Rectangle2D(true);
711        miniScreen_DfShSpecular->setCorners(-1.0001, 1.0001, 1.0, -1.0);
712        miniScreen_DfShSpecular->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
713        miniScreenNode_DfShSpecular = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShSpecular");
714        miniScreenNode_DfShSpecular->attachObject(miniScreen_DfShSpecular);
715        miniScreen_DfShSpecular->setMaterial("RttMat_DfShSpecular");
716
717        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
718        // DfShEmissive
719
720        RTT_Texture_DfShEmissive = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShEmissive",
721      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
722      TU_RENDERTARGET);
723
724       
725        renderTexture_DfShEmissive = RTT_Texture_DfShEmissive->getBuffer()->getRenderTarget();
726        renderTexture_DfShEmissive->addViewport(m_pCamera);
727        renderTexture_DfShEmissive->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
728        renderTexture_DfShEmissive->getViewport(0)->setBackgroundColour(ColourValue::Black);
729        renderTexture_DfShEmissive->getViewport(0)->setOverlaysEnabled(false);
730
731        RTT_Mat_DfShEmissive = MaterialManager::getSingleton().create("RttMat_DfShEmissive", "RTTResources");
732        RTT_Technique_DfShEmissive = RTT_Mat_DfShEmissive->createTechnique();
733        RTT_Technique_DfShEmissive->createPass();
734        TextureUnitState* tState_DfShEmissive = RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShEmissive");
735        tState_DfShEmissive->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
736        RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setLightingEnabled(false);
737        if(m_nSpeedRender)
738                RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
739        else
740                RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
741       
742
743        //renderTexture_DfShEmissive->addListener(this);
744
745        miniScreen_DfShEmissive = new Ogre::Rectangle2D(true);
746        miniScreen_DfShEmissive->setCorners(-1.0001, 1.0001, 1.0, -1.0);
747        miniScreen_DfShEmissive->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
748        miniScreenNode_DfShEmissive = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShEmissive");
749        miniScreenNode_DfShEmissive->attachObject(miniScreen_DfShEmissive);
750        miniScreen_DfShEmissive->setMaterial("RttMat_DfShEmissive");
751
752       
753        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
754        // DfShLamp
755
756        RTT_Texture_DfShLamp = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShLamp",
757      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB, 
758      TU_RENDERTARGET);//, 0, false, 6);
759       
760        renderTexture_DfShLamp = RTT_Texture_DfShLamp->getBuffer()->getRenderTarget();
761        renderTexture_DfShLamp->addViewport(m_pCamera);
762        renderTexture_DfShLamp->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH);
763        renderTexture_DfShLamp->getViewport(0)->setBackgroundColour(ColourValue::Black);
764        renderTexture_DfShLamp->getViewport(0)->setOverlaysEnabled(false);
765
766        RTT_Mat_DfShLamp = MaterialManager::getSingleton().create("RttMat_DfShLamp", "RTTResources");
767        RTT_Technique_DfShLamp = RTT_Mat_DfShLamp->createTechnique();
768        RTT_Technique_DfShLamp->createPass();
769        TextureUnitState* tState_DfShLamp = RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShLamp");
770        tState_DfShLamp->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
771        RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->setLightingEnabled(false);
772        RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
773        //renderTexture_DfShLamp->addListener(this);
774
775        miniScreen_DfShLamp = new Ogre::Rectangle2D(true);
776        miniScreen_DfShLamp->setCorners(-1.0001, 1.0001, 1.0, -1.0);
777        miniScreen_DfShLamp->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
778        miniScreenNode_DfShLamp = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShLamp");
779        miniScreenNode_DfShLamp->attachObject(miniScreen_DfShLamp);
780        miniScreen_DfShLamp->setMaterial("RttMat_DfShLamp");
781       
782       
783
784        /*
785        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
786        // DfShData
787
788        RTT_Texture_DfShData = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShData",
789      "RTTResources", TEX_TYPE_2D, DSWidthB, DSHeightB, 0, PF_FLOAT16_RGB,
790      TU_RENDERTARGET);
791       
792        renderTexture_DfShData = RTT_Texture_DfShData->getBuffer()->getRenderTarget();
793        renderTexture_DfShData->addViewport(m_pCamera);
794        renderTexture_DfShData->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
795        renderTexture_DfShData->getViewport(0)->setBackgroundColour(ColourValue::Black);
796        renderTexture_DfShData->getViewport(0)->setOverlaysEnabled(false);
797
798        RTT_Mat_DfShData = MaterialManager::getSingleton().create("RttMat_DfShData", "RTTResources");
799        RTT_Technique_DfShData = RTT_Mat_DfShData->createTechnique();
800        RTT_Technique_DfShData->createPass();
801        TextureUnitState* tState_DfShData = RTT_Mat_DfShData->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShData");
802        tState_DfShData->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
803        RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setLightingEnabled(false);
804        if(m_nSpeedRender)
805                RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
806        else
807                RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
808        //renderTexture_DfShData->addListener(this);
809
810        miniScreen_DfShData = new Ogre::Rectangle2D(true);
811        miniScreen_DfShData->setCorners(-1.0001, 1.0001, 1.0, -1.0);
812        miniScreen_DfShData->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
813        miniScreenNode_DfShData = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShData");
814        miniScreenNode_DfShData->attachObject(miniScreen_DfShData);
815        miniScreen_DfShData->setMaterial("RttMat_DfShData");
816       
817        */
818
819       
820        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
821        // DfShTemp
822
823        RTT_Texture_DfShTemp = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShTemp",
824      "RTTResources", TEX_TYPE_2D, TEMPWidth, TEMPHeight, 0, PF_FLOAT16_RGB, 
825      TU_RENDERTARGET);//, 0, false, 6);
826       
827        renderTexture_DfShTemp = RTT_Texture_DfShTemp->getBuffer()->getRenderTarget();
828        renderTexture_DfShTemp->addViewport(m_pCamera);
829        renderTexture_DfShTemp->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH); 
830        renderTexture_DfShTemp->getViewport(0)->setBackgroundColour(ColourValue::Black);
831        renderTexture_DfShTemp->getViewport(0)->setOverlaysEnabled(false);
832
833        RTT_Mat_DfShTemp = MaterialManager::getSingleton().create("RttMat_DfShTemp", "RTTResources");
834        RTT_Technique_DfShTemp = RTT_Mat_DfShTemp->createTechnique();
835        RTT_Technique_DfShTemp->createPass();
836        TextureUnitState* tState_DfShTemp = RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShTemp");
837        tState_DfShTemp->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
838        RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->setLightingEnabled(false);
839        RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
840        //renderTexture_DfShTemp->addListener(this);
841
842        miniScreen_DfShTemp = new Ogre::Rectangle2D(true);
843        miniScreen_DfShTemp->setCorners(-1.0001, 1.0001, 1.0, -1.0);
844        miniScreen_DfShTemp->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
845        miniScreenNode_DfShTemp = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShTemp");
846        miniScreenNode_DfShTemp->attachObject(miniScreen_DfShTemp);
847        miniScreen_DfShTemp->setMaterial("RttMat_DfShTemp");
848
849
850       
851        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
852        // DfShMix
853
854                RTT_Texture_DfShMix = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShMix",
855      "RTTResources", TEX_TYPE_2D, RTTWidth, RTTHeight, 0, PF_FLOAT16_RGB,
856      TU_RENDERTARGET);
857
858       
859        renderTexture_DfShMix = RTT_Texture_DfShMix->getBuffer()->getRenderTarget();
860        renderTexture_DfShMix->addViewport(m_pCamera);
861        renderTexture_DfShMix->getViewport(0)->setClearEveryFrame(false);//, FBT_DEPTH);
862        renderTexture_DfShMix->getViewport(0)->setBackgroundColour(ColourValue::Black);
863        renderTexture_DfShMix->getViewport(0)->setOverlaysEnabled(false);
864
865        RTT_Mat_DfShMix = MaterialManager::getSingleton().create("RttMat_DfShMix", "RTTResources");
866        RTT_Technique_DfShMix = RTT_Mat_DfShMix->createTechnique();
867        RTT_Technique_DfShMix->createPass();
868        TextureUnitState* tState_DfShMix = RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShMix");
869        tState_DfShMix->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
870        RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->setLightingEnabled(false);
871        RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
872
873
874        miniScreen_DfShMix = new Ogre::Rectangle2D(true);
875        miniScreen_DfShMix->setCorners(-1.0001, 1.0001, 1.0, -1.0);
876        miniScreen_DfShMix->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
877        miniScreenNode_DfShMix = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShMix");
878        miniScreenNode_DfShMix->attachObject(miniScreen_DfShMix);
879        miniScreen_DfShMix->setMaterial("RttMat_DfShMix");
880       
881        if(m_nRenderHDR)
882        {
883
884               
885                //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
886                // BlurA
887               
888                RTT_Texture_BlurA = Ogre::TextureManager::getSingleton().createManual("RttTex_BlurA",
889                                "RTTResources", TEX_TYPE_2D, DSWidth/2, DSHeight/2, 0, PF_FLOAT16_RGB,
890                                TU_RENDERTARGET);
891               
892                renderTexture_BlurA = RTT_Texture_BlurA->getBuffer()->getRenderTarget();
893                renderTexture_BlurA->addViewport(m_pCamera);
894                renderTexture_BlurA->getViewport(0)->setClearEveryFrame(false);
895                renderTexture_BlurA->getViewport(0)->setBackgroundColour(ColourValue::Black);
896                renderTexture_BlurA->getViewport(0)->setOverlaysEnabled(false);
897
898                RTT_Mat_BlurA = MaterialManager::getSingleton().create("RttMat_BlurA", "RTTResources");
899                RTT_Technique_BlurA = RTT_Mat_BlurA->createTechnique();
900                RTT_Technique_BlurA->createPass();
901                TextureUnitState* tState_BlurA = RTT_Mat_BlurA->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_BlurA");
902                tState_BlurA->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
903                RTT_Mat_BlurA->getTechnique(0)->getPass(0)->setLightingEnabled(false);
904                RTT_Mat_BlurA->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
905
906                miniScreen_BlurA = new Ogre::Rectangle2D(true);
907                miniScreen_BlurA->setCorners(-1.0001, 1.0001, 1.0, -1.0);
908                miniScreen_BlurA->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
909                miniScreenNode_BlurA = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_BlurA");
910                miniScreenNode_BlurA->attachObject(miniScreen_BlurA);
911                miniScreen_BlurA->setMaterial("RttMat_BlurA");
912
913                //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
914                // BlurB
915               
916                RTT_Texture_BlurB = Ogre::TextureManager::getSingleton().createManual("RttTex_BlurB",
917                                "RTTResources", TEX_TYPE_2D, DSWidth/2, DSHeight/2, 0, PF_FLOAT16_RGB,
918                                TU_RENDERTARGET);
919               
920                renderTexture_BlurB = RTT_Texture_BlurB->getBuffer()->getRenderTarget();
921                renderTexture_BlurB->addViewport(m_pCamera);
922                renderTexture_BlurB->getViewport(0)->setClearEveryFrame(false);
923                renderTexture_BlurB->getViewport(0)->setBackgroundColour(ColourValue::Black);
924                renderTexture_BlurB->getViewport(0)->setOverlaysEnabled(false);
925
926                RTT_Mat_BlurB = MaterialManager::getSingleton().create("RttMat_BlurB", "RTTResources");
927                RTT_Technique_BlurB = RTT_Mat_BlurB->createTechnique();
928                RTT_Technique_BlurB->createPass();
929                TextureUnitState* tState_BlurB = RTT_Mat_BlurB->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_BlurB");
930                tState_BlurB->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
931                RTT_Mat_BlurB->getTechnique(0)->getPass(0)->setLightingEnabled(false);
932                RTT_Mat_BlurB->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
933
934                miniScreen_BlurB = new Ogre::Rectangle2D(true);
935                miniScreen_BlurB->setCorners(-1.0001, 1.0001, 1.0, -1.0);
936                miniScreen_BlurB->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
937                miniScreenNode_BlurB = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_BlurB");
938                miniScreenNode_BlurB->attachObject(miniScreen_BlurB);
939                miniScreen_BlurB->setMaterial("RttMat_BlurB");
940               
941        } // end if m_nRenderHDR       
942       
943        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
944        // mixing quad
945        miniScreen_DfShMaster = new Ogre::Rectangle2D(true);
946        miniScreen_DfShMaster->setCorners(-1.0001, 1.0001, 1.0, -1.0);
947        miniScreen_DfShMaster->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
948        miniScreenNode_DfShMaster = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShMaster");
949        miniScreenNode_DfShMaster->attachObject(miniScreen_DfShMaster);
950        //miniScreen_DfShMaster->setMaterial("RttMat_DfShDiffuse") ;
951        //miniScreen_DfShMaster->setMaterial("DfShMix") ; // doesn't matter what material we use, since we mix from pre-rendered textures
952       
953        //RTT_Mat_Shadow->getTechnique(0)->getPass(0)->getTextureUnitState("RttTex_Shadow")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
954       
955}
956
957void OgreFramework::DestroyRTTAssets()
958{
959}
960
961void OgreFramework::UpdateRenderTargets()
962{
963
964        int nZoneList=0 ;
965        int nZone=0 ;
966        Ogre::Entity*   pEntity=NULL ;
967        int nMO=0 ;
968        int nZGStart=0 ;
969        int nZGEnd=0 ;
970
971        int nVisEnt=0 ;
972        int nEntity=0 ;
973//      int nMaxEntity=0 ;
974        int nSubMesh=0 ;
975        int nMaxSubMesh=0 ;
976
977        int nMaxVisibleZone=*m_pGlobal_MaxVisibleZone ;
978
979        SetAllLightsOff() ;
980
981       
982        // extra texture params
983        // TexParam.x is 1 for d3d, -1 for ogl, needed for screen space UV calculations y flip
984        // TexParam.y is game time, in 1/10th of a second since start of level
985
986        Ogre::Vector4 TexParam ;
987        if(m_IsOpenGL) 
988                TexParam.x=-1 ; 
989        else 
990                TexParam.x= 1 ;
991        TexParam.y=m_GameTime/100 ;
992        TexParam.z=512.0f ; // pixelnoise subdivisions for the emmissive data function.
993
994
995        // remove all the nodes, so we start with a clean slate
996        m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
997       
998
999        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1000        //
1001        // deferred shading data textures
1002        //
1003        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1004
1005        SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ;
1006
1007        // attach the entity masternode, update positions and orientations
1008        for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1009        {
1010                nEntity=m_pFrustumEntity[nVisEnt] ;
1011                m_pEntityInfo[ nEntity ].pMasterNode->setPosition( m_pEntityInfo[nEntity].Postition ) ; // set position.
1012                m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ;
1013        }
1014
1015
1016       
1017       
1018        /////////////////////////////////////////////////////////////////////
1019        // DfShPosition
1020       
1021        // change material
1022        for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1023        {
1024                nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1025                nZGStart        =       m_nZoneMOStart[nZone] ;
1026                nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1027                       
1028                for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1029                        if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
1030                        {
1031                                pEntity=m_pZoneEntity[nMO] ;
1032                                pEntity->setMaterial( m_pZoneEntityMaterial_DfShPosition[nMO] ) ;
1033                        }// end for entities
1034
1035        }// end for zonelist
1036
1037
1038        // first time we set materials we need to set non-opaque to the be invisible.  After we don't need to do it, they'll already be invisible
1039        // Set the entity material
1040
1041        for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1042        {
1043                nEntity=m_pFrustumEntity[nVisEnt] ;
1044                nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1045
1046                for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1047                        if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
1048                        {
1049                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShPosition[nSubMesh] ) ;
1050                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ; // first time around, make sure it is visible
1051                        }
1052                        else
1053                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ;
1054        }
1055
1056
1057
1058        renderTexture_DfShPosition->update(true) ;
1059       
1060        /////////////////////////////////////////////////////////////////////
1061        // DfShFuncTNB
1062
1063        // change material
1064        for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1065        {
1066                nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1067                nZGStart        =       m_nZoneMOStart[nZone] ;
1068                nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1069                       
1070                for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1071                        if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
1072                        {
1073                                pEntity=m_pZoneEntity[nMO] ;
1074                                pEntity->setMaterial( m_pZoneEntityMaterial_DfShFuncTNB[nMO] ) ;
1075                        }// end for entities
1076
1077        }// end for zonelist
1078
1079        for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1080        {
1081                nEntity=m_pFrustumEntity[nVisEnt] ;
1082                nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1083
1084                for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1085                        if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
1086                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShFuncTNB[nSubMesh] ) ;
1087        }
1088
1089
1090        renderTexture_DfShFuncTNB->update(true) ;
1091       
1092       
1093        /////////////////////////////////////////////////////////////////////
1094        // DfShDiffuse
1095       
1096        // the diffuse pass is used for the wireframe render as well
1097
1098
1099
1100        if(m_nDisplayInfoMode!=1)
1101        {
1102                // change material
1103                for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1104                {
1105                        nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1106                        nZGStart        =       m_nZoneMOStart[nZone] ;
1107                        nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1108                               
1109                        for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1110                                if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
1111                                {
1112                                        pEntity=m_pZoneEntity[nMO] ;
1113                                        pEntity->setMaterial( m_pZoneEntityMaterial_DfShDiffuse[nMO] ) ;
1114                                }// end for entities
1115
1116                }// end for zonelist
1117
1118                // set the entity material
1119
1120                for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1121                {
1122                        nEntity=m_pFrustumEntity[nVisEnt] ;
1123                        nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1124
1125                        for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1126                                if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
1127                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShDiffuse[nSubMesh] ) ;
1128                }
1129
1130
1131                renderTexture_DfShDiffuse->update(true) ;
1132        }
1133        else // if we are doing wireframe we use this pass for it
1134        {
1135                // add gels just for the wireframe
1136                SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ;     
1137
1138
1139                // clear the RTT texture, since our wireframe won't clear it.
1140                m_pRoot->getRenderSystem()->_setViewport(renderTexture_DfShDiffuse->getViewport(0)) ;
1141                m_pRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR|FBT_DEPTH, Ogre::ColourValue(0,0,0,1)) ;
1142               
1143                // set the camera to wireframe mode
1144                m_pCamera->setPolygonMode(PM_WIREFRAME);
1145
1146                // change material
1147                for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1148                {
1149                        nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1150                        nZGStart        =       m_nZoneMOStart[nZone] ;
1151                        nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1152                               
1153                        for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1154                                if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
1155                                {
1156                                        pEntity=m_pZoneEntity[nMO] ;
1157                                        pEntity->setMaterial( MaterialManager::getSingleton().getByName("White") ) ;
1158                                }// end for entities
1159
1160                }// end for zonelist
1161
1162                for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1163                {
1164                        nEntity=m_pFrustumEntity[nVisEnt] ;
1165                        nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1166
1167                        for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1168                        {
1169                                if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_OPAQUE) // any non-opaque submeshes need to be made visible
1170                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
1171
1172                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial(MaterialManager::getSingleton().getByName("White") ) ;
1173                        }
1174                }
1175
1176                renderTexture_DfShDiffuse->update(true) ;
1177       
1178                // reset back to pre-wireframe setup
1179                m_pCamera->setPolygonMode(PM_SOLID);
1180
1181                // remove everything and then add back OPAQUE
1182                m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
1183                SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ;
1184
1185
1186                // reattach entities, make non-opaque subentities invisible
1187                for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1188                {
1189                        nEntity=m_pFrustumEntity[nVisEnt] ;
1190                        nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1191
1192                        m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[  nEntity  ].pMasterNode) ;
1193
1194                        for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1195                        {
1196                                if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_OPAQUE) 
1197                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ;
1198                        }
1199                }
1200
1201
1202
1203        }
1204
1205       
1206       
1207        /////////////////////////////////////////////////////////////////////
1208        // DfShSpecular
1209
1210        // change material
1211        for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1212        {
1213                nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1214                nZGStart        =       m_nZoneMOStart[nZone] ;
1215                nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1216                       
1217                for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1218                        if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
1219                        {
1220                                pEntity=m_pZoneEntity[nMO] ;
1221                                pEntity->setMaterial( m_pZoneEntityMaterial_DfShSpecular[nMO] ) ;
1222                        }// end for entities
1223
1224        }// end for zonelist
1225
1226        for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1227        {
1228                nEntity=m_pFrustumEntity[nVisEnt] ;
1229                nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1230
1231                // set the entity material
1232                for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1233                        if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
1234                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShSpecular[nSubMesh] ) ;
1235        }
1236
1237        renderTexture_DfShSpecular->update(true) ;
1238       
1239        /*
1240        /////////////////////////////////////////////////////////////////////
1241        // DfShData
1242
1243        // change material
1244        for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1245        {
1246                nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1247                nZGStart        =       m_nZoneMOStart[nZone] ;
1248                nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1249                       
1250                for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1251                        if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
1252                        {
1253                                pEntity=m_pZoneEntity[nMO] ;
1254                                pEntity->setMaterial( m_pZoneEntityMaterial_DfShData[nMO] ) ;
1255                        }// end for entities
1256
1257        }// end for zonelist
1258
1259        renderTexture_DfShData->update(true) ;
1260        */
1261
1262       
1263        /////////////////////////////////////////////////////////////////////
1264        // DfShEmissive
1265
1266        // we add the glow entities for this pass, if we are doing HDR
1267        if(m_nRenderHDR)
1268                SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GLOW) ;
1269
1270
1271        // change material
1272        for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1273        {
1274                nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1275                nZGStart        =       m_nZoneMOStart[nZone] ;
1276                nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1277                       
1278                for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1279                        if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GLOW))
1280                        {
1281                                pEntity=m_pZoneEntity[nMO] ;
1282                                pEntity->setMaterial( m_pZoneEntityMaterial_DfShEmissive[nMO] ) ;
1283
1284                                TexParam.z=512.0f ; // pixelnoise subdivisions for the emmissive data function.
1285                                pEntity->getSubEntity(0)->setCustomParameter(4, TexParam) ; // emissive makes use of gametime for some lighting effects
1286                        }// end for entities
1287
1288        }// end for zonelist
1289
1290        // set the entity material
1291        for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1292        {
1293                nEntity=m_pFrustumEntity[nVisEnt] ;
1294                nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1295
1296                for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1297                        if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW))
1298                        {
1299                                // make glow stuff visible
1300                                if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW)
1301                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
1302
1303                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShEmissive[nSubMesh] ) ;
1304                        }
1305        }
1306
1307        renderTexture_DfShEmissive->update(true) ;
1308
1309       
1310
1311        ////////////////////////////////////////////////////////////////////
1312        // we need to know how to colour stuff if we're seeing it through gel
1313        // this colouring will be applied when we mix lamp and emmissive down to DfShMix
1314        //
1315        // Note that this leaves the light/lamp glow entities attached in HDR mode,
1316        // we need them to block the gels otherwise the blur on the lights/lamps
1317        // comes out incorrectly coloured by gel that should be behind it.
1318
1319        // add the transparent stuff
1320        SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ;
1321
1322        // change material
1323        for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1324        {
1325                nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1326                nZGStart        =       m_nZoneMOStart[nZone] ;
1327                nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1328                       
1329                for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1330                        if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL) || (m_pZoneEntityMaterialType[nMO]==MAT_GLOW))
1331                        {
1332                                pEntity=m_pZoneEntity[nMO] ;
1333                                pEntity->setMaterial( m_pZoneEntityMaterial_DfShColour[nMO] ) ;
1334                        }// end for entities
1335
1336
1337        }// end for zonelist
1338
1339        for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
1340        {
1341                nEntity=m_pFrustumEntity[nVisEnt] ;
1342                nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1343
1344                // set the entity material
1345                for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1346                        if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW))
1347                        {
1348                                // make gel stuff visible (glow was already made visible on the emissive pass)
1349                                if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL)
1350                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
1351
1352                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShColour[nSubMesh] ) ;
1353                        }
1354        }
1355
1356        // render colour to the temp surface
1357        renderTexture_DfShTemp->update(true) ;
1358
1359       
1360
1361        //clear the mix buffer once
1362        m_pRoot->getRenderSystem()->_setViewport(renderTexture_DfShMix->getViewport(0)) ;
1363        m_pRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR|FBT_DEPTH, Ogre::ColourValue(0,0,0,1)) ;
1364
1365        // remove all the nodes
1366        m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
1367
1368        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1369        //
1370        // deferred shading non-shadowing point lights
1371        //
1372        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1373
1374
1375
1376        if(true)
1377        {
1378                SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_LAMP) ; // attach the lamp boxes
1379
1380                // this renders our deferred shader lamps
1381                renderTexture_DfShLamp->update(true) ;
1382
1383                // this shader combines the deferred light render with the emissive render and colours it with any gels
1384                miniScreen_DfShMaster->setMaterial("Mix_Lamps") ; 
1385
1386                // get rid of all the scene geometry
1387                m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1388
1389                // put up a fullscreen quad so DfShMix has some UV coordinates.
1390                m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
1391
1392                // update DfShMix, but don't swap buffers yet since we may be back again next loop with more lights to add.
1393                renderTexture_DfShMix->update(false) ; 
1394
1395                // now DfShMix has all the deferred render stuff mixed onto it, as well as emissive stuff,
1396                // and it's ready for forward rendered shadowing lights to be additively blended over it.
1397        } // end if deferred render active
1398
1399
1400
1401       
1402
1403        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1404        //
1405        // forward rendered shadowing spotlights
1406        //
1407        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1408
1409        // we now add entities from m_pVisibleEntity instead of m_pFrustumEntity since entities outside the frustum might still contribute shadows.
1410        //''
1411        if(true)
1412        {
1413
1414
1415                // multiple attempts at getting additive blending of the shadows failed, so I have to do an extra pass to "accumulate" the data :(
1416
1417                int nMaxVisibleLight=*m_pGlobal_MaxVisibleLight ;
1418
1419                // the texture view projection per light.  We use four Vector4 instead of a single Matrix4 because we have to pass them to the shaders as custom params
1420                Ogre::Vector4   tvpMat0 ;
1421                Ogre::Vector4   tvpMat1 ;
1422                Ogre::Vector4   tvpMat2 ;
1423                Ogre::Vector4   tvpMat3 ;
1424
1425
1426
1427                int nVisibleLight=0 ;
1428                int nLt=0 ;
1429                int nProjector=0 ;
1430                int nEntLtIndex=0 ;
1431                int nEntLtIndexMax=0 ;
1432
1433                m_nVisibleLightCount=0 ; // total shadow lights added from all loops
1434
1435
1436                miniScreen_DfShMaster->setMaterial("Mix_ShadowLights") ;
1437               
1438               
1439                // loop through shadow casting lights
1440                for(nVisibleLight=0 ; nVisibleLight<nMaxVisibleLight ; nVisibleLight++)
1441                {
1442                         // copy the camera's original settings because we'll be modifying it
1443                        m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ;
1444
1445                        nLt=m_pGlobal_VisibleLightList[nVisibleLight] ;
1446
1447                        // setup the light and light's shadow camera, skip if light isn't really visible
1448                        if(SetupSingleVisibleLightAndShadowCamera(nLt, m_pGlobal_LightVis, m_pGlobal_VisibleLightList, m_pCamera))
1449                        {
1450                                // count the light
1451                                m_nVisibleLightCount++ ;
1452                               
1453                               
1454
1455                               
1456                                /////////////////////////////////////////////////////////////////////////////////////////////////////
1457                                // Render the shadow map
1458
1459                                // add all the opaque stuff
1460                                m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; 
1461                                SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ; 
1462
1463                               
1464                                for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
1465                                {
1466                                        // check if this entity touches this light
1467                                        nEntity=m_pVisibleEntity[nVisEnt] ;
1468                                       
1469                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ;
1470
1471                                        nEntLtIndexMax=m_pEntityInfo[nEntity].Light[INDEX_LIGHTPERENTITY] ;
1472                                        m_pEntityInfo[nEntity].LightTouch=0 ; // default, doesn't touch this light, use black material
1473                                        for(nEntLtIndex=0 ; nEntLtIndex<nEntLtIndexMax ; nEntLtIndex++)
1474                                                if(m_pEntityInfo[nEntity].Light[nEntLtIndex]==nLt) // found a match, entity is touched by this light
1475                                                {
1476                                                        m_pEntityInfo[nEntity].LightTouch=1 ; // touches this light, don't use black
1477                                                        break ;
1478                                                }
1479
1480                                }// end for nVisEnt
1481                               
1482
1483
1484
1485
1486
1487
1488                                // change to shadow pass material
1489                                for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1490                                {
1491                                        nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1492                                        nZGStart        =       m_nZoneMOStart[nZone] ;
1493                                        nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1494                                               
1495                                        for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1496                                                if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
1497                                                {
1498                                                        pEntity=m_pZoneEntity[nMO] ;
1499                                                        pEntity->setMaterial( m_pZoneEntityMaterial_Shadow[nMO] ) ;
1500                                                }// end for entities
1501
1502                                }// end for zonelist
1503
1504                                for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
1505                                {
1506                                        nEntity=m_pVisibleEntity[nVisEnt] ;
1507                                        nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1508
1509                                        // set the entity material
1510                                        for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1511                                                if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
1512                                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Shadow[nSubMesh] ) ;
1513                                                else
1514                                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ; // non-opaque stuff is invisible
1515                                }
1516
1517
1518                                // render the shadow map out to the Shadow texture
1519                                renderTexture_Shadow->update(true) ;
1520
1521                                // Opaque nodes are already in the scene, add all the Transparent stuff
1522                                SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ; 
1523
1524                                // if this light is flagged as needing colourized shadows, we do the slower shadow method
1525                                // this means rendering an extra couple of coloured shadow maps here, plus a different material for the view render
1526                                if(m_nColouredShadow)
1527                                {
1528                                       
1529                                        /////////////////////////////////////////////////////////////////////////////////////////////////////
1530                                        // Render the ShadeFront map
1531
1532                                       
1533
1534                                        // change to shadow pass material
1535                                        for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1536                                        {
1537                                                nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1538                                                nZGStart        =       m_nZoneMOStart[nZone] ;
1539                                                nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1540                                                       
1541                                                for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1542                                                        if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
1543                                                        {
1544                                                                pEntity=m_pZoneEntity[nMO] ;
1545                                                                pEntity->setMaterial( m_pZoneEntityMaterial_ShadeFront[nMO] ) ;
1546                                                        }// end for entities
1547
1548                                        }// end for zonelist
1549
1550                                        for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
1551                                        {
1552                                                nEntity=m_pVisibleEntity[nVisEnt] ;
1553                                                nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1554
1555                                                // set the entity material (pClearMaterial is already set)
1556                                                for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1557                                                        if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
1558                                                        {
1559                                                                // make gel stuff visible
1560                                                                if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL)
1561                                                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
1562
1563                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_ShadeFront[nSubMesh] ) ;
1564                                                        }
1565                                        }
1566
1567                                        // render the shadow map out to the Shadow texture
1568                                        renderTexture_ShadeFront->update(true) ;
1569
1570                                       
1571                                        /////////////////////////////////////////////////////////////////////////////////////////////////////
1572                                        // Render the ShadeBack map
1573
1574                                        // change to shadow pass material
1575                                        for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1576                                        {
1577                                                nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1578                                                nZGStart        =       m_nZoneMOStart[nZone] ;
1579                                                nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1580                                                       
1581                                                for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1582                                                        if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
1583                                                        {
1584                                                                pEntity=m_pZoneEntity[nMO] ;
1585                                                                pEntity->setMaterial( m_pZoneEntityMaterial_ShadeBack[nMO] ) ;
1586                                                        }// end for entities
1587
1588                                        }// end for zonelist
1589
1590                                        for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
1591                                        {
1592                                                nEntity=m_pVisibleEntity[nVisEnt] ;
1593                                                nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1594
1595                                                // set the entity material (pClearMaterial is already set)
1596                                                for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1597                                                        if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
1598                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_ShadeBack[nSubMesh] ) ;
1599                                        }
1600
1601                                        // render the shadow map out to the Shadow texture
1602                                        renderTexture_ShadeBack->update(true) ;
1603                                       
1604                                } // end if we need coloured shadows
1605
1606
1607       
1608
1609
1610
1611
1612                                /////////////////////////////////////////////////////////////////////////////////////////////////////
1613                                // Apply the shadow map to the view
1614
1615                                // calculate the texture view projection matrix for this light
1616                                Matrix4 TexViewProj=CreateTextureViewProjectionMatrix(m_pCamera) ;
1617
1618                                // change the matrix to four Vector4s so we can pass it in as a shader parameter
1619                                tvpMat0[0]=TexViewProj[0][0] ; tvpMat0[1]=TexViewProj[0][1] ; tvpMat0[2]=TexViewProj[0][2] ; tvpMat0[3]=TexViewProj[0][3] ;
1620                                tvpMat1[0]=TexViewProj[1][0] ; tvpMat1[1]=TexViewProj[1][1] ; tvpMat1[2]=TexViewProj[1][2] ; tvpMat1[3]=TexViewProj[1][3] ;
1621                                tvpMat2[0]=TexViewProj[2][0] ; tvpMat2[1]=TexViewProj[2][1] ; tvpMat2[2]=TexViewProj[2][2] ; tvpMat2[3]=TexViewProj[2][3] ;
1622                                tvpMat3[0]=TexViewProj[3][0] ; tvpMat3[1]=TexViewProj[3][1] ; tvpMat3[2]=TexViewProj[3][2] ; tvpMat3[3]=TexViewProj[3][3] ;
1623
1624                                // put the camera back to its proper position and settings.
1625                                m_pCamera->synchroniseBaseSettingsWith(m_pCameraCopy) ;
1626                                m_pCamera->setFOVy( Degree(m_flFOV) ) ;
1627                                m_pCamera->setAspectRatio( Real(m_flAspectRatio) );
1628
1629
1630                                nProjector=m_Q3Map->m_pLight[nLt].Texture ; // what projector texture is this light using?
1631
1632                                // change material and set all the tvp custom params
1633                                for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
1634                                {
1635                                        nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
1636                                        nZGStart        =       m_nZoneMOStart[nZone] ;
1637                                        nZGEnd          =       m_nZoneMOStart[nZone+1] ;
1638                                               
1639                                        for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
1640                                                if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
1641                                                {
1642                                                        pEntity=m_pZoneEntity[nMO] ;
1643
1644
1645                                                        // since the spot light pass is one of the slowest, we set the material of all the zones that don't touch
1646                                                        // this light to just a black material.  Only the zone of this light gets the real lighting material
1647                                                        // We need to have the other zones though or we end up seeing through walls.
1648                                                        // ALSO don't set gels to black, or else they block out the light in other zones.
1649
1650                                                       
1651                                                        if((m_pZoneEntityMaterialType[nMO]==MAT_GEL) || (LightTouchesZone(nLt, nZone)) )
1652                                                        {
1653                                                                if(m_nColouredShadow)
1654                                                                        pEntity->setMaterial( m_pZoneEntityMaterial_Base[nProjector][nMO] ) ; // coloured shadows
1655                                                                else
1656                                                                        pEntity->setMaterial( m_pZoneEntityMaterial_Fast[nProjector][nMO] ) ; // fast shadows
1657                                                        }
1658                                                        else
1659                                                                pEntity->setMaterial( m_pZoneEntityMaterial_Black[nMO] ) ; // just flat black, alpha tested for some
1660
1661
1662                                                       
1663                               
1664
1665                                                        // set the custom parameter, our texture view projection matrix for this light
1666                                                        pEntity->getSubEntity(0)->setCustomParameter(0, tvpMat0) ;
1667                                                        pEntity->getSubEntity(0)->setCustomParameter(1, tvpMat1) ;
1668                                                        pEntity->getSubEntity(0)->setCustomParameter(2, tvpMat2) ;
1669                                                        pEntity->getSubEntity(0)->setCustomParameter(3, tvpMat3) ;
1670
1671                                                        pEntity->getSubEntity(0)->setCustomParameter(4, TexParam) ;
1672
1673                                                }// end for entities
1674
1675                                }// end for zonelist
1676
1677                                for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
1678                                {
1679                                        nEntity=m_pVisibleEntity[nVisEnt] ;
1680                                        nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
1681
1682                                        // set the entity material
1683                                        for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
1684                                                if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
1685                                                {
1686
1687                                                        // if it's gel or the light touches the entity, use proper material, else use black
1688                                                        if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL) || m_pEntityInfo[nEntity].LightTouch)
1689                                                        {
1690                                                                if(m_nColouredShadow)
1691                                                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Base[nProjector][nSubMesh] ) ; // coloured shadows
1692                                                                else
1693                                                                        m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Fast[nProjector][nSubMesh] ) ; // fast shadows
1694                                                        }
1695                                                        else
1696                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Black[nSubMesh] ) ; // flat black
1697
1698
1699
1700                                                        // set the custom parameter, our texture view projection matrix for this light
1701                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(0, tvpMat0) ;
1702                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(1, tvpMat1) ;
1703                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(2, tvpMat2) ;
1704                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(3, tvpMat3) ;
1705
1706                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(4, TexParam) ;
1707                                                }
1708                                                else
1709                                                                m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( pClearMaterial ) ;
1710                                }
1711
1712
1713
1714
1715                                // if this is the first visible light, add emmissive transparent/alphablend particles. 
1716                                // they are added here so that they render correctly according to gels.
1717                                // But since they aren't shadowed, we only need render them for one light.
1718                                if(m_nVisibleLightCount==1)
1719                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pParticleNode) ; // attach the particles
1720
1721
1722
1723                                /////////////////////////////////////////////////////////////////////////////////////////////
1724                                // render the scene out to the DfShTemp texture.
1725                                //
1726
1727                                renderTexture_DfShTemp->update(true) ; 
1728
1729                                //
1730                                /////////////////////////////////////////////////////////////////////////////////////////////
1731                               
1732                               
1733                               
1734                                // remove the particles
1735                                if(m_nVisibleLightCount==1)
1736                                        m_pSceneMgr->getRootSceneNode()->removeChild(m_pParticleNode) ;
1737
1738
1739                                ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1740                                // Render Mix
1741
1742                                //?? unfortunately Ogre shares depth buffers in a manner that won't allow us to just additively render to DfShMix.
1743                                // If we try, we get glitching from the buffer sharing between Shadow and DfShMix.
1744                                // So instead we get rid of all geometry and additively render a fullscreen quad of DfShTemp to DfShMix.
1745                                // Slows things down a little, but at least it works.
1746
1747                                // get rid of all the scene geometry
1748                                m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1749
1750                                // put up a fullscreen quad so DfShMix has some UV coordinates.
1751                                m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
1752
1753                                // update DfShMix, but don't swap buffers yet since we may be back again next loop with more lights to add.
1754                                renderTexture_DfShMix->update(false) ; 
1755
1756                        }// end if light is visible
1757
1758
1759                }// end for nVisibleLight
1760                       
1761        }// end if forward render active
1762
1763        ///////////////////////////////////////////////////////////////////////////////////////
1764
1765
1766
1767        // after we've finished with all the lights and mixing, time to swap the mix buffer
1768        renderTexture_DfShMix->swapBuffers(false) ;
1769
1770       
1771        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1772        //
1773        // HDR bloom
1774        //
1775        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1776       
1777        if(m_nRenderHDR)
1778        {
1779                /////////////////////////////////////////////////////////
1780                // copy DfShMix to BlurA
1781
1782                // get rid of all the scene geometry
1783                m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1784
1785                // this shader renders DfShMix onto a surface
1786                miniScreen_DfShMaster->setMaterial("HDR_MixToBlurA") ; 
1787
1788                // put up a fullscreen quad so BlurA has some UV coordinates.
1789                m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
1790
1791                // render DfShMix to BlurA
1792                renderTexture_BlurA->update(true) ;
1793
1794               
1795
1796
1797                //////////////////////////////////////////////////////////////
1798                // now we do a few rounds of ping-pong bluring of A to B, B to A.
1799                int nMaxBlur=4 ;
1800//              int nLastBlur=nMaxBlur-1 ;
1801                int nBlurLoop=0 ;
1802
1803               
1804                // opengl and direct3d give different results for the same blur shader,
1805                // the issue is that d3d with bilinear filtering will offset stuff,
1806                // leading to a right-down drift that we need to compensate for.
1807                // So we need two versions of the blur shaders, one for ogl and one for d3d.
1808
1809                if(m_IsOpenGL)
1810                {
1811                        miniScreen_BlurA->setMaterial("HDR_BlurA_ogl");
1812                        miniScreen_BlurB->setMaterial("HDR_BlurB_ogl");
1813                }
1814                else
1815                {
1816                        miniScreen_BlurA->setMaterial("HDR_BlurA_d3d");
1817                        miniScreen_BlurB->setMaterial("HDR_BlurB_d3d");
1818                }
1819
1820                               
1821                // the main blur
1822                for(nBlurLoop=0 ; nBlurLoop<nMaxBlur ; nBlurLoop++)
1823                {
1824                        // blur A onto B
1825                        m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1826                        m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ;
1827                        renderTexture_BlurB->update(true) ;
1828
1829                        // blur B onto A
1830                        m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1831                        m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurB) ;
1832                        renderTexture_BlurA->update(true) ;
1833                }
1834               
1835
1836                // If I don't set these materials back to their originals, I get a crash on exit.
1837                // Not sure why.  Something to do with deleting the originals?
1838                // Doesn't matter, this fixes things.
1839
1840                miniScreen_BlurA->setMaterial("RttMat_BlurA");
1841                miniScreen_BlurB->setMaterial("RttMat_BlurB");
1842               
1843               
1844
1845                //////////////////////////////////////////////////////////////////
1846                // blend BlurA onto DfShMix
1847
1848                // get rid of all the scene geometry
1849                m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1850
1851                // this shader blends BlurA onto a surface
1852                if(m_IsOpenGL)
1853                        miniScreen_DfShMaster->setMaterial("HDR_BlurAToMix_ogl") ;
1854                else
1855                        miniScreen_DfShMaster->setMaterial("HDR_BlurAToMix_d3d") ;
1856
1857                // put up a fullscreen quad so DfShMix has some UV coordinates.
1858                m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
1859
1860                // update DfShMix.
1861                renderTexture_DfShMix->update(true) ;
1862
1863        }// end if HDR
1864       
1865
1866        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1867        //
1868        // display a rendered window
1869        //
1870        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1871
1872       
1873        m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
1874       
1875       
1876        if(m_nGoggleMode==GOGGLE_MODE_OFF) // stereo rendering not active
1877        {
1878                switch(m_nDisplayInfoMode)
1879                {
1880
1881                        case 0: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ; break ;
1882                        case 1: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShTemp) ; break ; // for wireframe view
1883                        case 2: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShLamp) ; break ;
1884                        case 3: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ; break ;
1885
1886                        case 4: // instead of showing the original position texture, we show a scaled version, since the original is outside 0-1 range
1887
1888                                // get rid of all the scene geometry
1889                                m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1890
1891                                // this shader renders DfShMix onto a surface
1892                                miniScreen_DfShMaster->setMaterial("Mix_ScalePosition") ; 
1893
1894                                // put up a fullscreen quad so BlurA has some UV coordinates.
1895                                m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
1896
1897                                // render DfShPostion to DfShMix
1898                                renderTexture_DfShMix->update(true) ;
1899
1900                                // display mix, which is a scaled copy of position.
1901                                m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ;
1902                                break ;
1903                       
1904                        case 5: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShFuncTNB) ; break ;
1905                        case 6: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ; break ;
1906                        case 7: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShSpecular) ; break ;                       
1907                        case 8: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShEmissive) ; break ;
1908                }
1909
1910
1911
1912
1913               
1914                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShPosition) ;
1915                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShFuncTNB) ;
1916                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShSpecular) ;
1917                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ;
1918                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShEmissive) ;
1919                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShData) ;
1920                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShLamp) ;
1921
1922                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ;
1923
1924                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ;
1925               
1926                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_Shadow) ;
1927                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShTemp) ;
1928                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_ShadeBack) ;
1929                //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_ShadeFront) ;
1930        }
1931        else
1932        {
1933                // add and position the Goggles
1934                m_pSceneMgr->getRootSceneNode()->addChild(m_pNodeGoggles) ;
1935                m_pNodeGoggles->setOrientation( m_pCamera->getOrientation() ) ;
1936                m_pNodeGoggles->setPosition( m_pCamera->getPosition() ) ;
1937        }
1938
1939       
1940        //m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1941        //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ;
1942       
1943       
1944        m_pRenderWnd->update(true) ;
1945
1946
1947        //m_pSceneMgr->getRootSceneNode()->removeChild(miniScreenNode_DfShSpecular) ;
1948        m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
1949
1950       
1951
1952
1953        ///////////////////////////////////////////
1954        // blittomemory experiment
1955        //uchar pixelData[64] ;
1956        //RTT_Texture_DfShPosition->getBuffer()->blitToMemory( Box( 0, 0, 1, 1), PixelBox(2, 2, 1, PF_FLOAT16_RGB, (void*)pixelData) ) ;
1957
1958
1959}
1960
1961// generate the texture view Projection matrix used in shadow mapping
1962Ogre::Matrix4 OgreFramework::CreateTextureViewProjectionMatrix(Ogre::Camera* pCamera)
1963{
1964
1965        const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE(
1966                      0.5,    0,    0,  0.5,
1967                            0,   -0.5,    0,  0.5,
1968                                  0,      0,    1,    0,
1969                                        0,      0,    0,    1);
1970
1971        Matrix4 TexViewProj = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * pCamera->getProjectionMatrixWithRSDepth() * pCamera->getViewMatrix();
1972
1973        return TexViewProj ;
1974
1975}
1976
1977void OgreFramework::DestroyGoggles()
1978{
1979        //m_pGoggleL->~ManualObject() ;
1980        //m_pGoggleR->~ManualObject() ;
1981
1982        //m_pNodeGoggles->~SceneNode() ;
1983       
1984
1985}
1986
1987// create the "virtual" virtual reality goggles we use to get around stereoscopic driver problems.
1988int OgreFramework::CreateGoggles()
1989{
1990
1991       
1992        float flMinX=0.0f ;
1993        float flMinY=0.0f ;
1994        float flMaxX=0.0f ;
1995        float flMaxY=0.0f ;
1996
1997
1998        // if they already exist, destroy them so we can recreate them
1999        if(m_pNodeGoggles!=NULL)        m_pNodeGoggles->detachAllObjects() ;
2000        if(m_pGoggleL!=NULL)                    m_pGoggleL->clear() ;
2001        if(m_pGoggleR!=NULL)                    m_pGoggleR->clear() ;
2002       
2003
2004        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2005
2006        // left goggle
2007
2008                if(m_pGoggleL==NULL) m_pGoggleL=m_pSceneMgr->createManualObject("GoggleL") ;
2009                m_pGoggleL->begin("RttMat_DfShMix", RenderOperation::OT_TRIANGLE_LIST) ;
2010       
2011                flMinX=-100*m_flGoggleAspectRatio*m_flGoggleXScale ;
2012                flMinY=-50*m_flGoggleYScale ;
2013
2014
2015                flMaxX=0 ;
2016                flMaxY=50*m_flGoggleYScale ;
2017
2018               
2019                m_pGoggleL->position(flMinX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
2020                m_pGoggleL->normal(0.0, 0.0, -1) ;
2021                m_pGoggleL->textureCoord(0.0, 0.0) ;
2022                m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
2023                m_pGoggleL->normal(0.0, 0.0, -1) ;
2024                m_pGoggleL->textureCoord(1.0, 0.0) ;
2025                m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
2026                m_pGoggleL->normal(0.0, 0.0, -1) ;
2027                m_pGoggleL->textureCoord(1.0, 1.0) ;
2028                m_pGoggleL->position(flMinX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
2029                m_pGoggleL->normal(0.0, 0.0, -1) ;
2030                m_pGoggleL->textureCoord(0.0, 1.0) ;
2031
2032                m_pGoggleL->quad(3, 2, 1, 0) ;
2033                m_pGoggleL->end() ;
2034
2035                m_pGoggleL->setCastShadows(false) ;
2036
2037        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2038
2039        // right goggle
2040
2041                if(m_pGoggleR==NULL) m_pGoggleR=m_pSceneMgr->createManualObject("GoggleR") ;
2042                m_pGoggleR->begin("RttMat_DfShMix", RenderOperation::OT_TRIANGLE_LIST) ;
2043
2044
2045                flMinX=0 ;
2046                flMinY=-50*m_flGoggleYScale ;
2047
2048
2049                flMaxX=100*m_flGoggleAspectRatio*m_flGoggleXScale ;
2050                flMaxY=50*m_flGoggleYScale ;
2051
2052               
2053                m_pGoggleR->position(flMinX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
2054                m_pGoggleR->normal(0.0, 0.0, -1) ;
2055                m_pGoggleR->textureCoord(0.0, 0.0) ;
2056                m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
2057                m_pGoggleR->normal(0.0, 0.0, -1) ;
2058                m_pGoggleR->textureCoord(1.0, 0.0) ;
2059                m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
2060                m_pGoggleR->normal(0.0, 0.0, -1) ;
2061                m_pGoggleR->textureCoord(1.0, 1.0) ;
2062                m_pGoggleR->position(flMinX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
2063                m_pGoggleR->normal(0.0, 0.0, -1) ;
2064                m_pGoggleR->textureCoord(0.0, 1.0) ;
2065
2066                m_pGoggleR->quad(3, 2, 1, 0) ;
2067                m_pGoggleR->end() ;
2068
2069                m_pGoggleR->setCastShadows(false) ;
2070               
2071        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2072
2073        // attach the goggles to the node.
2074        if(m_pNodeGoggles==NULL) m_pNodeGoggles=m_pSceneMgr->getRootSceneNode()->createChildSceneNode("NodeGoggles") ;
2075        m_pNodeGoggles->attachObject(m_pGoggleL) ;
2076        m_pNodeGoggles->attachObject(m_pGoggleR) ;
2077
2078        return 1 ;
2079}
2080
2081// create the "virtual" virtual reality goggles we use to get around stereoscopic driver problems.
2082// This version of the goggles just has a test image for setting up the correct real driver settings,
2083// so that the left eye sees only the left "goggle" and the right eye only the right "goggle",
2084// and the goggles have the right depth relative to the screen (flat to it)
2085int OgreFramework::CreateGogglesTestImage() 
2086{
2087
2088        float flMinX=0.0f ;
2089        float flMinY=0.0f ;
2090        float flMaxX=0.0f ;
2091        float flMaxY=0.0f ;
2092
2093
2094        // if they already exist, destroy them so we can recreate them
2095        if(m_pNodeGoggles!=NULL)        m_pNodeGoggles->detachAllObjects() ;
2096        if(m_pGoggleL!=NULL)                    m_pGoggleL->clear() ;
2097        if(m_pGoggleR!=NULL)                    m_pGoggleR->clear() ;
2098       
2099
2100        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2101
2102        // left goggle
2103
2104                if(m_pGoggleL==NULL) m_pGoggleL=m_pSceneMgr->createManualObject("GoggleL") ;
2105                m_pGoggleL->begin("GoggleTest", RenderOperation::OT_TRIANGLE_LIST) ;
2106       
2107                flMinX=-100*m_flGoggleAspectRatio*m_flGoggleXScale ;
2108                flMinY=-50*m_flGoggleYScale ;
2109
2110
2111                flMaxX=0 ;
2112                flMaxY=50*m_flGoggleYScale ;
2113
2114               
2115                m_pGoggleL->position(flMinX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
2116                m_pGoggleL->normal(0.0, 0.0, -1) ;
2117                m_pGoggleL->textureCoord(0.0, 0.0) ;
2118                m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
2119                m_pGoggleL->normal(0.0, 0.0, -1) ;
2120                m_pGoggleL->textureCoord(1.0, 0.0) ;
2121                m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
2122                m_pGoggleL->normal(0.0, 0.0, -1) ;
2123                m_pGoggleL->textureCoord(1.0, 1.0) ;
2124                m_pGoggleL->position(flMinX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
2125                m_pGoggleL->normal(0.0, 0.0, -1) ;
2126                m_pGoggleL->textureCoord(0.0, 1.0) ;
2127
2128                m_pGoggleL->quad(3, 2, 1, 0) ;
2129                m_pGoggleL->end() ;
2130
2131                m_pGoggleL->setCastShadows(false) ;
2132
2133        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2134
2135        // right goggle
2136
2137                if(m_pGoggleR==NULL) m_pGoggleR=m_pSceneMgr->createManualObject("GoggleR") ;
2138                m_pGoggleR->begin("GoggleTest", RenderOperation::OT_TRIANGLE_LIST) ;
2139
2140
2141                flMinX=0 ;
2142                flMinY=-50*m_flGoggleYScale ;
2143
2144
2145                flMaxX=100*m_flGoggleAspectRatio*m_flGoggleXScale ;
2146                flMaxY=50*m_flGoggleYScale ;
2147
2148               
2149                m_pGoggleR->position(flMinX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
2150                m_pGoggleR->normal(0.0, 0.0, -1) ;
2151                m_pGoggleR->textureCoord(1.0, 1.0) ;
2152                m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
2153                m_pGoggleR->normal(0.0, 0.0, -1) ;
2154                m_pGoggleR->textureCoord(0.0, 1.0) ;
2155                m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
2156                m_pGoggleR->normal(0.0, 0.0, -1) ;
2157                m_pGoggleR->textureCoord(0.0, 0.0) ;
2158                m_pGoggleR->position(flMinX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
2159                m_pGoggleR->normal(0.0, 0.0, -1) ;
2160                m_pGoggleR->textureCoord(1.0, 0.0) ;
2161
2162                m_pGoggleR->quad(3, 2, 1, 0) ;
2163                m_pGoggleR->end() ;
2164
2165                m_pGoggleR->setCastShadows(false) ;
2166               
2167        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2168
2169        // attach the goggles to the node.
2170        if(m_pNodeGoggles==NULL) m_pNodeGoggles=m_pSceneMgr->getRootSceneNode()->createChildSceneNode("NodeGoggles") ;
2171        m_pNodeGoggles->attachObject(m_pGoggleL) ;
2172        m_pNodeGoggles->attachObject(m_pGoggleR) ;
2173
2174        return 1 ;
2175}
2176
2177//|||||||||||||||||||||||||||||||||||||||||||||||
2178
2179bool OgreFramework::keyPressed(const OIS::KeyEvent &keyEventRef)
2180{
2181        //m_pLog->logMessage("OgreFramework::keyPressed");
2182       
2183        if(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
2184        {
2185                        m_bShutDownOgre = true;
2186                        return true;
2187        }
2188
2189        if(m_pKeyboard->isKeyDown(OIS::KC_SYSRQ))
2190        {
2191                std::ostringstream ss;
2192                ss << "screenshot_" << ++m_iNumScreenShots << ".png";
2193                m_pRenderWnd->writeContentsToFile(ss.str());
2194                return true;
2195        }
2196
2197        /*
2198        if(m_pKeyboard->isKeyDown(OIS::KC_M))
2199        {
2200                static int mode = 0;
2201               
2202                if(mode == 2)
2203                {
2204                        m_pCamera->setPolygonMode(PM_SOLID);
2205                        mode = 0;
2206                }
2207                else if(mode == 0)
2208                {
2209                         m_pCamera->setPolygonMode(PM_WIREFRAME);
2210                         mode = 1;
2211                }
2212                else if(mode == 1)
2213                {
2214                        m_pCamera->setPolygonMode(PM_POINTS);
2215                        mode = 2;
2216                }
2217        }
2218        */
2219
2220        if(m_pKeyboard->isKeyDown(OIS::KC_O))
2221        {
2222                if(m_pDebugOverlay)
2223                {
2224                        if(!m_pDebugOverlay->isVisible())
2225                                m_pDebugOverlay->show();
2226                        else
2227                                m_pDebugOverlay->hide();
2228                }
2229        }
2230
2231
2232
2233        return true;
2234}
2235
2236//|||||||||||||||||||||||||||||||||||||||||||||||
2237
2238bool OgreFramework::keyReleased(const OIS::KeyEvent &keyEventRef)
2239{
2240        return true;
2241}
2242
2243//|||||||||||||||||||||||||||||||||||||||||||||||
2244
2245bool OgreFramework::mouseMoved(const OIS::MouseEvent &evt)
2246{
2247        m_pCamera->yaw(Degree(evt.state.X.rel * -0.1));
2248        m_pCamera->pitch(Degree(evt.state.Y.rel * -0.1));
2249       
2250        return true;
2251}
2252
2253//|||||||||||||||||||||||||||||||||||||||||||||||
2254
2255bool OgreFramework::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
2256{
2257        return true;
2258}
2259
2260//|||||||||||||||||||||||||||||||||||||||||||||||
2261
2262bool OgreFramework::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
2263{
2264        return true;
2265}
2266
2267//|||||||||||||||||||||||||||||||||||||||||||||||
2268
2269void OgreFramework::updateOgre(double timeSinceLastFrame)
2270{
2271
2272
2273
2274
2275        // update the game time
2276        m_GameTime+=timeSinceLastFrame ;
2277
2278
2279        m_MoveScale = m_MoveSpeed   * timeSinceLastFrame;
2280        m_RotScale  = m_RotateSpeed * timeSinceLastFrame;
2281               
2282        m_TranslateVector = Vector3::ZERO;
2283
2284//      char chMessage[1024] ;
2285        //sprintf(chMessage, "winmessage %u, %u, %u", m_pRenderWnd->m_Test_uMsg, (UINT)m_pRenderWnd->m_Test_wParam, (UINT)m_pRenderWnd->m_Test_lParam) ;
2286        //m_pLog->logMessage(chMessage) ;
2287
2288
2289
2290        /*
2291        if((m_pRenderWnd->m_Test_uMsg==258) && (m_pRenderWnd->m_Test_wParam==0x78))
2292        //if(GetAsyncKeyState(0x78))
2293        {
2294
2295                m_TranslateVector.z = -m_MoveScale;
2296                //m_nGotInput=1 ;
2297               
2298                //sprintf(chMessage, "T %i: winmessage %u, %u, %u", m_nTime, m_pRenderWnd->m_Test_uMsg, (UINT)m_pRenderWnd->m_Test_wParam, (UINT)m_pRenderWnd->m_Test_lParam) ;
2299                //m_pLog->logMessage(chMessage) ;
2300        }
2301        else
2302                m_nGotInput=0 ;
2303        */
2304
2305        // add a test particle to the system
2306        /*
2307        if( m_ps->getNumParticles() < m_ps->getParticleQuota() )
2308        {
2309                Ogre::Particle *p = m_ps->createParticle() ;
2310                p->setDimensions( m_ps->getDefaultWidth(), m_ps->getDefaultHeight() ) ;
2311                p->colour = Ogre::ColourValue::White;
2312                p->direction = Ogre::Vector3::UNIT_Y;
2313                p->position = Ogre::Vector3::ZERO;
2314                p->timeToLive = p->totalTimeToLive = 10;
2315                p->rotation = Ogre::Radian(0);   
2316                p->rotationSpeed = Ogre::Radian(0);
2317        }
2318        */
2319
2320
2321        m_ps->_update(timeSinceLastFrame/1000.0f) ;
2322
2323        getInput();
2324
2325        moveCamera();
2326
2327
2328        //Ogre::Vector3 Pos ;
2329        //float CamPos[3] ;
2330        //Pos=m_pCamera->getPosition() ;
2331        //CamPos[0]=Pos.x ;
2332        //CamPos[1]=Pos.y ;
2333        //CamPos[2]=Pos.z ;
2334
2335
2336
2337        if(m_nGoggleMode==GOGGLE_MODE_OFF)
2338        {
2339
2340
2341                m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ; // copy the camera's original settings because we'll be modifying it for the LR views.
2342                m_pCameraCopy->setFOVy( Degree(m_flFOV) ) ;
2343                m_pCameraCopy->setAspectRatio( Real(m_flAspectRatio) );
2344
2345
2346
2347                if(m_nMapLoaded)
2348                {
2349                        SetupEntityZones() ;
2350                       
2351                        CalculateZoneVisibility(m_pCameraCopy, &m_nCameraZoneL, m_chZoneVisL, m_chLightVisL, m_chSubLightVisL, m_chPortalVisL, &m_nMaxVisibleLightL, m_uVisibleLightListL) ;
2352                        CalculateEntityVisibility(m_pCameraCopy, m_chZoneVisL) ;
2353
2354                        UpdateVisibleZoneList(m_chZoneVisL, m_uVisibleZoneListL, &m_nMaxVisibleZoneL) ;
2355
2356                        //m_nVisibleLightCount=m_nMaxVisibleLightL ;
2357                        m_nVisibleZoneCount=m_nMaxVisibleZoneL ;
2358                }
2359
2360
2361
2362                m_pGlobal_VisibleZoneList=m_uVisibleZoneListL ;
2363                m_pGlobal_MaxVisibleZone=&m_nMaxVisibleZoneL ;
2364
2365                m_pGlobal_VisibleLightList      =       m_uVisibleLightListL ;
2366                m_pGlobal_MaxVisibleLight               =       &m_nMaxVisibleLightL ;
2367                m_pGlobal_LightVis                                      =       m_chLightVisL ;
2368
2369
2370        }
2371        else
2372        {
2373                // "virtual" stereo goggle mode.  Render everything twice, L and R view, and output to L quad and a R quad.
2374
2375                m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ; // copy the camera's original settings because we'll be modifying it for the LR views.
2376
2377                if(m_nMapLoaded)
2378                {
2379                        SetupEntityZones() ;
2380
2381                        CalculateZoneVisibility(m_pCameraCopy, &m_nCameraZoneL, m_chZoneVisL, m_chLightVisL, m_chSubLightVisL, m_chPortalVisL, &m_nMaxVisibleLightL, m_uVisibleLightListL) ;
2382                        UpdateVisibleZoneList(m_chZoneVisL, m_uVisibleZoneListL, &m_nMaxVisibleZoneL) ;
2383
2384                       
2385                        //m_nVisibleLightCount=m_nMaxVisibleLightL ;
2386                        m_nVisibleZoneCount=m_nMaxVisibleZoneL ;
2387                }
2388
2389                m_pGlobal_VisibleZoneList=m_uVisibleZoneListL ;
2390                m_pGlobal_MaxVisibleZone=&m_nMaxVisibleZoneL ;
2391        }
2392
2393
2394        updateStats();
2395
2396
2397        //,,
2398        //sprintf(m_chFrame, "End of updateOgre frame %i",m_nFrame) ;
2399        //OFBug.LogAddCR(m_chFrame) ;
2400       
2401
2402
2403        m_nFrame++ ;
2404
2405
2406       
2407}
2408
2409
2410
2411//|||||||||||||||||||||||||||||||||||||||||||||||
2412
2413void OgreFramework::updateStats() 
2414{ 
2415       
2416       
2417        Ogre::Vector3 Pos ;
2418        Pos=m_pCamera->getPosition() ;
2419        Ogre::Real nCamX=Pos.x ;
2420        Ogre::Real nCamY=Pos.y ;
2421        Ogre::Real nCamZ=Pos.z ;
2422
2423
2424        static String currFps = "FPS: "; 
2425    static String avgFps = "Av FPS: "; 
2426    static String bestFps = "Best FPS: "; 
2427    static String worstFps = "Worst FPS: "; 
2428    static String tris = "Triangle Count: "; 
2429    static String batches = "Batch Count: "; 
2430
2431 
2432    OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps"); 
2433    OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps"); 
2434    OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps"); 
2435    OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps"); 
2436
2437        const RenderTarget::FrameStats& stats = m_pRenderWnd->getStatistics();
2438   
2439                //int LastFrameTime=1000000/stats.lastFPS ;
2440                float LastFrameTime=1000/stats.lastFPS ;
2441
2442
2443
2444
2445
2446                switch(m_nDisplayInfoMode)
2447                {
2448
2449                        case 0:
2450                                if(m_IsOpenGL)
2451                                        guiCurr->setCaption("OGL FPS: " + StringConverter::toString(stats.lastFPS) +" "+StringConverter::toString(LastFrameTime)+" ms"); 
2452                                else
2453                                        guiCurr->setCaption("D3D FPS: " + StringConverter::toString(stats.lastFPS) +" "+StringConverter::toString(LastFrameTime)+" ms"); 
2454                                break ;
2455
2456                        case 1: guiCurr->setCaption("Wireframe") ; break ;
2457                        case 2: guiCurr->setCaption("Lamps") ; break ;
2458                        case 3: guiCurr->setCaption("HDR Blur") ; break ;
2459                        case 4: guiCurr->setCaption("DefShade Position (Scaled)") ; break ;
2460                        case 5: guiCurr->setCaption("DefShade Normals") ; break ;
2461                        case 6: guiCurr->setCaption("DefShade Diffuse") ; break ;
2462                        case 7: guiCurr->setCaption("DefShade Specular") ; break ;
2463                        case 8: guiCurr->setCaption("DefShade Emissive") ; break ;
2464
2465                }
2466
2467                guiAvg->setCaption("Lt: " + StringConverter::toString(m_nVisibleLightCount)
2468                        + " Zn: " + StringConverter::toString(m_nVisibleZoneCount) 
2469                        + " Cam: "+StringConverter::toString(nCamX)+" "+StringConverter::toString(nCamY)+" "+StringConverter::toString(nCamZ));
2470
2471
2472
2473
2474                //m_flDebug0=m_nTotalTriangles ;
2475                //m_flDebug1=m_nMaxVisibleEntity ;
2476                //m_flDebug2=m_nMaxFrustumEntity ;
2477                guiWorst->setCaption("ZnEnt: " + StringConverter::toString(m_nMaxVisibleEntity) + " Tri: " + StringConverter::toString(m_nVisibleEntityTriangleCount) + " FwdTri: " + StringConverter::toString(m_nVisibleEntityTriangleCount)    ) ;
2478                guiBest->setCaption("FrEnt: " + StringConverter::toString(m_nMaxFrustumEntity) + " Tri: " + StringConverter::toString(m_nFrustumEntityTriangleCount) + " DefTri: " + StringConverter::toString(m_nFrustumEntityTriangleCount)    ) ;
2479
2480
2481
2482
2483                //guiWorst->setCaption(StringConverter::toString(m_flDebug0) + " " + StringConverter::toString(m_flDebug1) + " " + StringConverter::toString(m_flDebug2)) ;
2484                //guiBest->setCaption(StringConverter::toString(m_flDebug3) + " " + StringConverter::toString(m_flDebug4) + " " + StringConverter::toString(m_flDebug5)) ;
2485                /*
2486                guiWorst->setCaption(
2487                        " A "+StringConverter::toString(m_flDebugMatrix[0][0])+" "+StringConverter::toString(m_flDebugMatrix[0][1])+" "+StringConverter::toString(m_flDebugMatrix[0][2])+" "+StringConverter::toString(m_flDebugMatrix[0][3]) +
2488                        " B "+StringConverter::toString(m_flDebugMatrix[1][0])+" "+StringConverter::toString(m_flDebugMatrix[1][1])+" "+StringConverter::toString(m_flDebugMatrix[1][2])+" "+StringConverter::toString(m_flDebugMatrix[1][3]) ) ;
2489
2490                guiBest->setCaption(
2491                        " C "+StringConverter::toString(m_flDebugMatrix[2][0])+" "+StringConverter::toString(m_flDebugMatrix[2][1])+" "+StringConverter::toString(m_flDebugMatrix[2][2])+" "+StringConverter::toString(m_flDebugMatrix[2][3]) +
2492                        " D "+StringConverter::toString(m_flDebugMatrix[3][0])+" "+StringConverter::toString(m_flDebugMatrix[3][1])+" "+StringConverter::toString(m_flDebugMatrix[3][2])+" "+StringConverter::toString(m_flDebugMatrix[3][3]) ) ;
2493                */
2494       
2495               
2496               
2497               
2498                //guiWorst->setCaption(StringConverter::toString(flVarA)+" "+StringConverter::toString(flVarB)+" "+StringConverter::toString(flVarC)+" "+StringConverter::toString(flVarD)
2499   
2500        //guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)
2501  //          +" "+StringConverter::toString(stats.bestFrameTime)+" ms");
2502        //guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)
2503  //          +" "+StringConverter::toString(stats.worstFrameTime)+" ms");
2504       
2505        //guiWorst->setCaption(worstFps + StringConverter::toString(nCamX)+" " + StringConverter::toString(nCamY)+" " + StringConverter::toString(nCamZ)+" ") ;
2506   
2507       
2508        OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris"); 
2509        guiTris->setCaption("MpTri: " + StringConverter::toString(m_nTotalTriangles)); 
2510
2511        OverlayElement* guiBatches = OverlayManager::getSingleton().getOverlayElement("Core/NumBatches"); 
2512    guiBatches->setCaption(batches + StringConverter::toString(stats.batchCount)); 
2513
2514        OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText"); 
2515                guiDbg->setCaption("A:"+StringConverter::toString(m_nDebugA) + " B:" + StringConverter::toString(m_nDebugB) + " C:" + StringConverter::toString(m_nDebugC) + " ") ;
2516       
2517        //guiDbg->setCaption(
2518        //      " A "+StringConverter::toString(m_flDebugMatrix[0][0])+" "+StringConverter::toString(m_flDebugMatrix[0][1])+" "+StringConverter::toString(m_flDebugMatrix[0][2])+" "+StringConverter::toString(m_flDebugMatrix[0][3]) +
2519        //      " B "+StringConverter::toString(m_flDebugMatrix[1][0])+" "+StringConverter::toString(m_flDebugMatrix[1][1])+" "+StringConverter::toString(m_flDebugMatrix[1][2])+" "+StringConverter::toString(m_flDebugMatrix[1][3]) +
2520        //      " C "+StringConverter::toString(m_flDebugMatrix[2][0])+" "+StringConverter::toString(m_flDebugMatrix[2][1])+" "+StringConverter::toString(m_flDebugMatrix[2][2])+" "+StringConverter::toString(m_flDebugMatrix[2][3]) +
2521        //      " D "+StringConverter::toString(m_flDebugMatrix[3][0])+" "+StringConverter::toString(m_flDebugMatrix[3][1])+" "+StringConverter::toString(m_flDebugMatrix[3][2])+" "+StringConverter::toString(m_flDebugMatrix[3][3]) ) ;
2522
2523
2524
2525
2526        //guiDbg->setCaption("");
2527} 
2528
2529//|||||||||||||||||||||||||||||||||||||||||||||||
2530
2531void OgreFramework::moveCamera()
2532{
2533        if( m_nKeyDown_Ctrl && m_nKeyDown_Shift ) // super slow
2534                        m_pCamera->moveRelative(m_TranslateVector/50);
2535                else
2536                        if(m_nKeyDown_Shift)    // fast
2537                                m_pCamera->moveRelative(m_TranslateVector*10);
2538                        else
2539                                if(m_nKeyDown_Ctrl) // slow
2540                                        m_pCamera->moveRelative(m_TranslateVector/5);
2541                                else
2542                                        m_pCamera->moveRelative(m_TranslateVector*2); // normal
2543}
2544
2545//|||||||||||||||||||||||||||||||||||||||||||||||
2546
2547void OgreFramework::getInput()
2548{
2549        if(m_pKeyboard->isKeyDown(OIS::KC_LCONTROL))
2550                m_nKeyDown_Ctrl=1 ;
2551        else
2552                m_nKeyDown_Ctrl=0 ;
2553
2554        if(m_pKeyboard->isKeyDown(OIS::KC_LSHIFT))
2555                m_nKeyDown_Shift=1 ;
2556        else
2557                m_nKeyDown_Shift=0 ;
2558
2559
2560
2561
2562
2563
2564        if(m_pKeyboard->isKeyDown(OIS::KC_A))
2565        {
2566                m_TranslateVector.x = -m_MoveScale;
2567        }
2568
2569        if(m_pKeyboard->isKeyDown(OIS::KC_D))
2570        {
2571                m_TranslateVector.x = m_MoveScale;
2572        }
2573
2574        if(m_pKeyboard->isKeyDown(OIS::KC_W))
2575        {
2576                m_TranslateVector.z = -m_MoveScale;
2577                m_nGotInput=1 ;
2578        }
2579
2580        if(m_pKeyboard->isKeyDown(OIS::KC_S))
2581        {
2582                m_TranslateVector.z = m_MoveScale;
2583        }
2584
2585
2586        // generic toggle for debugging
2587        if(m_pKeyboard->isKeyDown(OIS::KC_T))
2588        {
2589                if(m_nKeyToggle[OIS::KC_T]==0)
2590                {
2591                        m_nKeyToggle[OIS::KC_T]=1 ; // toggle to stop key repeating
2592                        m_nToggle=1-m_nToggle ;
2593                        //OFBug.MessageInt(m_nToggle) ;
2594                }
2595        }
2596        else
2597                m_nKeyToggle[OIS::KC_T]=0 ;
2598
2599        //m_flDebug0=m_nKeyToggle[OIS::KC_T] ;
2600        //m_flDebug1=m_nToggle ;
2601
2602        /*
2603        if(m_pKeyboard->isKeyDown(OIS::KC_LEFT))
2604        {
2605                m_pCamera->yaw(m_RotScale);
2606        }
2607
2608        if(m_pKeyboard->isKeyDown(OIS::KC_RIGHT))
2609        {
2610                m_pCamera->yaw(-m_RotScale);
2611        }
2612
2613        if(m_pKeyboard->isKeyDown(OIS::KC_UP))
2614        {
2615                m_pCamera->pitch(m_RotScale);
2616        }
2617
2618        if(m_pKeyboard->isKeyDown(OIS::KC_DOWN))
2619        {
2620                m_pCamera->pitch(-m_RotScale);
2621        }
2622        */
2623
2624        /////////////////////////////////////////////////////////////////////////////////////////////////////////
2625        //
2626        // Stereo controls
2627
2628       
2629
2630        // toggle stereo test image mode
2631        if(m_pKeyboard->isKeyDown(OIS::KC_DELETE))
2632        {
2633                if(m_nKeyToggle[OIS::KC_DELETE]==0)
2634                {
2635                        m_nKeyToggle[OIS::KC_DELETE]=1 ; // toggle to stop key repeating
2636                       
2637                        m_nGoggleMode++ ; // cyle through the goggle modes
2638                        if(m_nGoggleMode>=GOGGLE_MODE_MAX)
2639                                m_nGoggleMode=GOGGLE_MODE_OFF ;
2640
2641                        if(m_nGoggleMode==GOGGLE_MODE_TEST)
2642                                CreateGogglesTestImage() ; // create the test goggles
2643                        else
2644                                if(m_nGoggleMode==GOGGLE_MODE_ON)
2645                                        CreateGoggles() ; // create the stereo goggles
2646                }
2647        }
2648        else
2649                m_nKeyToggle[OIS::KC_DELETE]=0 ;
2650
2651        if(m_nGoggleMode==GOGGLE_MODE_TEST) // controls for setting up the test image
2652        {
2653                int nDoPause=0 ; // if any control gets used we do a quick pause to make the rate of change a bit more consistent, not as frame-rate dependent
2654
2655                if(m_pKeyboard->isKeyDown(OIS::KC_PGUP))
2656                {
2657                        nDoPause=1 ;
2658
2659                        if(m_nKeyDown_Shift)
2660                                m_flGoggleZPos-=1.0 ;
2661                        else
2662                                if(m_nKeyDown_Ctrl)
2663                                        m_flGoggleZPos-=0.01 ;
2664                                else
2665                                        m_flGoggleZPos-=0.1 ;
2666
2667                        CreateGogglesTestImage() ;
2668                }
2669
2670                if(m_pKeyboard->isKeyDown(OIS::KC_PGDOWN))
2671                {
2672                        nDoPause=1 ;
2673
2674                        if(m_nKeyDown_Shift)
2675                                m_flGoggleZPos+=1.0 ;
2676                        else
2677                                if(m_nKeyDown_Ctrl)
2678                                        m_flGoggleZPos+=0.01 ;
2679                                else
2680                                        m_flGoggleZPos+=0.1 ;
2681
2682                        CreateGogglesTestImage() ;
2683                }
2684
2685                if(m_pKeyboard->isKeyDown(OIS::KC_HOME))
2686                {
2687                        nDoPause=1 ;
2688
2689                        if(m_nKeyDown_Shift)
2690                                m_flGoggleXGap-=0.1 ;
2691                        else
2692                                if(m_nKeyDown_Ctrl)
2693                                        m_flGoggleXGap-=0.001 ;
2694                                else
2695                                        m_flGoggleXGap-=0.01 ;
2696
2697                        if(m_flGoggleXGap<0)
2698                                m_flGoggleXGap=0 ;
2699
2700                        CreateGogglesTestImage() ;
2701                }
2702
2703                if(m_pKeyboard->isKeyDown(OIS::KC_END))
2704                {
2705                        nDoPause=1 ;
2706
2707                        if(m_nKeyDown_Shift)
2708                                m_flGoggleXGap+=0.1 ;
2709                        else
2710                                if(m_nKeyDown_Ctrl)
2711                                        m_flGoggleXGap+=0.001 ;
2712                                else
2713                                        m_flGoggleXGap+=0.01 ;
2714
2715                        if(m_flGoggleXGap<0)
2716                                m_flGoggleXGap=0 ;
2717
2718                        CreateGogglesTestImage() ;
2719                }
2720
2721                if(m_pKeyboard->isKeyDown(OIS::KC_UP))
2722                {
2723                        nDoPause=1 ;
2724
2725                        if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
2726                                m_flGoggleYScale=1.0 ;
2727                        else
2728                                if(m_nKeyDown_Shift)
2729                                        m_flGoggleYScale+=0.002 ;
2730                                else
2731                                        if(m_nKeyDown_Ctrl)
2732                                                m_flGoggleYScale+=0.00002 ;
2733                                        else
2734                                                m_flGoggleYScale+=0.0002 ;
2735
2736                                if(m_flGoggleYScale<0)
2737                                        m_flGoggleYScale=0 ;
2738
2739                                CreateGogglesTestImage() ;
2740                }
2741
2742                if(m_pKeyboard->isKeyDown(OIS::KC_DOWN))
2743                {
2744                        nDoPause=1 ;
2745
2746                        if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
2747                                m_flGoggleYScale=1.0 ;
2748                        else
2749                                if(m_nKeyDown_Shift)
2750                                        m_flGoggleYScale-=0.002 ;
2751                                else
2752                                        if(m_nKeyDown_Ctrl)
2753                                                m_flGoggleYScale-=0.00002 ;
2754                                        else
2755                                                m_flGoggleYScale-=0.0002 ;
2756
2757                        if(m_flGoggleYScale<0)
2758                                m_flGoggleYScale=0 ;
2759
2760                        CreateGogglesTestImage() ;
2761                }
2762
2763                if(m_pKeyboard->isKeyDown(OIS::KC_LEFT))
2764                {
2765                        nDoPause=1 ;
2766
2767                        if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
2768                                m_flGoggleXScale=1.0 ;
2769                        else
2770                                if(m_nKeyDown_Shift)
2771                                        m_flGoggleXScale+=0.002 ;
2772                                else
2773                                        if(m_nKeyDown_Ctrl)
2774                                                m_flGoggleXScale+=0.00002 ;
2775                                        else
2776                                                m_flGoggleXScale+=0.0002 ;
2777
2778                        if(m_flGoggleXScale<0)
2779                                m_flGoggleXScale=0 ;
2780
2781                        CreateGogglesTestImage() ;
2782                }
2783
2784                if(m_pKeyboard->isKeyDown(OIS::KC_RIGHT))
2785                {
2786                        nDoPause=1 ;
2787
2788                        if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
2789                                m_flGoggleXScale=1.0 ;
2790                        else
2791                                if(m_nKeyDown_Shift)
2792                                        m_flGoggleXScale-=0.002 ;
2793                                else
2794                                        if(m_nKeyDown_Ctrl)
2795                                                m_flGoggleXScale-=0.00002 ;
2796                                        else
2797                                                m_flGoggleXScale-=0.0002 ;
2798
2799                        if(m_flGoggleXScale<0)
2800                                m_flGoggleXScale=0 ;
2801
2802                        CreateGogglesTestImage() ;
2803                }
2804
2805               
2806
2807                if(nDoPause) Sleep(20) ; // pause makes rate more consisent, less frame rate dependent.
2808
2809        }// end test image controls
2810
2811       
2812
2813        //
2814        //
2815        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2816
2817        // flashlight
2818        if(m_pKeyboard->isKeyDown(OIS::KC_F))
2819        {
2820                if(m_nKeyToggle[OIS::KC_F]==0)
2821                {
2822                        m_nKeyToggle[OIS::KC_F]=1 ; // toggle to stop key repeating
2823                        m_nFlashLight=1-m_nFlashLight ;
2824                        m_nDebugA=m_nFlashLight ;
2825                        //OFBug.MessageInt(m_nToggle) ;
2826                }
2827        }
2828        else
2829                m_nKeyToggle[OIS::KC_F]=0 ;
2830
2831
2832        if(m_pKeyboard->isKeyDown(OIS::KC_J))
2833        {
2834                if(m_nJumpToggle==0)
2835                {
2836                        m_nJumpToggle=1 ;
2837
2838
2839                        m_nJumpVal++ ;
2840                        if(m_nJumpVal>=m_Q3Map->m_nLightMax)
2841                                m_nJumpVal=0 ;
2842
2843                        //m_flDebug0=m_nJumpVal ;
2844                       
2845                       
2846                        //m_nJumpVal=12 ; // for now always jump to light 0
2847                        //m_pCamera->setPosition(m_Q3Map->m_pLight[m_nJumpVal].Position[0], m_Q3Map->m_pLight[m_nJumpVal].Position[1], m_Q3Map->m_pLight[m_nJumpVal].Position[2]) ;
2848                        //m_nJumpVal=13 ;
2849                        //m_pCamera->lookAt(Vector3(m_Q3Map->m_pLight[m_nJumpVal].Position[0], m_Q3Map->m_pLight[m_nJumpVal].Position[1], m_Q3Map->m_pLight[m_nJumpVal].Position[2]));
2850                       
2851                        //m_pCamera->setPosition(166, 222, -111) ;
2852                        //m_pCamera->setDirection(0.707, 0, -0.707) ;
2853
2854                        //m_pCamera->setPosition(m_Q3Map->m_pLight[0].Position[0], m_Q3Map->m_pLight[0].Position[1], m_Q3Map->m_pLight[0].Position[2]) ;
2855                        //m_pCamera->setDirection(m_Q3Map->m_pLight[0].Direction[0], m_Q3Map->m_pLight[0].Direction[1], m_Q3Map->m_pLight[0].Direction[2]) ;
2856                        //m_pCamera->setFOVy( Degree(m_Q3Map->m_pLight[0].Angle ) ) ;
2857
2858                        //m_pCamera->setDirection(m_pLight[m_nJumpVal].Direction[0], m_pLight[m_nJumpVal].Direction[1], m_pLight[m_nJumpVal].Direction[2]) ;
2859                        // 880 120 -340
2860                        //m_pCamera->lookAt(Vector3(880,120,-340));
2861                        //m_pCamera->lookAt(Vector3(915,155,-340));
2862
2863
2864                        m_pCamera->setPosition(600, 200, -250) ;
2865                        //m_pCamera->setDirection(1.0, 0.0, 0.0) ;
2866                        m_pCamera->lookAt(700, 200, -450);
2867
2868                       
2869
2870                }
2871        }
2872        else
2873                m_nJumpToggle=0 ;
2874       
2875
2876        if(m_pKeyboard->isKeyDown(OIS::KC_L))
2877        {
2878                if(m_nLoadToggle==0)
2879                {
2880                        UnloadMap(false) ;
2881                        nMap++ ;
2882                        LoadMap() ;
2883                        //m_nLoadToggle=1 ;
2884                }
2885        }
2886        else
2887                m_nLoadToggle=0 ;
2888
2889
2890                // generic toggle for debugging
2891        if(m_pKeyboard->isKeyDown(OIS::KC_M))
2892        {
2893                if(m_nKeyToggle[OIS::KC_M]==0)
2894                {
2895                        m_nKeyToggle[OIS::KC_M]=1 ; // toggle to stop key repeating
2896
2897                        m_nDisplayInfoMode++ ;
2898                        if(m_nDisplayInfoMode==9)
2899                                m_nDisplayInfoMode=0 ;
2900
2901
2902
2903                }
2904        }
2905        else
2906                m_nKeyToggle[OIS::KC_M]=0 ;
2907
2908
2909
2910
2911
2912        //if(m_pKeyboard->isKeyDown(OIS::KC_K)) m_nVideoRestart=1 ;
2913
2914
2915        if(m_pKeyboard->isKeyDown(OIS::KC_P))
2916        {
2917                if(m_nPortalToggle==0)
2918                {
2919                        m_nPortalState=1-m_nPortalState ;
2920                        m_nPortalToggle=1 ;
2921                }
2922        }
2923        else
2924                m_nPortalToggle=0 ;
2925
2926        if(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
2927        {
2928                        m_bShutDownOgre = true;
2929        }
2930
2931}
2932
2933//|||||||||||||||||||||||||||||||||||||||||||||||
2934//shutdown
2935// the dynamic memory deletes are all safe, so it's ok to try and delete them even if they don't exist.
2936void OgreFramework::UnloadMap(bool bShutdown)
2937{       
2938
2939        //if(!bShutdown) DestroyRTTAssets() ;
2940
2941        //if(ResourceGroupManager::getSingleton().isResourceGroupLoaded("Raw Bsp"))
2942        //      ResourceGroupManager::getSingleton().clearResourceGroup("Raw Bsp") ;
2943
2944
2945        // only do if there was a definitely a map loaded.
2946        if(m_nMapLoaded)
2947        {
2948                char chSceneNodeName[1024] ;
2949                // make sure all the zone nodes are re-attached to the root node or they won't get deleted
2950                for(int nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
2951                {
2952                        // Opaque nodes
2953                        if(m_nOpaqueNodeUsed[nZone]) // only do this if the node actually exists
2954                        {
2955                                if(!m_pOpaqueNode[nZone]->isInSceneGraph())
2956                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
2957
2958                                sprintf(chSceneNodeName, "Opaque%05i", nZone) ;
2959                                m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
2960
2961                        }
2962
2963                        // Trans nodes
2964                        if(m_nTransNodeUsed[nZone]) // only do this if the node actually exists
2965                        {
2966                                if(!m_pTransNode[nZone]->isInSceneGraph())
2967                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
2968
2969                                sprintf(chSceneNodeName, "Trans%05i", nZone) ;
2970                                m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
2971
2972                        }
2973
2974                        // Lamp nodes
2975                        if(m_nLampNodeUsed[nZone]) // only do this if the node actually exists
2976                        {
2977                                if(!m_pLampNode[nZone]->isInSceneGraph())
2978                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
2979
2980                                sprintf(chSceneNodeName, "Lamp%05i", nZone) ;
2981                                m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
2982
2983                        }
2984
2985                        // Glow nodes
2986                        if(m_nGlowNodeUsed[nZone]) // only do this if the node actually exists
2987                        {
2988                                if(!m_pGlowNode[nZone]->isInSceneGraph())
2989                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
2990
2991                                sprintf(chSceneNodeName, "Glow%05i", nZone) ;
2992                                m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
2993
2994                        }
2995
2996                }
2997
2998
2999                // reattach all entity scenenodes.
3000                int nLoop=0 ;
3001//              int nSubMesh=0 ;
3002//              int nMaxSubMesh=0 ;
3003                for(nLoop=0 ; nLoop<m_nMaxEntity ; nLoop++)
3004                        m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[nLoop].pMasterNode) ;
3005
3006        }// end if map loaded
3007
3008
3009        // free ogre stuff
3010        //Ogre::ResourceGroupManager::getSingleton().clearResourceGroup(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) ;
3011
3012        //Ogre::ResourcePtr RTT=Ogre::TextureManager::getSingleton().getByName("RttTex") ;
3013        //Ogre::TextureManager::getSingleton().remove(RTT) ;
3014       
3015        //RTT_Texture->unload() ;
3016
3017       
3018
3019
3020       
3021       
3022
3023        //m_pSceneMgr->clearScene() ;
3024        m_pSceneMgr->getRootSceneNode()->removeAndDestroyAllChildren() ; // destroy all scenenodes
3025       
3026        m_pSceneMgr->destroyAllEntities() ;
3027        m_pSceneMgr->destroyAllLights() ;
3028        m_pSceneMgr->destroyAllManualObjects() ;
3029       
3030
3031        /*
3032        // unload all the meshes
3033        int nMaxMesh=m_nZoneMOStart[m_Q3Map->m_nMaxZone] ;
3034        int nMesh=0 ;
3035        for(nMesh=0 ; nMesh<nMaxMesh ; nMesh++)
3036        {
3037                m_pSceneMgr->destroyEntity(m_pZoneEntity[nMesh]) ;
3038                //m_pZoneMesh[nMesh]->cleanupDictionary() ;
3039                //m_pZoneMesh[nMesh]->unload() ;
3040
3041
3042        }
3043        */
3044       
3045        MeshManager::getSingleton().removeAll() ; // this destroys all the meshes
3046
3047       
3048
3049        //OFBug.MessageInt(333) ;
3050        //Ogre::TextureManager::getSingleton().unloadAll() ;
3051        //Ogre::TextureManager::getSingleton().removeAll() ;
3052       
3053        //Ogre::MaterialManager::getSingleton().unloadAll() ;
3054        //Ogre::MaterialManager::getSingleton().removeAll() ;
3055
3056       
3057
3058
3059
3060        //SetupResourceLocations() ;
3061
3062        // delete our array of Zone group manual objects
3063        //CHECKDELETE_ARRAY( m_pZoneMO ) ;
3064        CHECKDELETE_ARRAY( m_pZoneMesh, NEW_CHECK_m_pZoneMesh ) ; 
3065        CHECKDELETE_ARRAY( m_pZoneEntity, NEW_CHECK_m_pZoneEntity  ) ; 
3066        CHECKDELETE_ARRAY( m_pZoneEntityMaterialType, NEW_CHECK_m_pZoneEntityMaterialType  ) ; 
3067
3068
3069        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Shadow, NEW_CHECK_m_pZoneEntityMaterial_Shadow  ) ; 
3070        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeFront, NEW_CHECK_m_pZoneEntityMaterial_ShadeFront  ) ; 
3071        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeBack, NEW_CHECK_m_pZoneEntityMaterial_ShadeBack  ) ; 
3072
3073        int nPTex=0 ;
3074        for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
3075        {
3076                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Base[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Base  ) ; 
3077                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Fast[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Fast  ) ; 
3078        }
3079
3080        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Black, NEW_CHECK_m_pZoneEntityMaterial_Black  ) ; 
3081        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShColour, NEW_CHECK_m_pZoneEntityMaterial_DfShColour  ) ; 
3082        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShPosition, NEW_CHECK_m_pZoneEntityMaterial_DfShPosition  ) ; 
3083        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShDiffuse, NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse  ) ; 
3084        //CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DSNormal ) ;
3085        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShFuncTNB, NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB  ) ; 
3086        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShSpecular, NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular  ) ; 
3087        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShEmissive, NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive  ) ; 
3088        //CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShData ) ;
3089        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShMix, NEW_CHECK_m_pZoneEntityMaterial_DfShMix  ) ; 
3090
3091        ////////////////////////////////////////////////////////
3092        CHECKDELETE_ARRAY( m_pEntityInfo, NEW_CHECK_m_pEntityInfo  ) ; 
3093        CHECKDELETE_ARRAY( m_pVisibleEntity, NEW_CHECK_m_pVisibleEntity  ) ;
3094        CHECKDELETE_ARRAY( m_pFrustumEntity, NEW_CHECK_m_pFrustumEntity  ) ;
3095
3096
3097        // was leaking before, but this seems to have fixed things.
3098        Ogre::ResourceGroupManager::getSingleton().clearResourceGroup(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) ;
3099
3100        // delete our debug light manualobjects/zones
3101//      CHECKDELETE_ARRAY( m_pLightMO ) ;
3102
3103//      CHECKDELETE_ARRAY( m_pPortalMO ) ;
3104//      CHECKDELETE_ARRAY( m_pPortalNode ) ;
3105
3106        // free our dynamic memory
3107        if(m_Q3Map)
3108        {
3109                m_Q3Map->~Q3Map() ;             // get rid of all the m_Q3Map stuff
3110                CHECKDELETE_POINTER( m_Q3Map, NEW_CHECK_m_Q3Map) ; 
3111                m_Q3Map=NULL ;
3112        }
3113
3114        if(m_bRawBspFileIsLoaded) 
3115        {
3116                //m_pRawBspFile->unload() ;
3117                CHECKDELETE_ARRAY(m_pRawBspFile, NEW_CHECK_m_pRawBspFile ) ; 
3118                m_bRawBspFileIsLoaded=false ;
3119        }
3120
3121        // indicate that there is no map.
3122        m_nMapLoaded=0 ;
3123
3124       
3125
3126       
3127        int nCheck=0 ;
3128        for(nCheck=0 ; nCheck<MAX_NEW_CHECK ; nCheck++)
3129        if(m_nNewCheck[nCheck]!=0)
3130        {
3131                sprintf(m_chBug, "MEMORY LEAK: NewCheck %i, NewCount %i", nCheck, m_nNewCheck[nCheck]) ;
3132                m_pLog->logMessage(m_chBug) ;
3133        }
3134
3135
3136                //OFBug.MessageInt(333) ;
3137                //Sleep(50) ;
3138}
3139
3140
3141
3142
3143
3144
3145
3146
3147 /***********************************************************************************************************\
3148                                               
3149                                                 LOAD MAP
3150                                               
3151 \***********************************************************************************************************/
3152
3153
3154
3155
3156int OgreFramework::LoadMap(void)
3157{       
3158        m_pLog->logMessage("LoadMap.") ;
3159
3160
3161
3162        ZeroMemory((void*)m_nKeyToggle, sizeof(m_nKeyToggle)) ; // good place to clear the keytoggle just in case
3163
3164        m_pLog->logMessage("Pre InitAllResourceGroups.") ;
3165        Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();       
3166        m_pLog->logMessage("Post InitAllResourceGroups.") ;
3167
3168        // setup the clear material
3169        pClearMaterial=MaterialManager::getSingleton().getByName("Clear") ;
3170
3171       
3172        //CreateRTTAssets() ;
3173
3174
3175
3176        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3177
3178                m_pDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
3179                m_pDebugOverlay->show();
3180
3181                //m_MapName="test04e.bsp" ;
3182                //m_MapName="test04g.bsp" ;
3183                //m_MapName="test03f.bsp" ;
3184
3185                //m_MapName="testnew00a.bsp" ;
3186                //m_MapName="test04gNew.bsp" ;
3187
3188                //m_MapName="test10a.bsp" ;
3189                m_MapName="testmap06.bsp" ;
3190               
3191
3192                //////////////////////////////////////////////////////////////////////////////////////////////////
3193                // Load the file, get the data
3194       
3195
3196
3197                // open the stream to the bsp
3198                Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(m_MapName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
3199
3200                // create memory to hold the bsp
3201                size_t Size = stream->size() ;
3202                m_pRawBspFile= new char[Size] ;
3203                if( m_pRawBspFile==NULL) 
3204                        { m_pLog->logMessage("Error loading map: Initial load out of memory.")                  ; UnloadMap(false) ; return 0 ; }
3205                else
3206                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pRawBspFile]++ ; }
3207
3208                // stream bsp into memory
3209                stream->read((void*)m_pRawBspFile, Size) ;
3210
3211                // close the stream, don't need it anymore
3212                stream->close() ;
3213               
3214                // indicate that the raw bsp is loaded
3215                m_bRawBspFileIsLoaded=true ;
3216
3217
3218
3219       
3220
3221               
3222                //////////////////////////////////////////////////////////////////////////////////////////////////
3223                // Setup Q3Map
3224
3225                m_Q3Map=new Q3Map();
3226                if(m_Q3Map==NULL) 
3227                        { m_pLog->logMessage("Error loading map: New Map.")                     ; UnloadMap(false) ; return 0 ; }
3228                else
3229                        {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_Q3Map]++ ; }
3230
3231
3232
3233                m_pLog->logMessage("pre ParseMap") ;
3234
3235                // process the bsp, log errors and fail if needed.
3236                switch(m_Q3Map->ParseAndTriangulateMap( m_pRawBspFile, Size ) )
3237                {
3238                        case ERROR_ParseMap:                                            m_pLog->logMessage("Error loading map: Parse Map.") ;                                                   UnloadMap(false) ; return 0 ;
3239                        case ERROR_ParseEntities:                               m_pLog->logMessage("Error loading map: Parse Entities.") ;                              UnloadMap(false) ; return 0 ;
3240                        case ERROR_AllocateVertex:                      m_pLog->logMessage("Error loading map: Allocate Vertex.") ;                             UnloadMap(false) ; return 0 ;
3241                        case ERROR_AllocateTriangle:            m_pLog->logMessage("Error loading map: Allocate Triangle.") ;                   UnloadMap(false) ; return 0 ;
3242                        case ERROR_InitializeFaces:                     m_pLog->logMessage("Error loading map: Initialize Faces") ;                             UnloadMap(false) ; return 0 ;
3243                        case ERROR_ConvertFaces:                                m_pLog->logMessage("Error loading map: Convert Faces.") ;                                       UnloadMap(false) ; return 0 ;
3244                        case ERROR_ConvertPatches:                      m_pLog->logMessage("Error loading map: Convert Patches.") ;                             UnloadMap(false) ; return 0 ;
3245                        case ERROR_ConvertTexLamp:                      m_pLog->logMessage("Error loading map: Convert TexLamps.") ;                    UnloadMap(false) ; return 0 ;
3246                        case ERROR_ConvertLamps:                                m_pLog->logMessage("Error loading map: Convert Lamps.") ;                                       UnloadMap(false) ; return 0 ;
3247                        case ERROR_ConvertLampGlow:                     m_pLog->logMessage("Error loading map: Convert Lamp Glow.") ;                   UnloadMap(false) ; return 0 ;
3248                        case ERROR_ConvertLightGlow:            m_pLog->logMessage("Error loading map: Convert Light Glow.") ;          UnloadMap(false) ; return 0 ;
3249                        case ERROR_AssignTriangles:                     m_pLog->logMessage("Error loading map: Assign Triangles") ;                             UnloadMap(false) ; return 0 ;
3250                        case ERROR_SortTriangles:                               m_pLog->logMessage("Error loading map: Sort Triangles") ;                                       UnloadMap(false) ; return 0 ;
3251                        case ERROR_SetupTransTextures:  m_pLog->logMessage("Error loading map: Setup Trans Textures") ;         UnloadMap(false) ; return 0 ;
3252                        case ERROR_SortGroups:                                  m_pLog->logMessage("Error loading map: Sort Groups") ;                                          UnloadMap(false) ; return 0 ;
3253                }
3254
3255                m_pLog->logMessage("post ParseMap") ;
3256
3257                //////////////////////////////////////////////////////////////////////////////////////////////////
3258                // use the triangles to build our zone/texture manualObjects, which make up the map
3259                if(!ConstructMapFromTriangles()){ m_pLog->logMessage("Error loading map: Construct Map") ;              UnloadMap(false) ; return 0 ; }
3260
3261                ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3262                // delete all the stuff that was only needed for parsing the bsp and converting it into manaulObjects.
3263                m_Q3Map->FreeParseMem() ;
3264       
3265
3266
3267               
3268
3269               
3270               
3271                //////////////////////////////////////////////////////////////////////////////////////////////////
3272                // Create the scenenodes for the zones and attach the manualObjects
3273
3274                int nZone=0 ;
3275                char chSceneNodeName[1024] ;
3276                int nMO=0 ;
3277                int nZGStart=0 ;
3278                int nZGEnd=0 ;
3279
3280                char chMessage[1024] ;
3281                sprintf(chMessage, "Max Zones %i", m_Q3Map->m_nMaxZone) ; m_pLog->logMessage(chMessage) ;
3282                for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
3283                {
3284                        //sprintf(chMessage, "Zone %i Top", nZone) ; m_pLog->logMessage(chMessage) ;
3285
3286
3287                        // create Opaque node if needed
3288                        if(m_nOpaqueNodeUsed[nZone])
3289                        {
3290                                sprintf(chSceneNodeName, "Opaque%05i", nZone) ;
3291                                m_pOpaqueNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
3292                        }
3293
3294                        // create Trans node if needed
3295                        if(m_nTransNodeUsed[nZone])
3296                        {
3297                                sprintf(chSceneNodeName, "Trans%05i", nZone) ;
3298                                m_pTransNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
3299                        }
3300
3301                        // create Lamp node if needed
3302                        if(m_nLampNodeUsed[nZone])
3303                        {
3304                                sprintf(chSceneNodeName, "Lamp%05i", nZone) ;
3305                                m_pLampNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
3306                        }
3307
3308                        // create Glow node if needed
3309                        if(m_nGlowNodeUsed[nZone])
3310                        {
3311                                sprintf(chSceneNodeName, "Glow%05i", nZone) ;
3312                                m_pGlowNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
3313                        }
3314
3315                        // get start and end of this zone's batches. 
3316                        // If there's none, the start and end will be the same. (don't have to worry about checking for m_pZoneMO[nZone]==NULL)
3317                        nZGStart        =       m_nZoneMOStart[nZone] ;
3318                        nZGEnd          =       m_nZoneMOStart[nZone+1] ;
3319                       
3320                        //sprintf(chMessage, "  Zone %i, ZGStart %i, ZGEnd %i", nZone, nZGStart, nZGEnd) ; m_pLog->logMessage(chMessage) ;
3321
3322                        for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
3323                        {
3324                                //sprintf(chMessage, "    Zone %i, nMO %i", nZone, nMO) ; m_pLog->logMessage(chMessage) ;
3325
3326                                // attach the entity to the appropriate node
3327
3328                                if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
3329                                        m_pOpaqueNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
3330                                else
3331                                if(m_pZoneEntityMaterialType[nMO]==MAT_GEL)
3332                                        m_pTransNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
3333                                else
3334                                if(m_pZoneEntityMaterialType[nMO]==MAT_LAMP)
3335                                        m_pLampNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
3336                                else
3337                                if(m_pZoneEntityMaterialType[nMO]==MAT_GLOW)
3338                                        m_pGlowNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
3339                        }
3340
3341                }
3342
3343
3344                // add the game entities
3345                if(!SetupGameEntities()) { m_pLog->logMessage("Error loading map: Setup Entities") ;            UnloadMap(false) ; return 0 ; }
3346
3347
3348                // prior to the first frame, all zone scenenodes are detached.
3349                m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
3350
3351                //////////////////////////////////////////////////////////////////////////////////////////////////////
3352                // Setup the lights
3353
3354
3355
3356               
3357                initLight() ; 
3358
3359                //if(m_nDebugLightBox)
3360                //      AddLightCullingBoxes() ;
3361
3362
3363                //if(m_nPortalDebug)
3364                //      AddPortalBoxes() ;
3365
3366
3367                ///////////////////////////////////////////////////////////////////////////////////////////////////
3368                // misc finalization of the map
3369
3370                m_nCameraZone=-1 ; // indicate that we need to look up the zone the player is in.
3371                m_nCameraZoneL=-1 ;
3372                m_nCameraZoneR=-1 ;
3373
3374                m_nMapLoaded=1 ; // map was loaded ok
3375
3376
3377
3378                // set the camera's start position here.
3379                // I tried setting it during startup, but for some strange reason it didn't work IF the camera was in a zone
3380                // but was ok if the camera started outside a zone.  Bit of a mystery... but it makes more sense to set it here anyway.
3381                m_pCamera->setPosition(Vector3(0, 0, 0));
3382
3383                if(m_Q3Map->m_nLightMax>0) // make sure there's at least one light before we point to it!
3384                        m_pCamera->lookAt(Ogre::Vector3(m_Q3Map->m_pLight[0].Position[0], m_Q3Map->m_pLight[0].Position[1], m_Q3Map->m_pLight[0].Position[2])) ;
3385
3386
3387               
3388
3389                if(m_nGoggleMode==GOGGLE_MODE_TEST)
3390                                CreateGogglesTestImage() ; // create the test goggles
3391                        else
3392                                if(m_nGoggleMode==GOGGLE_MODE_ON)
3393                                        CreateGoggles() ; // create the stereo goggles
3394
3395
3396                SetupParticles() ;
3397
3398
3399                m_pLog->logMessage("LoadMap bottom.") ;
3400
3401                // reset the game timer
3402                m_GameTime=0.0 ;
3403                m_nFrame=0 ;
3404
3405
3406
3407                //OFBug.MessageInt(m_nNewCount) ;
3408
3409                return 1 ;
3410}
3411
3412//''
3413int OgreFramework::SetupParticles()
3414{
3415                        ParticleSystem::setDefaultNonVisibleUpdateTimeout(5);  // set nonvisible timeout
3416
3417               
3418
3419    // create some nice fireworks and place it at the origin
3420    //m_ps = m_pSceneMgr->createParticleSystem("Fireworks", "particle/fallspark00");
3421                m_ps = m_pSceneMgr->createParticleSystem("Fireworks", "particle/spark00");
3422                m_pParticleNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("ParticleNode") ;
3423                m_pParticleNode->attachObject(m_ps) ;
3424
3425                //m_pParticleNode->setPosition(360.0f, 360.0f, -860.0f) ;
3426                m_pParticleNode->setPosition(586.0f, 228.0f, -520.0f) ;
3427
3428
3429        return 1 ;
3430}
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451// take the sorted list of triangles and contruct our Zone manualObjects array, m_pZoneMO, etc
3452// and setup all the materials.
3453int OgreFramework::ConstructMapFromTriangles(void)
3454{
3455
3456
3457        int nVert=0 ;
3458        int nMaxVertex=0 ;
3459       
3460        float flPosX=0.0f ;
3461        float flPosY=0.0f ;
3462        float flPosZ=0.0f ;
3463        float   flNormX=0.0f ;
3464        float   flNormY=0.0f ;
3465        float   flNormZ=0.0f ;
3466        float flTexU=0.0f ;
3467        float flTexV=0.0f ;
3468
3469        float flLampPosX=0.0f ;
3470        float flLampPosY=0.0f ;
3471        float flLampPosZ=0.0f ;
3472        float flLampBrightness=0.0f ;
3473        float flLampR=0.0f ;
3474        float flLampG=0.0f ;
3475        float flLampB=0.0f ;
3476
3477        int nVertA=0 ;
3478        int nVertB=0 ;
3479        int nVertC=0 ;
3480
3481        char chMessage[1024] ;
3482
3483        int nZone=0 ;
3484        char chManualName[1024] ; // name for manual objects we create
3485        char chMeshName[1024] ;
3486
3487        int nTriangle=0 ;
3488//      int nStart=0 ;
3489        int nEnd=0 ;
3490        int nMaterial=0 ;
3491        int nGroup=0 ;
3492        int nTri=0 ;
3493        int nPos=0 ;
3494
3495        ZeroMemory((void*)m_nOpaqueNodeUsed, sizeof(m_nOpaqueNodeUsed)) ; // set all as unused
3496        ZeroMemory((void*)m_nTransNodeUsed, sizeof(m_nTransNodeUsed)) ; // set all as unused
3497        ZeroMemory((void*)m_nLampNodeUsed, sizeof(m_nLampNodeUsed)) ; // set all as unused
3498        ZeroMemory((void*)m_nGlowNodeUsed, sizeof(m_nGlowNodeUsed)) ; // set all as unused
3499       
3500        char chMaterial_Base[1024] ;
3501        MaterialPtr pMaterial_Base ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
3502       
3503        char chMaterial_Fast[1024] ;
3504        MaterialPtr pMaterial_Fast ; // faster version of the base, mainly non-coloured shadowning.
3505
3506        char chMaterial_Black[1024] ;
3507        MaterialPtr pMaterial_Black ; // just plain black, or black with alpha testing.
3508
3509        char chMaterial_DfShColour[1024] ;
3510        MaterialPtr pMaterial_DfShColour ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
3511       
3512
3513        char chMaterial_Shadow[1024] ;
3514        MaterialPtr pMaterial_Shadow ;
3515
3516        char chMaterial_ShadeFront[1024] ;
3517        MaterialPtr pMaterial_ShadeFront ;
3518
3519        char chMaterial_ShadeBack[1024] ;
3520        MaterialPtr pMaterial_ShadeBack ;
3521
3522        char chMaterial_DfShPosition[1024] ;
3523        MaterialPtr pMaterial_DfShPosition ;
3524       
3525        char chMaterial_DfShDiffuse[1024] ;
3526        MaterialPtr pMaterial_DfShDiffuse ;
3527       
3528        //char chMaterial_DSNormal[1024] ;
3529        //MaterialPtr pMaterial_DSNormal ;
3530       
3531        char chMaterial_DfShFuncTNB[1024] ;
3532        MaterialPtr pMaterial_DfShFuncTNB ;
3533
3534        char chMaterial_DfShSpecular[1024] ;
3535        MaterialPtr pMaterial_DfShSpecular ;
3536
3537        char chMaterial_DfShEmissive[1024] ;
3538        MaterialPtr pMaterial_DfShEmissive ;
3539
3540        //char chMaterial_DfShData[1024] ;
3541        //MaterialPtr pMaterial_DfShData ;
3542
3543        char chMaterial_DfShMix[1024] ;
3544        MaterialPtr pMaterial_DfShMix ;
3545
3546        char chCompare[1024] ;
3547
3548        // for calculating bounds of mesh
3549        float flMinX=0.0f ;
3550        float flMinY=0.0f ;
3551        float flMinZ=0.0f ;
3552        float flMaxX=0.0f ;
3553        float flMaxY=0.0f ;
3554        float flMaxZ=0.0f ;
3555//      float flMidX=0.0f ;
3556//      float flMidY=0.0f ;
3557//      float flMidZ=0.0f ;
3558        float flDisX=0.0f ;
3559        float flDisY=0.0f ;
3560        float flDisZ=0.0f ;
3561        float flRadius=0.0f ;
3562        AxisAlignedBox AABB ;
3563        unsigned short src, dest; // for tangent vectors
3564
3565
3566        // Work out how many manual objects we are going to need.  We need one for every group within every material within every zone.
3567        // Groups tend to all be 0 except for transparent triangles which have different groups within the same material/zone,
3568        // due to the need to sort and render transparent things in a specific depth order relative to the camera.
3569
3570
3571        int nMOCount=0 ;
3572        nMaterial=-1 ;
3573        nZone=-1 ;
3574        nGroup=-1 ;
3575
3576        // loop through all triangles to count how many manual objects we'll need.
3577        for(nTri=0 ; nTri<m_Q3Map->m_nTriangleMax ; nTri++)
3578        {
3579               
3580                if(m_Q3Map->m_pTriangle[nTri].Zone!=nZone) // found a new zone
3581                {
3582                        nZone=m_Q3Map->m_pTriangle[nTri].Zone ; 
3583                        nMaterial=m_Q3Map->m_pTriangle[nTri].Texture ;
3584                        nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
3585                        nMOCount++ ;
3586                }
3587                else
3588                        if(m_Q3Map->m_pTriangle[nTri].Texture!=nMaterial) // found a new material within the current zone
3589                        {
3590                                nMaterial=m_Q3Map->m_pTriangle[nTri].Texture ;
3591                                nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
3592                                nMOCount++ ;
3593                        }
3594                        else
3595                                if(m_Q3Map->m_pTriangle[nTri].Group!=nGroup) // found a new group within the current material within the current zone
3596                                {
3597                                        nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
3598                                        nMOCount++ ;
3599                                }
3600
3601        }// end for tri
3602       
3603
3604
3605        // create the manualobject array for our zones and materials
3606        m_pZoneMO = new Ogre::ManualObject*[nMOCount] ;
3607        if(m_pZoneMO==NULL) 
3608                return 0 ; // fail, out of mem
3609        else
3610                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneMO]++ ; }
3611
3612        m_pZoneMesh = new Ogre::MeshPtr[nMOCount] ;
3613        if(m_pZoneMesh==NULL) 
3614                return 0 ; // fail, out of mem
3615        else
3616                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneMesh]++ ; }
3617
3618        // our entities for the meshes
3619        m_pZoneEntity = new Ogre::Entity*[nMOCount] ;
3620        if(m_pZoneEntity==NULL) 
3621                return 0 ; // fail, out of mem
3622        else
3623                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntity]++ ; }
3624
3625        // need to keep track of which entities are transparent
3626        m_pZoneEntityMaterialType = new int[nMOCount] ;
3627        if(m_pZoneEntityMaterialType==NULL) 
3628                return 0 ; // fail, out of mem
3629        else
3630                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterialType]++ ; }
3631        ZeroMemory((void*)m_pZoneEntityMaterialType, nMOCount*sizeof(int)) ; // set all as non-transparent
3632
3633
3634        int nPTex=0 ;
3635        for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
3636        {
3637                // our base materials for the meshes
3638                m_pZoneEntityMaterial_Base[nPTex] = new Ogre::MaterialPtr[nMOCount] ;
3639                if(m_pZoneEntityMaterial_Base[nPTex]==NULL) 
3640                        return 0 ; // fail, out of mem
3641                else
3642                        {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Base]++ ; }
3643
3644                // our fast materials for the meshes
3645                m_pZoneEntityMaterial_Fast[nPTex] = new Ogre::MaterialPtr[nMOCount] ;
3646                if(m_pZoneEntityMaterial_Fast[nPTex]==NULL) 
3647                        return 0 ; // fail, out of mem
3648                else
3649                        {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Fast]++ ; }
3650        }
3651
3652        // our black materials for the meshes
3653        m_pZoneEntityMaterial_Black = new Ogre::MaterialPtr[nMOCount] ;
3654        if(m_pZoneEntityMaterial_Black==NULL) 
3655                return 0 ; // fail, out of mem
3656        else
3657                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Black]++ ; }
3658
3659        // our base materials for the meshes
3660        m_pZoneEntityMaterial_DfShColour = new Ogre::MaterialPtr[nMOCount] ;
3661        if(m_pZoneEntityMaterial_DfShColour==NULL) 
3662                return 0 ; // fail, out of mem
3663        else
3664                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShColour]++ ; }
3665
3666        // materials for the meshes
3667        m_pZoneEntityMaterial_Shadow = new Ogre::MaterialPtr[nMOCount] ;
3668        if(m_pZoneEntityMaterial_Shadow==NULL) 
3669                return 0 ; // fail, out of mem
3670        else
3671                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Shadow]++ ; }
3672
3673        // materials for the meshes
3674        m_pZoneEntityMaterial_ShadeFront = new Ogre::MaterialPtr[nMOCount] ;
3675        if(m_pZoneEntityMaterial_ShadeFront==NULL) 
3676                return 0 ; // fail, out of mem
3677        else
3678                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_ShadeFront]++ ; }
3679
3680        // materials for the meshes
3681        m_pZoneEntityMaterial_ShadeBack = new Ogre::MaterialPtr[nMOCount] ;
3682        if(m_pZoneEntityMaterial_ShadeBack==NULL) 
3683                return 0 ; // fail, out of mem
3684        else
3685                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_ShadeBack]++ ; }
3686
3687        // materials for the meshes
3688        m_pZoneEntityMaterial_DfShPosition = new Ogre::MaterialPtr[nMOCount] ;
3689        if(m_pZoneEntityMaterial_DfShPosition==NULL) 
3690                return 0 ; // fail, out of mem
3691        else
3692                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShPosition]++ ; }
3693
3694        // materials for the meshes
3695        m_pZoneEntityMaterial_DfShDiffuse = new Ogre::MaterialPtr[nMOCount] ;
3696        if(m_pZoneEntityMaterial_DfShDiffuse==NULL) 
3697                return 0 ; // fail, out of mem
3698        else
3699                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse]++ ; }
3700
3701        // materials for the meshes
3702        //m_pZoneEntityMaterial_DSNormal = new Ogre::MaterialPtr[nMOCount] ;
3703        //if(m_pZoneEntityMaterial_DSNormal==NULL) return 0 ; // fail, out of mem
3704
3705        // materials for the meshes
3706        m_pZoneEntityMaterial_DfShFuncTNB = new Ogre::MaterialPtr[nMOCount] ;
3707        if(m_pZoneEntityMaterial_DfShFuncTNB==NULL) 
3708                return 0 ; // fail, out of mem
3709        else
3710                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB]++ ; }
3711
3712        // materials for the meshes
3713        m_pZoneEntityMaterial_DfShSpecular = new Ogre::MaterialPtr[nMOCount] ;
3714        if(m_pZoneEntityMaterial_DfShSpecular==NULL) 
3715                return 0 ; // fail, out of mem
3716        else
3717                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular]++ ; }
3718
3719        // materials for the meshes
3720        m_pZoneEntityMaterial_DfShEmissive = new Ogre::MaterialPtr[nMOCount] ;
3721        if(m_pZoneEntityMaterial_DfShEmissive==NULL) 
3722                return 0 ; // fail, out of mem
3723        else
3724                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive]++ ; }
3725
3726
3727        // materials for the meshes
3728        //m_pZoneEntityMaterial_DfShData = new Ogre::MaterialPtr[nMOCount] ;
3729        //if(m_pZoneEntityMaterial_DfShData==NULL) return 0 ; // fail, out of mem
3730
3731        // materials for the meshes
3732        m_pZoneEntityMaterial_DfShMix = new Ogre::MaterialPtr[nMOCount] ;
3733        if(m_pZoneEntityMaterial_DfShMix==NULL) 
3734                return 0 ; // fail, out of mem
3735        else
3736                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShMix]++ ; }
3737
3738
3739        // memory for keeping track of re-assigned verts, since we only add verts to a manualobject if they are needed, we don't add every vertex
3740        int* pVertIndex = new int [m_Q3Map->m_nVertexMax] ; // at most, there can be m_Q3Map->m_nVertexMax verts in a zone if the map is one big subzone.
3741        if(pVertIndex==NULL) //{ CHECKDELETE_ARRAY( m_pZoneMO ) ; return 0 ; } // fail, out of mem
3742                return 0 ;
3743        else
3744                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_pVertIndex]++ ; }
3745
3746
3747
3748
3749
3750        // go through all the zones and create their manualobjects in m_pZoneMO, one for each material
3751        int nMOIndex=0 ;
3752        for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
3753        {
3754                m_nZoneTriangleCount[nZone]=0 ; // just for our stats
3755
3756
3757                m_nZoneMOStart[nZone]=nMOIndex ; // record where we start from.
3758
3759                // because the triangles have been sorted in order of zone, if there are any triangles in this zone
3760                // then nTriangle will already be on the first example.  However it could be there is a zone that contains
3761                // no triangles.  If we have such an empty zone, we don't create any manual object for it and set its pointer
3762                // to NULL.
3763
3764                if(m_Q3Map->m_pTriangle[nTriangle].Zone!=nZone)
3765                {
3766                        m_pZoneMO[nMOIndex]=NULL ;
3767                        continue ;
3768                        //break ;
3769                }
3770
3771               
3772
3773
3774                // scan through all triangles in this zone
3775                while((nTriangle<m_Q3Map->m_nTriangleMax) && (m_Q3Map->m_pTriangle[nTriangle].Zone==nZone))
3776                {
3777                       
3778
3779                       
3780                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3781                        //
3782                        // start adding a begin/end block of all triangles in a zone with the same material/group
3783                        //
3784                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3785
3786
3787
3788
3789                       
3790                        nMaterial=m_Q3Map->m_pTriangle[nTriangle].Texture ;
3791                        nGroup=m_Q3Map->m_pTriangle[nTriangle].Group ;
3792                       
3793
3794                       
3795
3796                        // create the zone's manualobject
3797                        sprintf(chManualName, "ZoneMO_%04i_%04i_%05i", nZone, nMaterial, nTriangle) ;
3798                        m_pZoneMO[nMOIndex]=m_pSceneMgr->createManualObject(chManualName) ;
3799                       
3800                       
3801
3802                        // scan forward to find the end of this block of triangles with the same texture and group
3803                        nEnd=nTriangle+1 ;
3804                        while(
3805                                                                (nEnd<m_Q3Map->m_nTriangleMax) 
3806                                                        &&(m_Q3Map->m_pTriangle[nEnd].Zone==nZone)
3807                                                        &&(m_Q3Map->m_pTriangle[nEnd].Texture==nMaterial)
3808                                                        &&(m_Q3Map->m_pTriangle[nEnd].Group==nGroup)
3809                                                )
3810                                nEnd++ ;
3811
3812                        // copy the material name.
3813                        // q3 texture names are a max of 64 characters ( Q3NAMESIZE ) and may not be null terminated.  They have no extension either.
3814                        nPos=-1 ;
3815                        while((++nPos<Q3NAMESIZE) && (m_Q3Map->m_pTexture[nMaterial].name[nPos]!=' ') && (m_Q3Map->m_pTexture[nMaterial].name[nPos]!='\0'))
3816                                chMaterial_Base[nPos]=m_Q3Map->m_pTexture[nMaterial].name[nPos] ;
3817
3818                        // make sure name is null terminated
3819                        chMaterial_Base[nPos]='\0' ;
3820
3821
3822
3823                        //..
3824
3825                        //if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_ShinyGlassPlateTL") ;
3826                        //if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_Prototype") ;
3827                        //if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_Prototype") ;
3828                        if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_glassred") ; 
3829                        if(strcmp(chMaterial_Base, "textures/common/exptex2")==0) strcpy(chMaterial_Base, "GEL_GreyGlass") ; 
3830                        if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "ALPHAPF_DSCE_Prototype") ;
3831                        //if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;
3832                        //if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "ALPHAPF_DS_alphaplategreen") ;
3833
3834
3835                       
3836                        // if the material is a lamp material we need to specify either an OpenGl or Direct3D version
3837                        strcpy(chCompare, chMaterial_Base) ;
3838                        chCompare[12]='\0' ;
3839                        if(strcmp("lights/lamp_", chCompare)==0) // material is LAMP
3840                        {
3841                                if(m_IsOpenGL)
3842                                        strcat(chMaterial_Base, "_ogl") ;
3843                                else
3844                                        strcat(chMaterial_Base, "_d3d") ;
3845
3846                        }
3847
3848                        strcpy(chCompare, chMaterial_Base) ;
3849                        chCompare[17]='\0' ;
3850                        if(strcmp("lights/lamp2pass_", chCompare)==0) // material is LAMP, 2 pass version
3851                        {
3852                                if(m_IsOpenGL)
3853                                        strcat(chMaterial_Base, "_ogl") ;
3854                                else
3855                                        strcat(chMaterial_Base, "_d3d") ;
3856                        }
3857                       
3858
3859
3860                        // check that this material script exists, if not set to the default
3861                        pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
3862                        if(pMaterial_Base.isNull())
3863                        {
3864                                strcat(chMaterial_Base, " *** MISSING ***") ;
3865//                              OFBug.LogAddCR(chMaterial_Base) ;
3866                               
3867                                //sprintf(chMessage, "Missing material, using default: %s", chMaterial_Base) ;
3868                                //m_pLog->logMessage(chMessage);
3869
3870                                /*
3871                                switch(rand()%6)
3872                                {
3873                                        case 0: strcpy(chMaterial_Base, "OPAQUE_DSC_Plate2x2A") ;                                       break ;
3874                                        case 1: strcpy(chMaterial_Base, "OPAQUE_DSC_HexColourA") ;                              break ;
3875                                        case 2: strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;                    break ;
3876                                        case 3: strcpy(chMaterial_Base, "OPAQUE_DSC_FloorA") ;                                          break ;
3877                                        case 4: strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimUD_A") ;                   break ;
3878                                        case 5: strcpy(chMaterial_Base, "OPAQUE_DSCE_TechRadar") ;                              break ;
3879                                }
3880                                */
3881
3882                                //strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ; 
3883
3884                                //strcpy(chMaterial_Base, "OPAQUE_DSC_Plate2x2A") ;
3885                                //strcpy(chMaterial_Base, "OPAQUE_DSC_HexColourA") ;
3886                                //strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;
3887                                //strcpy(chMaterial_Base, "OPAQUE_DSC_FloorA") ;
3888                                strcpy(chMaterial_Base, "textures/metaltech/OPAQUE_DSCE_TechRadar") ;
3889                                //strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimA") ;
3890                                //strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimB") ;
3891
3892                                //strcpy(chMaterial_Base, "Standard_Normal") ;
3893                                //strcpy(chMaterial_Base, "test") ;
3894                                //strcpy(chMaterial_Base, "metalN") ;
3895                                //strcpy(chMaterial_Base, "OPAQUE_DSC_Prototype") ;
3896                               
3897                                //strcpy(chMaterial_Base, "textures/common/exptex") ;
3898                                //strcpy(chMaterial_Base, "metalN_DSNormal") ;
3899                                //strcpy(chMaterial_Base, "metalN_DfShFuncTNB") ;
3900                                //strcpy(chMaterial_Base, "metalN_DfShDiffuse") ;
3901                                //strcpy(chMaterial_Base, "metalN_DfShPosition") ;
3902                                //strcpy(chMaterial_Base, "metalD") ;
3903                                //strcpy(chMaterial_Base, "metalR") ;   
3904                                //strcpy(chMaterial_Base, "WonderShader_Lim3_Fast") ;
3905                                //strcpy(chMaterial_Base, "reliefMaterial") ;
3906                                //strcpy(chMaterial_Base, "tute02") ;reliefMaterial
3907                                //strcpy(chMaterial_Base, "Examples/OffsetMapping/Specular") ;
3908                                pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
3909                        }
3910                        else
3911//                              OFBug.LogAddCR(chMaterial_Base) ;
3912
3913
3914
3915                        if(nMOIndex==20)
3916                        {
3917                                sprintf(m_chBug, "****** %s *******", chMaterial_Base) ;
3918                                m_pLog->logMessage(m_chBug);
3919                        }
3920
3921
3922
3923
3924                        // setup whether this material and it's entities are transparent or whatever
3925
3926                        if(strstr(chMaterial_Base, "OPAQUE")!=NULL) // material and its entity are OPAQUE
3927                        {
3928                                m_nOpaqueNodeUsed[nZone]=1 ;
3929                                m_pZoneEntityMaterialType[nMOIndex]=MAT_OPAQUE ; // note that the derived entity will be opaque
3930                        }
3931                        else
3932                        {
3933
3934                                if(strstr(chMaterial_Base, "ALPHAPF")!=NULL) // material and its entity are ALPHAPF
3935                                {
3936                                        m_nOpaqueNodeUsed[nZone]=1 ;
3937                                        m_pZoneEntityMaterialType[nMOIndex]=MAT_OPAQUE ; // note that the derived entity will be opaque
3938                                }
3939                                else
3940                                {
3941
3942                                        if(strstr(chMaterial_Base, "GEL")!=NULL) // material and its entity are GEL
3943                                        {
3944                                                m_nTransNodeUsed[nZone]=1 ;
3945                                                m_pZoneEntityMaterialType[nMOIndex]=MAT_GEL ; // note that the derived entity will be transparent
3946                                        }
3947                                        else
3948                                        {
3949
3950                                                strcpy(chCompare, chMaterial_Base) ;
3951                                                chCompare[12]='\0' ;
3952                                                if(strcmp("lights/lamp_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
3953                                                {
3954                                                        m_nLampNodeUsed[nZone]=1 ;
3955                                                        m_pZoneEntityMaterialType[nMOIndex]=MAT_LAMP ; // note that the derived entity will be lamp
3956                                                }
3957                                                else
3958                                                {
3959                                                        strcpy(chCompare, chMaterial_Base) ;
3960                                                        chCompare[17]='\0' ;
3961                                                        if(strcmp("lights/lamp2pass_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
3962                                                        {
3963                                                                m_nLampNodeUsed[nZone]=1 ;
3964                                                                m_pZoneEntityMaterialType[nMOIndex]=MAT_LAMP ; // note that the derived entity will be lamp
3965                                                        }
3966                                                        else
3967                                                        {
3968
3969                                                                if(strstr(chMaterial_Base, "GLOW_")!=NULL) // material and its entity are GLOW
3970                                                                {
3971                                                                        m_nGlowNodeUsed[nZone]=1 ;
3972                                                                        m_pZoneEntityMaterialType[nMOIndex]=MAT_GLOW ; // note that the derived entity will be glow
3973                                                                }
3974                                                        }       
3975                                                }                                       
3976                                        }
3977                                }
3978                        }
3979
3980
3981
3982
3983
3984
3985                        ///////////////////////////////////////////////////////////////////////////////////////////////////////
3986                        //
3987                        // Setup the different material names and pointers needed for various passes
3988                        //
3989                        // Lamps need only one material, pMaterial_Base, which is already assigned above, so it skips all this.
3990                        //
3991                        // Glow needs two materials, pMaterial_Base plus pMaterial_DfShColour for the coloured gel deferred pass.
3992                        // However it's better to make a third, and duplicate the pMaterial_Base to pMaterial_Emissive, since
3993                        // when glow gets rendered on the Emmisive pass it would be odd to switch to the base material instead
3994                        // of the emmisive.
3995                        //
3996                        // Other objects need multiple materials for various different deferred shading and FX passes
3997                       
3998                        if((m_pZoneEntityMaterialType[nMOIndex]!=MAT_LAMP) && (m_pZoneEntityMaterialType[nMOIndex]!=MAT_GLOW))
3999                        {
4000
4001                                // material for fast shading
4002                                strcpy(chMaterial_Fast, chMaterial_Base) ;
4003                                strcat(chMaterial_Fast, "_Fast") ;
4004
4005                                pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
4006                                if(pMaterial_Fast.isNull())
4007                                {
4008                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_Fast) ;
4009                                        m_pLog->logMessage(chMessage);
4010
4011                                        strcpy(chMaterial_Fast, "Fast") ;
4012                                        pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
4013                                }
4014
4015                                // material for black shading
4016                                strcpy(chMaterial_Black, chMaterial_Base) ;
4017                                strcat(chMaterial_Black, "_Black") ;
4018                                pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
4019                                if(pMaterial_Black.isNull())
4020                                {
4021                                        // only issue a warning if this is an alpha testing material, others don't need specialized Black materials
4022                                        if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
4023                                        {
4024                                                sprintf(chMessage, "Missing material, using default: %s", chMaterial_Black) ;
4025                                                m_pLog->logMessage(chMessage);
4026                                        }
4027
4028                                        strcpy(chMaterial_Black, "Black") ;
4029                                        pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
4030                                }
4031                               
4032                                // material for shadow casting
4033                                strcpy(chMaterial_Shadow, chMaterial_Base) ;
4034                                strcat(chMaterial_Shadow, "_Shadow") ;
4035                                pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
4036                                if(pMaterial_Shadow.isNull())
4037                                {
4038                                        strcpy(chMaterial_Shadow, "OPAQUE_Shadow") ;
4039                                        pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
4040                                }
4041
4042                               
4043                               
4044                                // material for shadow casting
4045                                strcpy(chMaterial_ShadeFront, chMaterial_Base) ;
4046                                strcat(chMaterial_ShadeFront, "_ShadeFront") ;
4047                                pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
4048                                if(pMaterial_ShadeFront.isNull())
4049                                {
4050                                         // standard opaque ShadeFront. 
4051                                        // Transparent surfaces MUST have their own _ShadeFront material or they will not colour light and can interfere with other trans surfaces.
4052                                        strcpy(chMaterial_ShadeFront, "OPAQUE_ShadeFront") ;
4053
4054                                        pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
4055                                }
4056
4057
4058                                // material for shadow casting
4059                                strcpy(chMaterial_ShadeBack, chMaterial_Base) ;
4060                                strcat(chMaterial_ShadeBack, "_ShadeBack") ;
4061                                pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
4062                                if(pMaterial_ShadeBack.isNull())
4063                                {
4064                                         // standard opaque ShadeBack. 
4065                                        // Transparent surfaces MUST have their own _ShadeBack material or they will not colour light and can interfere with other trans surfaces.
4066                                        strcpy(chMaterial_ShadeBack, "OPAQUE_ShadeBack") ;
4067
4068                                        pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
4069                                }
4070
4071                                // material for deferred shading
4072                                strcpy(chMaterial_DfShColour, chMaterial_Base) ;
4073                                strcat(chMaterial_DfShColour, "_DfShColour") ;
4074                                pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
4075                                if(pMaterial_DfShColour.isNull())
4076                                {
4077                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShColour) ;
4078                                        m_pLog->logMessage(chMessage);
4079
4080                                        strcpy(chMaterial_DfShColour, "DfShColour") ;
4081                                        pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
4082                                }
4083                               
4084
4085                                // material for deferred shading
4086                                strcpy(chMaterial_DfShPosition, chMaterial_Base) ;
4087                                strcat(chMaterial_DfShPosition, "_DfShPosition") ;
4088                                pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
4089                                if(pMaterial_DfShPosition.isNull())
4090                                {
4091                                        // only issue a warning if this is an alpha testing material, others don't need specialized DfShPosition materials
4092                                        if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
4093                                        {
4094                                                sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShPosition) ;
4095                                                m_pLog->logMessage(chMessage);
4096                                        }
4097
4098                                        strcpy(chMaterial_DfShPosition, "DfShPosition") ;
4099                                        pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
4100                                }
4101                               
4102                                // material for deferred shading
4103                                strcpy(chMaterial_DfShDiffuse, chMaterial_Base) ;
4104                                strcat(chMaterial_DfShDiffuse, "_DfShDiffuse") ;
4105                                pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
4106                                if(pMaterial_DfShDiffuse.isNull())
4107                                {
4108                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShDiffuse) ;
4109                                        m_pLog->logMessage(chMessage);
4110
4111                                        strcpy(chMaterial_DfShDiffuse, "DfShDiffuse") ;
4112                                        pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
4113                                }
4114
4115                                /*
4116                                // material for deferred shading // UNUSED
4117                                strcpy(chMaterial_DSNormal, chMaterial_Base) ;
4118                                strcat(chMaterial_DSNormal, "_DSNormal") ;
4119                                pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
4120                                if(pMaterial_DSNormal.isNull())
4121                                {
4122                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DSNormal) ;
4123                                        m_pLog->logMessage(chMessage);
4124
4125                                        strcpy(chMaterial_DSNormal, "DSNormal") ;
4126                                        pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
4127                                }
4128                                */
4129
4130                                // material for deferred shading
4131                                strcpy(chMaterial_DfShFuncTNB, chMaterial_Base) ;
4132                                strcat(chMaterial_DfShFuncTNB, "_DfShFuncTNB") ;
4133                                pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
4134                                if(pMaterial_DfShFuncTNB.isNull())
4135                                {
4136                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShFuncTNB) ;
4137                                        m_pLog->logMessage(chMessage);
4138
4139                                        strcpy(chMaterial_DfShFuncTNB, "DfShFuncTNB") ;
4140                                        pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
4141                                }
4142
4143                                // material for deferred shading
4144                                strcpy(chMaterial_DfShSpecular, chMaterial_Base) ;
4145                                strcat(chMaterial_DfShSpecular, "_DfShSpecular") ;
4146                                pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
4147                                if(pMaterial_DfShSpecular.isNull())
4148                                {
4149                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShSpecular) ;
4150                                        m_pLog->logMessage(chMessage);
4151
4152                                        strcpy(chMaterial_DfShSpecular, "DfShSpecular") ;
4153                                        pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
4154                                }
4155
4156                                // material for deferred shading
4157                                strcpy(chMaterial_DfShEmissive, chMaterial_Base) ;
4158                                strcat(chMaterial_DfShEmissive, "_DfShEmissive") ;
4159                                pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
4160                                if(pMaterial_DfShEmissive.isNull())
4161                                {
4162                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShEmissive) ;
4163                                        m_pLog->logMessage(chMessage);
4164
4165                                        strcpy(chMaterial_DfShEmissive, "DfShEmissive") ;
4166                                        pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
4167                                }
4168
4169
4170                                /*
4171                                // material for deferred shading
4172                                strcpy(chMaterial_DfShData, chMaterial_Base) ;
4173                                strcat(chMaterial_DfShData, "_DfShData") ;
4174                                pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
4175                                if(pMaterial_DfShData.isNull())
4176                                {
4177                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShData) ;
4178                                        m_pLog->logMessage(chMessage);
4179
4180                                        strcpy(chMaterial_DfShData, "DfShData") ;
4181                                        pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
4182                                }
4183                                */
4184
4185                                // material for deferred shading
4186                                strcpy(chMaterial_DfShMix, chMaterial_Base) ;
4187                                strcat(chMaterial_DfShMix, "_DfShMix") ;
4188                                pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
4189                                if(pMaterial_DfShMix.isNull())
4190                                {
4191                                        // Pretty much all materials just use the default mix material,
4192                                        // so don't issue warnings if there isn't a specialized version
4193                                        //sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShMix) ;
4194                                        //m_pLog->logMessage(chMessage);
4195
4196                                        strcpy(chMaterial_DfShMix, "DfShMix") ;
4197                                        pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
4198                                }
4199                               
4200                       
4201
4202
4203
4204                        }// end if not MAT_LAMP or MAT_GLOW
4205                        else
4206                                if(m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW) // the two materials that glow needs
4207                                {
4208
4209                                        // when I get around to allowing user defined GLOW materials as well as the automatic ones,
4210                                        // this'll be the place to add it. 
4211                                        // For now, just the automatically generated lamp/light stuff has a glow.
4212                                       
4213                                        // if the base material was "GLOW_lamp"
4214                                        strcpy(chCompare, chMaterial_Base) ;
4215                                        chCompare[strlen("GLOW_lamp")]='\0' ;
4216                                        if(strcmp("GLOW_lamp", chCompare)==0) 
4217                                        {
4218                                                strcpy(chMaterial_DfShColour, "GLOW_lampcol") ;
4219                                                pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
4220
4221                                                strcpy(chMaterial_DfShEmissive, "GLOW_lamp") ;
4222                                                pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
4223                                        }
4224                                        else
4225                                        {
4226
4227                                                // if the base material was "GLOW_light"
4228                                                strcpy(chCompare, chMaterial_Base) ;
4229                                                chCompare[strlen("GLOW_light")]='\0' ;
4230                                                if(strcmp("GLOW_light", chCompare)==0) 
4231                                                {
4232                                                        strcpy(chMaterial_DfShColour, "GLOW_lightcol") ;
4233                                                        pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
4234
4235                                                        strcpy(chMaterial_DfShEmissive, "GLOW_light") ;
4236                                                        pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
4237                                                }
4238
4239                                        }
4240                                }
4241
4242
4243
4244
4245
4246
4247                        // work out which vertices we'll need, we don't add every vertex, just used ones.
4248                        nMaxVertex=0 ;
4249                        for(nVert=0 ; nVert<m_Q3Map->m_nVertexMax ; nVert++)
4250                                pVertIndex[nVert]=-1 ; // initialize all verts as unused.
4251                       
4252
4253                        // start defining the manualObject
4254                        m_pZoneMO[nMOIndex]->begin(chMaterial_Base, RenderOperation::OT_TRIANGLE_LIST) ;
4255
4256
4257                        // reset the min max stuff
4258                        flMinX=flMinY=flMinZ=MINMAXLIMIT ;
4259                        flMaxX=flMaxY=flMaxZ=-MINMAXLIMIT ;
4260       
4261
4262                        // add the verts.  We avoid repeating the same vert multiple times where it is used by many triangles
4263                        for(nTri=nTriangle ; nTri<nEnd ; nTri++)
4264                                for(nVert=0 ; nVert<3 ; nVert++)
4265                                {
4266                                        if(pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ]==-1) // this vert hasn't been added yet
4267                                        {
4268                                                pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ]=nMaxVertex++ ; // so we can correctly look it up when we add the triangles
4269
4270                                                flPosX=m_Q3Map->m_pVertex[      m_Q3Map->m_pTriangle[nTri].VIndex[nVert]  ].position[0] ;
4271                                                flPosY=m_Q3Map->m_pVertex[      m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].position[1] ;
4272                                                flPosZ=m_Q3Map->m_pVertex[      m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].position[2] ;
4273                                                flNormX=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert]    ].normal[0] ;
4274                                                flNormY=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert]    ].normal[1] ;
4275                                                flNormZ=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert]    ].normal[2] ;
4276                                               
4277                                               
4278                                               
4279                                                // lamps have some different vertex data, also glow
4280                                                // lamp needs colour and also info about the origin, which is stored in the UVs.
4281                                                // glow only needs the colour, but it doesn't hurt to store the orgin too, no harm and simpler code.
4282                                                if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW))
4283                                                {
4284                                                        flLampPosX =                    m_Q3Map->m_pVertex[     m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].texcoord[0][0] ;
4285                                                        flLampPosY =                    m_Q3Map->m_pVertex[     m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].texcoord[0][1] ;
4286                                                        flLampPosZ =                    m_Q3Map->m_pVertex[     m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].texcoord[1][0] ;
4287                                                        flLampBrightness=       m_Q3Map->m_pVertex[     m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].texcoord[1][1] ;
4288
4289                                                        flLampR=m_Q3Map->m_pVertex[     m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].color[0]/255.0f ;
4290                                                        flLampG=m_Q3Map->m_pVertex[     m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].color[1]/255.0f ;
4291                                                        flLampB=m_Q3Map->m_pVertex[     m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].color[2]/255.0f ;
4292
4293                                                        // set the vertex data
4294                                                        m_pZoneMO[nMOIndex]->position(flPosX, flPosY, flPosZ) ;
4295                                                        m_pZoneMO[nMOIndex]->normal(flNormX, flNormY, flNormZ) ;
4296                                                        m_pZoneMO[nMOIndex]->textureCoord(flLampPosX, flLampPosY, flLampPosZ, flLampBrightness) ;
4297                                                        m_pZoneMO[nMOIndex]->colour(flLampR, flLampG, flLampB) ;
4298
4299                                                }
4300                                                else // non-lamps
4301                                                {
4302                                                        flTexU=m_Q3Map->m_pVertex[      m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].texcoord[0][0] ;
4303                                                        flTexV=m_Q3Map->m_pVertex[      m_Q3Map->m_pTriangle[nTri].VIndex[nVert]        ].texcoord[0][1] ;
4304
4305                                                        // set the vertex data
4306                                                        m_pZoneMO[nMOIndex]->position(flPosX, flPosY, flPosZ) ;
4307                                                        m_pZoneMO[nMOIndex]->normal(flNormX, flNormY, flNormZ) ;
4308                                                        m_pZoneMO[nMOIndex]->textureCoord(flTexU, flTexV) ;
4309                                                }
4310
4311                                                // update bounds
4312                                                if(flPosX<flMinX) flMinX=flPosX ;
4313                                                if(flPosY<flMinY) flMinY=flPosY ;
4314                                                if(flPosZ<flMinZ) flMinZ=flPosZ ;
4315                                                if(flPosX>flMaxX) flMaxX=flPosX ;
4316                                                if(flPosY>flMaxY) flMaxY=flPosY ;
4317                                                if(flPosZ>flMaxZ) flMaxZ=flPosZ ;
4318
4319                                        }// end if adding vert
4320                                }
4321
4322                        // add the triangles
4323                        for(nTri=nTriangle ; nTri<nEnd ; nTri++)
4324                        {
4325                                nVertA=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[0] ] ;
4326                                nVertB=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[1] ] ;
4327                                nVertC=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[2] ] ;
4328                                m_pZoneMO[nMOIndex]->triangle(nVertA, nVertC, nVertB) ;
4329                                m_nZoneTriangleCount[nZone]++ ;
4330                                //m_pZoneMO[nMOIndex]->triangle(nVertA, nVertB, nVertC) ;
4331                        }
4332
4333
4334                        // all done for this block of material
4335                        m_pZoneMO[nMOIndex]->end() ;
4336                        m_pZoneMO[nMOIndex]->setCastShadows(true) ;
4337                        m_pZoneMO[nMOIndex]->setDynamic(false) ;
4338
4339                        // convert the manualobject to a mesh
4340                        sprintf(chMeshName, "ZoneMesh_%04i_%04i_%05i", nZone, nMaterial, nTriangle) ;
4341                        m_pZoneMesh[nMOIndex]= m_pZoneMO[nMOIndex]->convertToMesh(chMeshName);
4342
4343                        // don't need the manual object anymore
4344                        m_pSceneMgr->destroyManualObject(m_pZoneMO[nMOIndex]) ;
4345
4346
4347                        // temp cludge to add thickness
4348                        flMinX-=1.0f ;
4349                        flMinY-=1.0f ;
4350                        flMinZ-=1.0f ;
4351                        flMaxX+=1.0f ;
4352                        flMaxY+=1.0f ;
4353                        flMaxZ+=1.0f ;
4354
4355                        // set axis aligned bounding box of this mesh
4356                        AABB.setMinimumX(flMinX) ; 
4357                        AABB.setMinimumY(flMinY) ; 
4358                        AABB.setMinimumZ(flMinZ) ;
4359                        AABB.setMaximumX(flMaxX) ; 
4360                        AABB.setMaximumY(flMaxY) ; 
4361                        AABB.setMaximumZ(flMaxZ) ;
4362                        m_pZoneMesh[nMOIndex]->_setBounds(AABB, false) ;
4363                       
4364                        // set bounding sphere of this mesh
4365                        flDisX=flMaxX-flMinX ;
4366                        flDisY=flMaxY-flMinY ;
4367                        flDisZ=flMaxZ-flMinZ ;
4368                        flRadius=sqrt( flDisX*flDisX + flDisY*flDisY + flDisZ*flDisZ )/2.0 ;
4369                        m_pZoneMesh[nMOIndex]->_setBoundingSphereRadius(flRadius) ;
4370
4371
4372                        //if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassred")==0)
4373                        //      OFBug.MessageFloat(flRadius, flMinX, flMinY, flMinZ, flMaxX, flMaxY, flMaxZ) ;
4374
4375                        //if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassgreen")==0)
4376                        //      OFBug.MessageFloat(flRadius, flMinX, flMinY, flMinZ, flMaxX, flMaxY, flMaxZ) ;
4377
4378                        // calculate tangents for the mesh             
4379                        if((m_pZoneEntityMaterialType[nMOIndex]!=MAT_LAMP) && (m_pZoneEntityMaterialType[nMOIndex]!=MAT_GLOW))// lamps and glow don't need tangent vectors
4380                        {
4381                                m_pZoneMesh[nMOIndex]->suggestTangentVectorBuildParams(VES_TANGENT, src, dest) ;
4382                                m_pZoneMesh[nMOIndex]->buildTangentVectors(VES_TANGENT, src, dest);
4383                        }
4384       
4385                        m_pZoneMesh[nMOIndex]->load() ;
4386
4387                        m_pZoneMesh[nMOIndex]->getSubMesh(0)->generateExtremes(8) ;
4388
4389                        // create an entity for this mesh.  We need this so we can change the material during deferred shading
4390                        m_pZoneEntity[nMOIndex]=m_pSceneMgr->createEntity(m_pZoneMesh[nMOIndex]->getName(), m_pZoneMesh[nMOIndex]->getName()) ;
4391
4392                        // if the entity is a lamp or glow, set its material because they never get changed
4393                        if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW)) 
4394                                m_pZoneEntity[nMOIndex]->setMaterial( pMaterial_Base) ;
4395
4396
4397                        //AABB=m_pZoneEntity[nMOIndex]->getBoundingBox() ;
4398                        //Ogre::Vector3 mn, mx ;
4399                        //mn=AABB.getMinimum() ;
4400                        //mx=AABB.getMaximum() ;
4401                        //if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassred")==0)
4402                        //      OFBug.MessageFloat(mn.x, mn.y, mn.z, mx.x, mx.y, mx.z) ;
4403
4404
4405
4406
4407
4408
4409                        // store the pointers to the materials of this entity
4410                        //m_pZoneEntityMaterial_Base[nMOIndex]=pMaterial_Base ;
4411                        //m_pZoneEntityMaterial_Fast[nMOIndex]=pMaterial_Fast ;
4412                        m_pZoneEntityMaterial_Black[nMOIndex]=pMaterial_Black ;
4413                        m_pZoneEntityMaterial_DfShColour[nMOIndex]=pMaterial_DfShColour ;
4414                        m_pZoneEntityMaterial_Shadow[nMOIndex]=pMaterial_Shadow ;
4415                        m_pZoneEntityMaterial_ShadeFront[nMOIndex]=pMaterial_ShadeFront ;
4416                        m_pZoneEntityMaterial_ShadeBack[nMOIndex]=pMaterial_ShadeBack ;
4417                        m_pZoneEntityMaterial_DfShPosition[nMOIndex]=pMaterial_DfShPosition ;
4418                        m_pZoneEntityMaterial_DfShDiffuse[nMOIndex]=pMaterial_DfShDiffuse ;
4419                        //m_pZoneEntityMaterial_DSNormal[nMOIndex]=pMaterial_DSNormal ;
4420                        m_pZoneEntityMaterial_DfShFuncTNB[nMOIndex]=pMaterial_DfShFuncTNB ;
4421                        m_pZoneEntityMaterial_DfShSpecular[nMOIndex]=pMaterial_DfShSpecular ;
4422                        m_pZoneEntityMaterial_DfShEmissive[nMOIndex]=pMaterial_DfShEmissive ;
4423                        //m_pZoneEntityMaterial_DfShData[nMOIndex]=pMaterial_DfShData ;
4424                        m_pZoneEntityMaterial_DfShMix[nMOIndex]=pMaterial_DfShMix ;
4425
4426
4427                        //////////////////////////////////////////////////////////////////////////////////////////
4428
4429                        char chNewName[1024] ;
4430                        for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
4431                        {
4432                                Ogre::AliasTextureNamePairList AliasList ;
4433                               
4434                                // check the necessary texture exists
4435                                //if(TextureManager::getSingleton().getByName(m_Q3Map->m_chSpotlightTexture[nPTex]).isNull())
4436                                //      OFBug.MessageInt(666) ;
4437                               
4438                               
4439                                AliasList.insert(AliasTextureNamePairList::value_type("projector_tex", m_Q3Map->m_chSpotlightTexture[nPTex]));
4440
4441                               
4442
4443                                sprintf(chNewName, "%s_%i", chMaterial_Base, 0) ;
4444                                m_pZoneEntityMaterial_Base[nPTex][nMOIndex]=pMaterial_Base->clone(chNewName) ;
4445                                // change the texture unit
4446                                m_pZoneEntityMaterial_Base[nPTex][nMOIndex]->applyTextureAliases(AliasList) ;
4447
4448                                sprintf(chNewName, "%s_%i", chMaterial_Fast, 0) ;
4449                                m_pZoneEntityMaterial_Fast[nPTex][nMOIndex]=pMaterial_Fast->clone(chNewName) ;
4450                                // change the texture unit
4451                                m_pZoneEntityMaterial_Fast[nPTex][nMOIndex]->applyTextureAliases(AliasList) ;
4452
4453                        }
4454
4455
4456
4457                        //////////////////////////////////////////////////////////////////////////////////////////
4458
4459
4460                        // move to the end of this block of materials
4461                        nTriangle=nEnd ;
4462                        nMOIndex++ ;
4463
4464
4465                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4466                        //
4467                        // end adding a begin/end block of all triangles in a zone with the same material
4468                        //
4469                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4470
4471
4472
4473
4474                }// end scanning triangles in a zone
4475
4476
4477
4478        }// end looping through all zones
4479
4480        m_nZoneMOStart[m_Q3Map->m_nMaxZone]=nMOIndex ; // indicates the end pos of all the manual objects
4481
4482        CHECKDELETE_ARRAY( pVertIndex, NEW_CHECK_pVertIndex  );  // free the vert index memory we used
4483
4484        CHECKDELETE_ARRAY( m_pZoneMO, NEW_CHECK_m_pZoneMO  ) ;  // free the manual object memory we used
4485        // quick check
4486        if(nMOCount!=nMOIndex)
4487        {
4488                sprintf(chMessage, "ERROR ConstructMap: MOIndex %i does not match MOCount %i", nMOIndex, nMOCount) ;
4489                m_pLog->logMessage(chMessage);
4490                //CHECKDELETE_ARRAY( m_pZoneMO ) ;
4491                CHECKDELETE_ARRAY( m_pZoneMesh, NEW_CHECK_m_pZoneMesh  ) ; 
4492                CHECKDELETE_ARRAY( m_pZoneEntity, NEW_CHECK_m_pZoneEntity  ) ; 
4493                CHECKDELETE_ARRAY( m_pZoneEntityMaterialType, NEW_CHECK_m_pZoneEntityMaterialType  ) ; 
4494
4495                for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
4496                {
4497                        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Base[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Base  ) ; 
4498                        CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Fast[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Fast  ) ; 
4499                }
4500
4501                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Black, NEW_CHECK_m_pZoneEntityMaterial_Black  ) ; 
4502                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShColour, NEW_CHECK_m_pZoneEntityMaterial_DfShColour  ) ; 
4503                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Shadow, NEW_CHECK_m_pZoneEntityMaterial_Shadow  ) ; 
4504                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeFront, NEW_CHECK_m_pZoneEntityMaterial_ShadeFront  ) ; 
4505                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeBack, NEW_CHECK_m_pZoneEntityMaterial_ShadeBack  ) ; 
4506                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShPosition, NEW_CHECK_m_pZoneEntityMaterial_DfShPosition  ) ; 
4507                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShDiffuse, NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse  ) ; 
4508                //CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DSNormal ) ;
4509                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShFuncTNB, NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB  ) ; 
4510                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShSpecular, NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular  ) ; 
4511                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShEmissive, NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive  ) ; 
4512                //CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShData ) ;
4513                CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShMix, NEW_CHECK_m_pZoneEntityMaterial_DfShMix  ) ; 
4514
4515
4516                return 0 ;
4517        }
4518
4519
4520        return 1 ;
4521
4522}
4523
4524////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4525//
4526// setup the game entities
4527//
4528
4529int OgreFramework::SetupGameEntities(void)
4530{
4531        int nEntity=0 ;
4532        char chMeshName[1024] ;
4533       
4534
4535        // work out the maximum number of entities we need
4536        m_nMaxEntity=10 ;
4537        int nHalfMax=m_nMaxEntity/2 ;
4538       
4539
4540
4541
4542        // create the dynamic memory for the entities
4543        m_pEntityInfo=new ENTITYINFO[m_nMaxEntity] ;
4544        if(m_pEntityInfo==NULL) 
4545                return 0 ;
4546        else
4547                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pEntityInfo]++ ; }
4548
4549        m_pVisibleEntity=new int[m_nMaxEntity] ;
4550        if(m_pVisibleEntity==NULL) 
4551                return 0 ;
4552        else
4553                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pVisibleEntity]++ ; }
4554
4555        m_pFrustumEntity=new int[m_nMaxEntity] ;
4556        if(m_pFrustumEntity==NULL) 
4557                return 0 ;
4558        else
4559                {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pFrustumEntity]++ ; }
4560
4561
4562
4563        // setup materials and default data for the entities
4564        for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
4565        {
4566                //switch(nEntity%3)
4567                //{
4568                //      case 0: strcpy(chMeshName, "robot.mesh") ; break ;
4569                //      case 1: strcpy(chMeshName, "ninja.mesh") ; break ;
4570                //      case 2: strcpy(chMeshName, "athene.mesh") ; break ;
4571                //}
4572
4573                strcpy(chMeshName, "robot.mesh") ;
4574
4575                SetupEntity(nEntity, chMeshName) ;
4576        }
4577
4578
4579
4580
4581        // setup start data for each entity
4582        for(nEntity=0 ; nEntity<nHalfMax ; nEntity++)
4583        {
4584                m_pEntityInfo[nEntity].Postition=Ogre::Vector3(750.0f, 128.0f, -1950.0f-nEntity*40.0f) ;
4585                //m_pEntityInfo[nEntity].pMasterNode->setPosition(750.0f, 128.0f, -1950.0f-nEntity*40.0f) ;
4586        }
4587
4588        for(nEntity=nHalfMax ; nEntity<m_nMaxEntity ; nEntity++)
4589        {
4590                m_pEntityInfo[nEntity].Postition=Ogre::Vector3(590.0f, 128.0f, -320.0f-nEntity*40.0f) ;
4591                //m_pEntityInfo[nEntity].pMasterNode->setPosition(590.0f, 128.0f, -320.0f-nEntity*40.0f) ;
4592        }
4593
4594       
4595
4596        for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
4597        {
4598                m_pEntityInfo[nEntity].Active=1 ;
4599                m_pVisibleEntity[nEntity]=nEntity ;
4600                m_pFrustumEntity[nEntity]=nEntity ;
4601        }
4602
4603
4604        m_nMaxVisibleEntity=m_nMaxEntity ;
4605        m_nMaxFrustumEntity=m_nMaxEntity ;
4606
4607        return 1 ;
4608
4609}
4610
4611
4612int OgreFramework::SetupEntity(int nEntity, char *chMeshName)
4613{
4614
4615        char chEntityName[1024] ;
4616        //char chMeshName[1024] ;
4617
4618
4619        int nSubMesh=0 ;
4620        int nMaxSubMesh=0 ;
4621
4622
4623
4624        Ogre::String MaterialName ;
4625
4626
4627        char chMaterial_Base[1024] ;
4628        MaterialPtr pMaterial_Base ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
4629       
4630        char chMaterial_Fast[1024] ;
4631        MaterialPtr pMaterial_Fast ; // faster version of the base, mainly non-coloured shadowning.
4632
4633        char chMaterial_Black[1024] ;
4634        MaterialPtr pMaterial_Black ; // just plain black, or black with alpha testing.
4635
4636        char chMaterial_DfShColour[1024] ;
4637        MaterialPtr pMaterial_DfShColour ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
4638       
4639
4640        char chMaterial_Shadow[1024] ;
4641        MaterialPtr pMaterial_Shadow ;
4642
4643        char chMaterial_ShadeFront[1024] ;
4644        MaterialPtr pMaterial_ShadeFront ;
4645
4646        char chMaterial_ShadeBack[1024] ;
4647        MaterialPtr pMaterial_ShadeBack ;
4648
4649        char chMaterial_DfShPosition[1024] ;
4650        MaterialPtr pMaterial_DfShPosition ;
4651       
4652        char chMaterial_DfShDiffuse[1024] ;
4653        MaterialPtr pMaterial_DfShDiffuse ;
4654       
4655        //char chMaterial_DSNormal[1024] ;
4656        //MaterialPtr pMaterial_DSNormal ;
4657       
4658        char chMaterial_DfShFuncTNB[1024] ;
4659        MaterialPtr pMaterial_DfShFuncTNB ;
4660
4661        char chMaterial_DfShSpecular[1024] ;
4662        MaterialPtr pMaterial_DfShSpecular ;
4663
4664        char chMaterial_DfShEmissive[1024] ;
4665        MaterialPtr pMaterial_DfShEmissive ;
4666
4667        //char chMaterial_DfShData[1024] ;
4668        //MaterialPtr pMaterial_DfShData ;
4669
4670        char chMaterial_DfShMix[1024] ;
4671        MaterialPtr pMaterial_DfShMix ;
4672
4673        char chCompare[1024] ;
4674
4675        unsigned short src, dest; // for tangent vectors
4676
4677        char chMasterNodeName[1024] ;
4678        char chSubNodeName[1024] ;
4679
4680        char chMessage[1024] ;
4681        int nPTex=0 ;
4682
4683
4684        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4685
4686                sprintf(chEntityName, "Entity_%05i", nEntity) ;
4687                //strcpy(chMeshName, "robot.mesh") ;
4688
4689
4690                // load the mesh
4691
4692                m_pEntityInfo[nEntity].pEnt=m_pSceneMgr->createEntity( chEntityName, chMeshName );
4693
4694                m_pEntityInfo[nEntity].TriangleCount=0 ;
4695               
4696
4697                // create the master scenenode
4698                sprintf(chMasterNodeName, "Entity_%05i", nEntity) ;
4699                m_pEntityInfo[nEntity].pMasterNode=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chMasterNodeName) ;
4700                m_pEntityInfo[nEntity].pMasterNode->attachObject(m_pEntityInfo[nEntity].pEnt) ;
4701
4702                nMaxSubMesh=m_pEntityInfo[nEntity].pEnt->getMesh()->getNumSubMeshes() ;
4703                if(nMaxSubMesh>MAX_SUBMESH)
4704                {
4705                        sprintf(m_chBug, "MESH ERROR: Mesh %s has %i submeshes, max is %i", chMeshName, m_pEntityInfo[nEntity].MaxSubMesh, MAX_SUBMESH) ;
4706                        m_pLog->logMessage(m_chBug);
4707                        nMaxSubMesh=MAX_SUBMESH ;
4708                }
4709                m_pEntityInfo[nEntity].MaxSubMesh=nMaxSubMesh ;
4710
4711                sprintf(m_chBug, "Entity %i, Mesh %s, MaxSubMesh %i", nEntity, chMeshName,  m_pEntityInfo[nEntity].MaxSubMesh) ;
4712                m_pLog->logMessage(m_chBug);
4713
4714                // assign all the materials needed for all the submeshes
4715                for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
4716                {
4717                        // we count the triangles just for stats
4718                        m_pEntityInfo[nEntity].TriangleCount += m_pEntityInfo[nEntity].pEnt->getMesh()->getSubMesh(nSubMesh)->indexData->indexCount/3 ;
4719
4720
4721                        MaterialName=m_pEntityInfo[nEntity].pEnt->getMesh()->getSubMesh(nSubMesh)->getMaterialName() ;
4722               
4723                       
4724                       
4725
4726                        if(MaterialName.size()<512) // make sure name isn't too long before we copy it.
4727                                strcpy(chMaterial_Base, MaterialName.c_str()) ;
4728                        else
4729                        {
4730                                sprintf(m_chBug, "MESH ERROR: Mesh %s submesh %i material name is too long.", chMeshName, nSubMesh) ;
4731                                m_pLog->logMessage(m_chBug);
4732                                m_pLog->logMessage(MaterialName) ;
4733                                chMaterial_Base[0]='\0' ; // no material
4734                        }
4735
4736                        sprintf(m_chBug, "Entity %i SubMesh %i, Material %s", nEntity, nSubMesh, chMaterial_Base) ;
4737                        m_pLog->logMessage(m_chBug);
4738
4739
4740                        // if the material is a lamp material we need to specify either an OpenGl or Direct3D version
4741                        strcpy(chCompare, chMaterial_Base) ;
4742                        chCompare[12]='\0' ;
4743                        if(strcmp("lights/lamp_", chCompare)==0) // material is LAMP
4744                        {
4745                                if(m_IsOpenGL)
4746                                        strcat(chMaterial_Base, "_ogl") ;
4747                                else
4748                                        strcat(chMaterial_Base, "_d3d") ;
4749
4750                        }
4751
4752                        strcpy(chCompare, chMaterial_Base) ;
4753                        chCompare[17]='\0' ;
4754                        if(strcmp("lights/lamp2pass_", chCompare)==0) // material is LAMP, 2 pass version
4755                        {
4756                                if(m_IsOpenGL)
4757                                        strcat(chMaterial_Base, "_ogl") ;
4758                                else
4759                                        strcat(chMaterial_Base, "_d3d") ;
4760                        }
4761                       
4762                        // check that this material script exists, if not set to the default
4763                        pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
4764                        if(true)//pMaterial_Base.isNull())
4765                        {
4766                                strcat(chMaterial_Base, " *** MISSING ***") ;
4767//                              OFBug.LogAddCR(chMaterial_Base) ;
4768                               
4769                                strcpy(chMaterial_Base, "textures/metaltech/OPAQUE_DSCE_TechRadar") ;
4770                                pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
4771                        }
4772
4773
4774                        // setup whether this material and it's entities are transparent or whatever
4775                       
4776                        m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=0 ;// default to nothing
4777                       
4778                        if(strstr(chMaterial_Base, "OPAQUE")!=NULL) // material and its entity are OPAQUE
4779                        {
4780                                m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_OPAQUE ; // note that the derived entity will be opaque
4781
4782                        }
4783                        else
4784                        {
4785
4786                                if(strstr(chMaterial_Base, "ALPHAPF")!=NULL) // material and its entity are ALPHAPF
4787                                {
4788                                        m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_OPAQUE ; // note that the derived entity will be opaque
4789                                }
4790                                else
4791                                {
4792
4793                                        if(strstr(chMaterial_Base, "GEL")!=NULL) // material and its entity are GEL
4794                                        {
4795                                                m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_GEL ; // note that the derived entity will be transparent
4796                                        }
4797                                        else
4798                                        {
4799
4800                                                strcpy(chCompare, chMaterial_Base) ;
4801                                                chCompare[12]='\0' ;
4802                                                if(strcmp("lights/lamp_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
4803                                                {
4804                                                        m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_LAMP ; // note that the derived entity will be lamp
4805                                                }
4806                                                else
4807                                                {
4808                                                        strcpy(chCompare, chMaterial_Base) ;
4809                                                        chCompare[17]='\0' ;
4810                                                        if(strcmp("lights/lamp2pass_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
4811                                                        {
4812                                                                m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_LAMP ; // note that the derived entity will be lamp
4813                                                        }
4814                                                        else
4815                                                        {
4816
4817                                                                if(strstr(chMaterial_Base, "GLOW_")!=NULL) // material and its entity are GLOW
4818                                                                {
4819                                                                        m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_GLOW ; // note that the derived entity will be glow
4820                                                                }
4821                                                        }       
4822                                                }                                       
4823                                        }
4824                                }
4825                        }
4826
4827
4828
4829                       
4830
4831                        ///////////////////////////////////////////////////////////////////////////////////////////////////////
4832                        //
4833                        // Setup the different material names and pointers needed for various passes
4834                        //
4835                        // Lamps need only one material, pMaterial_Base, which is already assigned above, so it skips all this.
4836                        //
4837                        // Glow needs two materials, pMaterial_Base plus pMaterial_DfShColour for the coloured gel deferred pass.
4838                        // However it's better to make a third, and duplicate the pMaterial_Base to pMaterial_Emissive, since
4839                        // when glow gets rendered on the Emmisive pass it would be odd to switch to the base material instead
4840                        // of the emmisive.
4841                        //
4842                        // Other objects need multiple materials for various different deferred shading and FX passes
4843                       
4844                        if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_LAMP) && (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_GLOW))
4845                        {
4846
4847                                // material for fast shading
4848                                strcpy(chMaterial_Fast, chMaterial_Base) ;
4849                                strcat(chMaterial_Fast, "_Fast") ;
4850                                pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
4851                                if(pMaterial_Fast.isNull())
4852                                {
4853                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_Fast) ;
4854                                        m_pLog->logMessage(chMessage);
4855
4856                                        strcpy(chMaterial_Fast, "Fast") ;
4857                                        pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
4858                                }
4859
4860                                // material for black shading
4861                                strcpy(chMaterial_Black, chMaterial_Base) ;
4862                                strcat(chMaterial_Black, "_Black") ;
4863                                pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
4864                                if(pMaterial_Black.isNull())
4865                                {
4866                                        // only issue a warning if this is an alpha testing material, others don't need specialized Black materials
4867                                        if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
4868                                        {
4869                                                sprintf(chMessage, "Missing material, using default: %s", chMaterial_Black) ;
4870                                                m_pLog->logMessage(chMessage);
4871                                        }
4872
4873                                        strcpy(chMaterial_Black, "Black") ;
4874                                        pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
4875                                }
4876                               
4877                                // material for shadow casting
4878                                strcpy(chMaterial_Shadow, chMaterial_Base) ;
4879                                strcat(chMaterial_Shadow, "_Shadow") ;
4880                                pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
4881                                if(pMaterial_Shadow.isNull())
4882                                {
4883                                        strcpy(chMaterial_Shadow, "OPAQUE_Shadow") ;
4884                                        pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
4885                                }
4886
4887                               
4888                               
4889                                // material for shadow casting
4890                                strcpy(chMaterial_ShadeFront, chMaterial_Base) ;
4891                                strcat(chMaterial_ShadeFront, "_ShadeFront") ;
4892                                pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
4893                                if(pMaterial_ShadeFront.isNull())
4894                                {
4895                                         // standard opaque ShadeFront. 
4896                                        // Transparent surfaces MUST have their own _ShadeFront material or they will not colour light and can interfere with other trans surfaces.
4897                                        strcpy(chMaterial_ShadeFront, "OPAQUE_ShadeFront") ;
4898
4899                                        pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
4900                                }
4901
4902
4903                                // material for shadow casting
4904                                strcpy(chMaterial_ShadeBack, chMaterial_Base) ;
4905                                strcat(chMaterial_ShadeBack, "_ShadeBack") ;
4906                                pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
4907                                if(pMaterial_ShadeBack.isNull())
4908                                {
4909                                         // standard opaque ShadeBack. 
4910                                        // Transparent surfaces MUST have their own _ShadeBack material or they will not colour light and can interfere with other trans surfaces.
4911                                        strcpy(chMaterial_ShadeBack, "OPAQUE_ShadeBack") ;
4912
4913                                        pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
4914                                }
4915
4916                                // material for deferred shading
4917                                strcpy(chMaterial_DfShColour, chMaterial_Base) ;
4918                                strcat(chMaterial_DfShColour, "_DfShColour") ;
4919                                pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
4920                                if(pMaterial_DfShColour.isNull())
4921                                {
4922                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShColour) ;
4923                                        m_pLog->logMessage(chMessage);
4924
4925                                        strcpy(chMaterial_DfShColour, "DfShColour") ;
4926                                        pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
4927                                }
4928                               
4929
4930                                // material for deferred shading
4931                                strcpy(chMaterial_DfShPosition, chMaterial_Base) ;
4932                                strcat(chMaterial_DfShPosition, "_DfShPosition") ;
4933                                pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
4934                                if(pMaterial_DfShPosition.isNull())
4935                                {
4936                                        // only issue a warning if this is an alpha testing material, others don't need specialized DfShPosition materials
4937                                        if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
4938                                        {
4939                                                sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShPosition) ;
4940                                                m_pLog->logMessage(chMessage);
4941                                        }
4942
4943                                        strcpy(chMaterial_DfShPosition, "DfShPosition") ;
4944                                        pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
4945                                }
4946                               
4947                                // material for deferred shading
4948                                strcpy(chMaterial_DfShDiffuse, chMaterial_Base) ;
4949                                strcat(chMaterial_DfShDiffuse, "_DfShDiffuse") ;
4950                                pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
4951                                if(pMaterial_DfShDiffuse.isNull())
4952                                {
4953                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShDiffuse) ;
4954                                        m_pLog->logMessage(chMessage);
4955
4956                                        strcpy(chMaterial_DfShDiffuse, "DfShDiffuse") ;
4957                                        pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
4958                                }
4959
4960                                /*
4961                                // material for deferred shading // UNUSED
4962                                strcpy(chMaterial_DSNormal, chMaterial_Base) ;
4963                                strcat(chMaterial_DSNormal, "_DSNormal") ;
4964                                pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
4965                                if(pMaterial_DSNormal.isNull())
4966                                {
4967                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DSNormal) ;
4968                                        m_pLog->logMessage(chMessage);
4969
4970                                        strcpy(chMaterial_DSNormal, "DSNormal") ;
4971                                        pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
4972                                }
4973                                */
4974
4975                                // material for deferred shading
4976                                strcpy(chMaterial_DfShFuncTNB, chMaterial_Base) ;
4977                                strcat(chMaterial_DfShFuncTNB, "_DfShFuncTNB") ;
4978                                pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
4979                                if(pMaterial_DfShFuncTNB.isNull())
4980                                {
4981                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShFuncTNB) ;
4982                                        m_pLog->logMessage(chMessage);
4983
4984                                        strcpy(chMaterial_DfShFuncTNB, "DfShFuncTNB") ;
4985                                        pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
4986                                }
4987
4988                                // material for deferred shading
4989                                strcpy(chMaterial_DfShSpecular, chMaterial_Base) ;
4990                                strcat(chMaterial_DfShSpecular, "_DfShSpecular") ;
4991                                pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
4992                                if(pMaterial_DfShSpecular.isNull())
4993                                {
4994                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShSpecular) ;
4995                                        m_pLog->logMessage(chMessage);
4996
4997                                        strcpy(chMaterial_DfShSpecular, "DfShSpecular") ;
4998                                        pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
4999                                }
5000
5001                                // material for deferred shading
5002                                strcpy(chMaterial_DfShEmissive, chMaterial_Base) ;
5003                                strcat(chMaterial_DfShEmissive, "_DfShEmissive") ;
5004                                pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
5005                                if(pMaterial_DfShEmissive.isNull())
5006                                {
5007                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShEmissive) ;
5008                                        m_pLog->logMessage(chMessage);
5009
5010                                        strcpy(chMaterial_DfShEmissive, "DfShEmissive") ;
5011                                        pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
5012                                }
5013
5014
5015                                /*
5016                                // material for deferred shading
5017                                strcpy(chMaterial_DfShData, chMaterial_Base) ;
5018                                strcat(chMaterial_DfShData, "_DfShData") ;
5019                                pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
5020                                if(pMaterial_DfShData.isNull())
5021                                {
5022                                        sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShData) ;
5023                                        m_pLog->logMessage(chMessage);
5024
5025                                        strcpy(chMaterial_DfShData, "DfShData") ;
5026                                        pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
5027                                }
5028                                */
5029
5030                                // material for deferred shading
5031                                strcpy(chMaterial_DfShMix, chMaterial_Base) ;
5032                                strcat(chMaterial_DfShMix, "_DfShMix") ;
5033                                pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
5034                                if(pMaterial_DfShMix.isNull())
5035                                {
5036                                        // Pretty much all materials just use the default mix material,
5037                                        // so don't issue warnings if there isn't a specialized version
5038                                        //sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShMix) ;
5039                                        //m_pLog->logMessage(chMessage);
5040
5041                                        strcpy(chMaterial_DfShMix, "DfShMix") ;
5042                                        pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
5043                                }
5044                               
5045                       
5046
5047
5048
5049                        }// end if not MAT_LAMP or MAT_GLOW
5050                        else
5051                                if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW) // the two materials that glow needs
5052                                {
5053
5054                                        // when I get around to allowing user defined GLOW materials as well as the automatic ones,
5055                                        // this'll be the place to add it. 
5056                                        // For now, just the automatically generated lamp/light stuff has a glow.
5057                                       
5058                                        // if the base material was "GLOW_lamp"
5059                                        strcpy(chCompare, chMaterial_Base) ;
5060                                        chCompare[strlen("GLOW_lamp")]='\0' ;
5061                                        if(strcmp("GLOW_lamp", chCompare)==0) 
5062                                        {
5063                                                strcpy(chMaterial_DfShColour, "GLOW_lampcol") ;
5064                                                pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
5065
5066                                                strcpy(chMaterial_DfShEmissive, "GLOW_lamp") ;
5067                                                pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
5068                                        }
5069                                        else
5070                                        {
5071
5072                                                // if the base material was "GLOW_light"
5073                                                strcpy(chCompare, chMaterial_Base) ;
5074                                                chCompare[strlen("GLOW_light")]='\0' ;
5075                                                if(strcmp("GLOW_light", chCompare)==0) 
5076                                                {
5077                                                        strcpy(chMaterial_DfShColour, "GLOW_lightcol") ;
5078                                                        pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
5079
5080                                                        strcpy(chMaterial_DfShEmissive, "GLOW_light") ;
5081                                                        pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
5082                                                }
5083
5084                                        }
5085                                }
5086
5087
5088
5089
5090                        // if the entity is a lamp or glow, set its material because they never get changed
5091                        //if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW))
5092                        //      m_pZoneEntity[nMOIndex]->setMaterial( pMaterial_Base) ;
5093
5094
5095                        // store the pointers to the materials of this entity
5096                        //m_pZoneEntityMaterial_Base[nMOIndex]=pMaterial_Base ;
5097                        //m_pZoneEntityMaterial_Fast[nMOIndex]=pMaterial_Fast ;
5098                        m_pEntityInfo[nEntity].Material_Black[nSubMesh]=pMaterial_Black ;
5099                        m_pEntityInfo[nEntity].Material_DfShColour[nSubMesh]=pMaterial_DfShColour ;
5100                        m_pEntityInfo[nEntity].Material_Shadow[nSubMesh]=pMaterial_Shadow ;
5101                        m_pEntityInfo[nEntity].Material_ShadeFront[nSubMesh]=pMaterial_ShadeFront ;
5102                        m_pEntityInfo[nEntity].Material_ShadeBack[nSubMesh]=pMaterial_ShadeBack ;
5103                        m_pEntityInfo[nEntity].Material_DfShPosition[nSubMesh]=pMaterial_DfShPosition ;
5104                        m_pEntityInfo[nEntity].Material_DfShDiffuse[nSubMesh]=pMaterial_DfShDiffuse ;
5105                        //m_pEntityInfo[nEntity].Material_DSNormal[nSubMesh]=pMaterial_DSNormal ;
5106                        m_pEntityInfo[nEntity].Material_DfShFuncTNB[nSubMesh]=pMaterial_DfShFuncTNB ;
5107                        m_pEntityInfo[nEntity].Material_DfShSpecular[nSubMesh]=pMaterial_DfShSpecular ;
5108                        m_pEntityInfo[nEntity].Material_DfShEmissive[nSubMesh]=pMaterial_DfShEmissive ;
5109                        //m_pEntityInfo[nEntity].Material_DfShData[nSubMesh]=pMaterial_DfShData ;
5110                        m_pEntityInfo[nEntity].Material_DfShMix[nSubMesh]=pMaterial_DfShMix ;
5111
5112                       
5113                        //////////////////////////////////////////////////////////////////////////////////////////
5114
5115                        char chNewName[1024] ;
5116                        for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
5117                        {
5118                                Ogre::AliasTextureNamePairList AliasList ;
5119                               
5120                                // check the necessary texture exists
5121                                //if(TextureManager::getSingleton().getByName(m_Q3Map->m_chSpotlightTexture[nPTex]).isNull())
5122                                //      OFBug.MessageInt(666) ;
5123                               
5124                                AliasList.insert(AliasTextureNamePairList::value_type("projector_tex", m_Q3Map->m_chSpotlightTexture[nPTex]));
5125
5126                                sprintf(chNewName, "%s_%i", chMaterial_Base, 0) ;
5127                                m_pEntityInfo[nEntity].Material_Base[nPTex][nSubMesh]=pMaterial_Base->clone(chNewName) ;
5128                                // change the texture unit
5129                                m_pEntityInfo[nEntity].Material_Base[nPTex][nSubMesh]->applyTextureAliases(AliasList) ;
5130
5131                                sprintf(chNewName, "%s_%i", chMaterial_Fast, 0) ;
5132                                m_pEntityInfo[nEntity].Material_Fast[nPTex][nSubMesh]=pMaterial_Fast->clone(chNewName) ;
5133                                // change the texture unit
5134                                m_pEntityInfo[nEntity].Material_Fast[nPTex][nSubMesh]->applyTextureAliases(AliasList) ;
5135
5136                        }
5137
5138                        // create the sub scenenodes
5139                        //sprintf(chSubNodeName, "Entity_%05i_%05i", nEntity, nSubMesh) ;
5140                        //m_pEntityInfo[nEntity].pSubNode[nSubMesh]=m_pEntityInfo[nEntity].pMasterNode->createChildSceneNode(chSubNodeName) ;
5141
5142
5143                        sprintf(m_chBug, "Node %s, Subnode %s, Type %i", chMasterNodeName, chSubNodeName, m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]) ;
5144                        m_pLog->logMessage(m_chBug);
5145               
5146                }// end for submesh
5147
5148                // build tangent vectors for the mesh
5149                m_pEntityInfo[nEntity].pEnt->getMesh()->suggestTangentVectorBuildParams(VES_TANGENT, src, dest) ;
5150                m_pEntityInfo[nEntity].pEnt->getMesh()->buildTangentVectors(VES_TANGENT, src, dest);
5151
5152
5153        // default to not active, not visible and in no zones
5154        m_pEntityInfo[nEntity].Active=0 ;
5155        m_pEntityInfo[nEntity].Visible=0 ;
5156        m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=0 ;
5157
5158        // add some info about the bounding box
5159        Ogre::AxisAlignedBox aabb ;
5160        Ogre::Vector3 Minimum ;
5161        Ogre::Vector3 Maximum ;
5162
5163        aabb=m_pEntityInfo[nEntity].pEnt->getBoundingBox() ;
5164        Minimum=aabb.getMinimum() ;
5165        Maximum=aabb.getMaximum() ;
5166
5167        m_pEntityInfo[nEntity].AABB=aabb ;
5168        m_pEntityInfo[nEntity].Centre.x=(Maximum.x-Minimum.x)/2.0f ;
5169        m_pEntityInfo[nEntity].Centre.y=(Maximum.y-Minimum.y)/2.0f ;
5170        m_pEntityInfo[nEntity].Centre.z=(Maximum.z-Minimum.z)/2.0f ;
5171
5172        m_pEntityInfo[nEntity].AABBMin[0]=Minimum.x ;
5173        m_pEntityInfo[nEntity].AABBMin[1]=Minimum.y ;
5174        m_pEntityInfo[nEntity].AABBMin[2]=Minimum.z ;
5175        m_pEntityInfo[nEntity].AABBMax[0]=Maximum.x ;
5176        m_pEntityInfo[nEntity].AABBMax[1]=Maximum.y ;
5177        m_pEntityInfo[nEntity].AABBMax[2]=Maximum.z ;
5178
5179
5180        m_pEntityInfo[nEntity].Postition=Ogre::Vector3(0.0f, 0.0f, 0.0f) ;
5181
5182
5183
5184        return 1 ;
5185}
5186
5187
5188// Hmm... wanted to control some CG compiling, mainly to turn shadow filtering on or off, but I couln't get this to work.
5189// I ended up just manually creating filtered and unfiltered version of the materials.
5190/*
5191int OgreFramework::ApplyCGDefines(void)
5192{
5193        int nZoneMO=0 ;
5194        int nMaxZoneMO=m_nZoneMOStart[m_Q3Map->m_nMaxZone] ;
5195        int nPTex=0 ;
5196       
5197        Ogre::Pass *CGPass ;
5198        int nPass=0 ;
5199        int nMaxPass=0 ;
5200
5201        for(nZoneMO=0 ; nZoneMO<nMaxZoneMO ; nZoneMO++)
5202        {
5203                //OFBug.MessageInt(nZoneMO, nMaxZoneMO, m_pZoneEntityMaterialType[nZoneMO]) ;
5204               
5205                if(m_pZoneEntityMaterialType[nZoneMO]==MAT_OPAQUE)
5206                        for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
5207                        {
5208                                //m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(1)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON 1") ;
5209                                nMaxPass=m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getNumPasses() ;
5210                               
5211                                for(nPass=0 ; nPass<nMaxPass ; nPass++)
5212                                {
5213                                        m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(nPass)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON=1") ;
5214                                        //m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(nPass)->getFragmentProgram()->reload();
5215                                }       
5216                                //CGPass=m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(0) ;
5217                        }
5218        }
5219       
5220
5221        //m_pZoneEntityMaterial_Base[0][0]->getTechnique(0)->getPass(1)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON 1") ;
5222               
5223
5224        return 1 ;
5225
5226
5227}
5228*/
5229
5230
5231///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5232// create light manual objects, just for debugging/testing.
5233// This is an array of manualobject AABBs that show the light culling box (double sided) for each light
5234
5235int OgreFramework::AddLightCullingBoxes()
5236{
5237        int nLt=0 ;
5238        // for calculating bounds of mesh
5239        float flMinX=0.0f ;
5240        float flMinY=0.0f ;
5241        float flMinZ=0.0f ;
5242        float flMaxX=0.0f ;
5243        float flMaxY=0.0f ;
5244        float flMaxZ=0.0f ;
5245        int nMaxLight=m_Q3Map->m_nLightMax ;
5246
5247        char chSceneNodeName[1024] ;
5248        char chManualName[1024] ;
5249
5250        m_pLightMO = new Ogre::ManualObject*[nMaxLight] ;
5251        if(m_pLightMO==NULL) return 0 ; // fail, out of mem
5252
5253        for(nLt=0 ; nLt<nMaxLight ; nLt++)
5254        {
5255               
5256                sprintf(chManualName, "LightMO_%05i", nLt) ;
5257                m_pLightMO[nLt]=m_pSceneMgr->createManualObject(chManualName) ;
5258
5259                // start defining the manualObject
5260                m_pLightMO[nLt]->begin("lighttest", RenderOperation::OT_TRIANGLE_LIST) ;
5261
5262               
5263                flMinX=m_Q3Map->m_pLight[nLt].Min[0] ;
5264                flMinY=m_Q3Map->m_pLight[nLt].Min[1] ;
5265                flMinZ=m_Q3Map->m_pLight[nLt].Min[2] ;
5266
5267                flMaxX=m_Q3Map->m_pLight[nLt].Max[0] ;
5268                flMaxY=m_Q3Map->m_pLight[nLt].Max[1] ;
5269                flMaxZ=m_Q3Map->m_pLight[nLt].Max[2] ;
5270               
5271               
5272                //////////////////////////////////////////////////////
5273                // back face
5274                m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
5275                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5276                m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
5277
5278                m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
5279                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5280                m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
5281
5282                m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
5283                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5284                m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
5285
5286                m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
5287                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5288                m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
5289
5290                m_pLightMO[nLt]->quad(0, 1, 2, 3) ;
5291                m_pLightMO[nLt]->quad(3, 2, 1, 0) ;
5292
5293                //////////////////////////////////////////////////////
5294                // front face
5295                m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
5296                m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
5297                m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
5298
5299                m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
5300                m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
5301                m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
5302
5303                m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
5304                m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
5305                m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
5306
5307                m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
5308                m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
5309                m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
5310
5311                m_pLightMO[nLt]->quad(7, 6, 5, 4) ;
5312                m_pLightMO[nLt]->quad(4, 5, 6, 7) ;
5313
5314                //////////////////////////////////////////////////////
5315                // left face
5316                m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
5317                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5318                m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
5319
5320                m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
5321                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5322                m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
5323
5324                m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
5325                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5326                m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
5327
5328                m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
5329                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5330                m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
5331
5332                m_pLightMO[nLt]->quad(8, 9, 10, 11) ;
5333                m_pLightMO[nLt]->quad(11, 10, 9, 8) ;
5334
5335               
5336                //////////////////////////////////////////////////////
5337                // right face
5338                m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
5339                m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
5340                m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
5341
5342                m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
5343                m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
5344                m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
5345
5346                m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
5347                m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
5348                m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
5349
5350                m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
5351                m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
5352                m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
5353
5354                m_pLightMO[nLt]->quad(15, 14, 13, 12) ;
5355                m_pLightMO[nLt]->quad(12, 13, 14, 15) ;
5356
5357                //////////////////////////////////////////////////////
5358                // top face
5359                m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
5360                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5361                m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
5362
5363                m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
5364                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5365                m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
5366
5367                m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
5368                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5369                m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
5370
5371                m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
5372                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5373                m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
5374
5375                m_pLightMO[nLt]->quad(16, 17, 18, 19) ;
5376                m_pLightMO[nLt]->quad(19, 18, 17, 16) ;
5377
5378                //////////////////////////////////////////////////////
5379                // bottom face
5380                m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
5381                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5382                m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
5383
5384                m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
5385                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5386                m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
5387
5388                m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
5389                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5390                m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
5391
5392                m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
5393                m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
5394                m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
5395
5396                m_pLightMO[nLt]->quad(23, 22, 21, 20) ;
5397                m_pLightMO[nLt]->quad(20, 21, 22, 23) ;
5398                //////////////////////////////////////////////////////
5399
5400                m_pLightMO[nLt]->end() ;
5401
5402
5403
5404                sprintf(chSceneNodeName, "LSN%05i", nLt) ;
5405                m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName)->attachObject(m_pLightMO[nLt]) ;
5406
5407               
5408        }
5409
5410        return 1 ;
5411}
5412
5413int OgreFramework::AddPortalBoxes()
5414{
5415        int nPt=0 ;
5416        // for calculating bounds of mesh
5417        float flMinX=0.0f ;
5418        float flMinY=0.0f ;
5419        float flMinZ=0.0f ;
5420        float flMaxX=0.0f ;
5421        float flMaxY=0.0f ;
5422        float flMaxZ=0.0f ;
5423        int nMaxPortal=m_Q3Map->m_iNumPortals ;
5424
5425        char chSceneNodeName[1024] ;
5426        char chManualName[1024] ;
5427
5428        m_pPortalMO = new Ogre::ManualObject*[nMaxPortal] ;
5429        if(m_pPortalMO==NULL) return 0 ; // fail, out of mem
5430
5431        m_pPortalNode = new Ogre::Node*[nMaxPortal] ;
5432        if(m_pPortalNode==NULL) 
5433        {
5434                //CHECKDELETE_ARRAY( m_pPortalMO ) ;
5435                return 0 ; // fail, out of mem
5436        }
5437
5438        for(nPt=0 ; nPt<nMaxPortal ; nPt++)
5439        {
5440               
5441                sprintf(chManualName, "PortalMO_%05i", nPt) ;
5442                m_pPortalMO[nPt]=m_pSceneMgr->createManualObject(chManualName) ;
5443
5444                // start defining the manualObject
5445                m_pPortalMO[nPt]->begin("white", RenderOperation::OT_TRIANGLE_LIST) ;
5446
5447                flMinX=m_Q3Map->m_pPortals[nPt].Min[0] ;
5448                flMinY=m_Q3Map->m_pPortals[nPt].Min[1] ;
5449                flMinZ=m_Q3Map->m_pPortals[nPt].Min[2] ;
5450
5451                flMaxX=m_Q3Map->m_pPortals[nPt].Max[0] ;
5452                flMaxY=m_Q3Map->m_pPortals[nPt].Max[1] ;
5453                flMaxZ=m_Q3Map->m_pPortals[nPt].Max[2] ;
5454               
5455               
5456                //////////////////////////////////////////////////////
5457                // back face
5458                m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
5459                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5460                m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
5461
5462                m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
5463                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5464                m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
5465
5466                m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
5467                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5468                m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
5469
5470                m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
5471                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5472                m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
5473
5474                m_pPortalMO[nPt]->quad(0, 1, 2, 3) ;
5475                m_pPortalMO[nPt]->quad(3, 2, 1, 0) ;
5476
5477                //////////////////////////////////////////////////////
5478                // front face
5479                m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
5480                m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
5481                m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
5482
5483                m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
5484                m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
5485                m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
5486
5487                m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
5488                m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
5489                m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
5490
5491                m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
5492                m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
5493                m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
5494
5495                m_pPortalMO[nPt]->quad(7, 6, 5, 4) ;
5496                m_pPortalMO[nPt]->quad(4, 5, 6, 7) ;
5497
5498                //////////////////////////////////////////////////////
5499                // left face
5500                m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
5501                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5502                m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
5503
5504                m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
5505                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5506                m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
5507
5508                m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
5509                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5510                m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
5511
5512                m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
5513                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5514                m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
5515
5516                m_pPortalMO[nPt]->quad(8, 9, 10, 11) ;
5517                m_pPortalMO[nPt]->quad(11, 10, 9, 8) ;
5518
5519               
5520                //////////////////////////////////////////////////////
5521                // right face
5522                m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
5523                m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
5524                m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
5525
5526                m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
5527                m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
5528                m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
5529
5530                m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
5531                m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
5532                m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
5533
5534                m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
5535                m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
5536                m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
5537
5538                m_pPortalMO[nPt]->quad(15, 14, 13, 12) ;
5539                m_pPortalMO[nPt]->quad(12, 13, 14, 15) ;
5540
5541                //////////////////////////////////////////////////////
5542                // top face
5543                m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
5544                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5545                m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
5546
5547                m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
5548                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5549                m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
5550
5551                m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
5552                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5553                m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
5554
5555                m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
5556                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5557                m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
5558
5559                m_pPortalMO[nPt]->quad(16, 17, 18, 19) ;
5560                m_pPortalMO[nPt]->quad(19, 18, 17, 16) ;
5561
5562                //////////////////////////////////////////////////////
5563                // bottom face
5564                m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
5565                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5566                m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
5567
5568                m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
5569                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5570                m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
5571
5572                m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
5573                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5574                m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
5575
5576                m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
5577                m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
5578                m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
5579
5580                m_pPortalMO[nPt]->quad(23, 22, 21, 20) ;
5581                m_pPortalMO[nPt]->quad(20, 21, 22, 23) ;
5582                //////////////////////////////////////////////////////
5583
5584                m_pPortalMO[nPt]->end() ;
5585
5586
5587
5588                sprintf(chSceneNodeName, "PSN%05i", nPt) ;
5589                m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName)->attachObject(m_pPortalMO[nPt]) ;
5590                m_pPortalNode[nPt]=m_pSceneMgr->getRootSceneNode()->getChild(chSceneNodeName) ;
5591               
5592        }
5593
5594        return 1 ;
5595}
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5612
5613
5614
5615
5616// this function calculates which zones are visible. 
5617// If they are in the view frustum and any connecting portals are open, they're visible. 
5618// It calls a recursive functions that goes into each visible zone and scans it's portals
5619// for more visible zones, cutting down the frustum as it goes.
5620//
5621// This function also checks which lights are visible.
5622// First it scans the original zone the camera is in, any light whose centre is in that zone
5623// is visible regardless of how many other zones that light touches.
5624// Lights that are completely contained in any of the further zones are checked against the
5625// current cut down frustum.
5626void OgreFramework::CalculateZoneVisibility(Ogre::Camera *pCamera, int *pCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis, char* pPortalVis, int* pMaxVisibleLight, unsigned short* pVisibleLightList)
5627{
5628
5629       
5630        int nZone=0 ;
5631//      int nZoneIndex=0 ;
5632        int nSubZone=0 ;
5633//      int nSubZoneIndex=0 ;
5634        int nMaxSubZone=0 ;
5635        int nPortal=0 ;
5636//      int nPortalIndex=0 ;
5637        int nMaxPortal=0 ;
5638//      int nMaxPortalZone=0 ;
5639//      int nPortalZone=0 ;
5640//      int nPortalZoneIndex=0 ;
5641//      int nMaxZone=0 ;
5642       
5643
5644        int nMaxLight=m_Q3Map->m_nLightMax ;
5645        int nLt=0 ;
5646
5647//      int nMaxSubLight=m_Q3Map->m_nSubLightMax ;
5648        int nSubLt=0 ;
5649       
5650        m_nMaxVisibleLight=0 ;
5651
5652       
5653
5654        Ogre::Vector3 Pos=pCamera->getPosition() ;
5655        float flPos[3]={Pos.x, Pos.y, Pos.z} ;
5656
5657        Ogre::AxisAlignedBox AAB ;
5658
5659
5660
5661        // initially all lights are invisible
5662        // set all remaining real lights to invisible
5663        SetAllLightsOff() ;
5664
5665        m_nTotalTriangles=0 ;
5666
5667        *pMaxVisibleLight=0 ; // no lights in the list
5668       
5669        if(m_nZoneCullingActive) // if zone culling is active
5670        {
5671               
5672                // by default, all zones are not visible
5673                nZone=m_Q3Map->m_nMaxZone ;
5674                while(nZone)
5675                        pZoneVis[--nZone]=ZONE_UNCHECKED ;
5676
5677                // by default, all lights are not visible
5678                nLt=nMaxLight ;
5679                while(nLt)
5680                        pLightVis[--nLt]=LIGHT_UNCHECKED ;
5681
5682                // by default, all lights are not visible
5683                nSubLt=m_Q3Map->m_nSubLightMax ;
5684                while(nSubLt)
5685                        pSubLightVis[--nSubLt]=LIGHT_UNCHECKED ;
5686
5687                // by default, all portals are not visible
5688                nPortal=m_Q3Map->m_iNumPortals ;
5689                while(nPortal)
5690                        pPortalVis[--nPortal]=PORTAL_UNCHECKED ;
5691        }
5692        else
5693        {
5694                // for debugging, all zones are visible
5695                nZone=m_Q3Map->m_nMaxZone ;
5696                while(nZone)
5697                        pZoneVis[--nZone]=ZONE_VISIBLE ;
5698
5699
5700                // by default, all lights are visible
5701                nLt=nMaxLight ;
5702                while(nLt)
5703                        pLightVis[--nLt]=LIGHT_VISIBLE ;
5704
5705                nSubLt=m_Q3Map->m_nSubLightMax ;
5706                while(nSubLt)
5707                        pSubLightVis[--nSubLt]=LIGHT_VISIBLE ;
5708
5709                // by default, all portals are visible
5710                nPortal=m_Q3Map->m_iNumPortals ;
5711                while(nPortal)
5712                        pPortalVis[--nPortal]=PORTAL_VISIBLE ;
5713
5714                return ;
5715        }
5716
5717
5718
5719
5720
5721
5722
5723
5724        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5725       
5726
5727
5728        /////////////////////////////////////////////////////////////////////////////////////
5729        // check camera is actually in the zone designated, otherwise update it.
5730
5731        if((*pCameraZone==-1) || (!m_Q3Map->PointInZone(flPos, *pCameraZone)) )
5732        {
5733
5734                nSubZone=m_Q3Map->GetNextSubZone(flPos, -1, m_Q3Map->m_iNumSubZones) ;
5735                       
5736                // subzone might still be -1 if the point isn't in any zone.  If this happens, set all zones in the view frustum as visible.
5737                // this shouldn't generally happen, but if we aren't clipping and are flying around testing, it can.
5738                // Don't worry about optimizing this.
5739
5740
5741
5742                if(nSubZone==-1)
5743                {
5744
5745                        nMaxSubZone=m_Q3Map->m_iNumSubZones ;
5746                        for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
5747                        {
5748                                AAB.setExtents(m_Q3Map->m_pSubZones[nSubZone].Min[0], m_Q3Map->m_pSubZones[nSubZone].Min[1], m_Q3Map->m_pSubZones[nSubZone].Min[2], m_Q3Map->m_pSubZones[nSubZone].Max[0], m_Q3Map->m_pSubZones[nSubZone].Max[1], m_Q3Map->m_pSubZones[nSubZone].Max[2]) ;
5749
5750                                if(pCamera->isVisible(AAB))
5751                                        pZoneVis[ m_Q3Map->m_pSubZones[nSubZone].Zone ]=ZONE_VISIBLE ;
5752                        }       
5753
5754                        *pCameraZone=-1 ;
5755                        return ; // skip everything else
5756                }
5757
5758                *pCameraZone=m_Q3Map->m_pSubZones[nSubZone].Zone ; // update the zone
5759       
5760        }
5761
5762        //
5763        /////////////////////////////////////////////////////////////////////////////////////
5764
5765
5766        // update the portal states
5767        nMaxPortal=m_Q3Map->m_iNumPortals ;
5768        nPortal=nMaxPortal ;
5769        while(nPortal)
5770        {
5771                nPortal-- ;
5772
5773                if(m_nPortalDebug==0)
5774                        m_chPortalState[nPortal]=PORTALSTATE_OPEN ; 
5775                else
5776                {
5777                        //if(m_nPortalState==1)
5778                                m_chPortalState[nPortal]=PORTALSTATE_OPEN ; 
5779                        //else
5780                        //      m_chPortalState[nPortal]=PORTALSTATE_CLOSED ;
5781
5782
5783                       
5784                }
5785               
5786                //m_chPortalState[nPortal]|=PORTAL_FLAG_UNCHECKED ; // by default all portals are unchecked
5787               
5788                //m_chPortalState[nPortal]&=~(PORTAL_FLAG_VISCHECK|PORTAL_FLAG_VISIBLE) ; // by default, all portals are vis unchecked and not visible
5789        }
5790
5791        //m_chPortalState[0]=PORTAL_FLAG_CLOSED ;
5792        if(m_nPortalState==1)
5793                m_chPortalState[1]=PORTALSTATE_OPEN ;
5794        else
5795                m_chPortalState[1]=PORTALSTATE_CLOSED ;
5796
5797
5798
5799
5800        //Ogre::Camera* pTestCamera ;
5801        //pTestCamera->synchroniseBaseSettingsWith(pCamera) ;
5802
5803        //Ogre::Real OrigL, OrigR, OrigT, OrigB ; // original frustum extents
5804        //pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
5805       
5806        //pCamera->setFrustumExtents(OrigL/2.0, OrigR/2.0, OrigT/2.0, OrigB/2.0) ; // reset the original frustum extents
5807
5808        m_nRecurseCount=0 ;
5809
5810       
5811        // work out the aspect scaling we'll need
5812        Ogre::Real OrigL, OrigR, OrigT, OrigB, ScaleX, ScaleY ; // frustum extents per each portal in this zone
5813        Ogre::Real NewL, NewR, NewT, NewB ;
5814        pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
5815
5816        m_ViewMatrix=pCamera->getViewMatrix(true) ;
5817        m_ProjectionMatrix=pCamera->getProjectionMatrix() ;
5818       
5819
5820        //if(m_nOriginalZoneOpenPortals=0) // no portals on player zone are open, so we can only see the current zones.
5821        //      pZoneVis[nZone]=ZONE_VISIBLE ; // flag this subzone as visible
5822        //else
5823        {
5824
5825                /*
5826                // apply the stereofrustum tweak if needed
5827                if(m_flStereoFrustumTweak!=0.0f)
5828                {
5829
5830                        NewL=OrigL-m_flStereoFrustumTweak ;
5831                        NewR=OrigR+m_flStereoFrustumTweak ;
5832                        NewT=OrigT ;
5833                        NewB=OrigB ;
5834                        pCamera->setFrustumExtents(NewL, NewR, NewT, NewB) ;
5835                }
5836                else
5837                */
5838                {
5839                        NewL=OrigL ;
5840                        NewR=OrigR ;
5841                        NewT=OrigT ;
5842                        NewB=OrigB ;
5843                }
5844               
5845                ScaleX=NewR ;
5846                ScaleY=NewT ;
5847
5848
5849                PortalScan(pCamera, *pCameraZone, ScaleX, ScaleY, pZoneVis, pLightVis, pSubLightVis, pPortalVis, pMaxVisibleLight, pVisibleLightList) ; // recursively scan portals and work out zone visibility
5850
5851               
5852                pCamera->setFrustumExtents(OrigL, OrigR, OrigT, OrigB) ; // reset the original frustum extents
5853
5854                CheckMultiZoneLights(*pCameraZone, pZoneVis, pLightVis, pSubLightVis) ;
5855                AddZonesFromMultiZoneLights(pZoneVis, pLightVis, pSubLightVis) ;
5856
5857                // check entity visibility
5858               
5859
5860        }
5861
5862
5863
5864
5865
5866
5867
5868       
5869}
5870
5871
5872void OgreFramework::SetupEntityZones(void)
5873{
5874        // work out what zones any active entities are in.
5875        int nEntity=0 ;
5876        float Centre[3] ;
5877        float AABBMin[3] ;
5878        float AABBMax[3] ;
5879        float* pLightMin ;
5880        float* pLightMax ;
5881       
5882        int nOldZone=0 ;
5883        int nCurrentZone=0 ;
5884        int nMaxOldZone=0 ;
5885        int nZonePerZoneIndex=0 ;
5886        int nZone=0 ;
5887        int nZoneIndex=0 ;
5888        int nMaxZone=0 ;
5889        int nMaxSubLightIndex=0 ;
5890        int nSubLightIndex=0 ;
5891        int nSubLight=0 ;
5892
5893//      int nLight=0;
5894        int nLightIndex=0 ;
5895
5896
5897       
5898
5899        for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
5900                if(m_pEntityInfo[nEntity].Active)
5901                {
5902                        nLightIndex=0 ;
5903                        // to calculate what zones an entity is in, we test the centre of it's bounding box to get the main zone.
5904                        // we then test all zones that touch the central zone and see if they touch the entity bounding box.
5905
5906                        // check if the entity central point is still in the same zone as last time.
5907                        Centre[0]=m_pEntityInfo[nEntity].Centre.x + m_pEntityInfo[nEntity].Postition.x ;
5908                        Centre[1]=m_pEntityInfo[nEntity].Centre.y + m_pEntityInfo[nEntity].Postition.y ;
5909                        Centre[2]=m_pEntityInfo[nEntity].Centre.z + m_pEntityInfo[nEntity].Postition.z ;
5910
5911                        nMaxOldZone=m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT] ;
5912
5913
5914
5915                        if(nMaxOldZone>0)
5916                        {
5917                                nOldZone=m_pEntityInfo[nEntity].Zone[0] ;
5918                                if(m_Q3Map->PointInZone(Centre, nOldZone))
5919                                        nCurrentZone=nOldZone ; // still in the same zone as last round
5920                                else
5921                                {
5922                                        // see if we are in one of the other zones that were touched by this entity's aabb last round
5923
5924                                        nCurrentZone=-1 ;
5925                                        for(nZoneIndex=1 ; nZoneIndex<nMaxOldZone ; nZoneIndex++)
5926                                        {
5927                                                if(m_Q3Map->PointInZone(Centre, m_pEntityInfo[nEntity].Zone[nZoneIndex]))
5928                                                {
5929                                                        nCurrentZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ; // found the current zone we are in
5930                                                        break ;
5931                                                }// end if point in zone
5932
5933                                        }// end for zoneindex
5934
5935                                }// end if not in old zone.
5936                        }
5937                        else
5938                                nCurrentZone=-1 ;
5939
5940
5941                        // if we haven't found the current zone so far, we need to check every zone.
5942                        if(nCurrentZone==-1)
5943                        {
5944                                nZone=m_Q3Map->m_nMaxZone ;
5945                                while(nZone)
5946                                        if(m_Q3Map->PointInZone(Centre, --nZone))
5947                                        {
5948                                                nCurrentZone=nZone ;
5949                                                break ;
5950                                        }
5951                        }// end if nCurrentZone -1
5952
5953
5954                       
5955                        // now either nCurrentZone is the zone the central point is in, or the entity isn't in any zone
5956                        if(nCurrentZone==-1)
5957                                m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=0 ;
5958                        else
5959                        {
5960                                // scan through all the zones that touch this entitys central zone
5961                                // see if the entitys AABB touches those other zones.
5962                                m_pEntityInfo[nEntity].Zone[0]=nCurrentZone ;
5963                                nZonePerZoneIndex=1 ;
5964                               
5965                                AABBMin[0]=m_pEntityInfo[nEntity].Postition.x + m_pEntityInfo[nEntity].AABBMin[0] ; 
5966                                AABBMin[1]=m_pEntityInfo[nEntity].Postition.y + m_pEntityInfo[nEntity].AABBMin[1] ; 
5967                                AABBMin[2]=m_pEntityInfo[nEntity].Postition.z + m_pEntityInfo[nEntity].AABBMin[2] ;
5968
5969                                AABBMax[0]=m_pEntityInfo[nEntity].Postition.x + m_pEntityInfo[nEntity].AABBMax[0] ; 
5970                                AABBMax[1]=m_pEntityInfo[nEntity].Postition.y + m_pEntityInfo[nEntity].AABBMax[1] ; 
5971                                AABBMax[2]=m_pEntityInfo[nEntity].Postition.z + m_pEntityInfo[nEntity].AABBMax[2] ;
5972
5973
5974                                nMaxZone=m_Q3Map->m_nZoneTouchesZone[nCurrentZone][INDEX_ZONEPERZONECOUNT] ;
5975                                for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++)
5976                                {
5977                                        nZone=m_Q3Map->m_nZoneTouchesZone[nCurrentZone][nZoneIndex] ;
5978
5979                                        if(m_Q3Map->AABBTouchesZone(AABBMin, AABBMax, nZone)) 
5980                                        {
5981                                                m_pEntityInfo[nEntity].Zone[nZonePerZoneIndex]=nZone ;
5982                                                nZonePerZoneIndex++ ;
5983
5984                                                if(nZonePerZoneIndex>MAX_ZONEPERENTITY)
5985                                                        nZonePerZoneIndex=MAX_ZONEPERENTITY ;
5986                                        }
5987
5988                                       
5989
5990                                }// end for nZoneIndex
5991
5992
5993                                m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=nZonePerZoneIndex ;
5994
5995                                // go through all the zones and check which lights touch this entity AABB
5996                                for(nZoneIndex=0 ; nZoneIndex<nZonePerZoneIndex ; nZoneIndex++)
5997                                {
5998                                        nZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ;
5999
6000                                        nMaxSubLightIndex=m_Q3Map->m_nZoneTouchesSubLight[nZone][MAX_LIGHTPERZONE] ;
6001                                        for(nSubLightIndex=0 ; nSubLightIndex<nMaxSubLightIndex ; nSubLightIndex++)
6002                                        {
6003                                                nSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][nSubLightIndex] ;
6004                                                pLightMin=m_Q3Map->m_SubLight[nSubLight].Min ;
6005                                                pLightMax=m_Q3Map->m_SubLight[nSubLight].Max ;
6006
6007                                                // if the entity overlaps the sublight
6008                                                if(
6009                                                                         (AABBMin[0]<pLightMax[0]) && (AABBMax[0]>pLightMin[0])
6010                                                                && (AABBMin[1]<pLightMax[1]) && (AABBMax[1]>pLightMin[1])
6011                                                                && (AABBMin[2]<pLightMax[2]) && (AABBMax[2]>pLightMin[2])
6012                                                        )
6013                                                {
6014                                                        // add this to the list of lights.
6015                                                        // it's possible it might get listed more than once if this is a multizone light, that's ok.
6016                       
6017                                                        m_pEntityInfo[nEntity].Light[nLightIndex]=m_Q3Map->m_SubLight[nSubLight].Light ;
6018                                                        nLightIndex++ ;
6019                                                        if(nLightIndex>MAX_LIGHTPERENTITY)
6020                                                                nLightIndex=MAX_LIGHTPERENTITY ;
6021
6022
6023                                                } // end if overlap
6024
6025                                        }// end for nSubLightIndex
6026
6027                                }// end for nZoneIndex
6028
6029                        }// end if we have a central zone
6030                       
6031                       
6032                        m_pEntityInfo[nEntity].Light[INDEX_LIGHTPERENTITY]=nLightIndex ;
6033
6034
6035                }// end if entity is active
6036}
6037
6038// spotlights need entities set as visible if they are in a visible zone, even if they aren't in the frustum,
6039// because they might cast shadows that are in the frustum.
6040// However the deferred render only needs consider entities which are in a visible zone AND in the frustum.
6041// m_pVisibleEntity holds entities in visible zones,
6042// m_pFrustumEntity holds entities in visible zones that are also in the view frustum.
6043void OgreFramework::CalculateEntityVisibility(Ogre::Camera* pCamera, char* pZoneVis)
6044{
6045
6046        int nEntity=0 ;
6047        int nMaxZone=0 ;
6048        int nZone=0 ;
6049        int nZoneIndex=0 ;
6050//      int nVisible=0 ;
6051        Ogre::AxisAlignedBox AABB ;
6052
6053
6054        m_nMaxVisibleEntity=0 ; // default to an empty list
6055        m_nMaxFrustumEntity=0 ; // default to an empty list
6056
6057        m_nVisibleEntityTriangleCount=0 ;
6058        m_nFrustumEntityTriangleCount=0 ;
6059
6060        for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
6061                if(m_pEntityInfo[nEntity].Active)
6062                {
6063                        m_pEntityInfo[nEntity].Visible=0 ; // default to not visible
6064                        m_pEntityInfo[nEntity].Frustum=0 ; // default to not visible and not in frustum
6065
6066                        nMaxZone=m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT] ;
6067
6068
6069
6070                                for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++)
6071                                {
6072                                        nZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ;
6073
6074                                        // if a zone this entity touches is visible, test if it is in the view frustrum
6075                                        if(pZoneVis[nZone]==ZONE_VISIBLE)
6076                                        {
6077
6078                                                m_pEntityInfo[nEntity].Visible=1 ;
6079                                                m_nVisibleEntityTriangleCount+=m_pEntityInfo[nEntity].TriangleCount ;
6080                                                m_pVisibleEntity[m_nMaxVisibleEntity++]=nEntity ;
6081                                               
6082
6083                                                // is this entity also in the view frustum?
6084                                                AABB.setMinimum( m_pEntityInfo[nEntity].AABB.getMinimum() + m_pEntityInfo[nEntity].Postition ) ;
6085                                                AABB.setMaximum( m_pEntityInfo[nEntity].AABB.getMaximum() + m_pEntityInfo[nEntity].Postition ) ;
6086
6087                                                if(pCamera->isVisible(AABB))
6088                                                {
6089                                                        m_pEntityInfo[nEntity].Frustum=1 ;
6090                                                        m_nFrustumEntityTriangleCount+=m_pEntityInfo[nEntity].TriangleCount ;
6091                                                        m_pFrustumEntity[m_nMaxFrustumEntity++]=nEntity ;
6092                                                }
6093
6094
6095
6096
6097
6098                                                break ; // get out of the loop, we know the entity is visible.
6099
6100                                        }// end if zone is visible
6101
6102                                }// end for nZoneIndex
6103
6104                }// end if entity is active
6105
6106}
6107
6108
6109
6110
6111
6112void OgreFramework::SetAllLightsOff(void)
6113{
6114        Light *light;
6115        char chLightName[1024] ;
6116        int nLt=0 ;
6117        for(nLt=0 ; nLt<MAXLIGHTPERLOOP ; nLt++)
6118        {
6119                sprintf(chLightName, "LT%02i", nLt) ;
6120                light=m_pSceneMgr->getLight(chLightName) ;
6121                light->setVisible(false) ;
6122        }
6123}
6124
6125void OgreFramework::SetSingleVisibleLight(int nLt, bool bOn)
6126{
6127        Light *light;
6128
6129        light=m_pSceneMgr->getLight("LT00") ;
6130
6131
6132        // if we're just turning the light off, make it invisible and return.
6133        if(bOn==false)
6134        {
6135                light->setVisible(false) ;
6136                return ;
6137        }
6138
6139       
6140                       
6141        light->setDiffuseColour(Ogre::ColourValue(1,1,1));
6142        light->setSpecularColour(Ogre::ColourValue(1,1,1));
6143                       
6144        light->setAttenuation(m_Q3Map->m_pLight[nLt].Cutoff, 1.0, 1.0, 0.005);
6145        light->setPosition(Ogre::Vector3(m_Q3Map->m_pLight[nLt].Position[0], m_Q3Map->m_pLight[nLt].Position[1], m_Q3Map->m_pLight[nLt].Position[2]));
6146        light->setDirection(Ogre::Vector3(m_Q3Map->m_pLight[nLt].Direction[0], m_Q3Map->m_pLight[nLt].Direction[1], m_Q3Map->m_pLight[nLt].Direction[2]));
6147                       
6148        light->setSpotlightRange(Degree(m_Q3Map->m_pLight[nLt].Angle-5.0), Degree(m_Q3Map->m_pLight[nLt].Angle), 1.0) ;
6149        light->setVisible(true) ;
6150}
6151
6152
6153// sets up a single visible light from the visible light list and assigns the camera to its position and settings
6154// returns true if successful, false if not (such as if the light isn't actually visible)
6155
6156bool OgreFramework::SetupSingleVisibleLightAndShadowCamera(int nLt, char* pLightVis, unsigned short* pVisibleLightList, Ogre::Camera* pCamera)
6157{
6158        //if(nLt!=4) return false ;
6159       
6160        if((pLightVis[nLt]&LIGHT_VISIBLE)==0) // we need to check this again, since there's a chance a multi-zone light might have been culled at the last stage
6161                return false ;
6162
6163       
6164        Light *light=m_pSceneMgr->getLight("LT00") ;
6165       
6166        light->setDiffuseColour(Ogre::ColourValue(m_Q3Map->m_pLight[nLt].Colour[0], m_Q3Map->m_pLight[nLt].Colour[1], m_Q3Map->m_pLight[nLt].Colour[2]));
6167
6168        float   flRange=m_Q3Map->m_pLight[nLt].Cutoff ; // set the range
6169        if(flRange<10240.0) //!! Ogre seems to cut off lights wrongly if the range is low, so set it to a minimum.
6170                flRange=10240 ;
6171
6172        // The light attenuation parameters have been co-opted by me... they no longer represent range, constant, linear, quadratic
6173        // instead,
6174        // first parameter is the above range, just set high so Ogre doesn't turn lights off itself.  The shaders ignore this parameter.
6175        // second parameter is the cutoff used in the shader.  Light suddenly cuts off after this distance.
6176        // third parameter is the brightness.  This controls the quadratic falloff of the light.
6177        // fourth parameter is unused, leave as 1.0 for now.
6178
6179        light->setAttenuation(flRange, m_Q3Map->m_pLight[nLt].Cutoff, m_Q3Map->m_pLight[nLt].Brightness, 1.0) ;
6180       
6181       
6182       
6183        // Ogre uses a fixed yaw axis which will cause pCamera->setDirection to malfunction if we point directly up or down.
6184        // To avoid this we need to check for such lights and shift their direction a little.
6185       
6186        float DirX=m_Q3Map->m_pLight[nLt].Direction[0] ;
6187        float DirY=m_Q3Map->m_pLight[nLt].Direction[1] ;
6188        float DirZ=m_Q3Map->m_pLight[nLt].Direction[2] ;
6189       
6190
6191        if((DirY>1.0-CAMERA_EPSILON) && (DirY<1.0+CAMERA_EPSILON)) // camera is pointing directly up
6192        {
6193                DirX=0.0f ;
6194                DirY=1.0f ;
6195                DirZ=0.000001f ;
6196        }
6197        else
6198                if((DirY>-1.0-CAMERA_EPSILON) && (DirY<-1.0+CAMERA_EPSILON)) // camera is pointing directly down
6199                {
6200                        DirX=0.0f ;
6201                        DirY=-1.0f ;
6202                        DirZ=0.000001f ;
6203                }
6204       
6205        light->setPosition(Ogre::Vector3(m_Q3Map->m_pLight[nLt].Position[0], m_Q3Map->m_pLight[nLt].Position[1], m_Q3Map->m_pLight[nLt].Position[2]));
6206        light->setDirection(Ogre::Vector3(DirX, DirY, DirZ));
6207                       
6208        light->setSpotlightRange(Degree(m_Q3Map->m_pLight[nLt].Angle-5.0), Degree(m_Q3Map->m_pLight[nLt].Angle), 1.0) ;
6209        light->setVisible(true) ;
6210
6211        // setup the camera
6212        pCamera->setAspectRatio(1) ;
6213        pCamera->yaw(Ogre::Radian(0)) ;
6214        pCamera->roll(Ogre::Radian(0)) ;
6215        pCamera->pitch(Ogre::Radian(0)) ;
6216        pCamera->setPosition(m_Q3Map->m_pLight[nLt].Position[0], m_Q3Map->m_pLight[nLt].Position[1], m_Q3Map->m_pLight[nLt].Position[2]) ;
6217        pCamera->setDirection(DirX, DirY, DirZ) ;
6218        pCamera->setFOVy( Degree(m_Q3Map->m_pLight[nLt].Angle ) ) ;
6219
6220        return true ;
6221
6222}
6223
6224
6225void OgreFramework::UpdateVisibleZoneList(char* pZoneVis, unsigned short* pVisibleZoneList, int* pMaxVisibleZone)
6226{
6227        int nZone=0 ;
6228        int nMaxVisibleZone=0 ;
6229
6230        for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
6231                if(pZoneVis[nZone]==ZONE_VISIBLE)
6232                        pVisibleZoneList[nMaxVisibleZone++]=nZone ;
6233
6234        *pMaxVisibleZone=nMaxVisibleZone ;
6235
6236}
6237
6238void OgreFramework::SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags)
6239{
6240
6241                int nListPos=0 ;
6242                int nZone=0 ;
6243                int nMaxListPos=*pMaxVisibleZone ;
6244
6245
6246
6247                for(nListPos=0 ; nListPos<nMaxListPos ; nListPos++)
6248                {
6249                        nZone=pVisibleZoneList[nListPos] ;
6250
6251                                // if the zone node is not already attached, attach it.
6252
6253                                if( m_nOpaqueNodeUsed[nZone] && (nMaterialFlags&MAT_OPAQUE) && !m_pOpaqueNode[nZone]->isInSceneGraph() )
6254                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
6255
6256                                if( m_nTransNodeUsed[nZone] && (nMaterialFlags&MAT_GEL) && !m_pTransNode[nZone]->isInSceneGraph() )
6257                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
6258
6259                                if( m_nLampNodeUsed[nZone] && (nMaterialFlags&MAT_LAMP) && !m_pLampNode[nZone]->isInSceneGraph() )
6260                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
6261
6262                                if( m_nGlowNodeUsed[nZone] && (nMaterialFlags&MAT_GLOW) && !m_pGlowNode[nZone]->isInSceneGraph() )
6263                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
6264
6265                }
6266
6267
6268                       
6269/*
6270                if(m_nDebugLightBox)
6271                {
6272                        int nLt=0 ;
6273                        int nMaxLight=m_Q3Map->m_nLightMax ;
6274
6275                        for(nLt=0 ; nLt<nMaxLight ; nLt++)
6276                                if(m_chLightVis[nLt]==LIGHT_VISIBLE)
6277                                {
6278                                        m_pLightMO[nLt]->setVisible(true) ;
6279
6280                                }
6281                                else
6282                                        m_pLightMO[nLt]->setVisible(false) ;
6283
6284
6285
6286                }
6287
6288                if(m_nPortalDebug)
6289                {
6290                        int nPt=0 ;
6291                        int nMaxPortal=m_Q3Map->m_iNumPortals ;
6292
6293                        for(nPt=0 ; nPt<nMaxPortal ; nPt++)
6294                                if(
6295                                                        (m_chPortalVis[nPt]&PORTAL_VISIBLE)
6296                                                        &&
6297                                                        (m_chPortalState[nPt]&PORTALSTATE_CLOSED)
6298                                        )
6299                                        m_pPortalMO[nPt]->setVisible(true) ;
6300                                else
6301                                        m_pPortalMO[nPt]->setVisible(false) ;
6302                }               
6303                       
6304        */
6305}
6306
6307
6308void OgreFramework::SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags, int nLight)
6309{
6310
6311                nLight=IGNORE_LIGHT ;
6312
6313                int nListPos=0 ;
6314                int nZone=0 ;
6315                int nMaxListPos=*pMaxVisibleZone ;
6316
6317                int nLightZone=0 ;
6318                int nMaxLightZone=0 ;
6319                int nFoundZone=0 ;
6320
6321
6322                for(nListPos=0 ; nListPos<nMaxListPos ; nListPos++)
6323                {
6324                        nZone=pVisibleZoneList[nListPos] ;
6325
6326                        // is this zone touched by this light?
6327                        if(nLight!=IGNORE_LIGHT)
6328                        {
6329                                nMaxLightZone=m_Q3Map->m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
6330
6331                                nFoundZone=0 ;
6332                                for(nLightZone=0 ; nLightZone<nMaxLightZone ; nLightZone++)
6333                                        if(m_Q3Map->m_nLightTouchesZone[nLight][nLightZone]==nZone)
6334                                        {
6335                                                nFoundZone=1 ;
6336                                                break ;
6337                                        }
6338
6339                        }
6340                        else
6341                                nFoundZone=1 ;
6342
6343
6344                        if(nFoundZone) // if the light touches this zone, or we're ignoring lights
6345                        {
6346                                // if the zone node is not already attached, attach it.
6347
6348                                if( m_nOpaqueNodeUsed[nZone] && (nMaterialFlags&MAT_OPAQUE) && !m_pOpaqueNode[nZone]->isInSceneGraph() )
6349                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
6350
6351                                if( m_nTransNodeUsed[nZone] && (nMaterialFlags&MAT_GEL) && !m_pTransNode[nZone]->isInSceneGraph() )
6352                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
6353
6354                                if( m_nLampNodeUsed[nZone] && (nMaterialFlags&MAT_LAMP) && !m_pLampNode[nZone]->isInSceneGraph() )
6355                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
6356
6357                                if( m_nGlowNodeUsed[nZone] && (nMaterialFlags&MAT_GLOW) && !m_pGlowNode[nZone]->isInSceneGraph() )
6358                                        m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
6359                        }
6360                }
6361
6362}
6363
6364bool OgreFramework::LightTouchesZone(int nLight, int nZone)
6365{
6366                int nLightZone=0 ;
6367                int nMaxLightZone=0 ;
6368
6369                nMaxLightZone=m_Q3Map->m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
6370                               
6371                for(nLightZone=0 ; nLightZone<nMaxLightZone ; nLightZone++)
6372                        if(m_Q3Map->m_nLightTouchesZone[nLight][nLightZone]==nZone)
6373                                return true ;
6374
6375                return false ;
6376}
6377
6378
6379// last chance to cull some more multizone lights
6380// Then we set all zones the remaining multizone lights touch to visible so that we get correct shadows
6381void OgreFramework::CheckMultiZoneLights(int nCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis)
6382{
6383        int nLightMax=m_Q3Map->m_nMaxMultiZoneLight ;
6384        int nLight=0 ;
6385        int nLightIndex=0 ;
6386//      int nLightVal=0 ;
6387        int nOpenPortals=0 ;
6388//      int nZoneHasOpenPortals=0 ;
6389        int nPortal=0 ;
6390        int nPortalIndex=0 ;
6391        int nMaxPortal=0 ;
6392//      int nZone=0 ;
6393//      int nMaxZone=0 ;
6394//      int nZoneIndex=0 ;
6395
6396        int nSubLightMax=0 ;
6397//      int nSubLightIndex=0 ;
6398        int nSubLight=0 ;
6399        int nSubLightStart=0 ;
6400
6401        int nPortalLightMax=0 ;
6402        int nPortalLightIndex=0 ;
6403//      int nPortalLight=0 ;
6404
6405        int nCentreZone=0 ;
6406
6407
6408        for(nLightIndex=0 ; nLightIndex<nLightMax ; nLightIndex++)
6409        {
6410                nLight=m_Q3Map->m_nMultiZoneLight[nLightIndex] ;
6411                if(pLightVis[nLight]==LIGHT_VISIBLE) // try to kill multizone lights that are currently set as visible
6412                {
6413
6414                        ////////////////////////////////////////////////////////////////////////////////////////////////////////////.
6415                        // if the zone that contains the centre isn't visible,
6416                        // and the portals that the light touches are closed,
6417                        // then this light can't be visible anywhere else
6418
6419                        nCentreZone=m_Q3Map->m_pLight[nLight].CentreZone ;
6420                       
6421                       
6422                        // is the zone that contains the light centre not visible?
6423                        if(pZoneVis[nCentreZone]!=ZONE_VISIBLE)
6424                        {
6425                                // check the portals on the centre sublight zone. 
6426                                // If the ones that the light touches are closed,
6427                                // then this light can't be visible
6428
6429                               
6430                                nMaxPortal=m_Q3Map->m_nZoneTouchesPortal[nCentreZone][INDEX_PORTALCOUNT] ;
6431                                nOpenPortals=0 ;
6432                                nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
6433
6434                                for(nPortalIndex=0 ; nPortalIndex<nMaxPortal ; nPortalIndex++)
6435                                {
6436                                        nPortal=m_Q3Map->m_nZoneTouchesPortal[nCentreZone][nPortalIndex] ;
6437
6438                                        // if portal's open...
6439                                        if(m_chPortalState[nPortal]&PORTALSTATE_OPEN)
6440                                        {
6441                                                nPortalLightMax=m_Q3Map->m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT] ;
6442                                               
6443                                                // scan all the lights that touch this portal to see if our current light is one of them
6444                                                for(nPortalLightIndex=0 ; nPortalLightIndex<nPortalLightMax ; nPortalLightIndex++)
6445                                                        if(m_Q3Map->m_nPortalTouchesLight[nPortal][nPortalLightIndex]==nLight)
6446                                                        {
6447                                                                nOpenPortals=1 ;
6448                                                                break ;
6449                                                        }
6450
6451                                        }// end if portal is open
6452
6453                                        if(nOpenPortals) break ; // get out if we found an open portal that the light touches
6454                                }// end for portals
6455
6456
6457
6458                                // if none of the portals touched by the centre light were open, set this light and it's sublights to not visible
6459                                if(nOpenPortals==0)
6460                                {
6461                                        pLightVis[nLight]=LIGHT_UNCHECKED ;
6462
6463                                        nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
6464                                        nSubLightMax=nSubLightStart+m_Q3Map->m_pLight[nLight].ZoneCount ; 
6465
6466                                        for(nSubLight=nSubLightStart ; nSubLight<nSubLightMax ; nSubLight++)
6467                                                pSubLightVis[nSubLightStart]=LIGHT_UNCHECKED ;
6468
6469                                }// end if no light centre portals that touched lights were open
6470
6471
6472
6473                        }// end if light centre zone isn't visible
6474
6475                }// end if light is visibile
6476
6477        }// end for lightindex
6478
6479}
6480
6481
6482// for lights that touch multiple zones, work out what additional zones we need to make
6483// visible in order that lighting will come out with correct shadows.
6484void OgreFramework::AddZonesFromMultiZoneLights(char* pZoneVis, char* pLightVis, char* pSubLightVis)
6485{
6486        int nLightMax=m_Q3Map->m_nMaxMultiZoneLight ;
6487        int nLight=0 ;
6488        int nLightIndex=0 ;
6489        float flMinX=0.0f ;
6490        float flMaxX=0.0f ;
6491        float flMinY=0.0f ;
6492        float flMaxY=0.0f ;
6493        float flMinZ=0.0f ;
6494        float flMaxZ=0.0f ;
6495
6496        int nSubLightMax=0 ;
6497//      int nSubLightIndex=0 ;
6498        int nSubLight=0 ;
6499        int nSubLightStart=0 ;
6500        int nSubLightFirst=0 ;
6501
6502        int nInnerLight=0 ;
6503
6504
6505        for(nLightIndex=0 ; nLightIndex<nLightMax ; nLightIndex++)
6506        {
6507                nLight=m_Q3Map->m_nMultiZoneLight[nLightIndex] ;
6508                if(pLightVis[nLight]==LIGHT_VISIBLE)
6509                {
6510                        nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
6511                        nSubLightFirst=nSubLightStart+1 ;// start from the first sublight after the one containing the centre
6512                        nSubLightMax=nSubLightStart+m_Q3Map->m_pLight[nLight].ZoneCount ; 
6513                       
6514
6515                        for(nSubLight=nSubLightStart ; nSubLight<nSubLightMax ; nSubLight++)   
6516                                if(pSubLightVis[nSubLight]==LIGHT_VISIBLE) // sublight is visible (and unchecked)
6517                                {
6518                                        // create the new AABB
6519                                        // this is bounded by this sublight and the centre holding sublight. 
6520                                        flMinX = m_Q3Map->m_SubLight[nSubLight].Min[0] < m_Q3Map->m_SubLight[nSubLightStart].Min[0] ? m_Q3Map->m_SubLight[nSubLight].Min[0] : m_Q3Map->m_SubLight[nSubLightStart].Min[0] ; 
6521                                        flMinY = m_Q3Map->m_SubLight[nSubLight].Min[1] < m_Q3Map->m_SubLight[nSubLightStart].Min[1] ? m_Q3Map->m_SubLight[nSubLight].Min[1] : m_Q3Map->m_SubLight[nSubLightStart].Min[1] ; 
6522                                        flMinZ = m_Q3Map->m_SubLight[nSubLight].Min[2] < m_Q3Map->m_SubLight[nSubLightStart].Min[2] ? m_Q3Map->m_SubLight[nSubLight].Min[2] : m_Q3Map->m_SubLight[nSubLightStart].Min[2] ; 
6523                               
6524                                        flMaxX = m_Q3Map->m_SubLight[nSubLight].Max[0] > m_Q3Map->m_SubLight[nSubLightStart].Max[0] ? m_Q3Map->m_SubLight[nSubLight].Max[0] : m_Q3Map->m_SubLight[nSubLightStart].Max[0] ; 
6525                                        flMaxY = m_Q3Map->m_SubLight[nSubLight].Max[1] > m_Q3Map->m_SubLight[nSubLightStart].Max[1] ? m_Q3Map->m_SubLight[nSubLight].Max[1] : m_Q3Map->m_SubLight[nSubLightStart].Max[1] ; 
6526                                        flMaxZ = m_Q3Map->m_SubLight[nSubLight].Max[2] > m_Q3Map->m_SubLight[nSubLightStart].Max[2] ? m_Q3Map->m_SubLight[nSubLight].Max[2] : m_Q3Map->m_SubLight[nSubLightStart].Max[2] ; 
6527                               
6528                                        for(nInnerLight=nSubLightStart ; nInnerLight<nSubLightMax ; nInnerLight++)
6529                                        {
6530
6531                                               
6532                                                if(
6533                                                                        (nInnerLight!=nSubLight) // no need to test itself
6534                                                                &&(pZoneVis[  m_Q3Map->m_SubLight[nInnerLight].Zone  ] != ZONE_VISIBLE) // don't test if already visible
6535                                                                // if overlap, InnerLight's zone is visible
6536                                                                &&(flMinX<m_Q3Map->m_SubLight[nInnerLight].Max[0]) && (flMaxX>m_Q3Map->m_SubLight[nInnerLight].Min[0])
6537                                                                &&(flMinY<m_Q3Map->m_SubLight[nInnerLight].Max[1]) && (flMaxY>m_Q3Map->m_SubLight[nInnerLight].Min[1])
6538                                                                &&(flMinZ<m_Q3Map->m_SubLight[nInnerLight].Max[2]) && (flMaxZ>m_Q3Map->m_SubLight[nInnerLight].Min[2])
6539                                                        )
6540                                                {
6541                                                        pZoneVis[  m_Q3Map->m_SubLight[nInnerLight].Zone  ]=ZONE_VISIBLE ; // flag this zone as visible
6542                                                        m_nTotalTriangles+=m_nZoneTriangleCount[ m_Q3Map->m_SubLight[nInnerLight].Zone ] ; // just some stats for interest
6543                                                }
6544
6545                                        } // end for innerlight
6546                                       
6547                                }// end if sublight is visible
6548
6549                }// end if light is visible
6550
6551        }// end for nLightIndex
6552
6553}
6554
6555// scan all the unchecked portals in a subzone to see if they are visible,
6556// then move into any visible subzones and recurse.
6557// scalex and scaley will convert the screen space numbers (-1 to 1) into frustum numbers (varies, often -0.5ish to 0.5ish) which is probably due to screen aspect ratios etc
6558
6559// we also add visible lights if they are in the view frustum
6560void OgreFramework::PortalScan(Ogre::Camera *pCamera, int nZone, Ogre::Real ScaleX, Ogre::Real ScaleY, char* pZoneVis, char* pLightVis, char* pSubLightVis, char* pPortalVis, int* pMaxVisibleLight, unsigned short* pVisibleLightList)
6561{
6562        Ogre::Real OrigL, OrigR, OrigT, OrigB ; // original frustum extents
6563        Ogre::Real PortalL, PortalR, PortalT, PortalB ; // frustum extents per each portal in this zone
6564        pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
6565       
6566
6567       
6568
6569        Ogre::AxisAlignedBox AAB ;
6570
6571
6572        int nPortalMax=m_Q3Map->m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT] ;
6573        int nPortalIndex=0 ;
6574        int nPortal=0 ;
6575
6576        int nPortalZoneMax=0 ;
6577        int nPortalZone=0 ;
6578        int nPortalZoneIndex=0 ;
6579
6580
6581        //////////////////////////////////////////////////////////////////////////////////////
6582        //
6583        // LIGHTING CHECKS
6584        //
6585
6586        int nLight=0;
6587        int nLightVal=0 ;
6588//      int nLightIndex=0 ;
6589//      int nMaxLight=0 ;
6590
6591        int nSubLight=0 ;
6592        int nSubLightIndex=0 ;
6593        int nMaxSubLight=0 ;
6594//      int nSubLightVal=0 ;
6595
6596       
6597        // check all lights completely contained in this zone to see if they're visible
6598        nMaxSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ;
6599        for(nSubLightIndex=0 ; nSubLightIndex<nMaxSubLight ; nSubLightIndex++)
6600        {
6601                nSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][nSubLightIndex] ;
6602                //nSubLightVal=m_chSubLightVis[nSubLight] ;
6603
6604                nLight=m_Q3Map->m_SubLight[nSubLight].Light ;
6605                nLightVal=pLightVis[nLight] ;
6606
6607                // if we haven't previously established that the light is visible or out of the frustum, check it.
6608
6609                        AAB.setExtents(m_Q3Map->m_SubLight[nSubLight].Min[0], m_Q3Map->m_SubLight[nSubLight].Min[1], m_Q3Map->m_SubLight[nSubLight].Min[2], m_Q3Map->m_SubLight[nSubLight].Max[0], m_Q3Map->m_SubLight[nSubLight].Max[1], m_Q3Map->m_SubLight[nSubLight].Max[2]) ;
6610                        if(pCamera->isVisible(AAB)) // sublight is visible
6611                        {
6612                                // flag this light and sublight as visible
6613                                if((nLightVal!=LIGHT_VISIBLE) && (*pMaxVisibleLight<MAXVISIBLELIGHT))
6614                                {
6615                                        pVisibleLightList[*pMaxVisibleLight]=nLight ;
6616                                        *pMaxVisibleLight=*pMaxVisibleLight+1 ;
6617                                }
6618                                pSubLightVis[nSubLight] = pLightVis[nLight] = LIGHT_VISIBLE ;
6619                               
6620                        }
6621
6622
6623        }// end for lights in zone
6624       
6625
6626        //
6627        ///////////////////////////////////////////////////////////////////////////////////////
6628
6629
6630
6631
6632
6633        pZoneVis[nZone]=ZONE_VISIBLE ; // flag this zone as visible
6634        m_nTotalTriangles+=m_nZoneTriangleCount[nZone] ; // just some stats for interest
6635
6636
6637        // loop through all the portals in this zone
6638        for(nPortalIndex=0 ; nPortalIndex<nPortalMax ; nPortalIndex++)
6639        {
6640               
6641
6642                nPortal=m_Q3Map->m_nZoneTouchesPortal[nZone][nPortalIndex] ;
6643
6644
6645                if((pPortalVis[nPortal]&PORTAL_VISCHECK)==0) // portal hasn't already been checked
6646                {
6647
6648                        pPortalVis[nPortal] |= PORTAL_VISCHECK ; // flag portal as vischecked
6649                        AAB.setExtents(m_Q3Map->m_pPortals[nPortal].Min[0], m_Q3Map->m_pPortals[nPortal].Min[1], m_Q3Map->m_pPortals[nPortal].Min[2], m_Q3Map->m_pPortals[nPortal].Max[0], m_Q3Map->m_pPortals[nPortal].Max[1], m_Q3Map->m_pPortals[nPortal].Max[2]) ;
6650               
6651                        if(pCamera->isVisible(AAB)) // portal is in the view frustum
6652                        {                       
6653
6654                                pPortalVis[nPortal] |= PORTAL_VISIBLE ; // flag portal as visible
6655
6656                                // if the portal is open, go in and check the new zone.
6657                                if(m_chPortalState[nPortal]&PORTALSTATE_OPEN)
6658                                {
6659                       
6660                                        // calculate the new frustum extents through this portal
6661                                        PortalL=OrigL ;
6662                                        PortalR=OrigR ;
6663                                        PortalT=OrigT ;
6664                                        PortalB=OrigB ;
6665
6666                                        if(CalculatePortalFrustum(pCamera, nPortal, &PortalL, &PortalR, &PortalT, &PortalB, ScaleX, ScaleY))
6667                                        {
6668
6669
6670
6671
6672
6673                                                // Loop through all the zones attached to this portal
6674                                                nPortalZoneMax=m_Q3Map->m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ;
6675                                                for(nPortalZoneIndex=0 ; nPortalZoneIndex<nPortalZoneMax ; nPortalZoneIndex++)
6676                                                {
6677                                                        nPortalZone=m_Q3Map->m_nPortalTouchesZone[nPortal][nPortalZoneIndex] ;
6678                                                        if(pZoneVis[nPortalZone]==ZONE_UNCHECKED) // don't go back into zones we've already scanned.
6679                                                        {
6680
6681                                                                pCamera->setFrustumExtents(PortalL, PortalR, PortalT, PortalB) ; // set the frustum extents
6682
6683                                                                // recurse
6684                                                                //m_nRecurseCount++ ;
6685                                                                PortalScan(pCamera, nPortalZone, ScaleX, ScaleY, pZoneVis, pLightVis, pSubLightVis, pPortalVis, pMaxVisibleLight, pVisibleLightList) ;
6686                                                                //m_nRecurseCount-- ;
6687
6688                                                               
6689                                                               
6690                                                        }// end if zone hasn't already been checked
6691
6692                                                }// end scanning all zones connected by this portal
6693
6694                                        }// end if frustum is still active
6695
6696                                }// end if portal is open
6697                               
6698                        }// end if portal is in the view frustum
6699               
6700                }// end if portal hasn't been checked   
6701
6702                // reset the frustum
6703                pCamera->setFrustumExtents(OrigL, OrigR, OrigT, OrigB) ; // reset the original frustum extents
6704       
6705        }// end for portalindex
6706
6707
6708}
6709
6710// gives new frustum settings, and returns 0 if the frustum has been killed completely.
6711int OgreFramework::CalculatePortalFrustum(Ogre::Camera *pCamera, int nPortal, Ogre::Real* pPortalL, Ogre::Real* pPortalR, Ogre::Real* pPortalT, Ogre::Real* pPortalB, Ogre::Real ScaleX, Ogre::Real ScaleY)
6712{
6713
6714
6715        // if the camera is actually inside the portal then don't change the frustum but return OK
6716        Vector3 CamPos=pCamera->getPosition() ;
6717
6718        if(
6719                                (CamPos.x>=m_Q3Map->m_pPortals[nPortal].Min[0]) && (CamPos.x<=m_Q3Map->m_pPortals[nPortal].Max[0])
6720                        &&(CamPos.y>=m_Q3Map->m_pPortals[nPortal].Min[1]) && (CamPos.y<=m_Q3Map->m_pPortals[nPortal].Max[1])
6721                        &&(CamPos.z>=m_Q3Map->m_pPortals[nPortal].Min[2]) && (CamPos.z<=m_Q3Map->m_pPortals[nPortal].Max[2])
6722                )
6723                return 1 ;
6724
6725
6726
6727
6728
6729        int nLoop=0 ;
6730        int nBehindPoint=0 ; // keep track of how many transformed points are behind the camera
6731        //Real OrigL=*pPortalL ;
6732        //Real OrigR=*pPortalR ;
6733        //Real OrigT=*pPortalT ;
6734        //Real OrigB=*pPortalB ;
6735
6736        Real MinX=MINMAXLIMIT ;
6737        Real MaxX=-MINMAXLIMIT ;
6738        Real MaxY=-MINMAXLIMIT ;
6739        Real MinY=MINMAXLIMIT ;
6740
6741
6742        // set portal corners as 8 individual points.  order is xyz, Xyz, xYz, XYz, xyZ, XyZ, xYZ, XYZ,
6743        Vector3 xyz[8] ;
6744
6745       
6746        xyz[0].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
6747        xyz[0].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
6748        xyz[0].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
6749
6750        xyz[1].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
6751        xyz[1].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
6752        xyz[1].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
6753
6754        xyz[2].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
6755        xyz[2].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
6756        xyz[2].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
6757
6758        xyz[3].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
6759        xyz[3].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
6760        xyz[3].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
6761
6762        xyz[4].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
6763        xyz[4].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
6764        xyz[4].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
6765
6766        xyz[5].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
6767        xyz[5].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
6768        xyz[5].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
6769
6770        xyz[6].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
6771        xyz[6].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
6772        xyz[6].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
6773
6774        xyz[7].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
6775        xyz[7].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
6776        xyz[7].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
6777
6778        // transform the points to eyespace
6779        for(nLoop=0 ; nLoop<8 ; nLoop++)
6780                xyz[nLoop]=m_ViewMatrix*xyz[nLoop] ;//pCamera->getViewMatrix(true)*xyz[nLoop] ;
6781
6782        // transform the points to screen space
6783        for(nLoop=0 ; nLoop<8 ; nLoop++)
6784                if(xyz[nLoop].z<0) // less than zero means point is in front of camera
6785                {
6786                        xyz[nLoop]=m_ProjectionMatrix*xyz[nLoop] ;// pCamera->getProjectionMatrix()*xyz[nLoop] ;
6787                        if(xyz[nLoop].x<MinX) MinX=xyz[nLoop].x ;
6788                        if(xyz[nLoop].x>MaxX) MaxX=xyz[nLoop].x ;
6789                        if(xyz[nLoop].y<MinY) MinY=xyz[nLoop].y ;
6790                        if(xyz[nLoop].y>MaxY) MaxY=xyz[nLoop].y ;
6791
6792                }
6793                else // point is behind the camera
6794                        nBehindPoint++ ;
6795               
6796
6797
6798       
6799        MinX*=ScaleX ;
6800        MaxX*=ScaleX ;
6801        MinY*=ScaleY ;
6802        MaxY*=ScaleY ;
6803       
6804        // apply the stereofrustum tweak if needed
6805        //float flTweak=0.0f ;
6806        //if(m_flStereoFrustumTweak!=0.0f)
6807        //{
6808        //      MinX-=m_flStereoFrustumTweak ;
6809        //      MaxX+=m_flStereoFrustumTweak ;
6810        //}
6811
6812
6813        // if we have more than three behindpoints, don't cull
6814        if(nBehindPoint>3) return 1 ;
6815
6816        // use these to cut down the frustum
6817        if(MinX>*pPortalL) *pPortalL=MinX ;
6818        if(MaxX<*pPortalR) *pPortalR=MaxX ;
6819        if(MinY>*pPortalB) *pPortalB=MinY ;
6820        if(MaxY<*pPortalT) *pPortalT=MaxY ;
6821
6822
6823
6824       
6825
6826       
6827
6828        // check if frustum has been cut out of existence
6829        // culling at this point didn't work, so this is a hack to make if function.
6830        if((*pPortalL>=*pPortalR) || (*pPortalB>=*pPortalT))
6831                return 0 ;
6832
6833
6834        /*
6835        if(*pPortalL>=*pPortalR)
6836        {
6837                *pPortalL=(*pPortalL+*pPortalR)/2.0-0.01 ;
6838                *pPortalR=*pPortalL+0.02 ;
6839        }
6840
6841        if(*pPortalB>=*pPortalT)
6842        {
6843                *pPortalB=(*pPortalB+*pPortalT)/2.0-0.01 ;
6844                *pPortalT=*pPortalB+0.02 ;
6845        }
6846        */
6847
6848               
6849                //return 0 ;
6850
6851
6852        return 1 ;
6853}
6854
6855
6856
6857
6858
6859
6860
6861
6862 /***********************************************************************************************************\
6863                                               
6864                                            LIGHTING SETUP
6865                                               
6866 \***********************************************************************************************************/
6867
6868
6869
6870
6871
6872void OgreFramework::initLight() 
6873{
6874//      char chMessage[1024] ;
6875
6876                // these lights only have placeholder settings to begin with, since they get moved around and reused thoughout the level.
6877       
6878                int nLt=0 ;
6879                int nMaxLt=MAXLIGHTPERLOOP ;
6880                Light *light;
6881                char chLightName[1024] ;
6882
6883
6884               
6885
6886                for(nLt=0 ; nLt<nMaxLt ; nLt++)
6887                {
6888                        sprintf(chLightName, "LT%02i", nLt) ;
6889                       
6890                        light = m_pSceneMgr->createLight(chLightName);
6891                        light->setType(Light::LT_SPOTLIGHT);
6892                        light->setCastShadows(true);
6893                        light->setVisible(false) ;
6894
6895                }
6896       
6897}
6898
6899 /***********************************************************************************************************\
6900                                               
6901                                            CONFIG FILE
6902                                               
6903 \***********************************************************************************************************/
6904
6905void OgreFramework::ParseBZNConfig(void)
6906{
6907        const int KVSIZE=1024 ;
6908        // make sure the config is a string
6909        int nConfigPos=-1 ;
6910//      int nPos=0 ;
6911        int nKeyPos=0 ;
6912        int nValuePos=0 ;
6913
6914        char chKey[KVSIZE] ;
6915        char chValue[KVSIZE] ;
6916        int nValue=0 ;
6917
6918       
6919
6920        while(nConfigPos<BZN_CONFIG_SIZE)
6921        {
6922                // scan forward to find the next key
6923                while   (                       
6924                                                                (++nConfigPos<BZN_CONFIG_SIZE)
6925                                                &&      ((m_chBZNConfig[nConfigPos]<'A') || (m_chBZNConfig[nConfigPos]>'z'))
6926                                        ) ;
6927
6928                if(nConfigPos<BZN_CONFIG_SIZE)
6929                {
6930
6931
6932
6933                        // find the end of the key
6934                        nKeyPos=0 ;
6935                        while   ((m_chBZNConfig[nConfigPos]!=' ') && (m_chBZNConfig[nConfigPos]!='/') && (m_chBZNConfig[nConfigPos]!=0x0A) && (m_chBZNConfig[nConfigPos]!=0x0D))
6936                        {
6937                                chKey[nKeyPos++]=m_chBZNConfig[nConfigPos++] ;
6938                                if((nConfigPos==BZN_CONFIG_SIZE) || (nKeyPos==KVSIZE))
6939                                        break ;
6940                        }
6941
6942                        if((nConfigPos<BZN_CONFIG_SIZE) && (nKeyPos<KVSIZE))
6943                        {
6944                                chKey[nKeyPos]='\0' ; // null terminate the key
6945                       
6946                                // scan off the the number
6947                                nValuePos=0 ;
6948                               
6949
6950                                while   ((m_chBZNConfig[nConfigPos]!=0x0A) && (m_chBZNConfig[nConfigPos]!=0x0D) && (m_chBZNConfig[nConfigPos]!='/'))
6951                                {
6952                                        if(
6953                                                                        ((m_chBZNConfig[nConfigPos]>='0') && (m_chBZNConfig[nConfigPos]<='9'))
6954                                                        ||      (m_chBZNConfig[nConfigPos]=='-') 
6955                                                        ||      (m_chBZNConfig[nConfigPos]=='.')
6956                                                )
6957                                                chValue[nValuePos++]=m_chBZNConfig[nConfigPos] ;
6958
6959                                        nConfigPos++ ;
6960                                        if((nConfigPos==BZN_CONFIG_SIZE) || (nKeyPos==KVSIZE))
6961                                                break ;
6962                                }
6963
6964                                if((nConfigPos<BZN_CONFIG_SIZE) && (nValuePos<KVSIZE))
6965                                {
6966                                        chValue[nValuePos]='\0' ; // null terminate the value
6967                               
6968                                        // convert value string to a float
6969                                        nValue=atoi(chValue) ;
6970
6971                                        // assign that value
6972                                        if(strcmp("r_shadowmapsize", chKey)==0)         { m_nShadowMapSize=nValue ; if(m_nShadowMapSize<2) m_nShadowMapSize=2 ; }
6973                                        if(strcmp("r_shadowrgbsize", chKey)==0)         { m_nShadowRGBSize=nValue ; if(m_nShadowRGBSize<2) m_nShadowRGBSize=2 ; }
6974                                        if(strcmp("r_colouredshadow", chKey)==0)        { m_nColouredShadow=nValue ; }
6975                                        if(strcmp("r_renderhdr", chKey)==0)                             { m_nRenderHDR=nValue ; }
6976                                        if(strcmp("r_maxgpuquery", chKey)==0)                   { m_nMaxGPUQuery=nValue ; if(m_nMaxGPUQuery<0) m_nMaxGPUQuery=0 ; if(m_nMaxGPUQuery>MAXGPUQUERY) m_nMaxGPUQuery=MAXGPUQUERY ; }
6977
6978                                        //sprintf(m_chBug, "Key: %s, Value: %i", chKey, nValue) ;
6979                                        //m_pLog->logMessage(m_chBug);
6980                               
6981                                }// end found end of value
6982
6983
6984
6985
6986
6987
6988
6989                        }// end found end of key
6990
6991
6992
6993
6994
6995                }// end found start of key
6996                                               
6997
6998
6999        }// end scanning whole config
7000
7001
7002}
Note: See TracBrowser for help on using the repository browser.