//||||||||||||||||||||||||||||||||||||||||||||||| /* =========================================================================== 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 . */ #include "OgreFramework.hpp" #include #include /* Needed only for _O_RDWR definition */ #include #include "Q3Map_misc.h" // safe pointer deletes //||||||||||||||||||||||||||||||||||||||||||||||| using namespace Ogre; //||||||||||||||||||||||||||||||||||||||||||||||| template<> OgreFramework* Ogre::Singleton::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 ; nPTexlogMessage(" "); m_pLog->logMessage(" Mircosecs: Physics Render Ideal Average Pragma Total"); m_pLog->logMessage(" ----------------------------------------"); for(nFrame=0 ; nFramelogMessage(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(m_pInputMgr->createInputObject(OIS::OISKeyboard, true)); m_pMouse = static_cast(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 ; nVisEntsetPosition( m_pEntityInfo[nEntity].Postition ) ; // set position. m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ; } ///////////////////////////////////////////////////////////////////// // DfShPosition // change material for(nZoneList=0 ; nZoneListsetMaterial( 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 ; nVisEntgetSubEntity(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 ; nZoneListsetMaterial( m_pZoneEntityMaterial_DfShFuncTNB[nMO] ) ; }// end for entities }// end for zonelist for(nVisEnt=0 ; nVisEntgetSubEntity(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 ; nZoneListsetMaterial( m_pZoneEntityMaterial_DfShDiffuse[nMO] ) ; }// end for entities }// end for zonelist // set the entity material for(nVisEnt=0 ; nVisEntgetSubEntity(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 ; nZoneListsetMaterial( MaterialManager::getSingleton().getByName("White") ) ; }// end for entities }// end for zonelist for(nVisEnt=0 ; nVisEntgetSubEntity(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 ; nVisEntgetRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ; for(nSubMesh=0 ; nSubMeshgetSubEntity(nSubMesh)->setVisible(false) ; } } } ///////////////////////////////////////////////////////////////////// // DfShSpecular // change material for(nZoneList=0 ; nZoneListsetMaterial( m_pZoneEntityMaterial_DfShSpecular[nMO] ) ; }// end for entities }// end for zonelist for(nVisEnt=0 ; nVisEntgetSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShSpecular[nSubMesh] ) ; } renderTexture_DfShSpecular->update(true) ; /* ///////////////////////////////////////////////////////////////////// // DfShData // change material for(nZoneList=0 ; nZoneListsetMaterial( 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 ; nZoneListsetMaterial( 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 ; nVisEntgetSubEntity(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 ; nZoneListsetMaterial( m_pZoneEntityMaterial_DfShColour[nMO] ) ; }// end for entities }// end for zonelist for(nVisEnt=0 ; nVisEntgetSubEntity(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 ; nVisibleLightsynchroniseBaseSettingsWith(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 ; nVisEntgetRootSceneNode()->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 ; nEntLtIndexsetMaterial( m_pZoneEntityMaterial_Shadow[nMO] ) ; }// end for entities }// end for zonelist for(nVisEnt=0 ; nVisEntgetSubEntity(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 ; nZoneListsetMaterial( m_pZoneEntityMaterial_ShadeFront[nMO] ) ; }// end for entities }// end for zonelist for(nVisEnt=0 ; nVisEntgetSubEntity(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 ; nZoneListsetMaterial( m_pZoneEntityMaterial_ShadeBack[nMO] ) ; }// end for entities }// end for zonelist for(nVisEnt=0 ; nVisEntgetSubEntity(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 ; nZoneListsetMaterial( 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 ; nVisEntgetSubEntity(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 ; nBlurLoopgetRootSceneNode()->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 ; nZonem_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 ; nLoopgetRootSceneNode()->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 ; nMeshdestroyEntity(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~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 ; nChecklogMessage(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 ; nZonem_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 ; nMOlogMessage(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 ; nTrim_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 ; nPTexm_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 ; nZonem_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((nTrianglem_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( (nEndm_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((++nPosm_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 ; nVertm_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 ; nTrim_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(flPosXflMaxX) flMaxX=flPosX ; if(flPosY>flMaxY) flMaxY=flPosY ; if(flPosZ>flMaxZ) flMaxZ=flPosZ ; }// end if adding vert } // add the triangles for(nTri=nTriangle ; nTrim_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 ; nPTexm_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 ; nPTexsetPosition(750.0f, 128.0f, -1950.0f-nEntity*40.0f) ; } for(nEntity=nHalfMax ; nEntitysetPosition(590.0f, 128.0f, -320.0f-nEntity*40.0f) ; } for(nEntity=0 ; nEntitycreateEntity( 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 ; nSubMeshgetMesh()->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 ; nPTexm_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 ; nZoneMOgetTechnique(0)->getPass(1)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON 1") ; nMaxPass=m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getNumPasses() ; for(nPass=0 ; nPassgetTechnique(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 ; nLtcreateManualObject(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 ; nPtcreateManualObject(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 ; nSubZonem_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 ; nEntity0) { 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 ; nZoneIndexPointInZone(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 ; nZoneIndexm_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 ; nZoneIndexm_nZoneTouchesSubLight[nZone][MAX_LIGHTPERZONE] ; for(nSubLightIndex=0 ; nSubLightIndexm_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]pLightMin[0]) && (AABBMin[1]pLightMin[1]) && (AABBMin[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 ; nEntityisVisible(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 ; nLtgetLight(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 ; nZonem_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 ; nListPosisInSceneGraph() ) 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 ; nLtsetVisible(true) ; } else m_pLightMO[nLt]->setVisible(false) ; } if(m_nPortalDebug) { int nPt=0 ; int nMaxPortal=m_Q3Map->m_iNumPortals ; for(nPt=0 ; nPtsetVisible(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 ; nListPosm_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ; nFoundZone=0 ; for(nLightZone=0 ; nLightZonem_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 ; nLightZonem_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 ; nLightIndexm_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 ; nPortalIndexm_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 ; nPortalLightIndexm_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 ; nSubLightm_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 ; nLightIndexm_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 ; nSubLightm_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 ; nInnerLightm_SubLight[nInnerLight].Zone ] != ZONE_VISIBLE) // don't test if already visible // if overlap, InnerLight's zone is visible &&(flMinXm_SubLight[nInnerLight].Max[0]) && (flMaxX>m_Q3Map->m_SubLight[nInnerLight].Min[0]) &&(flMinYm_SubLight[nInnerLight].Max[1]) && (flMaxY>m_Q3Map->m_SubLight[nInnerLight].Min[1]) &&(flMinZm_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 ; nSubLightIndexm_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) && (*pMaxVisibleLightm_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 ; nPortalZoneIndexm_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].xMaxX) MaxX=xyz[nLoop].x ; if(xyz[nLoop].yMaxY) 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 ; nLtcreateLight(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'z')) ) ; if(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((nConfigPosMAXGPUQUERY) 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 }