/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program 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. * * This program 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 this program. If not, see . * */ /* * Copyright (C) 2006-2010 - Frictional Games * * This file is part of HPL1 Engine. */ #include "hpl1/engine/scene/World3D.h" #include "hpl1/engine/impl/tinyXML/tinyxml.h" #include "hpl1/engine/system/Script.h" #include "hpl1/engine/system/String.h" #include "hpl1/engine/system/low_level_system.h" #include "hpl1/engine/math/Math.h" #include "hpl1/engine/math/MathTypes.h" #include "hpl1/engine/game/Game.h" #include "hpl1/engine/graphics/Beam.h" #include "hpl1/engine/graphics/BillBoard.h" #include "hpl1/engine/graphics/Graphics.h" #include "hpl1/engine/graphics/Mesh.h" #include "hpl1/engine/graphics/ParticleEmitter3D.h" #include "hpl1/engine/graphics/ParticleSystem3D.h" #include "hpl1/engine/graphics/Renderer3D.h" #include "hpl1/engine/resources/FileSearcher.h" #include "hpl1/engine/resources/MaterialManager.h" #include "hpl1/engine/resources/ParticleManager.h" #include "hpl1/engine/resources/Resources.h" #include "hpl1/engine/resources/ScriptManager.h" #include "hpl1/engine/resources/SoundEntityManager.h" #include "hpl1/engine/resources/TextureManager.h" #include "hpl1/engine/scene/Camera.h" #include "hpl1/engine/scene/ColliderEntity.h" #include "hpl1/engine/scene/Light3DPoint.h" #include "hpl1/engine/scene/Light3DSpot.h" #include "hpl1/engine/scene/MeshEntity.h" #include "hpl1/engine/scene/Node3D.h" #include "hpl1/engine/scene/PortalContainer.h" #include "hpl1/engine/scene/Scene.h" #include "hpl1/engine/scene/SoundEntity.h" #include "hpl1/engine/scene/SoundSource.h" #include "hpl1/engine/system/System.h" #include "hpl1/engine/sound/Sound.h" #include "hpl1/engine/sound/SoundEntityData.h" #include "hpl1/engine/sound/SoundHandler.h" #include "hpl1/engine/physics/Physics.h" #include "hpl1/engine/physics/PhysicsBody.h" #include "hpl1/engine/physics/PhysicsWorld.h" #include "hpl1/engine/ai/AI.h" #include "hpl1/engine/ai/AINodeContainer.h" #include "hpl1/engine/ai/AINodeGenerator.h" #include "hpl1/engine/ai/AStar.h" namespace hpl { ////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cWorld3D::cWorld3D(tString asName, cGraphics *apGraphics, cResources *apResources, cSound *apSound, cPhysics *apPhysics, cScene *apScene, cSystem *apSystem, cAI *apAI) { mpGraphics = apGraphics; mpResources = apResources; mpSound = apSound; mpPhysics = apPhysics; mpScene = apScene; mpSystem = apSystem; mpAI = apAI; mpRootNode = hplNew(cNode3D, ()); mpScript = NULL; msName = asName; mAmbientColor = cColor(0, 0); mpPortalContainer = hplNew(cPortalContainer, ()); mpPhysicsWorld = NULL; mbAutoDeletePhysicsWorld = false; msFileName = ""; } //----------------------------------------------------------------------- cWorld3D::~cWorld3D() { STLDeleteAll(mlstMeshEntities); STLDeleteAll(mlstLights); STLDeleteAll(mlstBillboards); STLDeleteAll(mlstBeams); STLDeleteAll(mlstColliders); STLDeleteAll(mlstParticleSystems); STLDeleteAll(mlstStartPosEntities); STLMapDeleteAll(m_mapAreaEntities); STLDeleteAll(mlstAINodeContainers); STLDeleteAll(mlstAStarHandlers); STLMapDeleteAll(m_mapTempNodes); if (mpScript) { mpResources->GetScriptManager()->Destroy(mpScript); } if (mpPhysicsWorld && mbAutoDeletePhysicsWorld) mpPhysics->DestroyWorld(mpPhysicsWorld); // So that bodies can stop sound entities on destruction. STLDeleteAll(mlstSoundEntities); hplDelete(mpPortalContainer); hplDelete(mpRootNode); } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cWorld3D::Update(float afTimeStep) { START_TIMING(Physics); if (mpPhysicsWorld) mpPhysicsWorld->Update(afTimeStep); STOP_TIMING(Physics); START_TIMING(Entities); UpdateEntities(afTimeStep); STOP_TIMING(Entities); START_TIMING(Bodies); UpdateBodies(afTimeStep); STOP_TIMING(Bodies); START_TIMING(Particles); UpdateParticles(afTimeStep); STOP_TIMING(Particles); START_TIMING(Lights); UpdateLights(afTimeStep); STOP_TIMING(Lights); START_TIMING(SoundEntities); UpdateSoundEntities(afTimeStep); STOP_TIMING(SoundEntities); } //----------------------------------------------------------------------- void cWorld3D::PreUpdate(float afTotalTime, float afTimeStep) { mpSound->GetSoundHandler()->SetSilent(true); while (afTotalTime > 0) { if (mpPhysicsWorld) mpPhysicsWorld->Update(afTimeStep); UpdateParticles(afTimeStep); afTotalTime -= afTimeStep; } mpSound->GetSoundHandler()->SetSilent(false); } //----------------------------------------------------------------------- iRenderableContainer *cWorld3D::GetRenderContainer() { return mpPortalContainer; } cPortalContainer *cWorld3D::GetPortalContainer() { return mpPortalContainer; } //----------------------------------------------------------------------- void cWorld3D::SetPhysicsWorld(iPhysicsWorld *apWorld, bool abAutoDelete) { mpPhysicsWorld = apWorld; mbAutoDeletePhysicsWorld = abAutoDelete; if (mpPhysicsWorld) mpPhysicsWorld->SetWorld3D(this); } iPhysicsWorld *cWorld3D::GetPhysicsWorld() { return mpPhysicsWorld; } //----------------------------------------------------------------------- static void CheckMinMaxUpdate(cVector3f &avMin, cVector3f &avMax, const cVector3f &avLocalMin, const cVector3f &avLocalMax) { if (avMin.x > avLocalMin.x) avMin.x = avLocalMin.x; if (avMax.x < avLocalMax.x) avMax.x = avLocalMax.x; if (avMin.y > avLocalMin.y) avMin.y = avLocalMin.y; if (avMax.y < avLocalMax.y) avMax.y = avLocalMax.y; if (avMin.z > avLocalMin.z) avMin.z = avLocalMin.z; if (avMax.z < avLocalMax.z) avMax.z = avLocalMax.z; } void cWorld3D::SetUpData() { mpPortalContainer->Compile(); tSectorMap *pSectorMap = mpPortalContainer->GetSectorMap(); ////////////////////////////////////////////// // Get world size by getting sector BV if (pSectorMap->size() > 0) { tSectorMapIt SectorIt = pSectorMap->begin(); cSector *pSector = SectorIt->second; cVector3f vMin = pSector->GetBV()->GetMin(); cVector3f vMax = pSector->GetBV()->GetMax(); ++SectorIt; for (; SectorIt != pSectorMap->end(); ++SectorIt) { pSector = SectorIt->second; cVector3f vLocalMin = pSector->GetBV()->GetMin(); cVector3f vLocalMax = pSector->GetBV()->GetMax(); CheckMinMaxUpdate(vMin, vMax, vLocalMin, vLocalMax); } // Log("World Min: (%s) Max: (%s)\n",vMin.ToString().c_str(), vMax.ToString().c_str()); // Create a 10 m border around the world as well: vMin = vMin - cVector3f(10, 10, 10); vMax = vMax + cVector3f(10, 10, 10); if (mpPhysicsWorld) mpPhysicsWorld->SetWorldSize(vMin, vMax); } ////////////////////////////////////////////// // Get world size by getting global objects BV else { cVector3f vMin = cVector3f(10000, 10000, 100000); cVector3f vMax = cVector3f(-10000, -10000, -100000); // Dynamic tRenderableSet *pRenSet = mpPortalContainer->GetGlobalDynamicObjectSet(); tRenderableSetIt DynIt = pRenSet->begin(); for (; DynIt != pRenSet->end(); ++DynIt) { iRenderable *pObject = *DynIt; cVector3f vLocalMin = pObject->GetBoundingVolume()->GetMin(); cVector3f vLocalMax = pObject->GetBoundingVolume()->GetMax(); CheckMinMaxUpdate(vMin, vMax, vLocalMin, vLocalMax); } // Static tRenderableList *pRenList = mpPortalContainer->GetGlobalStaticObjectList(); tRenderableListIt StaticIt = pRenList->begin(); for (; StaticIt != pRenList->end(); ++StaticIt) { iRenderable *pObject = *StaticIt; cVector3f vLocalMin = pObject->GetBoundingVolume()->GetMin(); cVector3f vLocalMax = pObject->GetBoundingVolume()->GetMax(); CheckMinMaxUpdate(vMin, vMax, vLocalMin, vLocalMax); } vMin = vMin - cVector3f(10, 10, 10); vMax = vMax + cVector3f(10, 10, 10); if (mpPhysicsWorld) mpPhysicsWorld->SetWorldSize(vMin, vMax); } } //----------------------------------------------------------------------- void cWorld3D::AddSaveData(cSaveDataHandler *apHandler) { /////////////////////////////// // Save mesh entities tMeshEntityListIt MeshIt = mlstMeshEntities.begin(); for (; MeshIt != mlstMeshEntities.end(); MeshIt++) { cMeshEntity *pEntity = *MeshIt; if (pEntity->IsSaved()) { iSaveData *pData = pEntity->CreateSaveData(); pEntity->SaveToSaveData(pData); apHandler->Add(pData); } } /////////////////////////////// // Save billboards tBillboardListIt BillIt = mlstBillboards.begin(); for (; BillIt != mlstBillboards.end(); BillIt++) { cBillboard *pEntity = *BillIt; if (pEntity->IsSaved()) { iSaveData *pData = pEntity->CreateSaveData(); pEntity->SaveToSaveData(pData); apHandler->Add(pData); } } /////////////////////////////// // Save lights tLight3DListIt LightIt = mlstLights.begin(); for (; LightIt != mlstLights.end(); LightIt++) { iLight3D *pEntity = *LightIt; if (pEntity->IsSaved()) { iSaveData *pData = pEntity->CreateSaveData(); pEntity->SaveToSaveData(pData); apHandler->Add(pData); } } /////////////////////////////// // Save sounds entities tSoundEntityListIt SoundIt = mlstSoundEntities.begin(); for (; SoundIt != mlstSoundEntities.end(); SoundIt++) { cSoundEntity *pEntity = *SoundIt; if (pEntity->IsSaved()) { iSaveData *pData = pEntity->CreateSaveData(); pEntity->SaveToSaveData(pData); apHandler->Add(pData); } } /////////////////////////////// // Save particle systems tParticleSystem3DListIt PSIt = mlstParticleSystems.begin(); for (; PSIt != mlstParticleSystems.end(); PSIt++) { cParticleSystem3D *pEntity = *PSIt; if (pEntity->IsSaved()) { iSaveData *pData = pEntity->CreateSaveData(); pEntity->SaveToSaveData(pData); apHandler->Add(pData); } } /////////////////////////////// // Add world 3d data apHandler->Add(CreateSaveData()); } //----------------------------------------------------------------------- cAreaEntity *cWorld3D::CreateAreaEntity(const tString &asName) { cAreaEntity *pArea = hplNew(cAreaEntity, ()); pArea->msName = asName; m_mapAreaEntities.insert(tAreaEntityMap::value_type(asName, pArea)); return pArea; } cAreaEntity *cWorld3D::GetAreaEntity(const tString &asName) { tAreaEntityMapIt it = m_mapAreaEntities.find(asName); if (it == m_mapAreaEntities.end()) return NULL; return it->second; } //----------------------------------------------------------------------- iEntity3D *cWorld3D::CreateEntity(const tString &asName, const cMatrixf &a_mtxTransform, const tString &asFile, bool abLoadReferences) { iEntity3D *pEntity = NULL; tString sFileName = cString::SetFileExt(asFile, "ent"); tString sPath = mpResources->GetFileSearcher()->GetFilePath(sFileName); if (sPath != "") { TiXmlDocument *pEntityDoc = hplNew(TiXmlDocument, ()); if (pEntityDoc->LoadFile(sPath.c_str()) == false) { Error("Couldn't load '%s'!\n", sPath.c_str()); } else { TiXmlElement *pRootElem = pEntityDoc->FirstChildElement(); TiXmlElement *pMainElem = pRootElem->FirstChildElement("MAIN"); tString sType = cString::ToString(pMainElem->Attribute("Type"), ""); iEntity3DLoader *pLoader = mpResources->GetEntity3DLoader(sType); if (pLoader) { pEntity = pLoader->Load(asName, pRootElem, a_mtxTransform, this, sFileName, abLoadReferences); pEntity->SetSourceFile(sFileName); } else { Error("Couldn't find loader for type '%s' in file '%s'\n", sType.c_str(), sFileName.c_str()); } } hplDelete(pEntityDoc); } else { Error("Entity file '%s' was not found!\n", sFileName.c_str()); } return pEntity; } //----------------------------------------------------------------------- cMeshEntity *cWorld3D::CreateMeshEntity(const tString &asName, cMesh *apMesh, bool abAddToContainer) { cMeshEntity *pMesh = hplNew(cMeshEntity, (asName, apMesh, mpResources->GetMaterialManager(), mpResources->GetMeshManager(), mpResources->GetAnimationManager())); mlstMeshEntities.push_back(pMesh); if (abAddToContainer) mpPortalContainer->Add(pMesh, false); pMesh->SetWorld(this); return pMesh; } //----------------------------------------------------------------------- void cWorld3D::DestroyMeshEntity(cMeshEntity *apMesh) { if (apMesh == NULL) return; tMeshEntityListIt It = mlstMeshEntities.begin(); for (; It != mlstMeshEntities.end(); ++It) { if (apMesh == *It) { mlstMeshEntities.erase(It); break; } } mpPortalContainer->Remove(apMesh); hplDelete(apMesh); } //----------------------------------------------------------------------- cMeshEntity *cWorld3D::GetMeshEntity(const tString &asName) { tMeshEntityListIt It = mlstMeshEntities.begin(); for (; It != mlstMeshEntities.end(); ++It) { if ((*It)->GetName() == asName) { return *It; } } return NULL; } //----------------------------------------------------------------------- cMeshEntityIterator cWorld3D::GetMeshEntityIterator() { return cMeshEntityIterator(&mlstMeshEntities); } //----------------------------------------------------------------------- void cWorld3D::DrawMeshBoundingBoxes(const cColor &aColor, bool abStatic) { tMeshEntityListIt It = mlstMeshEntities.begin(); for (; It != mlstMeshEntities.end(); ++It) { cMeshEntity *pEntity = *It; if (abStatic == false && pEntity->IsStatic()) continue; cBoundingVolume *pBV = pEntity->GetBoundingVolume(); mpGraphics->GetLowLevel()->DrawBoxMaxMin(pBV->GetMax(), pBV->GetMin(), aColor); } } //----------------------------------------------------------------------- cLight3DPoint *cWorld3D::CreateLightPoint(const tString &asName, bool abAddToContainer) { cLight3DPoint *pLight = hplNew(cLight3DPoint, (asName, mpResources)); mlstLights.push_back(pLight); if (abAddToContainer) mpPortalContainer->Add(pLight, false); pLight->SetWorld3D(this); return pLight; } //----------------------------------------------------------------------- cLight3DSpot *cWorld3D::CreateLightSpot(const tString &asName, const tString &asGobo, bool abAddToContainer) { cLight3DSpot *pLight = hplNew(cLight3DSpot, (asName, mpResources)); mlstLights.push_back(pLight); if (asGobo != "") { iTexture *pTexture = mpResources->GetTextureManager()->Create2D(asGobo, true); if (pTexture != NULL) pLight->SetTexture(pTexture); else Warning("Couldn't load texture '%s' for light '%s'", asGobo.c_str(), asName.c_str()); } if (abAddToContainer) mpPortalContainer->Add(pLight, false); pLight->SetWorld3D(this); return pLight; } //----------------------------------------------------------------------- void cWorld3D::DestroyLight(iLight3D *apLight) { mpPortalContainer->Remove(apLight); STLFindAndDelete(mlstLights, apLight); } //----------------------------------------------------------------------- iLight3D *cWorld3D::GetLight(const tString &asName) { tLight3DListIt LightIt = mlstLights.begin(); for (; LightIt != mlstLights.end(); ++LightIt) { if ((*LightIt)->GetName() == asName) { return *LightIt; } } return NULL; } //----------------------------------------------------------------------- cBillboard *cWorld3D::CreateBillboard(const tString &asName, const cVector2f &avSize, const tString &asMaterial, bool abAddToContainer, cMatrixf *apTransform) { cBillboard *pBillboard = hplNew(cBillboard, (asName, avSize, mpResources, mpGraphics)); mlstBillboards.push_back(pBillboard); if (apTransform) pBillboard->SetMatrix(*apTransform); if (asMaterial != "") { iMaterial *pMat = mpResources->GetMaterialManager()->CreateMaterial(asMaterial); pBillboard->SetMaterial(pMat); } if (abAddToContainer) mpPortalContainer->Add(pBillboard, false); return pBillboard; } //----------------------------------------------------------------------- void cWorld3D::DestroyBillboard(cBillboard *apObject) { mpPortalContainer->Remove(apObject); STLFindAndDelete(mlstBillboards, apObject); } //----------------------------------------------------------------------- cBillboard *cWorld3D::GetBillboard(const tString &asName) { return (cBillboard *)STLFindByName(mlstBillboards, asName); } //----------------------------------------------------------------------- cBillboardIterator cWorld3D::GetBillboardIterator() { return cBillboardIterator(&mlstBillboards); } //----------------------------------------------------------------------- cBeam *cWorld3D::CreateBeam(const tString &asName) { cBeam *pBeam = hplNew(cBeam, (asName, mpResources, mpGraphics)); mlstBeams.push_back(pBeam); mpPortalContainer->Add(pBeam, false); return pBeam; } //----------------------------------------------------------------------- void cWorld3D::DestroyBeam(cBeam *apObject) { mpPortalContainer->Remove(apObject); STLFindAndDelete(mlstBeams, apObject); } //----------------------------------------------------------------------- cBeam *cWorld3D::GetBeam(const tString &asName) { return (cBeam *)STLFindByName(mlstBeams, asName); } //----------------------------------------------------------------------- cBeamIterator cWorld3D::GetBeamIterator() { return cBeamIterator(&mlstBeams); } //----------------------------------------------------------------------- cParticleSystem3D *cWorld3D::CreateParticleSystem(const tString &asName, const tString &asType, const cVector3f &avSize, const cMatrixf &a_mtxTransform) { cParticleSystem3D *pPS = mpResources->GetParticleManager()->CreatePS3D(asName, asType, avSize, a_mtxTransform); if (pPS == NULL) { Error("Couldn't create particle system '%s' of type '%s'\n", asName.c_str(), asType.c_str()); return NULL; } // Log("Created particle system '%s' of type '%s'\n",asName.c_str(), asType.c_str()); // Add the emitters contained in the system. // Do not add the system itself. for (int i = 0; i < pPS->GetEmitterNum(); ++i) { iParticleEmitter3D *pPE = pPS->GetEmitter(i); mpPortalContainer->Add(pPE, false); pPE->SetWorld(this); } mlstParticleSystems.push_back(pPS); // Log("Created particle system '%s'\n",asType.c_str()); return pPS; } //----------------------------------------------------------------------- void cWorld3D::DestroyParticleSystem(cParticleSystem3D *apPS) { if (apPS == NULL) return; for (int i = 0; i < apPS->GetEmitterNum(); ++i) { iParticleEmitter3D *pPE = apPS->GetEmitter(i); mpPortalContainer->Remove(pPE); } STLFindAndDelete(mlstParticleSystems, apPS); } //----------------------------------------------------------------------- cParticleSystem3D *cWorld3D::GetParticleSystem(const tString &asName) { return (cParticleSystem3D *)STLFindByName(mlstParticleSystems, asName); } //----------------------------------------------------------------------- bool cWorld3D::ParticleSystemExists(cParticleSystem3D *apPS) { tParticleSystem3DListIt it = mlstParticleSystems.begin(); for (; it != mlstParticleSystems.end(); ++it) { if (apPS == *it) return true; } return false; } //----------------------------------------------------------------------- cColliderEntity *cWorld3D::CreateColliderEntity(const tString &asName, iPhysicsBody *apBody) { cColliderEntity *pCollider = hplNew(cColliderEntity, (asName, apBody, mpPhysicsWorld)); mlstColliders.push_back(pCollider); return pCollider; } void cWorld3D::DestroyColliderEntity(cColliderEntity *apCollider) { STLFindAndDelete(mlstColliders, apCollider); } cColliderEntity *cWorld3D::GetColliderEntity(const tString &asName) { return (cColliderEntity *)STLFindByName(mlstColliders, asName); } //----------------------------------------------------------------------- cSoundEntity *cWorld3D::CreateSoundEntity(const tString &asName, const tString &asSoundEntity, bool abRemoveWhenOver) { cSoundEntityData *pData = mpResources->GetSoundEntityManager()->CreateSoundEntity(asSoundEntity); if (pData == NULL) { Error("Cannot find sound entity '%s'\n", asSoundEntity.c_str()); return NULL; } cSoundEntity *pSound = hplNew(cSoundEntity, (asName, pData, mpResources->GetSoundEntityManager(), this, mpSound->GetSoundHandler(), abRemoveWhenOver)); mlstSoundEntities.push_back(pSound); return pSound; } void cWorld3D::DestroySoundEntity(cSoundEntity *apEntity) { // STLFindAndDelete(mlstSoundEntities,apEntity); tSoundEntityListIt it = mlstSoundEntities.begin(); for (; it != mlstSoundEntities.end(); ++it) { cSoundEntity *pSound = *it; if (pSound == apEntity) { mlstSoundEntities.erase(it); hplDelete(pSound); break; } } } void cWorld3D::DestroyAllSoundEntities() { // Make sure no body has any sound entity if (mpPhysicsWorld) { cPhysicsBodyIterator bodyIt = mpPhysicsWorld->GetBodyIterator(); while (bodyIt.HasNext()) { iPhysicsBody *pBody = bodyIt.Next(); pBody->SetScrapeSoundEntity(NULL); pBody->SetRollSoundEntity(NULL); } cPhysicsJointIterator jointIt = mpPhysicsWorld->GetJointIterator(); while (jointIt.HasNext()) { iPhysicsJoint *pJoint = jointIt.Next(); pJoint->SetSound(NULL); } } // Destroy all sound entities STLDeleteAll(mlstSoundEntities); mlstSoundEntities.clear(); } cSoundEntity *cWorld3D::GetSoundEntity(const tString &asName) { return (cSoundEntity *)STLFindByName(mlstSoundEntities, asName); } bool cWorld3D::SoundEntityExists(cSoundEntity *apEntity) { tSoundEntityListIt it = mlstSoundEntities.begin(); tSoundEntityListIt end = mlstSoundEntities.end(); for (; it != end; ++it) { if (*it == apEntity) return true; } return false; } //----------------------------------------------------------------------- cStartPosEntity *cWorld3D::CreateStartPos(const tString &asName) { cStartPosEntity *pStartPos = hplNew(cStartPosEntity, (asName)); mlstStartPosEntities.push_back(pStartPos); return pStartPos; } cStartPosEntity *cWorld3D::GetStartPosEntity(const tString &asName) { return (cStartPosEntity *)STLFindByName(mlstStartPosEntities, asName); } cStartPosEntity *cWorld3D::GetFirstStartPosEntity() { if (mlstStartPosEntities.empty()) return NULL; return mlstStartPosEntities.front(); } //----------------------------------------------------------------------- void cWorld3D::GenerateAINodes(cAINodeGeneratorParams *apParams) { mpAI->GetNodeGenerator()->Generate(this, apParams); } //----------------------------------------------------------------------- cAINodeContainer *cWorld3D::CreateAINodeContainer(const tString &asName, const tString &asNodeName, const cVector3f &avSize, bool abNodeIsAtCenter, int alMinEdges, int alMaxEdges, float afMaxEdgeDistance, float afMaxHeight) { cAINodeContainer *pContainer = NULL; // unsigned long lStartTime = mpSystem->GetLowLevel()->GetTime(); ////////////////////////////////// // See if the container is already loaded. tAINodeContainerListIt it = mlstAINodeContainers.begin(); for (; it != mlstAINodeContainers.end(); ++it) { cAINodeContainer *pCont = *it; if (pCont->GetName() == asName) { pContainer = pCont; } } ////////////////////////////////// // Get file name cFileSearcher *pFileSearcher = mpResources->GetFileSearcher(); tString sMapPath = pFileSearcher->GetFilePath(GetFileName()); tString sAiFileName = cString::SetFileExt(sMapPath, ""); sAiFileName += "_" + asName; sAiFileName = cString::SetFileExt(sAiFileName, "nodes"); ////////////////////////////////// // If there is no container created, create it. if (pContainer == NULL) { tTempNodeContainerMapIt ContIt = m_mapTempNodes.find(asNodeName); if (ContIt == m_mapTempNodes.end()) { Warning("AI node type '%s' does not exist!\n", asNodeName.c_str()); return NULL; } cTempNodeContainer *pTempCont = ContIt->second; pContainer = hplNew(cAINodeContainer, (asName, asNodeName, this, avSize)); mlstAINodeContainers.push_back(pContainer); // Set properties pContainer->SetMinEdges(alMinEdges); pContainer->SetMaxEdges(alMaxEdges); pContainer->SetMaxEdgeDistance(afMaxEdgeDistance); pContainer->SetMaxHeight(afMaxHeight); pContainer->SetNodeIsAtCenter(abNodeIsAtCenter); // Reserve space for the incoming nodes. pContainer->ReserveSpace(pTempCont->mlstNodes.size()); // Add nodes to container tTempAiNodeListIt NodeIt = pTempCont->mlstNodes.begin(); for (; NodeIt != pTempCont->mlstNodes.end(); ++NodeIt) { cTempAiNode &pNode = *NodeIt; pContainer->AddNode(pNode.msName, pNode.mvPos, NULL); } bool bLoadedFromFile = false; if (FileExists(cString::To16Char(sAiFileName))) { cDate dateMapFile = FileModifiedDate(cString::To16Char(sMapPath)); cDate dateAIFile = FileModifiedDate(cString::To16Char(sAiFileName)); if (dateAIFile > dateMapFile) { bLoadedFromFile = true; pContainer->LoadFromFile(sAiFileName); } } if (bLoadedFromFile == false) { Log("Rebuilding node connections and saving to '%s'\n", sAiFileName.c_str()); // Compile pContainer->Compile(); // Save to disk pContainer->SaveToFile(sAiFileName); } } // unsigned long lTime = mpSystem->GetLowLevel()->GetTime() - lStartTime; // Log("Creating ai nodes took: %d\n",lTime); return pContainer; } //----------------------------------------------------------------------- cAStarHandler *cWorld3D::CreateAStarHandler(cAINodeContainer *apContainer) { cAStarHandler *pAStar = hplNew(cAStarHandler, (apContainer)); mlstAStarHandlers.push_back(pAStar); return pAStar; } //----------------------------------------------------------------------- void cWorld3D::AddAINode(const tString &asName, const tString &asType, const cVector3f &avPosition) { cTempNodeContainer *pContainer = NULL; tTempNodeContainerMapIt it = m_mapTempNodes.find(asType); if (it != m_mapTempNodes.end()) { pContainer = it->second; } if (pContainer == NULL) { pContainer = hplNew(cTempNodeContainer, ()); m_mapTempNodes.insert(tTempNodeContainerMap::value_type(asType, pContainer)); } pContainer->mlstNodes.push_back(cTempAiNode(avPosition, asName)); } //----------------------------------------------------------------------- tTempAiNodeList *cWorld3D::GetAINodeList(const tString &asType) { cTempNodeContainer *pContainer = NULL; tTempNodeContainerMapIt it = m_mapTempNodes.find(asType); if (it != m_mapTempNodes.end()) { pContainer = it->second; } if (pContainer == NULL) { pContainer = hplNew(cTempNodeContainer, ()); m_mapTempNodes.insert(tTempNodeContainerMap::value_type(asType, pContainer)); } return &pContainer->mlstNodes; } //----------------------------------------------------------------------- bool cWorld3D::CreateFromFile(tString asFile) { return false; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cWorld3D::UpdateParticles(float afTimeStep) { tParticleSystem3DListIt it = mlstParticleSystems.begin(); while (it != mlstParticleSystems.end()) { cParticleSystem3D *pPS = *it; // Debug: // for(int i=0; i<100;++i) pPS->UpdateLogic(afTimeStep / 100.0f); pPS->UpdateLogic(afTimeStep); // Check if the system is alive, else destroy if (pPS->IsDead()) { // Log("Deleting particle system '%s'", pPS->GetName().c_str()); it = mlstParticleSystems.erase(it); for (int i = 0; i < pPS->GetEmitterNum(); ++i) { mpPortalContainer->Remove(pPS->GetEmitter(i)); } hplDelete(pPS); } else { it++; } } } //----------------------------------------------------------------------- void cWorld3D::UpdateEntities(float afTimeStep) { tMeshEntityListIt MeshIt = mlstMeshEntities.begin(); for (; MeshIt != mlstMeshEntities.end(); MeshIt++) { cMeshEntity *pEntity = *MeshIt; if (pEntity->IsActive()) { // bool bTime = cString::GetLastStringPos(pEntity->GetName(), "infected")>=0; // if(bTime) START_TIMING_EX(pEntity->GetName().c_str(),entity); // Debug: // for(int i=0; i<100;++i) pEntity->UpdateLogic(afTimeStep / 100.0f); pEntity->UpdateLogic(afTimeStep); // if(bTime) STOP_TIMING(entity); } } } //----------------------------------------------------------------------- void cWorld3D::UpdateBodies(float afTimeStep) { } //----------------------------------------------------------------------- void cWorld3D::UpdateLights(float afTimeStep) { tLight3DListIt it = mlstLights.begin(); while (it != mlstLights.end()) { iLight3D *pLight = *it; if (pLight->IsActive()) pLight->UpdateLogic(afTimeStep); ++it; } } //----------------------------------------------------------------------- void cWorld3D::UpdateSoundEntities(float afTimeStep) { tSoundEntityListIt it = mlstSoundEntities.begin(); while (it != mlstSoundEntities.end()) { cSoundEntity *pSound = *it; if (pSound->IsActive()) { // Debug: // for(int i=0; i<100;++i) pSound->UpdateLogic(afTimeStep / 100.0f); pSound->UpdateLogic(afTimeStep); } // Check if the system is stopped, else destroy if (pSound->IsStopped() && pSound->GetRemoveWhenOver()) { it = mlstSoundEntities.erase(it); hplDelete(pSound); } else { it++; } } } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // SAVE OBJECT STUFF ////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------- kBeginSerializeBase(cAreaEntity) kSerializeVar(msName, eSerializeType_String) kSerializeVar(msType, eSerializeType_String) kSerializeVar(m_mtxTransform, eSerializeType_Matrixf) kSerializeVar(mvSize, eSerializeType_Vector3f) kEndSerialize() //------------------------------------------------------------------- kBeginSerializeBase(cStartPosEntity) kSerializeVar(msName, eSerializeType_String) kSerializeVar(m_mtxTransform, eSerializeType_Matrixf) kEndSerialize() //----------------------------------------------------------------------- kBeginSerializeBase(cSaveData_cWorld3D) kSerializeClassContainer(mlstStartpos, cStartPosEntity, eSerializeType_Class) kSerializeClassContainer(mlstAreaEntities, cAreaEntity, eSerializeType_Class) kSerializeClassContainer(mlstScriptVars, cScriptVar, eSerializeType_Class) kEndSerialize() //----------------------------------------------------------------------- iSaveObject *cSaveData_cWorld3D::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) { cWorld3D *pWorld = apGame->GetScene()->GetWorld3D(); /////////////////////// // Start pos cContainerListIterator StartIt = mlstStartpos.GetIterator(); while (StartIt.HasNext()) { cStartPosEntity &tempStart = StartIt.Next(); cStartPosEntity *pStart = pWorld->CreateStartPos(tempStart.GetName()); pStart->SetMatrix(tempStart.GetWorldMatrix()); } /////////////////////// // Area entities cContainerListIterator AreaIt = mlstAreaEntities.GetIterator(); while (AreaIt.HasNext()) { cAreaEntity &tempArea = AreaIt.Next(); cAreaEntity *pArea = pWorld->CreateAreaEntity(tempArea.msName); pArea->m_mtxTransform = tempArea.m_mtxTransform; pArea->msType = tempArea.msType; pArea->mvSize = tempArea.mvSize; } /////////////////////// // Script vars cContainerListIterator VarIt = mlstScriptVars.GetIterator(); while (VarIt.HasNext()) { cScriptVar &tempVar = VarIt.Next(); cScriptVar *pVar = apGame->GetScene()->CreateLocalVar(tempVar.msName); pVar->mlVal = tempVar.mlVal; } return NULL; } //----------------------------------------------------------------------- int cSaveData_cWorld3D::GetSaveCreatePrio() { return 4; } //----------------------------------------------------------------------- iSaveData *cWorld3D::CreateSaveData() { cSaveData_cWorld3D *pData = hplNew(cSaveData_cWorld3D, ()); // Start pos tStartPosEntityListIt StartIt = mlstStartPosEntities.begin(); for (; StartIt != mlstStartPosEntities.end(); ++StartIt) { pData->mlstStartpos.Add(*(*StartIt)); } // Area entities tAreaEntityMapIt AreaIt = m_mapAreaEntities.begin(); for (; AreaIt != m_mapAreaEntities.end(); ++AreaIt) { pData->mlstAreaEntities.Add(*(AreaIt->second)); } // Local scripts tScriptVarMap *pLocalVarMap = mpScene->GetLocalVarMap(); tScriptVarMapIt VarIt = pLocalVarMap->begin(); for (; VarIt != pLocalVarMap->end(); ++VarIt) { pData->mlstScriptVars.Add(VarIt->second); } return pData; } //----------------------------------------------------------------------- } // namespace hpl