[Orxonox-commit 2103] r6819 - in code/branches/fps/src/libraries/tools: . fps
landauf at orxonox.net
landauf at orxonox.net
Sun May 2 23:11:32 CEST 2010
Author: landauf
Date: 2010-05-02 23:11:32 +0200 (Sun, 02 May 2010)
New Revision: 6819
Added:
code/branches/fps/src/libraries/tools/fps/
code/branches/fps/src/libraries/tools/fps/DemoApp.cpp
code/branches/fps/src/libraries/tools/fps/DemoApp.hpp
code/branches/fps/src/libraries/tools/fps/JarDebug.cpp
code/branches/fps/src/libraries/tools/fps/JarDebug.h
code/branches/fps/src/libraries/tools/fps/OgreFramework.cpp
code/branches/fps/src/libraries/tools/fps/OgreFramework.hpp
code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.cpp
code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.h
code/branches/fps/src/libraries/tools/fps/Q3Map.cpp
code/branches/fps/src/libraries/tools/fps/Q3Map.h
code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.cpp
code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.h
code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.cpp
code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.h
code/branches/fps/src/libraries/tools/fps/Q3Map_misc.h
code/branches/fps/src/libraries/tools/fps/main.cpp
code/branches/fps/src/libraries/tools/fps/misc.cpp
Log:
copy paste of all BZN bsp renderer files
Added: code/branches/fps/src/libraries/tools/fps/DemoApp.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/DemoApp.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/DemoApp.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,602 @@
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#include "DemoApp.hpp"
+
+#include <OgreLight.h>
+#include <OgreWindowEventUtilities.h>
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+DemoApp::DemoApp()
+{
+
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+DemoApp::~DemoApp()
+{
+ StereoConfig_Write() ; // write out the stereo configuration. Just rough for now, a binary file
+
+
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void DemoApp::startDemo()
+{
+
+
+ m_bShutdown = false;
+
+
+
+
+
+
+
+ new OgreFramework();
+
+
+
+ OgreFramework::getSingletonPtr()->initOgre("Video Start", this, 0);
+
+ BZNConfig_Read() ;
+
+ OgreFramework::getSingletonPtr()->AdditionalSetup() ;
+
+ if(!setupDemoScene()) return ; // failure setting up level
+
+
+
+ //runDemo_Default();
+ runDemo_MethodA();
+
+ OgreFramework::getSingletonPtr()->UnloadMap(true) ;
+ //OgreFramework::getSingletonPtr()->OFBug.MessageInt(333) ;
+ //delete OgreFramework::getSingletonPtr(); // causes a crash on exit in 1.7, was ok in 1.6.3
+ //OgreFramework::getSingletonPtr()->
+
+ OgreFramework::getSingletonPtr()->FinalShutdown() ;
+
+
+ //OgreFramework::getSingletonPtr()->OFBug.MessageInt(333) ;
+
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+int DemoApp::setupDemoScene()
+{
+ return OgreFramework::getSingletonPtr()->LoadMap() ;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+// four different versions of runDemo() depending on method of GPUBuffer flushing.
+
+int DemoApp::runDemo_Default()
+{
+
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop (Default)...");
+
+ char chMessage[1024] ;
+
+ UINT uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMilliseconds();
+ UINT uFrameTotalTime=0 ;
+
+ OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics() ;
+
+
+
+
+
+ while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown())
+ {
+
+
+
+
+ if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+ Ogre::WindowEventUtilities::messagePump() ;
+#endif
+
+
+
+
+ if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
+ {
+
+
+ // get start time of frame
+ uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+
+ // update input and physics
+ OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
+ OgreFramework::getSingletonPtr()->m_pMouse->capture();
+ OgreFramework::getSingletonPtr()->updateOgre(uFrameTotalTime/1000.0f);
+
+
+ // render the frame
+ OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+
+
+
+
+
+ // calculate frame time.
+ uFrameTotalTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds()-uFrameStartTime ;
+
+ }
+ else
+ {
+ Sleep(1000);
+ }
+
+
+ }
+
+
+
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit (Default)");
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
+
+
+ return 1 ;
+}
+
+int DemoApp::runDemo_MethodA()
+{
+
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop (MethodA)...");
+
+ char chMessage[1024] ;
+
+ UINT uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMilliseconds();
+ UINT uFrameTotalTime=0 ;
+
+ OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics() ;
+
+
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ // use a renderQueueListener with 1 to 4 HardwareOcclusionQueries to prevent the CPU from
+ // getting too far ahead of the GPU and causing input lag from keyboard and mouse.
+ // thanks to Sinbad for this suggestion and code outline.
+ // We aren't actually doing Hardware Occlusion Culling, just exploiting the way we can
+ // make it flush the GPU buffer for prior frames.
+ // Messing with the GPU command buffer can be turned off completely by seting m_nMaxGPUQuery to 0
+
+
+ // get the maximum gpu queries to be used.
+ int nMaxGPUQuery=OgreFramework::getSingletonPtr()->m_nMaxGPUQuery ;
+ unsigned int dummy=0 ;
+ int nNewQuery=0 ;
+ int nOldQuery=0 ;
+ rQueueListener* rqListener=NULL ;
+ Ogre::HardwareOcclusionQuery** pHOQ=NULL ;
+
+ int nQueryReady[MAXGPUQUERY] ;
+
+
+ if(nMaxGPUQuery!=0) // if querying is turned on
+ {
+ // make sure it is in range.
+ if(nMaxGPUQuery<1)
+ nMaxGPUQuery=1 ;
+ else
+ if(nMaxGPUQuery>MAXGPUQUERY)
+ nMaxGPUQuery=MAXGPUQUERY ;
+
+
+ rqListener = new rQueueListener ;
+
+ OgreFramework::getSingletonPtr()->m_pSceneMgr->addRenderQueueListener(rqListener) ;
+
+ // create our queries
+ pHOQ=rqListener->Query ;
+ for(nNewQuery=0 ; nNewQuery<nMaxGPUQuery ; nNewQuery++)
+ pHOQ[nNewQuery] = OgreFramework::getSingletonPtr()->m_pRoot->getRenderSystem()->createHardwareOcclusionQuery() ;
+
+ nNewQuery=nOldQuery-1 ;
+ if(nNewQuery<0)
+ nNewQuery+=nMaxGPUQuery ;
+
+ // set the queries to not ready
+ for(int nReadyLoop=0 ; nReadyLoop<MAXGPUQUERY ; nReadyLoop++)
+ nQueryReady[nReadyLoop]=0 ;
+ }
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+ while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown())
+ {
+
+
+
+
+ if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+ Ogre::WindowEventUtilities::messagePump() ;
+#endif
+
+
+ //OgreFramework::getSingletonPtr()->m_pLog->logMessage("Update START");
+
+
+ if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
+ {
+
+ // get start time of frame
+ uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+
+ // update input and physics
+ OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
+ OgreFramework::getSingletonPtr()->m_pMouse->capture();
+ OgreFramework::getSingletonPtr()->updateOgre(uFrameTotalTime/1000.0f);
+
+
+ if(nMaxGPUQuery==0) // querying the GPU command buffer is disabled
+ {
+ // render the frame
+ OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+ }
+ else // querying the GPU command buffer is enabled
+ {
+ // increment the buffer.
+ nNewQuery=nOldQuery ;
+ nOldQuery++ ;
+ if(nOldQuery==nMaxGPUQuery)
+ nOldQuery=0 ;
+
+
+ // define query beginning for this frame
+ pHOQ[ nNewQuery ]->beginOcclusionQuery() ;
+
+ // render the frame
+ //OgreFramework::getSingletonPtr()->m_pRoot->renderOneFrame();
+ OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+
+ // define query end for this frame
+ pHOQ[ nNewQuery ]->endOcclusionQuery() ;
+ nQueryReady[ nNewQuery ]=1 ;
+
+
+
+ // pull query for a prior frame. Flushes GPU command buffer up to the end of a prior frame but no further.
+ if(nQueryReady[ nOldQuery ])
+ {
+ pHOQ[ nOldQuery ]->pullOcclusionQuery(&dummy) ;
+ nQueryReady[ nOldQuery ]=0 ;
+ }
+ }
+
+
+
+ // calculate frame time.
+ uFrameTotalTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds()-uFrameStartTime ;
+
+ }
+ else
+ {
+ Sleep(1000);
+ }
+
+
+ }
+
+ if(nMaxGPUQuery>0) // if necessary, clean up our HOQ queries and renderQueueListener
+ {
+
+ for(nNewQuery=0 ; nNewQuery<nMaxGPUQuery ; nNewQuery++)
+ OgreFramework::getSingletonPtr()->m_pRoot->getRenderSystem()->destroyHardwareOcclusionQuery( pHOQ[nNewQuery] ) ;
+
+ OgreFramework::getSingletonPtr()->m_pSceneMgr->removeRenderQueueListener(rqListener) ;
+ delete rqListener ;
+ }
+
+
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit (MethodA)");
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
+
+
+ return 1 ;
+}
+
+int DemoApp::runDemo_MethodB()
+{
+
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop (MethodB)...");
+
+ char chMessage[1024] ;
+
+ UINT uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMilliseconds();
+ UINT uFrameTotalTime=0 ;
+
+ OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics() ;
+
+
+
+ int numberOfQueuedFrames=1 ;
+ bool GPUBufferSetupDone=false ;
+
+
+ while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown())
+ {
+
+
+
+
+ if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+ Ogre::WindowEventUtilities::messagePump() ;
+#endif
+
+
+ if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
+ {
+
+
+ if(GPUBufferSetupDone==false) // I added it here because I assume I can be very sure there's an active render window by now.
+ {
+ GPUBufferSetupDone=true ;
+ mBufferFlush.start(numberOfQueuedFrames);
+ }
+
+ // get start time of frame
+ uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+
+ // update input and physics
+ OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
+ OgreFramework::getSingletonPtr()->m_pMouse->capture();
+ OgreFramework::getSingletonPtr()->updateOgre(uFrameTotalTime/1000.0f);
+
+
+ // render the frame
+ OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+
+
+
+
+ // calculate frame time.
+ uFrameTotalTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds()-uFrameStartTime ;
+
+ }
+ else
+ {
+ Sleep(1000);
+ }
+
+
+
+ }
+
+
+ mBufferFlush.stop() ;
+
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit (MethodB)");
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
+
+
+ return 1 ;
+}
+
+
+int DemoApp::runDemo_MethodC()
+{
+
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop (MethodC)...");
+
+ char chMessage[1024] ;
+
+ int uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMilliseconds();
+ int uFrameRenderTime=0 ;
+ int uFrameTargetTime=10000 ;
+
+ OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics() ;
+
+
+
+ int uSleepTime=0 ;
+
+ while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown())
+ {
+
+
+
+
+ if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+ Ogre::WindowEventUtilities::messagePump() ;
+#endif
+
+
+
+
+ if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
+ {
+
+
+ // get start time of frame
+ uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+
+ // update input and physics
+ OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
+ OgreFramework::getSingletonPtr()->m_pMouse->capture();
+ OgreFramework::getSingletonPtr()->updateOgre(uFrameTargetTime/1000.0f);
+
+
+ // render the frame
+ OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+
+
+ // calculate frame time.
+ uFrameRenderTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds()-uFrameStartTime ;
+
+
+ uFrameTargetTime-=1000 ;
+ if(uFrameTargetTime<0) uFrameTargetTime=0 ;
+
+ if(uFrameRenderTime>uFrameTargetTime-10000)
+ uFrameTargetTime=uFrameRenderTime+20000 ;
+
+ if(uFrameTargetTime>100000) uFrameTargetTime=100000 ;
+
+
+
+
+
+ uSleepTime=(uFrameTargetTime-uFrameRenderTime)/1000.0f ;
+ if(uSleepTime>0) Sleep(uSleepTime) ;
+
+ sprintf(chMessage, "render %i, target %i, sleep %i", uFrameRenderTime, uFrameTargetTime, uSleepTime) ;
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage(chMessage);
+
+ }
+ else
+ {
+ Sleep(1000);
+ }
+
+
+ }
+
+
+
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit (MethodC)");
+ OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
+
+
+ return 1 ;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
+void DemoApp::ResetSectionTimer()
+{
+ m_uLastTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+}
+
+UINT DemoApp::GetSectionTimer()
+{
+ UINT uThisTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+ UINT uSectionTime=uThisTime-m_uLastTime ;
+ m_uLastTime=uThisTime ;
+ return uSectionTime ;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+
+bool DemoApp::keyPressed(const OIS::KeyEvent &keyEventRef)
+{
+
+ OgreFramework::getSingletonPtr()->keyPressed(keyEventRef);
+
+ if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_F))
+ {
+ //do something
+ }
+
+ return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool DemoApp::keyReleased(const OIS::KeyEvent &keyEventRef)
+{
+ OgreFramework::getSingletonPtr()->keyReleased(keyEventRef);
+
+ return true;
+}
+
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void DemoApp::StereoConfig_Write( void )
+{
+ int fh;
+ if( (fh = _open( "stereoscopic.cfg", _O_RDWR | _O_BINARY | _O_CREAT | _O_TRUNC,
+ _S_IREAD | _S_IWRITE )) != -1 )
+ {
+ write( fh, (void*)&OgreFramework::getSingletonPtr()->m_nGoggleMode, sizeof(int)) ;
+ write( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleZPos, sizeof(float)) ;
+ write( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleXGap, sizeof(float)) ;
+ write( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleXScale, sizeof(float)) ;
+ write( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleYScale, sizeof(float)) ;
+ _close( fh );
+ }
+}
+bool DemoApp::StereoConfig_Read(void)
+{
+ int fh;
+ bool found_file=true ;
+
+ // Open file for input
+ if( (fh = _open( "stereoscopic.cfg", _O_RDONLY | _O_BINARY )) == -1 )
+ {
+ found_file=false ;
+ }
+ else
+ {
+ read( fh, (void*)&OgreFramework::getSingletonPtr()->m_nGoggleMode, sizeof(int)) ;
+ read( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleZPos, sizeof(float)) ;
+ read( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleXGap, sizeof(float)) ;
+ read( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleXScale, sizeof(float)) ;
+ read( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleYScale, sizeof(float)) ;
+ _close( fh );
+ }// end if else
+ return found_file ;
+}
+
+
+void DemoApp::BZNConfig_Write(void)
+{
+ int fh;
+ if( (fh = _open( "bzn.cfg", _O_RDWR | _O_BINARY | _O_CREAT | _O_TRUNC,
+ _S_IREAD | _S_IWRITE )) != -1 )
+ {
+ write( fh, (void*)OgreFramework::getSingletonPtr()->m_chBZNConfig, BZN_CONFIG_SIZE) ;
+ _close( fh );
+ }
+}
+
+bool DemoApp::BZNConfig_Read(void)
+{
+
+ int fh;
+ bool found_file=true ;
+
+ // make sure the config memory is blank
+ ZeroMemory((void*)OgreFramework::getSingletonPtr()->m_chBZNConfig, BZN_CONFIG_SIZE) ;
+
+ // Open file for input
+ if( (fh = _open( "bzn.cfg", _O_RDONLY | _O_BINARY )) == -1 )
+ {
+ found_file=false ;
+ }
+ else
+ {
+ read( fh, (void*)OgreFramework::getSingletonPtr()->m_chBZNConfig, BZN_CONFIG_SIZE) ;
+ _close( fh );
+ OgreFramework::getSingletonPtr()->ParseBZNConfig() ;
+ }// end if else
+
+
+ return found_file ;
+
+}
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/DemoApp.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/DemoApp.hpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/DemoApp.hpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/DemoApp.hpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,57 @@
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#ifndef OGRE_DEMO_HPP
+#define OGRE_DEMO_HPP
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#include "OgreFramework.hpp"
+
+// for loading/saving the stereo config file
+#include <io.h>
+#include <fcntl.h> /* Needed only for _O_RDWR definition */
+#include <sys/stat.h>
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+class DemoApp : public OIS::KeyListener
+{
+public:
+ DemoApp();
+ ~DemoApp();
+
+ void startDemo();
+
+ bool keyPressed(const OIS::KeyEvent &keyEventRef);
+ bool keyReleased(const OIS::KeyEvent &keyEventRef);
+
+private:
+ int setupDemoScene();
+ int runDemo_Default(); // no gpu buffer flushing code
+ int runDemo_MethodA(); // my HOQ gpu buffer flushing code
+ int runDemo_MethodB(); // ogre HOQ gpu buffer flushing code
+ int runDemo_MethodC(); // my blit gpu buffer flushing code
+
+ UINT m_uLastTime ;
+ void ResetSectionTimer() ;
+ UINT GetSectionTimer() ;
+
+
+ void StereoConfig_Write( void ) ;
+ bool StereoConfig_Read(void) ;
+
+ void BZNConfig_Write(void) ;
+ bool BZNConfig_Read(void) ;
+
+
+
+ Ogre::GpuCommandBufferFlush mBufferFlush;
+
+ bool m_bShutdown;
+};
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#endif
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/DemoApp.hpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/JarDebug.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/JarDebug.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/JarDebug.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,1637 @@
+// JarDebug.cpp: implementation of the CJarDebug class.
+//
+//////////////////////////////////////////////////////////////////////
+
+//#include "stdafx.h"
+#include "JarDebug.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+
+#pragma warning( disable : 4996 ) // stop bitching about unsafe string functions
+#pragma warning( disable : 4267 ) // stop bitching about conversion of size_t to int
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CJarDebug::CJarDebug()
+{
+ m_chCR[0]=0x0D ;
+ m_chCR[1]=0x0A ;
+ m_chCR[2]='\0' ;
+ //AfxMessageBox("JarDebug active") ;
+}
+
+CJarDebug::~CJarDebug()
+{
+
+}
+
+//void CJarDebug::StartTiming(void) { m_Time=timeGetTime() ; }
+//int CJarDebug::GetTiming(void) { return timeGetTime()-m_Time ; }
+
+
+void CJarDebug::LogInit(void)
+{
+ m_chLog[0]='\0' ;
+}
+
+void CJarDebug::LogAdd(char LETTERS[])
+{
+ strcat(m_chLog, LETTERS) ;
+}
+
+void CJarDebug::LogAdd(char LETTERS[], bool bCR)
+{
+ strcat(m_chLog, LETTERS) ;
+ if(bCR) strcat(m_chLog, m_chCR) ;
+}
+
+void CJarDebug::LogAddCR(char LETTERS[])
+{
+ strcat(m_chLog, LETTERS) ;
+ strcat(m_chLog, m_chCR) ;
+}
+
+void CJarDebug::LogCR(void)
+{
+ strcat(m_chLog, m_chCR) ;
+}
+
+void CJarDebug::LogSave(char FILENAME[])
+{
+ int fh=0 ;
+ LogCR() ;
+ LogAddCR("END LOG.") ;
+ if( (fh = _open( FILENAME, _O_RDWR | _O_BINARY | _O_CREAT | _O_TRUNC,
+ _S_IREAD | _S_IWRITE )) != -1 )
+ {
+ _write( fh, m_chLog, sizeof(m_chLog )) ;
+ _close( fh );
+ }
+}
+
+
+void CJarDebug::PrintInfo(char LETTERS[], int nXPos, int nYPos)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+ TextOut(hdc, nXPos, nYPos, (LPCWSTR)LETTERS, strlen(LETTERS)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+
+}
+
+void CJarDebug::Pixel(int nPosX, int nPosY, COLORREF clrCol)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+ SetPixelV(hdc, nPosX, nPosY, clrCol) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+void CJarDebug::Pixel(int nPosX, int nPosY, int nCol)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+ int nRed=(nCol&63488)/256 ;
+ int nGreen=(nCol&2016)/8 ;
+ int nBlue=(nCol&31)*8 ;
+ SetPixelV(hdc, nPosX, nPosY, RGB(nRed, nGreen, nBlue)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::BlankArea(int nStartX, int nStartY, int nEndX, int nEndY)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+ RECT rect ;
+
+ rect.left=nStartX ;
+ rect.right=nEndX ;
+ rect.top=nStartY ;
+ rect.bottom=nEndY ;
+
+ FillRect(hdc, &rect, (HBRUSH) ( GetStockObject(BLACK_BRUSH) ));
+}
+
+
+/////////////////////////////////////////////
+//
+// no number
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(char LETTERS[])
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)LETTERS, strlen(LETTERS)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[])
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)LETTERS, strlen(LETTERS)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 1 number
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(char LETTERS[], int Int0)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 2 numbers
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 3 numbers
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, int Int2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, int Int2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, int Int2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, int Int2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, float Float2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, float Float2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, float Float2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, float Float2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 4 numbers
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, int Int2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Int3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, int Int2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Int3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, int Int2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Int3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, int Int2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Int3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, float Float2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Int3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, float Float2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Int3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, float Float2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Int3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, float Float2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Int3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, int Int2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Float3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, int Int2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Float3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, int Int2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Float3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, int Int2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Float3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, float Float2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Float3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, float Float2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Float3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, float Float2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Float3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, float Float2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Float3) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 5 numbers
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, int Int2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Int3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, int Int2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Int3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, int Int2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Int3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, int Int2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Int3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, float Float2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Int3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, float Float2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Int3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, float Float2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Int3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, float Float2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Int3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, int Int2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Float3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, int Int2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Float3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, int Int2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Float3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, int Int2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Float3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, float Float2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Float3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, float Float2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Float3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, float Float2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Float3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, float Float2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Float3, Int4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, int Int2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Int3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, int Int2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Int3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, int Int2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Int3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, int Int2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Int3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, float Float2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Int3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, float Float2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Int3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, float Float2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Int3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, float Float2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Int3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, int Int2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Float3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, int Int2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Float3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, int Int2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Float3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, int Int2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Float3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, int Int1, float Float2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Float3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, int Int1, float Float2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Float3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], int Int0, float Float1, float Float2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Float3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(char LETTERS[], float Float0, float Float1, float Float2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Float3, Float4) ;
+
+ TextOut(hdc, 0, 0, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/////////////////////////////////////////////
+//
+// 1 number
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 2 numbers
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 3 numbers
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 4 numbers
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Int3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Int3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Int3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Int3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Int3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Int3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Int3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, int Int3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Int3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Float3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Float3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Float3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Float3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Float3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Float3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Float3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, float Float3)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Float3) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+/////////////////////////////////////////////
+//
+// 5 numbers
+//
+/////////////////////////////////////////////
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Int3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Int3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Int3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Int3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Int3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Int3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Int3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, int Int3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Int3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Float3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Float3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Float3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Float3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Float3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Float3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Float3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, float Float3, int Int4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Float3, Int4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Int3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Int3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Int3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Int3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Int3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Int3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Int3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, int Int3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Int3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Int2, Float3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Int2, Float3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Int2, Float3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Int2, Float3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Int1, Float2, Float3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Int1, Float2, Float3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Int0, Float1, Float2, Float3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+void CJarDebug::Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, float Float3, float Float4)
+{
+ HDC hdc=GetDC(GetActiveWindow()) ;
+
+ sprintf(m_chMessage, LETTERS, Float0, Float1, Float2, Float3, Float4) ;
+
+ TextOut(hdc, Xpos, Ypos, (LPCWSTR)m_chMessage, strlen(m_chMessage)) ;
+ ReleaseDC(GetActiveWindow(), hdc) ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// 1 int
+void CJarDebug::MessageInt(int NUM0)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%d", NUM0) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 2 int
+void CJarDebug::MessageInt(int NUM0, int NUM1)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%d %d", NUM0, NUM1) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 3 int
+void CJarDebug::MessageInt(int NUM0, int NUM1, int NUM2)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%d %d %d", NUM0, NUM1, NUM2) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 4 int
+void CJarDebug::MessageInt(int NUM0, int NUM1, int NUM2, int NUM3)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%d %d %d %d", NUM0, NUM1, NUM2, NUM3) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 5 int
+void CJarDebug::MessageInt(int NUM0, int NUM1, int NUM2, int NUM3, int NUM4)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%d %d %d %d %d", NUM0, NUM1, NUM2, NUM3, NUM4) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 6 int
+void CJarDebug::MessageInt(int NUM0, int NUM1, int NUM2, int NUM3, int NUM4, int NUM5)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%d %d %d %d %d %d", NUM0, NUM1, NUM2, NUM3, NUM4, NUM5) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 7 int
+void CJarDebug::MessageInt(int NUM0, int NUM1, int NUM2, int NUM3, int NUM4, int NUM5, int NUM6)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%d %d %d %d %d %d %d", NUM0, NUM1, NUM2, NUM3, NUM4, NUM5, NUM6) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 1 float
+void CJarDebug::MessageFloat(float NUM0)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f", NUM0) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 2 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f", NUM0, NUM1) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 3 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f", NUM0, NUM1, NUM2) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 4 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f %f", NUM0, NUM1, NUM2, NUM3) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 5 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f %f %f", NUM0, NUM1, NUM2, NUM3, NUM4) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 6 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f %f %f %f", NUM0, NUM1, NUM2, NUM3, NUM4, NUM5) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+// 7 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f %f %f %f %f", NUM0, NUM1, NUM2, NUM3, NUM4, NUM5, NUM6) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+
+// 8 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6, float NUM7)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f %f %f %f %f %f", NUM0, NUM1, NUM2, NUM3, NUM4, NUM5, NUM6, NUM7) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+
+// 9 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6, float NUM7, float NUM8)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f %f %f %f %f %f %f", NUM0, NUM1, NUM2, NUM3, NUM4, NUM5, NUM6, NUM7, NUM8) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+
+// 10 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6, float NUM7, float NUM8, float NUM9)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f %f %f %f %f %f %f %f", NUM0, NUM1, NUM2, NUM3, NUM4, NUM5, NUM6, NUM7, NUM8, NUM9) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+
+// 11 float
+void CJarDebug::MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6, float NUM7, float NUM8, float NUM9, float NUM10)
+{
+ char chMessage[256] ;
+ sprintf(chMessage, "%f %f %f %f %f %f %f %f %f %f %f", NUM0, NUM1, NUM2, NUM3, NUM4, NUM5, NUM6, NUM7, NUM8, NUM9, NUM10) ;
+ MessageBoxA(GetActiveWindow(),chMessage,"FATAL ERROR",MB_ICONSTOP|MB_OK);
+}
+
+#pragma warning( default : 4996 )
+#pragma warning( default : 4267 )
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/JarDebug.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/JarDebug.h
===================================================================
--- code/branches/fps/src/libraries/tools/fps/JarDebug.h (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/JarDebug.h 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,219 @@
+// JarDebug.h: interface for the CJarDebug class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_JARDEBUG_H__69B857B3_878C_470A_B99E_4AA56D6B9508__INCLUDED_)
+#define AFX_JARDEBUG_H__69B857B3_878C_470A_B99E_4AA56D6B9508__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include <windows.h>
+
+#include <fcntl.h> /* Needed only for _O_RDWR definition */
+#include <io.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+//#include <mmsystem.h> // for the timer functions
+
+#define JLOGSIZE 5120000 // log is 500k
+
+class CJarDebug
+{
+public:
+ CJarDebug();
+ virtual ~CJarDebug();
+
+ //DWORD m_Time ;
+ //void StartTiming(void) ;
+ //int GetTiming(void) ;
+
+ void LogInit() ;
+ void LogAdd(char LETTERS[]) ;
+ void LogAdd(char LETTERS[], bool bCR) ;
+ void LogAddCR(char LETTERS[]) ;
+ void LogCR() ;
+ void LogSave(char FILENAME[]) ;
+
+ void Pixel(int nPosX, int nPosY, COLORREF clrCol) ;
+ void Pixel(int nPosX, int nPosY, int nCol) ;
+ void BlankArea(int nStartX, int nStartY, int nEndX, int nEndY) ;
+
+ void MessageInt(int NUM0) ;
+ void MessageInt(int NUM0, int NUM1) ;
+ void MessageInt(int NUM0, int NUM1, int NUM2) ;
+ void MessageInt(int NUM0, int NUM1, int NUM2, int NUM3) ;
+ void MessageInt(int NUM0, int NUM1, int NUM2, int NUM3, int NUM4) ;
+ void MessageInt(int NUM0, int NUM1, int NUM2, int NUM3, int NUM4, int NUM5) ;
+ void MessageInt(int NUM0, int NUM1, int NUM2, int NUM3, int NUM4, int NUM5, int NUM6) ;
+ void MessageFloat(float NUM0) ;
+ void MessageFloat(float NUM0, float NUM1) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6, float NUM7) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6, float NUM7, float NUM8) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6, float NUM7, float NUM8, float NUM9) ;
+ void MessageFloat(float NUM0, float NUM1, float NUM2, float NUM3, float NUM4, float NUM5, float NUM6, float NUM7, float NUM8, float NUM9, float NUM10) ;
+
+ void PrintInfo(char LETTERS[], int nXPos, int nYPos) ;
+
+ char m_chMessage[1024] ;
+
+ void Info(char LETTERS[]) ;
+ void Info(int Xpos, int Ypos, char LETTERS[]) ;
+
+ void Info(char LETTERS[], int Int0) ;
+ void Info(char LETTERS[], float Float0) ;
+
+ void Info(char LETTERS[], int Int0, int Int1) ;
+ void Info(char LETTERS[], float Float0, int Int1) ;
+ void Info(char LETTERS[], int Int0, float Float1) ;
+ void Info(char LETTERS[], float Float0, float Float1) ;
+
+ void Info(char LETTERS[], int Int0, int Int1, int Int2) ;
+ void Info(char LETTERS[], float Float0, int Int1, int Int2) ;
+ void Info(char LETTERS[], int Int0, float Float1, int Int2) ;
+ void Info(char LETTERS[], float Float0, float Float1, int Int2) ;
+ void Info(char LETTERS[], int Int0, int Int1, float Float2) ;
+ void Info(char LETTERS[], float Float0, int Int1, float Float2) ;
+ void Info(char LETTERS[], int Int0, float Float1, float Float2) ;
+ void Info(char LETTERS[], float Float0, float Float1, float Float2) ;
+
+ void Info(char LETTERS[], int Int0, int Int1, int Int2, int Int3) ;
+ void Info(char LETTERS[], float Float0, int Int1, int Int2, int Int3) ;
+ void Info(char LETTERS[], int Int0, float Float1, int Int2, int Int3) ;
+ void Info(char LETTERS[], float Float0, float Float1, int Int2, int Int3) ;
+ void Info(char LETTERS[], int Int0, int Int1, float Float2, int Int3) ;
+ void Info(char LETTERS[], float Float0, int Int1, float Float2, int Int3) ;
+ void Info(char LETTERS[], int Int0, float Float1, float Float2, int Int3) ;
+ void Info(char LETTERS[], float Float0, float Float1, float Float2, int Int3) ;
+ void Info(char LETTERS[], int Int0, int Int1, int Int2, float Float3) ;
+ void Info(char LETTERS[], float Float0, int Int1, int Int2, float Float3) ;
+ void Info(char LETTERS[], int Int0, float Float1, int Int2, float Float3) ;
+ void Info(char LETTERS[], float Float0, float Float1, int Int2, float Float3) ;
+ void Info(char LETTERS[], int Int0, int Int1, float Float2, float Float3) ;
+ void Info(char LETTERS[], float Float0, int Int1, float Float2, float Float3) ;
+ void Info(char LETTERS[], int Int0, float Float1, float Float2, float Float3) ;
+ void Info(char LETTERS[], float Float0, float Float1, float Float2, float Float3) ;
+
+ void Info(char LETTERS[], int Int0, int Int1, int Int2, int Int3, int Int4) ;
+ void Info(char LETTERS[], float Float0, int Int1, int Int2, int Int3, int Int4) ;
+ void Info(char LETTERS[], int Int0, float Float1, int Int2, int Int3, int Int4) ;
+ void Info(char LETTERS[], float Float0, float Float1, int Int2, int Int3, int Int4) ;
+ void Info(char LETTERS[], int Int0, int Int1, float Float2, int Int3, int Int4) ;
+ void Info(char LETTERS[], float Float0, int Int1, float Float2, int Int3, int Int4) ;
+ void Info(char LETTERS[], int Int0, float Float1, float Float2, int Int3, int Int4) ;
+ void Info(char LETTERS[], float Float0, float Float1, float Float2, int Int3, int Int4) ;
+ void Info(char LETTERS[], int Int0, int Int1, int Int2, float Float3, int Int4) ;
+ void Info(char LETTERS[], float Float0, int Int1, int Int2, float Float3, int Int4) ;
+ void Info(char LETTERS[], int Int0, float Float1, int Int2, float Float3, int Int4) ;
+ void Info(char LETTERS[], float Float0, float Float1, int Int2, float Float3, int Int4) ;
+ void Info(char LETTERS[], int Int0, int Int1, float Float2, float Float3, int Int4) ;
+ void Info(char LETTERS[], float Float0, int Int1, float Float2, float Float3, int Int4) ;
+ void Info(char LETTERS[], int Int0, float Float1, float Float2, float Float3, int Int4) ;
+ void Info(char LETTERS[], float Float0, float Float1, float Float2, float Float3, int Int4) ;
+ void Info(char LETTERS[], int Int0, int Int1, int Int2, int Int3, float Float4) ;
+ void Info(char LETTERS[], float Float0, int Int1, int Int2, int Int3, float Float4) ;
+ void Info(char LETTERS[], int Int0, float Float1, int Int2, int Int3, float Float4) ;
+ void Info(char LETTERS[], float Float0, float Float1, int Int2, int Int3, float Float4) ;
+ void Info(char LETTERS[], int Int0, int Int1, float Float2, int Int3, float Float4) ;
+ void Info(char LETTERS[], float Float0, int Int1, float Float2, int Int3, float Float4) ;
+ void Info(char LETTERS[], int Int0, float Float1, float Float2, int Int3, float Float4) ;
+ void Info(char LETTERS[], float Float0, float Float1, float Float2, int Int3, float Float4) ;
+ void Info(char LETTERS[], int Int0, int Int1, int Int2, float Float3, float Float4) ;
+ void Info(char LETTERS[], float Float0, int Int1, int Int2, float Float3, float Float4) ;
+ void Info(char LETTERS[], int Int0, float Float1, int Int2, float Float3, float Float4) ;
+ void Info(char LETTERS[], float Float0, float Float1, int Int2, float Float3, float Float4) ;
+ void Info(char LETTERS[], int Int0, int Int1, float Float2, float Float3, float Float4) ;
+ void Info(char LETTERS[], float Float0, int Int1, float Float2, float Float3, float Float4) ;
+ void Info(char LETTERS[], int Int0, float Float1, float Float2, float Float3, float Float4) ;
+ void Info(char LETTERS[], float Float0, float Float1, float Float2, float Float3, float Float4) ;
+
+
+
+
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0) ;
+
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1) ;
+
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2) ;
+
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, int Int3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, int Int3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, int Int3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, int Int3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, int Int3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, int Int3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, int Int3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, int Int3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, float Float3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, float Float3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, float Float3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, float Float3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, float Float3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, float Float3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, float Float3) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, float Float3) ;
+
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, int Int3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, int Int3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, int Int3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, int Int3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, int Int3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, int Int3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, int Int3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, int Int3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, float Float3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, float Float3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, float Float3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, float Float3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, float Float3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, float Float3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, float Float3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, float Float3, int Int4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, int Int3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, int Int3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, int Int3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, int Int3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, int Int3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, int Int3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, int Int3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, int Int3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, int Int2, float Float3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, int Int2, float Float3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, int Int2, float Float3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, int Int2, float Float3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, int Int1, float Float2, float Float3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, int Int1, float Float2, float Float3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], int Int0, float Float1, float Float2, float Float3, float Float4) ;
+ void Info(int Xpos, int Ypos, char LETTERS[], float Float0, float Float1, float Float2, float Float3, float Float4) ;
+
+
+
+
+
+
+private:
+ char m_chLog[JLOGSIZE] ;
+ char m_chCR[3] ;
+};
+
+#endif // !defined(AFX_JARDEBUG_H__69B857B3_878C_470A_B99E_4AA56D6B9508__INCLUDED_)
Property changes on: code/branches/fps/src/libraries/tools/fps/JarDebug.h
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/OgreFramework.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/OgreFramework.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/OgreFramework.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,7002 @@
+//|||||||||||||||||||||||||||||||||||||||||||||||
+/*
+===========================================================================
+Copyright (C) 2010 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "OgreFramework.hpp"
+
+#include <io.h>
+#include <fcntl.h> /* Needed only for _O_RDWR definition */
+#include <sys/stat.h>
+#include "Q3Map_misc.h" // safe pointer deletes
+
+
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+using namespace Ogre;
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+template<> OgreFramework* Ogre::Singleton<class OgreFramework>::ms_Singleton = 0;
+
+
+
+OgreFramework::OgreFramework()
+{
+
+ m_nNewCount=0 ;
+ ZeroMemory((void*)m_nNewCheck, sizeof(m_nNewCheck)) ;
+
+ m_MoveSpeed = 0.1;
+ m_RotateSpeed = 0.3;
+
+ m_bShutDownOgre = false;
+ m_iNumScreenShots = 0;
+
+ m_pRoot = 0;
+ m_pSceneMgr = 0;
+ m_pRenderWnd = 0;
+ m_pCamera = 0;
+ m_pViewport = 0;
+ m_pLog = 0;
+ m_pTimer = 0;
+
+ m_pInputMgr = 0;
+ m_pKeyboard = 0;
+ m_pMouse = 0;
+
+ m_pDebugOverlay = 0;
+ m_pInfoOverlay = 0;
+
+ //mRawFileManager=NULL ; // pointer for text file resource handler
+ m_pRawBspFile=NULL ;
+ m_bRawBspFileIsLoaded=false ;
+
+ // pointers for q3map stuff
+ m_TempMem=NULL ;
+ m_Q3Map=NULL ;
+
+
+ m_pZoneMO=NULL ;
+ m_pZoneMesh=NULL ;
+ m_pZoneEntity=NULL ;
+ m_pZoneEntityMaterialType=NULL ;
+
+ int nPTex=0 ;
+ for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+ {
+ m_pZoneEntityMaterial_Base[nPTex]=NULL ;
+ m_pZoneEntityMaterial_Fast[nPTex]=NULL ;
+ }
+
+ m_pZoneEntityMaterial_Black=NULL ;
+
+ m_pZoneEntityMaterial_DfShColour=NULL ;
+ m_pZoneEntityMaterial_Shadow=NULL ;
+ m_pZoneEntityMaterial_ShadeFront=NULL ;
+ m_pZoneEntityMaterial_ShadeBack=NULL ;
+ m_pZoneEntityMaterial_DfShPosition=NULL ;
+ m_pZoneEntityMaterial_DfShDiffuse=NULL ;
+ //m_pZoneEntityMaterial_DSNormal=NULL ;
+ m_pZoneEntityMaterial_DfShFuncTNB=NULL ;
+ m_pZoneEntityMaterial_DfShSpecular=NULL ;
+ m_pZoneEntityMaterial_DfShEmissive=NULL ;
+ //m_pZoneEntityMaterial_DfShData=NULL ;
+ m_pZoneEntityMaterial_DfShMix=NULL ;
+
+
+ /////////////////////////////////
+
+ m_nMaxEntity=0 ;
+ m_pEntityInfo=NULL ;
+ m_nMaxVisibleEntity=NULL ;
+ m_pVisibleEntity=NULL ;
+ m_nMaxFrustumEntity=NULL ;
+ m_pFrustumEntity=NULL ;
+
+
+ // debug light meshes
+ m_pLightMO=NULL ;
+ m_pPortalMO=NULL ;
+ m_pPortalNode=NULL ;
+
+ m_pCubeNode = 0;
+ m_pCubeEntity = 0;
+
+ nMap=2 ;
+ m_nLoadToggle=0 ;
+ m_nJumpToggle=0 ;
+ m_nJumpVal=-1 ;
+
+
+
+
+
+ m_nDebugA=0 ;
+ m_nDebugB=0 ;
+ m_nDebugC=0 ;
+ m_nRecurseCount=0 ;
+
+
+ m_nDebugLightBox=0 ;
+ m_nZoneCullingActive=1 ;
+
+ m_nPortalDebug=0 ;
+ m_nPortalToggle=0 ;
+ m_nPortalState=1 ;
+
+ m_nKeyDown_Shift=0 ;
+ m_nKeyDown_Ctrl=0 ;
+
+
+
+ m_flStereoFrustumTweak=0.0f ;
+
+ m_nGoggleMode=GOGGLE_MODE_OFF ;
+ m_pGoggleL=NULL ;
+ m_pGoggleR=NULL ;
+ m_pNodeGoggles=NULL ;
+
+ // default goggle settings
+ m_flGoggleZPos=-250 ;
+ m_flGoggleXGap=0.0 ;
+ m_flGoggleXScale=1.0 ;
+ m_flGoggleYScale=1.0 ;
+
+ m_nMapLoaded=0 ;
+
+ m_nTime=0 ;
+
+
+
+ ZeroMemory((void*)m_nFrameTime, sizeof(m_nFrameTime)) ;
+ m_nFrame=0 ;
+ m_nGotInput=0 ;
+
+ ZeroMemory((void*)m_nKeyToggle, sizeof(m_nKeyToggle)) ;
+
+ OFBug.LogInit() ;
+
+ m_nRTTAssetsExist=0 ;
+
+ m_nToggle=0 ;
+
+ m_nFlashLight=0 ;
+
+
+
+ m_flAspectRatio=1.0f ;
+ m_flFOV=60.0f ;
+
+ // whether we are drawing the render or one of the info screens, such as wireframe or one of the deferred screens
+ m_nDisplayInfoMode=0 ;
+
+ m_nSpeedRender=0 ;
+
+ //m_nRenderHDR=0 ;
+
+ srand( (unsigned)time( NULL ) );
+
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+OgreFramework::~OgreFramework()
+{
+ OFBug.LogSave("OFBug.txt") ;
+
+ /*
+ char chMessage[1024] ;
+ int nFrame=0 ;
+ m_pLog->logMessage(" ");
+ m_pLog->logMessage(" Mircosecs: Physics Render Ideal Average Pragma Total");
+ m_pLog->logMessage(" ----------------------------------------");
+ for(nFrame=0 ; nFrame<MAXFRAME ; nFrame++)
+ {
+ //sprintf(chMessage, " Frame %3i: %8i %8i %8i", nFrame, m_nFrameTime[nFrame][0], m_nFrameTime[nFrame][1], m_nFrameTime[nFrame][2]) ;
+ 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]) ;
+ m_pLog->logMessage(chMessage);
+ }
+ m_pLog->logMessage("");
+ */
+
+ //UnloadMap(true) ;
+
+
+ //mRawFileManager->~RawFileManager() ; //!! is this correct?
+ //DELETE_POINTER( mRawFileManager ) ;
+
+
+ DELETE_POINTER( m_pKeyboard );
+ DELETE_POINTER( m_pMouse );
+ OIS::InputManager::destroyInputSystem(m_pInputMgr);
+
+
+ //DELETE_POINTER( m_pRoot );
+ //delete m_pRoot ;
+}
+
+
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::initOgre(Ogre::String wndTitle, OIS::KeyListener *pKeyListener, OIS::MouseListener *pMouseListener)
+{
+ Ogre::LogManager* logMgr = new Ogre::LogManager();
+
+ m_pLog = Ogre::LogManager::getSingleton().createLog("OgreLogfile.log", true, true, false);
+ m_pLog->setDebugOutputEnabled(true);
+
+ m_pRoot = new Ogre::Root();
+
+ // our manager for the raw bsp
+ //mRawFileManager = new RawFileManager();
+ //ResourceGroupManager::getSingleton().createResourceGroup("Raw Bsp") ;
+
+
+
+
+ m_pRoot->showConfigDialog();
+
+ if (!m_pRoot->restoreConfig() && !m_pRoot->showConfigDialog())
+ {
+ throw Exception(52, "User canceled the config dialog!", "Application::setupRenderSystem()");
+ }
+
+
+ m_pRenderWnd = m_pRoot->initialise(true, wndTitle);
+
+ m_pSceneMgr = m_pRoot->createSceneManager(ST_GENERIC, "SceneManager");
+ m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.0, 0.0, 0.0));
+
+
+ m_pCamera = m_pSceneMgr->createCamera("Camera");
+ m_pCamera->setPosition(Vector3(0, 0, 0));
+ m_pCamera->lookAt(Vector3(0,0,0));
+ m_pCamera->setNearClipDistance(NEARCLIP);
+ m_pCamera->setFarClipDistance(FARCLIP);
+ m_pCamera->setFOVy( Degree(m_flFOV) ) ;
+
+ m_pCameraCopy = m_pSceneMgr->createCamera("CameraCopy");
+ m_pCameraCopy->setNearClipDistance(NEARCLIP);
+ m_pCameraCopy->setFarClipDistance(FARCLIP);
+
+
+
+ m_pCameraNoJitter = m_pSceneMgr->createCamera("CameraNoJitter");
+
+
+
+
+
+ m_pViewport = m_pRenderWnd->addViewport(m_pCamera);
+
+ m_pViewport->setBackgroundColour(ColourValue(0.5, 0.5, 0.5, 1.0));
+
+ m_flAspectRatio= (float)m_pViewport->getActualWidth() / (float)m_pViewport->getActualHeight() ;
+
+ m_flGoggleAspectRatio=m_flAspectRatio ; // we use this to set up the Goggles
+ m_pCamera->setAspectRatio( Real(m_flAspectRatio) );
+ m_pCameraCopy->setAspectRatio( Real(m_flAspectRatio) );
+
+ m_pViewport->setCamera(m_pCamera);
+ m_pViewport->setClearEveryFrame(true);//, FBT_DEPTH) ;
+
+
+
+
+ unsigned long hWnd = 0;
+ OIS::ParamList paramList;
+ m_pRenderWnd->getCustomAttribute("WINDOW", &hWnd);
+
+ paramList.insert(OIS::ParamList::value_type("WINDOW", Ogre::StringConverter::toString(hWnd)));
+
+ m_pInputMgr = OIS::InputManager::createInputSystem(paramList);
+
+ m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputMgr->createInputObject(OIS::OISKeyboard, true));
+ m_pMouse = static_cast<OIS::Mouse*>(m_pInputMgr->createInputObject(OIS::OISMouse, true));
+
+
+ m_pMouse->getMouseState().height = m_pRenderWnd->getHeight();
+ m_pMouse->getMouseState().width = m_pRenderWnd->getWidth();
+
+ if(pKeyListener == 0)
+ m_pKeyboard->setEventCallback(this);
+ else
+ m_pKeyboard->setEventCallback(pKeyListener);
+
+ if(pMouseListener == 0)
+ m_pMouse->setEventCallback(this);
+ else
+ m_pMouse->setEventCallback(pMouseListener);
+
+ SetupResourceLocations() ;
+
+ // D3D or OGL
+ if (Root::getSingleton().getRenderSystem()->getName().find("GL") != String::npos)
+ m_IsOpenGL = true;
+ else
+ m_IsOpenGL = false;
+
+
+
+
+
+ m_pTimer = new Ogre::Timer();
+ m_pTimer->reset();
+
+
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+
+
+
+
+
+
+ m_nRTTWidth = m_pRenderWnd->getWidth() ;
+ m_nRTTHeight = m_pRenderWnd->getHeight() ;
+
+
+ m_pRenderWnd->addListener(this);
+ m_pRenderWnd->setActive(true);
+
+
+ // default values, may be changed from the bzn.cfg file
+ m_nShadowMapSize=512 ;
+ m_nShadowRGBSize=512 ;
+ m_nColouredShadow=1 ;
+ m_nRenderHDR=1 ;
+ m_nMaxGPUQuery=1 ;
+
+}
+
+void OgreFramework::FinalShutdown(void)
+{
+
+ //Ogre::ResourceGroupManager::getSingleton().shutdownAll();
+ //m_pRoot->destroySceneManager(m_pSceneMgr);
+ //m_pRoot->shutdown() ;
+ delete m_pRoot ;
+}
+
+void OgreFramework::AdditionalSetup()
+{
+
+ CreateRTTAssets() ;
+}
+
+
+void OgreFramework::SetupResourceLocations()
+{
+ Ogre::String secName, typeName, archName;
+ Ogre::ConfigFile cf;
+ cf.load("resources.cfg");
+
+ Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
+ while (seci.hasMoreElements())
+ {
+ secName = seci.peekNextKey();
+ Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
+ Ogre::ConfigFile::SettingsMultiMap::iterator i;
+ for (i = settings->begin(); i != settings->end(); ++i)
+ {
+ typeName = i->first;
+ archName = i->second;
+ Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
+ }
+ }
+ Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
+}
+
+
+// create the textures, materials and miniscreens needed for the RTTs
+void OgreFramework::CreateRTTAssets()
+{
+
+
+ // I originally had problems with OpenGL 2.1.1 suddenly running very slow if I had more than 12 RTT surfaces
+ // but that issue seems to have vanished, perhaps because all my surfaces are now FLOAT16_RGB or FLOAT16_RGBA.
+ // It doesn't like FLOAT32 surfaces, and it also didn't seem to like mixing R8G8B8 with FLOAT16, at least
+ // those configurations seem to have been problems in the past, so I try to keep everything FLOAT16_RGB where possible.
+
+ // I go through quite a few RTT surfaces, and I don't use MRT since I couldn't get it working.
+
+ MaterialManager::getSingleton().initialise() ;
+
+ // need our own resource group so that the RTTs dont get destroyed when we load a new level.
+ Ogre::ResourceGroupManager::getSingleton().createResourceGroup("RTTResources") ;
+
+ Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+
+ int RTTWidth = m_nRTTWidth ;//m_pRenderWnd->getWidth() ;
+ int RTTHeight = m_nRTTHeight ; //m_pRenderWnd->getHeight() ;
+
+ int DSWidth = m_nRTTWidth ;
+ int DSHeight = m_nRTTHeight ;
+
+ int DSWidthB = m_nSpeedRender ? m_nRTTWidth/2 : m_nRTTWidth ;
+ int DSHeightB = m_nSpeedRender ? m_nRTTHeight/2 : m_nRTTHeight ;
+
+ int TEMPWidth = m_nRTTWidth ;
+ int TEMPHeight = m_nRTTHeight ;
+
+
+ Ogre::ColourValue ClearColour=Ogre::ColourValue(0,0,0,1) ; // clears alpha as well. for RGBA textures
+ //!! for now use alpha 1, since Ogre seems to force it to 1 anyway on shadow render.
+
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Shadow
+
+ RTT_Texture_Shadow = Ogre::TextureManager::getSingleton().createManual("RttTex_Shadow",
+ "RTTResources", TEX_TYPE_2D, m_nShadowMapSize, m_nShadowMapSize, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+
+ renderTexture_Shadow = RTT_Texture_Shadow->getBuffer()->getRenderTarget();
+ renderTexture_Shadow->addViewport(m_pCamera);
+ renderTexture_Shadow->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_Shadow->getViewport(0)->setBackgroundColour(ColourValue::White);
+ renderTexture_Shadow->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_Shadow = MaterialManager::getSingleton().create("RttMat_Shadow", "RTTResources");
+ RTT_Technique_Shadow = RTT_Mat_Shadow->createTechnique();
+ RTT_Technique_Shadow->createPass();
+ TextureUnitState* tState_Shadow = RTT_Mat_Shadow->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_Shadow");
+ tState_Shadow->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_Shadow->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_Shadow->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+ miniScreen_Shadow = new Ogre::Rectangle2D(true);
+ miniScreen_Shadow->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_Shadow->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_Shadow = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_Shadow");
+ miniScreenNode_Shadow->attachObject(miniScreen_Shadow);
+ miniScreen_Shadow->setMaterial("RttMat_Shadow");
+
+
+ if(m_nColouredShadow)
+ {
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // ShadeFront
+
+ RTT_Texture_ShadeFront = Ogre::TextureManager::getSingleton().createManual("RttTex_ShadeFront",
+ "RTTResources", TEX_TYPE_2D, m_nShadowRGBSize, m_nShadowRGBSize, 0, PF_FLOAT16_RGBA,
+ TU_RENDERTARGET);
+
+
+ renderTexture_ShadeFront = RTT_Texture_ShadeFront->getBuffer()->getRenderTarget();
+ renderTexture_ShadeFront->addViewport(m_pCamera);
+ renderTexture_ShadeFront->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH);
+ renderTexture_ShadeFront->getViewport(0)->setBackgroundColour(ColourValue::White);
+ renderTexture_ShadeFront->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_ShadeFront = MaterialManager::getSingleton().create("RttMat_ShadeFront", "RTTResources");
+ RTT_Technique_ShadeFront = RTT_Mat_ShadeFront->createTechnique();
+ RTT_Technique_ShadeFront->createPass();
+ TextureUnitState* tState_ShadeFront = RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_ShadeFront");
+ tState_ShadeFront->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+ miniScreen_ShadeFront = new Ogre::Rectangle2D(true);
+ miniScreen_ShadeFront->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_ShadeFront->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_ShadeFront = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_ShadeFront");
+ miniScreenNode_ShadeFront->attachObject(miniScreen_ShadeFront);
+ miniScreen_ShadeFront->setMaterial("RttMat_ShadeFront");
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // ShadeBack
+
+ RTT_Texture_ShadeBack = Ogre::TextureManager::getSingleton().createManual("RttTex_ShadeBack",
+ "RTTResources", TEX_TYPE_2D, m_nShadowRGBSize, m_nShadowRGBSize, 0, PF_FLOAT16_RGBA,
+ TU_RENDERTARGET);
+
+
+ renderTexture_ShadeBack = RTT_Texture_ShadeBack->getBuffer()->getRenderTarget();
+ renderTexture_ShadeBack->addViewport(m_pCamera);
+ renderTexture_ShadeBack->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH);
+ renderTexture_ShadeBack->getViewport(0)->setBackgroundColour(ColourValue::White);
+ renderTexture_ShadeBack->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_ShadeBack = MaterialManager::getSingleton().create("RttMat_ShadeBack", "RTTResources");
+ RTT_Technique_ShadeBack = RTT_Mat_ShadeBack->createTechnique();
+ RTT_Technique_ShadeBack->createPass();
+ TextureUnitState* tState_ShadeBack = RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_ShadeBack");
+ tState_ShadeBack->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+ miniScreen_ShadeBack = new Ogre::Rectangle2D(true);
+ miniScreen_ShadeBack->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_ShadeBack->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_ShadeBack = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_ShadeBack");
+ miniScreenNode_ShadeBack->attachObject(miniScreen_ShadeBack);
+ miniScreen_ShadeBack->setMaterial("RttMat_ShadeBack");
+
+ } // end if coloured shadows
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShPosition
+
+ RTT_Texture_DfShPosition = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShPosition",
+ "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+
+ renderTexture_DfShPosition = RTT_Texture_DfShPosition->getBuffer()->getRenderTarget();
+ renderTexture_DfShPosition->addViewport(m_pCamera);
+ renderTexture_DfShPosition->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_DfShPosition->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShPosition->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShPosition = MaterialManager::getSingleton().create("RttMat_DfShPosition", "RTTResources");
+ RTT_Technique_DfShPosition = RTT_Mat_DfShPosition->createTechnique();
+ RTT_Technique_DfShPosition->createPass();
+ TextureUnitState* tState_DfShPosition = RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShPosition");
+ tState_DfShPosition->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+
+ //renderTexture_DfShPosition->addListener(this);
+
+ miniScreen_DfShPosition = new Ogre::Rectangle2D(true);
+ miniScreen_DfShPosition->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShPosition->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShPosition = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShPosition");
+ miniScreenNode_DfShPosition->attachObject(miniScreen_DfShPosition);
+ miniScreen_DfShPosition->setMaterial("RttMat_DfShPosition");
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShDiffuse
+
+ RTT_Texture_DfShDiffuse = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShDiffuse",
+ "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+
+ renderTexture_DfShDiffuse = RTT_Texture_DfShDiffuse->getBuffer()->getRenderTarget();
+ renderTexture_DfShDiffuse->addViewport(m_pCamera);
+ renderTexture_DfShDiffuse->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_DfShDiffuse->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShDiffuse->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShDiffuse = MaterialManager::getSingleton().create("RttMat_DfShDiffuse", "RTTResources");
+ RTT_Technique_DfShDiffuse = RTT_Mat_DfShDiffuse->createTechnique();
+ RTT_Technique_DfShDiffuse->createPass();
+ TextureUnitState* tState_DfShDiffuse = RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShDiffuse");
+ tState_DfShDiffuse->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+
+ //renderTexture_DfShDiffuse->addListener(this);
+
+ miniScreen_DfShDiffuse = new Ogre::Rectangle2D(true);
+ miniScreen_DfShDiffuse->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShDiffuse->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShDiffuse = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShDiffuse");
+ miniScreenNode_DfShDiffuse->attachObject(miniScreen_DfShDiffuse);
+ miniScreen_DfShDiffuse->setMaterial("RttMat_DfShDiffuse");
+
+ /*
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DSNormal
+
+ RTT_Texture_DSNormal = Ogre::TextureManager::getSingleton().createManual("RttTex_DSNormal",
+ "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+
+ renderTexture_DSNormal = RTT_Texture_DSNormal->getBuffer()->getRenderTarget();
+ renderTexture_DSNormal->addViewport(m_pCamera);
+ renderTexture_DSNormal->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_DSNormal->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DSNormal->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DSNormal = MaterialManager::getSingleton().create("RttMat_DSNormal", "RTTResources");
+ RTT_Technique_DSNormal = RTT_Mat_DSNormal->createTechnique();
+ RTT_Technique_DSNormal->createPass();
+ TextureUnitState* tState_DSNormal = RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DSNormal");
+ tState_DSNormal->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+
+
+ //renderTexture_DSNormal->addListener(this);
+
+ miniScreen_DSNormal = new Ogre::Rectangle2D(true);
+ miniScreen_DSNormal->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DSNormal->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DSNormal = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DSNormal");
+ miniScreenNode_DSNormal->attachObject(miniScreen_DSNormal);
+ miniScreen_DSNormal->setMaterial("RttMat_DSNormal");
+
+ */
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShFuncTNB
+
+ RTT_Texture_DfShFuncTNB = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShFuncTNB",
+ "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+
+ renderTexture_DfShFuncTNB = RTT_Texture_DfShFuncTNB->getBuffer()->getRenderTarget();
+ renderTexture_DfShFuncTNB->addViewport(m_pCamera);
+ renderTexture_DfShFuncTNB->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_DfShFuncTNB->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShFuncTNB->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShFuncTNB = MaterialManager::getSingleton().create("RttMat_DfShFuncTNB", "RTTResources");
+ RTT_Technique_DfShFuncTNB = RTT_Mat_DfShFuncTNB->createTechnique();
+ RTT_Technique_DfShFuncTNB->createPass();
+ TextureUnitState* tState_DfShFuncTNB = RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShFuncTNB");
+ tState_DfShFuncTNB->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+ //renderTexture_DfShFuncTNB->addListener(this);
+
+ miniScreen_DfShFuncTNB = new Ogre::Rectangle2D(true);
+ miniScreen_DfShFuncTNB->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShFuncTNB->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShFuncTNB = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShFuncTNB");
+ miniScreenNode_DfShFuncTNB->attachObject(miniScreen_DfShFuncTNB);
+ miniScreen_DfShFuncTNB->setMaterial("RttMat_DfShFuncTNB");
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShSpecular
+
+ RTT_Texture_DfShSpecular = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShSpecular",
+ "RTTResources", TEX_TYPE_2D, DSWidthB, DSHeightB, 0, PF_FLOAT16_RGBA,
+ TU_RENDERTARGET);
+
+
+ renderTexture_DfShSpecular = RTT_Texture_DfShSpecular->getBuffer()->getRenderTarget();
+ renderTexture_DfShSpecular->addViewport(m_pCamera);
+ renderTexture_DfShSpecular->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_DfShSpecular->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShSpecular->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShSpecular = MaterialManager::getSingleton().create("RttMat_DfShSpecular", "RTTResources");
+ RTT_Technique_DfShSpecular = RTT_Mat_DfShSpecular->createTechnique();
+ RTT_Technique_DfShSpecular->createPass();
+ TextureUnitState* tState_DfShSpecular = RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShSpecular");
+ tState_DfShSpecular->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ if(m_nSpeedRender)
+ RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+ else
+ RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+
+ //renderTexture_DfShSpecular->addListener(this);
+
+ miniScreen_DfShSpecular = new Ogre::Rectangle2D(true);
+ miniScreen_DfShSpecular->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShSpecular->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShSpecular = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShSpecular");
+ miniScreenNode_DfShSpecular->attachObject(miniScreen_DfShSpecular);
+ miniScreen_DfShSpecular->setMaterial("RttMat_DfShSpecular");
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShEmissive
+
+ RTT_Texture_DfShEmissive = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShEmissive",
+ "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+
+ renderTexture_DfShEmissive = RTT_Texture_DfShEmissive->getBuffer()->getRenderTarget();
+ renderTexture_DfShEmissive->addViewport(m_pCamera);
+ renderTexture_DfShEmissive->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_DfShEmissive->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShEmissive->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShEmissive = MaterialManager::getSingleton().create("RttMat_DfShEmissive", "RTTResources");
+ RTT_Technique_DfShEmissive = RTT_Mat_DfShEmissive->createTechnique();
+ RTT_Technique_DfShEmissive->createPass();
+ TextureUnitState* tState_DfShEmissive = RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShEmissive");
+ tState_DfShEmissive->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ if(m_nSpeedRender)
+ RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+ else
+ RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+
+ //renderTexture_DfShEmissive->addListener(this);
+
+ miniScreen_DfShEmissive = new Ogre::Rectangle2D(true);
+ miniScreen_DfShEmissive->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShEmissive->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShEmissive = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShEmissive");
+ miniScreenNode_DfShEmissive->attachObject(miniScreen_DfShEmissive);
+ miniScreen_DfShEmissive->setMaterial("RttMat_DfShEmissive");
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShLamp
+
+ RTT_Texture_DfShLamp = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShLamp",
+ "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);//, 0, false, 6);
+
+ renderTexture_DfShLamp = RTT_Texture_DfShLamp->getBuffer()->getRenderTarget();
+ renderTexture_DfShLamp->addViewport(m_pCamera);
+ renderTexture_DfShLamp->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH);
+ renderTexture_DfShLamp->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShLamp->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShLamp = MaterialManager::getSingleton().create("RttMat_DfShLamp", "RTTResources");
+ RTT_Technique_DfShLamp = RTT_Mat_DfShLamp->createTechnique();
+ RTT_Technique_DfShLamp->createPass();
+ TextureUnitState* tState_DfShLamp = RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShLamp");
+ tState_DfShLamp->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+ //renderTexture_DfShLamp->addListener(this);
+
+ miniScreen_DfShLamp = new Ogre::Rectangle2D(true);
+ miniScreen_DfShLamp->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShLamp->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShLamp = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShLamp");
+ miniScreenNode_DfShLamp->attachObject(miniScreen_DfShLamp);
+ miniScreen_DfShLamp->setMaterial("RttMat_DfShLamp");
+
+
+
+ /*
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShData
+
+ RTT_Texture_DfShData = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShData",
+ "RTTResources", TEX_TYPE_2D, DSWidthB, DSHeightB, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+ renderTexture_DfShData = RTT_Texture_DfShData->getBuffer()->getRenderTarget();
+ renderTexture_DfShData->addViewport(m_pCamera);
+ renderTexture_DfShData->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_DfShData->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShData->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShData = MaterialManager::getSingleton().create("RttMat_DfShData", "RTTResources");
+ RTT_Technique_DfShData = RTT_Mat_DfShData->createTechnique();
+ RTT_Technique_DfShData->createPass();
+ TextureUnitState* tState_DfShData = RTT_Mat_DfShData->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShData");
+ tState_DfShData->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ if(m_nSpeedRender)
+ RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+ else
+ RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+ //renderTexture_DfShData->addListener(this);
+
+ miniScreen_DfShData = new Ogre::Rectangle2D(true);
+ miniScreen_DfShData->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShData->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShData = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShData");
+ miniScreenNode_DfShData->attachObject(miniScreen_DfShData);
+ miniScreen_DfShData->setMaterial("RttMat_DfShData");
+
+ */
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShTemp
+
+ RTT_Texture_DfShTemp = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShTemp",
+ "RTTResources", TEX_TYPE_2D, TEMPWidth, TEMPHeight, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);//, 0, false, 6);
+
+ renderTexture_DfShTemp = RTT_Texture_DfShTemp->getBuffer()->getRenderTarget();
+ renderTexture_DfShTemp->addViewport(m_pCamera);
+ renderTexture_DfShTemp->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+ renderTexture_DfShTemp->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShTemp->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShTemp = MaterialManager::getSingleton().create("RttMat_DfShTemp", "RTTResources");
+ RTT_Technique_DfShTemp = RTT_Mat_DfShTemp->createTechnique();
+ RTT_Technique_DfShTemp->createPass();
+ TextureUnitState* tState_DfShTemp = RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShTemp");
+ tState_DfShTemp->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+ //renderTexture_DfShTemp->addListener(this);
+
+ miniScreen_DfShTemp = new Ogre::Rectangle2D(true);
+ miniScreen_DfShTemp->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShTemp->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShTemp = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShTemp");
+ miniScreenNode_DfShTemp->attachObject(miniScreen_DfShTemp);
+ miniScreen_DfShTemp->setMaterial("RttMat_DfShTemp");
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // DfShMix
+
+ RTT_Texture_DfShMix = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShMix",
+ "RTTResources", TEX_TYPE_2D, RTTWidth, RTTHeight, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+
+ renderTexture_DfShMix = RTT_Texture_DfShMix->getBuffer()->getRenderTarget();
+ renderTexture_DfShMix->addViewport(m_pCamera);
+ renderTexture_DfShMix->getViewport(0)->setClearEveryFrame(false);//, FBT_DEPTH);
+ renderTexture_DfShMix->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_DfShMix->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_DfShMix = MaterialManager::getSingleton().create("RttMat_DfShMix", "RTTResources");
+ RTT_Technique_DfShMix = RTT_Mat_DfShMix->createTechnique();
+ RTT_Technique_DfShMix->createPass();
+ TextureUnitState* tState_DfShMix = RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShMix");
+ tState_DfShMix->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+
+ miniScreen_DfShMix = new Ogre::Rectangle2D(true);
+ miniScreen_DfShMix->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShMix->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShMix = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShMix");
+ miniScreenNode_DfShMix->attachObject(miniScreen_DfShMix);
+ miniScreen_DfShMix->setMaterial("RttMat_DfShMix");
+
+ if(m_nRenderHDR)
+ {
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // BlurA
+
+ RTT_Texture_BlurA = Ogre::TextureManager::getSingleton().createManual("RttTex_BlurA",
+ "RTTResources", TEX_TYPE_2D, DSWidth/2, DSHeight/2, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+ renderTexture_BlurA = RTT_Texture_BlurA->getBuffer()->getRenderTarget();
+ renderTexture_BlurA->addViewport(m_pCamera);
+ renderTexture_BlurA->getViewport(0)->setClearEveryFrame(false);
+ renderTexture_BlurA->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_BlurA->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_BlurA = MaterialManager::getSingleton().create("RttMat_BlurA", "RTTResources");
+ RTT_Technique_BlurA = RTT_Mat_BlurA->createTechnique();
+ RTT_Technique_BlurA->createPass();
+ TextureUnitState* tState_BlurA = RTT_Mat_BlurA->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_BlurA");
+ tState_BlurA->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_BlurA->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_BlurA->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+
+ miniScreen_BlurA = new Ogre::Rectangle2D(true);
+ miniScreen_BlurA->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_BlurA->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_BlurA = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_BlurA");
+ miniScreenNode_BlurA->attachObject(miniScreen_BlurA);
+ miniScreen_BlurA->setMaterial("RttMat_BlurA");
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // BlurB
+
+ RTT_Texture_BlurB = Ogre::TextureManager::getSingleton().createManual("RttTex_BlurB",
+ "RTTResources", TEX_TYPE_2D, DSWidth/2, DSHeight/2, 0, PF_FLOAT16_RGB,
+ TU_RENDERTARGET);
+
+ renderTexture_BlurB = RTT_Texture_BlurB->getBuffer()->getRenderTarget();
+ renderTexture_BlurB->addViewport(m_pCamera);
+ renderTexture_BlurB->getViewport(0)->setClearEveryFrame(false);
+ renderTexture_BlurB->getViewport(0)->setBackgroundColour(ColourValue::Black);
+ renderTexture_BlurB->getViewport(0)->setOverlaysEnabled(false);
+
+ RTT_Mat_BlurB = MaterialManager::getSingleton().create("RttMat_BlurB", "RTTResources");
+ RTT_Technique_BlurB = RTT_Mat_BlurB->createTechnique();
+ RTT_Technique_BlurB->createPass();
+ TextureUnitState* tState_BlurB = RTT_Mat_BlurB->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_BlurB");
+ tState_BlurB->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+ RTT_Mat_BlurB->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+ RTT_Mat_BlurB->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+
+ miniScreen_BlurB = new Ogre::Rectangle2D(true);
+ miniScreen_BlurB->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_BlurB->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_BlurB = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_BlurB");
+ miniScreenNode_BlurB->attachObject(miniScreen_BlurB);
+ miniScreen_BlurB->setMaterial("RttMat_BlurB");
+
+ } // end if m_nRenderHDR
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // mixing quad
+ miniScreen_DfShMaster = new Ogre::Rectangle2D(true);
+ miniScreen_DfShMaster->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+ miniScreen_DfShMaster->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
+ miniScreenNode_DfShMaster = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShMaster");
+ miniScreenNode_DfShMaster->attachObject(miniScreen_DfShMaster);
+ //miniScreen_DfShMaster->setMaterial("RttMat_DfShDiffuse") ;
+ //miniScreen_DfShMaster->setMaterial("DfShMix") ; // doesn't matter what material we use, since we mix from pre-rendered textures
+
+ //RTT_Mat_Shadow->getTechnique(0)->getPass(0)->getTextureUnitState("RttTex_Shadow")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+
+}
+
+void OgreFramework::DestroyRTTAssets()
+{
+}
+
+void OgreFramework::UpdateRenderTargets()
+{
+
+ int nZoneList=0 ;
+ int nZone=0 ;
+ Ogre::Entity* pEntity=NULL ;
+ int nMO=0 ;
+ int nZGStart=0 ;
+ int nZGEnd=0 ;
+
+ int nVisEnt=0 ;
+ int nEntity=0 ;
+ int nMaxEntity=0 ;
+ int nSubMesh=0 ;
+ int nMaxSubMesh=0 ;
+
+ int nMaxVisibleZone=*m_pGlobal_MaxVisibleZone ;
+
+ SetAllLightsOff() ;
+
+
+ // extra texture params
+ // TexParam.x is 1 for d3d, -1 for ogl, needed for screen space UV calculations y flip
+ // TexParam.y is game time, in 1/10th of a second since start of level
+
+ Ogre::Vector4 TexParam ;
+ if(m_IsOpenGL)
+ TexParam.x=-1 ;
+ else
+ TexParam.x= 1 ;
+ TexParam.y=m_GameTime/100 ;
+ TexParam.z=512.0f ; // pixelnoise subdivisions for the emmissive data function.
+
+
+ // remove all the nodes, so we start with a clean slate
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // deferred shading data textures
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ;
+
+ // attach the entity masternode, update positions and orientations
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ m_pEntityInfo[ nEntity ].pMasterNode->setPosition( m_pEntityInfo[nEntity].Postition ) ; // set position.
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ;
+ }
+
+
+
+
+ /////////////////////////////////////////////////////////////////////
+ // DfShPosition
+
+ // change material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_DfShPosition[nMO] ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+
+ // 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
+ // Set the entity material
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+ {
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShPosition[nSubMesh] ) ;
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ; // first time around, make sure it is visible
+ }
+ else
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ;
+ }
+
+
+
+ renderTexture_DfShPosition->update(true) ;
+
+ /////////////////////////////////////////////////////////////////////
+ // DfShFuncTNB
+
+ // change material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_DfShFuncTNB[nMO] ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShFuncTNB[nSubMesh] ) ;
+ }
+
+
+ renderTexture_DfShFuncTNB->update(true) ;
+
+
+ /////////////////////////////////////////////////////////////////////
+ // DfShDiffuse
+
+ // the diffuse pass is used for the wireframe render as well
+
+
+
+ if(m_nDisplayInfoMode!=1)
+ {
+ // change material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_DfShDiffuse[nMO] ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+ // set the entity material
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShDiffuse[nSubMesh] ) ;
+ }
+
+
+ renderTexture_DfShDiffuse->update(true) ;
+ }
+ else // if we are doing wireframe we use this pass for it
+ {
+ // add gels just for the wireframe
+ SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ;
+
+
+ // clear the RTT texture, since our wireframe won't clear it.
+ m_pRoot->getRenderSystem()->_setViewport(renderTexture_DfShDiffuse->getViewport(0)) ;
+ m_pRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR|FBT_DEPTH, Ogre::ColourValue(0,0,0,1)) ;
+
+ // set the camera to wireframe mode
+ m_pCamera->setPolygonMode(PM_WIREFRAME);
+
+ // change material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( MaterialManager::getSingleton().getByName("White") ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ {
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_OPAQUE) // any non-opaque submeshes need to be made visible
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
+
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial(MaterialManager::getSingleton().getByName("White") ) ;
+ }
+ }
+
+ renderTexture_DfShDiffuse->update(true) ;
+
+ // reset back to pre-wireframe setup
+ m_pCamera->setPolygonMode(PM_SOLID);
+
+ // remove everything and then add back OPAQUE
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
+ SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ;
+
+
+ // reattach entities, make non-opaque subentities invisible
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ;
+
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ {
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_OPAQUE)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ;
+ }
+ }
+
+
+
+ }
+
+
+
+ /////////////////////////////////////////////////////////////////////
+ // DfShSpecular
+
+ // change material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_DfShSpecular[nMO] ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ // set the entity material
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShSpecular[nSubMesh] ) ;
+ }
+
+ renderTexture_DfShSpecular->update(true) ;
+
+ /*
+ /////////////////////////////////////////////////////////////////////
+ // DfShData
+
+ // change material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_DfShData[nMO] ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+ renderTexture_DfShData->update(true) ;
+ */
+
+
+ /////////////////////////////////////////////////////////////////////
+ // DfShEmissive
+
+ // we add the glow entities for this pass, if we are doing HDR
+ if(m_nRenderHDR)
+ SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GLOW) ;
+
+
+ // change material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GLOW))
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_DfShEmissive[nMO] ) ;
+
+ TexParam.z=512.0f ; // pixelnoise subdivisions for the emmissive data function.
+ pEntity->getSubEntity(0)->setCustomParameter(4, TexParam) ; // emissive makes use of gametime for some lighting effects
+ }// end for entities
+
+ }// end for zonelist
+
+ // set the entity material
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW))
+ {
+ // make glow stuff visible
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
+
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShEmissive[nSubMesh] ) ;
+ }
+ }
+
+ renderTexture_DfShEmissive->update(true) ;
+
+
+
+ ////////////////////////////////////////////////////////////////////
+ // we need to know how to colour stuff if we're seeing it through gel
+ // this colouring will be applied when we mix lamp and emmissive down to DfShMix
+ //
+ // Note that this leaves the light/lamp glow entities attached in HDR mode,
+ // we need them to block the gels otherwise the blur on the lights/lamps
+ // comes out incorrectly coloured by gel that should be behind it.
+
+ // add the transparent stuff
+ SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ;
+
+ // change material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL) || (m_pZoneEntityMaterialType[nMO]==MAT_GLOW))
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_DfShColour[nMO] ) ;
+ }// end for entities
+
+
+ }// end for zonelist
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+ {
+ nEntity=m_pFrustumEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ // set the entity material
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW))
+ {
+ // make gel stuff visible (glow was already made visible on the emissive pass)
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
+
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShColour[nSubMesh] ) ;
+ }
+ }
+
+ // render colour to the temp surface
+ renderTexture_DfShTemp->update(true) ;
+
+
+
+ //clear the mix buffer once
+ m_pRoot->getRenderSystem()->_setViewport(renderTexture_DfShMix->getViewport(0)) ;
+ m_pRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR|FBT_DEPTH, Ogre::ColourValue(0,0,0,1)) ;
+
+ // remove all the nodes
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // deferred shading non-shadowing point lights
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+ if(true)
+ {
+ SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_LAMP) ; // attach the lamp boxes
+
+ // this renders our deferred shader lamps
+ renderTexture_DfShLamp->update(true) ;
+
+ // this shader combines the deferred light render with the emissive render and colours it with any gels
+ miniScreen_DfShMaster->setMaterial("Mix_Lamps") ;
+
+ // get rid of all the scene geometry
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+ // put up a fullscreen quad so DfShMix has some UV coordinates.
+ m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+ // update DfShMix, but don't swap buffers yet since we may be back again next loop with more lights to add.
+ renderTexture_DfShMix->update(false) ;
+
+ // now DfShMix has all the deferred render stuff mixed onto it, as well as emissive stuff,
+ // and it's ready for forward rendered shadowing lights to be additively blended over it.
+ } // end if deferred render active
+
+
+
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // forward rendered shadowing spotlights
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // we now add entities from m_pVisibleEntity instead of m_pFrustumEntity since entities outside the frustum might still contribute shadows.
+ //''
+ if(true)
+ {
+
+
+ // multiple attempts at getting additive blending of the shadows failed, so I have to do an extra pass to "accumulate" the data :(
+
+ int nMaxVisibleLight=*m_pGlobal_MaxVisibleLight ;
+
+ // 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
+ Ogre::Vector4 tvpMat0 ;
+ Ogre::Vector4 tvpMat1 ;
+ Ogre::Vector4 tvpMat2 ;
+ Ogre::Vector4 tvpMat3 ;
+
+
+
+ int nVisibleLight=0 ;
+ int nLt=0 ;
+ int nProjector=0 ;
+ int nEntLtIndex=0 ;
+ int nEntLtIndexMax=0 ;
+
+ m_nVisibleLightCount=0 ; // total shadow lights added from all loops
+
+
+ miniScreen_DfShMaster->setMaterial("Mix_ShadowLights") ;
+
+
+ // loop through shadow casting lights
+ for(nVisibleLight=0 ; nVisibleLight<nMaxVisibleLight ; nVisibleLight++)
+ {
+ // copy the camera's original settings because we'll be modifying it
+ m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ;
+
+ nLt=m_pGlobal_VisibleLightList[nVisibleLight] ;
+
+ // setup the light and light's shadow camera, skip if light isn't really visible
+ if(SetupSingleVisibleLightAndShadowCamera(nLt, m_pGlobal_LightVis, m_pGlobal_VisibleLightList, m_pCamera))
+ {
+ // count the light
+ m_nVisibleLightCount++ ;
+
+
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Render the shadow map
+
+ // add all the opaque stuff
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+ SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ;
+
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+ {
+ // check if this entity touches this light
+ nEntity=m_pVisibleEntity[nVisEnt] ;
+
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ;
+
+ nEntLtIndexMax=m_pEntityInfo[nEntity].Light[INDEX_LIGHTPERENTITY] ;
+ m_pEntityInfo[nEntity].LightTouch=0 ; // default, doesn't touch this light, use black material
+ for(nEntLtIndex=0 ; nEntLtIndex<nEntLtIndexMax ; nEntLtIndex++)
+ if(m_pEntityInfo[nEntity].Light[nEntLtIndex]==nLt) // found a match, entity is touched by this light
+ {
+ m_pEntityInfo[nEntity].LightTouch=1 ; // touches this light, don't use black
+ break ;
+ }
+
+ }// end for nVisEnt
+
+
+
+
+
+
+
+ // change to shadow pass material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_Shadow[nMO] ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+ {
+ nEntity=m_pVisibleEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ // set the entity material
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Shadow[nSubMesh] ) ;
+ else
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ; // non-opaque stuff is invisible
+ }
+
+
+ // render the shadow map out to the Shadow texture
+ renderTexture_Shadow->update(true) ;
+
+ // Opaque nodes are already in the scene, add all the Transparent stuff
+ SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ;
+
+ // if this light is flagged as needing colourized shadows, we do the slower shadow method
+ // this means rendering an extra couple of coloured shadow maps here, plus a different material for the view render
+ if(m_nColouredShadow)
+ {
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Render the ShadeFront map
+
+
+
+ // change to shadow pass material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_ShadeFront[nMO] ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+ {
+ nEntity=m_pVisibleEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ // set the entity material (pClearMaterial is already set)
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
+ {
+ // make gel stuff visible
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
+
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_ShadeFront[nSubMesh] ) ;
+ }
+ }
+
+ // render the shadow map out to the Shadow texture
+ renderTexture_ShadeFront->update(true) ;
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Render the ShadeBack map
+
+ // change to shadow pass material
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+ pEntity->setMaterial( m_pZoneEntityMaterial_ShadeBack[nMO] ) ;
+ }// end for entities
+
+ }// end for zonelist
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+ {
+ nEntity=m_pVisibleEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ // set the entity material (pClearMaterial is already set)
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_ShadeBack[nSubMesh] ) ;
+ }
+
+ // render the shadow map out to the Shadow texture
+ renderTexture_ShadeBack->update(true) ;
+
+ } // end if we need coloured shadows
+
+
+
+
+
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Apply the shadow map to the view
+
+ // calculate the texture view projection matrix for this light
+ Matrix4 TexViewProj=CreateTextureViewProjectionMatrix(m_pCamera) ;
+
+ // change the matrix to four Vector4s so we can pass it in as a shader parameter
+ tvpMat0[0]=TexViewProj[0][0] ; tvpMat0[1]=TexViewProj[0][1] ; tvpMat0[2]=TexViewProj[0][2] ; tvpMat0[3]=TexViewProj[0][3] ;
+ tvpMat1[0]=TexViewProj[1][0] ; tvpMat1[1]=TexViewProj[1][1] ; tvpMat1[2]=TexViewProj[1][2] ; tvpMat1[3]=TexViewProj[1][3] ;
+ tvpMat2[0]=TexViewProj[2][0] ; tvpMat2[1]=TexViewProj[2][1] ; tvpMat2[2]=TexViewProj[2][2] ; tvpMat2[3]=TexViewProj[2][3] ;
+ tvpMat3[0]=TexViewProj[3][0] ; tvpMat3[1]=TexViewProj[3][1] ; tvpMat3[2]=TexViewProj[3][2] ; tvpMat3[3]=TexViewProj[3][3] ;
+
+ // put the camera back to its proper position and settings.
+ m_pCamera->synchroniseBaseSettingsWith(m_pCameraCopy) ;
+ m_pCamera->setFOVy( Degree(m_flFOV) ) ;
+ m_pCamera->setAspectRatio( Real(m_flAspectRatio) );
+
+
+ nProjector=m_Q3Map->m_pLight[nLt].Texture ; // what projector texture is this light using?
+
+ // change material and set all the tvp custom params
+ for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+ {
+ nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
+ {
+ pEntity=m_pZoneEntity[nMO] ;
+
+
+ // since the spot light pass is one of the slowest, we set the material of all the zones that don't touch
+ // this light to just a black material. Only the zone of this light gets the real lighting material
+ // We need to have the other zones though or we end up seeing through walls.
+ // ALSO don't set gels to black, or else they block out the light in other zones.
+
+
+ if((m_pZoneEntityMaterialType[nMO]==MAT_GEL) || (LightTouchesZone(nLt, nZone)) )
+ {
+ if(m_nColouredShadow)
+ pEntity->setMaterial( m_pZoneEntityMaterial_Base[nProjector][nMO] ) ; // coloured shadows
+ else
+ pEntity->setMaterial( m_pZoneEntityMaterial_Fast[nProjector][nMO] ) ; // fast shadows
+ }
+ else
+ pEntity->setMaterial( m_pZoneEntityMaterial_Black[nMO] ) ; // just flat black, alpha tested for some
+
+
+
+
+
+ // set the custom parameter, our texture view projection matrix for this light
+ pEntity->getSubEntity(0)->setCustomParameter(0, tvpMat0) ;
+ pEntity->getSubEntity(0)->setCustomParameter(1, tvpMat1) ;
+ pEntity->getSubEntity(0)->setCustomParameter(2, tvpMat2) ;
+ pEntity->getSubEntity(0)->setCustomParameter(3, tvpMat3) ;
+
+ pEntity->getSubEntity(0)->setCustomParameter(4, TexParam) ;
+
+ }// end for entities
+
+ }// end for zonelist
+
+ for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+ {
+ nEntity=m_pVisibleEntity[nVisEnt] ;
+ nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+ // set the entity material
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
+ {
+
+ // if it's gel or the light touches the entity, use proper material, else use black
+ if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL) || m_pEntityInfo[nEntity].LightTouch)
+ {
+ if(m_nColouredShadow)
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Base[nProjector][nSubMesh] ) ; // coloured shadows
+ else
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Fast[nProjector][nSubMesh] ) ; // fast shadows
+ }
+ else
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Black[nSubMesh] ) ; // flat black
+
+
+
+ // set the custom parameter, our texture view projection matrix for this light
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(0, tvpMat0) ;
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(1, tvpMat1) ;
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(2, tvpMat2) ;
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(3, tvpMat3) ;
+
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(4, TexParam) ;
+ }
+ else
+ m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( pClearMaterial ) ;
+ }
+
+
+
+
+ // if this is the first visible light, add emmissive transparent/alphablend particles.
+ // they are added here so that they render correctly according to gels.
+ // But since they aren't shadowed, we only need render them for one light.
+ if(m_nVisibleLightCount==1)
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pParticleNode) ; // attach the particles
+
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ // render the scene out to the DfShTemp texture.
+ //
+
+ renderTexture_DfShTemp->update(true) ;
+
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+ // remove the particles
+ if(m_nVisibleLightCount==1)
+ m_pSceneMgr->getRootSceneNode()->removeChild(m_pParticleNode) ;
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Render Mix
+
+ //?? unfortunately Ogre shares depth buffers in a manner that won't allow us to just additively render to DfShMix.
+ // If we try, we get glitching from the buffer sharing between Shadow and DfShMix.
+ // So instead we get rid of all geometry and additively render a fullscreen quad of DfShTemp to DfShMix.
+ // Slows things down a little, but at least it works.
+
+ // get rid of all the scene geometry
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+ // put up a fullscreen quad so DfShMix has some UV coordinates.
+ m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+ // update DfShMix, but don't swap buffers yet since we may be back again next loop with more lights to add.
+ renderTexture_DfShMix->update(false) ;
+
+ }// end if light is visible
+
+
+ }// end for nVisibleLight
+
+ }// end if forward render active
+
+ ///////////////////////////////////////////////////////////////////////////////////////
+
+
+
+ // after we've finished with all the lights and mixing, time to swap the mix buffer
+ renderTexture_DfShMix->swapBuffers(false) ;
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // HDR bloom
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ if(m_nRenderHDR)
+ {
+ /////////////////////////////////////////////////////////
+ // copy DfShMix to BlurA
+
+ // get rid of all the scene geometry
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+ // this shader renders DfShMix onto a surface
+ miniScreen_DfShMaster->setMaterial("HDR_MixToBlurA") ;
+
+ // put up a fullscreen quad so BlurA has some UV coordinates.
+ m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+ // render DfShMix to BlurA
+ renderTexture_BlurA->update(true) ;
+
+
+
+
+ //////////////////////////////////////////////////////////////
+ // now we do a few rounds of ping-pong bluring of A to B, B to A.
+ int nMaxBlur=4 ;
+ int nLastBlur=nMaxBlur-1 ;
+ int nBlurLoop=0 ;
+
+
+ // opengl and direct3d give different results for the same blur shader,
+ // the issue is that d3d with bilinear filtering will offset stuff,
+ // leading to a right-down drift that we need to compensate for.
+ // So we need two versions of the blur shaders, one for ogl and one for d3d.
+
+ if(m_IsOpenGL)
+ {
+ miniScreen_BlurA->setMaterial("HDR_BlurA_ogl");
+ miniScreen_BlurB->setMaterial("HDR_BlurB_ogl");
+ }
+ else
+ {
+ miniScreen_BlurA->setMaterial("HDR_BlurA_d3d");
+ miniScreen_BlurB->setMaterial("HDR_BlurB_d3d");
+ }
+
+
+ // the main blur
+ for(nBlurLoop=0 ; nBlurLoop<nMaxBlur ; nBlurLoop++)
+ {
+ // blur A onto B
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+ m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ;
+ renderTexture_BlurB->update(true) ;
+
+ // blur B onto A
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+ m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurB) ;
+ renderTexture_BlurA->update(true) ;
+ }
+
+
+ // If I don't set these materials back to their originals, I get a crash on exit.
+ // Not sure why. Something to do with deleting the originals?
+ // Doesn't matter, this fixes things.
+
+ miniScreen_BlurA->setMaterial("RttMat_BlurA");
+ miniScreen_BlurB->setMaterial("RttMat_BlurB");
+
+
+
+ //////////////////////////////////////////////////////////////////
+ // blend BlurA onto DfShMix
+
+ // get rid of all the scene geometry
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+ // this shader blends BlurA onto a surface
+ if(m_IsOpenGL)
+ miniScreen_DfShMaster->setMaterial("HDR_BlurAToMix_ogl") ;
+ else
+ miniScreen_DfShMaster->setMaterial("HDR_BlurAToMix_d3d") ;
+
+ // put up a fullscreen quad so DfShMix has some UV coordinates.
+ m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+ // update DfShMix.
+ renderTexture_DfShMix->update(true) ;
+
+ }// end if HDR
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // display a rendered window
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
+
+
+ if(m_nGoggleMode==GOGGLE_MODE_OFF) // stereo rendering not active
+ {
+ switch(m_nDisplayInfoMode)
+ {
+
+ case 0: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ; break ;
+ case 1: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShTemp) ; break ; // for wireframe view
+ case 2: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShLamp) ; break ;
+ case 3: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ; break ;
+
+ case 4: // instead of showing the original position texture, we show a scaled version, since the original is outside 0-1 range
+
+ // get rid of all the scene geometry
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+ // this shader renders DfShMix onto a surface
+ miniScreen_DfShMaster->setMaterial("Mix_ScalePosition") ;
+
+ // put up a fullscreen quad so BlurA has some UV coordinates.
+ m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+ // render DfShPostion to DfShMix
+ renderTexture_DfShMix->update(true) ;
+
+ // display mix, which is a scaled copy of position.
+ m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ;
+ break ;
+
+ case 5: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShFuncTNB) ; break ;
+ case 6: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ; break ;
+ case 7: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShSpecular) ; break ;
+ case 8: m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShEmissive) ; break ;
+ }
+
+
+
+
+
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShPosition) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShFuncTNB) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShSpecular) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShEmissive) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShData) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShLamp) ;
+
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ;
+
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ;
+
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_Shadow) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShTemp) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_ShadeBack) ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_ShadeFront) ;
+ }
+ else
+ {
+ // add and position the Goggles
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pNodeGoggles) ;
+ m_pNodeGoggles->setOrientation( m_pCamera->getOrientation() ) ;
+ m_pNodeGoggles->setPosition( m_pCamera->getPosition() ) ;
+ }
+
+
+ //m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+ //m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ;
+
+
+ m_pRenderWnd->update(true) ;
+
+
+ //m_pSceneMgr->getRootSceneNode()->removeChild(miniScreenNode_DfShSpecular) ;
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+
+
+
+ ///////////////////////////////////////////
+ // blittomemory experiment
+ //uchar pixelData[64] ;
+ //RTT_Texture_DfShPosition->getBuffer()->blitToMemory( Box( 0, 0, 1, 1), PixelBox(2, 2, 1, PF_FLOAT16_RGB, (void*)pixelData) ) ;
+
+
+}
+
+// generate the texture view Projection matrix used in shadow mapping
+Ogre::Matrix4 OgreFramework::CreateTextureViewProjectionMatrix(Ogre::Camera* pCamera)
+{
+
+ const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE(
+ 0.5, 0, 0, 0.5,
+ 0, -0.5, 0, 0.5,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+
+ Matrix4 TexViewProj = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * pCamera->getProjectionMatrixWithRSDepth() * pCamera->getViewMatrix();
+
+ return TexViewProj ;
+
+}
+
+void OgreFramework::DestroyGoggles()
+{
+ //m_pGoggleL->~ManualObject() ;
+ //m_pGoggleR->~ManualObject() ;
+
+ //m_pNodeGoggles->~SceneNode() ;
+
+
+}
+
+// create the "virtual" virtual reality goggles we use to get around stereoscopic driver problems.
+int OgreFramework::CreateGoggles()
+{
+
+
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+
+
+ // if they already exist, destroy them so we can recreate them
+ if(m_pNodeGoggles!=NULL) m_pNodeGoggles->detachAllObjects() ;
+ if(m_pGoggleL!=NULL) m_pGoggleL->clear() ;
+ if(m_pGoggleR!=NULL) m_pGoggleR->clear() ;
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // left goggle
+
+ if(m_pGoggleL==NULL) m_pGoggleL=m_pSceneMgr->createManualObject("GoggleL") ;
+ m_pGoggleL->begin("RttMat_DfShMix", RenderOperation::OT_TRIANGLE_LIST) ;
+
+ flMinX=-100*m_flGoggleAspectRatio*m_flGoggleXScale ;
+ flMinY=-50*m_flGoggleYScale ;
+
+
+ flMaxX=0 ;
+ flMaxY=50*m_flGoggleYScale ;
+
+
+ m_pGoggleL->position(flMinX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+ m_pGoggleL->normal(0.0, 0.0, -1) ;
+ m_pGoggleL->textureCoord(0.0, 0.0) ;
+ m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+ m_pGoggleL->normal(0.0, 0.0, -1) ;
+ m_pGoggleL->textureCoord(1.0, 0.0) ;
+ m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+ m_pGoggleL->normal(0.0, 0.0, -1) ;
+ m_pGoggleL->textureCoord(1.0, 1.0) ;
+ m_pGoggleL->position(flMinX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+ m_pGoggleL->normal(0.0, 0.0, -1) ;
+ m_pGoggleL->textureCoord(0.0, 1.0) ;
+
+ m_pGoggleL->quad(3, 2, 1, 0) ;
+ m_pGoggleL->end() ;
+
+ m_pGoggleL->setCastShadows(false) ;
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // right goggle
+
+ if(m_pGoggleR==NULL) m_pGoggleR=m_pSceneMgr->createManualObject("GoggleR") ;
+ m_pGoggleR->begin("RttMat_DfShMix", RenderOperation::OT_TRIANGLE_LIST) ;
+
+
+ flMinX=0 ;
+ flMinY=-50*m_flGoggleYScale ;
+
+
+ flMaxX=100*m_flGoggleAspectRatio*m_flGoggleXScale ;
+ flMaxY=50*m_flGoggleYScale ;
+
+
+ m_pGoggleR->position(flMinX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+ m_pGoggleR->normal(0.0, 0.0, -1) ;
+ m_pGoggleR->textureCoord(0.0, 0.0) ;
+ m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+ m_pGoggleR->normal(0.0, 0.0, -1) ;
+ m_pGoggleR->textureCoord(1.0, 0.0) ;
+ m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+ m_pGoggleR->normal(0.0, 0.0, -1) ;
+ m_pGoggleR->textureCoord(1.0, 1.0) ;
+ m_pGoggleR->position(flMinX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+ m_pGoggleR->normal(0.0, 0.0, -1) ;
+ m_pGoggleR->textureCoord(0.0, 1.0) ;
+
+ m_pGoggleR->quad(3, 2, 1, 0) ;
+ m_pGoggleR->end() ;
+
+ m_pGoggleR->setCastShadows(false) ;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // attach the goggles to the node.
+ if(m_pNodeGoggles==NULL) m_pNodeGoggles=m_pSceneMgr->getRootSceneNode()->createChildSceneNode("NodeGoggles") ;
+ m_pNodeGoggles->attachObject(m_pGoggleL) ;
+ m_pNodeGoggles->attachObject(m_pGoggleR) ;
+
+ return 1 ;
+}
+
+// create the "virtual" virtual reality goggles we use to get around stereoscopic driver problems.
+// This version of the goggles just has a test image for setting up the correct real driver settings,
+// so that the left eye sees only the left "goggle" and the right eye only the right "goggle",
+// and the goggles have the right depth relative to the screen (flat to it)
+int OgreFramework::CreateGogglesTestImage()
+{
+
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+
+
+ // if they already exist, destroy them so we can recreate them
+ if(m_pNodeGoggles!=NULL) m_pNodeGoggles->detachAllObjects() ;
+ if(m_pGoggleL!=NULL) m_pGoggleL->clear() ;
+ if(m_pGoggleR!=NULL) m_pGoggleR->clear() ;
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // left goggle
+
+ if(m_pGoggleL==NULL) m_pGoggleL=m_pSceneMgr->createManualObject("GoggleL") ;
+ m_pGoggleL->begin("GoggleTest", RenderOperation::OT_TRIANGLE_LIST) ;
+
+ flMinX=-100*m_flGoggleAspectRatio*m_flGoggleXScale ;
+ flMinY=-50*m_flGoggleYScale ;
+
+
+ flMaxX=0 ;
+ flMaxY=50*m_flGoggleYScale ;
+
+
+ m_pGoggleL->position(flMinX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+ m_pGoggleL->normal(0.0, 0.0, -1) ;
+ m_pGoggleL->textureCoord(0.0, 0.0) ;
+ m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+ m_pGoggleL->normal(0.0, 0.0, -1) ;
+ m_pGoggleL->textureCoord(1.0, 0.0) ;
+ m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+ m_pGoggleL->normal(0.0, 0.0, -1) ;
+ m_pGoggleL->textureCoord(1.0, 1.0) ;
+ m_pGoggleL->position(flMinX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+ m_pGoggleL->normal(0.0, 0.0, -1) ;
+ m_pGoggleL->textureCoord(0.0, 1.0) ;
+
+ m_pGoggleL->quad(3, 2, 1, 0) ;
+ m_pGoggleL->end() ;
+
+ m_pGoggleL->setCastShadows(false) ;
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // right goggle
+
+ if(m_pGoggleR==NULL) m_pGoggleR=m_pSceneMgr->createManualObject("GoggleR") ;
+ m_pGoggleR->begin("GoggleTest", RenderOperation::OT_TRIANGLE_LIST) ;
+
+
+ flMinX=0 ;
+ flMinY=-50*m_flGoggleYScale ;
+
+
+ flMaxX=100*m_flGoggleAspectRatio*m_flGoggleXScale ;
+ flMaxY=50*m_flGoggleYScale ;
+
+
+ m_pGoggleR->position(flMinX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+ m_pGoggleR->normal(0.0, 0.0, -1) ;
+ m_pGoggleR->textureCoord(1.0, 1.0) ;
+ m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+ m_pGoggleR->normal(0.0, 0.0, -1) ;
+ m_pGoggleR->textureCoord(0.0, 1.0) ;
+ m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+ m_pGoggleR->normal(0.0, 0.0, -1) ;
+ m_pGoggleR->textureCoord(0.0, 0.0) ;
+ m_pGoggleR->position(flMinX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+ m_pGoggleR->normal(0.0, 0.0, -1) ;
+ m_pGoggleR->textureCoord(1.0, 0.0) ;
+
+ m_pGoggleR->quad(3, 2, 1, 0) ;
+ m_pGoggleR->end() ;
+
+ m_pGoggleR->setCastShadows(false) ;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // attach the goggles to the node.
+ if(m_pNodeGoggles==NULL) m_pNodeGoggles=m_pSceneMgr->getRootSceneNode()->createChildSceneNode("NodeGoggles") ;
+ m_pNodeGoggles->attachObject(m_pGoggleL) ;
+ m_pNodeGoggles->attachObject(m_pGoggleR) ;
+
+ return 1 ;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::keyPressed(const OIS::KeyEvent &keyEventRef)
+{
+ //m_pLog->logMessage("OgreFramework::keyPressed");
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
+ {
+ m_bShutDownOgre = true;
+ return true;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_SYSRQ))
+ {
+ std::ostringstream ss;
+ ss << "screenshot_" << ++m_iNumScreenShots << ".png";
+ m_pRenderWnd->writeContentsToFile(ss.str());
+ return true;
+ }
+
+ /*
+ if(m_pKeyboard->isKeyDown(OIS::KC_M))
+ {
+ static int mode = 0;
+
+ if(mode == 2)
+ {
+ m_pCamera->setPolygonMode(PM_SOLID);
+ mode = 0;
+ }
+ else if(mode == 0)
+ {
+ m_pCamera->setPolygonMode(PM_WIREFRAME);
+ mode = 1;
+ }
+ else if(mode == 1)
+ {
+ m_pCamera->setPolygonMode(PM_POINTS);
+ mode = 2;
+ }
+ }
+ */
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_O))
+ {
+ if(m_pDebugOverlay)
+ {
+ if(!m_pDebugOverlay->isVisible())
+ m_pDebugOverlay->show();
+ else
+ m_pDebugOverlay->hide();
+ }
+ }
+
+
+
+ return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::keyReleased(const OIS::KeyEvent &keyEventRef)
+{
+ return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::mouseMoved(const OIS::MouseEvent &evt)
+{
+ m_pCamera->yaw(Degree(evt.state.X.rel * -0.1));
+ m_pCamera->pitch(Degree(evt.state.Y.rel * -0.1));
+
+ return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
+{
+ return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
+{
+ return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::updateOgre(double timeSinceLastFrame)
+{
+
+
+
+
+ // update the game time
+ m_GameTime+=timeSinceLastFrame ;
+
+
+ m_MoveScale = m_MoveSpeed * timeSinceLastFrame;
+ m_RotScale = m_RotateSpeed * timeSinceLastFrame;
+
+ m_TranslateVector = Vector3::ZERO;
+
+ char chMessage[1024] ;
+ //sprintf(chMessage, "winmessage %u, %u, %u", m_pRenderWnd->m_Test_uMsg, (UINT)m_pRenderWnd->m_Test_wParam, (UINT)m_pRenderWnd->m_Test_lParam) ;
+ //m_pLog->logMessage(chMessage) ;
+
+
+
+ /*
+ if((m_pRenderWnd->m_Test_uMsg==258) && (m_pRenderWnd->m_Test_wParam==0x78))
+ //if(GetAsyncKeyState(0x78))
+ {
+
+ m_TranslateVector.z = -m_MoveScale;
+ //m_nGotInput=1 ;
+
+ //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) ;
+ //m_pLog->logMessage(chMessage) ;
+ }
+ else
+ m_nGotInput=0 ;
+ */
+
+ // add a test particle to the system
+ /*
+ if( m_ps->getNumParticles() < m_ps->getParticleQuota() )
+ {
+ Ogre::Particle *p = m_ps->createParticle() ;
+ p->setDimensions( m_ps->getDefaultWidth(), m_ps->getDefaultHeight() ) ;
+ p->colour = Ogre::ColourValue::White;
+ p->direction = Ogre::Vector3::UNIT_Y;
+ p->position = Ogre::Vector3::ZERO;
+ p->timeToLive = p->totalTimeToLive = 10;
+ p->rotation = Ogre::Radian(0);
+ p->rotationSpeed = Ogre::Radian(0);
+ }
+ */
+
+
+ m_ps->_update(timeSinceLastFrame/1000.0f) ;
+
+ getInput();
+
+ moveCamera();
+
+
+ //Ogre::Vector3 Pos ;
+ //float CamPos[3] ;
+ //Pos=m_pCamera->getPosition() ;
+ //CamPos[0]=Pos.x ;
+ //CamPos[1]=Pos.y ;
+ //CamPos[2]=Pos.z ;
+
+
+
+ if(m_nGoggleMode==GOGGLE_MODE_OFF)
+ {
+
+
+ m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ; // copy the camera's original settings because we'll be modifying it for the LR views.
+ m_pCameraCopy->setFOVy( Degree(m_flFOV) ) ;
+ m_pCameraCopy->setAspectRatio( Real(m_flAspectRatio) );
+
+
+
+ if(m_nMapLoaded)
+ {
+ SetupEntityZones() ;
+
+ CalculateZoneVisibility(m_pCameraCopy, &m_nCameraZoneL, m_chZoneVisL, m_chLightVisL, m_chSubLightVisL, m_chPortalVisL, &m_nMaxVisibleLightL, m_uVisibleLightListL) ;
+ CalculateEntityVisibility(m_pCameraCopy, m_chZoneVisL) ;
+
+ UpdateVisibleZoneList(m_chZoneVisL, m_uVisibleZoneListL, &m_nMaxVisibleZoneL) ;
+
+ //m_nVisibleLightCount=m_nMaxVisibleLightL ;
+ m_nVisibleZoneCount=m_nMaxVisibleZoneL ;
+ }
+
+
+
+ m_pGlobal_VisibleZoneList=m_uVisibleZoneListL ;
+ m_pGlobal_MaxVisibleZone=&m_nMaxVisibleZoneL ;
+
+ m_pGlobal_VisibleLightList = m_uVisibleLightListL ;
+ m_pGlobal_MaxVisibleLight = &m_nMaxVisibleLightL ;
+ m_pGlobal_LightVis = m_chLightVisL ;
+
+
+ }
+ else
+ {
+ // "virtual" stereo goggle mode. Render everything twice, L and R view, and output to L quad and a R quad.
+
+ m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ; // copy the camera's original settings because we'll be modifying it for the LR views.
+
+ if(m_nMapLoaded)
+ {
+ SetupEntityZones() ;
+
+ CalculateZoneVisibility(m_pCameraCopy, &m_nCameraZoneL, m_chZoneVisL, m_chLightVisL, m_chSubLightVisL, m_chPortalVisL, &m_nMaxVisibleLightL, m_uVisibleLightListL) ;
+ UpdateVisibleZoneList(m_chZoneVisL, m_uVisibleZoneListL, &m_nMaxVisibleZoneL) ;
+
+
+ //m_nVisibleLightCount=m_nMaxVisibleLightL ;
+ m_nVisibleZoneCount=m_nMaxVisibleZoneL ;
+ }
+
+ m_pGlobal_VisibleZoneList=m_uVisibleZoneListL ;
+ m_pGlobal_MaxVisibleZone=&m_nMaxVisibleZoneL ;
+ }
+
+
+ updateStats();
+
+
+ //,,
+ //sprintf(m_chFrame, "End of updateOgre frame %i",m_nFrame) ;
+ //OFBug.LogAddCR(m_chFrame) ;
+
+
+
+ m_nFrame++ ;
+
+
+
+}
+
+
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::updateStats()
+{
+
+
+ Ogre::Vector3 Pos ;
+ Pos=m_pCamera->getPosition() ;
+ int nCamX=Pos.x ;
+ int nCamY=Pos.y ;
+ int nCamZ=Pos.z ;
+
+
+ static String currFps = "FPS: ";
+ static String avgFps = "Av FPS: ";
+ static String bestFps = "Best FPS: ";
+ static String worstFps = "Worst FPS: ";
+ static String tris = "Triangle Count: ";
+ static String batches = "Batch Count: ";
+
+
+ OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
+ OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
+ OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
+ OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
+
+ const RenderTarget::FrameStats& stats = m_pRenderWnd->getStatistics();
+
+ //int LastFrameTime=1000000/stats.lastFPS ;
+ float LastFrameTime=1000/stats.lastFPS ;
+
+
+
+
+
+ switch(m_nDisplayInfoMode)
+ {
+
+ case 0:
+ if(m_IsOpenGL)
+ guiCurr->setCaption("OGL FPS: " + StringConverter::toString(stats.lastFPS) +" "+StringConverter::toString(LastFrameTime)+" ms");
+ else
+ guiCurr->setCaption("D3D FPS: " + StringConverter::toString(stats.lastFPS) +" "+StringConverter::toString(LastFrameTime)+" ms");
+ break ;
+
+ case 1: guiCurr->setCaption("Wireframe") ; break ;
+ case 2: guiCurr->setCaption("Lamps") ; break ;
+ case 3: guiCurr->setCaption("HDR Blur") ; break ;
+ case 4: guiCurr->setCaption("DefShade Position (Scaled)") ; break ;
+ case 5: guiCurr->setCaption("DefShade Normals") ; break ;
+ case 6: guiCurr->setCaption("DefShade Diffuse") ; break ;
+ case 7: guiCurr->setCaption("DefShade Specular") ; break ;
+ case 8: guiCurr->setCaption("DefShade Emissive") ; break ;
+
+ }
+
+ guiAvg->setCaption("Lt: " + StringConverter::toString(m_nVisibleLightCount)
+ + " Zn: " + StringConverter::toString(m_nVisibleZoneCount)
+ + " Cam: "+StringConverter::toString(nCamX)+" "+StringConverter::toString(nCamY)+" "+StringConverter::toString(nCamZ));
+
+
+
+
+ //m_flDebug0=m_nTotalTriangles ;
+ //m_flDebug1=m_nMaxVisibleEntity ;
+ //m_flDebug2=m_nMaxFrustumEntity ;
+ guiWorst->setCaption("ZnEnt: " + StringConverter::toString(m_nMaxVisibleEntity) + " Tri: " + StringConverter::toString(m_nVisibleEntityTriangleCount) + " FwdTri: " + StringConverter::toString(m_nVisibleEntityTriangleCount) ) ;
+ guiBest->setCaption("FrEnt: " + StringConverter::toString(m_nMaxFrustumEntity) + " Tri: " + StringConverter::toString(m_nFrustumEntityTriangleCount) + " DefTri: " + StringConverter::toString(m_nFrustumEntityTriangleCount) ) ;
+
+
+
+
+ //guiWorst->setCaption(StringConverter::toString(m_flDebug0) + " " + StringConverter::toString(m_flDebug1) + " " + StringConverter::toString(m_flDebug2)) ;
+ //guiBest->setCaption(StringConverter::toString(m_flDebug3) + " " + StringConverter::toString(m_flDebug4) + " " + StringConverter::toString(m_flDebug5)) ;
+ /*
+ guiWorst->setCaption(
+ " 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]) +
+ " 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]) ) ;
+
+ guiBest->setCaption(
+ " 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]) +
+ " 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]) ) ;
+ */
+
+
+
+
+ //guiWorst->setCaption(StringConverter::toString(flVarA)+" "+StringConverter::toString(flVarB)+" "+StringConverter::toString(flVarC)+" "+StringConverter::toString(flVarD)
+
+ //guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)
+ // +" "+StringConverter::toString(stats.bestFrameTime)+" ms");
+ //guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)
+ // +" "+StringConverter::toString(stats.worstFrameTime)+" ms");
+
+ //guiWorst->setCaption(worstFps + StringConverter::toString(nCamX)+" " + StringConverter::toString(nCamY)+" " + StringConverter::toString(nCamZ)+" ") ;
+
+
+ OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
+ guiTris->setCaption("MpTri: " + StringConverter::toString(m_nTotalTriangles));
+
+ OverlayElement* guiBatches = OverlayManager::getSingleton().getOverlayElement("Core/NumBatches");
+ guiBatches->setCaption(batches + StringConverter::toString(stats.batchCount));
+
+ OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
+ guiDbg->setCaption("A:"+StringConverter::toString(m_nDebugA) + " B:" + StringConverter::toString(m_nDebugB) + " C:" + StringConverter::toString(m_nDebugC) + " ") ;
+
+ //guiDbg->setCaption(
+ // " 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]) +
+ // " 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]) +
+ // " 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]) +
+ // " 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]) ) ;
+
+
+
+
+ //guiDbg->setCaption("");
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::moveCamera()
+{
+ if( m_nKeyDown_Ctrl && m_nKeyDown_Shift ) // super slow
+ m_pCamera->moveRelative(m_TranslateVector/50);
+ else
+ if(m_nKeyDown_Shift) // fast
+ m_pCamera->moveRelative(m_TranslateVector*10);
+ else
+ if(m_nKeyDown_Ctrl) // slow
+ m_pCamera->moveRelative(m_TranslateVector/5);
+ else
+ m_pCamera->moveRelative(m_TranslateVector*2); // normal
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::getInput()
+{
+ if(m_pKeyboard->isKeyDown(OIS::KC_LCONTROL))
+ m_nKeyDown_Ctrl=1 ;
+ else
+ m_nKeyDown_Ctrl=0 ;
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_LSHIFT))
+ m_nKeyDown_Shift=1 ;
+ else
+ m_nKeyDown_Shift=0 ;
+
+
+
+
+
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_A))
+ {
+ m_TranslateVector.x = -m_MoveScale;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_D))
+ {
+ m_TranslateVector.x = m_MoveScale;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_W))
+ {
+ m_TranslateVector.z = -m_MoveScale;
+ m_nGotInput=1 ;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_S))
+ {
+ m_TranslateVector.z = m_MoveScale;
+ }
+
+
+ // generic toggle for debugging
+ if(m_pKeyboard->isKeyDown(OIS::KC_T))
+ {
+ if(m_nKeyToggle[OIS::KC_T]==0)
+ {
+ m_nKeyToggle[OIS::KC_T]=1 ; // toggle to stop key repeating
+ m_nToggle=1-m_nToggle ;
+ //OFBug.MessageInt(m_nToggle) ;
+ }
+ }
+ else
+ m_nKeyToggle[OIS::KC_T]=0 ;
+
+ //m_flDebug0=m_nKeyToggle[OIS::KC_T] ;
+ //m_flDebug1=m_nToggle ;
+
+ /*
+ if(m_pKeyboard->isKeyDown(OIS::KC_LEFT))
+ {
+ m_pCamera->yaw(m_RotScale);
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_RIGHT))
+ {
+ m_pCamera->yaw(-m_RotScale);
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_UP))
+ {
+ m_pCamera->pitch(m_RotScale);
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_DOWN))
+ {
+ m_pCamera->pitch(-m_RotScale);
+ }
+ */
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Stereo controls
+
+
+
+ // toggle stereo test image mode
+ if(m_pKeyboard->isKeyDown(OIS::KC_DELETE))
+ {
+ if(m_nKeyToggle[OIS::KC_DELETE]==0)
+ {
+ m_nKeyToggle[OIS::KC_DELETE]=1 ; // toggle to stop key repeating
+
+ m_nGoggleMode++ ; // cyle through the goggle modes
+ if(m_nGoggleMode>=GOGGLE_MODE_MAX)
+ m_nGoggleMode=GOGGLE_MODE_OFF ;
+
+ if(m_nGoggleMode==GOGGLE_MODE_TEST)
+ CreateGogglesTestImage() ; // create the test goggles
+ else
+ if(m_nGoggleMode==GOGGLE_MODE_ON)
+ CreateGoggles() ; // create the stereo goggles
+ }
+ }
+ else
+ m_nKeyToggle[OIS::KC_DELETE]=0 ;
+
+ if(m_nGoggleMode==GOGGLE_MODE_TEST) // controls for setting up the test image
+ {
+ 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
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_PGUP))
+ {
+ nDoPause=1 ;
+
+ if(m_nKeyDown_Shift)
+ m_flGoggleZPos-=1.0 ;
+ else
+ if(m_nKeyDown_Ctrl)
+ m_flGoggleZPos-=0.01 ;
+ else
+ m_flGoggleZPos-=0.1 ;
+
+ CreateGogglesTestImage() ;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_PGDOWN))
+ {
+ nDoPause=1 ;
+
+ if(m_nKeyDown_Shift)
+ m_flGoggleZPos+=1.0 ;
+ else
+ if(m_nKeyDown_Ctrl)
+ m_flGoggleZPos+=0.01 ;
+ else
+ m_flGoggleZPos+=0.1 ;
+
+ CreateGogglesTestImage() ;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_HOME))
+ {
+ nDoPause=1 ;
+
+ if(m_nKeyDown_Shift)
+ m_flGoggleXGap-=0.1 ;
+ else
+ if(m_nKeyDown_Ctrl)
+ m_flGoggleXGap-=0.001 ;
+ else
+ m_flGoggleXGap-=0.01 ;
+
+ if(m_flGoggleXGap<0)
+ m_flGoggleXGap=0 ;
+
+ CreateGogglesTestImage() ;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_END))
+ {
+ nDoPause=1 ;
+
+ if(m_nKeyDown_Shift)
+ m_flGoggleXGap+=0.1 ;
+ else
+ if(m_nKeyDown_Ctrl)
+ m_flGoggleXGap+=0.001 ;
+ else
+ m_flGoggleXGap+=0.01 ;
+
+ if(m_flGoggleXGap<0)
+ m_flGoggleXGap=0 ;
+
+ CreateGogglesTestImage() ;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_UP))
+ {
+ nDoPause=1 ;
+
+ if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
+ m_flGoggleYScale=1.0 ;
+ else
+ if(m_nKeyDown_Shift)
+ m_flGoggleYScale+=0.002 ;
+ else
+ if(m_nKeyDown_Ctrl)
+ m_flGoggleYScale+=0.00002 ;
+ else
+ m_flGoggleYScale+=0.0002 ;
+
+ if(m_flGoggleYScale<0)
+ m_flGoggleYScale=0 ;
+
+ CreateGogglesTestImage() ;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_DOWN))
+ {
+ nDoPause=1 ;
+
+ if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
+ m_flGoggleYScale=1.0 ;
+ else
+ if(m_nKeyDown_Shift)
+ m_flGoggleYScale-=0.002 ;
+ else
+ if(m_nKeyDown_Ctrl)
+ m_flGoggleYScale-=0.00002 ;
+ else
+ m_flGoggleYScale-=0.0002 ;
+
+ if(m_flGoggleYScale<0)
+ m_flGoggleYScale=0 ;
+
+ CreateGogglesTestImage() ;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_LEFT))
+ {
+ nDoPause=1 ;
+
+ if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
+ m_flGoggleXScale=1.0 ;
+ else
+ if(m_nKeyDown_Shift)
+ m_flGoggleXScale+=0.002 ;
+ else
+ if(m_nKeyDown_Ctrl)
+ m_flGoggleXScale+=0.00002 ;
+ else
+ m_flGoggleXScale+=0.0002 ;
+
+ if(m_flGoggleXScale<0)
+ m_flGoggleXScale=0 ;
+
+ CreateGogglesTestImage() ;
+ }
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_RIGHT))
+ {
+ nDoPause=1 ;
+
+ if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
+ m_flGoggleXScale=1.0 ;
+ else
+ if(m_nKeyDown_Shift)
+ m_flGoggleXScale-=0.002 ;
+ else
+ if(m_nKeyDown_Ctrl)
+ m_flGoggleXScale-=0.00002 ;
+ else
+ m_flGoggleXScale-=0.0002 ;
+
+ if(m_flGoggleXScale<0)
+ m_flGoggleXScale=0 ;
+
+ CreateGogglesTestImage() ;
+ }
+
+
+
+ if(nDoPause) Sleep(20) ; // pause makes rate more consisent, less frame rate dependent.
+
+ }// end test image controls
+
+
+
+ //
+ //
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // flashlight
+ if(m_pKeyboard->isKeyDown(OIS::KC_F))
+ {
+ if(m_nKeyToggle[OIS::KC_F]==0)
+ {
+ m_nKeyToggle[OIS::KC_F]=1 ; // toggle to stop key repeating
+ m_nFlashLight=1-m_nFlashLight ;
+ m_nDebugA=m_nFlashLight ;
+ //OFBug.MessageInt(m_nToggle) ;
+ }
+ }
+ else
+ m_nKeyToggle[OIS::KC_F]=0 ;
+
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_J))
+ {
+ if(m_nJumpToggle==0)
+ {
+ m_nJumpToggle=1 ;
+
+
+ m_nJumpVal++ ;
+ if(m_nJumpVal>=m_Q3Map->m_nLightMax)
+ m_nJumpVal=0 ;
+
+ //m_flDebug0=m_nJumpVal ;
+
+
+ //m_nJumpVal=12 ; // for now always jump to light 0
+ //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]) ;
+ //m_nJumpVal=13 ;
+ //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]));
+
+ //m_pCamera->setPosition(166, 222, -111) ;
+ //m_pCamera->setDirection(0.707, 0, -0.707) ;
+
+ //m_pCamera->setPosition(m_Q3Map->m_pLight[0].Position[0], m_Q3Map->m_pLight[0].Position[1], m_Q3Map->m_pLight[0].Position[2]) ;
+ //m_pCamera->setDirection(m_Q3Map->m_pLight[0].Direction[0], m_Q3Map->m_pLight[0].Direction[1], m_Q3Map->m_pLight[0].Direction[2]) ;
+ //m_pCamera->setFOVy( Degree(m_Q3Map->m_pLight[0].Angle ) ) ;
+
+ //m_pCamera->setDirection(m_pLight[m_nJumpVal].Direction[0], m_pLight[m_nJumpVal].Direction[1], m_pLight[m_nJumpVal].Direction[2]) ;
+ // 880 120 -340
+ //m_pCamera->lookAt(Vector3(880,120,-340));
+ //m_pCamera->lookAt(Vector3(915,155,-340));
+
+
+ m_pCamera->setPosition(600, 200, -250) ;
+ //m_pCamera->setDirection(1.0, 0.0, 0.0) ;
+ m_pCamera->lookAt(700, 200, -450);
+
+
+
+ }
+ }
+ else
+ m_nJumpToggle=0 ;
+
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_L))
+ {
+ if(m_nLoadToggle==0)
+ {
+ UnloadMap(false) ;
+ nMap++ ;
+ LoadMap() ;
+ //m_nLoadToggle=1 ;
+ }
+ }
+ else
+ m_nLoadToggle=0 ;
+
+
+ // generic toggle for debugging
+ if(m_pKeyboard->isKeyDown(OIS::KC_M))
+ {
+ if(m_nKeyToggle[OIS::KC_M]==0)
+ {
+ m_nKeyToggle[OIS::KC_M]=1 ; // toggle to stop key repeating
+
+ m_nDisplayInfoMode++ ;
+ if(m_nDisplayInfoMode==9)
+ m_nDisplayInfoMode=0 ;
+
+
+
+ }
+ }
+ else
+ m_nKeyToggle[OIS::KC_M]=0 ;
+
+
+
+
+
+ //if(m_pKeyboard->isKeyDown(OIS::KC_K)) m_nVideoRestart=1 ;
+
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_P))
+ {
+ if(m_nPortalToggle==0)
+ {
+ m_nPortalState=1-m_nPortalState ;
+ m_nPortalToggle=1 ;
+ }
+ }
+ else
+ m_nPortalToggle=0 ;
+
+ if(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
+ {
+ m_bShutDownOgre = true;
+ }
+
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+//shutdown
+// the dynamic memory deletes are all safe, so it's ok to try and delete them even if they don't exist.
+void OgreFramework::UnloadMap(bool bShutdown)
+{
+
+ //if(!bShutdown) DestroyRTTAssets() ;
+
+ //if(ResourceGroupManager::getSingleton().isResourceGroupLoaded("Raw Bsp"))
+ // ResourceGroupManager::getSingleton().clearResourceGroup("Raw Bsp") ;
+
+
+ // only do if there was a definitely a map loaded.
+ if(m_nMapLoaded)
+ {
+ char chSceneNodeName[1024] ;
+ // make sure all the zone nodes are re-attached to the root node or they won't get deleted
+ for(int nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
+ {
+ // Opaque nodes
+ if(m_nOpaqueNodeUsed[nZone]) // only do this if the node actually exists
+ {
+ if(!m_pOpaqueNode[nZone]->isInSceneGraph())
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
+
+ sprintf(chSceneNodeName, "Opaque%05i", nZone) ;
+ m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
+
+ }
+
+ // Trans nodes
+ if(m_nTransNodeUsed[nZone]) // only do this if the node actually exists
+ {
+ if(!m_pTransNode[nZone]->isInSceneGraph())
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
+
+ sprintf(chSceneNodeName, "Trans%05i", nZone) ;
+ m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
+
+ }
+
+ // Lamp nodes
+ if(m_nLampNodeUsed[nZone]) // only do this if the node actually exists
+ {
+ if(!m_pLampNode[nZone]->isInSceneGraph())
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
+
+ sprintf(chSceneNodeName, "Lamp%05i", nZone) ;
+ m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
+
+ }
+
+ // Glow nodes
+ if(m_nGlowNodeUsed[nZone]) // only do this if the node actually exists
+ {
+ if(!m_pGlowNode[nZone]->isInSceneGraph())
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
+
+ sprintf(chSceneNodeName, "Glow%05i", nZone) ;
+ m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
+
+ }
+
+ }
+
+
+ // reattach all entity scenenodes.
+ int nLoop=0 ;
+ int nSubMesh=0 ;
+ int nMaxSubMesh=0 ;
+ for(nLoop=0 ; nLoop<m_nMaxEntity ; nLoop++)
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[nLoop].pMasterNode) ;
+
+ }// end if map loaded
+
+
+ // free ogre stuff
+ //Ogre::ResourceGroupManager::getSingleton().clearResourceGroup(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) ;
+
+ //Ogre::ResourcePtr RTT=Ogre::TextureManager::getSingleton().getByName("RttTex") ;
+ //Ogre::TextureManager::getSingleton().remove(RTT) ;
+
+ //RTT_Texture->unload() ;
+
+
+
+
+
+
+
+ //m_pSceneMgr->clearScene() ;
+ m_pSceneMgr->getRootSceneNode()->removeAndDestroyAllChildren() ; // destroy all scenenodes
+
+ m_pSceneMgr->destroyAllEntities() ;
+ m_pSceneMgr->destroyAllLights() ;
+ m_pSceneMgr->destroyAllManualObjects() ;
+
+
+ /*
+ // unload all the meshes
+ int nMaxMesh=m_nZoneMOStart[m_Q3Map->m_nMaxZone] ;
+ int nMesh=0 ;
+ for(nMesh=0 ; nMesh<nMaxMesh ; nMesh++)
+ {
+ m_pSceneMgr->destroyEntity(m_pZoneEntity[nMesh]) ;
+ //m_pZoneMesh[nMesh]->cleanupDictionary() ;
+ //m_pZoneMesh[nMesh]->unload() ;
+
+
+ }
+ */
+
+ MeshManager::getSingleton().removeAll() ; // this destroys all the meshes
+
+
+
+ //OFBug.MessageInt(333) ;
+ //Ogre::TextureManager::getSingleton().unloadAll() ;
+ //Ogre::TextureManager::getSingleton().removeAll() ;
+
+ //Ogre::MaterialManager::getSingleton().unloadAll() ;
+ //Ogre::MaterialManager::getSingleton().removeAll() ;
+
+
+
+
+
+ //SetupResourceLocations() ;
+
+ // delete our array of Zone group manual objects
+ //CHECKDELETE_ARRAY( m_pZoneMO ) ;
+ CHECKDELETE_ARRAY( m_pZoneMesh, NEW_CHECK_m_pZoneMesh ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntity, NEW_CHECK_m_pZoneEntity ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterialType, NEW_CHECK_m_pZoneEntityMaterialType ) ;
+
+
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Shadow, NEW_CHECK_m_pZoneEntityMaterial_Shadow ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeFront, NEW_CHECK_m_pZoneEntityMaterial_ShadeFront ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeBack, NEW_CHECK_m_pZoneEntityMaterial_ShadeBack ) ;
+
+ int nPTex=0 ;
+ for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+ {
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Base[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Base ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Fast[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Fast ) ;
+ }
+
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Black, NEW_CHECK_m_pZoneEntityMaterial_Black ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShColour, NEW_CHECK_m_pZoneEntityMaterial_DfShColour ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShPosition, NEW_CHECK_m_pZoneEntityMaterial_DfShPosition ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShDiffuse, NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse ) ;
+ //CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DSNormal ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShFuncTNB, NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShSpecular, NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShEmissive, NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive ) ;
+ //CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShData ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShMix, NEW_CHECK_m_pZoneEntityMaterial_DfShMix ) ;
+
+ ////////////////////////////////////////////////////////
+ CHECKDELETE_ARRAY( m_pEntityInfo, NEW_CHECK_m_pEntityInfo ) ;
+ CHECKDELETE_ARRAY( m_pVisibleEntity, NEW_CHECK_m_pVisibleEntity ) ;
+ CHECKDELETE_ARRAY( m_pFrustumEntity, NEW_CHECK_m_pFrustumEntity ) ;
+
+
+ // was leaking before, but this seems to have fixed things.
+ Ogre::ResourceGroupManager::getSingleton().clearResourceGroup(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) ;
+
+ // delete our debug light manualobjects/zones
+// CHECKDELETE_ARRAY( m_pLightMO ) ;
+
+// CHECKDELETE_ARRAY( m_pPortalMO ) ;
+// CHECKDELETE_ARRAY( m_pPortalNode ) ;
+
+ // free our dynamic memory
+ if(m_Q3Map)
+ {
+ m_Q3Map->~Q3Map() ; // get rid of all the m_Q3Map stuff
+ CHECKDELETE_POINTER( m_Q3Map, NEW_CHECK_m_Q3Map) ;
+ m_Q3Map=NULL ;
+ }
+
+ if(m_bRawBspFileIsLoaded)
+ {
+ //m_pRawBspFile->unload() ;
+ CHECKDELETE_ARRAY(m_pRawBspFile, NEW_CHECK_m_pRawBspFile ) ;
+ m_bRawBspFileIsLoaded=false ;
+ }
+
+ // indicate that there is no map.
+ m_nMapLoaded=0 ;
+
+
+
+
+ int nCheck=0 ;
+ for(nCheck=0 ; nCheck<MAX_NEW_CHECK ; nCheck++)
+ if(m_nNewCheck[nCheck]!=0)
+ {
+ sprintf(m_chBug, "MEMORY LEAK: NewCheck %i, NewCount %i", nCheck, m_nNewCheck[nCheck]) ;
+ m_pLog->logMessage(m_chBug) ;
+ }
+
+
+ //OFBug.MessageInt(333) ;
+ //Sleep(50) ;
+}
+
+
+
+
+
+
+
+
+ /***********************************************************************************************************\
+
+ LOAD MAP
+
+ \***********************************************************************************************************/
+
+
+
+
+int OgreFramework::LoadMap(void)
+{
+ m_pLog->logMessage("LoadMap.") ;
+
+
+
+ ZeroMemory((void*)m_nKeyToggle, sizeof(m_nKeyToggle)) ; // good place to clear the keytoggle just in case
+
+ m_pLog->logMessage("Pre InitAllResourceGroups.") ;
+ Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+ m_pLog->logMessage("Post InitAllResourceGroups.") ;
+
+ // setup the clear material
+ pClearMaterial=MaterialManager::getSingleton().getByName("Clear") ;
+
+
+ //CreateRTTAssets() ;
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ m_pDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
+ m_pDebugOverlay->show();
+
+ //m_MapName="test04e.bsp" ;
+ //m_MapName="test04g.bsp" ;
+ //m_MapName="test03f.bsp" ;
+
+ //m_MapName="testnew00a.bsp" ;
+ //m_MapName="test04gNew.bsp" ;
+
+ //m_MapName="test10a.bsp" ;
+ m_MapName="testmap06.bsp" ;
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////
+ // Load the file, get the data
+
+
+
+ // open the stream to the bsp
+ Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(m_MapName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
+
+ // create memory to hold the bsp
+ size_t Size = stream->size() ;
+ m_pRawBspFile= new char[Size] ;
+ if( m_pRawBspFile==NULL)
+ { m_pLog->logMessage("Error loading map: Initial load out of memory.") ; UnloadMap(false) ; return 0 ; }
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pRawBspFile]++ ; }
+
+ // stream bsp into memory
+ stream->read((void*)m_pRawBspFile, Size) ;
+
+ // close the stream, don't need it anymore
+ stream->close() ;
+
+ // indicate that the raw bsp is loaded
+ m_bRawBspFileIsLoaded=true ;
+
+
+
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////
+ // Setup Q3Map
+
+ m_Q3Map=new Q3Map();
+ if(m_Q3Map==NULL)
+ { m_pLog->logMessage("Error loading map: New Map.") ; UnloadMap(false) ; return 0 ; }
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_Q3Map]++ ; }
+
+
+
+ m_pLog->logMessage("pre ParseMap") ;
+
+ // process the bsp, log errors and fail if needed.
+ switch(m_Q3Map->ParseAndTriangulateMap( m_pRawBspFile, Size ) )
+ {
+ case ERROR_ParseMap: m_pLog->logMessage("Error loading map: Parse Map.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_ParseEntities: m_pLog->logMessage("Error loading map: Parse Entities.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_AllocateVertex: m_pLog->logMessage("Error loading map: Allocate Vertex.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_AllocateTriangle: m_pLog->logMessage("Error loading map: Allocate Triangle.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_InitializeFaces: m_pLog->logMessage("Error loading map: Initialize Faces") ; UnloadMap(false) ; return 0 ;
+ case ERROR_ConvertFaces: m_pLog->logMessage("Error loading map: Convert Faces.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_ConvertPatches: m_pLog->logMessage("Error loading map: Convert Patches.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_ConvertTexLamp: m_pLog->logMessage("Error loading map: Convert TexLamps.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_ConvertLamps: m_pLog->logMessage("Error loading map: Convert Lamps.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_ConvertLampGlow: m_pLog->logMessage("Error loading map: Convert Lamp Glow.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_ConvertLightGlow: m_pLog->logMessage("Error loading map: Convert Light Glow.") ; UnloadMap(false) ; return 0 ;
+ case ERROR_AssignTriangles: m_pLog->logMessage("Error loading map: Assign Triangles") ; UnloadMap(false) ; return 0 ;
+ case ERROR_SortTriangles: m_pLog->logMessage("Error loading map: Sort Triangles") ; UnloadMap(false) ; return 0 ;
+ case ERROR_SetupTransTextures: m_pLog->logMessage("Error loading map: Setup Trans Textures") ; UnloadMap(false) ; return 0 ;
+ case ERROR_SortGroups: m_pLog->logMessage("Error loading map: Sort Groups") ; UnloadMap(false) ; return 0 ;
+ }
+
+ m_pLog->logMessage("post ParseMap") ;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////
+ // use the triangles to build our zone/texture manualObjects, which make up the map
+ if(!ConstructMapFromTriangles()){ m_pLog->logMessage("Error loading map: Construct Map") ; UnloadMap(false) ; return 0 ; }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // delete all the stuff that was only needed for parsing the bsp and converting it into manaulObjects.
+ m_Q3Map->FreeParseMem() ;
+
+
+
+
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////
+ // Create the scenenodes for the zones and attach the manualObjects
+
+ int nZone=0 ;
+ char chSceneNodeName[1024] ;
+ int nMO=0 ;
+ int nZGStart=0 ;
+ int nZGEnd=0 ;
+
+ char chMessage[1024] ;
+ sprintf(chMessage, "Max Zones %i", m_Q3Map->m_nMaxZone) ; m_pLog->logMessage(chMessage) ;
+ for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
+ {
+ //sprintf(chMessage, "Zone %i Top", nZone) ; m_pLog->logMessage(chMessage) ;
+
+
+ // create Opaque node if needed
+ if(m_nOpaqueNodeUsed[nZone])
+ {
+ sprintf(chSceneNodeName, "Opaque%05i", nZone) ;
+ m_pOpaqueNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
+ }
+
+ // create Trans node if needed
+ if(m_nTransNodeUsed[nZone])
+ {
+ sprintf(chSceneNodeName, "Trans%05i", nZone) ;
+ m_pTransNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
+ }
+
+ // create Lamp node if needed
+ if(m_nLampNodeUsed[nZone])
+ {
+ sprintf(chSceneNodeName, "Lamp%05i", nZone) ;
+ m_pLampNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
+ }
+
+ // create Glow node if needed
+ if(m_nGlowNodeUsed[nZone])
+ {
+ sprintf(chSceneNodeName, "Glow%05i", nZone) ;
+ m_pGlowNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
+ }
+
+ // get start and end of this zone's batches.
+ // If there's none, the start and end will be the same. (don't have to worry about checking for m_pZoneMO[nZone]==NULL)
+ nZGStart = m_nZoneMOStart[nZone] ;
+ nZGEnd = m_nZoneMOStart[nZone+1] ;
+
+ //sprintf(chMessage, " Zone %i, ZGStart %i, ZGEnd %i", nZone, nZGStart, nZGEnd) ; m_pLog->logMessage(chMessage) ;
+
+ for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+ {
+ //sprintf(chMessage, " Zone %i, nMO %i", nZone, nMO) ; m_pLog->logMessage(chMessage) ;
+
+ // attach the entity to the appropriate node
+
+ if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+ m_pOpaqueNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
+ else
+ if(m_pZoneEntityMaterialType[nMO]==MAT_GEL)
+ m_pTransNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
+ else
+ if(m_pZoneEntityMaterialType[nMO]==MAT_LAMP)
+ m_pLampNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
+ else
+ if(m_pZoneEntityMaterialType[nMO]==MAT_GLOW)
+ m_pGlowNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
+ }
+
+ }
+
+
+ // add the game entities
+ if(!SetupGameEntities()) { m_pLog->logMessage("Error loading map: Setup Entities") ; UnloadMap(false) ; return 0 ; }
+
+
+ // prior to the first frame, all zone scenenodes are detached.
+ m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Setup the lights
+
+
+
+
+ initLight() ;
+
+ //if(m_nDebugLightBox)
+ // AddLightCullingBoxes() ;
+
+
+ //if(m_nPortalDebug)
+ // AddPortalBoxes() ;
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////
+ // misc finalization of the map
+
+ m_nCameraZone=-1 ; // indicate that we need to look up the zone the player is in.
+ m_nCameraZoneL=-1 ;
+ m_nCameraZoneR=-1 ;
+
+ m_nMapLoaded=1 ; // map was loaded ok
+
+
+
+ // set the camera's start position here.
+ // I tried setting it during startup, but for some strange reason it didn't work IF the camera was in a zone
+ // but was ok if the camera started outside a zone. Bit of a mystery... but it makes more sense to set it here anyway.
+ m_pCamera->setPosition(Vector3(0, 0, 0));
+
+ if(m_Q3Map->m_nLightMax>0) // make sure there's at least one light before we point to it!
+ 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])) ;
+
+
+
+
+ if(m_nGoggleMode==GOGGLE_MODE_TEST)
+ CreateGogglesTestImage() ; // create the test goggles
+ else
+ if(m_nGoggleMode==GOGGLE_MODE_ON)
+ CreateGoggles() ; // create the stereo goggles
+
+
+ SetupParticles() ;
+
+
+ m_pLog->logMessage("LoadMap bottom.") ;
+
+ // reset the game timer
+ m_GameTime=0.0 ;
+ m_nFrame=0 ;
+
+
+
+ //OFBug.MessageInt(m_nNewCount) ;
+
+ return 1 ;
+}
+
+//''
+int OgreFramework::SetupParticles()
+{
+ ParticleSystem::setDefaultNonVisibleUpdateTimeout(5); // set nonvisible timeout
+
+
+
+ // create some nice fireworks and place it at the origin
+ //m_ps = m_pSceneMgr->createParticleSystem("Fireworks", "particle/fallspark00");
+ m_ps = m_pSceneMgr->createParticleSystem("Fireworks", "particle/spark00");
+ m_pParticleNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("ParticleNode") ;
+ m_pParticleNode->attachObject(m_ps) ;
+
+ //m_pParticleNode->setPosition(360.0f, 360.0f, -860.0f) ;
+ m_pParticleNode->setPosition(586.0f, 228.0f, -520.0f) ;
+
+
+ return 1 ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// take the sorted list of triangles and contruct our Zone manualObjects array, m_pZoneMO, etc
+// and setup all the materials.
+int OgreFramework::ConstructMapFromTriangles(void)
+{
+
+
+ int nVert=0 ;
+ int nMaxVertex=0 ;
+
+ float flPosX=0.0f ;
+ float flPosY=0.0f ;
+ float flPosZ=0.0f ;
+ float flNormX=0.0f ;
+ float flNormY=0.0f ;
+ float flNormZ=0.0f ;
+ float flTexU=0.0f ;
+ float flTexV=0.0f ;
+
+ float flLampPosX=0.0f ;
+ float flLampPosY=0.0f ;
+ float flLampPosZ=0.0f ;
+ float flLampBrightness=0.0f ;
+ float flLampR=0.0f ;
+ float flLampG=0.0f ;
+ float flLampB=0.0f ;
+
+ int nVertA=0 ;
+ int nVertB=0 ;
+ int nVertC=0 ;
+
+ char chMessage[1024] ;
+
+ int nZone=0 ;
+ char chManualName[1024] ; // name for manual objects we create
+ char chMeshName[1024] ;
+
+ int nTriangle=0 ;
+ int nStart=0 ;
+ int nEnd=0 ;
+ int nMaterial=0 ;
+ int nGroup=0 ;
+ int nTri=0 ;
+ int nPos=0 ;
+
+ ZeroMemory((void*)m_nOpaqueNodeUsed, sizeof(m_nOpaqueNodeUsed)) ; // set all as unused
+ ZeroMemory((void*)m_nTransNodeUsed, sizeof(m_nTransNodeUsed)) ; // set all as unused
+ ZeroMemory((void*)m_nLampNodeUsed, sizeof(m_nLampNodeUsed)) ; // set all as unused
+ ZeroMemory((void*)m_nGlowNodeUsed, sizeof(m_nGlowNodeUsed)) ; // set all as unused
+
+ char chMaterial_Base[1024] ;
+ MaterialPtr pMaterial_Base ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
+
+ char chMaterial_Fast[1024] ;
+ MaterialPtr pMaterial_Fast ; // faster version of the base, mainly non-coloured shadowning.
+
+ char chMaterial_Black[1024] ;
+ MaterialPtr pMaterial_Black ; // just plain black, or black with alpha testing.
+
+ char chMaterial_DfShColour[1024] ;
+ MaterialPtr pMaterial_DfShColour ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
+
+
+ char chMaterial_Shadow[1024] ;
+ MaterialPtr pMaterial_Shadow ;
+
+ char chMaterial_ShadeFront[1024] ;
+ MaterialPtr pMaterial_ShadeFront ;
+
+ char chMaterial_ShadeBack[1024] ;
+ MaterialPtr pMaterial_ShadeBack ;
+
+ char chMaterial_DfShPosition[1024] ;
+ MaterialPtr pMaterial_DfShPosition ;
+
+ char chMaterial_DfShDiffuse[1024] ;
+ MaterialPtr pMaterial_DfShDiffuse ;
+
+ //char chMaterial_DSNormal[1024] ;
+ //MaterialPtr pMaterial_DSNormal ;
+
+ char chMaterial_DfShFuncTNB[1024] ;
+ MaterialPtr pMaterial_DfShFuncTNB ;
+
+ char chMaterial_DfShSpecular[1024] ;
+ MaterialPtr pMaterial_DfShSpecular ;
+
+ char chMaterial_DfShEmissive[1024] ;
+ MaterialPtr pMaterial_DfShEmissive ;
+
+ //char chMaterial_DfShData[1024] ;
+ //MaterialPtr pMaterial_DfShData ;
+
+ char chMaterial_DfShMix[1024] ;
+ MaterialPtr pMaterial_DfShMix ;
+
+ char chCompare[1024] ;
+
+ // for calculating bounds of mesh
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+ float flMaxZ=0.0f ;
+ float flMidX=0.0f ;
+ float flMidY=0.0f ;
+ float flMidZ=0.0f ;
+ float flDisX=0.0f ;
+ float flDisY=0.0f ;
+ float flDisZ=0.0f ;
+ float flRadius=0.0f ;
+ AxisAlignedBox AABB ;
+ unsigned short src, dest; // for tangent vectors
+
+
+ // Work out how many manual objects we are going to need. We need one for every group within every material within every zone.
+ // Groups tend to all be 0 except for transparent triangles which have different groups within the same material/zone,
+ // due to the need to sort and render transparent things in a specific depth order relative to the camera.
+
+
+ int nMOCount=0 ;
+ nMaterial=-1 ;
+ nZone=-1 ;
+ nGroup=-1 ;
+
+ // loop through all triangles to count how many manual objects we'll need.
+ for(nTri=0 ; nTri<m_Q3Map->m_nTriangleMax ; nTri++)
+ {
+
+ if(m_Q3Map->m_pTriangle[nTri].Zone!=nZone) // found a new zone
+ {
+ nZone=m_Q3Map->m_pTriangle[nTri].Zone ;
+ nMaterial=m_Q3Map->m_pTriangle[nTri].Texture ;
+ nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
+ nMOCount++ ;
+ }
+ else
+ if(m_Q3Map->m_pTriangle[nTri].Texture!=nMaterial) // found a new material within the current zone
+ {
+ nMaterial=m_Q3Map->m_pTriangle[nTri].Texture ;
+ nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
+ nMOCount++ ;
+ }
+ else
+ if(m_Q3Map->m_pTriangle[nTri].Group!=nGroup) // found a new group within the current material within the current zone
+ {
+ nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
+ nMOCount++ ;
+ }
+
+ }// end for tri
+
+
+
+ // create the manualobject array for our zones and materials
+ m_pZoneMO = new Ogre::ManualObject*[nMOCount] ;
+ if(m_pZoneMO==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneMO]++ ; }
+
+ m_pZoneMesh = new Ogre::MeshPtr[nMOCount] ;
+ if(m_pZoneMesh==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneMesh]++ ; }
+
+ // our entities for the meshes
+ m_pZoneEntity = new Ogre::Entity*[nMOCount] ;
+ if(m_pZoneEntity==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntity]++ ; }
+
+ // need to keep track of which entities are transparent
+ m_pZoneEntityMaterialType = new int[nMOCount] ;
+ if(m_pZoneEntityMaterialType==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterialType]++ ; }
+ ZeroMemory((void*)m_pZoneEntityMaterialType, nMOCount*sizeof(int)) ; // set all as non-transparent
+
+
+ int nPTex=0 ;
+ for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+ {
+ // our base materials for the meshes
+ m_pZoneEntityMaterial_Base[nPTex] = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_Base[nPTex]==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Base]++ ; }
+
+ // our fast materials for the meshes
+ m_pZoneEntityMaterial_Fast[nPTex] = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_Fast[nPTex]==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Fast]++ ; }
+ }
+
+ // our black materials for the meshes
+ m_pZoneEntityMaterial_Black = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_Black==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Black]++ ; }
+
+ // our base materials for the meshes
+ m_pZoneEntityMaterial_DfShColour = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_DfShColour==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShColour]++ ; }
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_Shadow = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_Shadow==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Shadow]++ ; }
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_ShadeFront = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_ShadeFront==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_ShadeFront]++ ; }
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_ShadeBack = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_ShadeBack==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_ShadeBack]++ ; }
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_DfShPosition = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_DfShPosition==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShPosition]++ ; }
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_DfShDiffuse = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_DfShDiffuse==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse]++ ; }
+
+ // materials for the meshes
+ //m_pZoneEntityMaterial_DSNormal = new Ogre::MaterialPtr[nMOCount] ;
+ //if(m_pZoneEntityMaterial_DSNormal==NULL) return 0 ; // fail, out of mem
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_DfShFuncTNB = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_DfShFuncTNB==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB]++ ; }
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_DfShSpecular = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_DfShSpecular==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular]++ ; }
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_DfShEmissive = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_DfShEmissive==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive]++ ; }
+
+
+ // materials for the meshes
+ //m_pZoneEntityMaterial_DfShData = new Ogre::MaterialPtr[nMOCount] ;
+ //if(m_pZoneEntityMaterial_DfShData==NULL) return 0 ; // fail, out of mem
+
+ // materials for the meshes
+ m_pZoneEntityMaterial_DfShMix = new Ogre::MaterialPtr[nMOCount] ;
+ if(m_pZoneEntityMaterial_DfShMix==NULL)
+ return 0 ; // fail, out of mem
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShMix]++ ; }
+
+
+ // 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
+ 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.
+ if(pVertIndex==NULL) //{ CHECKDELETE_ARRAY( m_pZoneMO ) ; return 0 ; } // fail, out of mem
+ return 0 ;
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_pVertIndex]++ ; }
+
+
+
+
+
+ // go through all the zones and create their manualobjects in m_pZoneMO, one for each material
+ int nMOIndex=0 ;
+ for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
+ {
+ m_nZoneTriangleCount[nZone]=0 ; // just for our stats
+
+
+ m_nZoneMOStart[nZone]=nMOIndex ; // record where we start from.
+
+ // because the triangles have been sorted in order of zone, if there are any triangles in this zone
+ // then nTriangle will already be on the first example. However it could be there is a zone that contains
+ // no triangles. If we have such an empty zone, we don't create any manual object for it and set its pointer
+ // to NULL.
+
+ if(m_Q3Map->m_pTriangle[nTriangle].Zone!=nZone)
+ {
+ m_pZoneMO[nMOIndex]=NULL ;
+ continue ;
+ //break ;
+ }
+
+
+
+
+ // scan through all triangles in this zone
+ while((nTriangle<m_Q3Map->m_nTriangleMax) && (m_Q3Map->m_pTriangle[nTriangle].Zone==nZone))
+ {
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // start adding a begin/end block of all triangles in a zone with the same material/group
+ //
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+ nMaterial=m_Q3Map->m_pTriangle[nTriangle].Texture ;
+ nGroup=m_Q3Map->m_pTriangle[nTriangle].Group ;
+
+
+
+
+ // create the zone's manualobject
+ sprintf(chManualName, "ZoneMO_%04i_%04i_%05i", nZone, nMaterial, nTriangle) ;
+ m_pZoneMO[nMOIndex]=m_pSceneMgr->createManualObject(chManualName) ;
+
+
+
+ // scan forward to find the end of this block of triangles with the same texture and group
+ nEnd=nTriangle+1 ;
+ while(
+ (nEnd<m_Q3Map->m_nTriangleMax)
+ &&(m_Q3Map->m_pTriangle[nEnd].Zone==nZone)
+ &&(m_Q3Map->m_pTriangle[nEnd].Texture==nMaterial)
+ &&(m_Q3Map->m_pTriangle[nEnd].Group==nGroup)
+ )
+ nEnd++ ;
+
+ // copy the material name.
+ // q3 texture names are a max of 64 characters ( Q3NAMESIZE ) and may not be null terminated. They have no extension either.
+ nPos=-1 ;
+ while((++nPos<Q3NAMESIZE) && (m_Q3Map->m_pTexture[nMaterial].name[nPos]!=' ') && (m_Q3Map->m_pTexture[nMaterial].name[nPos]!='\0'))
+ chMaterial_Base[nPos]=m_Q3Map->m_pTexture[nMaterial].name[nPos] ;
+
+ // make sure name is null terminated
+ chMaterial_Base[nPos]='\0' ;
+
+
+
+ //..
+
+ //if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_ShinyGlassPlateTL") ;
+ //if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_Prototype") ;
+ //if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_Prototype") ;
+ if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_glassred") ;
+ if(strcmp(chMaterial_Base, "textures/common/exptex2")==0) strcpy(chMaterial_Base, "GEL_GreyGlass") ;
+ if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "ALPHAPF_DSCE_Prototype") ;
+ //if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;
+ //if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "ALPHAPF_DS_alphaplategreen") ;
+
+
+
+ // if the material is a lamp material we need to specify either an OpenGl or Direct3D version
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[12]='\0' ;
+ if(strcmp("lights/lamp_", chCompare)==0) // material is LAMP
+ {
+ if(m_IsOpenGL)
+ strcat(chMaterial_Base, "_ogl") ;
+ else
+ strcat(chMaterial_Base, "_d3d") ;
+
+ }
+
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[17]='\0' ;
+ if(strcmp("lights/lamp2pass_", chCompare)==0) // material is LAMP, 2 pass version
+ {
+ if(m_IsOpenGL)
+ strcat(chMaterial_Base, "_ogl") ;
+ else
+ strcat(chMaterial_Base, "_d3d") ;
+ }
+
+
+
+ // check that this material script exists, if not set to the default
+ pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
+ if(pMaterial_Base.isNull())
+ {
+ strcat(chMaterial_Base, " *** MISSING ***") ;
+ OFBug.LogAddCR(chMaterial_Base) ;
+
+ //sprintf(chMessage, "Missing material, using default: %s", chMaterial_Base) ;
+ //m_pLog->logMessage(chMessage);
+
+ /*
+ switch(rand()%6)
+ {
+ case 0: strcpy(chMaterial_Base, "OPAQUE_DSC_Plate2x2A") ; break ;
+ case 1: strcpy(chMaterial_Base, "OPAQUE_DSC_HexColourA") ; break ;
+ case 2: strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ; break ;
+ case 3: strcpy(chMaterial_Base, "OPAQUE_DSC_FloorA") ; break ;
+ case 4: strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimUD_A") ; break ;
+ case 5: strcpy(chMaterial_Base, "OPAQUE_DSCE_TechRadar") ; break ;
+ }
+ */
+
+ //strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;
+
+ //strcpy(chMaterial_Base, "OPAQUE_DSC_Plate2x2A") ;
+ //strcpy(chMaterial_Base, "OPAQUE_DSC_HexColourA") ;
+ //strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;
+ //strcpy(chMaterial_Base, "OPAQUE_DSC_FloorA") ;
+ strcpy(chMaterial_Base, "textures/metaltech/OPAQUE_DSCE_TechRadar") ;
+ //strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimA") ;
+ //strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimB") ;
+
+ //strcpy(chMaterial_Base, "Standard_Normal") ;
+ //strcpy(chMaterial_Base, "test") ;
+ //strcpy(chMaterial_Base, "metalN") ;
+ //strcpy(chMaterial_Base, "OPAQUE_DSC_Prototype") ;
+
+ //strcpy(chMaterial_Base, "textures/common/exptex") ;
+ //strcpy(chMaterial_Base, "metalN_DSNormal") ;
+ //strcpy(chMaterial_Base, "metalN_DfShFuncTNB") ;
+ //strcpy(chMaterial_Base, "metalN_DfShDiffuse") ;
+ //strcpy(chMaterial_Base, "metalN_DfShPosition") ;
+ //strcpy(chMaterial_Base, "metalD") ;
+ //strcpy(chMaterial_Base, "metalR") ;
+ //strcpy(chMaterial_Base, "WonderShader_Lim3_Fast") ;
+ //strcpy(chMaterial_Base, "reliefMaterial") ;
+ //strcpy(chMaterial_Base, "tute02") ;reliefMaterial
+ //strcpy(chMaterial_Base, "Examples/OffsetMapping/Specular") ;
+ pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
+ }
+ else
+ OFBug.LogAddCR(chMaterial_Base) ;
+
+
+
+ if(nMOIndex==20)
+ {
+ sprintf(m_chBug, "****** %s *******", chMaterial_Base) ;
+ m_pLog->logMessage(m_chBug);
+ }
+
+
+
+
+ // setup whether this material and it's entities are transparent or whatever
+
+ if(strstr(chMaterial_Base, "OPAQUE")!=NULL) // material and its entity are OPAQUE
+ {
+ m_nOpaqueNodeUsed[nZone]=1 ;
+ m_pZoneEntityMaterialType[nMOIndex]=MAT_OPAQUE ; // note that the derived entity will be opaque
+ }
+ else
+ {
+
+ if(strstr(chMaterial_Base, "ALPHAPF")!=NULL) // material and its entity are ALPHAPF
+ {
+ m_nOpaqueNodeUsed[nZone]=1 ;
+ m_pZoneEntityMaterialType[nMOIndex]=MAT_OPAQUE ; // note that the derived entity will be opaque
+ }
+ else
+ {
+
+ if(strstr(chMaterial_Base, "GEL")!=NULL) // material and its entity are GEL
+ {
+ m_nTransNodeUsed[nZone]=1 ;
+ m_pZoneEntityMaterialType[nMOIndex]=MAT_GEL ; // note that the derived entity will be transparent
+ }
+ else
+ {
+
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[12]='\0' ;
+ if(strcmp("lights/lamp_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
+ {
+ m_nLampNodeUsed[nZone]=1 ;
+ m_pZoneEntityMaterialType[nMOIndex]=MAT_LAMP ; // note that the derived entity will be lamp
+ }
+ else
+ {
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[17]='\0' ;
+ if(strcmp("lights/lamp2pass_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
+ {
+ m_nLampNodeUsed[nZone]=1 ;
+ m_pZoneEntityMaterialType[nMOIndex]=MAT_LAMP ; // note that the derived entity will be lamp
+ }
+ else
+ {
+
+ if(strstr(chMaterial_Base, "GLOW_")!=NULL) // material and its entity are GLOW
+ {
+ m_nGlowNodeUsed[nZone]=1 ;
+ m_pZoneEntityMaterialType[nMOIndex]=MAT_GLOW ; // note that the derived entity will be glow
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Setup the different material names and pointers needed for various passes
+ //
+ // Lamps need only one material, pMaterial_Base, which is already assigned above, so it skips all this.
+ //
+ // Glow needs two materials, pMaterial_Base plus pMaterial_DfShColour for the coloured gel deferred pass.
+ // However it's better to make a third, and duplicate the pMaterial_Base to pMaterial_Emissive, since
+ // when glow gets rendered on the Emmisive pass it would be odd to switch to the base material instead
+ // of the emmisive.
+ //
+ // Other objects need multiple materials for various different deferred shading and FX passes
+
+ if((m_pZoneEntityMaterialType[nMOIndex]!=MAT_LAMP) && (m_pZoneEntityMaterialType[nMOIndex]!=MAT_GLOW))
+ {
+
+ // material for fast shading
+ strcpy(chMaterial_Fast, chMaterial_Base) ;
+ strcat(chMaterial_Fast, "_Fast") ;
+
+ pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
+ if(pMaterial_Fast.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_Fast) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_Fast, "Fast") ;
+ pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
+ }
+
+ // material for black shading
+ strcpy(chMaterial_Black, chMaterial_Base) ;
+ strcat(chMaterial_Black, "_Black") ;
+ pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
+ if(pMaterial_Black.isNull())
+ {
+ // only issue a warning if this is an alpha testing material, others don't need specialized Black materials
+ if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_Black) ;
+ m_pLog->logMessage(chMessage);
+ }
+
+ strcpy(chMaterial_Black, "Black") ;
+ pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
+ }
+
+ // material for shadow casting
+ strcpy(chMaterial_Shadow, chMaterial_Base) ;
+ strcat(chMaterial_Shadow, "_Shadow") ;
+ pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
+ if(pMaterial_Shadow.isNull())
+ {
+ strcpy(chMaterial_Shadow, "OPAQUE_Shadow") ;
+ pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
+ }
+
+
+
+ // material for shadow casting
+ strcpy(chMaterial_ShadeFront, chMaterial_Base) ;
+ strcat(chMaterial_ShadeFront, "_ShadeFront") ;
+ pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
+ if(pMaterial_ShadeFront.isNull())
+ {
+ // standard opaque ShadeFront.
+ // Transparent surfaces MUST have their own _ShadeFront material or they will not colour light and can interfere with other trans surfaces.
+ strcpy(chMaterial_ShadeFront, "OPAQUE_ShadeFront") ;
+
+ pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
+ }
+
+
+ // material for shadow casting
+ strcpy(chMaterial_ShadeBack, chMaterial_Base) ;
+ strcat(chMaterial_ShadeBack, "_ShadeBack") ;
+ pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
+ if(pMaterial_ShadeBack.isNull())
+ {
+ // standard opaque ShadeBack.
+ // Transparent surfaces MUST have their own _ShadeBack material or they will not colour light and can interfere with other trans surfaces.
+ strcpy(chMaterial_ShadeBack, "OPAQUE_ShadeBack") ;
+
+ pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
+ }
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShColour, chMaterial_Base) ;
+ strcat(chMaterial_DfShColour, "_DfShColour") ;
+ pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+ if(pMaterial_DfShColour.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShColour) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShColour, "DfShColour") ;
+ pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+ }
+
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShPosition, chMaterial_Base) ;
+ strcat(chMaterial_DfShPosition, "_DfShPosition") ;
+ pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
+ if(pMaterial_DfShPosition.isNull())
+ {
+ // only issue a warning if this is an alpha testing material, others don't need specialized DfShPosition materials
+ if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShPosition) ;
+ m_pLog->logMessage(chMessage);
+ }
+
+ strcpy(chMaterial_DfShPosition, "DfShPosition") ;
+ pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
+ }
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShDiffuse, chMaterial_Base) ;
+ strcat(chMaterial_DfShDiffuse, "_DfShDiffuse") ;
+ pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
+ if(pMaterial_DfShDiffuse.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShDiffuse) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShDiffuse, "DfShDiffuse") ;
+ pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
+ }
+
+ /*
+ // material for deferred shading // UNUSED
+ strcpy(chMaterial_DSNormal, chMaterial_Base) ;
+ strcat(chMaterial_DSNormal, "_DSNormal") ;
+ pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
+ if(pMaterial_DSNormal.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DSNormal) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DSNormal, "DSNormal") ;
+ pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
+ }
+ */
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShFuncTNB, chMaterial_Base) ;
+ strcat(chMaterial_DfShFuncTNB, "_DfShFuncTNB") ;
+ pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
+ if(pMaterial_DfShFuncTNB.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShFuncTNB) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShFuncTNB, "DfShFuncTNB") ;
+ pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
+ }
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShSpecular, chMaterial_Base) ;
+ strcat(chMaterial_DfShSpecular, "_DfShSpecular") ;
+ pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
+ if(pMaterial_DfShSpecular.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShSpecular) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShSpecular, "DfShSpecular") ;
+ pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
+ }
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShEmissive, chMaterial_Base) ;
+ strcat(chMaterial_DfShEmissive, "_DfShEmissive") ;
+ pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+ if(pMaterial_DfShEmissive.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShEmissive) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShEmissive, "DfShEmissive") ;
+ pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+ }
+
+
+ /*
+ // material for deferred shading
+ strcpy(chMaterial_DfShData, chMaterial_Base) ;
+ strcat(chMaterial_DfShData, "_DfShData") ;
+ pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
+ if(pMaterial_DfShData.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShData) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShData, "DfShData") ;
+ pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
+ }
+ */
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShMix, chMaterial_Base) ;
+ strcat(chMaterial_DfShMix, "_DfShMix") ;
+ pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
+ if(pMaterial_DfShMix.isNull())
+ {
+ // Pretty much all materials just use the default mix material,
+ // so don't issue warnings if there isn't a specialized version
+ //sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShMix) ;
+ //m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShMix, "DfShMix") ;
+ pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
+ }
+
+
+
+
+
+ }// end if not MAT_LAMP or MAT_GLOW
+ else
+ if(m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW) // the two materials that glow needs
+ {
+
+ // when I get around to allowing user defined GLOW materials as well as the automatic ones,
+ // this'll be the place to add it.
+ // For now, just the automatically generated lamp/light stuff has a glow.
+
+ // if the base material was "GLOW_lamp"
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[strlen("GLOW_lamp")]='\0' ;
+ if(strcmp("GLOW_lamp", chCompare)==0)
+ {
+ strcpy(chMaterial_DfShColour, "GLOW_lampcol") ;
+ pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+
+ strcpy(chMaterial_DfShEmissive, "GLOW_lamp") ;
+ pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+ }
+ else
+ {
+
+ // if the base material was "GLOW_light"
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[strlen("GLOW_light")]='\0' ;
+ if(strcmp("GLOW_light", chCompare)==0)
+ {
+ strcpy(chMaterial_DfShColour, "GLOW_lightcol") ;
+ pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+
+ strcpy(chMaterial_DfShEmissive, "GLOW_light") ;
+ pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+ }
+
+ }
+ }
+
+
+
+
+
+
+ // work out which vertices we'll need, we don't add every vertex, just used ones.
+ nMaxVertex=0 ;
+ for(nVert=0 ; nVert<m_Q3Map->m_nVertexMax ; nVert++)
+ pVertIndex[nVert]=-1 ; // initialize all verts as unused.
+
+
+ // start defining the manualObject
+ m_pZoneMO[nMOIndex]->begin(chMaterial_Base, RenderOperation::OT_TRIANGLE_LIST) ;
+
+
+ // reset the min max stuff
+ flMinX=flMinY=flMinZ=MINMAXLIMIT ;
+ flMaxX=flMaxY=flMaxZ=-MINMAXLIMIT ;
+
+
+ // add the verts. We avoid repeating the same vert multiple times where it is used by many triangles
+ for(nTri=nTriangle ; nTri<nEnd ; nTri++)
+ for(nVert=0 ; nVert<3 ; nVert++)
+ {
+ if(pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ]==-1) // this vert hasn't been added yet
+ {
+ pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ]=nMaxVertex++ ; // so we can correctly look it up when we add the triangles
+
+ flPosX=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].position[0] ;
+ flPosY=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].position[1] ;
+ flPosZ=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].position[2] ;
+ flNormX=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].normal[0] ;
+ flNormY=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].normal[1] ;
+ flNormZ=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].normal[2] ;
+
+
+
+ // lamps have some different vertex data, also glow
+ // lamp needs colour and also info about the origin, which is stored in the UVs.
+ // glow only needs the colour, but it doesn't hurt to store the orgin too, no harm and simpler code.
+ if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW))
+ {
+ flLampPosX = m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].texcoord[0][0] ;
+ flLampPosY = m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].texcoord[0][1] ;
+ flLampPosZ = m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].texcoord[1][0] ;
+ flLampBrightness= m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].texcoord[1][1] ;
+
+ flLampR=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].color[0]/255.0f ;
+ flLampG=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].color[1]/255.0f ;
+ flLampB=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].color[2]/255.0f ;
+
+ // set the vertex data
+ m_pZoneMO[nMOIndex]->position(flPosX, flPosY, flPosZ) ;
+ m_pZoneMO[nMOIndex]->normal(flNormX, flNormY, flNormZ) ;
+ m_pZoneMO[nMOIndex]->textureCoord(flLampPosX, flLampPosY, flLampPosZ, flLampBrightness) ;
+ m_pZoneMO[nMOIndex]->colour(flLampR, flLampG, flLampB) ;
+
+ }
+ else // non-lamps
+ {
+ flTexU=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].texcoord[0][0] ;
+ flTexV=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ].texcoord[0][1] ;
+
+ // set the vertex data
+ m_pZoneMO[nMOIndex]->position(flPosX, flPosY, flPosZ) ;
+ m_pZoneMO[nMOIndex]->normal(flNormX, flNormY, flNormZ) ;
+ m_pZoneMO[nMOIndex]->textureCoord(flTexU, flTexV) ;
+ }
+
+ // update bounds
+ if(flPosX<flMinX) flMinX=flPosX ;
+ if(flPosY<flMinY) flMinY=flPosY ;
+ if(flPosZ<flMinZ) flMinZ=flPosZ ;
+ if(flPosX>flMaxX) flMaxX=flPosX ;
+ if(flPosY>flMaxY) flMaxY=flPosY ;
+ if(flPosZ>flMaxZ) flMaxZ=flPosZ ;
+
+ }// end if adding vert
+ }
+
+ // add the triangles
+ for(nTri=nTriangle ; nTri<nEnd ; nTri++)
+ {
+ nVertA=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[0] ] ;
+ nVertB=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[1] ] ;
+ nVertC=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[2] ] ;
+ m_pZoneMO[nMOIndex]->triangle(nVertA, nVertC, nVertB) ;
+ m_nZoneTriangleCount[nZone]++ ;
+ //m_pZoneMO[nMOIndex]->triangle(nVertA, nVertB, nVertC) ;
+ }
+
+
+ // all done for this block of material
+ m_pZoneMO[nMOIndex]->end() ;
+ m_pZoneMO[nMOIndex]->setCastShadows(true) ;
+ m_pZoneMO[nMOIndex]->setDynamic(false) ;
+
+ // convert the manualobject to a mesh
+ sprintf(chMeshName, "ZoneMesh_%04i_%04i_%05i", nZone, nMaterial, nTriangle) ;
+ m_pZoneMesh[nMOIndex]= m_pZoneMO[nMOIndex]->convertToMesh(chMeshName);
+
+ // don't need the manual object anymore
+ m_pSceneMgr->destroyManualObject(m_pZoneMO[nMOIndex]) ;
+
+
+ // temp cludge to add thickness
+ flMinX-=1.0f ;
+ flMinY-=1.0f ;
+ flMinZ-=1.0f ;
+ flMaxX+=1.0f ;
+ flMaxY+=1.0f ;
+ flMaxZ+=1.0f ;
+
+ // set axis aligned bounding box of this mesh
+ AABB.setMinimumX(flMinX) ;
+ AABB.setMinimumY(flMinY) ;
+ AABB.setMinimumZ(flMinZ) ;
+ AABB.setMaximumX(flMaxX) ;
+ AABB.setMaximumY(flMaxY) ;
+ AABB.setMaximumZ(flMaxZ) ;
+ m_pZoneMesh[nMOIndex]->_setBounds(AABB, false) ;
+
+ // set bounding sphere of this mesh
+ flDisX=flMaxX-flMinX ;
+ flDisY=flMaxY-flMinY ;
+ flDisZ=flMaxZ-flMinZ ;
+ flRadius=sqrt( flDisX*flDisX + flDisY*flDisY + flDisZ*flDisZ )/2.0 ;
+ m_pZoneMesh[nMOIndex]->_setBoundingSphereRadius(flRadius) ;
+
+
+ //if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassred")==0)
+ // OFBug.MessageFloat(flRadius, flMinX, flMinY, flMinZ, flMaxX, flMaxY, flMaxZ) ;
+
+ //if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassgreen")==0)
+ // OFBug.MessageFloat(flRadius, flMinX, flMinY, flMinZ, flMaxX, flMaxY, flMaxZ) ;
+
+ // calculate tangents for the mesh
+ if((m_pZoneEntityMaterialType[nMOIndex]!=MAT_LAMP) && (m_pZoneEntityMaterialType[nMOIndex]!=MAT_GLOW))// lamps and glow don't need tangent vectors
+ {
+ m_pZoneMesh[nMOIndex]->suggestTangentVectorBuildParams(VES_TANGENT, src, dest) ;
+ m_pZoneMesh[nMOIndex]->buildTangentVectors(VES_TANGENT, src, dest);
+ }
+
+ m_pZoneMesh[nMOIndex]->load() ;
+
+ m_pZoneMesh[nMOIndex]->getSubMesh(0)->generateExtremes(8) ;
+
+ // create an entity for this mesh. We need this so we can change the material during deferred shading
+ m_pZoneEntity[nMOIndex]=m_pSceneMgr->createEntity(m_pZoneMesh[nMOIndex]->getName(), m_pZoneMesh[nMOIndex]->getName()) ;
+
+ // if the entity is a lamp or glow, set its material because they never get changed
+ if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW))
+ m_pZoneEntity[nMOIndex]->setMaterial( pMaterial_Base) ;
+
+
+ //AABB=m_pZoneEntity[nMOIndex]->getBoundingBox() ;
+ //Ogre::Vector3 mn, mx ;
+ //mn=AABB.getMinimum() ;
+ //mx=AABB.getMaximum() ;
+ //if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassred")==0)
+ // OFBug.MessageFloat(mn.x, mn.y, mn.z, mx.x, mx.y, mx.z) ;
+
+
+
+
+
+
+ // store the pointers to the materials of this entity
+ //m_pZoneEntityMaterial_Base[nMOIndex]=pMaterial_Base ;
+ //m_pZoneEntityMaterial_Fast[nMOIndex]=pMaterial_Fast ;
+ m_pZoneEntityMaterial_Black[nMOIndex]=pMaterial_Black ;
+ m_pZoneEntityMaterial_DfShColour[nMOIndex]=pMaterial_DfShColour ;
+ m_pZoneEntityMaterial_Shadow[nMOIndex]=pMaterial_Shadow ;
+ m_pZoneEntityMaterial_ShadeFront[nMOIndex]=pMaterial_ShadeFront ;
+ m_pZoneEntityMaterial_ShadeBack[nMOIndex]=pMaterial_ShadeBack ;
+ m_pZoneEntityMaterial_DfShPosition[nMOIndex]=pMaterial_DfShPosition ;
+ m_pZoneEntityMaterial_DfShDiffuse[nMOIndex]=pMaterial_DfShDiffuse ;
+ //m_pZoneEntityMaterial_DSNormal[nMOIndex]=pMaterial_DSNormal ;
+ m_pZoneEntityMaterial_DfShFuncTNB[nMOIndex]=pMaterial_DfShFuncTNB ;
+ m_pZoneEntityMaterial_DfShSpecular[nMOIndex]=pMaterial_DfShSpecular ;
+ m_pZoneEntityMaterial_DfShEmissive[nMOIndex]=pMaterial_DfShEmissive ;
+ //m_pZoneEntityMaterial_DfShData[nMOIndex]=pMaterial_DfShData ;
+ m_pZoneEntityMaterial_DfShMix[nMOIndex]=pMaterial_DfShMix ;
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ char chNewName[1024] ;
+ for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+ {
+ Ogre::AliasTextureNamePairList AliasList ;
+
+ // check the necessary texture exists
+ //if(TextureManager::getSingleton().getByName(m_Q3Map->m_chSpotlightTexture[nPTex]).isNull())
+ // OFBug.MessageInt(666) ;
+
+
+ AliasList.insert(AliasTextureNamePairList::value_type("projector_tex", m_Q3Map->m_chSpotlightTexture[nPTex]));
+
+
+
+ sprintf(chNewName, "%s_%i", chMaterial_Base, 0) ;
+ m_pZoneEntityMaterial_Base[nPTex][nMOIndex]=pMaterial_Base->clone(chNewName) ;
+ // change the texture unit
+ m_pZoneEntityMaterial_Base[nPTex][nMOIndex]->applyTextureAliases(AliasList) ;
+
+ sprintf(chNewName, "%s_%i", chMaterial_Fast, 0) ;
+ m_pZoneEntityMaterial_Fast[nPTex][nMOIndex]=pMaterial_Fast->clone(chNewName) ;
+ // change the texture unit
+ m_pZoneEntityMaterial_Fast[nPTex][nMOIndex]->applyTextureAliases(AliasList) ;
+
+ }
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+
+ // move to the end of this block of materials
+ nTriangle=nEnd ;
+ nMOIndex++ ;
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // end adding a begin/end block of all triangles in a zone with the same material
+ //
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ }// end scanning triangles in a zone
+
+
+
+ }// end looping through all zones
+
+ m_nZoneMOStart[m_Q3Map->m_nMaxZone]=nMOIndex ; // indicates the end pos of all the manual objects
+
+ CHECKDELETE_ARRAY( pVertIndex, NEW_CHECK_pVertIndex ); // free the vert index memory we used
+
+ CHECKDELETE_ARRAY( m_pZoneMO, NEW_CHECK_m_pZoneMO ) ; // free the manual object memory we used
+ // quick check
+ if(nMOCount!=nMOIndex)
+ {
+ sprintf(chMessage, "ERROR ConstructMap: MOIndex %i does not match MOCount %i", nMOIndex, nMOCount) ;
+ m_pLog->logMessage(chMessage);
+ //CHECKDELETE_ARRAY( m_pZoneMO ) ;
+ CHECKDELETE_ARRAY( m_pZoneMesh, NEW_CHECK_m_pZoneMesh ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntity, NEW_CHECK_m_pZoneEntity ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterialType, NEW_CHECK_m_pZoneEntityMaterialType ) ;
+
+ for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+ {
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Base[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Base ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Fast[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Fast ) ;
+ }
+
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Black, NEW_CHECK_m_pZoneEntityMaterial_Black ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShColour, NEW_CHECK_m_pZoneEntityMaterial_DfShColour ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Shadow, NEW_CHECK_m_pZoneEntityMaterial_Shadow ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeFront, NEW_CHECK_m_pZoneEntityMaterial_ShadeFront ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeBack, NEW_CHECK_m_pZoneEntityMaterial_ShadeBack ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShPosition, NEW_CHECK_m_pZoneEntityMaterial_DfShPosition ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShDiffuse, NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse ) ;
+ //CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DSNormal ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShFuncTNB, NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShSpecular, NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShEmissive, NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive ) ;
+ //CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShData ) ;
+ CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShMix, NEW_CHECK_m_pZoneEntityMaterial_DfShMix ) ;
+
+
+ return 0 ;
+ }
+
+
+ return 1 ;
+
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// setup the game entities
+//
+
+int OgreFramework::SetupGameEntities(void)
+{
+ int nEntity=0 ;
+ char chMeshName[1024] ;
+
+
+ // work out the maximum number of entities we need
+ m_nMaxEntity=10 ;
+ int nHalfMax=m_nMaxEntity/2 ;
+
+
+
+
+ // create the dynamic memory for the entities
+ m_pEntityInfo=new ENTITYINFO[m_nMaxEntity] ;
+ if(m_pEntityInfo==NULL)
+ return 0 ;
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pEntityInfo]++ ; }
+
+ m_pVisibleEntity=new int[m_nMaxEntity] ;
+ if(m_pVisibleEntity==NULL)
+ return 0 ;
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pVisibleEntity]++ ; }
+
+ m_pFrustumEntity=new int[m_nMaxEntity] ;
+ if(m_pFrustumEntity==NULL)
+ return 0 ;
+ else
+ {m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pFrustumEntity]++ ; }
+
+
+
+ // setup materials and default data for the entities
+ for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
+ {
+ //switch(nEntity%3)
+ //{
+ // case 0: strcpy(chMeshName, "robot.mesh") ; break ;
+ // case 1: strcpy(chMeshName, "ninja.mesh") ; break ;
+ // case 2: strcpy(chMeshName, "athene.mesh") ; break ;
+ //}
+
+ strcpy(chMeshName, "robot.mesh") ;
+
+ SetupEntity(nEntity, chMeshName) ;
+ }
+
+
+
+
+ // setup start data for each entity
+ for(nEntity=0 ; nEntity<nHalfMax ; nEntity++)
+ {
+ m_pEntityInfo[nEntity].Postition=Ogre::Vector3(750.0f, 128.0f, -1950.0f-nEntity*40.0f) ;
+ //m_pEntityInfo[nEntity].pMasterNode->setPosition(750.0f, 128.0f, -1950.0f-nEntity*40.0f) ;
+ }
+
+ for(nEntity=nHalfMax ; nEntity<m_nMaxEntity ; nEntity++)
+ {
+ m_pEntityInfo[nEntity].Postition=Ogre::Vector3(590.0f, 128.0f, -320.0f-nEntity*40.0f) ;
+ //m_pEntityInfo[nEntity].pMasterNode->setPosition(590.0f, 128.0f, -320.0f-nEntity*40.0f) ;
+ }
+
+
+
+ for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
+ {
+ m_pEntityInfo[nEntity].Active=1 ;
+ m_pVisibleEntity[nEntity]=nEntity ;
+ m_pFrustumEntity[nEntity]=nEntity ;
+ }
+
+
+ m_nMaxVisibleEntity=m_nMaxEntity ;
+ m_nMaxFrustumEntity=m_nMaxEntity ;
+
+ return 1 ;
+
+}
+
+
+int OgreFramework::SetupEntity(int nEntity, char *chMeshName)
+{
+
+ char chEntityName[1024] ;
+ //char chMeshName[1024] ;
+
+
+ int nSubMesh=0 ;
+ int nMaxSubMesh=0 ;
+
+
+
+ Ogre::String MaterialName ;
+
+
+ char chMaterial_Base[1024] ;
+ MaterialPtr pMaterial_Base ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
+
+ char chMaterial_Fast[1024] ;
+ MaterialPtr pMaterial_Fast ; // faster version of the base, mainly non-coloured shadowning.
+
+ char chMaterial_Black[1024] ;
+ MaterialPtr pMaterial_Black ; // just plain black, or black with alpha testing.
+
+ char chMaterial_DfShColour[1024] ;
+ MaterialPtr pMaterial_DfShColour ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
+
+
+ char chMaterial_Shadow[1024] ;
+ MaterialPtr pMaterial_Shadow ;
+
+ char chMaterial_ShadeFront[1024] ;
+ MaterialPtr pMaterial_ShadeFront ;
+
+ char chMaterial_ShadeBack[1024] ;
+ MaterialPtr pMaterial_ShadeBack ;
+
+ char chMaterial_DfShPosition[1024] ;
+ MaterialPtr pMaterial_DfShPosition ;
+
+ char chMaterial_DfShDiffuse[1024] ;
+ MaterialPtr pMaterial_DfShDiffuse ;
+
+ //char chMaterial_DSNormal[1024] ;
+ //MaterialPtr pMaterial_DSNormal ;
+
+ char chMaterial_DfShFuncTNB[1024] ;
+ MaterialPtr pMaterial_DfShFuncTNB ;
+
+ char chMaterial_DfShSpecular[1024] ;
+ MaterialPtr pMaterial_DfShSpecular ;
+
+ char chMaterial_DfShEmissive[1024] ;
+ MaterialPtr pMaterial_DfShEmissive ;
+
+ //char chMaterial_DfShData[1024] ;
+ //MaterialPtr pMaterial_DfShData ;
+
+ char chMaterial_DfShMix[1024] ;
+ MaterialPtr pMaterial_DfShMix ;
+
+ char chCompare[1024] ;
+
+ unsigned short src, dest; // for tangent vectors
+
+ char chMasterNodeName[1024] ;
+ char chSubNodeName[1024] ;
+
+ char chMessage[1024] ;
+ int nPTex=0 ;
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ sprintf(chEntityName, "Entity_%05i", nEntity) ;
+ //strcpy(chMeshName, "robot.mesh") ;
+
+
+ // load the mesh
+
+ m_pEntityInfo[nEntity].pEnt=m_pSceneMgr->createEntity( chEntityName, chMeshName );
+
+ m_pEntityInfo[nEntity].TriangleCount=0 ;
+
+
+ // create the master scenenode
+ sprintf(chMasterNodeName, "Entity_%05i", nEntity) ;
+ m_pEntityInfo[nEntity].pMasterNode=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chMasterNodeName) ;
+ m_pEntityInfo[nEntity].pMasterNode->attachObject(m_pEntityInfo[nEntity].pEnt) ;
+
+ nMaxSubMesh=m_pEntityInfo[nEntity].pEnt->getMesh()->getNumSubMeshes() ;
+ if(nMaxSubMesh>MAX_SUBMESH)
+ {
+ sprintf(m_chBug, "MESH ERROR: Mesh %s has %i submeshes, max is %i", chMeshName, m_pEntityInfo[nEntity].MaxSubMesh, MAX_SUBMESH) ;
+ m_pLog->logMessage(m_chBug);
+ nMaxSubMesh=MAX_SUBMESH ;
+ }
+ m_pEntityInfo[nEntity].MaxSubMesh=nMaxSubMesh ;
+
+ sprintf(m_chBug, "Entity %i, Mesh %s, MaxSubMesh %i", nEntity, chMeshName, m_pEntityInfo[nEntity].MaxSubMesh) ;
+ m_pLog->logMessage(m_chBug);
+
+ // assign all the materials needed for all the submeshes
+ for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+ {
+ // we count the triangles just for stats
+ m_pEntityInfo[nEntity].TriangleCount += m_pEntityInfo[nEntity].pEnt->getMesh()->getSubMesh(nSubMesh)->indexData->indexCount/3 ;
+
+
+ MaterialName=m_pEntityInfo[nEntity].pEnt->getMesh()->getSubMesh(nSubMesh)->getMaterialName() ;
+
+
+
+
+ if(MaterialName.size()<512) // make sure name isn't too long before we copy it.
+ strcpy(chMaterial_Base, MaterialName.c_str()) ;
+ else
+ {
+ sprintf(m_chBug, "MESH ERROR: Mesh %s submesh %i material name is too long.", chMeshName, nSubMesh) ;
+ m_pLog->logMessage(m_chBug);
+ m_pLog->logMessage(MaterialName) ;
+ chMaterial_Base[0]='\0' ; // no material
+ }
+
+ sprintf(m_chBug, "Entity %i SubMesh %i, Material %s", nEntity, nSubMesh, chMaterial_Base) ;
+ m_pLog->logMessage(m_chBug);
+
+
+ // if the material is a lamp material we need to specify either an OpenGl or Direct3D version
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[12]='\0' ;
+ if(strcmp("lights/lamp_", chCompare)==0) // material is LAMP
+ {
+ if(m_IsOpenGL)
+ strcat(chMaterial_Base, "_ogl") ;
+ else
+ strcat(chMaterial_Base, "_d3d") ;
+
+ }
+
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[17]='\0' ;
+ if(strcmp("lights/lamp2pass_", chCompare)==0) // material is LAMP, 2 pass version
+ {
+ if(m_IsOpenGL)
+ strcat(chMaterial_Base, "_ogl") ;
+ else
+ strcat(chMaterial_Base, "_d3d") ;
+ }
+
+ // check that this material script exists, if not set to the default
+ pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
+ if(true)//pMaterial_Base.isNull())
+ {
+ strcat(chMaterial_Base, " *** MISSING ***") ;
+ OFBug.LogAddCR(chMaterial_Base) ;
+
+ strcpy(chMaterial_Base, "textures/metaltech/OPAQUE_DSCE_TechRadar") ;
+ pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
+ }
+
+
+ // setup whether this material and it's entities are transparent or whatever
+
+ m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=0 ;// default to nothing
+
+ if(strstr(chMaterial_Base, "OPAQUE")!=NULL) // material and its entity are OPAQUE
+ {
+ m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_OPAQUE ; // note that the derived entity will be opaque
+
+ }
+ else
+ {
+
+ if(strstr(chMaterial_Base, "ALPHAPF")!=NULL) // material and its entity are ALPHAPF
+ {
+ m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_OPAQUE ; // note that the derived entity will be opaque
+ }
+ else
+ {
+
+ if(strstr(chMaterial_Base, "GEL")!=NULL) // material and its entity are GEL
+ {
+ m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_GEL ; // note that the derived entity will be transparent
+ }
+ else
+ {
+
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[12]='\0' ;
+ if(strcmp("lights/lamp_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
+ {
+ m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_LAMP ; // note that the derived entity will be lamp
+ }
+ else
+ {
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[17]='\0' ;
+ if(strcmp("lights/lamp2pass_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
+ {
+ m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_LAMP ; // note that the derived entity will be lamp
+ }
+ else
+ {
+
+ if(strstr(chMaterial_Base, "GLOW_")!=NULL) // material and its entity are GLOW
+ {
+ m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_GLOW ; // note that the derived entity will be glow
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Setup the different material names and pointers needed for various passes
+ //
+ // Lamps need only one material, pMaterial_Base, which is already assigned above, so it skips all this.
+ //
+ // Glow needs two materials, pMaterial_Base plus pMaterial_DfShColour for the coloured gel deferred pass.
+ // However it's better to make a third, and duplicate the pMaterial_Base to pMaterial_Emissive, since
+ // when glow gets rendered on the Emmisive pass it would be odd to switch to the base material instead
+ // of the emmisive.
+ //
+ // Other objects need multiple materials for various different deferred shading and FX passes
+
+ if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_LAMP) && (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_GLOW))
+ {
+
+ // material for fast shading
+ strcpy(chMaterial_Fast, chMaterial_Base) ;
+ strcat(chMaterial_Fast, "_Fast") ;
+ pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
+ if(pMaterial_Fast.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_Fast) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_Fast, "Fast") ;
+ pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
+ }
+
+ // material for black shading
+ strcpy(chMaterial_Black, chMaterial_Base) ;
+ strcat(chMaterial_Black, "_Black") ;
+ pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
+ if(pMaterial_Black.isNull())
+ {
+ // only issue a warning if this is an alpha testing material, others don't need specialized Black materials
+ if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_Black) ;
+ m_pLog->logMessage(chMessage);
+ }
+
+ strcpy(chMaterial_Black, "Black") ;
+ pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
+ }
+
+ // material for shadow casting
+ strcpy(chMaterial_Shadow, chMaterial_Base) ;
+ strcat(chMaterial_Shadow, "_Shadow") ;
+ pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
+ if(pMaterial_Shadow.isNull())
+ {
+ strcpy(chMaterial_Shadow, "OPAQUE_Shadow") ;
+ pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
+ }
+
+
+
+ // material for shadow casting
+ strcpy(chMaterial_ShadeFront, chMaterial_Base) ;
+ strcat(chMaterial_ShadeFront, "_ShadeFront") ;
+ pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
+ if(pMaterial_ShadeFront.isNull())
+ {
+ // standard opaque ShadeFront.
+ // Transparent surfaces MUST have their own _ShadeFront material or they will not colour light and can interfere with other trans surfaces.
+ strcpy(chMaterial_ShadeFront, "OPAQUE_ShadeFront") ;
+
+ pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
+ }
+
+
+ // material for shadow casting
+ strcpy(chMaterial_ShadeBack, chMaterial_Base) ;
+ strcat(chMaterial_ShadeBack, "_ShadeBack") ;
+ pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
+ if(pMaterial_ShadeBack.isNull())
+ {
+ // standard opaque ShadeBack.
+ // Transparent surfaces MUST have their own _ShadeBack material or they will not colour light and can interfere with other trans surfaces.
+ strcpy(chMaterial_ShadeBack, "OPAQUE_ShadeBack") ;
+
+ pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
+ }
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShColour, chMaterial_Base) ;
+ strcat(chMaterial_DfShColour, "_DfShColour") ;
+ pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+ if(pMaterial_DfShColour.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShColour) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShColour, "DfShColour") ;
+ pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+ }
+
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShPosition, chMaterial_Base) ;
+ strcat(chMaterial_DfShPosition, "_DfShPosition") ;
+ pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
+ if(pMaterial_DfShPosition.isNull())
+ {
+ // only issue a warning if this is an alpha testing material, others don't need specialized DfShPosition materials
+ if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShPosition) ;
+ m_pLog->logMessage(chMessage);
+ }
+
+ strcpy(chMaterial_DfShPosition, "DfShPosition") ;
+ pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
+ }
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShDiffuse, chMaterial_Base) ;
+ strcat(chMaterial_DfShDiffuse, "_DfShDiffuse") ;
+ pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
+ if(pMaterial_DfShDiffuse.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShDiffuse) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShDiffuse, "DfShDiffuse") ;
+ pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
+ }
+
+ /*
+ // material for deferred shading // UNUSED
+ strcpy(chMaterial_DSNormal, chMaterial_Base) ;
+ strcat(chMaterial_DSNormal, "_DSNormal") ;
+ pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
+ if(pMaterial_DSNormal.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DSNormal) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DSNormal, "DSNormal") ;
+ pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
+ }
+ */
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShFuncTNB, chMaterial_Base) ;
+ strcat(chMaterial_DfShFuncTNB, "_DfShFuncTNB") ;
+ pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
+ if(pMaterial_DfShFuncTNB.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShFuncTNB) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShFuncTNB, "DfShFuncTNB") ;
+ pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
+ }
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShSpecular, chMaterial_Base) ;
+ strcat(chMaterial_DfShSpecular, "_DfShSpecular") ;
+ pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
+ if(pMaterial_DfShSpecular.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShSpecular) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShSpecular, "DfShSpecular") ;
+ pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
+ }
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShEmissive, chMaterial_Base) ;
+ strcat(chMaterial_DfShEmissive, "_DfShEmissive") ;
+ pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+ if(pMaterial_DfShEmissive.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShEmissive) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShEmissive, "DfShEmissive") ;
+ pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+ }
+
+
+ /*
+ // material for deferred shading
+ strcpy(chMaterial_DfShData, chMaterial_Base) ;
+ strcat(chMaterial_DfShData, "_DfShData") ;
+ pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
+ if(pMaterial_DfShData.isNull())
+ {
+ sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShData) ;
+ m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShData, "DfShData") ;
+ pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
+ }
+ */
+
+ // material for deferred shading
+ strcpy(chMaterial_DfShMix, chMaterial_Base) ;
+ strcat(chMaterial_DfShMix, "_DfShMix") ;
+ pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
+ if(pMaterial_DfShMix.isNull())
+ {
+ // Pretty much all materials just use the default mix material,
+ // so don't issue warnings if there isn't a specialized version
+ //sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShMix) ;
+ //m_pLog->logMessage(chMessage);
+
+ strcpy(chMaterial_DfShMix, "DfShMix") ;
+ pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
+ }
+
+
+
+
+
+ }// end if not MAT_LAMP or MAT_GLOW
+ else
+ if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW) // the two materials that glow needs
+ {
+
+ // when I get around to allowing user defined GLOW materials as well as the automatic ones,
+ // this'll be the place to add it.
+ // For now, just the automatically generated lamp/light stuff has a glow.
+
+ // if the base material was "GLOW_lamp"
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[strlen("GLOW_lamp")]='\0' ;
+ if(strcmp("GLOW_lamp", chCompare)==0)
+ {
+ strcpy(chMaterial_DfShColour, "GLOW_lampcol") ;
+ pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+
+ strcpy(chMaterial_DfShEmissive, "GLOW_lamp") ;
+ pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+ }
+ else
+ {
+
+ // if the base material was "GLOW_light"
+ strcpy(chCompare, chMaterial_Base) ;
+ chCompare[strlen("GLOW_light")]='\0' ;
+ if(strcmp("GLOW_light", chCompare)==0)
+ {
+ strcpy(chMaterial_DfShColour, "GLOW_lightcol") ;
+ pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+
+ strcpy(chMaterial_DfShEmissive, "GLOW_light") ;
+ pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+ }
+
+ }
+ }
+
+
+
+
+ // if the entity is a lamp or glow, set its material because they never get changed
+ //if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW))
+ // m_pZoneEntity[nMOIndex]->setMaterial( pMaterial_Base) ;
+
+
+ // store the pointers to the materials of this entity
+ //m_pZoneEntityMaterial_Base[nMOIndex]=pMaterial_Base ;
+ //m_pZoneEntityMaterial_Fast[nMOIndex]=pMaterial_Fast ;
+ m_pEntityInfo[nEntity].Material_Black[nSubMesh]=pMaterial_Black ;
+ m_pEntityInfo[nEntity].Material_DfShColour[nSubMesh]=pMaterial_DfShColour ;
+ m_pEntityInfo[nEntity].Material_Shadow[nSubMesh]=pMaterial_Shadow ;
+ m_pEntityInfo[nEntity].Material_ShadeFront[nSubMesh]=pMaterial_ShadeFront ;
+ m_pEntityInfo[nEntity].Material_ShadeBack[nSubMesh]=pMaterial_ShadeBack ;
+ m_pEntityInfo[nEntity].Material_DfShPosition[nSubMesh]=pMaterial_DfShPosition ;
+ m_pEntityInfo[nEntity].Material_DfShDiffuse[nSubMesh]=pMaterial_DfShDiffuse ;
+ //m_pEntityInfo[nEntity].Material_DSNormal[nSubMesh]=pMaterial_DSNormal ;
+ m_pEntityInfo[nEntity].Material_DfShFuncTNB[nSubMesh]=pMaterial_DfShFuncTNB ;
+ m_pEntityInfo[nEntity].Material_DfShSpecular[nSubMesh]=pMaterial_DfShSpecular ;
+ m_pEntityInfo[nEntity].Material_DfShEmissive[nSubMesh]=pMaterial_DfShEmissive ;
+ //m_pEntityInfo[nEntity].Material_DfShData[nSubMesh]=pMaterial_DfShData ;
+ m_pEntityInfo[nEntity].Material_DfShMix[nSubMesh]=pMaterial_DfShMix ;
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ char chNewName[1024] ;
+ for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+ {
+ Ogre::AliasTextureNamePairList AliasList ;
+
+ // check the necessary texture exists
+ //if(TextureManager::getSingleton().getByName(m_Q3Map->m_chSpotlightTexture[nPTex]).isNull())
+ // OFBug.MessageInt(666) ;
+
+ AliasList.insert(AliasTextureNamePairList::value_type("projector_tex", m_Q3Map->m_chSpotlightTexture[nPTex]));
+
+ sprintf(chNewName, "%s_%i", chMaterial_Base, 0) ;
+ m_pEntityInfo[nEntity].Material_Base[nPTex][nSubMesh]=pMaterial_Base->clone(chNewName) ;
+ // change the texture unit
+ m_pEntityInfo[nEntity].Material_Base[nPTex][nSubMesh]->applyTextureAliases(AliasList) ;
+
+ sprintf(chNewName, "%s_%i", chMaterial_Fast, 0) ;
+ m_pEntityInfo[nEntity].Material_Fast[nPTex][nSubMesh]=pMaterial_Fast->clone(chNewName) ;
+ // change the texture unit
+ m_pEntityInfo[nEntity].Material_Fast[nPTex][nSubMesh]->applyTextureAliases(AliasList) ;
+
+ }
+
+ // create the sub scenenodes
+ //sprintf(chSubNodeName, "Entity_%05i_%05i", nEntity, nSubMesh) ;
+ //m_pEntityInfo[nEntity].pSubNode[nSubMesh]=m_pEntityInfo[nEntity].pMasterNode->createChildSceneNode(chSubNodeName) ;
+
+
+ sprintf(m_chBug, "Node %s, Subnode %s, Type %i", chMasterNodeName, chSubNodeName, m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]) ;
+ m_pLog->logMessage(m_chBug);
+
+ }// end for submesh
+
+ // build tangent vectors for the mesh
+ m_pEntityInfo[nEntity].pEnt->getMesh()->suggestTangentVectorBuildParams(VES_TANGENT, src, dest) ;
+ m_pEntityInfo[nEntity].pEnt->getMesh()->buildTangentVectors(VES_TANGENT, src, dest);
+
+
+ // default to not active, not visible and in no zones
+ m_pEntityInfo[nEntity].Active=0 ;
+ m_pEntityInfo[nEntity].Visible=0 ;
+ m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=0 ;
+
+ // add some info about the bounding box
+ Ogre::AxisAlignedBox aabb ;
+ Ogre::Vector3 Minimum ;
+ Ogre::Vector3 Maximum ;
+
+ aabb=m_pEntityInfo[nEntity].pEnt->getBoundingBox() ;
+ Minimum=aabb.getMinimum() ;
+ Maximum=aabb.getMaximum() ;
+
+ m_pEntityInfo[nEntity].AABB=aabb ;
+ m_pEntityInfo[nEntity].Centre.x=(Maximum.x-Minimum.x)/2.0f ;
+ m_pEntityInfo[nEntity].Centre.y=(Maximum.y-Minimum.y)/2.0f ;
+ m_pEntityInfo[nEntity].Centre.z=(Maximum.z-Minimum.z)/2.0f ;
+
+ m_pEntityInfo[nEntity].AABBMin[0]=Minimum.x ;
+ m_pEntityInfo[nEntity].AABBMin[1]=Minimum.y ;
+ m_pEntityInfo[nEntity].AABBMin[2]=Minimum.z ;
+ m_pEntityInfo[nEntity].AABBMax[0]=Maximum.x ;
+ m_pEntityInfo[nEntity].AABBMax[1]=Maximum.y ;
+ m_pEntityInfo[nEntity].AABBMax[2]=Maximum.z ;
+
+
+ m_pEntityInfo[nEntity].Postition=Ogre::Vector3(0.0f, 0.0f, 0.0f) ;
+
+
+
+ return 1 ;
+}
+
+
+// Hmm... wanted to control some CG compiling, mainly to turn shadow filtering on or off, but I couln't get this to work.
+// I ended up just manually creating filtered and unfiltered version of the materials.
+/*
+int OgreFramework::ApplyCGDefines(void)
+{
+ int nZoneMO=0 ;
+ int nMaxZoneMO=m_nZoneMOStart[m_Q3Map->m_nMaxZone] ;
+ int nPTex=0 ;
+
+ Ogre::Pass *CGPass ;
+ int nPass=0 ;
+ int nMaxPass=0 ;
+
+ for(nZoneMO=0 ; nZoneMO<nMaxZoneMO ; nZoneMO++)
+ {
+ //OFBug.MessageInt(nZoneMO, nMaxZoneMO, m_pZoneEntityMaterialType[nZoneMO]) ;
+
+ if(m_pZoneEntityMaterialType[nZoneMO]==MAT_OPAQUE)
+ for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+ {
+ //m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(1)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON 1") ;
+ nMaxPass=m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getNumPasses() ;
+
+ for(nPass=0 ; nPass<nMaxPass ; nPass++)
+ {
+ m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(nPass)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON=1") ;
+ //m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(nPass)->getFragmentProgram()->reload();
+ }
+ //CGPass=m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(0) ;
+ }
+ }
+
+
+ //m_pZoneEntityMaterial_Base[0][0]->getTechnique(0)->getPass(1)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON 1") ;
+
+
+ return 1 ;
+
+
+}
+*/
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// create light manual objects, just for debugging/testing.
+// This is an array of manualobject AABBs that show the light culling box (double sided) for each light
+
+int OgreFramework::AddLightCullingBoxes()
+{
+ int nLt=0 ;
+ // for calculating bounds of mesh
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+ float flMaxZ=0.0f ;
+ int nMaxLight=m_Q3Map->m_nLightMax ;
+
+ char chSceneNodeName[1024] ;
+ char chManualName[1024] ;
+
+ m_pLightMO = new Ogre::ManualObject*[nMaxLight] ;
+ if(m_pLightMO==NULL) return 0 ; // fail, out of mem
+
+ for(nLt=0 ; nLt<nMaxLight ; nLt++)
+ {
+
+ sprintf(chManualName, "LightMO_%05i", nLt) ;
+ m_pLightMO[nLt]=m_pSceneMgr->createManualObject(chManualName) ;
+
+ // start defining the manualObject
+ m_pLightMO[nLt]->begin("lighttest", RenderOperation::OT_TRIANGLE_LIST) ;
+
+
+ flMinX=m_Q3Map->m_pLight[nLt].Min[0] ;
+ flMinY=m_Q3Map->m_pLight[nLt].Min[1] ;
+ flMinZ=m_Q3Map->m_pLight[nLt].Min[2] ;
+
+ flMaxX=m_Q3Map->m_pLight[nLt].Max[0] ;
+ flMaxY=m_Q3Map->m_pLight[nLt].Max[1] ;
+ flMaxZ=m_Q3Map->m_pLight[nLt].Max[2] ;
+
+
+ //////////////////////////////////////////////////////
+ // back face
+ m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+ m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+ m_pLightMO[nLt]->quad(0, 1, 2, 3) ;
+ m_pLightMO[nLt]->quad(3, 2, 1, 0) ;
+
+ //////////////////////////////////////////////////////
+ // front face
+ m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+ m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+ m_pLightMO[nLt]->quad(7, 6, 5, 4) ;
+ m_pLightMO[nLt]->quad(4, 5, 6, 7) ;
+
+ //////////////////////////////////////////////////////
+ // left face
+ m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+ m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+ m_pLightMO[nLt]->quad(8, 9, 10, 11) ;
+ m_pLightMO[nLt]->quad(11, 10, 9, 8) ;
+
+
+ //////////////////////////////////////////////////////
+ // right face
+ m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+ m_pLightMO[nLt]->quad(15, 14, 13, 12) ;
+ m_pLightMO[nLt]->quad(12, 13, 14, 15) ;
+
+ //////////////////////////////////////////////////////
+ // top face
+ m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+ m_pLightMO[nLt]->quad(16, 17, 18, 19) ;
+ m_pLightMO[nLt]->quad(19, 18, 17, 16) ;
+
+ //////////////////////////////////////////////////////
+ // bottom face
+ m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+ m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+ m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
+ m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+ m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+ m_pLightMO[nLt]->quad(23, 22, 21, 20) ;
+ m_pLightMO[nLt]->quad(20, 21, 22, 23) ;
+ //////////////////////////////////////////////////////
+
+ m_pLightMO[nLt]->end() ;
+
+
+
+ sprintf(chSceneNodeName, "LSN%05i", nLt) ;
+ m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName)->attachObject(m_pLightMO[nLt]) ;
+
+
+ }
+
+ return 1 ;
+}
+
+int OgreFramework::AddPortalBoxes()
+{
+ int nPt=0 ;
+ // for calculating bounds of mesh
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+ float flMaxZ=0.0f ;
+ int nMaxPortal=m_Q3Map->m_iNumPortals ;
+
+ char chSceneNodeName[1024] ;
+ char chManualName[1024] ;
+
+ m_pPortalMO = new Ogre::ManualObject*[nMaxPortal] ;
+ if(m_pPortalMO==NULL) return 0 ; // fail, out of mem
+
+ m_pPortalNode = new Ogre::Node*[nMaxPortal] ;
+ if(m_pPortalNode==NULL)
+ {
+ //CHECKDELETE_ARRAY( m_pPortalMO ) ;
+ return 0 ; // fail, out of mem
+ }
+
+ for(nPt=0 ; nPt<nMaxPortal ; nPt++)
+ {
+
+ sprintf(chManualName, "PortalMO_%05i", nPt) ;
+ m_pPortalMO[nPt]=m_pSceneMgr->createManualObject(chManualName) ;
+
+ // start defining the manualObject
+ m_pPortalMO[nPt]->begin("white", RenderOperation::OT_TRIANGLE_LIST) ;
+
+ flMinX=m_Q3Map->m_pPortals[nPt].Min[0] ;
+ flMinY=m_Q3Map->m_pPortals[nPt].Min[1] ;
+ flMinZ=m_Q3Map->m_pPortals[nPt].Min[2] ;
+
+ flMaxX=m_Q3Map->m_pPortals[nPt].Max[0] ;
+ flMaxY=m_Q3Map->m_pPortals[nPt].Max[1] ;
+ flMaxZ=m_Q3Map->m_pPortals[nPt].Max[2] ;
+
+
+ //////////////////////////////////////////////////////
+ // back face
+ m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+ m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+ m_pPortalMO[nPt]->quad(0, 1, 2, 3) ;
+ m_pPortalMO[nPt]->quad(3, 2, 1, 0) ;
+
+ //////////////////////////////////////////////////////
+ // front face
+ m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+ m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+ m_pPortalMO[nPt]->quad(7, 6, 5, 4) ;
+ m_pPortalMO[nPt]->quad(4, 5, 6, 7) ;
+
+ //////////////////////////////////////////////////////
+ // left face
+ m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+ m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+ m_pPortalMO[nPt]->quad(8, 9, 10, 11) ;
+ m_pPortalMO[nPt]->quad(11, 10, 9, 8) ;
+
+
+ //////////////////////////////////////////////////////
+ // right face
+ m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+ m_pPortalMO[nPt]->quad(15, 14, 13, 12) ;
+ m_pPortalMO[nPt]->quad(12, 13, 14, 15) ;
+
+ //////////////////////////////////////////////////////
+ // top face
+ m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+ m_pPortalMO[nPt]->quad(16, 17, 18, 19) ;
+ m_pPortalMO[nPt]->quad(19, 18, 17, 16) ;
+
+ //////////////////////////////////////////////////////
+ // bottom face
+ m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+ m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+ m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
+ m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+ m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+ m_pPortalMO[nPt]->quad(23, 22, 21, 20) ;
+ m_pPortalMO[nPt]->quad(20, 21, 22, 23) ;
+ //////////////////////////////////////////////////////
+
+ m_pPortalMO[nPt]->end() ;
+
+
+
+ sprintf(chSceneNodeName, "PSN%05i", nPt) ;
+ m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName)->attachObject(m_pPortalMO[nPt]) ;
+ m_pPortalNode[nPt]=m_pSceneMgr->getRootSceneNode()->getChild(chSceneNodeName) ;
+
+ }
+
+ return 1 ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+// this function calculates which zones are visible.
+// If they are in the view frustum and any connecting portals are open, they're visible.
+// It calls a recursive functions that goes into each visible zone and scans it's portals
+// for more visible zones, cutting down the frustum as it goes.
+//
+// This function also checks which lights are visible.
+// First it scans the original zone the camera is in, any light whose centre is in that zone
+// is visible regardless of how many other zones that light touches.
+// Lights that are completely contained in any of the further zones are checked against the
+// current cut down frustum.
+void OgreFramework::CalculateZoneVisibility(Ogre::Camera *pCamera, int *pCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis, char* pPortalVis, int* pMaxVisibleLight, unsigned short* pVisibleLightList)
+{
+
+
+ int nZone=0 ;
+ int nZoneIndex=0 ;
+ int nSubZone=0 ;
+ int nSubZoneIndex=0 ;
+ int nMaxSubZone=0 ;
+ int nPortal=0 ;
+ int nPortalIndex=0 ;
+ int nMaxPortal=0 ;
+ int nMaxPortalZone=0 ;
+ int nPortalZone=0 ;
+ int nPortalZoneIndex=0 ;
+ int nMaxZone=0 ;
+
+
+ int nMaxLight=m_Q3Map->m_nLightMax ;
+ int nLt=0 ;
+
+ int nMaxSubLight=m_Q3Map->m_nSubLightMax ;
+ int nSubLt=0 ;
+
+ m_nMaxVisibleLight=0 ;
+
+
+
+ Ogre::Vector3 Pos=pCamera->getPosition() ;
+ float flPos[3]={Pos.x, Pos.y, Pos.z} ;
+
+ Ogre::AxisAlignedBox AAB ;
+
+
+
+ // initially all lights are invisible
+ // set all remaining real lights to invisible
+ SetAllLightsOff() ;
+
+ m_nTotalTriangles=0 ;
+
+ *pMaxVisibleLight=0 ; // no lights in the list
+
+ if(m_nZoneCullingActive) // if zone culling is active
+ {
+
+ // by default, all zones are not visible
+ nZone=m_Q3Map->m_nMaxZone ;
+ while(nZone)
+ pZoneVis[--nZone]=ZONE_UNCHECKED ;
+
+ // by default, all lights are not visible
+ nLt=nMaxLight ;
+ while(nLt)
+ pLightVis[--nLt]=LIGHT_UNCHECKED ;
+
+ // by default, all lights are not visible
+ nSubLt=m_Q3Map->m_nSubLightMax ;
+ while(nSubLt)
+ pSubLightVis[--nSubLt]=LIGHT_UNCHECKED ;
+
+ // by default, all portals are not visible
+ nPortal=m_Q3Map->m_iNumPortals ;
+ while(nPortal)
+ pPortalVis[--nPortal]=PORTAL_UNCHECKED ;
+ }
+ else
+ {
+ // for debugging, all zones are visible
+ nZone=m_Q3Map->m_nMaxZone ;
+ while(nZone)
+ pZoneVis[--nZone]=ZONE_VISIBLE ;
+
+
+ // by default, all lights are visible
+ nLt=nMaxLight ;
+ while(nLt)
+ pLightVis[--nLt]=LIGHT_VISIBLE ;
+
+ nSubLt=m_Q3Map->m_nSubLightMax ;
+ while(nSubLt)
+ pSubLightVis[--nSubLt]=LIGHT_VISIBLE ;
+
+ // by default, all portals are visible
+ nPortal=m_Q3Map->m_iNumPortals ;
+ while(nPortal)
+ pPortalVis[--nPortal]=PORTAL_VISIBLE ;
+
+ return ;
+ }
+
+
+
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+ /////////////////////////////////////////////////////////////////////////////////////
+ // check camera is actually in the zone designated, otherwise update it.
+
+ if((*pCameraZone==-1) || (!m_Q3Map->PointInZone(flPos, *pCameraZone)) )
+ {
+
+ nSubZone=m_Q3Map->GetNextSubZone(flPos, -1, m_Q3Map->m_iNumSubZones) ;
+
+ // 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.
+ // this shouldn't generally happen, but if we aren't clipping and are flying around testing, it can.
+ // Don't worry about optimizing this.
+
+
+
+ if(nSubZone==-1)
+ {
+
+ nMaxSubZone=m_Q3Map->m_iNumSubZones ;
+ for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+ {
+ 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]) ;
+
+ if(pCamera->isVisible(AAB))
+ pZoneVis[ m_Q3Map->m_pSubZones[nSubZone].Zone ]=ZONE_VISIBLE ;
+ }
+
+ *pCameraZone=-1 ;
+ return ; // skip everything else
+ }
+
+ *pCameraZone=m_Q3Map->m_pSubZones[nSubZone].Zone ; // update the zone
+
+ }
+
+ //
+ /////////////////////////////////////////////////////////////////////////////////////
+
+
+ // update the portal states
+ nMaxPortal=m_Q3Map->m_iNumPortals ;
+ nPortal=nMaxPortal ;
+ while(nPortal)
+ {
+ nPortal-- ;
+
+ if(m_nPortalDebug==0)
+ m_chPortalState[nPortal]=PORTALSTATE_OPEN ;
+ else
+ {
+ //if(m_nPortalState==1)
+ m_chPortalState[nPortal]=PORTALSTATE_OPEN ;
+ //else
+ // m_chPortalState[nPortal]=PORTALSTATE_CLOSED ;
+
+
+
+ }
+
+ //m_chPortalState[nPortal]|=PORTAL_FLAG_UNCHECKED ; // by default all portals are unchecked
+
+ //m_chPortalState[nPortal]&=~(PORTAL_FLAG_VISCHECK|PORTAL_FLAG_VISIBLE) ; // by default, all portals are vis unchecked and not visible
+ }
+
+ //m_chPortalState[0]=PORTAL_FLAG_CLOSED ;
+ if(m_nPortalState==1)
+ m_chPortalState[1]=PORTALSTATE_OPEN ;
+ else
+ m_chPortalState[1]=PORTALSTATE_CLOSED ;
+
+
+
+
+ //Ogre::Camera* pTestCamera ;
+ //pTestCamera->synchroniseBaseSettingsWith(pCamera) ;
+
+ //Ogre::Real OrigL, OrigR, OrigT, OrigB ; // original frustum extents
+ //pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
+
+ //pCamera->setFrustumExtents(OrigL/2.0, OrigR/2.0, OrigT/2.0, OrigB/2.0) ; // reset the original frustum extents
+
+ m_nRecurseCount=0 ;
+
+
+ // work out the aspect scaling we'll need
+ Ogre::Real OrigL, OrigR, OrigT, OrigB, ScaleX, ScaleY ; // frustum extents per each portal in this zone
+ Ogre::Real NewL, NewR, NewT, NewB ;
+ pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
+
+ m_ViewMatrix=pCamera->getViewMatrix(true) ;
+ m_ProjectionMatrix=pCamera->getProjectionMatrix() ;
+
+
+ //if(m_nOriginalZoneOpenPortals=0) // no portals on player zone are open, so we can only see the current zones.
+ // pZoneVis[nZone]=ZONE_VISIBLE ; // flag this subzone as visible
+ //else
+ {
+
+ /*
+ // apply the stereofrustum tweak if needed
+ if(m_flStereoFrustumTweak!=0.0f)
+ {
+
+ NewL=OrigL-m_flStereoFrustumTweak ;
+ NewR=OrigR+m_flStereoFrustumTweak ;
+ NewT=OrigT ;
+ NewB=OrigB ;
+ pCamera->setFrustumExtents(NewL, NewR, NewT, NewB) ;
+ }
+ else
+ */
+ {
+ NewL=OrigL ;
+ NewR=OrigR ;
+ NewT=OrigT ;
+ NewB=OrigB ;
+ }
+
+ ScaleX=NewR ;
+ ScaleY=NewT ;
+
+
+ PortalScan(pCamera, *pCameraZone, ScaleX, ScaleY, pZoneVis, pLightVis, pSubLightVis, pPortalVis, pMaxVisibleLight, pVisibleLightList) ; // recursively scan portals and work out zone visibility
+
+
+ pCamera->setFrustumExtents(OrigL, OrigR, OrigT, OrigB) ; // reset the original frustum extents
+
+ CheckMultiZoneLights(*pCameraZone, pZoneVis, pLightVis, pSubLightVis) ;
+ AddZonesFromMultiZoneLights(pZoneVis, pLightVis, pSubLightVis) ;
+
+ // check entity visibility
+
+
+ }
+
+
+
+
+
+
+
+
+}
+
+
+void OgreFramework::SetupEntityZones(void)
+{
+ // work out what zones any active entities are in.
+ int nEntity=0 ;
+ float Centre[3] ;
+ float AABBMin[3] ;
+ float AABBMax[3] ;
+ float* pLightMin ;
+ float* pLightMax ;
+
+ int nOldZone=0 ;
+ int nCurrentZone=0 ;
+ int nMaxOldZone=0 ;
+ int nZonePerZoneIndex=0 ;
+ int nZone=0 ;
+ int nZoneIndex=0 ;
+ int nMaxZone=0 ;
+ int nMaxSubLightIndex=0 ;
+ int nSubLightIndex=0 ;
+ int nSubLight=0 ;
+
+ int nLight=0;
+ int nLightIndex=0 ;
+
+
+
+
+ for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
+ if(m_pEntityInfo[nEntity].Active)
+ {
+ nLightIndex=0 ;
+ // to calculate what zones an entity is in, we test the centre of it's bounding box to get the main zone.
+ // we then test all zones that touch the central zone and see if they touch the entity bounding box.
+
+ // check if the entity central point is still in the same zone as last time.
+ Centre[0]=m_pEntityInfo[nEntity].Centre.x + m_pEntityInfo[nEntity].Postition.x ;
+ Centre[1]=m_pEntityInfo[nEntity].Centre.y + m_pEntityInfo[nEntity].Postition.y ;
+ Centre[2]=m_pEntityInfo[nEntity].Centre.z + m_pEntityInfo[nEntity].Postition.z ;
+
+ nMaxOldZone=m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT] ;
+
+
+
+ if(nMaxOldZone>0)
+ {
+ nOldZone=m_pEntityInfo[nEntity].Zone[0] ;
+ if(m_Q3Map->PointInZone(Centre, nOldZone))
+ nCurrentZone=nOldZone ; // still in the same zone as last round
+ else
+ {
+ // see if we are in one of the other zones that were touched by this entity's aabb last round
+
+ nCurrentZone=-1 ;
+ for(nZoneIndex=1 ; nZoneIndex<nMaxOldZone ; nZoneIndex++)
+ {
+ if(m_Q3Map->PointInZone(Centre, m_pEntityInfo[nEntity].Zone[nZoneIndex]))
+ {
+ nCurrentZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ; // found the current zone we are in
+ break ;
+ }// end if point in zone
+
+ }// end for zoneindex
+
+ }// end if not in old zone.
+ }
+ else
+ nCurrentZone=-1 ;
+
+
+ // if we haven't found the current zone so far, we need to check every zone.
+ if(nCurrentZone==-1)
+ {
+ nZone=m_Q3Map->m_nMaxZone ;
+ while(nZone)
+ if(m_Q3Map->PointInZone(Centre, --nZone))
+ {
+ nCurrentZone=nZone ;
+ break ;
+ }
+ }// end if nCurrentZone -1
+
+
+
+ // now either nCurrentZone is the zone the central point is in, or the entity isn't in any zone
+ if(nCurrentZone==-1)
+ m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=0 ;
+ else
+ {
+ // scan through all the zones that touch this entitys central zone
+ // see if the entitys AABB touches those other zones.
+ m_pEntityInfo[nEntity].Zone[0]=nCurrentZone ;
+ nZonePerZoneIndex=1 ;
+
+ AABBMin[0]=m_pEntityInfo[nEntity].Postition.x + m_pEntityInfo[nEntity].AABBMin[0] ;
+ AABBMin[1]=m_pEntityInfo[nEntity].Postition.y + m_pEntityInfo[nEntity].AABBMin[1] ;
+ AABBMin[2]=m_pEntityInfo[nEntity].Postition.z + m_pEntityInfo[nEntity].AABBMin[2] ;
+
+ AABBMax[0]=m_pEntityInfo[nEntity].Postition.x + m_pEntityInfo[nEntity].AABBMax[0] ;
+ AABBMax[1]=m_pEntityInfo[nEntity].Postition.y + m_pEntityInfo[nEntity].AABBMax[1] ;
+ AABBMax[2]=m_pEntityInfo[nEntity].Postition.z + m_pEntityInfo[nEntity].AABBMax[2] ;
+
+
+ nMaxZone=m_Q3Map->m_nZoneTouchesZone[nCurrentZone][INDEX_ZONEPERZONECOUNT] ;
+ for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++)
+ {
+ nZone=m_Q3Map->m_nZoneTouchesZone[nCurrentZone][nZoneIndex] ;
+
+ if(m_Q3Map->AABBTouchesZone(AABBMin, AABBMax, nZone))
+ {
+ m_pEntityInfo[nEntity].Zone[nZonePerZoneIndex]=nZone ;
+ nZonePerZoneIndex++ ;
+
+ if(nZonePerZoneIndex>MAX_ZONEPERENTITY)
+ nZonePerZoneIndex=MAX_ZONEPERENTITY ;
+ }
+
+
+
+ }// end for nZoneIndex
+
+
+ m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=nZonePerZoneIndex ;
+
+ // go through all the zones and check which lights touch this entity AABB
+ for(nZoneIndex=0 ; nZoneIndex<nZonePerZoneIndex ; nZoneIndex++)
+ {
+ nZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ;
+
+ nMaxSubLightIndex=m_Q3Map->m_nZoneTouchesSubLight[nZone][MAX_LIGHTPERZONE] ;
+ for(nSubLightIndex=0 ; nSubLightIndex<nMaxSubLightIndex ; nSubLightIndex++)
+ {
+ nSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][nSubLightIndex] ;
+ pLightMin=m_Q3Map->m_SubLight[nSubLight].Min ;
+ pLightMax=m_Q3Map->m_SubLight[nSubLight].Max ;
+
+ // if the entity overlaps the sublight
+ if(
+ (AABBMin[0]<pLightMax[0]) && (AABBMax[0]>pLightMin[0])
+ && (AABBMin[1]<pLightMax[1]) && (AABBMax[1]>pLightMin[1])
+ && (AABBMin[2]<pLightMax[2]) && (AABBMax[2]>pLightMin[2])
+ )
+ {
+ // add this to the list of lights.
+ // it's possible it might get listed more than once if this is a multizone light, that's ok.
+
+ m_pEntityInfo[nEntity].Light[nLightIndex]=m_Q3Map->m_SubLight[nSubLight].Light ;
+ nLightIndex++ ;
+ if(nLightIndex>MAX_LIGHTPERENTITY)
+ nLightIndex=MAX_LIGHTPERENTITY ;
+
+
+ } // end if overlap
+
+ }// end for nSubLightIndex
+
+ }// end for nZoneIndex
+
+ }// end if we have a central zone
+
+
+ m_pEntityInfo[nEntity].Light[INDEX_LIGHTPERENTITY]=nLightIndex ;
+
+
+ }// end if entity is active
+}
+
+// spotlights need entities set as visible if they are in a visible zone, even if they aren't in the frustum,
+// because they might cast shadows that are in the frustum.
+// However the deferred render only needs consider entities which are in a visible zone AND in the frustum.
+// m_pVisibleEntity holds entities in visible zones,
+// m_pFrustumEntity holds entities in visible zones that are also in the view frustum.
+void OgreFramework::CalculateEntityVisibility(Ogre::Camera* pCamera, char* pZoneVis)
+{
+
+ int nEntity=0 ;
+ int nMaxZone=0 ;
+ int nZone=0 ;
+ int nZoneIndex=0 ;
+ int nVisible=0 ;
+ Ogre::AxisAlignedBox AABB ;
+
+
+ m_nMaxVisibleEntity=0 ; // default to an empty list
+ m_nMaxFrustumEntity=0 ; // default to an empty list
+
+ m_nVisibleEntityTriangleCount=0 ;
+ m_nFrustumEntityTriangleCount=0 ;
+
+ for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
+ if(m_pEntityInfo[nEntity].Active)
+ {
+ m_pEntityInfo[nEntity].Visible=0 ; // default to not visible
+ m_pEntityInfo[nEntity].Frustum=0 ; // default to not visible and not in frustum
+
+ nMaxZone=m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT] ;
+
+
+
+ for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++)
+ {
+ nZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ;
+
+ // if a zone this entity touches is visible, test if it is in the view frustrum
+ if(pZoneVis[nZone]==ZONE_VISIBLE)
+ {
+
+ m_pEntityInfo[nEntity].Visible=1 ;
+ m_nVisibleEntityTriangleCount+=m_pEntityInfo[nEntity].TriangleCount ;
+ m_pVisibleEntity[m_nMaxVisibleEntity++]=nEntity ;
+
+
+ // is this entity also in the view frustum?
+ AABB.setMinimum( m_pEntityInfo[nEntity].AABB.getMinimum() + m_pEntityInfo[nEntity].Postition ) ;
+ AABB.setMaximum( m_pEntityInfo[nEntity].AABB.getMaximum() + m_pEntityInfo[nEntity].Postition ) ;
+
+ if(pCamera->isVisible(AABB))
+ {
+ m_pEntityInfo[nEntity].Frustum=1 ;
+ m_nFrustumEntityTriangleCount+=m_pEntityInfo[nEntity].TriangleCount ;
+ m_pFrustumEntity[m_nMaxFrustumEntity++]=nEntity ;
+ }
+
+
+
+
+
+ break ; // get out of the loop, we know the entity is visible.
+
+ }// end if zone is visible
+
+ }// end for nZoneIndex
+
+ }// end if entity is active
+
+}
+
+
+
+
+
+void OgreFramework::SetAllLightsOff(void)
+{
+ Light *light;
+ char chLightName[1024] ;
+ int nLt=0 ;
+ for(nLt=0 ; nLt<MAXLIGHTPERLOOP ; nLt++)
+ {
+ sprintf(chLightName, "LT%02i", nLt) ;
+ light=m_pSceneMgr->getLight(chLightName) ;
+ light->setVisible(false) ;
+ }
+}
+
+void OgreFramework::SetSingleVisibleLight(int nLt, bool bOn)
+{
+ Light *light;
+
+ light=m_pSceneMgr->getLight("LT00") ;
+
+
+ // if we're just turning the light off, make it invisible and return.
+ if(bOn==false)
+ {
+ light->setVisible(false) ;
+ return ;
+ }
+
+
+
+ light->setDiffuseColour(Ogre::ColourValue(1,1,1));
+ light->setSpecularColour(Ogre::ColourValue(1,1,1));
+
+ light->setAttenuation(m_Q3Map->m_pLight[nLt].Cutoff, 1.0, 1.0, 0.005);
+ 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]));
+ 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]));
+
+ light->setSpotlightRange(Degree(m_Q3Map->m_pLight[nLt].Angle-5.0), Degree(m_Q3Map->m_pLight[nLt].Angle), 1.0) ;
+ light->setVisible(true) ;
+}
+
+
+// sets up a single visible light from the visible light list and assigns the camera to its position and settings
+// returns true if successful, false if not (such as if the light isn't actually visible)
+
+bool OgreFramework::SetupSingleVisibleLightAndShadowCamera(int nLt, char* pLightVis, unsigned short* pVisibleLightList, Ogre::Camera* pCamera)
+{
+ //if(nLt!=4) return false ;
+
+ 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
+ return false ;
+
+
+ Light *light=m_pSceneMgr->getLight("LT00") ;
+
+ 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]));
+
+ float flRange=m_Q3Map->m_pLight[nLt].Cutoff ; // set the range
+ if(flRange<10240.0) //!! Ogre seems to cut off lights wrongly if the range is low, so set it to a minimum.
+ flRange=10240 ;
+
+ // The light attenuation parameters have been co-opted by me... they no longer represent range, constant, linear, quadratic
+ // instead,
+ // first parameter is the above range, just set high so Ogre doesn't turn lights off itself. The shaders ignore this parameter.
+ // second parameter is the cutoff used in the shader. Light suddenly cuts off after this distance.
+ // third parameter is the brightness. This controls the quadratic falloff of the light.
+ // fourth parameter is unused, leave as 1.0 for now.
+
+ light->setAttenuation(flRange, m_Q3Map->m_pLight[nLt].Cutoff, m_Q3Map->m_pLight[nLt].Brightness, 1.0) ;
+
+
+
+ // Ogre uses a fixed yaw axis which will cause pCamera->setDirection to malfunction if we point directly up or down.
+ // To avoid this we need to check for such lights and shift their direction a little.
+
+ float DirX=m_Q3Map->m_pLight[nLt].Direction[0] ;
+ float DirY=m_Q3Map->m_pLight[nLt].Direction[1] ;
+ float DirZ=m_Q3Map->m_pLight[nLt].Direction[2] ;
+
+
+ if((DirY>1.0-CAMERA_EPSILON) && (DirY<1.0+CAMERA_EPSILON)) // camera is pointing directly up
+ {
+ DirX=0.0f ;
+ DirY=1.0f ;
+ DirZ=0.000001f ;
+ }
+ else
+ if((DirY>-1.0-CAMERA_EPSILON) && (DirY<-1.0+CAMERA_EPSILON)) // camera is pointing directly down
+ {
+ DirX=0.0f ;
+ DirY=-1.0f ;
+ DirZ=0.000001f ;
+ }
+
+ 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]));
+ light->setDirection(Ogre::Vector3(DirX, DirY, DirZ));
+
+ light->setSpotlightRange(Degree(m_Q3Map->m_pLight[nLt].Angle-5.0), Degree(m_Q3Map->m_pLight[nLt].Angle), 1.0) ;
+ light->setVisible(true) ;
+
+ // setup the camera
+ pCamera->setAspectRatio(1) ;
+ pCamera->yaw(Ogre::Radian(0)) ;
+ pCamera->roll(Ogre::Radian(0)) ;
+ pCamera->pitch(Ogre::Radian(0)) ;
+ pCamera->setPosition(m_Q3Map->m_pLight[nLt].Position[0], m_Q3Map->m_pLight[nLt].Position[1], m_Q3Map->m_pLight[nLt].Position[2]) ;
+ pCamera->setDirection(DirX, DirY, DirZ) ;
+ pCamera->setFOVy( Degree(m_Q3Map->m_pLight[nLt].Angle ) ) ;
+
+ return true ;
+
+}
+
+
+void OgreFramework::UpdateVisibleZoneList(char* pZoneVis, unsigned short* pVisibleZoneList, int* pMaxVisibleZone)
+{
+ int nZone=0 ;
+ int nMaxVisibleZone=0 ;
+
+ for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
+ if(pZoneVis[nZone]==ZONE_VISIBLE)
+ pVisibleZoneList[nMaxVisibleZone++]=nZone ;
+
+ *pMaxVisibleZone=nMaxVisibleZone ;
+
+}
+
+void OgreFramework::SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags)
+{
+
+ int nListPos=0 ;
+ int nZone=0 ;
+ int nMaxListPos=*pMaxVisibleZone ;
+
+
+
+ for(nListPos=0 ; nListPos<nMaxListPos ; nListPos++)
+ {
+ nZone=pVisibleZoneList[nListPos] ;
+
+ // if the zone node is not already attached, attach it.
+
+ if( m_nOpaqueNodeUsed[nZone] && (nMaterialFlags&MAT_OPAQUE) && !m_pOpaqueNode[nZone]->isInSceneGraph() )
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
+
+ if( m_nTransNodeUsed[nZone] && (nMaterialFlags&MAT_GEL) && !m_pTransNode[nZone]->isInSceneGraph() )
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
+
+ if( m_nLampNodeUsed[nZone] && (nMaterialFlags&MAT_LAMP) && !m_pLampNode[nZone]->isInSceneGraph() )
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
+
+ if( m_nGlowNodeUsed[nZone] && (nMaterialFlags&MAT_GLOW) && !m_pGlowNode[nZone]->isInSceneGraph() )
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
+
+ }
+
+
+
+/*
+ if(m_nDebugLightBox)
+ {
+ int nLt=0 ;
+ int nMaxLight=m_Q3Map->m_nLightMax ;
+
+ for(nLt=0 ; nLt<nMaxLight ; nLt++)
+ if(m_chLightVis[nLt]==LIGHT_VISIBLE)
+ {
+ m_pLightMO[nLt]->setVisible(true) ;
+
+ }
+ else
+ m_pLightMO[nLt]->setVisible(false) ;
+
+
+
+ }
+
+ if(m_nPortalDebug)
+ {
+ int nPt=0 ;
+ int nMaxPortal=m_Q3Map->m_iNumPortals ;
+
+ for(nPt=0 ; nPt<nMaxPortal ; nPt++)
+ if(
+ (m_chPortalVis[nPt]&PORTAL_VISIBLE)
+ &&
+ (m_chPortalState[nPt]&PORTALSTATE_CLOSED)
+ )
+ m_pPortalMO[nPt]->setVisible(true) ;
+ else
+ m_pPortalMO[nPt]->setVisible(false) ;
+ }
+
+ */
+}
+
+
+void OgreFramework::SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags, int nLight)
+{
+
+ nLight=IGNORE_LIGHT ;
+
+ int nListPos=0 ;
+ int nZone=0 ;
+ int nMaxListPos=*pMaxVisibleZone ;
+
+ int nLightZone=0 ;
+ int nMaxLightZone=0 ;
+ int nFoundZone=0 ;
+
+
+ for(nListPos=0 ; nListPos<nMaxListPos ; nListPos++)
+ {
+ nZone=pVisibleZoneList[nListPos] ;
+
+ // is this zone touched by this light?
+ if(nLight!=IGNORE_LIGHT)
+ {
+ nMaxLightZone=m_Q3Map->m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
+
+ nFoundZone=0 ;
+ for(nLightZone=0 ; nLightZone<nMaxLightZone ; nLightZone++)
+ if(m_Q3Map->m_nLightTouchesZone[nLight][nLightZone]==nZone)
+ {
+ nFoundZone=1 ;
+ break ;
+ }
+
+ }
+ else
+ nFoundZone=1 ;
+
+
+ if(nFoundZone) // if the light touches this zone, or we're ignoring lights
+ {
+ // if the zone node is not already attached, attach it.
+
+ if( m_nOpaqueNodeUsed[nZone] && (nMaterialFlags&MAT_OPAQUE) && !m_pOpaqueNode[nZone]->isInSceneGraph() )
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
+
+ if( m_nTransNodeUsed[nZone] && (nMaterialFlags&MAT_GEL) && !m_pTransNode[nZone]->isInSceneGraph() )
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
+
+ if( m_nLampNodeUsed[nZone] && (nMaterialFlags&MAT_LAMP) && !m_pLampNode[nZone]->isInSceneGraph() )
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
+
+ if( m_nGlowNodeUsed[nZone] && (nMaterialFlags&MAT_GLOW) && !m_pGlowNode[nZone]->isInSceneGraph() )
+ m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
+ }
+ }
+
+}
+
+bool OgreFramework::LightTouchesZone(int nLight, int nZone)
+{
+ int nLightZone=0 ;
+ int nMaxLightZone=0 ;
+
+ nMaxLightZone=m_Q3Map->m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
+
+ for(nLightZone=0 ; nLightZone<nMaxLightZone ; nLightZone++)
+ if(m_Q3Map->m_nLightTouchesZone[nLight][nLightZone]==nZone)
+ return true ;
+
+ return false ;
+}
+
+
+// last chance to cull some more multizone lights
+// Then we set all zones the remaining multizone lights touch to visible so that we get correct shadows
+void OgreFramework::CheckMultiZoneLights(int nCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis)
+{
+ int nLightMax=m_Q3Map->m_nMaxMultiZoneLight ;
+ int nLight=0 ;
+ int nLightIndex=0 ;
+ int nLightVal=0 ;
+ int nOpenPortals=0 ;
+ int nZoneHasOpenPortals=0 ;
+ int nPortal=0 ;
+ int nPortalIndex=0 ;
+ int nMaxPortal=0 ;
+ int nZone=0 ;
+ int nMaxZone=0 ;
+ int nZoneIndex=0 ;
+
+ int nSubLightMax=0 ;
+ int nSubLightIndex=0 ;
+ int nSubLight=0 ;
+ int nSubLightStart=0 ;
+
+ int nPortalLightMax=0 ;
+ int nPortalLightIndex=0 ;
+ int nPortalLight=0 ;
+
+ int nCentreZone=0 ;
+
+
+ for(nLightIndex=0 ; nLightIndex<nLightMax ; nLightIndex++)
+ {
+ nLight=m_Q3Map->m_nMultiZoneLight[nLightIndex] ;
+ if(pLightVis[nLight]==LIGHT_VISIBLE) // try to kill multizone lights that are currently set as visible
+ {
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////.
+ // if the zone that contains the centre isn't visible,
+ // and the portals that the light touches are closed,
+ // then this light can't be visible anywhere else
+
+ nCentreZone=m_Q3Map->m_pLight[nLight].CentreZone ;
+
+
+ // is the zone that contains the light centre not visible?
+ if(pZoneVis[nCentreZone]!=ZONE_VISIBLE)
+ {
+ // check the portals on the centre sublight zone.
+ // If the ones that the light touches are closed,
+ // then this light can't be visible
+
+
+ nMaxPortal=m_Q3Map->m_nZoneTouchesPortal[nCentreZone][INDEX_PORTALCOUNT] ;
+ nOpenPortals=0 ;
+ nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
+
+ for(nPortalIndex=0 ; nPortalIndex<nMaxPortal ; nPortalIndex++)
+ {
+ nPortal=m_Q3Map->m_nZoneTouchesPortal[nCentreZone][nPortalIndex] ;
+
+ // if portal's open...
+ if(m_chPortalState[nPortal]&PORTALSTATE_OPEN)
+ {
+ nPortalLightMax=m_Q3Map->m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT] ;
+
+ // scan all the lights that touch this portal to see if our current light is one of them
+ for(nPortalLightIndex=0 ; nPortalLightIndex<nPortalLightMax ; nPortalLightIndex++)
+ if(m_Q3Map->m_nPortalTouchesLight[nPortal][nPortalLightIndex]==nLight)
+ {
+ nOpenPortals=1 ;
+ break ;
+ }
+
+ }// end if portal is open
+
+ if(nOpenPortals) break ; // get out if we found an open portal that the light touches
+ }// end for portals
+
+
+
+ // if none of the portals touched by the centre light were open, set this light and it's sublights to not visible
+ if(nOpenPortals==0)
+ {
+ pLightVis[nLight]=LIGHT_UNCHECKED ;
+
+ nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
+ nSubLightMax=nSubLightStart+m_Q3Map->m_pLight[nLight].ZoneCount ;
+
+ for(nSubLight=nSubLightStart ; nSubLight<nSubLightMax ; nSubLight++)
+ pSubLightVis[nSubLightStart]=LIGHT_UNCHECKED ;
+
+ }// end if no light centre portals that touched lights were open
+
+
+
+ }// end if light centre zone isn't visible
+
+ }// end if light is visibile
+
+ }// end for lightindex
+
+}
+
+
+// for lights that touch multiple zones, work out what additional zones we need to make
+// visible in order that lighting will come out with correct shadows.
+void OgreFramework::AddZonesFromMultiZoneLights(char* pZoneVis, char* pLightVis, char* pSubLightVis)
+{
+ int nLightMax=m_Q3Map->m_nMaxMultiZoneLight ;
+ int nLight=0 ;
+ int nLightIndex=0 ;
+ float flMinX=0.0f ;
+ float flMaxX=0.0f ;
+ float flMinY=0.0f ;
+ float flMaxY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxZ=0.0f ;
+
+ int nSubLightMax=0 ;
+ int nSubLightIndex=0 ;
+ int nSubLight=0 ;
+ int nSubLightStart=0 ;
+ int nSubLightFirst=0 ;
+
+ int nInnerLight=0 ;
+
+
+ for(nLightIndex=0 ; nLightIndex<nLightMax ; nLightIndex++)
+ {
+ nLight=m_Q3Map->m_nMultiZoneLight[nLightIndex] ;
+ if(pLightVis[nLight]==LIGHT_VISIBLE)
+ {
+ nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
+ nSubLightFirst=nSubLightStart+1 ;// start from the first sublight after the one containing the centre
+ nSubLightMax=nSubLightStart+m_Q3Map->m_pLight[nLight].ZoneCount ;
+
+
+ for(nSubLight=nSubLightStart ; nSubLight<nSubLightMax ; nSubLight++)
+ if(pSubLightVis[nSubLight]==LIGHT_VISIBLE) // sublight is visible (and unchecked)
+ {
+ // create the new AABB
+ // this is bounded by this sublight and the centre holding sublight.
+ 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] ;
+ 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] ;
+ 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] ;
+
+ 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] ;
+ 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] ;
+ 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] ;
+
+ for(nInnerLight=nSubLightStart ; nInnerLight<nSubLightMax ; nInnerLight++)
+ {
+
+
+ if(
+ (nInnerLight!=nSubLight) // no need to test itself
+ &&(pZoneVis[ m_Q3Map->m_SubLight[nInnerLight].Zone ] != ZONE_VISIBLE) // don't test if already visible
+ // if overlap, InnerLight's zone is visible
+ &&(flMinX<m_Q3Map->m_SubLight[nInnerLight].Max[0]) && (flMaxX>m_Q3Map->m_SubLight[nInnerLight].Min[0])
+ &&(flMinY<m_Q3Map->m_SubLight[nInnerLight].Max[1]) && (flMaxY>m_Q3Map->m_SubLight[nInnerLight].Min[1])
+ &&(flMinZ<m_Q3Map->m_SubLight[nInnerLight].Max[2]) && (flMaxZ>m_Q3Map->m_SubLight[nInnerLight].Min[2])
+ )
+ {
+ pZoneVis[ m_Q3Map->m_SubLight[nInnerLight].Zone ]=ZONE_VISIBLE ; // flag this zone as visible
+ m_nTotalTriangles+=m_nZoneTriangleCount[ m_Q3Map->m_SubLight[nInnerLight].Zone ] ; // just some stats for interest
+ }
+
+ } // end for innerlight
+
+ }// end if sublight is visible
+
+ }// end if light is visible
+
+ }// end for nLightIndex
+
+}
+
+// scan all the unchecked portals in a subzone to see if they are visible,
+// then move into any visible subzones and recurse.
+// 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
+
+// we also add visible lights if they are in the view frustum
+void 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)
+{
+ Ogre::Real OrigL, OrigR, OrigT, OrigB ; // original frustum extents
+ Ogre::Real PortalL, PortalR, PortalT, PortalB ; // frustum extents per each portal in this zone
+ pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
+
+
+
+
+ Ogre::AxisAlignedBox AAB ;
+
+
+ int nPortalMax=m_Q3Map->m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT] ;
+ int nPortalIndex=0 ;
+ int nPortal=0 ;
+
+ int nPortalZoneMax=0 ;
+ int nPortalZone=0 ;
+ int nPortalZoneIndex=0 ;
+
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ //
+ // LIGHTING CHECKS
+ //
+
+ int nLight=0;
+ int nLightVal=0 ;
+ int nLightIndex=0 ;
+ int nMaxLight=0 ;
+
+ int nSubLight=0 ;
+ int nSubLightIndex=0 ;
+ int nMaxSubLight=0 ;
+ int nSubLightVal=0 ;
+
+
+ // check all lights completely contained in this zone to see if they're visible
+ nMaxSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ;
+ for(nSubLightIndex=0 ; nSubLightIndex<nMaxSubLight ; nSubLightIndex++)
+ {
+ nSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][nSubLightIndex] ;
+ //nSubLightVal=m_chSubLightVis[nSubLight] ;
+
+ nLight=m_Q3Map->m_SubLight[nSubLight].Light ;
+ nLightVal=pLightVis[nLight] ;
+
+ // if we haven't previously established that the light is visible or out of the frustum, check it.
+
+ 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]) ;
+ if(pCamera->isVisible(AAB)) // sublight is visible
+ {
+ // flag this light and sublight as visible
+ if((nLightVal!=LIGHT_VISIBLE) && (*pMaxVisibleLight<MAXVISIBLELIGHT))
+ {
+ pVisibleLightList[*pMaxVisibleLight]=nLight ;
+ *pMaxVisibleLight=*pMaxVisibleLight+1 ;
+ }
+ pSubLightVis[nSubLight] = pLightVis[nLight] = LIGHT_VISIBLE ;
+
+ }
+
+
+ }// end for lights in zone
+
+
+ //
+ ///////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+ pZoneVis[nZone]=ZONE_VISIBLE ; // flag this zone as visible
+ m_nTotalTriangles+=m_nZoneTriangleCount[nZone] ; // just some stats for interest
+
+
+ // loop through all the portals in this zone
+ for(nPortalIndex=0 ; nPortalIndex<nPortalMax ; nPortalIndex++)
+ {
+
+
+ nPortal=m_Q3Map->m_nZoneTouchesPortal[nZone][nPortalIndex] ;
+
+
+ if((pPortalVis[nPortal]&PORTAL_VISCHECK)==0) // portal hasn't already been checked
+ {
+
+ pPortalVis[nPortal] |= PORTAL_VISCHECK ; // flag portal as vischecked
+ 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]) ;
+
+ if(pCamera->isVisible(AAB)) // portal is in the view frustum
+ {
+
+ pPortalVis[nPortal] |= PORTAL_VISIBLE ; // flag portal as visible
+
+ // if the portal is open, go in and check the new zone.
+ if(m_chPortalState[nPortal]&PORTALSTATE_OPEN)
+ {
+
+ // calculate the new frustum extents through this portal
+ PortalL=OrigL ;
+ PortalR=OrigR ;
+ PortalT=OrigT ;
+ PortalB=OrigB ;
+
+ if(CalculatePortalFrustum(pCamera, nPortal, &PortalL, &PortalR, &PortalT, &PortalB, ScaleX, ScaleY))
+ {
+
+
+
+
+
+ // Loop through all the zones attached to this portal
+ nPortalZoneMax=m_Q3Map->m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ;
+ for(nPortalZoneIndex=0 ; nPortalZoneIndex<nPortalZoneMax ; nPortalZoneIndex++)
+ {
+ nPortalZone=m_Q3Map->m_nPortalTouchesZone[nPortal][nPortalZoneIndex] ;
+ if(pZoneVis[nPortalZone]==ZONE_UNCHECKED) // don't go back into zones we've already scanned.
+ {
+
+ pCamera->setFrustumExtents(PortalL, PortalR, PortalT, PortalB) ; // set the frustum extents
+
+ // recurse
+ //m_nRecurseCount++ ;
+ PortalScan(pCamera, nPortalZone, ScaleX, ScaleY, pZoneVis, pLightVis, pSubLightVis, pPortalVis, pMaxVisibleLight, pVisibleLightList) ;
+ //m_nRecurseCount-- ;
+
+
+
+ }// end if zone hasn't already been checked
+
+ }// end scanning all zones connected by this portal
+
+ }// end if frustum is still active
+
+ }// end if portal is open
+
+ }// end if portal is in the view frustum
+
+ }// end if portal hasn't been checked
+
+ // reset the frustum
+ pCamera->setFrustumExtents(OrigL, OrigR, OrigT, OrigB) ; // reset the original frustum extents
+
+ }// end for portalindex
+
+
+}
+
+// gives new frustum settings, and returns 0 if the frustum has been killed completely.
+int 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)
+{
+
+
+ // if the camera is actually inside the portal then don't change the frustum but return OK
+ Vector3 CamPos=pCamera->getPosition() ;
+
+ if(
+ (CamPos.x>=m_Q3Map->m_pPortals[nPortal].Min[0]) && (CamPos.x<=m_Q3Map->m_pPortals[nPortal].Max[0])
+ &&(CamPos.y>=m_Q3Map->m_pPortals[nPortal].Min[1]) && (CamPos.y<=m_Q3Map->m_pPortals[nPortal].Max[1])
+ &&(CamPos.z>=m_Q3Map->m_pPortals[nPortal].Min[2]) && (CamPos.z<=m_Q3Map->m_pPortals[nPortal].Max[2])
+ )
+ return 1 ;
+
+
+
+
+
+ int nLoop=0 ;
+ int nBehindPoint=0 ; // keep track of how many transformed points are behind the camera
+ //Real OrigL=*pPortalL ;
+ //Real OrigR=*pPortalR ;
+ //Real OrigT=*pPortalT ;
+ //Real OrigB=*pPortalB ;
+
+ Real MinX=MINMAXLIMIT ;
+ Real MaxX=-MINMAXLIMIT ;
+ Real MaxY=-MINMAXLIMIT ;
+ Real MinY=MINMAXLIMIT ;
+
+
+ // set portal corners as 8 individual points. order is xyz, Xyz, xYz, XYz, xyZ, XyZ, xYZ, XYZ,
+ Vector3 xyz[8] ;
+
+
+ xyz[0].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
+ xyz[0].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
+ xyz[0].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
+
+ xyz[1].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
+ xyz[1].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
+ xyz[1].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
+
+ xyz[2].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
+ xyz[2].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
+ xyz[2].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
+
+ xyz[3].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
+ xyz[3].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
+ xyz[3].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
+
+ xyz[4].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
+ xyz[4].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
+ xyz[4].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
+
+ xyz[5].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
+ xyz[5].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
+ xyz[5].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
+
+ xyz[6].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
+ xyz[6].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
+ xyz[6].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
+
+ xyz[7].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
+ xyz[7].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
+ xyz[7].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
+
+ // transform the points to eyespace
+ for(nLoop=0 ; nLoop<8 ; nLoop++)
+ xyz[nLoop]=m_ViewMatrix*xyz[nLoop] ;//pCamera->getViewMatrix(true)*xyz[nLoop] ;
+
+ // transform the points to screen space
+ for(nLoop=0 ; nLoop<8 ; nLoop++)
+ if(xyz[nLoop].z<0) // less than zero means point is in front of camera
+ {
+ xyz[nLoop]=m_ProjectionMatrix*xyz[nLoop] ;// pCamera->getProjectionMatrix()*xyz[nLoop] ;
+ if(xyz[nLoop].x<MinX) MinX=xyz[nLoop].x ;
+ if(xyz[nLoop].x>MaxX) MaxX=xyz[nLoop].x ;
+ if(xyz[nLoop].y<MinY) MinY=xyz[nLoop].y ;
+ if(xyz[nLoop].y>MaxY) MaxY=xyz[nLoop].y ;
+
+ }
+ else // point is behind the camera
+ nBehindPoint++ ;
+
+
+
+
+ MinX*=ScaleX ;
+ MaxX*=ScaleX ;
+ MinY*=ScaleY ;
+ MaxY*=ScaleY ;
+
+ // apply the stereofrustum tweak if needed
+ //float flTweak=0.0f ;
+ //if(m_flStereoFrustumTweak!=0.0f)
+ //{
+ // MinX-=m_flStereoFrustumTweak ;
+ // MaxX+=m_flStereoFrustumTweak ;
+ //}
+
+
+ // if we have more than three behindpoints, don't cull
+ if(nBehindPoint>3) return 1 ;
+
+ // use these to cut down the frustum
+ if(MinX>*pPortalL) *pPortalL=MinX ;
+ if(MaxX<*pPortalR) *pPortalR=MaxX ;
+ if(MinY>*pPortalB) *pPortalB=MinY ;
+ if(MaxY<*pPortalT) *pPortalT=MaxY ;
+
+
+
+
+
+
+
+ // check if frustum has been cut out of existence
+ // culling at this point didn't work, so this is a hack to make if function.
+ if((*pPortalL>=*pPortalR) || (*pPortalB>=*pPortalT))
+ return 0 ;
+
+
+ /*
+ if(*pPortalL>=*pPortalR)
+ {
+ *pPortalL=(*pPortalL+*pPortalR)/2.0-0.01 ;
+ *pPortalR=*pPortalL+0.02 ;
+ }
+
+ if(*pPortalB>=*pPortalT)
+ {
+ *pPortalB=(*pPortalB+*pPortalT)/2.0-0.01 ;
+ *pPortalT=*pPortalB+0.02 ;
+ }
+ */
+
+
+ //return 0 ;
+
+
+ return 1 ;
+}
+
+
+
+
+
+
+
+
+ /***********************************************************************************************************\
+
+ LIGHTING SETUP
+
+ \***********************************************************************************************************/
+
+
+
+
+
+void OgreFramework::initLight()
+{
+ char chMessage[1024] ;
+
+ // these lights only have placeholder settings to begin with, since they get moved around and reused thoughout the level.
+
+ int nLt=0 ;
+ int nMaxLt=MAXLIGHTPERLOOP ;
+ Light *light;
+ char chLightName[1024] ;
+
+
+
+
+ for(nLt=0 ; nLt<nMaxLt ; nLt++)
+ {
+ sprintf(chLightName, "LT%02i", nLt) ;
+
+ light = m_pSceneMgr->createLight(chLightName);
+ light->setType(Light::LT_SPOTLIGHT);
+ light->setCastShadows(true);
+ light->setVisible(false) ;
+
+ }
+
+}
+
+ /***********************************************************************************************************\
+
+ CONFIG FILE
+
+ \***********************************************************************************************************/
+
+void OgreFramework::ParseBZNConfig(void)
+{
+ const int KVSIZE=1024 ;
+ // make sure the config is a string
+ int nConfigPos=-1 ;
+ int nPos=0 ;
+ int nKeyPos=0 ;
+ int nValuePos=0 ;
+
+ char chKey[KVSIZE] ;
+ char chValue[KVSIZE] ;
+ float flValue=0.0f ;
+
+
+
+ while(nConfigPos<BZN_CONFIG_SIZE)
+ {
+ // scan forward to find the next key
+ while (
+ (++nConfigPos<BZN_CONFIG_SIZE)
+ && ((m_chBZNConfig[nConfigPos]<'A') || (m_chBZNConfig[nConfigPos]>'z'))
+ ) ;
+
+ if(nConfigPos<BZN_CONFIG_SIZE)
+ {
+
+
+
+ // find the end of the key
+ nKeyPos=0 ;
+ while ((m_chBZNConfig[nConfigPos]!=' ') && (m_chBZNConfig[nConfigPos]!='/') && (m_chBZNConfig[nConfigPos]!=0x0A) && (m_chBZNConfig[nConfigPos]!=0x0D))
+ {
+ chKey[nKeyPos++]=m_chBZNConfig[nConfigPos++] ;
+ if((nConfigPos==BZN_CONFIG_SIZE) || (nKeyPos==KVSIZE))
+ break ;
+ }
+
+ if((nConfigPos<BZN_CONFIG_SIZE) && (nKeyPos<KVSIZE))
+ {
+ chKey[nKeyPos]='\0' ; // null terminate the key
+
+ // scan off the the number
+ nValuePos=0 ;
+
+
+ while ((m_chBZNConfig[nConfigPos]!=0x0A) && (m_chBZNConfig[nConfigPos]!=0x0D) && (m_chBZNConfig[nConfigPos]!='/'))
+ {
+ if(
+ ((m_chBZNConfig[nConfigPos]>='0') && (m_chBZNConfig[nConfigPos]<='9'))
+ || (m_chBZNConfig[nConfigPos]=='-')
+ || (m_chBZNConfig[nConfigPos]=='.')
+ )
+ chValue[nValuePos++]=m_chBZNConfig[nConfigPos] ;
+
+ nConfigPos++ ;
+ if((nConfigPos==BZN_CONFIG_SIZE) || (nKeyPos==KVSIZE))
+ break ;
+ }
+
+ if((nConfigPos<BZN_CONFIG_SIZE) && (nValuePos<KVSIZE))
+ {
+ chValue[nValuePos]='\0' ; // null terminate the value
+
+ // convert value string to a float
+ flValue=atof(chValue) ;
+
+ // assign that value
+ if(strcmp("r_shadowmapsize", chKey)==0) { m_nShadowMapSize=flValue ; if(m_nShadowMapSize<2) m_nShadowMapSize=2 ; }
+ if(strcmp("r_shadowrgbsize", chKey)==0) { m_nShadowRGBSize=flValue ; if(m_nShadowRGBSize<2) m_nShadowRGBSize=2 ; }
+ if(strcmp("r_colouredshadow", chKey)==0) { m_nColouredShadow=flValue ; }
+ if(strcmp("r_renderhdr", chKey)==0) { m_nRenderHDR=flValue ; }
+ if(strcmp("r_maxgpuquery", chKey)==0) { m_nMaxGPUQuery=flValue ; if(m_nMaxGPUQuery<0) m_nMaxGPUQuery=0 ; if(m_nMaxGPUQuery>MAXGPUQUERY) m_nMaxGPUQuery=MAXGPUQUERY ; }
+
+ //sprintf(m_chBug, "Key: %s, Value: %f", chKey, flValue) ;
+ //m_pLog->logMessage(m_chBug);
+
+ }// end found end of value
+
+
+
+
+
+
+
+ }// end found end of key
+
+
+
+
+
+ }// end found start of key
+
+
+
+ }// end scanning whole config
+
+
+}
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/OgreFramework.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/OgreFramework.hpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/OgreFramework.hpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/OgreFramework.hpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,724 @@
+/*
+===========================================================================
+Copyright (C) 2010 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#ifndef OGRE_FRAMEWORK_HPP
+#define OGRE_FRAMEWORK_HPP
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#include <OgreCamera.h>
+#include <OgreEntity.h>
+#include <OgreLogManager.h>
+#include <OgreOverlay.h>
+#include <OgreOverlayElement.h>
+#include <OgreOverlayManager.h>
+#include <OgreRoot.h>
+#include <OgreViewport.h>
+#include <OgreSceneManager.h>
+#include <OgreRenderWindow.h>
+#include <OgreConfigFile.h>
+#include <OgreManualObject.h>
+#include <OgreMaterialManager.h>
+#include <OgreRenderSystem.h>
+#include <OgreOverlayContainer.h>
+#include <OgreHardwarePixelBuffer.h>
+#include <OgreRenderQueueListener.h>
+#include <OgreHardwareOcclusionQuery.h>
+#include <OgreTextureUnitState.h>
+#include "OgreGpuCommandBufferFlush.h"
+
+
+#include "ExampleFrameListener.h"
+//#include <OgreFrameListener.h>
+//#include <OgreRenderTargetListener.h>
+
+
+#include <OIS/OIS.h>
+#include <OIS/OISEvents.h>
+#include <OIS/OISInputManager.h>
+#include <OIS/OISKeyboard.h>
+#include <OIS/OISMouse.h>
+
+#include "Q3Map.h"
+
+#include "JarDebug.h" //!! just for debugging, remove from final build
+
+
+#define CHECKDELETE_ARRAY(x, y) if(x) { delete [] x ; x=0 ; m_nNewCount-- ; m_nNewCheck[y]-- ;}
+#define CHECKDELETE_POINTER(x, y) if(x) { delete x ; x=0 ; m_nNewCount-- ; m_nNewCheck[y]-- ;}
+
+enum {
+ NEW_CHECK_m_pRawBspFile=0,
+ NEW_CHECK_m_Q3Map,
+ NEW_CHECK_m_pZoneMO,
+ NEW_CHECK_m_pZoneMesh,
+ NEW_CHECK_m_pZoneEntity,
+ NEW_CHECK_m_pZoneEntityMaterialType,
+ NEW_CHECK_m_pZoneEntityMaterial_Base,
+ NEW_CHECK_m_pZoneEntityMaterial_Fast,
+ NEW_CHECK_m_pZoneEntityMaterial_Black,
+ NEW_CHECK_m_pZoneEntityMaterial_DfShColour,
+ NEW_CHECK_m_pZoneEntityMaterial_Shadow,
+ NEW_CHECK_m_pZoneEntityMaterial_ShadeFront,
+ NEW_CHECK_m_pZoneEntityMaterial_ShadeBack,
+ NEW_CHECK_m_pZoneEntityMaterial_DfShPosition,
+ NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse,
+ NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB,
+ NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular,
+ NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive,
+ NEW_CHECK_m_pZoneEntityMaterial_DfShMix,
+ NEW_CHECK_pVertIndex,
+ NEW_CHECK_m_pEntityInfo,
+ NEW_CHECK_m_pVisibleEntity,
+ NEW_CHECK_m_pFrustumEntity,
+ MAX_NEW_CHECK
+} ;
+
+#define MAXFRAME 1000 // debugging/testing, copy out data on a per-frame basis
+
+#define MAXGPUQUERY 4
+
+#define MAXVISIBLELIGHT 128 // most shadow lights ever visible.
+#define MAXLIGHTPERLOOP 1 // most shadow lights rendered per deferred shader sub-loop. So shadow lights are rendered in lots of 4// no longer used
+
+#define NEARCLIP 1 // camera default near clip distance
+#define FARCLIP 10000 // camera default far clip distance
+
+#define CAMERA_EPSILON 0.000001f // small value to check for up/down cameras that would break with Ogre's fixed Yaw.
+
+#define IGNORE_LIGHT -1
+
+enum GoggleMode
+{
+ GOGGLE_MODE_OFF = 0,
+ GOGGLE_MODE_TEST,
+ GOGGLE_MODE_ON,
+ GOGGLE_MODE_MAX
+} ;
+
+#define MAT_OPAQUE 1 // Typical solid stuff. Can have emissive parts.
+#define MAT_TRANS 2 // Unused
+#define MAT_GLOW 4 // Only rendered in the deferred shader emmisive pass. Used to create the hdr bloom for light points.
+#define MAT_GEL 8 // Translucent, colours spotlights that pass through it.
+#define MAT_ALPHAPF 16 // Same as MAT_OPAQUE, but with alpha testing.
+#define MAT_LAMP 32 // The bounding boxes of deferred shading lights (lamps). Rendered as the last phase in deferred shading.
+
+#define BZN_CONFIG_SIZE 1024
+
+class rQueueListener: public Ogre::RenderQueueListener
+{
+public:
+
+ rQueueListener() {}
+ ~rQueueListener() {}
+
+ Ogre::HardwareOcclusionQuery* Query[MAXGPUQUERY] ;
+
+ void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) {}
+ void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) {}
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define MAX_SUBMESH 16 // most submeshes allowed in a mesh.
+#define MAX_ZONEPERENTITY 8 // the most zones an entity can touch at once.
+#define INDEX_ENTITYZONECOUNT 8 // index to value that holds the count of how many zones this entity touches
+#define MAX_LIGHTPERENTITY 64 // most shadowing lights that an entity can be lit by
+#define INDEX_LIGHTPERENTITY 64 // index to value
+typedef struct
+{
+ int Active ;
+ int Visible ;
+ int Frustum ;
+ int LightTouch ;
+
+ int TriangleCount ;
+
+ Ogre::Vector3 Postition ;
+ Ogre::Quaternion Orientation ;
+
+ Ogre::AxisAlignedBox AABB ;
+ Ogre::Vector3 Centre ;
+ float AABBMin[3] ;
+ float AABBMax[3] ;
+
+ unsigned short Zone[MAX_ZONEPERENTITY+1] ; // the zones this entity touches. Last value is a count of how many zones were touched.
+ unsigned short Light[MAX_LIGHTPERENTITY+1] ; // the shadow casting spotlights this entity touches. Last value is a count of how many lights.
+
+ int MaxSubMesh ;
+ int SubMeshMaterialType[MAX_SUBMESH] ;
+
+ Ogre::Entity* pEnt ;
+ Ogre::SceneNode* pMasterNode ;
+
+ Ogre::MaterialPtr Material_Base[MAX_PROJECTORTEX][MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_Fast[MAX_PROJECTORTEX][MAX_SUBMESH] ;
+
+ Ogre::MaterialPtr Material_Black[MAX_SUBMESH] ;
+
+ Ogre::MaterialPtr Material_DfShColour[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_Shadow[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_ShadeFront[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_ShadeBack[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_DfShPosition[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_DfShDiffuse[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_DfShFuncTNB[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_DfShSpecular[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_DfShEmissive[MAX_SUBMESH] ;
+ Ogre::MaterialPtr Material_DfShMix[MAX_SUBMESH] ;
+}
+ENTITYINFO;
+
+typedef struct
+{
+
+ int Type ;
+
+ Ogre::ParticleSystem* PSystem ;
+ Ogre::SceneNode* PNode ;
+
+}
+PARTICLEINFO;
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+class OgreFramework : public Ogre::Singleton<OgreFramework>, OIS::KeyListener, OIS::MouseListener, public RenderTargetListener
+{
+public:
+ OgreFramework();
+ ~OgreFramework();
+
+ int m_nNewCount ;
+ int m_nNewCheck[MAX_NEW_CHECK] ;
+
+ int m_nStartTime ;
+ int m_nTime ;
+
+ CJarDebug OFBug ; //!! just for debugging, remove from final build
+ char m_chBug[10240] ;
+ int m_nFrameTime[MAXFRAME][10] ;
+ int m_nFrame ;
+ char m_chFrame[1024] ;
+ int m_nGotInput ;
+
+ void initOgre(Ogre::String wndTitle, OIS::KeyListener *pKeyListener = 0, OIS::MouseListener *pMouseListener = 0);
+ void AdditionalSetup() ;
+
+ void updateOgre(double timeSinceLastFrame);
+ void updateStats();
+ void moveCamera();
+ void getInput();
+
+ bool isOgreToBeShutDown()const{return m_bShutDownOgre;}
+
+ bool keyPressed(const OIS::KeyEvent &keyEventRef);
+ bool keyReleased(const OIS::KeyEvent &keyEventRef);
+
+ bool mouseMoved(const OIS::MouseEvent &evt);
+ bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
+ bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
+
+ Ogre::Root* m_pRoot;
+ Ogre::SceneManager* m_pSceneMgr;
+ Ogre::RenderWindow* m_pRenderWnd;
+ Ogre::Camera* m_pCamera;
+ Ogre::Viewport* m_pViewport;
+ Ogre::Log* m_pLog;
+ Ogre::Timer* m_pTimer;
+
+ Ogre::Camera* m_pCameraCopy ;
+ Ogre::Camera* m_pCameraNoJitter ;
+
+ float m_flAspectRatio ;
+ float m_flFOV ;
+
+
+ //RawFilePtr m_pRawBspFile ; bool m_bRawBspFileIsLoaded ;
+
+ char *m_pRawBspFile ;
+ bool m_bRawBspFileIsLoaded ;
+
+ OIS::InputManager* m_pInputMgr;
+ OIS::Keyboard* m_pKeyboard;
+ OIS::Mouse* m_pMouse;
+
+ int nMap ;
+ Ogre::String m_MapName ;
+ int m_nLoadToggle ;
+
+ int m_nJumpToggle ;
+ int m_nJumpVal;
+
+ int m_nToggle ;
+
+ void UnloadMap(bool bShutdown) ;
+ int LoadMap(void) ;
+ int m_nMapLoaded ;
+
+ int m_nDebugLightBox ;
+ int m_nZoneCullingActive ;
+ int m_nPortalDebug ;
+ int m_nPortalToggle ;
+ int m_nPortalState ;
+
+ // Add this to OgreFramework and initialize it from 0 to MAXGPUQUERY
+ // If you're good you'll make it private and add some get/set functions,
+ // I just made it public for now.
+
+ // A value of 0 means don't mess with the GPU buffers at all. There
+ // might be some systems where the queries cause problems, so let the user
+ // deactivate the queries completely if desired.
+
+ // A value of 1 means we flush every frame, so no GPU command buffering.
+ // This is good for low FPS because even just 1 buffer gives noticable
+ // input lag. However users with high FPS can afford a few buffers.
+
+ int m_nMaxGPUQuery ;
+
+
+ int m_nDebugA ;
+ int m_nDebugB ;
+ int m_nDebugC ;
+ int m_nVisibleLightCount ;
+ int m_nVisibleZoneCount ;
+
+ float m_flDebugMatrix[4][4] ;
+
+ int m_nRecurseCount ;
+ char m_chDebug[10240] ;
+ float m_flDebug0 ;
+ float m_flDebug1 ;
+ float m_flDebug2 ;
+ float m_flDebug3 ;
+ float m_flDebug4 ;
+ float m_flDebug5 ;
+
+
+
+ Ogre::ManualObject* m_pGoggleL ;
+ Ogre::ManualObject* m_pGoggleR ;
+ Ogre::SceneNode* m_pNodeGoggles ;
+ int m_nGoggleMode ;
+ float m_flGoggleAspectRatio ;
+ float m_flGoggleZPos ;
+ float m_flGoggleXGap ;
+ float m_flGoggleXScale ;
+ float m_flGoggleYScale ;
+ int m_nGoggleTestImage ;
+ void DestroyGoggles() ;
+ int CreateGogglesTestImage() ;
+ int CreateGoggles() ;
+
+
+ void UpdateRenderTargets() ;
+
+ double m_GameTime ;
+
+ char m_chBZNConfig[BZN_CONFIG_SIZE] ;
+ void ParseBZNConfig(void) ;
+
+ void FinalShutdown(void) ;
+
+private:
+ OgreFramework(const OgreFramework&);
+ OgreFramework& operator= (const OgreFramework&);
+
+ Ogre::Overlay* m_pDebugOverlay;
+ Ogre::Overlay* m_pInfoOverlay;
+ int m_iNumScreenShots;
+
+ bool m_bShutDownOgre;
+
+ Ogre::Vector3 m_TranslateVector;
+ Ogre::Real m_MoveSpeed;
+ Ogre::Degree m_RotateSpeed;
+ float m_MoveScale;
+ Ogre::Degree m_RotScale;
+
+ int m_nKeyDown_Shift ;
+ int m_nKeyDown_Ctrl ;
+
+
+
+
+
+ //RawFileManager *mRawFileManager;
+
+ char* m_TempMem ;
+ Q3Map *m_Q3Map;
+
+
+ Ogre::SceneNode* m_pCubeNode;
+ Ogre::Entity* m_pCubeEntity;
+
+ Ogre::SceneNode *m_pOpaqueNode[MAX_ZONE] ;
+ int m_nOpaqueNodeUsed[MAX_ZONE] ;
+ Ogre::SceneNode *m_pTransNode[MAX_ZONE] ;
+ int m_nTransNodeUsed[MAX_ZONE] ;
+ Ogre::SceneNode *m_pLampNode[MAX_ZONE] ;
+ int m_nLampNodeUsed[MAX_ZONE] ;
+ Ogre::SceneNode *m_pGlowNode[MAX_ZONE] ;
+ int m_nGlowNodeUsed[MAX_ZONE] ;
+
+ Ogre::Matrix4 m_ViewMatrix ;
+ Ogre::Matrix4 m_ProjectionMatrix ;
+
+ Ogre::ManualObject** m_pZoneMO ; // the Zone's manualObject array
+ Ogre::MeshPtr* m_pZoneMesh ;
+ Ogre::Entity** m_pZoneEntity ;
+ int* m_pZoneEntityMaterialType ;
+
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_Base[MAX_PROJECTORTEX] ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_Fast[MAX_PROJECTORTEX] ;
+
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_Black ;
+
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShColour ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_Shadow ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_ShadeFront ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_ShadeBack ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShPosition ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShDiffuse ;
+ //Ogre::MaterialPtr* m_pZoneEntityMaterial_DSNormal ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShFuncTNB ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShSpecular ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShEmissive ;
+ //Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShData ;
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShMix ;
+
+ Ogre::MaterialPtr* m_pZoneEntityMaterial_BlurA ;
+
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ Ogre::MeshPtr* m_pGameMesh ;
+ ENTITYINFO* m_pEntityInfo ;
+ int* m_pVisibleEntity ; // entities that are in a visible zone
+ int* m_pFrustumEntity ; // entities that are in a visible zone and also in the view frustum
+
+ int m_nMaxGameMesh ;
+ int m_nMaxEntity ;
+ int m_nMaxVisibleEntity ;
+ int m_nMaxFrustumEntity ;
+ int m_nVisibleEntityTriangleCount ;
+ int m_nFrustumEntityTriangleCount ;
+ int m_nTotalTriangles ;
+ int m_nZoneTriangleCount[MAX_ZONE] ;
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ // for debugging/testing, make light volumes into meshes
+ Ogre::ManualObject** m_pLightMO ; // the manualObject array
+ int AddLightCullingBoxes(void) ;
+
+ // for debugging/testing, make portal volumes into meshes
+ Ogre::ManualObject** m_pPortalMO ; // the manualObject array
+ Ogre::Node** m_pPortalNode ; // the node of this portal
+ int AddPortalBoxes(void) ;
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+ void SetupResourceLocations() ;
+
+
+
+ float m_flStereoFrustumTweak ; // in stereoscopic mode the portal frustums might be too tight, so enlarge them a bit.
+
+
+ bool m_IsOpenGL ;
+
+
+ void initLight() ;
+
+ Ogre::Matrix4 CreateTextureViewProjectionMatrix(Ogre::Camera* pCamera) ;
+ bool SetupSingleVisibleLightAndShadowCamera(int nLt, char* pLightVis, unsigned short* pVisibleLightList, Ogre::Camera* pCamera) ;
+
+
+ int SetupParticles() ;
+ Ogre::ParticleSystem* m_ps;
+ Ogre::SceneNode* m_pParticleNode;
+
+ int m_nMaxParticleSystem ;
+
+
+ int ConstructMapFromTriangles(void) ;
+
+ int SetupGameEntities(void) ;
+ int SetupEntity(int nEntity, char *chMeshName) ;
+
+
+
+ int m_nKeyToggle[OIS::KC_MEDIASELECT+1] ; // for preventing multiple key triggers when needed.
+
+ int m_nFlashLight ;
+
+
+
+
+
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // left/mono visibility info
+ char m_chZoneVisL[MAX_ZONE] ;
+ char m_chLightVisL[MAX_LIGHT] ;
+ char m_chSubLightVisL[MAX_SUBLIGHT] ;
+ char m_chPortalVisL[MAX_PORTAL] ;
+ int m_nMaxVisibleZoneL ;
+ unsigned short m_uVisibleZoneListL[MAX_ZONE] ; // if MAX_ZONE goes above 65536 this will need to change to an int
+ int m_nMaxVisibleLightL ;
+ unsigned short m_uVisibleLightListL[MAXVISIBLELIGHT]; // if MAX_LIGHT goes above 65536 this will need to change to an int
+ int m_nCameraZoneL ; // zone player left eye is in.
+
+ // right visibility info
+ char m_chZoneVisR[MAX_ZONE] ;
+ char m_chLightVisR[MAX_LIGHT] ;
+ char m_chSubLightVisR[MAX_SUBLIGHT] ;
+ char m_chPortalVisR[MAX_PORTAL] ;
+ int m_nMaxVisibleZoneR ;
+ unsigned short m_uVisibleZoneListR[MAX_ZONE] ; // if MAX_ZONE goes above 65536 this will need to change to an int
+ int m_nMaxVisibleLightR ;
+ unsigned short m_uVisibleLightListR[MAXVISIBLELIGHT]; // if MAX_LIGHT goes above 65536 this will need to change to an int
+ int m_nCameraZoneR ; // zone player right eye is in.
+
+ int m_nCameraZone ; // zone player is in.
+
+
+
+
+
+ char* m_pGlobal_ZoneVis ;
+ char* m_pGlobal_LightVis ;
+ unsigned short* m_pGlobal_VisibleZoneList ;
+ int* m_pGlobal_MaxVisibleZone ;
+ unsigned short* m_pGlobal_VisibleLightList ;
+ int* m_pGlobal_MaxVisibleLight ;
+
+ char m_chPortalState[MAX_PORTAL] ;
+
+ int m_nMaxVisibleLight ;
+
+
+
+
+
+
+
+ int m_nZoneMOStart[MAX_ZONE+1] ; // index into m_pZoneMO for each zone, since each material within a zone is another manualObject.
+
+ void CalculateZoneVisibility(Ogre::Camera* pCamera, int *pCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis, char* pPortalVis, int* pMaxVisibleLight, unsigned short* pVisibleLightList) ;
+ void SetupEntityZones(void) ;
+ void CalculateEntityVisibility(Ogre::Camera* pCamera, char* pZoneVis) ;
+
+ void SetAllLightsOff(void) ;
+ void SetSingleVisibleLight(int nLt, bool bOn) ;
+ void UpdateVisibleZoneList(char* pZoneVis, unsigned short* pVisibleZoneList, int* pMaxVisibleZone) ;
+
+ void SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags) ;
+ void SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags, int nLight) ;
+ bool LightTouchesZone(int nLight, int nZone) ;
+
+ void 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) ;
+ int m_nOriginalZoneOpenPortals ;
+ void CheckMultiZoneLights(int nCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis) ;
+ void AddZonesFromMultiZoneLights(char* pZoneVis, char* pLightVis, char* pSubLightVis) ;
+ int CalculatePortalFrustum(Ogre::Camera *pCamera, int nPortal, Ogre::Real* pPortalL, Ogre::Real* pPortalR, Ogre::Real* pPortalT, Ogre::Real* pPortalB, Ogre::Real ScaleX, Ogre::Real ScaleY) ;
+
+
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ //int ApplyCGDefines(void) ;
+
+
+
+
+ int m_nSpeedRender ;
+ int m_nRenderHDR ;
+ int m_nColouredShadow ;
+ int m_nShadowMapSize ;
+ int m_nShadowRGBSize ;
+
+ int m_nDisplayInfoMode ;
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // render to texture quasi-deferred shading stuff
+
+ void CreateRTTAssets() ;
+ void DestroyRTTAssets() ;
+ int m_nRTTAssetsExist ;
+
+ // Shadow
+ Rectangle2D* miniScreen_Shadow;
+ Ogre::SceneNode* miniScreenNode_Shadow;
+ Ogre::TexturePtr RTT_Texture_Shadow ;
+ Ogre::RenderTexture* renderTexture_Shadow ;
+ Ogre::MaterialPtr RTT_Mat_Shadow ;
+ Ogre::Technique* RTT_Technique_Shadow ;
+
+ // ShadeFront
+ Rectangle2D* miniScreen_ShadeFront;
+ Ogre::SceneNode* miniScreenNode_ShadeFront;
+ Ogre::TexturePtr RTT_Texture_ShadeFront ;
+ Ogre::RenderTexture* renderTexture_ShadeFront ;
+ Ogre::MaterialPtr RTT_Mat_ShadeFront ;
+ Ogre::Technique* RTT_Technique_ShadeFront ;
+
+ // ShadeBack
+ Rectangle2D* miniScreen_ShadeBack;
+ Ogre::SceneNode* miniScreenNode_ShadeBack;
+ Ogre::TexturePtr RTT_Texture_ShadeBack ;
+ Ogre::RenderTexture* renderTexture_ShadeBack ;
+ Ogre::MaterialPtr RTT_Mat_ShadeBack ;
+ Ogre::Technique* RTT_Technique_ShadeBack ;
+
+ // DfShPosition
+ Rectangle2D* miniScreen_DfShPosition;
+ SceneNode* miniScreenNode_DfShPosition;
+ TexturePtr RTT_Texture_DfShPosition ;
+ RenderTexture* renderTexture_DfShPosition ;
+ MaterialPtr RTT_Mat_DfShPosition ;
+ Technique* RTT_Technique_DfShPosition ;
+ RenderTargetListener* Listener_DfShPosition ;
+
+ // DfShDiffuse
+ Rectangle2D* miniScreen_DfShDiffuse;
+ Ogre::SceneNode* miniScreenNode_DfShDiffuse;
+ Ogre::TexturePtr RTT_Texture_DfShDiffuse ;
+ Ogre::RenderTexture* renderTexture_DfShDiffuse ;
+ Ogre::MaterialPtr RTT_Mat_DfShDiffuse ;
+ Ogre::Technique* RTT_Technique_DfShDiffuse ;
+
+ /*
+ // DSNormal // UNUSED
+ Rectangle2D* miniScreen_DSNormal;
+ Ogre::SceneNode* miniScreenNode_DSNormal;
+ Ogre::TexturePtr RTT_Texture_DSNormal ;
+ Ogre::RenderTexture* renderTexture_DSNormal ;
+ Ogre::MaterialPtr RTT_Mat_DSNormal ;
+ Ogre::Technique* RTT_Technique_DSNormal ;
+ */
+
+ // DfShFuncTNB
+ Rectangle2D* miniScreen_DfShFuncTNB;
+ Ogre::SceneNode* miniScreenNode_DfShFuncTNB;
+ Ogre::TexturePtr RTT_Texture_DfShFuncTNB ;
+ Ogre::RenderTexture* renderTexture_DfShFuncTNB ;
+ Ogre::MaterialPtr RTT_Mat_DfShFuncTNB ;
+ Ogre::Technique* RTT_Technique_DfShFuncTNB ;
+
+ // DfShSpecular
+ Rectangle2D* miniScreen_DfShSpecular;
+ Ogre::SceneNode* miniScreenNode_DfShSpecular;
+ Ogre::TexturePtr RTT_Texture_DfShSpecular ;
+ Ogre::RenderTexture* renderTexture_DfShSpecular ;
+ Ogre::MaterialPtr RTT_Mat_DfShSpecular ;
+ Ogre::Technique* RTT_Technique_DfShSpecular ;
+
+ // DfShEmissive
+ Rectangle2D* miniScreen_DfShEmissive;
+ Ogre::SceneNode* miniScreenNode_DfShEmissive;
+ Ogre::TexturePtr RTT_Texture_DfShEmissive ;
+ Ogre::RenderTexture* renderTexture_DfShEmissive ;
+ Ogre::MaterialPtr RTT_Mat_DfShEmissive ;
+ Ogre::Technique* RTT_Technique_DfShEmissive ;
+
+ // DfShLamp
+ Rectangle2D* miniScreen_DfShLamp;
+ Ogre::SceneNode* miniScreenNode_DfShLamp;
+ Ogre::TexturePtr RTT_Texture_DfShLamp ;
+ Ogre::RenderTexture* renderTexture_DfShLamp ;
+ Ogre::MaterialPtr RTT_Mat_DfShLamp ;
+ Ogre::Technique* RTT_Technique_DfShLamp ;
+
+ /*
+ // DfShData
+ Rectangle2D* miniScreen_DfShData;
+ Ogre::SceneNode* miniScreenNode_DfShData;
+ Ogre::TexturePtr RTT_Texture_DfShData ;
+ Ogre::RenderTexture* renderTexture_DfShData ;
+ Ogre::MaterialPtr RTT_Mat_DfShData ;
+ Ogre::Technique* RTT_Technique_DfShData ;
+ */
+
+ // DfShMix
+ Rectangle2D* miniScreen_DfShMix;
+ Ogre::SceneNode* miniScreenNode_DfShMix;
+ Ogre::TexturePtr RTT_Texture_DfShMix ;
+ Ogre::RenderTexture* renderTexture_DfShMix ;
+ Ogre::MaterialPtr RTT_Mat_DfShMix ;
+ Ogre::Technique* RTT_Technique_DfShMix ;
+
+
+ // DfShTemp
+ Rectangle2D* miniScreen_DfShTemp;
+ Ogre::SceneNode* miniScreenNode_DfShTemp;
+ Ogre::TexturePtr RTT_Texture_DfShTemp ;
+ Ogre::RenderTexture* renderTexture_DfShTemp ;
+ Ogre::MaterialPtr RTT_Mat_DfShTemp ;
+ Ogre::Technique* RTT_Technique_DfShTemp ;
+
+ Rectangle2D* miniScreen_DfShMaster;
+ Ogre::SceneNode* miniScreenNode_DfShMaster;
+
+ int m_nRTTWidth ;
+ int m_nRTTHeight ;
+
+ // blur for hdr
+ Rectangle2D* miniScreen_BlurA;
+ Ogre::SceneNode* miniScreenNode_BlurA;
+ Ogre::TexturePtr RTT_Texture_BlurA ;
+ Ogre::RenderTexture* renderTexture_BlurA ;
+ Ogre::MaterialPtr RTT_Mat_BlurA ;
+ Ogre::Technique* RTT_Technique_BlurA ;
+
+ Rectangle2D* miniScreen_BlurB;
+ Ogre::SceneNode* miniScreenNode_BlurB;
+ Ogre::TexturePtr RTT_Texture_BlurB ;
+ Ogre::RenderTexture* renderTexture_BlurB ;
+ Ogre::MaterialPtr RTT_Mat_BlurB ;
+ Ogre::Technique* RTT_Technique_BlurB ;
+
+
+
+ Ogre::MaterialPtr pClearMaterial ;
+
+
+};
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#endif
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/OgreFramework.hpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,105 @@
+#include "OgreGpuCommandBufferFlush.h"
+#include "OgreRoot.h"
+#include "OgreRenderSystem.h"
+#include "OgreHardwareOcclusionQuery.h"
+
+namespace Ogre
+{
+ //---------------------------------------------------------------------
+ GpuCommandBufferFlush::GpuCommandBufferFlush()
+ : mUseOcclusionQuery(true)
+ , mMaxQueuedFrames(2)
+ , mCurrentFrame(0)
+ , mStartPull(false)
+ , mStarted(false)
+ {
+
+ }
+ //---------------------------------------------------------------------
+ GpuCommandBufferFlush::~GpuCommandBufferFlush()
+ {
+ stop();
+ }
+ //---------------------------------------------------------------------
+ void GpuCommandBufferFlush::start(size_t maxQueuedFrames)
+ {
+ if (!Root::getSingletonPtr() || !Root::getSingletonPtr()->getRenderSystem())
+ return;
+
+ stop();
+ mMaxQueuedFrames = maxQueuedFrames;
+ RenderSystem* rsys = Root::getSingleton().getRenderSystem();
+ mUseOcclusionQuery = rsys->getCapabilities()->hasCapability(RSC_HWOCCLUSION);
+
+ if (mUseOcclusionQuery)
+ {
+ for (size_t i = 0; i < mMaxQueuedFrames; ++i)
+ {
+ HardwareOcclusionQuery* hoq = rsys->createHardwareOcclusionQuery();
+ mHOQList.push_back(hoq);
+ }
+ }
+
+ mCurrentFrame = 0;
+ mStartPull = false;
+
+ Root::getSingleton().addFrameListener(this);
+
+ mStarted = true;
+
+ }
+ //---------------------------------------------------------------------
+ void GpuCommandBufferFlush::stop()
+ {
+ if (!mStarted || !Root::getSingletonPtr() || !Root::getSingletonPtr()->getRenderSystem())
+ return;
+
+ RenderSystem* rsys = Root::getSingleton().getRenderSystem();
+ for (HOQList::iterator i = mHOQList.begin(); i != mHOQList.end(); ++i)
+ {
+ rsys->destroyHardwareOcclusionQuery(*i);
+ }
+ mHOQList.clear();
+
+ Root::getSingleton().removeFrameListener(this);
+
+ mStarted = false;
+
+ }
+ //---------------------------------------------------------------------
+ bool GpuCommandBufferFlush::frameStarted(const FrameEvent& evt)
+ {
+ if (mUseOcclusionQuery)
+ {
+
+ mHOQList[mCurrentFrame]->beginOcclusionQuery();
+
+ }
+
+ return true;
+ }
+ //---------------------------------------------------------------------
+ bool GpuCommandBufferFlush::frameEnded(const FrameEvent& evt)
+ {
+ if (mUseOcclusionQuery)
+ {
+ mHOQList[mCurrentFrame]->endOcclusionQuery();
+ }
+ mCurrentFrame = (mCurrentFrame + 1) % mMaxQueuedFrames;
+ // If we've wrapped around, time to start pulling
+ if (mCurrentFrame == 0)
+ mStartPull = true;
+
+ if (mStartPull)
+ {
+ unsigned int dummy;
+ mHOQList[mCurrentFrame]->pullOcclusionQuery(&dummy);
+ }
+
+ return true;
+ }
+ //---------------------------------------------------------------------
+
+
+}
+
Property changes on: code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.h
===================================================================
--- code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.h (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.h 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,43 @@
+#ifndef __GPUCOMMANDBUFFERFLUSH_H__
+#define __GPUCOMMANDBUFFERFLUSH_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreFrameListener.h"
+
+namespace Ogre
+{
+
+ /** Helper class which can assist you in making sure the GPU command
+ buffer is regularly flushed, so in cases where the CPU is outpacing the
+ GPU we do not hit a situation where the CPU suddenly has to stall to
+ wait for more space in the buffer.
+ */
+ class GpuCommandBufferFlush : public FrameListener
+ {
+ protected:
+ bool mUseOcclusionQuery;
+ typedef std::vector<HardwareOcclusionQuery*> HOQList;
+ HOQList mHOQList;
+ size_t mMaxQueuedFrames;
+ size_t mCurrentFrame;
+ bool mStartPull;
+ bool mStarted;
+
+ public:
+ GpuCommandBufferFlush();
+ virtual ~GpuCommandBufferFlush();
+
+ void start(size_t maxQueuedFrames = 2);
+ void stop();
+ bool frameStarted(const FrameEvent& evt);
+ bool frameEnded(const FrameEvent& evt);
+
+ };
+
+
+}
+
+
+#endif
+
+
Property changes on: code/branches/fps/src/libraries/tools/fps/OgreGpuCommandBufferFlush.h
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/Q3Map.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/Q3Map.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/Q3Map.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,4881 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+Copyright (C) 2009 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// Q3Map.cpp -- handles the map data
+
+#include <string>
+#include <math.h>
+
+#include "Q3Map.h"
+#include "Q3Map_misc.h"
+
+
+//temp
+//#include <io.h>
+//#include <fcntl.h> /* Needed only for _O_RDWR definition */
+//#include <sys/stat.h>
+
+Q3Map::Q3Map()
+{
+ m_nDebugA=0 ;
+
+ m_nNewCount=0 ;
+
+ m_pTexturesOrig=NULL ;
+ m_pFaces=NULL ;
+ m_pVertices=NULL ;
+ m_pMeshVerts=NULL ;
+ m_pLeafs=NULL ;
+ m_pLeafFaces=NULL ;
+ m_pPlanes=NULL ;
+ m_pNodes=NULL ;
+
+ //m_VisData->vecs=NULL ; // can't NULL this because m_VisData doesn't exist yet!
+ m_VisData=NULL ;
+
+ m_pBrushes=NULL ;
+ m_pLeafBrushes=NULL ;
+ m_pBrushSides=NULL ;
+ m_pLightMaps=NULL ;
+ m_pEntities=NULL ;
+
+ m_pSubZones=NULL ;
+ m_pPortals=NULL ;
+ //////////////////////////////////////////////////////
+
+ // initiallize our triangle memory management
+ m_nTriangleSize=0 ;
+ m_pTriangleMem=NULL ;
+ m_pTriangle=NULL ;
+ m_nTriangleMax=0 ;
+ m_nTriangleLimit=0 ;
+
+ m_nVertexSize=0 ;
+ m_pVertexMem=NULL ;
+ m_pVertex=NULL ;
+ m_nVertexMax=0 ;
+ m_nVertexLimit=0 ;
+
+ m_nLightSize=0 ;
+ m_pLightMem=NULL ;
+ m_pLight=NULL ;
+ m_nLightMax=0 ;
+ m_nLightLimit=0 ;
+ m_nMaxMultiZoneLight=0 ;
+
+ m_nLampSize=0 ;
+ m_pLampMem=NULL ;
+ m_pLamp=NULL ;
+ m_nLampMax=0 ;
+ m_nLampLimit=0 ;
+
+ m_nTextureSize=0 ;
+ m_pTextureMem=NULL ;
+ m_pTexture=NULL ;
+ m_nTextureMax=0 ;
+ m_nTextureLimit=0 ;
+
+ m_nTexLampSize=0 ;
+ m_pTexLampMem=NULL ;
+ m_pTexLamp=NULL ;
+ m_nTexLampMax=0 ;
+ m_nTexLampLimit=0 ;
+
+ m_BspFaces=NULL;
+
+ m_pTransTexture=NULL ;
+
+
+ Q3Bug.LogInit() ;
+
+}
+
+Q3Map::~Q3Map()
+{
+ Q3Bug.LogSave("Q3Bug.log") ;
+
+ DELETE_ARRAY(m_pTransTexture) ;
+ //DELETE_ARRAY(m_pSubZones) ;
+ DELETE_ARRAY(mVisibleFaces) ;
+
+ FreeLightMemory() ;
+ FreeLampMemory() ;
+ FreeVertexMemory() ;
+ FreeTriangleMemory() ;
+ FreeTextureMemory() ;
+ FreeTexLampMemory() ;
+ DestroyBspFacesMemory() ; // free up face and patch data. Normally already done if we're just loading a new level or quitting, but we might also be here due to a loading fail or something.
+
+ // no need to delete any of the pointers to the lumps since their memory belongs to m_pRawBspFile over in OgreFramework.
+
+
+}
+
+void Q3Map::DestroyBspFacesMemory(void)
+{
+ if(m_BspFaces)
+ {
+ // clean up any memory declared for patches
+ for (int i=0; i < m_NumBspFaces; i++)
+ if ((m_BspFaces[i].type == PATCH) && (m_BspFaces[i].patch != NULL))
+ {
+ DELETE_ARRAY( m_BspFaces[i].patch->bezier ) ;
+ DELETE_POINTER( m_BspFaces[i].patch ) ;
+ }
+
+ // delete the faces memory
+ DELETE_ARRAY( m_BspFaces ) ;
+ }
+}
+
+
+
+int Q3Map::parseMap(const char* pMem, size_t Size)
+{
+ // we check all lump info to make sure it isn't trying to go out of bounds,
+ // in case some mangled bsp is trying to do something devious or is just corrupted
+
+
+
+
+
+ m_BspHeader=*((Q3BspHeader_t*)pMem) ; // pointer to the header
+
+ // run a check that the total size of all the iLengths plus the header isn't too large
+ size_t TotalLength=sizeof(Q3BspHeader_t) ; // initialize to the size of the header
+ int nLump=0 ;
+ int nOther=0 ;
+ int nLumpMin=0 ;
+ int nLumpMax=0 ;
+ int nOtherMin=0 ;
+ int nOtherMax=0 ;
+ for(nLump=0 ; nLump<MAX_LUMP ; nLump++)
+ {
+ if(m_BspHeader.Lumps[nLump].iLength<0) return -1 ; // lumps shouldn't have a negative size. FAIL!
+ if(m_BspHeader.Lumps[nLump].iLength>MAX_LUMP_SIZE) return -2 ; // no lump has a right to be this big... FAIL!
+
+
+ if( (m_BspHeader.Lumps[nLump].iLength>0) && (m_BspHeader.Lumps[nLump].iOffset<sizeof(Q3BspHeader_t)) )
+ return -3 ; // lump overlaps header, FAIL!
+
+ if((m_BspHeader.Lumps[nLump].iLength==0) && (m_BspHeader.Lumps[nLump].iOffset!=0))
+ return -4 ; // lump size is zero and yet offset is not zero??? FAIL!
+
+
+ TotalLength+=m_BspHeader.Lumps[nLump].iLength ;
+ if(TotalLength>Size) return -5 ;// this file is messed up, the lumps add up to more than the file size. FAIL!
+
+ // make sure this lump doesn't overlap any other lumps
+ nLumpMin=m_BspHeader.Lumps[nLump].iOffset ;
+ nLumpMax=nLumpMin+m_BspHeader.Lumps[nLump].iLength-1 ;
+
+ for(nOther=nLump+1 ; nOther<MAX_LUMP ; nOther++)
+ if((m_BspHeader.Lumps[nLump].iLength>0) && (m_BspHeader.Lumps[nOther].iLength>0)) // don't check zero sized lumps
+ {
+ nOtherMin=m_BspHeader.Lumps[nOther].iOffset ;
+ nOtherMax=nOtherMin+m_BspHeader.Lumps[nOther].iLength-1 ;
+
+ if((nLumpMax>=nOtherMin) && (nLumpMin<=nOtherMax))
+ return -6 ; // lump overlaps another lump, FAIL!
+ }
+ }
+
+
+
+
+ // setup pointers to the lumps
+
+ if((m_BspHeader.Lumps[0].iOffset<0) || (m_BspHeader.Lumps[0].iOffset>=Size)) return -7 ; // fail if out of memory bounds
+ m_pEntities=(char*)(pMem+m_BspHeader.Lumps[0].iOffset) ;
+
+ if((m_BspHeader.Lumps[Faces].iOffset<0) || (m_BspHeader.Lumps[Faces].iOffset>=Size)) return -8 ; // out of bounds
+ if(m_BspHeader.Lumps[Faces].iOffset+m_BspHeader.Lumps[Faces].iLength>Size) return -9 ; // out of bounds
+ m_iNumFaces = m_BspHeader.Lumps[Faces].iLength / sizeof(Q3BspFace_t);
+ m_pFaces=(Q3BspFace_t*)(pMem+m_BspHeader.Lumps[Faces].iOffset) ;
+
+ if((m_BspHeader.Lumps[Vertices].iOffset<0) || (m_BspHeader.Lumps[Vertices].iOffset>=Size)) return -10 ; // out of bounds
+ if(m_BspHeader.Lumps[Vertices].iOffset+m_BspHeader.Lumps[Vertices].iLength>Size) return -11 ; // out of bounds
+ m_iNumVertices = m_BspHeader.Lumps[Vertices].iLength / sizeof(Q3BspVertex);
+ m_pVertices=(Q3BspVertex*)(pMem+m_BspHeader.Lumps[Vertices].iOffset) ;
+
+ if((m_BspHeader.Lumps[MeshVerts].iOffset<0) || (m_BspHeader.Lumps[MeshVerts].iOffset>=Size)) return -12 ; // out of bounds
+ if(m_BspHeader.Lumps[MeshVerts].iOffset+m_BspHeader.Lumps[MeshVerts].iLength>Size) return -13 ; // out of bounds
+ m_iNumMeshVerts = m_BspHeader.Lumps[MeshVerts].iLength / sizeof(int);
+ m_pMeshVerts=(int*)(pMem+m_BspHeader.Lumps[MeshVerts].iOffset) ;
+
+ if((m_BspHeader.Lumps[Leafs].iOffset<0) || (m_BspHeader.Lumps[Leafs].iOffset>=Size)) return -14 ; // out of bounds
+ if(m_BspHeader.Lumps[Leafs].iOffset+m_BspHeader.Lumps[Leafs].iLength>Size) return -15 ; // out of bounds
+ m_iNumLeafs = m_BspHeader.Lumps[Leafs].iLength / sizeof(Q3BspLeaf);
+ m_pLeafs=(Q3BspLeaf*)(pMem+m_BspHeader.Lumps[Leafs].iOffset) ;
+
+ if((m_BspHeader.Lumps[LeafFaces].iOffset<0) || (m_BspHeader.Lumps[LeafFaces].iOffset>=Size)) return -16 ; // out of bounds
+ if(m_BspHeader.Lumps[LeafFaces].iOffset+m_BspHeader.Lumps[LeafFaces].iLength>Size) return -17 ; // out of bounds
+ m_iNumLeafFaces = m_BspHeader.Lumps[LeafFaces].iLength / sizeof(int);
+ m_pLeafFaces=(int*)(pMem+m_BspHeader.Lumps[LeafFaces].iOffset) ;
+
+ if((m_BspHeader.Lumps[LeafBrushes].iOffset<0) || (m_BspHeader.Lumps[LeafBrushes].iOffset>=Size)) return -18 ; // out of bounds
+ if(m_BspHeader.Lumps[LeafBrushes].iOffset+m_BspHeader.Lumps[LeafBrushes].iLength>Size) return -19 ; // out of bounds
+ m_iNumLeafBrushes = m_BspHeader.Lumps[LeafBrushes].iLength / sizeof(int);
+ m_pLeafBrushes=(int*)(pMem+m_BspHeader.Lumps[LeafBrushes].iOffset) ;
+
+ if((m_BspHeader.Lumps[Textures].iOffset<0) || (m_BspHeader.Lumps[Textures].iOffset>=Size)) return -20 ; // out of bounds
+ if(m_BspHeader.Lumps[Textures].iOffset+m_BspHeader.Lumps[Textures].iLength>Size) return -21 ; // out of bounds
+ m_iNumTexs = m_BspHeader.Lumps[Textures].iLength / sizeof(Q3BspTexture);
+ m_pTexturesOrig=(Q3BspTexture*)(pMem+m_BspHeader.Lumps[Textures].iOffset) ;
+
+ if((m_BspHeader.Lumps[Planes].iOffset<0) || (m_BspHeader.Lumps[Planes].iOffset>=Size)) return -22 ; // out of bounds
+ if(m_BspHeader.Lumps[Planes].iOffset+m_BspHeader.Lumps[Planes].iLength>Size) return -23 ; // out of bounds
+ m_iNumPlanes = m_BspHeader.Lumps[Planes].iLength / sizeof(Q3BspPlane);
+ m_pPlanes=(Q3BspPlane*)(pMem+m_BspHeader.Lumps[Planes].iOffset) ;
+
+ if((m_BspHeader.Lumps[Nodes].iOffset<0) || (m_BspHeader.Lumps[Nodes].iOffset>=Size)) return -24 ; // out of bounds
+ if(m_BspHeader.Lumps[Nodes].iOffset+m_BspHeader.Lumps[Nodes].iLength>Size) return -25 ; // out of bounds
+ m_iNumNodes = m_BspHeader.Lumps[Nodes].iLength / sizeof(Q3BspNode);
+ m_pNodes=(Q3BspNode*)(pMem+m_BspHeader.Lumps[Nodes].iOffset) ;
+
+ //m_iNumModels = m_BspHeader.Lumps[Models].iLength / sizeof(Q3BspModel);
+ //m_pModels = new Q3BspModel[m_iNumModels];
+
+ // bzn doesn't use lightmaps
+ //m_iNumLightMaps = m_BspHeader.Lumps[LightMaps].iLength / sizeof(Q3BspLightMap);
+ //m_pLightMaps=(Q3BspLightMap*)(pMem+m_BspHeader.Lumps[LightMaps].iOffset) ;
+
+ if((m_BspHeader.Lumps[Brushes].iOffset<0) || (m_BspHeader.Lumps[Brushes].iOffset>=Size)) return -26 ; // out of bounds
+ if(m_BspHeader.Lumps[Brushes].iOffset+m_BspHeader.Lumps[Brushes].iLength>Size) return -27 ; // out of bounds
+ m_iNumBrushes = m_BspHeader.Lumps[Brushes].iLength / sizeof(Q3BspBrush);
+ m_pBrushes=(Q3BspBrush*)(pMem+m_BspHeader.Lumps[Brushes].iOffset) ;
+
+
+ if((m_BspHeader.Lumps[BrushSides].iOffset<0) || (m_BspHeader.Lumps[BrushSides].iOffset>=Size)) return -28 ; // out of bounds
+ if(m_BspHeader.Lumps[BrushSides].iOffset+m_BspHeader.Lumps[BrushSides].iLength>Size) return -29 ; // out of bounds
+ m_iNumBrushSides = m_BspHeader.Lumps[BrushSides].iLength / sizeof(Q3BspBrushSide);
+ m_pBrushSides=(Q3BspBrushSide*)(pMem+m_BspHeader.Lumps[BrushSides].iOffset) ;
+
+ //m_iNumEffects = m_BspHeader.Lumps[Effects].iLength / sizeof(Q3BspEffect);
+ //m_pEffects = new Q3BspEffect[m_iNumEffects];
+ //
+ //m_pImages = new BDTexture[m_iNumTexs];
+
+ // bzn doesn't use visdata
+ //m_VisData=(Q3BspVisData*)(pMem+m_BspHeader.Lumps[VisData].iOffset) ;
+ //m_VisData->vecs=(unsigned char*)(pMem+m_BspHeader.Lumps[VisData].iOffset + 2*sizeof(int)) ;
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // bzn specific data
+ if((m_BspHeader.Lumps[SubZoneData].iOffset<0) || (m_BspHeader.Lumps[SubZoneData].iOffset>=Size)) return -30 ; // out of bounds
+ if(m_BspHeader.Lumps[SubZoneData].iOffset+m_BspHeader.Lumps[SubZoneData].iLength>Size) return -31 ; // out of bounds
+ m_iNumSubZones = m_BspHeader.Lumps[SubZoneData].iLength / sizeof(BZN_SubZone_t);
+ m_pSubZones=(BZN_SubZone_t*)(pMem+m_BspHeader.Lumps[SubZoneData].iOffset) ;
+
+ if((m_BspHeader.Lumps[PortalData].iOffset<0) || (m_BspHeader.Lumps[PortalData].iOffset>=Size)) return -32 ; // out of bounds
+ if(m_BspHeader.Lumps[PortalData].iOffset+m_BspHeader.Lumps[PortalData].iLength>Size) return -33 ; // out of bounds
+ m_iNumPortals = m_BspHeader.Lumps[PortalData].iLength / sizeof(BZN_Portal_t);
+ m_pPortals=(BZN_Portal_t*)(pMem+m_BspHeader.Lumps[PortalData].iOffset) ;
+
+
+
+
+
+
+ // fix coords and setup face memory
+ swizzleCoords();
+ mVisibleFaces = new int[m_iNumFaces];
+
+
+ // we need a new version of the textures, because when we parse the lights they will have textures to add to it,
+ // and we can't expand the texture lump because it's in the middle of a block of memory containing all the lumps.
+
+ // copy the texture lump
+ int nTexture=0 ;
+ for(nTexture=0 ; nTexture<m_iNumTexs ; nTexture++)
+ {
+ if(!AddTexture(m_pTexturesOrig[nTexture])) return -34 ; // failed to add texture, probably out of memory
+ }
+
+ return 0 ;
+
+}
+
+
+void Q3Map::swizzleCoords(void)
+{
+ //DEBUG_OUTPUT("swizziling data...");
+ // vertices
+ for (int i=0; i < m_iNumVertices; i++)
+ {
+ swizzleFloat3(m_pVertices[i].position);
+ swizzleFloat3(m_pVertices[i].normal);
+ //m_pVertices[i].texcoord[0][0] = 1.0f - m_pVertices[i].texcoord[0][0];
+ }
+
+ // leafs
+ for (int i=0; i < m_iNumLeafs; i++)
+ {
+ swizzleInt3(m_pLeafs[i].maxs);
+ swizzleInt3(m_pLeafs[i].mins);
+ }
+
+ // faces, do lightmaps later...
+ for (int i=0; i < m_iNumFaces; i++)
+ {
+ swizzleFloat3(m_pFaces[i].normal);
+ }
+
+ // planes
+ for (int i=0; i < m_iNumPlanes; i++)
+ {
+ swizzleFloat3(m_pPlanes[i].normal);
+ }
+
+ // nodes
+ for (int i=0; i < m_iNumNodes; i++)
+ {
+ swizzleInt3(m_pNodes[i].maxs);
+ swizzleInt3(m_pNodes[i].mins);
+ }
+
+
+ // subzones
+ float flTemp=0.0f ;
+ for (int i=0; i < m_iNumSubZones; i++)
+ {
+ swizzleFloat3(m_pSubZones[i].Max);
+ swizzleFloat3(m_pSubZones[i].Min);
+
+ // swizzling will mix up z max and min due to the sign change, so swap them
+ flTemp=m_pSubZones[i].Max[2] ;
+ m_pSubZones[i].Max[2]=m_pSubZones[i].Min[2] ;
+ m_pSubZones[i].Min[2]=flTemp ;
+
+ }
+
+ // portals
+ for (int i=0; i < m_iNumPortals; i++)
+ {
+ swizzleFloat3(m_pPortals[i].Max);
+ swizzleFloat3(m_pPortals[i].Min);
+
+ // swizzling will mix up z max and min due to the sign change, so swap them
+ flTemp=m_pPortals[i].Max[2] ;
+ m_pPortals[i].Max[2]=m_pPortals[i].Min[2] ;
+ m_pPortals[i].Min[2]=flTemp ;
+
+ }
+
+
+
+
+}
+
+void Q3Map::swizzleFloat3(float t[3])
+{
+ float temp;
+ temp = t[1];
+ t[1] = t[2];
+ t[2] = -temp;
+}
+
+void Q3Map::swizzleInt3(int t[3])
+{
+ int temp;
+ temp = t[1];
+ t[1] = t[2];
+ t[2] = -temp;
+}
+
+
+
+Q3BspPatch *Q3Map::handlePatch(int faceIndex)
+{
+ Q3BspPatch *q3patch;
+ q3patch = new Q3BspPatch;
+
+ int patch_size_x = (m_pFaces[faceIndex].size[0] - 1) / 2;
+ int patch_size_y = (m_pFaces[faceIndex].size[1] - 1) / 2;
+ int num_bezier_patches = patch_size_y * patch_size_x;
+
+ q3patch->size = num_bezier_patches;
+ q3patch->bezier = new Bezier[q3patch->size];
+
+ int patchIndex = 0;
+ int ii, n, j, nn;
+ for (ii = 0, n = 0; n < patch_size_x; n++, ii = 2*n)
+ {
+ for (j=0, nn=0; nn < patch_size_y; nn++, j = 2*nn)
+ {
+ int index = 0;
+ for (int ctr = 0; ctr < 3; ctr++)
+ {
+ int pos = ctr * m_pFaces[faceIndex].size[0];
+
+ q3patch->bezier[patchIndex].mControls[index++] =
+ BspVertex(
+ // position
+ m_pVertices[m_pFaces[faceIndex].vertex +
+ ii +
+ m_pFaces[faceIndex].size[0] * j +
+ pos].position,
+ // texture coordinates
+ m_pVertices[m_pFaces[faceIndex].vertex +
+ ii +
+ m_pFaces[faceIndex].size[0] * j +
+ pos].texcoord,
+ // normal
+ m_pVertices[m_pFaces[faceIndex].vertex +
+ ii +
+ m_pFaces[faceIndex].size[0] * j +
+ pos].normal);
+
+ q3patch->bezier[patchIndex].mControls[index++] =
+ BspVertex(
+ m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].position,
+ m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].texcoord,
+ m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].normal);
+
+ q3patch->bezier[patchIndex].mControls[index++] =
+ BspVertex(
+ m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].position,
+ m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].texcoord,
+ m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].normal);
+ }
+ q3patch->bezier[patchIndex].tessellate(5);
+ patchIndex++;
+ }
+ }
+
+ return q3patch;
+}
+
+
+int Q3Map::findVisibleFaces(const QVECTOR *camPos, int *facesToRender)
+{
+ int leaf;
+ int visCluster;
+
+ leaf = findLeaf(camPos);
+
+ visCluster = m_pLeafs[leaf].cluster;
+
+ memset(mVisibleFaces, 0, sizeof(int) * m_iNumFaces);
+
+ int faceindex;
+ int renderindex=0;
+ m_ClusterCount=0 ;
+
+ for (int i=0; i < m_iNumLeafs; i++)
+ {
+ if (isClusterVisible(visCluster, m_pLeafs[i].cluster))
+ {
+ m_ClusterCount++ ;
+ bool vis=true ;//bool vis = mViewFrustum->checkIfBoxInside(m_pLeafs[i].mins, m_pLeafs[i].maxs);
+
+ if (vis)
+ {
+ for (int k=0; k < m_pLeafs[i].n_leaffaces; k++)
+ {
+ faceindex = m_pLeafFaces[m_pLeafs[i].leafface + k];
+ if (mVisibleFaces[faceindex] == 0)
+ {
+ mVisibleFaces[faceindex] = 1;
+ facesToRender[renderindex++] = faceindex;
+ }
+ }
+ }
+ }
+ }
+
+
+ facesToRender[renderindex] = -1;
+
+ return renderindex;
+}
+
+
+int Q3Map::findLeaf(const QVECTOR *camPos) const
+{
+ int index = 0;
+
+ while (index >= 0)
+ {
+ const Q3BspNode *node = &m_pNodes[index];
+ const Q3BspPlane *plane = &m_pPlanes[node->plane];
+
+ // distance from point to plane
+ //QVECTOR normal = QVECTOR(plane->normal);
+ QVECTOR normal ;
+ normal[0]=plane->normal[0] ;
+ normal[1]=plane->normal[1] ;
+ normal[2]=plane->normal[2] ;
+
+
+ //const float distance = D3DXVec3Dot(&normal,camPos) - plane->dist;
+
+ const float distance=(normal[0]* *camPos[0] + normal[1]* *camPos[1] + normal[2]* *camPos[2]) - plane->dist ;
+
+ if(distance >= 0)
+ index = node->children[0];
+ else
+ index = node->children[1];
+ }
+
+ return -index - 1;
+}
+
+bool Q3Map::isClusterVisible(int visCluster, int testCluster) const
+{
+ if (m_VisData == NULL)
+ return true;
+
+ if ((m_VisData->vecs == NULL) || (visCluster < 0))
+ return true;
+
+ int i = (visCluster * m_VisData->sz_vecs) + (testCluster >> 3);
+ unsigned char visSet = m_VisData->vecs[i];
+
+ return (visSet & (1 << (testCluster & 7))) != 0;
+}
+
+Q3BspFace_t *Q3Map::getFaces(void)
+{
+ return m_pFaces;
+}
+
+
+
+
+
+ /***********************************************************************************************************\
+
+ New Parsing and Triangulation Functions
+
+ \***********************************************************************************************************/
+
+
+
+
+// This routine is basically an overview of the entire process that converts the BSP
+// into something our Ogre code can use to construct the map's mesh and level data.
+// In essence, it converts the map geometry into a list of triangles sorted by zone and material,
+// as well as extracting other map info like zone and portal bounding boxes, lights, entities etc.
+
+int Q3Map::ParseAndTriangulateMap(const char* pData, size_t Size)
+{
+
+ char chMessage[1024] ;
+ int nError=0 ;
+
+ // setup pointers to the various lumps and get their quantities
+ nError=parseMap( pData, Size ) ;
+ if(nError<0)
+ {
+ //sprintf(chMessage, "Parse Map Error: %i", nError) ;
+ //Q3Bug.LogAddCR(chMessage) ;
+ return ERROR_ParseMap ;
+ }
+
+ // extract entities such as lights, monsters, etc
+ if(!ParseEntities()) return ERROR_ParseEntities ;
+
+ // initial memory allocation for triangles
+ m_nVertexMax=0 ;
+ if(!AllocateVertexMemory(m_iNumVertices)) return ERROR_AllocateVertex ;
+ if(!AllocateTriangleMemory()) return ERROR_AllocateTriangle ;
+ if(!initFaces()) return ERROR_InitializeFaces ;
+
+ // no new map textures should be added after here, or else SetupTransTextures won't work
+ if(!SetupTransTextures()) return ERROR_SetupTransTextures ;
+
+ // work out the zones
+ SetupZones() ;
+
+ // convert faces to triangles
+ if(!ConvertFacesToTriangles()) return ERROR_ConvertFaces ;
+
+ if(!ConvertPatchesToTriangles()) return ERROR_ConvertPatches ;
+
+ if(!ConvertLampsToTriangles()) return ERROR_ConvertLamps ;
+
+ if(!ConvertLampsToGlowTriangles()) return ERROR_ConvertLampGlow ;
+
+ if(!ConvertLightsToGlowTriangles()) return ERROR_ConvertLightGlow ;
+
+ GetTexLampTextureNumbers() ; // find out which textures, if any, are textures/common/bzn_lightnode0 to textures/common/bzn_lightnode3
+
+ // assign triangles to zones, splitting them where necessary
+ if(!AssignTrianglesToZones()) return ERROR_AssignTriangles ;
+
+ if(!ConvertTexLampsToLampTriangles()) return ERROR_ConvertTexLamp ;
+
+ // sort by group and re-range the group numbers
+ if(!SortTrianglesIntoGroups()) return ERROR_SortGroups ;
+
+ // sort the triangles in order of zone and texture. This will also get rid of any unsubzoned triangles.
+ if(!SortTrianglesIntoBatches()) return ERROR_SortTriangles ;
+
+
+
+
+ // Setup the portals, lights and various bits of map connectivity
+ AssignPortalsToZones() ; // what portals each zone touches
+ AssignLightsToZones() ; // what lights each zone touches
+ AssignLightsToPortals() ; // what lights each portal touches
+ AssignZonesToZones() ; // what zones each zone touches
+
+
+ return NOERROR ;
+}
+
+void Q3Map::FreeParseMem(void)
+{
+ FreeVertexMemory() ;
+ FreeTriangleMemory() ;
+ DestroyBspFacesMemory() ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// memory management
+
+int Q3Map::AllocateTriangleMemory(void)
+{
+ // memory for the Triangle
+ m_nTriangleSize=MEMADD ; // starting memory size
+ m_pTriangleMem=malloc(m_nTriangleSize) ; // allocate starting memory space
+ m_pTriangle=(triangle_t*)m_pTriangleMem ; // a pointer to the memory cast as a triangle_t
+ m_nTriangleMax=0 ;
+ m_nTriangleLimit=m_nTriangleSize/sizeof(triangle_t) ; // if pos reaches this memory must expand
+
+ if(m_pTriangleMem==NULL)
+ return 0 ;
+
+ return 1 ;
+}
+
+void Q3Map::FreeTriangleMemory(void)
+{
+ if(m_pTriangleMem) free(m_pTriangleMem) ;
+ m_pTriangleMem=NULL ;
+ m_pTriangle=NULL ;
+ m_nTriangleMax=0 ;
+ m_nTriangleLimit=0 ;
+}
+
+// increase size of Triangle memory, return 0 if failed
+int Q3Map::ExpandTriangleMemory(void)
+{
+ m_nTriangleSize+=MEMADD ; // increase size
+ m_pTriangleMem=realloc(m_pTriangleMem, m_nTriangleSize) ; // reallocate the memory
+ if(m_pTriangleMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+ // if here then memory allocation succeeded
+ m_pTriangle=(triangle_t*)m_pTriangleMem ; // pointer to the memory cast as a triangle_t
+ m_nTriangleLimit=m_nTriangleSize/sizeof(triangle_t) ; // if pos reaches this memory must expand
+ return 1 ; // ok
+}
+
+int Q3Map::AddTriangle(triangle_t Triangle)
+{
+ if(m_nTriangleMax>=m_nTriangleLimit)
+ if( !ExpandTriangleMemory() )
+ return 0 ;
+
+ m_pTriangle[m_nTriangleMax++]=Triangle ;
+
+ return 1 ;
+}
+
+int Q3Map::AllocateVertexMemory(int nVertNum)
+{
+ // memory for the Vertex
+ m_nVertexSize=nVertNum*sizeof(Q3BspVertex)+MEMADD ; // starting memory size
+ m_pVertexMem=malloc(m_nVertexSize) ; // allocate starting memory space
+ m_pVertex=(Q3BspVertex*)m_pVertexMem ; // a pointer to the memory cast as a triangle_t
+ m_nVertexLimit=m_nVertexSize/sizeof(Q3BspVertex) ; // if pos reaches this memory must expand
+
+ if(m_pVertexMem==NULL)
+ return 0 ;
+
+ return 1 ;
+}
+
+void Q3Map::FreeVertexMemory(void)
+{
+ if(m_pVertexMem) free(m_pVertexMem) ;
+ m_pVertexMem=NULL ;
+ m_pVertex=NULL ;
+ m_nVertexMax=0 ;
+ m_nVertexLimit=0 ;
+}
+
+// increase size of Vertex memory, return 0 if failed
+int Q3Map::ExpandVertexMemory(void)
+{
+ m_nVertexSize+=MEMADD ; // increase size
+ m_pVertexMem=realloc(m_pVertexMem, m_nVertexSize) ; // reallocate the memory
+ if(m_pVertexMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+ // if here then memory allocation succeeded
+ m_pVertex=(Q3BspVertex*)m_pVertexMem ; // pointer to the memory cast as a triangle_t
+ m_nVertexLimit=m_nVertexSize/sizeof(Q3BspVertex) ; // if pos reaches this memory must expand
+ return 1 ; // ok
+}
+
+int Q3Map::AddVertex(Q3BspVertex Vertex)
+{
+
+ if(m_nVertexMax>=m_nVertexLimit)
+ if( !ExpandVertexMemory() )
+ return 0 ;
+
+ m_pVertex[m_nVertexMax++]=Vertex ;
+
+ return 1 ;
+}
+
+int Q3Map::AllocateLightMemory(void)
+{
+ // memory for the Light
+ m_nLightSize=MEMADD ; // starting memory size
+ m_pLightMem=malloc(m_nLightSize) ; // allocate starting memory space
+ m_pLight=(light_t*)m_pLightMem ; // a pointer to the memory cast as a light_t
+ m_nLightMax=0 ;
+ m_nLightLimit=m_nLightSize/sizeof(light_t) ; // if pos reaches this memory must expand
+
+ if(m_pLightMem==NULL)
+ return 0 ;
+
+ return 1 ;
+}
+
+void Q3Map::FreeLightMemory(void)
+{
+ if(m_pLightMem) free(m_pLightMem) ;
+ m_pLightMem=NULL ;
+ m_pLight=NULL ;
+ m_nLightMax=0 ;
+ m_nLightLimit=0 ;
+}
+
+// increase size of Light memory, return 0 if failed
+int Q3Map::ExpandLightMemory(void)
+{
+ m_nLightSize+=MEMADD ; // increase size
+ m_pLightMem=realloc(m_pLightMem, m_nLightSize) ; // reallocate the memory
+ if(m_pLightMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+ // if here then memory allocation succeeded
+ m_pLight=(light_t*)m_pLightMem ; // pointer to the memory cast as a light_t
+ m_nLightLimit=m_nLightSize/sizeof(light_t) ; // if pos reaches this memory must expand
+ return 1 ; // ok
+}
+
+int Q3Map::AddLight(light_t Light)
+{
+ if(m_nLightLimit==0) // light memory hasn't been allocated yet
+ {
+ if( !AllocateLightMemory() )
+ return 0 ;
+ }
+ else
+ if(m_nLightMax>=m_nLightLimit)
+ if( !ExpandLightMemory() )
+ return 0 ;
+
+ m_pLight[m_nLightMax++]=Light ;
+
+ return 1 ;
+}
+
+// lamps are deferred shading, non-shadowing point lights
+int Q3Map::AllocateLampMemory(void)
+{
+ // memory for the Lamp
+ m_nLampSize=MEMADD ; // starting memory size
+ m_pLampMem=malloc(m_nLampSize) ; // allocate starting memory space
+ m_pLamp=(lamp_t*)m_pLampMem ; // a pointer to the memory cast as a lamp_t
+ m_nLampMax=0 ;
+ m_nLampLimit=m_nLampSize/sizeof(lamp_t) ; // if pos reaches this memory must expand
+
+ if(m_pLampMem==NULL)
+ return 0 ;
+
+ return 1 ;
+}
+
+void Q3Map::FreeLampMemory(void)
+{
+ if(m_pLampMem) free(m_pLampMem) ;
+ m_pLampMem=NULL ;
+ m_pLamp=NULL ;
+ m_nLampMax=0 ;
+ m_nLampLimit=0 ;
+}
+
+// increase size of Lamp memory, return 0 if failed
+int Q3Map::ExpandLampMemory(void)
+{
+ m_nLampSize+=MEMADD ; // increase size
+ m_pLampMem=realloc(m_pLampMem, m_nLampSize) ; // reallocate the memory
+ if(m_pLampMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+ // if here then memory allocation succeeded
+ m_pLamp=(lamp_t*)m_pLampMem ; // pointer to the memory cast as a lamp_t
+ m_nLampLimit=m_nLampSize/sizeof(lamp_t) ; // if pos reaches this memory must expand
+ return 1 ; // ok
+}
+
+int Q3Map::AddLamp(lamp_t Lamp)
+{
+ if(m_nLampLimit==0) // Lamp memory hasn't been allocated yet
+ {
+ if( !AllocateLampMemory() )
+ return 0 ;
+ }
+ else
+ if(m_nLampMax>=m_nLampLimit)
+ if( !ExpandLampMemory() )
+ return 0 ;
+
+ m_pLamp[m_nLampMax++]=Lamp ;
+
+ return 1 ;
+}
+
+//////////////
+// Q3BspTexture textures. We duplicate the loaded texture mem and then add lighting textures to it.
+
+int Q3Map::AllocateTextureMemory(void)
+{
+ // memory for the Texture
+ m_nTextureSize=MEMADD ; // starting memory size
+ m_pTextureMem=malloc(m_nTextureSize) ; // allocate starting memory space
+ m_pTexture=(Q3BspTexture*)m_pTextureMem ; // a pointer to the memory cast as a Q3BspTexture
+ m_nTextureMax=0 ;
+ m_nTextureLimit=m_nTextureSize/sizeof(Q3BspTexture) ; // if pos reaches this memory must expand
+
+ if(m_pTextureMem==NULL)
+ return 0 ;
+
+ return 1 ;
+}
+
+void Q3Map::FreeTextureMemory(void)
+{
+ if(m_pTextureMem) free(m_pTextureMem) ;
+ m_pTextureMem=NULL ;
+ m_pTexture=NULL ;
+ m_nTextureMax=0 ;
+ m_nTextureLimit=0 ;
+}
+
+// increase size of Texture memory, return 0 if failed
+int Q3Map::ExpandTextureMemory(void)
+{
+ m_nTextureSize+=MEMADD ; // increase size
+ m_pTextureMem=realloc(m_pTextureMem, m_nTextureSize) ; // reallocate the memory
+ if(m_pTextureMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+ // if here then memory allocation succeeded
+ m_pTexture=(Q3BspTexture*)m_pTextureMem ; // pointer to the memory cast as a Q3BspTexture
+ m_nTextureLimit=m_nTextureSize/sizeof(Q3BspTexture) ; // if pos reaches this memory must expand
+ return 1 ; // ok
+}
+
+int Q3Map::AddTexture(Q3BspTexture Texture)
+{
+ if(m_nTextureLimit==0) // Texture memory hasn't been allocated yet
+ {
+ if( !AllocateTextureMemory() )
+ return 0 ;
+ }
+ else
+ if(m_nTextureMax>=m_nTextureLimit)
+ if( !ExpandTextureMemory() )
+ return 0 ;
+
+ m_pTexture[m_nTextureMax++]=Texture ;
+
+ return 1 ;
+}
+
+// special version of the Add function, will not add if the texture name already exist.
+// Will succeed even if the texture is already on the list, but fails if it can't add a new texture
+// returns texture index, or -1 on fail
+// Q3 texture names can be tricky, I think I've had cases where they ended in spaces instead of nulls,
+// and they might go all the way to the end without either.
+
+int Q3Map::AddTextureUnique(Q3BspTexture Texture)
+{
+ if(m_nTextureLimit==0) // Texture memory hasn't been allocated yet
+ if( !AllocateTextureMemory() )
+ return ADDTEXTUREUNIQUE_FAIL ; // fail
+
+
+ // scan through all the newly added textures so far and see if this one already exists.
+ int nTexture=0 ;
+ int nPos=0 ;
+
+ bool bMatch=false ;
+
+ for(nTexture=0 ; nTexture<m_nTextureMax ; nTexture++)
+ {
+ bMatch=true ;
+ // scan through the characters of the texture names, comparing them. We start after the original textures
+ //for(nPos=m_iNumTexs ; nPos<Q3NAMESIZE ; nPos++)
+ for(nPos=0 ; nPos<Q3NAMESIZE ; nPos++)
+ {
+ // is it the end of the texture name?
+ if(
+ ((Texture.name[nPos] ==0) || (Texture.name[nPos] ==' ')) // Texture name end
+ &&((m_pTexture[nTexture].name[nPos] ==0) || (m_pTexture[nTexture].name[nPos] ==' ')) // m_pTexture name end
+ )
+ break ;
+
+ // do the two textures have a difference in the name at this position?
+ if(Texture.name[nPos]!=m_pTexture[nTexture].name[nPos])
+ {
+ bMatch=false ;
+ break ;
+ }
+
+ }// end scanning name
+
+ if(bMatch) // found a match, so return ok but don't add a texture
+ {
+ return nTexture ; // we don't add any new texture, return this texture's index
+ }
+ }
+
+ // if we got this far, we must have a unique texture
+
+ // add the texture, it is unique
+ if(m_nTextureMax>=m_nTextureLimit)
+ if( !ExpandTextureMemory() )
+ return ADDTEXTUREUNIQUE_FAIL ; // fail
+
+ m_pTexture[m_nTextureMax++]=Texture ;
+
+ return m_nTextureMax-1 ; // return this new texture's index
+
+}
+
+
+////////////////////////////////////////
+
+int Q3Map::AllocateTexLampMemory(void)
+{
+ // memory for the TexLamp
+ m_nTexLampSize=MEMADD ; // starting memory size
+ m_pTexLampMem=malloc(m_nTexLampSize) ; // allocate starting memory space
+ m_pTexLamp=(int*)m_pTexLampMem ; // a pointer to the memory cast as an int
+ m_nTexLampMax=0 ;
+ m_nTexLampLimit=m_nTexLampSize/sizeof(int) ; // if pos reaches this memory must expand
+
+ if(m_pTexLampMem==NULL)
+ return 0 ;
+
+ return 1 ;
+}
+
+void Q3Map::FreeTexLampMemory(void)
+{
+ if(m_pTexLampMem) free(m_pTexLampMem) ;
+ m_pTexLampMem=NULL ;
+ m_pTexLamp=NULL ;
+ m_nTexLampMax=0 ;
+ m_nTexLampLimit=0 ;
+}
+
+// increase size of TexLamp memory, return 0 if failed
+int Q3Map::ExpandTexLampMemory(void)
+{
+ m_nTexLampSize+=MEMADD ; // increase size
+ m_pTexLampMem=realloc(m_pTexLampMem, m_nTexLampSize) ; // reallocate the memory
+ if(m_pTexLampMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+ // if here then memory allocation succeeded
+ m_pTexLamp=(int*)m_pTexLampMem ; // pointer to the memory cast as an int
+ m_nTexLampLimit=m_nTexLampSize/sizeof(int) ; // if pos reaches this memory must expand
+ return 1 ; // ok
+}
+
+int Q3Map::AddTexLamp(int TexLamp)
+{
+ if(m_nTexLampMax>=m_nTexLampLimit)
+ if( !ExpandTexLampMemory() )
+ return 0 ;
+
+ m_pTexLamp[m_nTexLampMax++]=TexLamp ;
+
+ return 1 ;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// extract entities from bsp entities lump
+int Q3Map::ParseEntities(void)
+{
+ char chKey[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+ char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+ int nPos=0 ;
+ int nMaxPos=m_BspHeader.Lumps[0].iLength ;
+ int nEntityType=0 ;
+
+
+ // reset the spotlight textures
+ m_nMaxSpotlightTexture=0 ;
+ for(nPos=0 ; nPos<MAX_PROJECTORTEX ; nPos++)
+ m_chSpotlightTexture[nPos][0]='\0' ;
+
+ strcpy(m_chSpotlightTexture[m_nMaxSpotlightTexture], "spotlight.dds") ; // the default spotlight texture
+ m_nMaxSpotlightTexture++ ;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // before adding all the entities we need to add some default textures
+ Q3BspTexture Texture ;
+ Texture.contents=0 ;
+ Texture.flags=0 ;
+
+ // default lamp texture
+ strcpy(Texture.name, "lights/lamp_default") ;
+ m_nDefaultTextureIndexLamp=AddTextureUnique(Texture) ;
+ if(m_nDefaultTextureIndexLamp==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+ // default lamp2Pass texture
+ strcpy(Texture.name, "lights/lamp2pass_default") ;
+ m_nDefaultTextureIndexLamp2Pass=AddTextureUnique(Texture) ;
+ if(m_nDefaultTextureIndexLamp2Pass==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+ // default glow texture
+ strcpy(Texture.name, "GLOW_lamp") ;
+ m_nDefaultTextureIndexGlowLamp=AddTextureUnique(Texture) ;
+ if(m_nDefaultTextureIndexGlowLamp==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+ // default glow texture
+ strcpy(Texture.name, "GLOW_light") ;
+ m_nDefaultTextureIndexGlowLight=AddTextureUnique(Texture) ;
+ if(m_nDefaultTextureIndexGlowLight==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+
+ // default spotlight texture
+ //strcpy(Texture.name, "lights/light_default") ;
+ //m_nDefaultTextureIndexSpotlight=AddTextureUnique(Texture) ;
+ //if(m_nDefaultTextureIndexSpotlight==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ nPos=-1 ;
+ while(NextEntity(&nPos, nMaxPos))
+ {
+
+ nEntityType=GetEntityType(nPos, nMaxPos) ; // what type of entity is it?
+
+
+ switch(nEntityType)
+ {
+ case ENTITY_ERROR: return 0 ; // something is wrong with the entity data
+
+ case ENTITY_LIGHT:
+ if(!ParseAndAddLight(&nPos, nMaxPos))
+ return 0 ; // something went wrong with parsing the light
+ break ;
+ }// end switch entity type
+
+
+ }// end get next entity
+
+
+
+ // everything is ok.
+ return 1 ;
+}
+
+// move to the beginning of the next entity.
+// fail if there are no more.
+int Q3Map::NextEntity(int* pPos, int nMaxPos)
+{
+ while((++*pPos<nMaxPos) && (m_pEntities[*pPos]!='{')) ;
+
+ if(*pPos==nMaxPos)
+ return 0 ;
+
+ return 1 ;
+}
+
+// find out what type of entity this is.
+// Since the classname might not be at the beginning we have to scan through the whole entity
+// This function also doesn't update the position like the others do,
+// since scanning of further key/values will have to start at the beginning of the entity again.
+int Q3Map::GetEntityType(int nPos, int nMaxPos)
+{
+ char chKey[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+ char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+
+ while(nPos<nMaxPos)
+ {
+ if(GetEntityKeyAndValue(&nPos, nMaxPos, chKey, chValue)!=KEY_OK) return ENTITY_ERROR ; // something went wrong, couldn't find any good keys
+
+ if(strcmp(chKey, "classname")==0) // found the classname key
+ {
+ if(strcmp(chValue, "worldspawn")==0) return ENTITY_WORLDSPAWN ;
+ if(strcmp(chValue, "light")==0) return ENTITY_LIGHT ;
+
+ // wasn't any entity we recognize
+ return ENTITY_UNKNOWN ;
+
+ }// end if got entity classname
+
+ }// end while nPos
+
+ // didn't find any classname
+ return ENTITY_ERROR ;
+}
+
+// get next entity key and value
+int Q3Map::GetEntityKeyAndValue(int* pPos, int nMaxPos, char* pKey, char* pValue)
+{
+
+ char* pEntText=m_pEntities ;
+ int nEntPos=*pPos ;
+ int nKeyPos=-1 ;
+ int nValuePos=-1 ;
+
+ // clear key and value strings
+ pKey[0]='\0' ;
+ pValue[0]='\0' ;
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Key
+
+ // find the next "
+ while((++nEntPos<nMaxPos) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) ;
+
+ // didn't find key, get out
+ if((nEntPos==nMaxPos) || (pEntText[nEntPos]=='}'))
+ return KEY_NONE ;
+
+
+ // copy key
+ while((++nEntPos<nMaxPos) && (nKeyPos<MAX_TOKENSIZE) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"'))
+ pKey[++nKeyPos]=pEntText[nEntPos] ;
+
+ if((nEntPos==nMaxPos) || (nKeyPos==MAX_TOKENSIZE) || (pEntText[nEntPos]=='}'))
+ return KEY_ERROR ; // entity was incomplete or too big
+
+ pKey[++nKeyPos]='\0' ;
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // value
+
+ // find the next "
+ while((++nEntPos<nMaxPos) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) ;
+
+ // didn't find value, get out
+ if((nEntPos==nMaxPos) || (pEntText[nEntPos]=='}'))
+ return KEY_ERROR ;
+
+ // copy value
+ while((++nEntPos<nMaxPos) && (nValuePos<MAX_TOKENSIZE) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"'))
+ pValue[++nValuePos]=pEntText[nEntPos] ;
+
+ if((nEntPos==nMaxPos) || (nValuePos==MAX_TOKENSIZE) || (pEntText[nEntPos]=='}'))
+ return KEY_ERROR ; // entity was incomplete or too big
+
+ pValue[++nValuePos]='\0' ;
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ *pPos=nEntPos+1 ;
+
+ return KEY_OK ;
+}
+
+
+// fills array pNumber with the values extracted from pValue, returns how many numbers it got.
+// float version
+int Q3Map::GetNumbersFromValue(char* pValue, float *pNumber, int nNumberSize)
+{
+ int nLength=strlen(pValue) ;
+ if(nLength<1) return 0 ;
+
+ int nPos=-1 ;
+ int nCount=0 ;
+ char chTemp[MAX_TOKENSIZE+1] ;
+ int nTempPos=0 ;
+
+ do
+ {
+
+ nPos++ ;
+
+ if(
+ ((pValue[nPos]>='0') && (pValue[nPos]<='9')) // found another digit
+ ||
+ (pValue[nPos]=='.')
+ ||
+ (pValue[nPos]=='-')
+ )
+ {
+ chTemp[nTempPos++]=pValue[nPos] ;
+ if(nTempPos==MAX_TOKENSIZE) return 0 ; // number too big
+ }
+ else // anything else means the end of the number
+ {
+
+ chTemp[nTempPos]='\0' ;
+ pNumber[nCount++]=atof(chTemp) ;
+ nTempPos=0 ;
+ }
+
+
+ }while((nPos<nLength) && (nCount<nNumberSize) && (pValue[nPos]!='\0')) ;
+
+
+ return nCount ;
+}
+
+// integer version
+int Q3Map::GetNumbersFromValue(char* pValue, int *pNumber, int nNumberSize)
+{
+ int nLength=strlen(pValue) ;
+ if(nLength<1) return 0 ;
+
+ int nPos=-1 ;
+ int nCount=0 ;
+ char chTemp[MAX_TOKENSIZE+1] ;
+ int nTempPos=0 ;
+
+ do
+ {
+
+ nPos++ ;
+
+ if(
+ ((pValue[nPos]>='0') && (pValue[nPos]<='9')) // found another digit
+ ||
+ (pValue[nPos]=='.')
+ ||
+ (pValue[nPos]=='-')
+ )
+ {
+ chTemp[nTempPos++]=pValue[nPos] ;
+ if(nTempPos==MAX_TOKENSIZE) return 0 ; // number too big
+ }
+ else // anything else means the end of the number
+ {
+
+ chTemp[nTempPos]='\0' ;
+ pNumber[nCount++]=atoi(chTemp) ;
+ nTempPos=0 ;
+ }
+
+
+ }while((nPos<nLength) && (nCount<nNumberSize) && (pValue[nPos]!='\0')) ;
+
+
+ return nCount ;
+}
+
+//''
+// extracts data for either forward rendered shadow casting spotlights or deferred shading non-shadowing point lights
+// the point lights ("lamps") will later be changed into map triangles.
+int Q3Map::ParseAndAddLight(int* pPos, int nMaxPos)
+{
+ char chMessage[1024] ;
+
+
+ char chKey[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+ char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+ float flOrigin[3]={0.0f, 0.0f, 0.0f} ;
+ float flColour[3]={1.0f, 1.0f, 1.0f} ;
+ float flCentre[3]={0.0f, 0.0f, 0.0f} ;
+ float flAimvec[3]={0.0f, 0.0f, 0.0f} ;
+ float flRadius[3]={0.0f, 0.0f, 0.0f} ;
+
+ float flTemp[3]={0.0f, 0.0f, 0.0f} ;
+ int nTemp[3] ;
+
+ float flAngle=0.0f ;
+ float flCutoff=0.0f ;
+ float flLength=0.0f ;
+ float flBrightness=0.0f ;
+ int nLightNode=-1 ;
+
+ bool bSpotLight=false ;
+
+ Q3BspTexture Q3Texture ;
+ Q3Texture.flags=0 ;
+ Q3Texture.contents=0 ;
+ Q3Texture.name[0]=0 ;
+
+
+ light_t NewLight ; // forward rendered shadow casting spotlight
+ ZeroMemory((void*)&NewLight, sizeof(light_t)) ;
+
+ lamp_t NewLamp ; // deferred shading non-shadowing point light
+ ZeroMemory((void*)&NewLamp, sizeof(lamp_t)) ;
+
+ int nKeyReturn=KEY_NONE ;
+
+ do
+ {
+ nKeyReturn=GetEntityKeyAndValue(pPos, nMaxPos, chKey, chValue) ;
+
+ if(nKeyReturn==KEY_OK) // found a key
+ {
+
+ if(strcmp(chKey, "origin")==0)
+ {
+ if(GetNumbersFromValue(chValue, flOrigin, 3)!=3) return 0 ; // extract the numbers
+ swizzleFloat3(flOrigin) ; // fix coordinates
+ }
+ else
+ if(strcmp(chKey, "_color")==0)
+ {
+ if(GetNumbersFromValue(chValue, flColour, 3)!=3) return 0 ; // extract the numbers
+ }
+ else
+ if(strcmp(chKey, "light_center")==0)
+ {
+ if(GetNumbersFromValue(chValue, flCentre, 3)!=3) return 0 ; // extract the numbers
+ swizzleFloat3(flCentre) ; // fix coordinates
+ }
+ else
+ if(strcmp(chKey, "light_target")==0)
+ {
+ if(GetNumbersFromValue(chValue, flAimvec, 3)!=3) return 0 ; // extract the numbers
+ swizzleFloat3(flAimvec) ; // fix coordinates
+ bSpotLight=true ; // if there's a target key, then this must be a spotlight
+ }
+ else
+ if(strcmp(chKey, "light_radius")==0)
+ {
+ if(GetNumbersFromValue(chValue, flRadius, 3)!=3) return 0 ; // extract the numbers
+ swizzleFloat3(flRadius) ; // fix coordinates
+ // make sure all values are positive
+ flRadius[0]=fabs(flRadius[0]) ;
+ flRadius[1]=fabs(flRadius[1]) ;
+ flRadius[2]=fabs(flRadius[2]) ;
+ }
+ else
+ if(strcmp(chKey, "light_abc")==0)
+ {
+ if(GetNumbersFromValue(chValue, flTemp, 3)!=3) return 0 ; // extract the numbers
+ flAngle = flTemp[0] ;
+ flBrightness = flTemp[1] ;
+ flCutoff = flTemp[2] ;
+ }
+ else
+ if(strcmp(chKey, "texture")==0)
+ {
+ strcpy(Q3Texture.name, chValue) ;
+ }
+ if(strcmp(chKey, "light_node")==0)
+ {
+ if(GetNumbersFromValue(chValue, nTemp, 1)!=1) return 0 ; // extract the number
+ nLightNode = nTemp[0] ;
+ if((nLightNode<0) || (nLightNode>3)) return 0 ; // something dodgy about the lightnode number
+ }
+
+ }// end if key ok
+
+
+
+ }while(nKeyReturn==KEY_OK) ; // end do looping through keys
+
+
+ // return a fail if there was a problem with the keys
+ if(nKeyReturn==KEY_ERROR) return 0 ;
+
+
+ if(bSpotLight)// found a light_target so this must be a spotlight
+ {
+ // light settings.
+ NewLight.Position[0]=flOrigin[0]+flCentre[0] ;
+ NewLight.Position[1]=flOrigin[1]+flCentre[1] ;
+ NewLight.Position[2]=flOrigin[2]+flCentre[2] ;
+
+ NewLight.Min[0]=flOrigin[0]-flRadius[0] ;
+ NewLight.Min[1]=flOrigin[1]-flRadius[1] ;
+ NewLight.Min[2]=flOrigin[2]-flRadius[2] ;
+
+ NewLight.Max[0]=flOrigin[0]+flRadius[0] ;
+ NewLight.Max[1]=flOrigin[1]+flRadius[1] ;
+ NewLight.Max[2]=flOrigin[2]+flRadius[2] ;
+
+ NewLight.Colour[0]=flColour[0] ;
+ NewLight.Colour[1]=flColour[1] ;
+ NewLight.Colour[2]=flColour[2] ;
+
+ NewLight.Angle=flAngle ;
+ NewLight.Cutoff=flCutoff ;
+ NewLight.Brightness=flBrightness * BRIGHTNESSTWEAK ;
+
+
+ // direction light points, as a normal
+ flLength=sqrt( flAimvec[0]*flAimvec[0] + flAimvec[1]*flAimvec[1] + flAimvec[2]*flAimvec[2] ) ;
+ if(flLength>0.0f)
+ {
+ NewLight.Direction[0]=flAimvec[0]/flLength ;
+ NewLight.Direction[1]=flAimvec[1]/flLength ;
+ NewLight.Direction[2]=flAimvec[2]/flLength ;
+ }
+ else
+ { // default to pointing down
+ NewLight.Direction[0]=0.0f ;
+ NewLight.Direction[1]=1.0f ;
+ NewLight.Direction[2]=0.0f ;
+ }
+
+ NewLight.ZoneCount=0 ;
+ NewLight.CentreZone=0 ;
+
+
+ if(Q3Texture.name[0]==0)
+ strcpy(Q3Texture.name, "spotlight.dds") ;
+
+ NewLight.Texture=AddSpolightTexture(Q3Texture.name) ;
+
+
+ if(NewLight.Texture==ADDSPOTLIGHTTEXTURE_FAIL)
+ return 0 ; // failure
+
+ //AddTextureUnique(Q3Texture) ;
+ /*
+ // add the light's texture index
+ if(Q3Texture.name[0]==0)
+ NewLight.Texture=m_nDefaultTextureIndexSpotlight ;
+ else
+ {
+ NewLight.Texture=AddTextureUnique(Q3Texture) ; // this will add the texture name to the list if it is unique, as well as setting the index
+ if(NewLight.Texture==ADDTEXTUREUNIQUE_FAIL)
+ return 0 ;
+ }
+ */
+
+ return AddLight(NewLight) ;
+ }
+ else // add a non-shadowing deferred shading point light
+ {
+ // light settings.
+ NewLamp.Position[0]=flOrigin[0]+flCentre[0] ;
+ NewLamp.Position[1]=flOrigin[1]+flCentre[1] ;
+ NewLamp.Position[2]=flOrigin[2]+flCentre[2] ;
+
+ NewLamp.Min[0]=flOrigin[0]-flRadius[0] ;
+ NewLamp.Min[1]=flOrigin[1]-flRadius[1] ;
+ NewLamp.Min[2]=flOrigin[2]-flRadius[2] ;
+
+ NewLamp.Max[0]=flOrigin[0]+flRadius[0] ;
+ NewLamp.Max[1]=flOrigin[1]+flRadius[1] ;
+ NewLamp.Max[2]=flOrigin[2]+flRadius[2] ;
+
+ NewLamp.Colour[0]=flColour[0] ;
+ NewLamp.Colour[1]=flColour[1] ;
+ NewLamp.Colour[2]=flColour[2] ;
+
+ NewLamp.Brightness=flBrightness * BRIGHTNESSTWEAK ;
+
+ NewLamp.LightNode=nLightNode ; // typically -1, but may be 0 to 3 if this lamp is the node for some TexLamp freeform deferred shading geometry.
+
+
+ // Note that m_pLamp.Zone will be set after we first convert lamps into triangles and then
+ // assign those triangles to zones. At that point, if the assigned triangle is also flagged as
+ // coming from a lamp, then the lamp's list of zones will be updated.
+
+ // add the light's texture index
+ if(Q3Texture.name[0]==0)
+ {
+ if(nLightNode==-1)
+ NewLamp.Texture=m_nDefaultTextureIndexLamp ; // normal 1 pass deferred shading
+ else
+ NewLamp.Texture=m_nDefaultTextureIndexLamp2Pass ; // special 2 pass deferred shading to texlamps
+ }
+ else
+ {
+ NewLamp.Texture=AddTextureUnique(Q3Texture) ; // this will add the texture name to the list if it is unique, as well as setting the index
+ if(NewLamp.Texture==ADDTEXTUREUNIQUE_FAIL)
+ return 0 ;
+ }
+
+ return AddLamp(NewLamp) ;
+ }
+
+}
+
+// adds a spotlight texture name if it is unique, returns the index to that texture name either way.
+// returns ADDSPOTLIGHTTEXTURE_FAIL on a fail
+
+int Q3Map::AddSpolightTexture(char TEXNAME[])
+{
+ if((strlen(TEXNAME)>Q3NAMESIZE) || (m_nMaxSpotlightTexture>=MAX_PROJECTORTEX))
+ return ADDSPOTLIGHTTEXTURE_FAIL ;
+
+
+ // scan through all the newly added textures so far and see if this one already exists.
+ int nTexture=0 ;
+ int nPos=0 ;
+
+ bool bMatch ;
+
+ for(nTexture=0 ; nTexture<m_nMaxSpotlightTexture ; nTexture++)
+ {
+ bMatch=true ;
+ // scan through the characters of the texture names, comparing them.
+ for(nPos=0 ; nPos<Q3NAMESIZE ; nPos++)
+ {
+ // do the two textures have a difference in the name at this position?
+ if(m_chSpotlightTexture[nTexture][nPos]!=TEXNAME[nPos])
+ {
+ bMatch=false ;
+ break ;
+ }
+
+ // is it the end of the texture name?
+ if(TEXNAME[nPos]=='\0') // end of texture
+ break ;
+
+ }// end scanning name
+
+ if(bMatch) // found a match, so return ok but don't add a texture
+ return nTexture ; // we don't add any new texture, return this texture's index
+ }
+
+ // if we got this far, we must have a unique texture
+ strcpy(m_chSpotlightTexture[m_nMaxSpotlightTexture], TEXNAME) ;
+ m_nMaxSpotlightTexture++ ;
+
+ return m_nMaxSpotlightTexture-1 ; // return this new texture's index
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+int Q3Map::initFaces(void)
+{
+
+ m_nGroup=0 ; // reset the group counter, used to work out transparent groupings for triangles.
+
+ Q3BspFace_t *faces = getFaces();
+
+ m_BspFaces = new Q3BspFaceRenderer[m_iNumFaces];
+ if(m_BspFaces==NULL) return 0 ; // fail, out of memory.
+ m_NumBspFaces = m_iNumFaces;
+
+
+ for (int i=0; i < m_NumBspFaces; i++)
+ {
+ m_BspFaces[i].lm_index = faces[i].lm_index;
+ m_BspFaces[i].meshvert = faces[i].meshvert;
+ m_BspFaces[i].n_meshverts = faces[i].n_meshverts;
+ m_BspFaces[i].n_vertexes = faces[i].n_vertexes;
+ for (int j=0; j<3; j++)
+ m_BspFaces[i].normal[j] = faces[i].normal[j];
+ m_BspFaces[i].texture = faces[i].texture;
+ m_BspFaces[i].type = faces[i].type;
+ m_BspFaces[i].vertex = faces[i].vertex;
+
+ m_BspFaces[i].n_triangles = m_BspFaces[i].n_meshverts / 3;
+
+ if (m_BspFaces[i].type == PATCH)
+ {
+ m_BspFaces[i].patch = handlePatch(i);
+ }
+ else
+ {
+ m_BspFaces[i].patch = NULL;
+ }
+
+
+ }
+
+
+ // check patches aren't degenerate
+ int numIndex = 0;
+ int numVertex = 0;
+
+
+ for (int i=0; i < m_NumBspFaces; i++)
+ {
+
+ numIndex = 0;
+ numVertex = 0;
+
+ if ((m_BspFaces[i].type == PATCH) && (m_BspFaces[i].patch != NULL))
+ {
+ for (int j=0; j < m_BspFaces[i].patch->size; j++)
+ {
+ numIndex += m_BspFaces[i].patch->bezier[j].mNumIndex;
+ numVertex += m_BspFaces[i].patch->bezier[j].mNumVertex;
+ }
+
+ if((numIndex==0) || (numVertex==0))
+ {
+ DELETE_ARRAY( m_BspFaces[i].patch->bezier ) ;
+ DELETE_POINTER( m_BspFaces[i].patch ) ;
+ }
+
+ }// end if patch
+
+
+ }// end for
+
+
+
+ // copy the vertices over.
+ // We need to work on a copy because we need to create new verts when splitting triangles that cross subzones, and for patches
+ for(int i=0 ; i<m_iNumVertices ; i++)
+ {
+ m_pVertex[i]=m_pVertices[i] ;
+ m_nVertexMax++ ; // need to update this manually since we aren't adding new verts, but filling in the original mem.
+ }
+
+
+ return 1 ;
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// stuff for assigning triangles to subzones, splitting them where necessary.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Q3Map::SetupZones(void)
+{
+ int nSubZone=0 ;
+ int nZone=0 ;
+ int nPos=0 ;
+
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+ float flMaxZ=0.0f ;
+
+ m_nMaxZone=0 ;
+
+ for(nZone=0 ; nZone<MAX_ZONE ; nZone++)
+ {
+ m_nZone[nZone][INDEX_SUBZONECOUNT]=0 ;
+ m_ZoneBoundary[nZone].Min[0]=MINMAXLIMIT ;
+ m_ZoneBoundary[nZone].Min[1]=MINMAXLIMIT ;
+ m_ZoneBoundary[nZone].Min[2]=MINMAXLIMIT ;
+ m_ZoneBoundary[nZone].Max[0]=-MINMAXLIMIT ;
+ m_ZoneBoundary[nZone].Max[1]=-MINMAXLIMIT ;
+ m_ZoneBoundary[nZone].Max[2]=-MINMAXLIMIT ;
+ }
+
+
+ // find the highest used zone number, then +1 to get our limit.
+ for(nSubZone=0 ; nSubZone<m_iNumSubZones ; nSubZone++)
+ if(m_pSubZones[nSubZone].Zone>m_nMaxZone)
+ m_nMaxZone=m_pSubZones[nSubZone].Zone ;
+
+ m_nMaxZone++ ; // our limit
+
+
+ //char chMessage[1024] ;
+
+
+ // fill in what subzones are in each zone
+ for(nSubZone=0 ; nSubZone<m_iNumSubZones ; nSubZone++)
+ {
+
+
+ nZone=m_pSubZones[nSubZone].Zone ;
+
+ // find next empty slot in this zone
+ nPos=0 ;
+ while((nPos<MAX_SUBZONEPERZONE) && (nPos<m_nZone[nZone][INDEX_SUBZONECOUNT]))
+ nPos++ ;
+
+ // if there's room, add the subzone to this zone
+ if(nPos<MAX_SUBZONEPERZONE)
+ {
+ m_nZone[nZone][nPos]=nSubZone ;
+
+ // limits used for cutting up lights (not useful for other boundary stuff, check subzones instead)
+ if(m_pSubZones[nSubZone].Min[0]<m_ZoneBoundary[nZone].Min[0])
+ m_ZoneBoundary[nZone].Min[0]= m_pSubZones[nSubZone].Min[0] ;
+ if(m_pSubZones[nSubZone].Min[1]<m_ZoneBoundary[nZone].Min[1])
+ m_ZoneBoundary[nZone].Min[1]= m_pSubZones[nSubZone].Min[1] ;
+ if(m_pSubZones[nSubZone].Min[2]<m_ZoneBoundary[nZone].Min[2])
+ m_ZoneBoundary[nZone].Min[2]= m_pSubZones[nSubZone].Min[2] ;
+
+ if(m_pSubZones[nSubZone].Max[0]>m_ZoneBoundary[nZone].Max[0])
+ m_ZoneBoundary[nZone].Max[0]= m_pSubZones[nSubZone].Max[0] ;
+ if(m_pSubZones[nSubZone].Max[1]>m_ZoneBoundary[nZone].Max[1])
+ m_ZoneBoundary[nZone].Max[1]= m_pSubZones[nSubZone].Max[1] ;
+ if(m_pSubZones[nSubZone].Max[2]>m_ZoneBoundary[nZone].Max[2])
+ m_ZoneBoundary[nZone].Max[2]= m_pSubZones[nSubZone].Max[2] ;
+
+ m_nZone[nZone][INDEX_SUBZONECOUNT]++ ;
+ }
+
+
+ }
+
+
+}
+
+
+// work out what zone each triangle is in.
+// if it is in more than one, cut it up into smaller triangles that are only in one zone each.
+int Q3Map::AssignTrianglesToZones(void)
+{
+ int nCurrentTriangle=0 ;
+ int nZone=0 ;
+
+
+ /*
+ char chMessage[1024] ;
+ float flPos[3] ;
+ int nTri=0 ;
+ float flVert[3][3] ;
+
+
+ for(nTri=0 ; nTri<m_nTriangleMax ; nTri++)
+ {
+ flVert[0][0]=m_pVertex[ m_pTriangle[nTri].VIndex[0] ].position[0] ;
+ flVert[0][1]=m_pVertex[ m_pTriangle[nTri].VIndex[0] ].position[1] ;
+ flVert[0][2]=m_pVertex[ m_pTriangle[nTri].VIndex[0] ].position[2] ;
+
+ flVert[1][0]=m_pVertex[ m_pTriangle[nTri].VIndex[1] ].position[0] ;
+ flVert[1][1]=m_pVertex[ m_pTriangle[nTri].VIndex[1] ].position[1] ;
+ flVert[1][2]=m_pVertex[ m_pTriangle[nTri].VIndex[1] ].position[2] ;
+
+ flVert[2][0]=m_pVertex[ m_pTriangle[nTri].VIndex[2] ].position[0] ;
+ flVert[2][1]=m_pVertex[ m_pTriangle[nTri].VIndex[2] ].position[1] ;
+ flVert[2][2]=m_pVertex[ m_pTriangle[nTri].VIndex[2] ].position[2] ;
+
+
+ flPos[0]=(flVert[0][0]+flVert[1][0]+flVert[2][0])/3.0f ;
+ flPos[1]=(flVert[0][1]+flVert[1][1]+flVert[2][1])/3.0f ;
+ flPos[2]=(flVert[0][2]+flVert[1][2]+flVert[2][2])/3.0f ;
+
+ nZone=0 ;
+ while((nZone<m_iNumSubZones) && !PointInZone(flPos, nZone))
+ nZone++ ;
+
+
+
+
+ }
+ */
+
+
+
+ for(nCurrentTriangle=0 ; nCurrentTriangle<m_nTriangleMax ; nCurrentTriangle++)
+ {
+ if(!SetupTriangleZone(nCurrentTriangle)) return 0 ; // what zone completely contains this triangle, if any
+
+ }// end for current triangle
+
+ return 1 ;
+}
+
+// return the zone this triangle is in, or -1 if it is not entirely contained by any zone
+// this is also a convienient spot for us to update Lamp zones when we discover what zones its triangles are in,
+// and also a handy place to note if the triangle is a TexLamp or not
+// (TexLamp is free form geometry that is bound to a lamp and gets converted to deferred shading lights, allowing us to do fake shadowing)
+
+int Q3Map::FindTriangleZone(int nTriangle)
+{
+ int nZone=0 ;
+ int nSubZone=0 ;
+ int nPos=0 ;
+ bool bVertInSubZone=false ;
+ int nVert=0 ;
+ bool bTriangleInZone=false ;
+ int nMaxSubZone=m_iNumSubZones ;
+ float flVert[6][3] ; // verts 0, 1, 2 are the original triangle corners, verts 3, 4, 5 are interpolated edge points.
+ // we need the edge points, since it's possible for all the
+ // triangle verts to be in one L shaped zone but the triangle they form not be in that zone.
+ // (such as if there's a vert at the corner and two ends of the "L")
+
+
+ flVert[0][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[0] ;
+ flVert[0][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[1] ;
+ flVert[0][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[2] ;
+
+ flVert[1][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[0] ;
+ flVert[1][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[1] ;
+ flVert[1][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[2] ;
+
+ flVert[2][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[0] ;
+ flVert[2][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[1] ;
+ flVert[2][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[2] ;
+
+ flVert[3][0]=(flVert[0][0]+flVert[1][0])/2.0f ;
+ flVert[3][1]=(flVert[0][1]+flVert[1][1])/2.0f ;
+ flVert[3][2]=(flVert[0][2]+flVert[1][2])/2.0f ;
+
+ flVert[4][0]=(flVert[1][0]+flVert[2][0])/2.0f ;
+ flVert[4][1]=(flVert[1][1]+flVert[2][1])/2.0f ;
+ flVert[4][2]=(flVert[1][2]+flVert[2][2])/2.0f ;
+
+ flVert[5][0]=(flVert[2][0]+flVert[0][0])/2.0f ;
+ flVert[5][1]=(flVert[2][1]+flVert[0][1])/2.0f ;
+ flVert[5][2]=(flVert[2][2]+flVert[0][2])/2.0f ;
+
+
+ // scan through the zones until:
+ // a) we find a zone that completely contains the six vertices
+ // b) we run out of zones.
+
+
+ do
+ {
+ nVert=0 ;
+ bTriangleInZone=false ;
+
+ // scan through the verts until:
+ // a) we find a vert that isn't in this zone
+ // b) we run out of verts
+
+ do
+ {
+
+ // scan through the zone's subzones until:
+ // a) we find one that contains this vert,
+ // b) we hit the subzoneperzone limit,
+ // c) this zone runs out of subzones
+
+ nPos=0 ;
+ do
+ {
+ bVertInSubZone=PointInSubZone(flVert[nVert], m_nZone[nZone][nPos]) ;
+ }while( !bVertInSubZone && (++nPos<MAX_SUBZONEPERZONE) && (nPos<m_nZone[nZone][INDEX_SUBZONECOUNT])) ;
+
+ // if bVertInSubZone is false, we found a vert that isn't in this zone.
+
+ }while(bVertInSubZone && (++nVert<6)) ;
+
+ if(bVertInSubZone) bTriangleInZone=true ;
+
+ }while(!bTriangleInZone && (++nZone<m_nMaxZone)) ;
+
+
+
+
+
+ if(!bTriangleInZone)
+ return -1 ;
+ else
+ {
+
+ // if this triangle came from a lamp entity, we note in that lamp entity that it touches this zone
+ int nLamp=m_pTriangle[nTriangle].Lamp ;
+ if(nLamp>-1) // if we have a lamp
+ {
+
+
+ int nSlot=m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT] ;
+
+ if(nSlot<MAX_ZONEPERLIGHT) // if the lamp isn't maxed out on zones
+ {
+ // check if we already have this zone recorded
+ int nCheckSlot=0 ;
+ int nFoundDuplicate=0 ;
+ for(nCheckSlot=0 ; nCheckSlot<nSlot ; nCheckSlot++)
+ if(m_pLamp[nLamp].Zone[nCheckSlot]==nZone)
+ {
+ nFoundDuplicate=1 ;
+ break ;
+ }
+
+ if(!nFoundDuplicate)
+ {
+ m_pLamp[nLamp].Zone[nSlot]=nZone ; // write the zone into this slot
+ m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT]++ ; // note that we have one more zone
+ }
+
+ }
+ }
+
+
+ // if this triangle is a TexLamp triangle (free form deferred lighting shapes)
+ // then we remember this, in order to make assigning it to a lamp faster
+ int nTexture=m_pTriangle[nTriangle].Texture ;
+ if((nTexture==m_nBZN_LightNode0) || (nTexture==m_nBZN_LightNode1) || (nTexture==m_nBZN_LightNode2) || (nTexture==m_nBZN_LightNode3))
+ if(!AddTexLamp(nTriangle))
+ return ADDTEXLAMP_FAIL ; //if we failed to note the texlamp (probably out of memory), the whole level load will fail.
+
+
+ // finally, return the zone the triangle is in.
+ return nZone ;
+ }
+}
+
+
+
+// work out what zone a triangle is in, cut it up if it's in more than one.
+int Q3Map::SetupTriangleZone(int nTriangle)
+{
+
+
+ int nZone=0 ;
+
+ nZone=FindTriangleZone(nTriangle) ;
+
+ if(nZone==ADDTEXLAMP_FAIL)
+ return 0 ;
+
+
+ if(nZone!=-1) // triangle was completely in a zone
+ m_pTriangle[nTriangle].Zone=nZone ;
+ else
+ {
+ // This triangle is in more than one zone. (Or no subzone at all)
+ // we chop it up along the edges of every subzone it is in (regardless of whether they are a common zone or not)
+ // so that the resulting triangles will all be in just one subzone, and therefore in only one zone.
+ // this might produce a few extra triangles more than we strictly need, since some will both be in the same zone,
+ // but it is simple and the extra triangles are trivial in number.
+
+ // As we go to each new cut plane, it must be applied progressively to all newly created triangles too.
+
+ int nInitialTrianglePos=m_nTriangleMax ; // where we start adding new triangles
+
+ int nTriLoop=0 ;
+ int nTriangleToCut=0 ;
+ int nMaxTriangle=0 ;
+ int nSide=0 ;
+ int nAxis=0 ;
+ float flCutPos=0.0f ;
+ int nSubZone=0 ;
+ int nMaxSubZone=m_iNumSubZones ;
+ int nVert=0 ;
+ float flVert[6][3] ; // verts 0, 1, 2 are the original triangle corners, verts 3, 4, 5 are interpolated edge points.
+ // we need the edge points, since it's possible for all the
+ // triangle verts to be in one L shaped zone but the triangle they form not be in that zone.
+ // (such as if there's a vert at the corner and two ends of the "L")
+
+
+ flVert[0][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[0] ;
+ flVert[0][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[1] ;
+ flVert[0][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[2] ;
+
+ flVert[1][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[0] ;
+ flVert[1][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[1] ;
+ flVert[1][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[2] ;
+
+ flVert[2][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[0] ;
+ flVert[2][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[1] ;
+ flVert[2][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[2] ;
+
+ flVert[3][0]=(flVert[0][0]+flVert[1][0])/2.0f ;
+ flVert[3][1]=(flVert[0][1]+flVert[1][1])/2.0f ;
+ flVert[3][2]=(flVert[0][2]+flVert[1][2])/2.0f ;
+
+ flVert[4][0]=(flVert[1][0]+flVert[2][0])/2.0f ;
+ flVert[4][1]=(flVert[1][1]+flVert[2][1])/2.0f ;
+ flVert[4][2]=(flVert[1][2]+flVert[2][2])/2.0f ;
+
+ flVert[5][0]=(flVert[2][0]+flVert[0][0])/2.0f ;
+ flVert[5][1]=(flVert[2][1]+flVert[0][1])/2.0f ;
+ flVert[5][2]=(flVert[2][2]+flVert[0][2])/2.0f ;
+
+
+
+
+ for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+ {
+ // are any of our original verts in this subzone?
+
+ nVert=0 ;
+ while( !PointInSubZone(flVert[nVert], nSubZone) && (++nVert<6)) ;
+
+ if(nVert<6) // one of the verts must have been in this subzone.
+ {
+ // cutup all triangles by the sides of this subzone.
+ // we'll need to cut more and more triangles as this progresses. (or at least test if they need to be cut)
+ for(nSide=0 ; nSide<6 ; nSide++)
+ {
+ switch(nSide)
+ {
+ case 0: nAxis=AXIS_X ; flCutPos=m_pSubZones[nSubZone].Min[0] ; break ;
+ case 1: nAxis=AXIS_X ; flCutPos=m_pSubZones[nSubZone].Max[0] ; break ;
+ case 2: nAxis=AXIS_Y ; flCutPos=m_pSubZones[nSubZone].Min[1] ; break ;
+ case 3: nAxis=AXIS_Y ; flCutPos=m_pSubZones[nSubZone].Max[1] ; break ;
+ case 4: nAxis=AXIS_Z ; flCutPos=m_pSubZones[nSubZone].Min[2] ; break ;
+ case 5: nAxis=AXIS_Z ; flCutPos=m_pSubZones[nSubZone].Max[2] ; break ;
+ }
+
+
+ nMaxTriangle=m_nTriangleMax-nInitialTrianglePos ; // how may new triangles have been created since we first started cutting the original.
+
+ for(nTriLoop=-1 ; nTriLoop<nMaxTriangle ; nTriLoop++)
+ {
+ // work out if we are cutting up the original triangle or one of the newly created ones.
+ if(nTriLoop==-1)
+ nTriangleToCut=nTriangle ; // the original triangle, perhaps heavily cutup by now.
+ else
+ nTriangleToCut=nInitialTrianglePos+nTriLoop ; // one of the newly created triangles.
+
+ if(!SplitTriangle(nTriangleToCut, nAxis, flCutPos)) return 0 ; // cut up the triangle, fail if we're out of memory or whatever.
+
+
+ }// end for nTriLoop
+
+ }// end cutting by each side of the subzone
+
+ }// end if one of the verts was in this subzone
+
+ }// end going through all subzones
+
+
+ // now that the triangle is well and truly chopped up, assign it a zone.
+ // Even though it should be entirely in a subzone by now, there's still the chance that
+ // it might not be inside any subzone at all. If so, it will be assigned -1 zone and
+ // exluded from the manualobjects
+
+ m_pTriangle[nTriangle].Zone=FindTriangleZone(nTriangle) ;
+
+ // we don't have to worry about assigning zones to the newly created triangles,
+ // they'll get theirs when the AssignTrianglesToZones loop reaches them at the end.
+
+ }// end if triangle was in more than one subzone (or no subzone at all)
+
+ return 1 ;
+}
+
+
+// cut a triangle along some axial plane, turning into 2 or 3 triangles.
+// If the plane doesn't go through the triangle then nothing will happen.
+int Q3Map::SplitTriangle(int nTriangle, int nAxis, float flCutPos)
+{
+
+ triangle_t NewTri ;
+
+ // these will stay -1 if no vert is created, else will be index of the new vert
+ int nABNum=-1 ;
+ int nBCNum=-1 ;
+ int nCANum=-1 ;
+
+ Q3BspVertex VertA = m_pVertex[ m_pTriangle[ nTriangle ].VIndex[0] ] ;
+ Q3BspVertex VertB = m_pVertex[ m_pTriangle[ nTriangle ].VIndex[1] ] ;
+ Q3BspVertex VertC = m_pVertex[ m_pTriangle[ nTriangle ].VIndex[2] ] ;
+ Q3BspVertex VertexAB ;
+ Q3BspVertex VertexBC ;
+ Q3BspVertex VertexCA ;
+
+ float flSpan=0.0f ;
+ float flCutSpan=0.0f ;
+ float flPercent=0.0f ;
+
+ switch(nAxis)
+ {
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ case AXIS_X:
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline.
+ if(
+ ((VertA.position[0]<flCutPos-SUBZONE_EPSILON) && (VertB.position[0]>flCutPos+SUBZONE_EPSILON))
+ ||
+ ((VertA.position[0]>flCutPos+SUBZONE_EPSILON) && (VertB.position[0]<flCutPos-SUBZONE_EPSILON))
+ )
+ {
+ // work out the span and percentage
+ if(VertA.position[0]<flCutPos)
+ {
+ flSpan=VertB.position[0]-VertA.position[0] ;
+ flCutSpan=flCutPos-VertA.position[0] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertA.position[0]-VertB.position[0] ;
+ flCutSpan=flCutPos-VertB.position[0] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ;
+ nABNum=m_nVertexMax ;
+ if(!AddVertex(VertexAB))
+ return 0 ;
+ }// end if need create VertexAB
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline.
+ if(
+ ((VertB.position[0]<flCutPos-SUBZONE_EPSILON) && (VertC.position[0]>flCutPos+SUBZONE_EPSILON))
+ ||
+ ((VertB.position[0]>flCutPos+SUBZONE_EPSILON) && (VertC.position[0]<flCutPos-SUBZONE_EPSILON))
+ )
+ {
+ // work out the span and percentage
+ if(VertB.position[0]<flCutPos)
+ {
+ flSpan=VertC.position[0]-VertB.position[0] ;
+ flCutSpan=flCutPos-VertB.position[0] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertB.position[0]-VertC.position[0] ;
+ flCutSpan=flCutPos-VertC.position[0] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ;
+ nBCNum=m_nVertexMax ;
+ if(!AddVertex(VertexBC))
+ return 0 ;
+
+ }// end if need create VertexBC
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline.
+ if(
+ ((VertC.position[0]<flCutPos) && (VertA.position[0]>flCutPos))
+ ||
+ ((VertC.position[0]>flCutPos) && (VertA.position[0]<flCutPos))
+ )
+ {
+ // work out the span and percentage
+ if(VertC.position[0]<flCutPos)
+ {
+ flSpan=VertA.position[0]-VertC.position[0] ;
+ flCutSpan=flCutPos-VertC.position[0] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertC.position[0]-VertA.position[0] ;
+ flCutSpan=flCutPos-VertA.position[0] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ;
+ nCANum=m_nVertexMax ;
+ if(!AddVertex(VertexCA))
+ return 0 ;
+
+ }// end if need create VertexCA
+ break ;
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ case AXIS_Y:
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline.
+ if(
+ ((VertA.position[1]<flCutPos-SUBZONE_EPSILON) && (VertB.position[1]>flCutPos+SUBZONE_EPSILON))
+ ||
+ ((VertA.position[1]>flCutPos+SUBZONE_EPSILON) && (VertB.position[1]<flCutPos-SUBZONE_EPSILON))
+ )
+ {
+ // work out the span and percentage
+ if(VertA.position[1]<flCutPos)
+ {
+ flSpan=VertB.position[1]-VertA.position[1] ;
+ flCutSpan=flCutPos-VertA.position[1] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertA.position[1]-VertB.position[1] ;
+ flCutSpan=flCutPos-VertB.position[1] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ;
+ nABNum=m_nVertexMax ;
+ if(!AddVertex(VertexAB))
+ return 0 ;
+ }// end if need create VertexAB
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline.
+ if(
+ ((VertB.position[1]<flCutPos-SUBZONE_EPSILON) && (VertC.position[1]>flCutPos+SUBZONE_EPSILON))
+ ||
+ ((VertB.position[1]>flCutPos+SUBZONE_EPSILON) && (VertC.position[1]<flCutPos-SUBZONE_EPSILON))
+ )
+ {
+ // work out the span and percentage
+ if(VertB.position[1]<flCutPos)
+ {
+ flSpan=VertC.position[1]-VertB.position[1] ;
+ flCutSpan=flCutPos-VertB.position[1] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertB.position[1]-VertC.position[1] ;
+ flCutSpan=flCutPos-VertC.position[1] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ;
+ nBCNum=m_nVertexMax ;
+ if(!AddVertex(VertexBC))
+ return 0 ;
+
+ }// end if need create VertexBC
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline.
+ if(
+ ((VertC.position[1]<flCutPos) && (VertA.position[1]>flCutPos))
+ ||
+ ((VertC.position[1]>flCutPos) && (VertA.position[1]<flCutPos))
+ )
+ {
+ // work out the span and percentage
+ if(VertC.position[1]<flCutPos)
+ {
+ flSpan=VertA.position[1]-VertC.position[1] ;
+ flCutSpan=flCutPos-VertC.position[1] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertC.position[1]-VertA.position[1] ;
+ flCutSpan=flCutPos-VertA.position[1] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ;
+ nCANum=m_nVertexMax ;
+ if(!AddVertex(VertexCA))
+ return 0 ;
+
+ }// end if need create VertexCA
+ break ;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ case AXIS_Z:
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline.
+ if(
+ ((VertA.position[2]<flCutPos-SUBZONE_EPSILON) && (VertB.position[2]>flCutPos+SUBZONE_EPSILON))
+ ||
+ ((VertA.position[2]>flCutPos+SUBZONE_EPSILON) && (VertB.position[2]<flCutPos-SUBZONE_EPSILON))
+ )
+ {
+ // work out the span and percentage
+ if(VertA.position[2]<flCutPos)
+ {
+ flSpan=VertB.position[2]-VertA.position[2] ;
+ flCutSpan=flCutPos-VertA.position[2] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertA.position[2]-VertB.position[2] ;
+ flCutSpan=flCutPos-VertB.position[2] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ;
+ nABNum=m_nVertexMax ;
+ if(!AddVertex(VertexAB))
+ return 0 ;
+ }// end if need create VertexAB
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline.
+ if(
+ ((VertB.position[2]<flCutPos-SUBZONE_EPSILON) && (VertC.position[2]>flCutPos+SUBZONE_EPSILON))
+ ||
+ ((VertB.position[2]>flCutPos+SUBZONE_EPSILON) && (VertC.position[2]<flCutPos-SUBZONE_EPSILON))
+ )
+ {
+ // work out the span and percentage
+ if(VertB.position[2]<flCutPos)
+ {
+ flSpan=VertC.position[2]-VertB.position[2] ;
+ flCutSpan=flCutPos-VertB.position[2] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertB.position[2]-VertC.position[2] ;
+ flCutSpan=flCutPos-VertC.position[2] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ;
+ nBCNum=m_nVertexMax ;
+ if(!AddVertex(VertexBC))
+ return 0 ;
+
+ }// end if need create VertexBC
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline.
+ if(
+ ((VertC.position[2]<flCutPos) && (VertA.position[2]>flCutPos))
+ ||
+ ((VertC.position[2]>flCutPos) && (VertA.position[2]<flCutPos))
+ )
+ {
+ // work out the span and percentage
+ if(VertC.position[2]<flCutPos)
+ {
+ flSpan=VertA.position[2]-VertC.position[2] ;
+ flCutSpan=flCutPos-VertC.position[2] ;
+ flPercent=1.0f-flCutSpan/flSpan ;
+ }
+ else
+ {
+ flSpan=VertC.position[2]-VertA.position[2] ;
+ flCutSpan=flCutPos-VertA.position[2] ;
+ flPercent=flCutSpan/flSpan ;
+ }
+
+ CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ;
+ nCANum=m_nVertexMax ;
+ if(!AddVertex(VertexCA))
+ return 0 ;
+
+ }// end if need create VertexCA
+ break ;
+
+
+ }
+
+ int nInitialTrianglePos=m_nTriangleMax ; // debugging
+
+ // default parameters for all new triangles
+ NewTri.Texture = m_pTriangle[ nTriangle ].Texture ;
+ //NewTri.Lightmap = m_pTriangle[ nTriangle ].Lightmap ; // bzn doesn't use lightmaps
+ NewTri.Lamp = m_pTriangle[ nTriangle ].Lamp ;
+ NewTri.Group = m_pTriangle[ nTriangle ].Group ;
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // now we create new triangles depending on the verts we created.
+ if((nABNum!=-1) && (nCANum!=-1))
+ {
+ // add (AB, B, C)
+ NewTri.VIndex[0]=nABNum ;
+ NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[1] ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // add (C, CA, AB)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ;
+ NewTri.VIndex[1]=nCANum ;
+ NewTri.VIndex[2]=nABNum ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // overwrite the original triangle with (A, AB, CA)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ;
+ NewTri.VIndex[1]=nABNum ;
+ NewTri.VIndex[2]=nCANum ;
+ m_pTriangle[ nTriangle ]=NewTri ;
+ }
+ else
+ if((nABNum!=-1) && (nBCNum!=-1))
+ {
+ // add (BC, C, A)
+ NewTri.VIndex[0]=nBCNum ;
+ NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[2] ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // add (A, AB, BC)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ;
+ NewTri.VIndex[1]=nABNum ;
+ NewTri.VIndex[2]=nBCNum ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // overwrite the original triangle with (B, BC, AB)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ;
+ NewTri.VIndex[1]=nBCNum ;
+ NewTri.VIndex[2]=nABNum ;
+ m_pTriangle[ nTriangle ]=NewTri ;
+ }
+ else
+ if((nBCNum!=-1) && (nCANum!=-1))
+ {
+ // add (CA, A, B)
+ NewTri.VIndex[0]=nCANum ;
+ NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[0] ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // add (B, BC, CA)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ;
+ NewTri.VIndex[1]=nBCNum ;
+ NewTri.VIndex[2]=nCANum ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // overwrite the original triangle with (C, CA, BC)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ;
+ NewTri.VIndex[1]=nCANum ;
+ NewTri.VIndex[2]=nBCNum ;
+ m_pTriangle[ nTriangle ]=NewTri ;
+ }
+ else
+ if(nABNum!=-1)
+ {
+ // add (AB, B, C)
+ NewTri.VIndex[0]=nABNum ;
+ NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[1] ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // overwrite the original triangle with (A, AB, C)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ;
+ NewTri.VIndex[1]=nABNum ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ;
+ m_pTriangle[ nTriangle ]=NewTri ;
+ }
+ else
+ if(nBCNum!=-1)
+ {
+ // add (BC, C, A)
+ NewTri.VIndex[0]=nBCNum ;
+ NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[2] ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // overwrite the original triangle with (B, BC, A)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ;
+ NewTri.VIndex[1]=nBCNum ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ;
+ m_pTriangle[ nTriangle ]=NewTri ;
+ }
+ else
+ if(nCANum!=-1)
+ {
+ // add (CA, A, B)
+ NewTri.VIndex[0]=nCANum ;
+ NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[0] ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ;
+ if(!AddTriangle(NewTri)) return 0 ;
+
+ // overwrite the original triangle with (C, CA, B)
+ NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ;
+ NewTri.VIndex[1]=nCANum ;
+ NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ;
+ m_pTriangle[ nTriangle ]=NewTri ;
+ }
+
+ return 1 ;
+}
+
+void Q3Map::CreateTweenVert(Q3BspVertex* pVertA, Q3BspVertex* pVertB, float flPercent0, Q3BspVertex* pVertexAB)
+{
+ float flPercent1=1.0f-flPercent0 ;
+
+ pVertexAB->color[0]=flPercent0*pVertA->color[0] + flPercent1*pVertB->color[0] ;
+ pVertexAB->color[1]=flPercent0*pVertA->color[1] + flPercent1*pVertB->color[1] ;
+ pVertexAB->color[2]=flPercent0*pVertA->color[2] + flPercent1*pVertB->color[2] ;
+ pVertexAB->color[3]=flPercent0*pVertA->color[3] + flPercent1*pVertB->color[3] ;
+
+ pVertexAB->position[0]=flPercent0*pVertA->position[0] + flPercent1*pVertB->position[0] ;
+ pVertexAB->position[1]=flPercent0*pVertA->position[1] + flPercent1*pVertB->position[1] ;
+ pVertexAB->position[2]=flPercent0*pVertA->position[2] + flPercent1*pVertB->position[2] ;
+
+ pVertexAB->texcoord[0][0]=flPercent0*pVertA->texcoord[0][0] + flPercent1*pVertB->texcoord[0][0] ;
+ pVertexAB->texcoord[0][1]=flPercent0*pVertA->texcoord[0][1] + flPercent1*pVertB->texcoord[0][1] ;
+ pVertexAB->texcoord[1][0]=flPercent0*pVertA->texcoord[1][0] + flPercent1*pVertB->texcoord[1][0] ;
+ pVertexAB->texcoord[1][1]=flPercent0*pVertA->texcoord[1][1] + flPercent1*pVertB->texcoord[1][1] ;
+
+ pVertexAB->normal[0]=flPercent0*pVertA->normal[0] + flPercent1*pVertB->normal[0] ;
+ pVertexAB->normal[1]=flPercent0*pVertA->normal[1] + flPercent1*pVertB->normal[1] ;
+ pVertexAB->normal[2]=flPercent0*pVertA->normal[2] + flPercent1*pVertB->normal[2] ;
+ // normalize
+ float flLen=sqrt(pVertexAB->normal[0]*pVertexAB->normal[0] + pVertexAB->normal[1]*pVertexAB->normal[1] + pVertexAB->normal[2]*pVertexAB->normal[2]) ;
+ if(flLen!=0.0f) // don't divide by zero... but normal is messed up.
+ {
+ pVertexAB->normal[0]/=flLen ;
+ pVertexAB->normal[1]/=flLen ;
+ pVertexAB->normal[2]/=flLen ;
+ }
+ else
+ {
+ // default a messed up normal to point upward
+ pVertexAB->normal[0]=0.0f ;
+ pVertexAB->normal[1]=1.0f ;
+ pVertexAB->normal[2]=0.0f ;
+ }
+}
+
+// returns the next subzone a point is in after the start subzone, or -1 if there are no more subzones
+int Q3Map::GetNextSubZone(float *flPoint, int nStart, int nMax)
+{
+ while(++nStart<nMax)
+ if(PointInSubZone(flPoint, nStart))
+ break ;
+
+ if(nStart==nMax)
+ return -1 ;
+ else
+ return nStart ;
+}
+
+// returns true if a point is in a subzone.
+bool Q3Map::PointInSubZone(float *flPoint, int nSubZone)
+{
+ if(
+ (flPoint[0]>=m_pSubZones[nSubZone].Min[0]-SUBZONE_EPSILON) && (flPoint[0]<=m_pSubZones[nSubZone].Max[0]+SUBZONE_EPSILON)
+ &&(flPoint[1]>=m_pSubZones[nSubZone].Min[1]-SUBZONE_EPSILON) && (flPoint[1]<=m_pSubZones[nSubZone].Max[1]+SUBZONE_EPSILON)
+ &&(flPoint[2]>=m_pSubZones[nSubZone].Min[2]-SUBZONE_EPSILON) && (flPoint[2]<=m_pSubZones[nSubZone].Max[2]+SUBZONE_EPSILON)
+ )
+ return true ;
+
+ return false ;
+}
+
+// returns true if a point is in a zone.
+bool Q3Map::PointInZone(float *flPos, int nZone)
+{
+ int nMaxSubZone=m_nZone[nZone][INDEX_SUBZONECOUNT] ;
+
+ for(int nSubZoneIndex=0 ; nSubZoneIndex<nMaxSubZone ; nSubZoneIndex++)
+ if(PointInSubZone(flPos, m_nZone[nZone][nSubZoneIndex]))
+ return true ;
+
+ return false ;
+}
+
+// returns true if an axis aligned bounding box touches a subzone.
+bool Q3Map::AABBTouchesSubZone(float *flPointMin, float *flPointMax, int nSubZone)
+{
+ // if test AABB overlaps the subzone AABB
+ if(
+ (m_pSubZones[nSubZone].Min[0]<flPointMax[0]) && (m_pSubZones[nSubZone].Max[0]>flPointMin[0])
+ && (m_pSubZones[nSubZone].Min[1]<flPointMax[1]) && (m_pSubZones[nSubZone].Max[1]>flPointMin[1])
+ && (m_pSubZones[nSubZone].Min[2]<flPointMax[2]) && (m_pSubZones[nSubZone].Max[2]>flPointMin[2])
+ )
+ return true ;
+
+ return false ;
+}
+
+// returns true if an axis aligned bounding box touches a zone.
+bool Q3Map::AABBTouchesZone(float *flPosMin, float *flPosMax, int nZone)
+{
+ int nMaxSubZone=m_nZone[nZone][INDEX_SUBZONECOUNT] ;
+
+ for(int nSubZoneIndex=0 ; nSubZoneIndex<nMaxSubZone ; nSubZoneIndex++)
+ if(AABBTouchesSubZone(flPosMin, flPosMax, m_nZone[nZone][nSubZoneIndex]))
+ return true ;
+
+ return false ;
+}
+
+// take the faces from the BSP and add them to our list of triangles.
+int Q3Map::ConvertFacesToTriangles(void)
+{
+ int nFaceIndex = 0 ;
+
+ int nVertex=0 ;
+ int nVertexMax=0 ;
+ int nTriangle=0 ;
+ int nTriangleMax=0 ;
+
+ float flPosX=0.0f ;
+ float flPosY=0.0f ;
+ float flPosZ=0.0f ;
+ float flNormX=0.0f ;
+ float flNormY=0.0f ;
+ float flNormZ=0.0f ;
+ float flTexU=0.0f ;
+ float flTexV=0.0f ;
+ int nMeshVert=0 ;
+ int nMeshVertA=0 ;
+ int nMeshVertB=0 ;
+ int nMeshVertC=0 ;
+
+ Q3BspVertex *vertices = m_pVertices ;
+ int *meshverts = m_pMeshVerts ;
+
+ QVECTOR junk ;
+ junk[0]=0.0f ;
+ junk[1]=0.0f ;
+ junk[2]=0.0f ;
+
+
+ nFaceIndex = 0 ;
+ while(nFaceIndex<m_iNumFaces)
+ {
+
+ switch (m_BspFaces[nFaceIndex].type)
+ {
+ case MESH:
+ case POLYGON:
+
+ nTriangleMax=m_BspFaces[nFaceIndex].n_triangles ;
+ nMeshVert=m_BspFaces[nFaceIndex].meshvert ;
+
+ for(nTriangle=0 ; nTriangle<nTriangleMax ; nTriangle++)
+ {
+
+ // if we are out of memory, grow it. If we can't grow it, fail
+ if(m_nTriangleMax>=m_nTriangleLimit)
+ if(!ExpandTriangleMemory())
+ return 0 ;
+
+
+
+ m_pTriangle[ m_nTriangleMax ].Texture= m_BspFaces[nFaceIndex].texture ;
+ //m_pTriangle[ m_nTriangleMax ].Lightmap= m_BspFaces[nFaceIndex].lm_index ; // bzn doesn't use lightmaps
+ m_pTriangle[ m_nTriangleMax ].VIndex[0]= meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ;
+ m_pTriangle[ m_nTriangleMax ].VIndex[1]= meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ;
+ m_pTriangle[ m_nTriangleMax ].VIndex[2]= meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ;
+
+ m_pTriangle[ m_nTriangleMax ].Lamp=-1 ; // assume it didn't come from a lamp, this will be updated later
+
+ m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ; // increment group number.
+
+ m_nTriangleMax++ ;
+ }// end for nTriangle
+ m_nGroup++ ; // increment group. Every face is a new group.
+
+ break ;
+
+ }// end switch
+
+ nFaceIndex++;
+ } // end while
+
+ return 1 ;
+
+}
+
+
+// convert the patch info from the BSP into bezier curved triangle meshes and add to our triangle list.
+int Q3Map::ConvertPatchesToTriangles(void)
+{
+
+ float flPosX=0.0f ;
+ float flPosY=0.0f ;
+ float flPosZ=0.0f ;
+ float flNormX=0.0f ;
+ float flNormY=0.0f ;
+ float flNormZ=0.0f ;
+ float flTexU=0.0f ;
+ float flTexV=0.0f ;
+ int nMeshVert=0 ;
+ int nMeshVertA=0 ;
+ int nMeshVertB=0 ;
+ int nMeshVertC=0 ;
+
+
+ int nTriPerRow=0 ;
+ int nRow=0 ;
+
+ int nFirstVertex=m_nVertexMax ;
+
+ int nVertCount=nFirstVertex ;
+ int nPatchCount=0 ;
+
+ int* pIndexBuffer=NULL ;
+
+ Q3BspVertex NewVert ;
+
+
+
+
+ int nCount=0 ;
+ int nCountB=0 ;
+
+
+
+
+ int indexBufferindex = 0;
+
+ int vertexBufferindex = 0;
+
+ for (int faceIndex=0; faceIndex < m_iNumFaces; faceIndex++)
+ {
+
+ nCount++ ;
+ if(nCount==1)
+ {
+ nCountB+=nCount ;
+ nCount=0 ;
+ }
+
+
+ if (m_BspFaces[faceIndex].type == PATCH)
+ {
+ Q3BspPatch *patch = m_BspFaces[faceIndex].patch;
+
+ if (patch != NULL)
+ {
+
+ for (int bezierIndex=0; bezierIndex < patch->size; bezierIndex++)
+ {
+ indexBufferindex = 0;
+ pIndexBuffer = new int[patch->bezier[bezierIndex].mNumIndex] ;
+ if(pIndexBuffer==NULL) return 0 ; // ran out of memory
+
+
+ for (int index=0; index < patch->bezier[bezierIndex].mNumIndex; index++)
+ {
+ pIndexBuffer[indexBufferindex] = patch->bezier[bezierIndex].mIndex[index];
+ indexBufferindex++;
+ }
+
+ for (int vertex=0; vertex < patch->bezier[bezierIndex].mNumVertex; vertex++)
+ {
+
+ BspVertex *bspVertex = &patch->bezier[bezierIndex].mVertex[vertex];
+
+ NewVert.position[0]=bspVertex->mPosition[0] ;
+ NewVert.position[1]=bspVertex->mPosition[1] ;
+ NewVert.position[2]=bspVertex->mPosition[2] ;
+ NewVert.normal[0]=bspVertex->mNormal[0] ;
+ NewVert.normal[1]=bspVertex->mNormal[1] ;
+ NewVert.normal[2]=bspVertex->mNormal[2] ;
+ NewVert.texcoord[0][0]=bspVertex->mTexcoord[0][0] ;
+ NewVert.texcoord[0][1]=bspVertex->mTexcoord[0][1] ;
+
+
+
+ // if we are out of memory, grow it. If we can't grow it, fail
+ if(m_nVertexMax>=m_nVertexLimit)
+ if(!ExpandVertexMemory())
+ {
+ if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ;
+ return 0 ;
+ }
+
+
+ if(!AddVertex(NewVert))
+ {
+ if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ;
+ return 0 ;
+ }
+
+ nVertCount++ ;
+ vertexBufferindex++;
+
+ }// end for vertex
+
+
+ for (int j=0; j < 5; j++)
+ {
+ nRow=m_BspFaces[faceIndex].patch->bezier[bezierIndex].mRowIndex[j] ;
+ nTriPerRow=m_BspFaces[faceIndex].patch->bezier[bezierIndex].mTrianglesPerRow[j] ;
+
+ nMeshVertA=pIndexBuffer[nRow+0]+nFirstVertex ;
+ nMeshVertB=pIndexBuffer[nRow+1]+nFirstVertex ;
+
+ for(int nVert=2 ; nVert<nTriPerRow ; nVert++)
+ {
+ // if we are out of memory, grow it. If we can't grow it, fail
+ if(m_nTriangleMax>=m_nTriangleLimit)
+ if(!ExpandTriangleMemory())
+ {
+ if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ;
+ return 0 ;
+ }
+
+ m_pTriangle[ m_nTriangleMax ].Texture= m_BspFaces[faceIndex].texture ;
+ //m_pTriangle[ m_nTriangleMax ].Lightmap= m_BspFaces[faceIndex].lm_index ; // bzn doesn't use lightmaps
+
+
+
+ nMeshVertC=pIndexBuffer[nRow+nVert]+nFirstVertex ;
+
+
+ if(nVert&1)
+ {
+ m_pTriangle[ m_nTriangleMax ].VIndex[0]= nMeshVertB ;
+ m_pTriangle[ m_nTriangleMax ].VIndex[1]= nMeshVertA ;
+ m_pTriangle[ m_nTriangleMax ].VIndex[2]= nMeshVertC ;
+ }
+ else
+ {
+ m_pTriangle[ m_nTriangleMax ].VIndex[0]= nMeshVertA ;
+ m_pTriangle[ m_nTriangleMax ].VIndex[1]= nMeshVertB ;
+ m_pTriangle[ m_nTriangleMax ].VIndex[2]= nMeshVertC ;
+ }
+
+ m_pTriangle[ m_nTriangleMax ].Lamp=-1 ; // assume it didn't come from a lamp, this will be updated later
+
+
+ m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ;
+
+
+ m_nTriangleMax++ ;
+
+ nMeshVertA=nMeshVertB ;
+ nMeshVertB=nMeshVertC ;
+ }
+
+
+ }
+
+
+ // finished with the index buffer
+ if(pIndexBuffer)
+ DELETE_ARRAY( pIndexBuffer ) ;
+
+ nFirstVertex=nVertCount ;
+ }// end for bezier index
+
+
+ m_nGroup++ ; // increment the group number. Each patch is treated as a single group.
+
+ }// end if patch not null
+ }// end if patch
+ }// end for faceIndex
+
+ return 1 ;
+
+}
+
+//''
+// some triangles might be designed to be deferred shading shapes inside of Lamp entities.
+// If so, change their material to the deferred shading configuration for that lamp entity.
+int Q3Map::ConvertTexLampsToLampTriangles(void)
+{
+
+ float flCentreX=0.0f ;
+ float flCentreY=0.0f ;
+ float flCentreZ=0.0f ;
+
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+ float flMaxZ=0.0f ;
+
+ float flNormX=0.0f ;
+ float flNormY=0.0f ;
+ float flNormZ=0.0f ;
+ float flTexU=0.0f ;
+ float flTexV=0.0f ;
+
+ float flColR=0.0f ;
+ float flColG=0.0f ;
+ float flColB=0.0f ;
+
+ float flBrightness=0.0f ;
+
+ int nLamp=0 ;
+ int nTriangle=0 ;
+ int nTexLampListPos=0 ;
+ int nLightNode=0 ;
+ int nTexture=0 ;
+ int nZone=0 ;
+ int nLampZone=0 ;
+ int nMaxLampZone=0 ;
+ int nZoneMatch=0 ;
+
+
+ for(nTexLampListPos=0 ; nTexLampListPos<m_nTexLampMax ; nTexLampListPos++)
+ {
+ nTriangle=m_pTexLamp[nTexLampListPos] ;
+
+ nZone=m_pTriangle[nTriangle].Zone ;
+
+ nTexture=m_pTriangle[nTriangle].Texture ;
+
+ if(nTexture==m_nBZN_LightNode0)
+ nLightNode=0 ;
+ else
+ if(nTexture==m_nBZN_LightNode1)
+ nLightNode=1 ;
+ else
+ if(nTexture==m_nBZN_LightNode2)
+ nLightNode=2 ;
+ else
+ if(nTexture==m_nBZN_LightNode3)
+ nLightNode=3 ;
+ else
+ return 0 ; // didn't match any lightnode, something went wrong.
+
+
+ // scan through all the lamps, finding the ones that touch the same zone as this triangle and that have the same lightnode number
+ for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++)
+ {
+ // skip if the lightnode doesn't match
+ if(m_pLamp[nLamp].LightNode!=nLightNode)
+ continue ;
+
+
+ /*
+ // lightnode matches, check if lamp touches the same zone (lamps can touch multiple zones so we have to check them all)
+ nZoneMatch=0 ;
+ nMaxLampZone=m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT] ;
+ for(nLampZone=0 ; nLampZone<nMaxLampZone ; nLampZone++)
+ {
+ if(m_pLamp[nLamp].Zone[nLampZone]==nZone)
+ {
+ nZoneMatch=1 ;
+ break ;
+ }
+ }
+
+
+ // if the zone didn't match, continue
+ if(!nZoneMatch) continue ;
+
+ */
+
+
+
+ // check if all three vertices of this triangle fall within the bounds of this lamp
+ if(
+ // first vert
+ (m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[0]>=m_pLamp[nLamp].Min[0])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[0]<=m_pLamp[nLamp].Max[0])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[1]>=m_pLamp[nLamp].Min[1])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[1]<=m_pLamp[nLamp].Max[1])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[2]>=m_pLamp[nLamp].Min[2])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[2]<=m_pLamp[nLamp].Max[2])
+ &&
+ // second vert
+ (m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[0]>=m_pLamp[nLamp].Min[0])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[0]<=m_pLamp[nLamp].Max[0])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[1]>=m_pLamp[nLamp].Min[1])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[1]<=m_pLamp[nLamp].Max[1])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[2]>=m_pLamp[nLamp].Min[2])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[2]<=m_pLamp[nLamp].Max[2])
+ &&
+ // third vert
+ (m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[0]>=m_pLamp[nLamp].Min[0])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[0]<=m_pLamp[nLamp].Max[0])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[1]>=m_pLamp[nLamp].Min[1])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[1]<=m_pLamp[nLamp].Max[1])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[2]>=m_pLamp[nLamp].Min[2])
+ &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[2]<=m_pLamp[nLamp].Max[2])
+
+ )
+ {
+
+
+ m_pTriangle[nTriangle].Texture=m_pLamp[nLamp].Texture ;
+ m_pTriangle[nTriangle].Lamp=nLamp ;
+
+ flCentreX = m_pLamp[nLamp].Position[0] ;
+ flCentreY = m_pLamp[nLamp].Position[1] ;
+ flCentreZ = m_pLamp[nLamp].Position[2] ;
+ flColR = m_pLamp[nLamp].Colour[0]*255.0f ;
+ flColG = m_pLamp[nLamp].Colour[1]*255.0f ;
+ flColB = m_pLamp[nLamp].Colour[2]*255.0f ;
+ flBrightness= m_pLamp[nLamp].Brightness ;
+
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].texcoord[0][0]=flCentreX ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].texcoord[0][1]=flCentreY ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].texcoord[1][0]=flCentreZ ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].texcoord[1][1]=flBrightness ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].color[0]=flColR ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].color[1]=flColG ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].color[2]=flColB ;
+
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].texcoord[0][0]=flCentreX ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].texcoord[0][1]=flCentreY ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].texcoord[1][0]=flCentreZ ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].texcoord[1][1]=flBrightness ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].color[0]=flColR ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].color[1]=flColG ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].color[2]=flColB ;
+
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].texcoord[0][0]=flCentreX ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].texcoord[0][1]=flCentreY ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].texcoord[1][0]=flCentreZ ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].texcoord[1][1]=flBrightness ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].color[0]=flColR ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].color[1]=flColG ;
+ m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].color[2]=flColB ;
+
+
+ m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ;
+
+
+ }// end triangle is in bounds of lamp
+
+
+ m_nGroup++ ; // increment group number. Every texture lamp is a group.
+
+
+ }// end for nLamp
+
+
+ }
+
+
+
+ return 1 ;
+}
+
+
+// convert lamps into boxes. Lamps are deferred shading non-shadowing lights, and are rendered as triangles
+// The texture coords are actually the light centre point, the spot the shaders calculate as the source of the lighting,
+// and also the brightness
+// The triangles created will remember the lamp they came from, via Triangle.Lamp
+
+int Q3Map::ConvertLampsToTriangles(void)
+{
+ float flCentreX=0.0f ;
+ float flCentreY=0.0f ;
+ float flCentreZ=0.0f ;
+
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+ float flMaxZ=0.0f ;
+
+ float flNormX=0.0f ;
+ float flNormY=0.0f ;
+ float flNormZ=0.0f ;
+ float flTexU=0.0f ;
+ float flTexV=0.0f ;
+
+ float flColR=0.0f ;
+ float flColG=0.0f ;
+ float flColB=0.0f ;
+
+ float flBrightness=0.0f ;
+
+ int nLamp=0 ;
+
+ // lower case = min, upper case = max
+ Q3BspVertex Vert_xyz ;
+ Q3BspVertex Vert_Xyz ;
+ Q3BspVertex Vert_xYz ;
+ Q3BspVertex Vert_XYz ;
+ Q3BspVertex Vert_xyZ ;
+ Q3BspVertex Vert_XyZ ;
+ Q3BspVertex Vert_xYZ ;
+ Q3BspVertex Vert_XYZ ;
+
+ int n_xyz=0 ;
+ int n_Xyz=0 ;
+ int n_xYz=0 ;
+ int n_XYz=0 ;
+ int n_xyZ=0 ;
+ int n_XyZ=0 ;
+ int n_xYZ=0 ;
+ int n_XYZ=0 ;
+
+ int nFirstVertex=0 ;
+
+ triangle_t Triangle ;
+ ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ;
+
+ for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++)
+ {
+ if(m_pLamp[nLamp].LightNode>-1) continue ; // lamps that are lightnodes don't add their own triangles. They just exist as information for TexLamps.
+
+
+ flCentreX = m_pLamp[nLamp].Position[0] ;
+ flCentreY = m_pLamp[nLamp].Position[1] ;
+ flCentreZ = m_pLamp[nLamp].Position[2] ;
+
+ flMinX = m_pLamp[nLamp].Min[0] ;
+ flMinY = m_pLamp[nLamp].Min[1] ;
+ flMinZ = m_pLamp[nLamp].Min[2] ;
+
+ flMaxX = m_pLamp[nLamp].Max[0] ;
+ flMaxY = m_pLamp[nLamp].Max[1] ;
+ flMaxZ = m_pLamp[nLamp].Max[2] ;
+
+ flColR = m_pLamp[nLamp].Colour[0]*255.0f ;
+ flColG = m_pLamp[nLamp].Colour[1]*255.0f ;
+ flColB = m_pLamp[nLamp].Colour[2]*255.0f ;
+
+ flBrightness= m_pLamp[nLamp].Brightness ;
+
+ //////////////////////////////////////
+ // setup our 8 vertices. Normal isn't that important, I just approximate regardless of actual box shape
+
+
+ nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles
+
+ // vertex numbers
+ n_xyz=nFirstVertex+0 ;
+ n_Xyz=nFirstVertex+1 ;
+ n_xYz=nFirstVertex+2 ;
+ n_XYz=nFirstVertex+3 ;
+ n_xyZ=nFirstVertex+4 ;
+ n_XyZ=nFirstVertex+5 ;
+ n_xYZ=nFirstVertex+6 ;
+ n_XYZ=nFirstVertex+7 ;
+
+
+ Vert_xyz.position[0]=flMinX ;
+ Vert_xyz.position[1]=flMinY ;
+ Vert_xyz.position[2]=flMinZ ;
+ Vert_xyz.normal[0]=-0.5773502691896 ;
+ Vert_xyz.normal[1]=-0.5773502691896 ;
+ Vert_xyz.normal[2]=-0.5773502691896 ;
+ Vert_xyz.texcoord[0][0]=flCentreX ;
+ Vert_xyz.texcoord[0][1]=flCentreY ;
+ Vert_xyz.texcoord[1][0]=flCentreZ ;
+ Vert_xyz.texcoord[1][1]=flBrightness ;
+ Vert_xyz.color[0]=flColR ;
+ Vert_xyz.color[1]=flColG ;
+ Vert_xyz.color[2]=flColB ;
+ if(!AddVertex(Vert_xyz)) return 0 ;
+
+
+ Vert_Xyz.position[0]=flMaxX ;
+ Vert_Xyz.position[1]=flMinY ;
+ Vert_Xyz.position[2]=flMinZ ;
+ Vert_Xyz.normal[0]= 0.5773502691896 ;
+ Vert_Xyz.normal[1]=-0.5773502691896 ;
+ Vert_Xyz.normal[2]=-0.5773502691896 ;
+ Vert_Xyz.texcoord[0][0]=flCentreX ;
+ Vert_Xyz.texcoord[0][1]=flCentreY ;
+ Vert_Xyz.texcoord[1][0]=flCentreZ ;
+ Vert_Xyz.texcoord[1][1]=flBrightness ;
+ Vert_Xyz.color[0]=flColR ;
+ Vert_Xyz.color[1]=flColG ;
+ Vert_Xyz.color[2]=flColB ;
+ if(!AddVertex(Vert_Xyz)) return 0 ;
+
+ Vert_xYz.position[0]=flMinX ;
+ Vert_xYz.position[1]=flMaxY ;
+ Vert_xYz.position[2]=flMinZ ;
+ Vert_xYz.normal[0]=-0.5773502691896 ;
+ Vert_xYz.normal[1]= 0.5773502691896 ;
+ Vert_xYz.normal[2]=-0.5773502691896 ;
+ Vert_xYz.texcoord[0][0]=flCentreX ;
+ Vert_xYz.texcoord[0][1]=flCentreY ;
+ Vert_xYz.texcoord[1][0]=flCentreZ ;
+ Vert_xYz.texcoord[1][1]=flBrightness ;
+ Vert_xYz.color[0]=flColR ;
+ Vert_xYz.color[1]=flColG ;
+ Vert_xYz.color[2]=flColB ;
+ if(!AddVertex(Vert_xYz)) return 0 ;
+
+ Vert_XYz.position[0]=flMaxX ;
+ Vert_XYz.position[1]=flMaxY ;
+ Vert_XYz.position[2]=flMinZ ;
+ Vert_XYz.normal[0]= 0.5773502691896 ;
+ Vert_XYz.normal[1]= 0.5773502691896 ;
+ Vert_XYz.normal[2]=-0.5773502691896 ;
+ Vert_XYz.texcoord[0][0]=flCentreX ;
+ Vert_XYz.texcoord[0][1]=flCentreY ;
+ Vert_XYz.texcoord[1][0]=flCentreZ ;
+ Vert_XYz.texcoord[1][1]=flBrightness ;
+ Vert_XYz.color[0]=flColR ;
+ Vert_XYz.color[1]=flColG ;
+ Vert_XYz.color[2]=flColB ;
+ if(!AddVertex(Vert_XYz)) return 0 ;
+
+ //////////////////////////////////////
+
+ Vert_xyZ.position[0]=flMinX ;
+ Vert_xyZ.position[1]=flMinY ;
+ Vert_xyZ.position[2]=flMaxZ ;
+ Vert_xyZ.normal[0]=-0.5773502691896 ;
+ Vert_xyZ.normal[1]=-0.5773502691896 ;
+ Vert_xyZ.normal[2]= 0.5773502691896 ;
+ Vert_xyZ.texcoord[0][0]=flCentreX ;
+ Vert_xyZ.texcoord[0][1]=flCentreY ;
+ Vert_xyZ.texcoord[1][0]=flCentreZ ;
+ Vert_xyZ.texcoord[1][1]=flBrightness ;
+ Vert_xyZ.color[0]=flColR ;
+ Vert_xyZ.color[1]=flColG ;
+ Vert_xyZ.color[2]=flColB ;
+ if(!AddVertex(Vert_xyZ)) return 0 ;
+
+ Vert_XyZ.position[0]=flMaxX ;
+ Vert_XyZ.position[1]=flMinY ;
+ Vert_XyZ.position[2]=flMaxZ ;
+ Vert_XyZ.normal[0]= 0.5773502691896 ;
+ Vert_XyZ.normal[1]=-0.5773502691896 ;
+ Vert_XyZ.normal[2]= 0.5773502691896 ;
+ Vert_XyZ.texcoord[0][0]=flCentreX ;
+ Vert_XyZ.texcoord[0][1]=flCentreY ;
+ Vert_XyZ.texcoord[1][0]=flCentreZ ;
+ Vert_XyZ.texcoord[1][1]=flBrightness ;
+ Vert_XyZ.color[0]=flColR ;
+ Vert_XyZ.color[1]=flColG ;
+ Vert_XyZ.color[2]=flColB ;
+ if(!AddVertex(Vert_XyZ)) return 0 ;
+
+ Vert_xYZ.position[0]=flMinX ;
+ Vert_xYZ.position[1]=flMaxY ;
+ Vert_xYZ.position[2]=flMaxZ ;
+ Vert_xYZ.normal[0]=-0.5773502691896 ;
+ Vert_xYZ.normal[1]= 0.5773502691896 ;
+ Vert_xYZ.normal[2]= 0.5773502691896 ;
+ Vert_xYZ.texcoord[0][0]=flCentreX ;
+ Vert_xYZ.texcoord[0][1]=flCentreY ;
+ Vert_xYZ.texcoord[1][0]=flCentreZ ;
+ Vert_xYZ.texcoord[1][1]=flBrightness ;
+ Vert_xYZ.color[0]=flColR ;
+ Vert_xYZ.color[1]=flColG ;
+ Vert_xYZ.color[2]=flColB ;
+ if(!AddVertex(Vert_xYZ)) return 0 ;
+
+ Vert_XYZ.position[0]=flMaxX ;
+ Vert_XYZ.position[1]=flMaxY ;
+ Vert_XYZ.position[2]=flMaxZ ;
+ Vert_XYZ.normal[0]= 0.5773502691896 ;
+ Vert_XYZ.normal[1]= 0.5773502691896 ;
+ Vert_XYZ.normal[2]= 0.5773502691896 ;
+ Vert_XYZ.texcoord[0][0]=flCentreX ;
+ Vert_XYZ.texcoord[0][1]=flCentreY ;
+ Vert_XYZ.texcoord[1][0]=flCentreZ ;
+ Vert_XYZ.texcoord[1][1]=flBrightness ;
+ Vert_XYZ.color[0]=flColR ;
+ Vert_XYZ.color[1]=flColG ;
+ Vert_XYZ.color[2]=flColB ;
+ if(!AddVertex(Vert_XYZ)) return 0 ;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ Triangle.Texture=m_pLamp[nLamp].Texture ;
+ Triangle.Lamp=nLamp ;
+ Triangle.Group=m_nGroup ;
+
+ /////////////////////////////////////
+
+ Triangle.VIndex[2]=n_xyz ;
+ Triangle.VIndex[1]=n_xyZ ;
+ Triangle.VIndex[0]=n_xYZ ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[2]=n_xYZ ;
+ Triangle.VIndex[1]=n_xYz ;
+ Triangle.VIndex[0]=n_xyz ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ /////////////////////////////////////
+
+ Triangle.VIndex[0]=n_Xyz ;
+ Triangle.VIndex[1]=n_XyZ ;
+ Triangle.VIndex[2]=n_XYZ ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_XYZ ;
+ Triangle.VIndex[1]=n_XYz ;
+ Triangle.VIndex[2]=n_Xyz ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ /////////////////////////////////////
+
+ Triangle.VIndex[2]=n_xyz ;
+ Triangle.VIndex[1]=n_xYz ;
+ Triangle.VIndex[0]=n_XYz ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[2]=n_XYz ;
+ Triangle.VIndex[1]=n_Xyz ;
+ Triangle.VIndex[0]=n_xyz ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ /////////////////////////////////////
+
+ Triangle.VIndex[0]=n_xyZ ;
+ Triangle.VIndex[1]=n_xYZ ;
+ Triangle.VIndex[2]=n_XYZ ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_XYZ ;
+ Triangle.VIndex[1]=n_XyZ ;
+ Triangle.VIndex[2]=n_xyZ ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ /////////////////////////////////////
+
+ Triangle.VIndex[0]=n_xyz ;
+ Triangle.VIndex[1]=n_xyZ ;
+ Triangle.VIndex[2]=n_XyZ ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_XyZ ;
+ Triangle.VIndex[1]=n_Xyz ;
+ Triangle.VIndex[2]=n_xyz ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ /////////////////////////////////////
+
+ Triangle.VIndex[2]=n_xYz ;
+ Triangle.VIndex[1]=n_xYZ ;
+ Triangle.VIndex[0]=n_XYZ ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[2]=n_XYZ ;
+ Triangle.VIndex[1]=n_XYz ;
+ Triangle.VIndex[0]=n_xYz ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ m_nGroup++ ; // increment group once for every lamp
+ }
+
+
+
+ return 1 ;
+}
+
+
+int Q3Map::ConvertLampsToGlowTriangles(void)
+{
+ float flCentreX=0.0f ;
+ float flCentreY=0.0f ;
+ float flCentreZ=0.0f ;
+
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+ float flMaxZ=0.0f ;
+
+ float flNormX=0.0f ;
+ float flNormY=0.0f ;
+ float flNormZ=0.0f ;
+ float flTexU=0.0f ;
+ float flTexV=0.0f ;
+
+ float flColR=0.0f ;
+ float flColG=0.0f ;
+ float flColB=0.0f ;
+
+ float flBrightness=0.0f ;
+
+ int nLamp=0 ;
+
+
+ Q3BspVertex Vert_L ;
+ Q3BspVertex Vert_R ;
+ Q3BspVertex Vert_F ;
+ Q3BspVertex Vert_B ;
+ Q3BspVertex Vert_U ;
+ Q3BspVertex Vert_D ;
+
+
+ int n_L=0 ;
+ int n_R=0 ;
+ int n_F=0 ;
+ int n_B=0 ;
+ int n_U=0 ;
+ int n_D=0 ;
+
+ int nFirstVertex=0 ;
+
+ float flBaseGlowSize=0.15f ;//0.2f;//0.001f ;
+ float flGlowSize=0.0f ;
+
+
+
+ triangle_t Triangle ;
+ ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ;
+
+ for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++)
+ {
+
+ flGlowSize=flBaseGlowSize*m_pLamp[nLamp].Brightness ;
+
+ flCentreX = m_pLamp[nLamp].Position[0] ;
+ flCentreY = m_pLamp[nLamp].Position[1] ;
+ flCentreZ = m_pLamp[nLamp].Position[2] ;
+
+ flMinX = flCentreX-flGlowSize ;
+ flMinY = flCentreY-flGlowSize ;
+ flMinZ = flCentreZ-flGlowSize ;
+
+ flMaxX = flCentreX+flGlowSize ;
+ flMaxY = flCentreY+flGlowSize ;
+ flMaxZ = flCentreZ+flGlowSize ;
+
+ flColR = m_pLamp[nLamp].Colour[0]*255.0f ;
+ flColG = m_pLamp[nLamp].Colour[1]*255.0f ;
+ flColB = m_pLamp[nLamp].Colour[2]*255.0f ;
+
+ flBrightness= m_pLamp[nLamp].Brightness*4.0f ;
+
+ //////////////////////////////////////
+ // setup our 8 vertices. Normal isn't that important, I just approximate regardless of actual box shape
+
+
+ nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles
+
+ // vertex numbers
+ n_L=nFirstVertex+0 ;
+ n_R=nFirstVertex+1 ;
+ n_F=nFirstVertex+2 ;
+ n_B=nFirstVertex+3 ;
+ n_U=nFirstVertex+4 ;
+ n_D=nFirstVertex+5 ;
+
+
+
+ Vert_L.position[0]=flMinX ;
+ Vert_L.position[1]=flCentreY ;
+ Vert_L.position[2]=flCentreZ ;
+ Vert_L.normal[0]=-1.0 ;
+ Vert_L.normal[1]=0.0 ;
+ Vert_L.normal[2]=0.0 ;
+ Vert_L.texcoord[0][0]=flCentreX ;
+ Vert_L.texcoord[0][1]=flCentreY ;
+ Vert_L.texcoord[1][0]=flCentreZ ;
+ Vert_L.texcoord[1][1]=flBrightness ;
+ Vert_L.color[0]=flColR ;
+ Vert_L.color[1]=flColG ;
+ Vert_L.color[2]=flColB ;
+ if(!AddVertex(Vert_L)) return 0 ;
+
+ Vert_R.position[0]=flMaxX ;
+ Vert_R.position[1]=flCentreY ;
+ Vert_R.position[2]=flCentreZ ;
+ Vert_R.normal[0]=1.0 ;
+ Vert_R.normal[1]=0.0 ;
+ Vert_R.normal[2]=0.0 ;
+ Vert_R.texcoord[0][0]=flCentreX ;
+ Vert_R.texcoord[0][1]=flCentreY ;
+ Vert_R.texcoord[1][0]=flCentreZ ;
+ Vert_R.texcoord[1][1]=flBrightness ;
+ Vert_R.color[0]=flColR ;
+ Vert_R.color[1]=flColG ;
+ Vert_R.color[2]=flColB ;
+ if(!AddVertex(Vert_R)) return 0 ;
+
+ Vert_F.position[0]=flCentreX ;
+ Vert_F.position[1]=flCentreY ;
+ Vert_F.position[2]=flMinZ ;
+ Vert_F.normal[0]=0.0 ;
+ Vert_F.normal[1]=0.0 ;
+ Vert_F.normal[2]=-1.0 ;
+ Vert_F.texcoord[0][0]=flCentreX ;
+ Vert_F.texcoord[0][1]=flCentreY ;
+ Vert_F.texcoord[1][0]=flCentreZ ;
+ Vert_F.texcoord[1][1]=flBrightness ;
+ Vert_F.color[0]=flColR ;
+ Vert_F.color[1]=flColG ;
+ Vert_F.color[2]=flColB ;
+ if(!AddVertex(Vert_F)) return 0 ;
+
+ Vert_B.position[0]=flCentreX ;
+ Vert_B.position[1]=flCentreY ;
+ Vert_B.position[2]=flMaxZ ;
+ Vert_B.normal[0]=0.0 ;
+ Vert_B.normal[1]=0.0 ;
+ Vert_B.normal[2]=1.0 ;
+ Vert_B.texcoord[0][0]=flCentreX ;
+ Vert_B.texcoord[0][1]=flCentreY ;
+ Vert_B.texcoord[1][0]=flCentreZ ;
+ Vert_B.texcoord[1][1]=flBrightness ;
+ Vert_B.color[0]=flColR ;
+ Vert_B.color[1]=flColG ;
+ Vert_B.color[2]=flColB ;
+ if(!AddVertex(Vert_B)) return 0 ;
+
+ Vert_U.position[0]=flCentreX ;
+ Vert_U.position[1]=flMaxY ;
+ Vert_U.position[2]=flCentreZ ;
+ Vert_U.normal[0]=0.0 ;
+ Vert_U.normal[1]=1.0 ;
+ Vert_U.normal[2]=0.0 ;
+ Vert_U.texcoord[0][0]=flCentreX ;
+ Vert_U.texcoord[0][1]=flCentreY ;
+ Vert_U.texcoord[1][0]=flCentreZ ;
+ Vert_U.texcoord[1][1]=flBrightness ;
+ Vert_U.color[0]=flColR ;
+ Vert_U.color[1]=flColG ;
+ Vert_U.color[2]=flColB ;
+ if(!AddVertex(Vert_U)) return 0 ;
+
+ Vert_D.position[0]=flCentreX ;
+ Vert_D.position[1]=flMinY ;
+ Vert_D.position[2]=flCentreZ ;
+ Vert_D.normal[0]=0.0 ;
+ Vert_D.normal[1]=-1.0 ;
+ Vert_D.normal[2]=0.0 ;
+ Vert_D.texcoord[0][0]=flCentreX ;
+ Vert_D.texcoord[0][1]=flCentreY ;
+ Vert_D.texcoord[1][0]=flCentreZ ;
+ Vert_D.texcoord[1][1]=flBrightness ;
+ Vert_D.color[0]=flColR ;
+ Vert_D.color[1]=flColG ;
+ Vert_D.color[2]=flColB ;
+ if(!AddVertex(Vert_D)) return 0 ;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ Triangle.Texture=m_nDefaultTextureIndexGlowLamp ;
+ Triangle.Lamp=-1 ;
+ Triangle.Group=m_nGroup ;
+
+ /////////////////////////////////////
+
+ Triangle.VIndex[0]=n_U ;
+ Triangle.VIndex[1]=n_L ;
+ Triangle.VIndex[2]=n_F ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_U ;
+ Triangle.VIndex[1]=n_F ;
+ Triangle.VIndex[2]=n_R ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_U ;
+ Triangle.VIndex[1]=n_R ;
+ Triangle.VIndex[2]=n_B ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_U ;
+ Triangle.VIndex[1]=n_B ;
+ Triangle.VIndex[2]=n_L ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ //////////////////////////////////////
+
+ Triangle.VIndex[2]=n_D ;
+ Triangle.VIndex[1]=n_L ;
+ Triangle.VIndex[0]=n_F ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[2]=n_D ;
+ Triangle.VIndex[1]=n_F ;
+ Triangle.VIndex[0]=n_R ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[2]=n_D ;
+ Triangle.VIndex[1]=n_R ;
+ Triangle.VIndex[0]=n_B ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[2]=n_D ;
+ Triangle.VIndex[1]=n_B ;
+ Triangle.VIndex[0]=n_L ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ m_nGroup++ ; // increment group once for each glow
+
+ }
+
+
+
+ return 1 ;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+int Q3Map::ConvertLightsToGlowTriangles(void)
+{
+ float flCentreX=0.0f ;
+ float flCentreY=0.0f ;
+ float flCentreZ=0.0f ;
+
+ float flMinX=0.0f ;
+ float flMinY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxX=0.0f ;
+ float flMaxY=0.0f ;
+ float flMaxZ=0.0f ;
+
+ float flNormX=0.0f ;
+ float flNormY=0.0f ;
+ float flNormZ=0.0f ;
+ float flTexU=0.0f ;
+ float flTexV=0.0f ;
+
+ float flColR=0.0f ;
+ float flColG=0.0f ;
+ float flColB=0.0f ;
+
+ float flBrightness=0.0f ;
+
+ int nLight=0 ;
+
+ Q3BspVertex Vert_Or ;
+ Q3BspVertex Vert_A0 ;
+ Q3BspVertex Vert_A1 ;
+ Q3BspVertex Vert_B0 ;
+ Q3BspVertex Vert_B1 ;
+
+
+ int n_Or=0 ;
+ int n_A0=0 ;
+ int n_A1=0 ;
+ int n_B0=0 ;
+ int n_B1=0 ;
+
+ int nFirstVertex=0 ;
+
+ float flBaseGlowSize=0.2f ;//0.001f ;
+ float flGlowSize=0.0f ;
+
+ char chMessage[1024] ;
+
+
+
+ triangle_t Triangle ;
+ ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ;
+
+ for(nLight=0 ; nLight<m_nLightMax ; nLight++)
+ //for(nLight=0 ; nLight<1 ; nLight++)
+ {
+ //if(m_pLight[nLight].LightNode>-1) continue ; // Lights that are lightnodes don't add their own triangles. They just exist as information for TexLights.
+
+ flGlowSize=flBaseGlowSize*m_pLight[nLight].Brightness ;
+
+ flCentreX = m_pLight[nLight].Position[0] ;
+ flCentreY = m_pLight[nLight].Position[1] ;
+ flCentreZ = m_pLight[nLight].Position[2] ;
+
+ flMinX = flCentreX-flGlowSize ;
+ flMinY = flCentreY-flGlowSize ;
+ flMinZ = flCentreZ-flGlowSize ;
+
+ flMaxX = flCentreX+flGlowSize ;
+ flMaxY = flCentreY+flGlowSize ;
+ flMaxZ = flCentreZ+flGlowSize ;
+
+ flColR = m_pLight[nLight].Colour[0]*255.0f ;
+ flColG = m_pLight[nLight].Colour[1]*255.0f ;
+ flColB = m_pLight[nLight].Colour[2]*255.0f ;
+
+ flBrightness= m_pLight[nLight].Brightness * 0.75 ;//*2.0 ;
+
+ //////////////////////////////////////
+ // setup our 5 vertices.
+
+
+ nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles
+
+ // vertex numbers
+ n_Or=nFirstVertex+0 ;
+ n_A0=nFirstVertex+1 ;
+ n_A1=nFirstVertex+2 ;
+ n_B0=nFirstVertex+3 ;
+ n_B1=nFirstVertex+4 ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ float flHALFPI = 1.5707963 ;
+ float flTWOPI = 6.2831853 ;
+ float flPI = 3.1415926 ;
+ float flAngle=(m_pLight[nLight].Angle/360.0f*flTWOPI)/2.0 ;
+ float flCutoff=32.0f ;//m_pLight[nLight].Brightness ;
+
+ Q3BspVertex color ;
+
+ Q3BspVertex NormalVert ;
+ SetVertex(&NormalVert, m_pLight[nLight].Direction[0], m_pLight[nLight].Direction[1], m_pLight[nLight].Direction[2]) ;
+ NormalVert=GetNormalised(&NormalVert) ;
+
+ Q3BspVertex normal ;
+ SetVertex(&normal, m_pLight[nLight].Direction[0]*flCutoff, m_pLight[nLight].Direction[1]*flCutoff, m_pLight[nLight].Direction[2]*flCutoff) ;
+
+ Q3BspVertex adjust=normal ;
+ VertexScale(&adjust, 0.5) ;
+
+ Q3BspVertex start ; SetVertex(&start, flCentreX, flCentreY, flCentreZ) ;
+ Q3BspVertex end ; SetVertex(&end, flCentreX+normal.position[0], flCentreY+normal.position[1], flCentreZ+normal.position[2]) ;
+
+ Q3BspVertex xaxis ; SetVertex(&xaxis, 1,0,0) ;
+ Q3BspVertex xaxisneg ; SetVertex(&xaxisneg, -1,0,0) ;
+ Q3BspVertex yaxis ; SetVertex(&yaxis, 0,1,0) ;
+ Q3BspVertex Origin ; SetVertex(&Origin, 0,0,0) ;
+ Q3BspVertex tangentA ;
+ Q3BspVertex tangentB ;
+ Q3BspVertex tangentStart ;
+ Q3BspVertex tangentEnd ;
+ Q3BspVertex tangentEndA0 ;
+ Q3BspVertex tangentEndA1 ;
+ Q3BspVertex tangentEndB0 ;
+ Q3BspVertex tangentEndB1 ;
+
+ Q3BspVertex tangentANorm ;
+ Q3BspVertex tangentBNorm ;
+
+ Q3BspVertex raytangent ;
+
+ Q3BspVertex ray ;
+ float theta=0.0f ;
+ float adjacent=0.0f ;
+ SetVertex(&color, 0.66, 0.66, 0.66) ;
+
+ if(flAngle<0.0001) return 0 ;
+
+ if(flAngle>flPI-0.01) // near on 180 degrees
+ flAngle=flPI-0.01 ;
+
+
+ Q3BspVertex backshift ;
+ backshift=normal ;
+ VertexScale(&backshift, 0.95) ;
+
+
+ if( !VectorsAreEqual(&NormalVert, &xaxis) && !VectorsAreEqual(&NormalVert, &xaxisneg) )
+ tangentA=NormalizedCrossProduct(Origin, normal, xaxis) ;
+ else
+ tangentA=NormalizedCrossProduct(Origin, normal, yaxis) ;
+
+ tangentB=NormalizedCrossProduct(Origin, normal, tangentA) ;
+
+ tangentANorm=tangentA ;
+ tangentBNorm=tangentB ;
+
+
+
+ theta=flHALFPI-flAngle ; // angle between adjacent and hypotenuse (the normal is the "opposite" side, and we know there's a right angle)
+ adjacent=VertexDistance(&Origin, &normal)/tan(theta) ;
+
+ //////////////////////////////////////////////////////////////////////
+
+ Vert_Or.position[0]=end.position[0]-backshift.position[0] ;
+ Vert_Or.position[1]=end.position[1]-backshift.position[1] ;
+ Vert_Or.position[2]=end.position[2]-backshift.position[2] ;
+ Vert_Or.normal[0]= NormalVert.position[0] ;
+ Vert_Or.normal[1]= NormalVert.position[1] ;
+ Vert_Or.normal[2]= NormalVert.position[2] ;
+ Vert_Or.texcoord[0][0]=flCentreX ;
+ Vert_Or.texcoord[0][1]=flCentreY ;
+ Vert_Or.texcoord[1][0]=flCentreZ ;
+ Vert_Or.texcoord[1][1]=flBrightness ;
+ Vert_Or.color[0]=flColR ;
+ Vert_Or.color[1]=flColG ;
+ Vert_Or.color[2]=flColB ;
+ if(!AddVertex(Vert_Or)) return 0 ;
+
+
+
+
+ //////////////////////////////////////////////////////////////////////
+
+ flColR=0.0f ;
+ flColG=0.0f ;
+ flColB=0.0f ;
+
+ tangentA=GetNormalised(&tangentA) ;
+ VertexScale(&tangentA, adjacent) ;
+
+ tangentStart=start ;
+ tangentEnd=VectorSubtract(&end, &tangentA) ;
+ ray=VectorSubtract(&tangentEnd, &tangentStart) ;
+ ray=GetNormalised(&ray) ;
+ VertexScale(&ray, flCutoff) ;
+ tangentStart=start ;
+ tangentEndA0=VectorAdd(&start, &ray) ;
+
+ raytangent=VectorSubtract(&end, &tangentEndA0) ;
+ raytangent=VectorAdd(&raytangent, &adjust) ;
+ raytangent=GetNormalised(&raytangent) ;
+
+
+
+ tangentEndA0=VectorSubtract(&tangentEndA0, &backshift) ;
+ Vert_A0.position[0]=tangentEndA0.position[0] ;
+ Vert_A0.position[1]=tangentEndA0.position[1] ;
+ Vert_A0.position[2]=tangentEndA0.position[2] ;
+ Vert_A0.normal[0]= -raytangent.position[0] ;
+ Vert_A0.normal[1]= -raytangent.position[1] ;
+ Vert_A0.normal[2]= -raytangent.position[2] ;
+ Vert_A0.texcoord[0][0]=flCentreX ;
+ Vert_A0.texcoord[0][1]=flCentreY ;
+ Vert_A0.texcoord[1][0]=flCentreZ ;
+ Vert_A0.texcoord[1][1]=flBrightness ;
+ Vert_A0.color[0]=flColR ;//abs(Vert_A0.normal[0])*255 ;//0.0f ;
+ Vert_A0.color[1]=flColG ;//abs(Vert_A0.normal[1])*255 ;//0.0f ;
+ Vert_A0.color[2]=flColB ;//abs(Vert_A0.normal[2])*255 ;//0.0f ;
+ if(!AddVertex(Vert_A0)) return 0 ;
+
+
+ tangentStart=start ;
+ tangentEnd=VectorAdd(&end, &tangentA) ;
+ ray=VectorSubtract(&tangentEnd, &tangentStart) ;
+ ray=GetNormalised(&ray) ;
+ VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ;
+ tangentStart=start ;
+ tangentEndA1=VectorAdd(&start, &ray) ;
+
+ raytangent=VectorSubtract(&end, &tangentEndA1) ;
+ raytangent=VectorAdd(&raytangent, &adjust) ;
+ raytangent=GetNormalised(&raytangent) ;
+
+ tangentEndA1=VectorSubtract(&tangentEndA1, &backshift) ;
+ Vert_A1.position[0]=tangentEndA1.position[0] ;
+ Vert_A1.position[1]=tangentEndA1.position[1] ;
+ Vert_A1.position[2]=tangentEndA1.position[2] ;
+ Vert_A1.normal[0]= -raytangent.position[0] ;
+ Vert_A1.normal[1]= -raytangent.position[1] ;
+ Vert_A1.normal[2]= -raytangent.position[2] ;
+ Vert_A1.texcoord[0][0]=flCentreX ;
+ Vert_A1.texcoord[0][1]=flCentreY ;
+ Vert_A1.texcoord[1][0]=flCentreZ ;
+ Vert_A1.texcoord[1][1]=flBrightness ;
+ Vert_A1.color[0]=flColR ;//abs(Vert_A1.normal[0])*255 ;//0.0f ;
+ Vert_A1.color[1]=flColG ;//abs(Vert_A1.normal[1])*255 ;//0.0f ;
+ Vert_A1.color[2]=flColB ;//abs(Vert_A1.normal[2])*255 ;//0.0f ;
+ if(!AddVertex(Vert_A1)) return 0 ;
+
+ //////////////////////////////////////////////////////////////////////
+
+ tangentB=GetNormalised(&tangentB) ;
+ VertexScale(&tangentB, adjacent) ; //tangentB.getScaledBy(adjacent) ;
+
+ tangentStart=start ;
+ tangentEnd=VectorSubtract(&end, &tangentB) ;
+ ray=VectorSubtract(&tangentEnd, &tangentStart) ;
+ ray=GetNormalised(&ray) ;
+ VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ;
+ tangentStart=start ;
+ tangentEndB0=VectorAdd(&start, &ray) ;
+
+ raytangent=VectorSubtract(&end, &tangentEndB0) ;
+ raytangent=VectorAdd(&raytangent, &adjust) ;
+ raytangent=GetNormalised(&raytangent) ;
+
+ tangentEndB0=VectorSubtract(&tangentEndB0, &backshift) ;
+ Vert_B0.position[0]=tangentEndB0.position[0] ;
+ Vert_B0.position[1]=tangentEndB0.position[1] ;
+ Vert_B0.position[2]=tangentEndB0.position[2] ;
+ Vert_B0.normal[0]= -raytangent.position[0] ;
+ Vert_B0.normal[1]= -raytangent.position[1] ;
+ Vert_B0.normal[2]= -raytangent.position[2] ;
+ Vert_B0.texcoord[0][0]=flCentreX ;
+ Vert_B0.texcoord[0][1]=flCentreY ;
+ Vert_B0.texcoord[1][0]=flCentreZ ;
+ Vert_B0.texcoord[1][1]=flBrightness ;
+ Vert_B0.color[0]=flColR ;//abs(Vert_B0.normal[0])*255 ;//0.0f ;
+ Vert_B0.color[1]=flColG ;//abs(Vert_B0.normal[1])*255 ;//0.0f ;
+ Vert_B0.color[2]=flColB ;//abs(Vert_B0.normal[2])*255 ;//0.0f ;
+ if(!AddVertex(Vert_B0)) return 0 ;
+
+ tangentStart=start ;
+ tangentEnd=VectorAdd(&end, &tangentB) ;
+ ray=VectorSubtract(&tangentEnd, &tangentStart) ;
+ ray=GetNormalised(&ray) ;
+ VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ;
+ tangentStart=start ;
+ tangentEndB1=VectorAdd(&start, &ray) ;
+
+ raytangent=VectorSubtract(&end, &tangentEndB1) ;
+ raytangent=VectorAdd(&raytangent, &adjust) ;
+ raytangent=GetNormalised(&raytangent) ;
+
+ tangentEndB1=VectorSubtract(&tangentEndB1, &backshift) ;
+ Vert_B1.position[0]=tangentEndB1.position[0] ;
+ Vert_B1.position[1]=tangentEndB1.position[1] ;
+ Vert_B1.position[2]=tangentEndB1.position[2] ;
+ Vert_B1.normal[0]= -raytangent.position[0] ;
+ Vert_B1.normal[1]= -raytangent.position[1] ;
+ Vert_B1.normal[2]= -raytangent.position[2] ;
+ Vert_B1.texcoord[0][0]=flCentreX ;
+ Vert_B1.texcoord[0][1]=flCentreY ;
+ Vert_B1.texcoord[1][0]=flCentreZ ;
+ Vert_B1.texcoord[1][1]=flBrightness ;
+ Vert_B1.color[0]=flColR ;//abs(Vert_B1.normal[0])*255 ;//0.0f ;
+ Vert_B1.color[1]=flColG ;//abs(Vert_B1.normal[1])*255 ;//0.0f ;
+ Vert_B1.color[2]=flColB ;//abs(Vert_B1.normal[2])*255 ;//0.0f ;
+ if(!AddVertex(Vert_B1)) return 0 ;
+
+ /////////////////////////////////////////////////////////////////////
+
+
+
+
+ // the four verts are position correctly to make the large end of a cone (or rather, pyramid) that would be consistent
+ // with the angle and their distance from the origin. However we cheat and move them back on top of the origin
+ // so that map lights come out looking better.
+
+ /*
+ SetVertex(&normal, m_pLight[nLight].Direction[0]*flCutoff, m_pLight[nLight].Direction[1]*flCutoff, m_pLight[nLight].Direction[2]*flCutoff) ;
+
+ tangentEndA0=VectorSubtract(&tangentEndA0, &normal) ;
+ Vert_A0.position[0]=tangentEndA0.position[0] ;
+ Vert_A0.position[1]=tangentEndA0.position[1] ;
+ Vert_A0.position[2]=tangentEndA0.position[2] ;
+
+ tangentEndA1=VectorSubtract(&tangentEndA1, &normal) ;
+ Vert_A1.position[0]=tangentEndA1.position[0] ;
+ Vert_A1.position[1]=tangentEndA1.position[1] ;
+ Vert_A1.position[2]=tangentEndA1.position[2] ;
+
+ tangentEndB0=VectorSubtract(&tangentEndB0, &normal) ;
+ Vert_A0.position[0]=tangentEndB0.position[0] ;
+ Vert_A0.position[1]=tangentEndB0.position[1] ;
+ Vert_A0.position[2]=tangentEndB0.position[2] ;
+
+ tangentEndB1=VectorSubtract(&tangentEndB1, &normal) ;
+ Vert_A1.position[0]=tangentEndB1.position[0] ;
+ Vert_A1.position[1]=tangentEndB1.position[1] ;
+ Vert_A1.position[2]=tangentEndB1.position[2] ;
+ */
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ Triangle.Texture=m_nDefaultTextureIndexGlowLight ;
+ Triangle.Lamp=-1 ;
+ Triangle.Group=m_nGroup ;
+
+ /////////////////////////////////////
+
+ Triangle.VIndex[0]=n_Or ;
+ Triangle.VIndex[2]=n_A0 ;
+ Triangle.VIndex[1]=n_B1 ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_Or ;
+ Triangle.VIndex[2]=n_B1 ;
+ Triangle.VIndex[1]=n_A1 ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_Or ;
+ Triangle.VIndex[2]=n_A1 ;
+ Triangle.VIndex[1]=n_B0 ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ Triangle.VIndex[0]=n_Or ;
+ Triangle.VIndex[2]=n_B0 ;
+ Triangle.VIndex[1]=n_A0 ;
+ if(!AddTriangle(Triangle)) return 0 ;
+
+ m_nGroup++ ; // increment group once for each glow
+
+ }
+
+ return 1 ;
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// some vertex manipulation functions used for setting up the light disk.
+// They only work on the position, so other parts of the struct need to be setup seperately
+
+
+void Q3Map::SetVertex(Q3BspVertex *pVert, float flXPos, float flYPos, float flZPos)
+{
+ pVert->position[0]=flXPos ;
+ pVert->position[1]=flYPos ;
+ pVert->position[2]=flZPos ;
+}
+
+// this doesn't test exact equivalence, but rather within the range of an epsilon VERYSMALL
+bool Q3Map::VectorsAreEqual(Q3BspVertex* pVecA, Q3BspVertex* pVecB)
+{
+ if( fabs(pVecA->position[0] - pVecB->position[0])>VERYSMALL ) return false ;
+ if( fabs(pVecA->position[1] - pVecB->position[1])>VERYSMALL ) return false ;
+ if( fabs(pVecA->position[2] - pVecB->position[2])>VERYSMALL ) return false ;
+
+ return true ;
+}
+
+// VertA is the origin of VertB and VertC
+Q3BspVertex Q3Map::NormalizedCrossProduct(Q3BspVertex VertA, Q3BspVertex VertB, Q3BspVertex VertC)
+{
+
+
+ Q3BspVertex Cross ;
+
+ // edge vectors
+ float flVecXA_CP = VertA.position[0] - VertB.position[0] ;
+ float flVecYA_CP = VertA.position[1] - VertB.position[1] ;
+ float flVecZA_CP = VertA.position[2] - VertB.position[2] ;
+ float flVecXB_CP = VertA.position[0] - VertC.position[0] ;
+ float flVecYB_CP = VertA.position[1] - VertC.position[1] ;
+ float flVecZB_CP = VertA.position[2] - VertC.position[2] ;
+
+ // cross product
+ float flCpx_CP = (flVecZA_CP * flVecYB_CP) - (flVecYA_CP * flVecZB_CP);
+ float flCpy_CP = (flVecXA_CP * flVecZB_CP) - (flVecZA_CP * flVecXB_CP);
+ float flCpz_CP = (flVecYA_CP * flVecXB_CP) - (flVecXA_CP * flVecYB_CP);
+
+ // Normalize
+ float flR_CP = sqrt(flCpx_CP * flCpx_CP + flCpy_CP * flCpy_CP + flCpz_CP * flCpz_CP);
+
+ Cross.position[0] = flCpx_CP / flR_CP;
+ Cross.position[1] = flCpy_CP / flR_CP;
+ Cross.position[2] = flCpz_CP / flR_CP;
+
+ return Cross ;
+}
+
+float Q3Map::VertexDistance(Q3BspVertex* VertA, Q3BspVertex* VertB)
+{
+ float flXDis=VertA->position[0]-VertB->position[0] ;
+ float flYDis=VertA->position[1]-VertB->position[1] ;
+ float flZDis=VertA->position[2]-VertB->position[2] ;
+
+ return sqrt(flXDis*flXDis+flYDis*flYDis+flZDis*flZDis) ;
+}
+
+void Q3Map::VertexScale(Q3BspVertex* pVert, float flScale)
+{
+ pVert->position[0]*=flScale ;
+ pVert->position[1]*=flScale ;
+ pVert->position[2]*=flScale ;
+}
+
+Q3BspVertex Q3Map::GetNormalised(Q3BspVertex* pVector)
+{
+ float flLength=sqrt((pVector->position[0]*pVector->position[0])+(pVector->position[1]*pVector->position[1])+(pVector->position[2]*pVector->position[2])) ;
+
+ Q3BspVertex Vector=*pVector ;
+
+ Vector.position[0]/=flLength ;
+ Vector.position[1]/=flLength ;
+ Vector.position[2]/=flLength ;
+
+ return Vector ;
+}
+
+Q3BspVertex Q3Map::VectorAdd(Q3BspVertex* pVecA, Q3BspVertex* pVecB)
+{
+ Q3BspVertex Vector ;
+
+ Vector.position[0]=pVecA->position[0] + pVecB->position[0] ;
+ Vector.position[1]=pVecA->position[1] + pVecB->position[1] ;
+ Vector.position[2]=pVecA->position[2] + pVecB->position[2] ;
+
+ return Vector ;
+}
+
+Q3BspVertex Q3Map::VectorSubtract(Q3BspVertex* pVecA, Q3BspVertex* pVecB)
+{
+ Q3BspVertex Vector ;
+
+ Vector.position[0]=pVecA->position[0] - pVecB->position[0] ;
+ Vector.position[1]=pVecA->position[1] - pVecB->position[1] ;
+ Vector.position[2]=pVecA->position[2] - pVecB->position[2] ;
+
+ return Vector ;
+}
+
+Q3BspVertex Q3Map::VectorMultiply(Q3BspVertex* pVecA, Q3BspVertex* pVecB)
+{
+ Q3BspVertex Vector ;
+
+ Vector.position[0]=pVecA->position[0] * pVecB->position[0] ;
+ Vector.position[1]=pVecA->position[1] * pVecB->position[1] ;
+ Vector.position[2]=pVecA->position[2] * pVecB->position[2] ;
+
+ return Vector ;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+void Q3Map::GetTexLampTextureNumbers()
+{
+ m_nBZN_LightNode0=-1 ;
+ m_nBZN_LightNode1=-1 ;
+ m_nBZN_LightNode2=-1 ;
+ m_nBZN_LightNode3=-1 ;
+
+ int nTex=0;
+ char chTexName[1024] ;
+ int nLen=0 ;
+ int nPos=0 ;
+
+ int nMatch=0 ;
+
+ strcpy(chTexName, "textures/common/bzn_lightnode") ;
+ nLen=strlen(chTexName) ;
+
+ for(nTex=0 ; nTex<m_nTextureMax ; nTex++)
+ {
+ nMatch=1 ;
+ for(nPos=nLen-1 ; nPos>=0 ; nPos--) // faster to check backwards since lots of textures will start with "textures/common/"
+ if(m_pTexture[nTex].name[nPos]!=chTexName[nPos])
+ {
+ nMatch=0 ;
+ break ;
+ }
+
+ if(nMatch)
+ {
+ // what is the last character?
+ if(m_pTexture[nTex].name[nLen]=='0')
+ m_nBZN_LightNode0=nTex ;
+ else
+ if(m_pTexture[nTex].name[nLen]=='1')
+ m_nBZN_LightNode1=nTex ;
+ else
+ if(m_pTexture[nTex].name[nLen]=='2')
+ m_nBZN_LightNode2=nTex ;
+ else
+ if(m_pTexture[nTex].name[nLen]=='3')
+ m_nBZN_LightNode3=nTex ;
+
+ }// end if match
+
+
+ }// end for nTex
+
+}
+
+int Q3Map::SortTrianglesIntoGroups(void)
+{
+
+
+ int nNewSize=0 ; // we will drop non-subzoned (-1 zone) triangles here, so new number of triangles may be less than old number.
+
+ ULONGLONG *pFaceOrder = new ULONGLONG[m_nTriangleMax] ;
+ if(pFaceOrder==NULL) return 0 ; // out of memory.
+
+ // temporary copy of m_pTriangles to make sorting easier
+ triangle_t *TempTriangle = new triangle_t[m_nTriangleMax];
+ if(TempTriangle==NULL) { DELETE_ARRAY( pFaceOrder ) ; return 0 ; } // out of memory
+ memcpy((void*)TempTriangle, (void*)m_pTriangle, m_nTriangleMax*sizeof(triangle_t)) ;
+
+ // create the initial face "value" by setting the most significant bits to it's criteria number
+ for (int i=0; i < m_nTriangleMax; i++)
+ if(m_pTriangle[i].Zone!=-1) // drop unsubzoned triangles
+ pFaceOrder[nNewSize++] = ( ((ULONGLONG)m_pTriangle[i].Zone)<<GROUPSORT_SUBZONE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Texture)<<GROUPSORT_GROUP_SHIFT ) + i ;
+
+ // sort the ULONGLONGs, this will order things according to our criteria
+ // sorting is based firstly on subzone, secondly on texture.
+ // So all triangles in a subzone will be grouped together,
+ // and within that group all triangles with the same material will be grouped together.
+
+ qsort( (void *)pFaceOrder, nNewSize, sizeof(ULONGLONG), &Q3Map::compareGroups);
+
+ // copy the sorted faces back to the original
+ for (int i=0; i < nNewSize; i++)
+ m_pTriangle[i]=TempTriangle[ (pFaceOrder[i]&FACESORT_FACE_MASK) ] ;
+
+ // update m_nTriangleMax to show that there may now be less triangles
+ m_nTriangleMax=nNewSize ;
+
+ // clean up the memory we used
+ DELETE_ARRAY( pFaceOrder ) ;
+ DELETE_ARRAY( TempTriangle ) ;
+
+
+ // now that the triangles are sorting according to zone and group,
+ // re-assign the group numbers per zone, from 0 to FACESORT_GROUP_LIMIT-1
+ // All non-trans triangles will be group 0, trans triangles will be 1 to FACESORT_GROUP_LIMIT-1
+
+ int nTri=0 ;
+ int nZone=-1 ;
+ int nGroup=-1 ;
+ int nNewGroup=0 ;
+
+ //char chMessage[1024] ;
+
+ for(nTri=0 ; nTri<m_nTriangleMax ; nTri++)
+ {
+ // reset the newgroup if we've got a new zone
+ if(m_pTriangle[nTri].Zone!=nZone)
+ {
+ nZone=m_pTriangle[nTri].Zone ;
+ nGroup=-1 ;
+ nNewGroup=0 ;
+ }
+
+ // if we have a new group, increment the newgroup number, fail if we have too many
+ if(m_pTriangle[nTri].Group!=nGroup)
+ {
+ // if this is a trans triangle, inc the newgroup
+ if(m_pTransTexture[ m_pTriangle[nTri].Texture ])
+ {
+ nNewGroup++ ; // will always be at least 1
+ if(nNewGroup>=FACESORT_GROUP_LIMIT) return 0 ; // too many groups in a zone.
+ }
+
+ nGroup=m_pTriangle[nTri].Group ;
+ }
+
+ if(m_pTransTexture[ m_pTriangle[nTri].Texture ]==0)
+ m_pTriangle[nTri].Group=0 ;
+ else
+ m_pTriangle[nTri].Group=nNewGroup ;
+
+
+
+ }// end for tri
+
+ return 1 ;
+}
+
+
+// static function for sorting groups, required by qsort
+int Q3Map::compareGroups( const void *arg1, const void *arg2 )
+{
+ ULONGLONG FaceA= *(ULONGLONG*)arg1 ;
+ ULONGLONG FaceB= *(ULONGLONG*)arg2 ;
+
+ if(FaceA < FaceB)
+ return -1 ;
+ else
+ if(FaceA > FaceB)
+ return 1 ;
+
+ return 0 ;
+}
+
+
+
+// sort faces so that we can batch effectively when constructing our manualobjects
+// Currently grouped according to zone and texture.
+// Triangles not in any subzone will be dropped at this stage.
+int Q3Map::SortTrianglesIntoBatches(void)
+{
+
+
+ int nNewSize=0 ; // we will drop non-subzoned (-1 zone) triangles here, so new number of triangles may be less than old number.
+
+ ULONGLONG *pFaceOrder = new ULONGLONG[m_nTriangleMax] ;
+ if(pFaceOrder==NULL) return 0 ; // out of memory.
+
+ // temporary copy of m_pTriangles to make sorting easier
+ triangle_t *TempTriangle = new triangle_t[m_nTriangleMax];
+ if(TempTriangle==NULL) { DELETE_ARRAY( pFaceOrder ) ; return 0 ; } // out of memory
+ memcpy((void*)TempTriangle, (void*)m_pTriangle, m_nTriangleMax*sizeof(triangle_t)) ;
+
+ // create the initial face "value" by setting the most significant bits to it's criteria number
+ for (int i=0; i < m_nTriangleMax; i++)
+ if(m_pTriangle[i].Zone!=-1) // drop unsubzoned triangles
+ pFaceOrder[nNewSize++] = ( ((ULONGLONG)m_pTriangle[i].Zone)<<FACESORT_SUBZONE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Texture)<<FACESORT_TEXTURE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Group)<<FACESORT_GROUP_SHIFT ) + i ;
+
+ // sort the ULONGLONGs, this will order things according to our criteria
+ // sorting is based firstly on subzone, secondly on texture.
+ // So all triangles in a subzone will be grouped together,
+ // and within that group all triangles with the same material will be grouped together.
+
+ qsort( (void *)pFaceOrder, nNewSize, sizeof(ULONGLONG), &Q3Map::compareTriangles);
+
+ // copy the sorted faces back to the original
+ for (int i=0; i < nNewSize; i++)
+ m_pTriangle[i]=TempTriangle[ (pFaceOrder[i]&FACESORT_FACE_MASK) ] ;
+
+ // update m_nTriangleMax to show that there may now be less triangles
+ m_nTriangleMax=nNewSize ;
+
+ // clean up the memory we used
+ DELETE_ARRAY( pFaceOrder ) ;
+ DELETE_ARRAY( TempTriangle ) ;
+
+ return 1 ;
+}
+
+// static function for sorting triangles, required by qsort
+int Q3Map::compareTriangles( const void *arg1, const void *arg2 )
+{
+ ULONGLONG FaceA= *(ULONGLONG*)arg1 ;
+ ULONGLONG FaceB= *(ULONGLONG*)arg2 ;
+
+ if(FaceA < FaceB)
+ return -1 ;
+ else
+ if(FaceA > FaceB)
+ return 1 ;
+
+ return 0 ;
+}
+
+
+
+
+// note which texture numbers correspond to textures that have transparency.
+// needed for when we work out transparency groups and related stuff
+int Q3Map::SetupTransTextures(void)
+{
+ int nMaterial=0 ;
+ int nPos=0 ;
+ char chMaterial[1024] ;
+
+ // create the memory for the transtextures
+ m_pTransTexture = new int[m_nTextureMax] ;
+ if(m_pTransTexture==NULL) return 0 ; // out of memory.
+
+ for(nMaterial=0 ; nMaterial<m_nTextureMax ; nMaterial++)
+ {
+ // copy the material name.
+ // q3 texture names are a max of 64 characters ( Q3NAMESIZE ) and may not be null terminated. They have no extension either.
+ nPos=-1 ;
+ while((++nPos<Q3NAMESIZE) && (m_pTexture[nMaterial].name[nPos]!=' ') && (m_pTexture[nMaterial].name[nPos]!='\0'))
+ chMaterial[nPos]=m_pTexture[nMaterial].name[nPos] ;
+
+ // make sure name is null terminated
+ chMaterial[nPos]='\0' ;
+
+
+ // is the texture a type we need to flag as transparent?
+ if(strstr(chMaterial, "GEL")!=NULL)
+ m_pTransTexture[nMaterial]=1 ;
+ else
+ m_pTransTexture[nMaterial]=0 ;
+
+ }// end for nMaterial
+
+ return 1 ;
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int Q3Map::AssignPortalsToZones(void)
+{
+ int nZone=0 ;
+ float flMinX=0.0f ;
+ float flMaxX=0.0f ;
+ float flMinY=0.0f ;
+ float flMaxY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxZ=0.0f ;
+ int nMaxSubZone=m_iNumSubZones ;
+ int nSubZone=0 ;
+ int nMaxPortal=m_iNumPortals ;
+ int nPortal=0 ;
+ int nIndex=0 ;
+ int nPos=0 ;
+
+
+
+ // clear the portal settings.
+ for(nZone=0 ; nZone<m_nMaxZone ; nZone++)
+ m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT]=0 ;
+
+ for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++)
+ m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT]=0 ;
+
+
+
+ // now test each subzone against each portal to see what zones each portal contains.
+ for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+ {
+ nZone=m_pSubZones[nSubZone].Zone ;
+ flMinX=m_pSubZones[nSubZone].Min[0] ;
+ flMaxX=m_pSubZones[nSubZone].Max[0] ;
+ flMinY=m_pSubZones[nSubZone].Min[1] ;
+ flMaxY=m_pSubZones[nSubZone].Max[1] ;
+ flMinZ=m_pSubZones[nSubZone].Min[2] ;
+ flMaxZ=m_pSubZones[nSubZone].Max[2] ;
+
+ // test all the portals to see if any overlap this subzone
+ for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++)
+ {
+
+ // if AABB overlap
+ if(
+ (flMinX<m_pPortals[nPortal].Max[0]) && (flMaxX>m_pPortals[nPortal].Min[0])
+ && (flMinY<m_pPortals[nPortal].Max[1]) && (flMaxY>m_pPortals[nPortal].Min[1])
+ && (flMinZ<m_pPortals[nPortal].Max[2]) && (flMaxZ>m_pPortals[nPortal].Min[2])
+ )
+ {
+
+ // add this portal to the zone's portal list
+ nIndex=m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT] ;
+ if(nIndex<MAX_PORTALPERZONE) // only add if we aren't already maxed out.
+ {
+ // we need to check this portal isn't already on the list.
+ // it might have gotten on by another subzone, since a zone can have multiple subzones.
+ nPos=-1 ;
+ while((++nPos<nIndex) && (m_nZoneTouchesPortal[nZone][nPos]!=nPortal)) ;
+
+ if(nPos==nIndex) // this can only be true if we didn't already find nPortal in the list
+ {
+ m_nZoneTouchesPortal[nZone][nIndex]=nPortal ;
+ m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT]++ ;
+ }
+ }
+
+ // add this zone to the portal's list
+ nIndex=m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ;
+ if(nIndex<MAX_ZONEPERPORTAL)
+ {
+ // we need to check this zone isn't already on the list.
+ // it might have gotten on by another subzone, since a zone can have multiple subzones.
+ nPos=-1 ;
+ while((++nPos<nIndex) && (m_nPortalTouchesZone[nPortal][nPos]!=nZone)) ;
+
+ if(nPos==nIndex) // this can only be true if we didn't already find nZone in the list
+ {
+ m_nPortalTouchesZone[nPortal][nIndex]=nZone ;
+ m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT]++ ;
+ }
+ }
+
+ }// end if portal overlaps subzone
+
+ }// end for portal
+
+ }// end for subzone
+
+ return 1 ;
+}
+
+int Q3Map::AssignLightsToZones(void)
+{
+ int nZone=0 ;
+ float flMinX=0.0f ;
+ float flMaxX=0.0f ;
+ float flMinY=0.0f ;
+ float flMaxY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxZ=0.0f ;
+ int nMaxSubZone=m_iNumSubZones ;
+ int nSubZone=0 ;
+ int nMaxLight=m_nLightMax ;
+ int nLight=0 ;
+ int nIndex=0 ;
+ int nPos=0 ;
+
+
+
+ // clear the light settings.
+ for(nZone=0 ; nZone<m_nMaxZone ; nZone++)
+ m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT]=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]=0 ;
+
+ for(nLight=0 ; nLight<nMaxLight ; nLight++)
+ m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]=0 ;
+
+
+
+
+ // now test each subzone against each light what contains/touches what
+ for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+ {
+ nZone=m_pSubZones[nSubZone].Zone ;
+ flMinX=m_pSubZones[nSubZone].Min[0] ;
+ flMaxX=m_pSubZones[nSubZone].Max[0] ;
+ flMinY=m_pSubZones[nSubZone].Min[1] ;
+ flMaxY=m_pSubZones[nSubZone].Max[1] ;
+ flMinZ=m_pSubZones[nSubZone].Min[2] ;
+ flMaxZ=m_pSubZones[nSubZone].Max[2] ;
+
+ // test all the lights to see if any have centers inside this subzone
+ for(nLight=0 ; nLight<nMaxLight ; nLight++)
+ {
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ // if light center is in this subzone
+ if(
+ (m_pLight[nLight].Position[0]>=flMinX) && (m_pLight[nLight].Position[0]<=flMaxX)
+ && (m_pLight[nLight].Position[1]>=flMinY) && (m_pLight[nLight].Position[1]<=flMaxY)
+ && (m_pLight[nLight].Position[2]>=flMinZ) && (m_pLight[nLight].Position[2]<=flMaxZ)
+ )
+ {
+
+ // add this light to the zone's light list
+ nIndex=m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT] ;
+ if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out.
+ {
+ // we need to check this light isn't already on the list.
+ // it might have gotten on by another subzone, since a zone can have multiple subzones.
+ nPos=-1 ;
+ while((++nPos<nIndex) && (m_nZoneContainsLightCentre[nZone][nPos]!=nLight)) ;
+
+ if(nPos==nIndex) // this can only be true if we didn't already find nLight in the list
+ {
+ m_nZoneContainsLightCentre[nZone][nIndex]=nLight ;
+ m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT]++ ;
+
+ // assign this zone as the light's centre. We only allow one zone to be the light's centre zone,
+ // so this will get overwritten if the light is on the border.
+ m_pLight[nLight].CentreZone=nZone ;
+ }
+ }
+
+ }// end if light centre contained by subzone
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ // if light touches subzone (we store it in ZoneTouchesSubLight for now, will overwrite later)
+ // if light AABB overlaps the zone AABB
+ if(
+ (flMinX<m_pLight[nLight].Max[0]) && (flMaxX>m_pLight[nLight].Min[0])
+ && (flMinY<m_pLight[nLight].Max[1]) && (flMaxY>m_pLight[nLight].Min[1])
+ && (flMinZ<m_pLight[nLight].Max[2]) && (flMaxZ>m_pLight[nLight].Min[2])
+ )
+ {
+ // add this light to the zone's light list
+ nIndex=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ;
+ if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out.
+ {
+ // we need to check this light isn't already on the list.
+ // it might have gotten on by another subzone, since a zone can have multiple subzones.
+ nPos=-1 ;
+ while((++nPos<nIndex) && (m_nZoneTouchesSubLight[nZone][nPos]!=nLight)) ;
+
+ if(nPos==nIndex) // this can only be true if we didn't already find nPortal in the list
+ {
+ m_nZoneTouchesSubLight[nZone][nIndex]=nLight ;
+ m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]++ ;
+ }
+ }
+
+ // add this zone to the light's list
+ nIndex=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
+ if(nIndex<MAX_ZONEPERLIGHT)
+ {
+ // we need to check this zone isn't already on the list.
+ // it might have gotten on by another subzone, since a zone can have multiple subzones.
+ nPos=-1 ;
+ while((++nPos<nIndex) && (m_nLightTouchesZone[nLight][nPos]!=nZone)) ;
+
+ if(nPos==nIndex) // this can only be true if we didn't already find nZone in the list
+ {
+ m_nLightTouchesZone[nLight][nIndex]=nZone ;
+ m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]++ ;
+ }
+ }
+
+ }// end if light touches contained by subzone
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ }// end for light
+
+ }// end for subzone
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // work out the sublights. These are cut up boxes made from the light boxes, one per zone.
+ // Most lights will just become a single sublight, but multizone lights will be cut up into
+ // multiple sublights. These are used for calculating light visibility.
+ //
+
+ m_nSubLightMax=0 ;
+ int nMaxZone=0 ;
+ int nZoneIndex=0 ;
+ int nSubLightCentre=0 ;
+ sublight_t TempSubLight ;
+ for(nLight=0 ; nLight<nMaxLight ; nLight++)
+ {
+
+ m_pLight[nLight].ZoneCount=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ; // in the light, note how many zones it touches
+
+ if((m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]>1) && (m_nMaxMultiZoneLight<MAX_LIGHT))// this is a multizone light
+ m_nMultiZoneLight[m_nMaxMultiZoneLight++]=nLight ;
+
+
+ m_pLight[nLight].SubLightStart=m_nSubLightMax ; // where this light's cut up sublights start in m_SubLight
+
+
+ // break the light up into it's different sublights, cut by zones.
+ nMaxZone=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
+ for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++)
+ {
+ nZone=m_nLightTouchesZone[nLight][nZoneIndex] ;
+
+ flMinX= m_pLight[nLight].Min[0]<m_ZoneBoundary[nZone].Min[0] ? m_ZoneBoundary[nZone].Min[0] : m_pLight[nLight].Min[0] ;
+ flMinY= m_pLight[nLight].Min[1]<m_ZoneBoundary[nZone].Min[1] ? m_ZoneBoundary[nZone].Min[1] : m_pLight[nLight].Min[1] ;
+ flMinZ= m_pLight[nLight].Min[2]<m_ZoneBoundary[nZone].Min[2] ? m_ZoneBoundary[nZone].Min[2] : m_pLight[nLight].Min[2] ;
+
+ flMaxX= m_pLight[nLight].Max[0]>m_ZoneBoundary[nZone].Max[0] ? m_ZoneBoundary[nZone].Max[0] : m_pLight[nLight].Max[0] ;
+ flMaxY= m_pLight[nLight].Max[1]>m_ZoneBoundary[nZone].Max[1] ? m_ZoneBoundary[nZone].Max[1] : m_pLight[nLight].Max[1] ;
+ flMaxZ= m_pLight[nLight].Max[2]>m_ZoneBoundary[nZone].Max[2] ? m_ZoneBoundary[nZone].Max[2] : m_pLight[nLight].Max[2] ;
+
+ // add the cut down light as a sublight
+ m_SubLight[m_nSubLightMax].Light=nLight ;
+ m_SubLight[m_nSubLightMax].Zone=nZone ;
+ m_SubLight[m_nSubLightMax].Min[0]=flMinX ;
+ m_SubLight[m_nSubLightMax].Min[1]=flMinY ;
+ m_SubLight[m_nSubLightMax].Min[2]=flMinZ ;
+ m_SubLight[m_nSubLightMax].Max[0]=flMaxX ;
+ m_SubLight[m_nSubLightMax].Max[1]=flMaxY ;
+ m_SubLight[m_nSubLightMax].Max[2]=flMaxZ ;
+
+ // remember which sublight is the centre
+ if(
+ (m_pLight[nLight].Position[0]>=flMinX) && (m_pLight[nLight].Position[0]<=flMaxX)
+ && (m_pLight[nLight].Position[1]>=flMinY) && (m_pLight[nLight].Position[1]<=flMaxY)
+ && (m_pLight[nLight].Position[2]>=flMinZ) && (m_pLight[nLight].Position[2]<=flMaxZ)
+ )
+ nSubLightCentre=m_nSubLightMax ;
+
+
+ m_nSubLightMax++ ; // we don't have to worry about bound checking this, because we've already checked there aren't too many lights.
+
+ }// end for zoneindex
+
+ // move the sublight that contains the centre to the beginning of the sublights for this light.
+ // We always want the first sublight to contain the centre to make the culling algos work better.
+ TempSubLight=m_SubLight[ m_pLight[nLight].SubLightStart ] ;
+ m_SubLight[ m_pLight[nLight].SubLightStart ] = m_SubLight[ nSubLightCentre ] ;
+ m_SubLight[ nSubLightCentre ] = TempSubLight ;
+
+
+
+ }// end for light
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // recalculate m_nZoneTouchesSubLight using the newly created sublights
+ // (instead of the complete lights that were originally used)
+ //
+
+ int nSubLight=0 ;
+
+
+ // clear the light settings.
+ for(nZone=0 ; nZone<m_nMaxZone ; nZone++)
+ m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]=0 ;
+
+ for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+ {
+ nZone=m_pSubZones[nSubZone].Zone ;
+ flMinX=m_pSubZones[nSubZone].Min[0] ;
+ flMaxX=m_pSubZones[nSubZone].Max[0] ;
+ flMinY=m_pSubZones[nSubZone].Min[1] ;
+ flMaxY=m_pSubZones[nSubZone].Max[1] ;
+ flMinZ=m_pSubZones[nSubZone].Min[2] ;
+ flMaxZ=m_pSubZones[nSubZone].Max[2] ;
+
+ // test all the lights to see if any have centers inside this subzone
+ for(nSubLight=0 ; nSubLight<m_nSubLightMax ; nSubLight++)
+ {
+ // if light touches subzone (we store it in ZoneTouchesSubLight for now, will overwrite later)
+ // if light AABB overlaps the zone AABB
+ if(
+ (flMinX<m_SubLight[nSubLight].Max[0]) && (flMaxX>m_SubLight[nSubLight].Min[0])
+ && (flMinY<m_SubLight[nSubLight].Max[1]) && (flMaxY>m_SubLight[nSubLight].Min[1])
+ && (flMinZ<m_SubLight[nSubLight].Max[2]) && (flMaxZ>m_SubLight[nSubLight].Min[2])
+ )
+ {
+ // add this light to the zone's light list
+ nIndex=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ;
+ if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out.
+ {
+ // we need to check this light isn't already on the list.
+ // it might have gotten on by another subzone, since a zone can have multiple subzones.
+ nPos=-1 ;
+ while((++nPos<nIndex) && (m_nZoneTouchesSubLight[nZone][nPos]!=nSubLight)) ;
+
+ if(nPos==nIndex) // this can only be true if we didn't already find nSubLight in the list
+ {
+ m_nZoneTouchesSubLight[nZone][nIndex]=nSubLight ;
+ m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]++ ;
+ }
+
+ }
+
+ }// end if overlap
+
+ }// end for nSubLight
+
+ }// end for nSubZone
+
+
+
+
+
+ return 1 ;
+}
+
+
+int Q3Map::AssignLightsToPortals(void)
+{
+ float flMinX=0.0f ;
+ float flMaxX=0.0f ;
+ float flMinY=0.0f ;
+ float flMaxY=0.0f ;
+ float flMinZ=0.0f ;
+ float flMaxZ=0.0f ;
+ int nMaxPortal=m_iNumPortals ;
+ int nPortal=0 ;
+ int nMaxLight=m_nLightMax ;
+ int nLight=0 ;
+ int nIndex=0 ;
+ int nPos=0 ;
+
+
+
+ // clear the light settings.
+ for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++)
+ m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT]=0 ;
+
+ // now test each portal against each light to see if they touch
+ for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++)
+ {
+ flMinX=m_pPortals[nPortal].Min[0] ;
+ flMaxX=m_pPortals[nPortal].Max[0] ;
+ flMinY=m_pPortals[nPortal].Min[1] ;
+ flMaxY=m_pPortals[nPortal].Max[1] ;
+ flMinZ=m_pPortals[nPortal].Min[2] ;
+ flMaxZ=m_pPortals[nPortal].Max[2] ;
+
+ // test all the lights to see if any touch this portal
+ for(nLight=0 ; nLight<nMaxLight ; nLight++)
+ {
+
+ // if light AABB overlaps the portal AABB
+ if(
+ (flMinX<m_pLight[nLight].Max[0]) && (flMaxX>m_pLight[nLight].Min[0])
+ && (flMinY<m_pLight[nLight].Max[1]) && (flMaxY>m_pLight[nLight].Min[1])
+ && (flMinZ<m_pLight[nLight].Max[2]) && (flMaxZ>m_pLight[nLight].Min[2])
+ )
+ {
+
+ // add this light to the portal's light list
+ nIndex=m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT] ;
+ if(nIndex<MAX_LIGHTPERPORTAL) // only add if we aren't already maxed out.
+ {
+ // we need to check this light isn't already on the list.
+ // it might have gotten on by another subzone, since a zone can have multiple subzones.
+ nPos=-1 ;
+ while((++nPos<nIndex) && (m_nPortalTouchesLight[nPortal][nPos]!=nLight)) ;
+
+ if(nPos==nIndex) // this can only be true if we didn't already find nLight in the list
+ {
+ m_nPortalTouchesLight[nPortal][nIndex]=nLight ;
+ m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT]++ ;
+ }
+ }
+
+ // we don't keep a list of the portals that a light touches, we don't use such a thing.
+
+ }// end if light touches portal
+
+ }// end for light
+
+ }// end for portal
+
+ return 1 ;
+}
+
+// work out all the other zones each zone touches, via portals
+int Q3Map::AssignZonesToZones(void)
+{
+
+
+ int nCentralZone=0 ;
+ int nPortalZone=0 ;
+ int nMaxPortalZone=0 ;
+ int nPortalZoneIndex=0 ;
+ int nPortal=0 ;
+ int nPortalIndex=0 ;
+ int nMaxPortal=0 ;
+
+ int nTouchZoneIndex=0 ;
+ int nMaxTouchZone=0 ;
+ int nAddZone=0 ;
+
+
+ // scan through all the zones (consider them "central zones")
+ for(nCentralZone=0 ; nCentralZone<m_nMaxZone ; nCentralZone++)
+ {
+ nMaxTouchZone=0 ;
+
+ // scan through all the portals in this centralzone.
+ nMaxPortal=m_nZoneTouchesPortal[nCentralZone][INDEX_PORTALCOUNT] ;
+ for(nPortalIndex=0 ; nPortalIndex<nMaxPortal; nPortalIndex++)
+ {
+ nPortal=m_nZoneTouchesPortal[nCentralZone][nPortalIndex] ;
+
+ // scan through all the zones this portal touches and add then to the central zone's list
+ nMaxPortalZone=m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ;
+ for(nPortalZoneIndex=0 ; nPortalZoneIndex<nMaxPortalZone ; nPortalZoneIndex++)
+ {
+ nPortalZone=m_nPortalTouchesZone[nPortal][nPortalZoneIndex] ;
+
+ // we've got a portal zone.
+ if(nPortalZone==nCentralZone) continue ; // if it's the central zone, skip it.
+
+ // check we don't already have it listed.
+ nAddZone=1 ;
+ for(nTouchZoneIndex=0 ; nTouchZoneIndex<nMaxTouchZone ; nTouchZoneIndex++)
+ {
+ if(m_nZoneTouchesPortal[nCentralZone][nTouchZoneIndex]==nPortalZone)
+ {
+ nAddZone=0 ;
+ break ;
+ }// end if
+ }// end for nTouchZoneIndex
+
+ if(nAddZone)
+ {
+ m_nZoneTouchesZone[nCentralZone][nMaxTouchZone]=nPortalZone ;
+ nMaxTouchZone++ ;
+ if(nMaxTouchZone>=MAX_ZONEPERZONE)
+ nMaxTouchZone=MAX_ZONEPERZONE-1 ;
+
+
+ }
+
+
+ }// end for portal zone index
+
+
+ }// end for portal index
+
+ // set the maximum
+ m_nZoneTouchesZone[nCentralZone][INDEX_ZONEPERZONECOUNT]=nMaxTouchZone ;
+
+ /*
+ sprintf(m_chBug, "CentralZone %i, TouchedZoneCount %i", nCentralZone, m_nZoneTouchesPortal[nCentralZone][INDEX_ZONEPERZONECOUNT]) ;
+ Q3Bug.LogAddCR(m_chBug) ;
+ for(nTouchZoneIndex=0 ; nTouchZoneIndex<m_nZoneTouchesZone[nCentralZone][INDEX_ZONEPERZONECOUNT] ; nTouchZoneIndex++)
+ {
+ sprintf(m_chBug, " TouchedZone %i", m_nZoneTouchesZone[nCentralZone][nTouchZoneIndex]) ;
+ Q3Bug.LogAddCR(m_chBug) ;
+ }
+ */
+
+
+ }// end for central zone
+
+
+
+
+ return 1 ;
+}
+
+
+
Property changes on: code/branches/fps/src/libraries/tools/fps/Q3Map.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/Q3Map.h
===================================================================
--- code/branches/fps/src/libraries/tools/fps/Q3Map.h (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/Q3Map.h 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,709 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+Copyright (C) 2009 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// Q3Map.h -- handles the map data
+
+#ifndef _Q3MAP_H
+#define _Q3MAP_H
+
+#define WIN32_LEAN_AND_MEAN
+#include "windows.h"
+
+#include "Q3Map_Bezier.h"
+
+#include <string>
+#include <vector>
+
+#include "Q3Map_misc.h"
+
+#include "JarDebug.h" //!! just for debugging, remove from final build
+
+#define MEMADD 65536 // memory is grown in 66k blocks
+#define MAX_TOKENSIZE 1024 // make sure tokens in texts aren't ridiculously large
+
+
+
+#define MINMAXLIMIT 10000000.0
+
+#define BRIGHTNESSTWEAK 0.5f //1.25f // tweak for spotlight brightness
+
+#define ADDTEXTUREUNIQUE_FAIL -1
+#define ADDTEXLAMP_FAIL -2
+
+#define ADDSPOTLIGHTTEXTURE_FAIL -1
+
+////////////////////////////////////////////////////
+
+#define AXIS_X 0
+#define AXIS_Y 1
+#define AXIS_Z 2
+
+////////////////////////////////////////////////////
+/*
+#define FACESORT_FACE_LIMIT 16777216
+#define FACESORT_FACE_SHIFT 0
+#define FACESORT_FACE_MASK 0x0000000000FFFFFF
+#define FACESORT_TEXTURE_LIMIT 4096
+#define FACESORT_TEXTURE_SHIFT 24
+#define FACESORT_TEXTURE_MASK 0x0000000FFF000000
+#define FACESORT_SUBZONE_LIMIT 4096 // also see MAX_ZONE
+#define FACESORT_SUBZONE_SHIFT 36
+#define FACESORT_SUBZONE_MASK 0x0000FFF000000000
+*/
+
+#define FACESORT_FACE_LIMIT 16777216
+#define FACESORT_FACE_SHIFT 0
+#define FACESORT_FACE_MASK 0x0000000000FFFFFF
+#define FACESORT_GROUP_LIMIT 65536 // also see MAX_TRANS
+#define FACESORT_GROUP_SHIFT 24
+#define FACESORT_GROUP_MASK 0x000000FFFF000000
+#define FACESORT_TEXTURE_LIMIT 4096
+#define FACESORT_TEXTURE_SHIFT 40
+#define FACESORT_TEXTURE_MASK 0x000FFF0000000000
+#define FACESORT_SUBZONE_LIMIT 4096 // also see MAX_ZONE
+#define FACESORT_SUBZONE_SHIFT 52
+#define FACESORT_SUBZONE_MASK 0xFFF0000000000000
+
+#define GROUPSORT_FACE_LIMIT 16777216
+#define GROUPSORT_FACE_SHIFT 0
+#define GROUPSORT_FACE_MASK 0x0000000000FFFFFF
+#define GROUPSORT_GROUP_LIMIT 16777216
+#define GROUPSORT_GROUP_SHIFT 24
+#define GROUPSORT_GROUP_MASK 0x0000FFFFFF000000
+#define GROUPSORT_SUBZONE_LIMIT 4096 // also see MAX_ZONE
+#define GROUPSORT_SUBZONE_SHIFT 52
+#define GROUPSORT_SUBZONE_MASK 0xFFF0000000000000
+
+
+
+////////////////////////////////////////////////////
+
+#define MAX_ZONE 4096 // max subzones and max zones. Also see FACESORT_SUBZONE_LIMIT
+#define MAX_SUBZONEPERZONE 16 // the most subzones that can make up a zone, further subzones ignored. INDEX_SUBZONECOUNT must be same as this
+#define INDEX_SUBZONECOUNT 16 // helps subzone counting in m_nZone. See MAX_SUBZONEPERZONE
+
+#define MAX_PORTAL 32768 // max subzoneportals in a map.
+#define MAX_PORTALPERZONE 64 // the most portals that a zone can have, further portals ignored. INDEX_PORTALCOUNT must be same as this
+#define MAX_ZONEPERPORTAL 8 // the most zones a portal can connect, further zones ignored. INDEX_PORTALZONECOUNT must be the same as this
+#define MAX_LIGHTPERPORTAL 16 // the most lights that can touch a portal, further lights ignored. INDEX_PORTALLIGHTCOUNT must be the same as this
+#define INDEX_PORTALCOUNT 64 // helps portal counting in m_nZoneTouchesPortal. See MAX_PORTALSPERZONE
+#define INDEX_PORTALZONECOUNT 8 // helps portalconnect counting in m_nPortalTouchesZone. See MAX_ZONEPERPORTAL
+#define INDEX_PORTALLIGHTCOUNT 16 // helps portallight counting in m_PortalConnectsLight. See MAX_LIGHTPERPORTAL
+
+#define MAX_ZONEPERZONE 64 // the most zones that a zone can connect to.
+#define INDEX_ZONEPERZONECOUNT 64 // helps zone per zone counting.
+
+#define MAX_LIGHT 32768 // max lights in a map, both from the map and other things (flashlight, missiles, etc)
+#define MAX_LIGHTPERZONE 64 // the most lights that a zone can have, further lights ignored. INDEX_LIGHTCOUNT must be same as this
+#define MAX_ZONEPERLIGHT 8 // the most zones a light can touch, further zones ignored. INDEX_LIGHTZONECOUNT must be the same as this
+#define INDEX_LIGHTCOUNT 64 // helps light counting in m_nZoneContainsLight. see MAX_LIGHTPERZONE
+#define INDEX_LIGHTZONECOUNT 8 // helps light counting in m_nLightContainedByZone. See MAX_ZONEPERLIGHT
+
+#define MAX_SUBLIGHT 262144 // must be MAX_LIGHT * MAX_ZONEPERLIGHT
+#define MAX_TRANS 65536 // most transparent objects per zone (objects may be defined in various ways). see FACESORT_TRANS_LIMIT
+
+
+
+////////////////////////////////////////////////////
+
+#define SUBZONE_EPSILON 0.01f // small buffer of extra size around subzones so that we don't accidentally exclude a point due to float accuracy errors.
+#define FRUSTUM_EPSILON 0.0001f // once frustum is this tiny consider it dead
+#define VERYSMALL 0.00001 // small number
+
+#define PORTAL_UNCHECKED 0
+#define PORTAL_VISCHECK 1
+#define PORTAL_VISIBLE 2
+
+#define PORTALSTATE_OPENCHECK 0
+#define PORTALSTATE_CLOSED 1
+#define PORTALSTATE_OPEN 2
+
+#define ZONE_UNCHECKED 0
+#define ZONE_VISIBLE 1
+
+#define LIGHT_UNCHECKED 0
+#define LIGHT_OUTOFFRUSTUM 1
+#define LIGHT_INSIDEFRUSTUM 2
+#define LIGHT_NOTVISIBLE 4
+#define LIGHT_VISIBLE 8
+#define LIGHT_CHECKED 16
+
+///////////////////////////////////////////////////
+
+#define MAX_PROJECTORTEX 16 // most types of projector textures we can have per map.
+
+
+///////////////////////////////////////////////////
+
+// NOERROR is already defined in a windows file, it is 0
+#define ERROR_ParseMap 1
+#define ERROR_ParseEntities 2
+#define ERROR_AllocateVertex 3
+#define ERROR_AllocateTriangle 4
+#define ERROR_InitializeFaces 5
+#define ERROR_ConvertFaces 6
+#define ERROR_ConvertPatches 7
+#define ERROR_ConvertLamps 8
+#define ERROR_ConvertLampGlow 9
+#define ERROR_ConvertLightGlow 10
+#define ERROR_AssignTriangles 11
+#define ERROR_SortTriangles 12
+#define ERROR_ConvertTexLamp 13
+#define ERROR_SetupTransTextures 14
+#define ERROR_SortGroups 15
+
+
+///////////////////////////////////////////////////
+// error values for parsing key/values
+#define KEY_OK 0
+#define KEY_NONE 1
+#define KEY_ERROR 2
+
+//////////////////////////////////////////////////
+// entity types
+#define ENTITY_ERROR 0
+#define ENTITY_UNKNOWN 1
+#define ENTITY_WORLDSPAWN 2
+#define ENTITY_LIGHT 3
+
+///////////////////////////////////////////////////
+
+
+
+// The lump idexes that make up a bsp file.
+// Bzn bsp lump data is almost identical to q3a bsp lump data, except that the
+// Effects, Lightmaps and VisData lumps are removed and there are two new lumps, one
+// describing the subzones and one describing the portals. The other difference is the lighting
+// entities (which are stored as normal entities in lump 0) since q3a bsps don't usually
+// store the light entities at all, and BZN has it's own unique set of lighting keys.
+
+const int Textures = 1;
+const int Planes = 2;
+const int Nodes = 3;
+const int Leafs = 4;
+const int LeafFaces = 5;
+const int LeafBrushes = 6;
+const int Brushes = 8;
+const int BrushSides = 9;
+const int Vertices = 10;
+const int MeshVerts = 11;
+const int Effects = 12; // removed from bzn
+const int Faces = 13;
+const int LightMaps = 14; // removed from bzn
+const int VisData = 16; // removed from bzn
+const int SubZoneData = 17 ; // added to bzn: overlapping subzones form zones. Zones are like groups of axial boxes.
+const int PortalData = 18 ; // added to bzn: portals overlapping different zones allow them to see each other.
+const int MAX_LUMP = 19 ;
+
+const int MAX_LUMP_SIZE = 100000000 ; // this value is very large and arbitrary, 100 megabytes. Just make sure MAX_LUMP_SIZE * MAX_LUMP is less than the max size for a size_t or parseMap error checking won't work.
+
+enum {POLYGON = 1, PATCH, MESH, BILLBOARD};
+
+typedef struct{
+ int iOffset;
+ int iLength;
+} direntry_t;
+
+#define Q3NAMESIZE 64
+typedef struct {
+ char name[Q3NAMESIZE];
+ int flags;
+ int contents;
+} Q3BspTexture;
+
+typedef struct{
+ unsigned char magic[4];
+ int version;
+ direntry_t Lumps[MAX_LUMP];
+} Q3BspHeader_t;
+
+typedef struct{
+ int texture;
+ int effect;
+ int type;
+ int vertex;
+ int n_vertexes;
+ int meshvert;
+ int n_meshverts;
+ int lm_index;
+ int lm_start[2];
+ int lm_size[2];
+ float lm_origin[3];
+ float lm_vecs[2][3];
+ float normal[3];
+ int size[2];
+} Q3BspFace_t;
+
+typedef struct{
+ float position[3];
+ float texcoord[2][2];
+ float normal[3];
+ unsigned char color[4];
+} Q3BspVertex;
+
+typedef struct {
+ int cluster;
+ int area;
+ int mins[3];
+ int maxs[3];
+ int leafface;
+ int n_leaffaces;
+ int leafbrush;
+ int n_leafbrushes;
+} Q3BspLeaf;
+
+typedef struct {
+ float normal[3];
+ float dist;
+} Q3BspPlane;
+
+typedef struct {
+ int plane;
+ int children[2];
+ int mins[3];
+ int maxs[3];
+} Q3BspNode;
+
+typedef struct {
+ int brushside;
+ int n_brushsides;
+ int texture;
+} Q3BspBrush;
+
+typedef struct {
+ int plane;
+ int texture;
+} Q3BspBrushSide;
+
+typedef struct {
+ unsigned char lightmap[128][128][3];
+} Q3BspLightMap;
+
+typedef struct {
+ int n_vecs;
+ int sz_vecs;
+ unsigned char *vecs;
+} Q3BspVisData;
+
+typedef struct {
+ int size;
+ Bezier *bezier;
+} Q3BspPatch;
+
+
+// this struct must be the same as in BZNq3map2
+typedef struct
+{
+ int Zone ;
+ float Min[3] ;
+ float Max[3] ;
+}
+BZN_SubZone_t;
+
+// this struct must be the same as in BZNq3map2
+typedef struct
+{
+ float Min[3] ;
+ float Max[3] ;
+}
+BZN_Portal_t;
+
+
+typedef struct{
+ int texture;
+ int type;
+ int vertex;
+ int n_vertexes;
+ int meshvert;
+ int n_meshverts;
+ int n_triangles;
+ int lm_index;
+ float normal[3];
+ int zone ; // added by Jared
+ Q3BspPatch *patch;
+} Q3BspFaceRenderer;
+
+//////////////////////////////////////
+typedef struct {
+ int Zone ; // this gets set to -1 for triangles in no zone, and they don't get added to the manualobjects
+ int Texture ;
+ //int Lightmap ; // bzn doesn't use lightmaps
+ int VIndex[3] ;
+ int Lamp ; // which lamp this triangle came from, -1 for most triangles.
+
+ int Group ; // triangles from the same face are the same group, triangles from the same patch are the same group. Most stuff is group 0 unless it needs special attention, such as transparent stuff
+} triangle_t;
+
+typedef struct {
+ unsigned int Flags ;
+ float Position[3] ;
+ float Direction[3] ;
+ float Colour[3] ;
+ float Min[3] ;
+ float Max[3] ;
+ float Cutoff ;
+ float Angle ;
+ float Brightness ;
+ int Texture ; // texture index of light
+ unsigned int ZoneCount ; // how many zones this light touches
+ unsigned int CentreZone ; // which zone contains the centre of this light. even if on a boundary, the light will only choose one zone as its centre.
+ short SubLightStart ; // where this light's sublights start in the sublight list.
+} light_t ;
+
+typedef struct {
+ unsigned int Flags ;
+ float Position[3] ;
+ float Colour[3] ;
+ float Min[3] ;
+ float Max[3] ;
+ float Brightness ;
+ int Texture ; // texture index of light
+ int LightNode ; // -1 if not a node, 0 - 3 if a node. LightNodes are used as the data for TexLamps, freeform geometry that gets converted to deferred shading lamp triangles.
+ unsigned short Zone[MAX_ZONEPERLIGHT+1] ; // the zones this lamp touches
+} lamp_t ;
+
+typedef struct
+{
+ float Min[3] ;
+ float Max[3] ;
+}
+minmax_t;
+
+// this used for the light culling algo, where each cutup light is treated as a subzone.
+typedef struct
+{
+ unsigned short Light ;
+ unsigned short Zone ;
+ float Min[3] ;
+ float Max[3] ;
+}
+sublight_t;
+
+
+class Q3Map
+{
+public:
+ Q3Map();
+ ~Q3Map();
+
+ int m_nNewCount ;
+
+ int m_nDebugA ;
+
+ CJarDebug Q3Bug ; //!! just for debugging, remove from final build
+ char m_chBug[10240] ;
+
+ int ParseAndTriangulateMap(const char* pData, size_t Size) ;
+ void FreeParseMem(void) ;
+
+ int parseMap(const char* pMem, size_t Size);
+
+ int findVisibleFaces(const QVECTOR *camPos, int *facesToRender);
+ Q3BspFace_t *getFaces(void);
+ Q3BspPatch *handlePatch(int faceIndex);
+
+ char m_chSpotlightTexture[MAX_PROJECTORTEX][Q3NAMESIZE] ;
+ int m_nMaxSpotlightTexture ;
+ int AddSpolightTexture(char TEXNAME[]) ;
+
+private:
+
+
+
+
+
+
+
+ int findLeaf(const QVECTOR *camPos) const;
+ bool isClusterVisible(int visCluster, int testCluster) const;
+
+ int *mVisibleFaces;
+
+ std::vector<Q3BspVisData> *patches;
+
+public:
+ // map data
+
+ Q3BspHeader_t m_BspHeader;
+
+ char *m_pEntities;
+
+ int m_iNumTexs;
+ Q3BspTexture *m_pTexturesOrig;
+
+ int m_iNumFaces;
+ Q3BspFace_t *m_pFaces;
+
+ int m_iNumVertices;
+ Q3BspVertex *m_pVertices;
+
+ int m_iNumMeshVerts;
+ int *m_pMeshVerts;
+
+ int m_iNumLeafs;
+ Q3BspLeaf *m_pLeafs;
+
+ int m_iNumLeafFaces;
+ int *m_pLeafFaces;
+
+ int m_iNumPlanes;
+ Q3BspPlane *m_pPlanes;
+
+ int m_iNumNodes;
+ Q3BspNode *m_pNodes;
+
+ int m_iNumLeafBrushes;
+ int *m_pLeafBrushes;
+
+ int m_iNumBrushes;
+ Q3BspBrush *m_pBrushes;
+
+ int m_iNumBrushSides;
+ Q3BspBrushSide *m_pBrushSides;
+
+ int m_iNumLightMaps;
+ Q3BspLightMap *m_pLightMaps;
+
+ Q3BspVisData *m_VisData;
+
+ int m_iNumSubZones ;
+ BZN_SubZone_t *m_pSubZones;
+
+ int m_iNumPortals ;
+ BZN_Portal_t *m_pPortals;
+
+
+
+
+ int m_ClusterCount ;
+
+ void swizzleCoords(void);
+ void swizzleFloat3(float t[3]);
+ void swizzleInt3(int t[3]);
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // memory management for the triangles
+ int AllocateTriangleMemory(void) ;
+ void FreeTriangleMemory(void) ;
+ int ExpandTriangleMemory(void) ;
+ int AddTriangle(triangle_t Triangle) ;
+ int m_nTriangleSize ; // starting memory size
+ void* m_pTriangleMem ; // allocate starting memory space
+ triangle_t* m_pTriangle ; // a pointer to the memory cast as a triangle_t
+ int m_nTriangleMax ;
+ int m_nTriangleLimit ;
+
+ // memory management for the vertices
+ int AllocateVertexMemory(int nVertNum) ;
+ void FreeVertexMemory(void) ;
+ int ExpandVertexMemory(void) ;
+ int AddVertex(Q3BspVertex Vertex) ;
+ int m_nVertexSize ; // starting memory size
+ void* m_pVertexMem ; // allocate starting memory space
+ Q3BspVertex* m_pVertex ; // a pointer to the memory cast as a Q3BspVertex
+ int m_nVertexMax ;
+ int m_nVertexLimit ;
+
+ // memory management for the lights
+ int AllocateLightMemory(void) ;
+ void FreeLightMemory(void) ;
+ int ExpandLightMemory(void) ;
+ int AddLight(light_t Light) ;
+ int m_nLightSize ; // starting memory size
+ void* m_pLightMem ; // allocate starting memory space
+ light_t* m_pLight ; // a pointer to the memory cast as a light_t
+ int m_nLightMax ;
+ int m_nLightLimit ;
+
+ // memory management for the lamps (a lamp is a deferred shading non-shadowing point light)
+ int AllocateLampMemory(void) ;
+ void FreeLampMemory(void) ;
+ int ExpandLampMemory(void) ;
+ int AddLamp(lamp_t Lamp) ;
+ int m_nLampSize ; // starting memory size
+ void* m_pLampMem ; // allocate starting memory space
+ lamp_t* m_pLamp ; // a pointer to the memory cast as a lamp_t
+ int m_nLampMax ;
+ int m_nLampLimit ;
+
+ // memory management for the textures
+ int AllocateTextureMemory(void) ;
+ void FreeTextureMemory(void) ;
+ int ExpandTextureMemory(void) ;
+ int AddTexture(Q3BspTexture Texture) ;
+ int AddTextureUnique(Q3BspTexture Texture) ; // special version of the Add function, will not add if the texture name already exist. returns texture index, or -1 on fail
+ int m_nTextureSize ; // starting memory size
+ void* m_pTextureMem ; // allocate starting memory space
+ Q3BspTexture* m_pTexture ; // a pointer to the memory cast as a Texture_t
+ int m_nTextureMax ;
+ int m_nTextureLimit ;
+
+ // memory management for the TexLamp Triangles
+ int AllocateTexLampMemory(void) ;
+ void FreeTexLampMemory(void) ;
+ int ExpandTexLampMemory(void) ;
+ int AddTexLamp(int TexLamp) ;
+ int m_nTexLampSize ; // starting memory size
+ void* m_pTexLampMem ; // allocate starting memory space
+ int* m_pTexLamp ; // a pointer to the memory cast as an int
+ int m_nTexLampMax ;
+ int m_nTexLampLimit ;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ int ParseEntities(void) ;
+ int NextEntity(int* pPos, int nMaxPos) ;
+ int GetEntityType(int nPos, int nMaxPos) ;
+ int GetEntityKeyAndValue(int* pPos, int nMaxPos, char* pKey, char* pValue) ;
+ int GetNumbersFromValue(char* pValue, float *pNumber, int nNumberSize) ;
+ int GetNumbersFromValue(char* pValue, int *pNumber, int nNumberSize) ;
+ int ParseAndAddLight(int* pPos, int nMaxPos) ;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ Q3BspFaceRenderer *m_BspFaces;
+ int m_NumBspFaces;
+ void DestroyBspFacesMemory(void) ;
+ int initFaces(void) ;
+
+ // we keep track of common texture indexes to avoid slow calls to AddTextureUnique when we add default light texture indexes
+ int m_nDefaultTextureIndexLamp ;
+ int m_nDefaultTextureIndexLamp2Pass ;
+ int m_nDefaultTextureIndexGlowLamp ;
+ int m_nDefaultTextureIndexGlowLight ;
+ int m_nDefaultTextureIndexSpotlight ;
+
+ void GetTexLampTextureNumbers() ;
+ int m_nBZN_LightNode0 ;
+ int m_nBZN_LightNode1 ;
+ int m_nBZN_LightNode2 ;
+ int m_nBZN_LightNode3 ;
+
+ int m_nGroup ;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Much easier to keep track of how zones/subzones/portals/lights connect to each other using hardwired arrays
+ // than dynamically allocated memory, even if it does waste a little space and impose some design limits.
+ // It's fast, easy to manage, and the total memory used is reasonably small.
+ // The design limits are generous enough that it's unlikely maps will get anywhere near hitting them.
+ //
+ // Memory Footprints:
+ //
+ // m_nZone: 4096 * (16+1) * sizeof(unsigned short) = 139,264
+ // m_ZoneBoundary 4096 * sizeof(minmax_t)24 = 98,304
+ // m_nZoneTouchesPortal 4096 * (64+1) * sizeof(unsigned short) = 532,480
+ // m_nPortalTouchesZone 32768 * ( 8+1) * sizeof(unsigned short) = 589,824
+ //
+ // m_nZoneContainsLightCentre 4096 * (64+1) * sizeof(unsigned short) = 532,480
+ // m_nLightTouchesZone 32768 * ( 8+1) * sizeof(unsigned short) = 589,824
+ // m_nZoneTouchesSubLight 4096 * (64+1) * sizeof(unsigned short) = 532,480
+ //
+ // m_nMultiZoneLight 32768 * sizeof(unsigned short) = 65,536
+ // m_SubLight 32768 * 8 * sizeof(sublight_t)28 = 6,815,744
+ // m_nZoneTouchesZone 4096 * (64+1) * sizeof(unsigned short) = 532,480
+ //
+ // TOTAL = 10,428,416 (9.9 meg)
+
+ unsigned short m_nZone[MAX_ZONE][MAX_SUBZONEPERZONE+1] ; // last index is used as a counter, INDEX_SUBZONECOUNT
+ minmax_t m_ZoneBoundary[MAX_ZONE] ; // min and max of a zone. Since zones might not be square, NEVER use this as the real zone boundary, work it out using the subzones instead. This is just for cutting up lights.
+
+ unsigned short m_nZoneTouchesPortal[MAX_ZONE][MAX_PORTALPERZONE+1] ; // last index is used as a counter, INDEX_PORTALCOUNT
+ unsigned short m_nPortalTouchesZone[MAX_PORTAL][MAX_ZONEPERPORTAL+1] ; // last index is used as a counter, INDEX_PORTALZONECOUNT
+
+ // PortalTouchesLight is true if the light AABB touches the portal.
+ unsigned short m_nPortalTouchesLight[MAX_PORTAL][MAX_LIGHTPERPORTAL+1] ; // last index is used as a counter, INDEX_PORTALLIGHTCOUNT
+
+ unsigned short m_nZoneContainsLightCentre[MAX_ZONE][MAX_LIGHTPERZONE+1] ; // last index is used as a counter, INDEX_LIGHTCOUNT
+ unsigned short m_nLightTouchesZone[MAX_LIGHT][MAX_ZONEPERLIGHT+1] ; // last index is used as a counter, INDEX_LIGHTZONECOUNT
+ unsigned short m_nZoneTouchesSubLight[MAX_ZONE][MAX_LIGHTPERZONE+1] ; // last index is used as a counter, INDEX_LIGHTCOUNT
+
+ unsigned short m_nZoneTouchesZone[MAX_ZONE][MAX_ZONEPERZONE+1] ; // last index is used as a counter, INDEX_ZONEPERZONECOUNT
+
+ // list of lights that touche more than one zone. These require more complex visibility checks
+ unsigned short m_nMultiZoneLight[MAX_LIGHT] ;
+ int m_nMaxMultiZoneLight ;
+
+ sublight_t m_SubLight[MAX_SUBLIGHT] ;
+ int m_nSubLightMax ;
+
+
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ int m_nMaxZone ;
+
+ int ConvertFacesToTriangles(void) ;
+ int ConvertPatchesToTriangles(void) ;
+ int ConvertTexLampsToLampTriangles(void) ;
+ int ConvertLampsToTriangles(void) ;
+ int ConvertLampsToGlowTriangles(void) ;
+ int ConvertLightsToGlowTriangles(void) ;
+
+
+ void SetVertex(Q3BspVertex *pVert, float flXPos, float flYPos, float flZPos) ;
+ bool VectorsAreEqual(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ;
+ Q3BspVertex NormalizedCrossProduct(Q3BspVertex VertA, Q3BspVertex VertB, Q3BspVertex VertC) ;
+ float VertexDistance(Q3BspVertex* VertA, Q3BspVertex* VertB) ;
+ void VertexScale(Q3BspVertex* pVert, float flScale) ;
+ Q3BspVertex GetNormalised(Q3BspVertex* pVector) ;
+ Q3BspVertex VectorAdd(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ;
+ Q3BspVertex VectorSubtract(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ;
+ Q3BspVertex VectorMultiply(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ;
+
+ void SetupZones(void) ;
+ int GetNextSubZone(float *flPoint, int nStart, int nMax) ;
+
+ bool PointInSubZone(float *flPoint, int nSubZone) ;
+ bool PointInZone(float *flPos, int nZone) ;
+
+ bool AABBTouchesSubZone(float *flPointMin, float *flPointMax, int nSubZone) ;
+ bool AABBTouchesZone(float *flPosMin, float *flPosMax, int nZone) ;
+
+ int AssignTrianglesToZones(void) ;
+ int FindTriangleZone(int nTriangle) ;
+ int SetupTriangleZone(int nTriangle) ;
+ int SplitTriangle(int nTriangle, int nAxis, float flCutPos) ; // only does axial cuts. returns false on failure, probably due to lack of memory.
+ void CreateTweenVert(Q3BspVertex* pVertA, Q3BspVertex* pVertB, float flPercent0, Q3BspVertex* pVertAB) ;
+
+
+ int SortTrianglesIntoGroups(void) ;
+ static int compareGroups( const void *arg1, const void *arg2 ) ;
+
+ int SortTrianglesIntoBatches(void) ;
+ static int compareTriangles( const void *arg1, const void *arg2 ) ;
+
+ int SetupTransTextures(void) ;
+ int* m_pTransTexture ;
+
+
+ int AssignPortalsToZones(void) ;
+ int AssignLightsToPortals(void) ;
+ int AssignLightsToZones(void) ;
+ int AssignZonesToZones(void) ;
+
+};
+
+#endif /* _Q3MAP_H */
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/Q3Map.h
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,131 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// Bezier.cpp -- tessellates the Bezier patches
+
+/* The tessellation code is taken from the document
+"Rendering Quake 3 Maps" at
+http://graphics.cs.brown.edu/games/quake/quake3.html
+The author states that it is based on code from
+Paul Baker's Octagon project,
+http://www.paulsprojects.net/opengl/octagon/octagon.html
+which is released under the New BSD license.
+Please see the licenses folder.
+*/
+
+#include "Q3Map_Bezier.h"
+#include "Q3Map_misc.h"
+
+
+Bezier::Bezier()
+{
+ mVertex = 0;
+ mIndex = 0;
+ mTrianglesPerRow = 0;
+ mRowIndex = 0;
+}
+
+Bezier::~Bezier()
+{
+ DELETE_ARRAY(mVertex);
+ DELETE_ARRAY(mIndex);
+ DELETE_ARRAY(mTrianglesPerRow);
+ DELETE_ARRAY(mRowIndex);
+}
+
+
+
+
+
+void Bezier::tessellate(int L)
+{
+ // The number of vertices along a side is 1 + num edges
+ const int L1 = L + 1;
+
+ mVertex = new BspVertex[L1*L1];
+ mNumVertex = L1*L1;
+
+ // Compute the vertices
+ for (int i = 0; i <= L; ++i)
+ {
+ float a = (float)i / L;
+ float b = 1.0f - a;
+
+ mVertex[i] =
+ mControls[0] * (b * b) +
+ mControls[3] * (2 * b * a) +
+ mControls[6] * (a * a);
+ }
+
+ for (int i = 1; i <= L; i++)
+ {
+ float a = (float)i / L;
+ float b = 1.0f - a;
+
+ BspVertex temp[3];
+
+ for (int j = 0; j < 3; j++)
+ {
+ int k = 3 * j;
+ temp[j] =
+ mControls[k + 0] * (b * b) +
+ mControls[k + 1] * (2 * b * a) +
+ mControls[k + 2] * (a * a);
+ }
+
+ for(int j = 0; j <= L; ++j)
+ {
+ float a = (float)j / L;
+ float b = 1.0f - a;
+
+ mVertex[i * L1 + j]=
+ temp[0] * (b * b) +
+ temp[1] * (2 * b * a) +
+ temp[2] * (a * a);
+ }
+ }
+
+ // Compute the indices
+ mIndex = new unsigned int[L * (L + 1) * 2];
+ mNumIndex = L * (L + 1) * 2;
+
+ for (int row = 0; row < L; ++row)
+ {
+ for(int col = 0; col <= L; ++col)
+ {
+ mIndex[(row * (L + 1) + col) * 2 + 1] = row * L1 + col;
+ mIndex[(row * (L + 1) + col) * 2] = (row + 1) * L1 + col;
+ }
+ }
+
+ mTrianglesPerRow = new unsigned int[L];
+ mRowIndex = new unsigned int[L];
+
+ for (int row = 0; row < L; ++row)
+ {
+ mTrianglesPerRow[row] = 2 * L1;
+ //rowIndexes[row] = &indexes[row * 2 * L1];
+ mRowIndex[row] = row * 2 * L1;
+ }
+
+ for (int i=0; i < L1*L1; i++)
+ mVertex[i].normalise();
+}
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.h
===================================================================
--- code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.h (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.h 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,48 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// Bezier.h -- class for the Bezier patches
+
+#ifndef _BEZIER_H
+#define _BEZIER_H
+
+#include "Q3Map_BspVertex.h"
+
+class Bezier
+{
+public:
+ Bezier();
+ ~Bezier();
+
+ void tessellate(int level);
+
+ BspVertex mControls[9];
+ BspVertex *mVertex;
+ unsigned int *mIndex;
+ unsigned int *mTrianglesPerRow;
+ unsigned int *mRowIndex;
+ unsigned int mNumIndex;
+ unsigned int mNumVertex;
+ int mBaseBufferindex;
+ int mBaseVertexIndex;
+};
+
+#endif
Property changes on: code/branches/fps/src/libraries/tools/fps/Q3Map_Bezier.h
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,106 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// BspVertex.cpp -- used in the tessellation of the Bezier patches
+
+
+#include <math.h>
+#include "Q3Map_BspVertex.h"
+
+
+BspVertex::BspVertex()
+{
+ for (int i=0; i<3; i++)
+ mPosition[i] = 0;
+
+ for (int i=0; i<3; i++)
+ mNormal[i] = 0;
+
+ for(int i=0; i<2; i++)
+ for(int j=0; j<2; j++)
+ mTexcoord[i][j] = 0;
+}
+
+BspVertex::BspVertex(float p[3], float texcoord[2][2], float n[3])
+{
+ for (int i=0; i<3; i++)
+ mPosition[i] = p[i];
+
+ for (int i=0; i<3; i++)
+ mNormal[i] = n[i];
+
+ for(int i=0; i<2; i++)
+ for(int j=0; j<2; j++)
+ {
+ this->mTexcoord[i][j] = texcoord[i][j];
+ }
+}
+
+BspVertex BspVertex::operator+(BspVertex a)
+{
+ BspVertex res;
+
+ for (int i=0; i<3; i++)
+ {
+ res.mPosition[i] = this->mPosition[i] + a.mPosition[i];
+ res.mNormal[i] = this->mNormal[i] + a.mNormal[i];
+ }
+
+ for(int i=0; i<2; i++)
+ for(int j=0; j<2; j++)
+ {
+ res.mTexcoord[i][j] = this->mTexcoord[i][j] + a.mTexcoord[i][j];
+ }
+
+ return res;
+}
+
+BspVertex BspVertex::operator*(float a)
+{
+ BspVertex res;
+
+ for (int i=0; i<3; i++)
+ {
+ res.mPosition[i] = this->mPosition[i] * a;
+ res.mNormal[i] = this->mNormal[i] * a;
+ }
+
+ for(int i=0; i<2; i++)
+ for(int j=0; j<2; j++)
+ res.mTexcoord[i][j] = this->mTexcoord[i][j] * a;
+
+ return res;
+}
+
+void BspVertex::normalise(void)
+{
+ //QVECTOR n((float)mNormal[0], (float)mNormal[1], (float)mNormal[2]);
+
+ //D3DXVec3Normalize(&n, &n);
+ //mNormal[0] = n.x;
+ //mNormal[1] = n.y;
+ //mNormal[2] = n.z;
+
+ float flLen=sqrt( mNormal[0]*mNormal[0] + mNormal[1]*mNormal[1] + mNormal[2]*mNormal[2] ) ;
+ mNormal[0]/=flLen ;
+ mNormal[1]/=flLen ;
+ mNormal[2]/=flLen ;
+}
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.h
===================================================================
--- code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.h (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.h 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,44 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// BspVertex.h -- used in the tessellation of the Bezier patches
+
+#ifndef _BSPVERTEX_H
+#define _BSPVERTEX_H
+
+class BspVertex
+{
+public:
+ BspVertex();
+ BspVertex(float p[3], float texcoord[2][2], float n[3]);
+
+ float mPosition[3];
+ float mTexcoord[2][2];
+ float mNormal[3];
+
+ BspVertex operator+(BspVertex a);
+ BspVertex operator*(float a);
+
+ void normalise(void);
+
+};
+
+#endif
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/Q3Map_BspVertex.h
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/Q3Map_misc.h
===================================================================
--- code/branches/fps/src/libraries/tools/fps/Q3Map_misc.h (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/Q3Map_misc.h 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,33 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+Copyright (C) 2009 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// misc.h -- various definitions and functions
+
+#ifndef _MISC_H
+#define _MISC_H
+
+#define DELETE_POINTER(x) if(x) { delete x ; x=0 ; }
+#define DELETE_ARRAY(x) if(x) { delete [] x ; x=0 ; }
+
+typedef float QVECTOR[3];
+
+#endif /* _MISC_H */
Property changes on: code/branches/fps/src/libraries/tools/fps/Q3Map_misc.h
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/main.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/main.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/main.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,35 @@
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#include "DemoApp.hpp"
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+#define WIN32_LEAN_AND_MEAN
+#include "windows.h"
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
+#else
+int main(int argc, char **argv)
+#endif
+{
+ try
+ {
+ DemoApp demo;
+ demo.startDemo();
+ }
+ catch(std::exception& e)
+ {
+#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+ MessageBoxA(NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
+#else
+ fprintf(stderr, "An exception has occurred: %s\n", e.getFullDescription().c_str());
+#endif
+ }
+
+ return 0;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/main.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: code/branches/fps/src/libraries/tools/fps/misc.cpp
===================================================================
--- code/branches/fps/src/libraries/tools/fps/misc.cpp (rev 0)
+++ code/branches/fps/src/libraries/tools/fps/misc.cpp 2010-05-02 21:11:32 UTC (rev 6819)
@@ -0,0 +1,32 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// misc.cpp -- various definitions and functions
+
+#include "misc.h"
+
+void exitFunction(string reason)
+{
+ cerr << "\n" << reason << "\n";
+ cerr << "exiting\n";
+ Sleep(3000);
+ exit(1);
+}
\ No newline at end of file
Property changes on: code/branches/fps/src/libraries/tools/fps/misc.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
More information about the Orxonox-commit
mailing list