#include "StdAfx.h" #ifndef CODE_INGAME #include "LightsManager.h" #include "Terrain.h" #include #include CLightsManager::CLightsManager( CTerrain *pTerrain ) : m_pTerrain( pTerrain ) { m_pkSun = NULL; m_pkFillLight = NULL; } CLightsManager::~CLightsManager(void) { } NiLight* CLightsManager::GetLight(NiEntityInterface *pkEntityInterface) { return m_LightsMap[pkEntityInterface]; } // 从 pkAVObj 中找到 NiLight 节点 NiLight* GetLightNode(NiAVObject* pkAVObj) { if (pkAVObj == NULL) return NULL; NiNode* pkNode = NiDynamicCast(NiNode, pkAVObj); if (pkNode != NULL) { for (int i=0; iGetChildCount(); i++) { NiAVObject* pkChild = pkNode->GetAt(0); NiLight* pkLight = GetLightNode(pkAVObj); if (pkLight) return pkLight; } return NULL; } return NiDynamicCast(NiLight, pkAVObj); } // 从 entity 中获取 NiLight NiLight* GetNiLightFromEntity(NiEntityInterface* pkEntity) { if (pkEntity == NULL) return NULL; NiObject* pkSceneRoot = NULL; if (!pkEntity->GetPropertyData("Scene Root Pointer", pkSceneRoot, 0)) { return NULL; } NiAVObject* pkAVObj = NiDynamicCast(NiAVObject, pkSceneRoot); return GetLightNode(pkAVObj); } bool CLightsManager::AddLight(NiEntityInterface *pkEntityInterface) { NiLight* pkLight = GetNiLightFromEntity(pkEntityInterface); if (pkLight == NULL) return false; NiFixedString strLightType; // 灯光类型 pkEntityInterface->GetPropertyData(LIGHTTYPE, strLightType); NiFixedString strName = pkEntityInterface->GetName(); // 灯光名称 if (strLightType == "Directional") { if (strName == "sun") { m_pkSun = pkLight; } else if (strName == "fill_light") { m_pkFillLight = pkLight; } else if (strName == "character_sun") { return false; } } else if (strLightType == "Point") { } else if (strLightType == "Ambient") { if (strName == "character_ambient") { return false; } /*if (strName == "ch") { m_pkPreview = pkLight; } else { return false; }*/ } else { return false; } /// 把Light放入Map m_LightsMap.insert(map::value_type(pkEntityInterface, pkLight) ); pkLight->AttachAffectedNode( m_pTerrain->GetTerrainRootNode() ); m_pTerrain->GetTerrainRootNode()->UpdateEffects(); pkLight->UpdateEffects(); /* NiLight* pkLight; NiFixedString strLightType; pkEntityInterface->GetPropertyData(LIGHTTYPE, strLightType); if (strLightType == "Directional") { NiDirectionalLight* pkDirectionalLight = NiNew NiDirectionalLight; NiFixedString strName = pkEntityInterface->GetName(); if (strName.ContainsNoCase("sun")) { m_pkSunShadowGenerator = NiNew NiShadowGenerator(pkDirectionalLight); m_pkSunShadowGenerator->SetAutoCalcNearClippingDist(false); m_pkSunShadowGenerator->SetAutoCalcFarClippingDist(false); m_pkSunShadowGenerator->SetNearClippingDist(150.0f); m_pkSunShadowGenerator->SetFarClippingDist(8000.0f); NiFixedString strTech; if (pkEntityInterface->GetPropertyData("Shadow Technique",strTech)) { NiShadowTechnique* pkTech = NiShadowManager::GetActiveShadowTechnique(strTech); m_pkSunShadowGenerator->SetShadowTechnique(pkTech); m_pkSunShadowGenerator->SetDepthBiasToDefault(); NiShadowManager::AddShadowGenerator(m_pkSunShadowGenerator); } } pkLight = pkDirectionalLight; } else if (strLightType == "Point") { NiPointLight* pkPointLight = NiNew NiPointLight; /// SetConstantAttenuation float fParam; pkEntityInterface->GetPropertyData(ATTENUATION_CONSTANT, fParam); pkPointLight->SetConstantAttenuation(fParam); /// SetLinearAttenuation pkEntityInterface->GetPropertyData(ATTENUATION_LINEAR, fParam); pkPointLight->SetLinearAttenuation(fParam); /// SetQuadraticAttenuation pkEntityInterface->GetPropertyData(ATTENUATION_QUADRATIC, fParam); pkPointLight->SetQuadraticAttenuation(fParam); pkLight = pkPointLight; } else if (strLightType == "Spot") { NiSpotLight* pkSpotLight = NiNew NiSpotLight; /// SetSpotAngle float fParam; pkEntityInterface->GetPropertyData(SPOTANGLE_OUTER, fParam); pkSpotLight->SetSpotAngle(fParam); /// SetInnerSpotAngle pkEntityInterface->GetPropertyData(SPOTANGLE_INNER, fParam); pkSpotLight->SetInnerSpotAngle(fParam); /// SetSpotExponent pkEntityInterface->GetPropertyData(SPOT_EXPONENT, fParam); pkSpotLight->SetSpotExponent(fParam); pkLight = pkSpotLight; } else if (strLightType == "Ambient") { pkLight = NiNew NiAmbientLight; } else { return false; } /// SetDimmer float fDimmer; pkEntityInterface->GetPropertyData(DIMMER, fDimmer); pkLight->SetDimmer(fDimmer); /// SetAmbientColor NiColor kColor; pkEntityInterface->GetPropertyData(COLOR_AMBIENT, kColor); pkLight->SetAmbientColor(kColor); /// SetDiffuseColor pkEntityInterface->GetPropertyData(COLOR_DIFFUSE, kColor); pkLight->SetDiffuseColor(kColor); /// SetSpecularColor pkEntityInterface->GetPropertyData(COLOR_SPECULAR, kColor); pkLight->SetSpecularColor(kColor); /// 六个自由度 NiPoint3 vPos; NiMatrix3 vRot; float fScale; pkEntityInterface->GetPropertyData(TRANSLATION, vPos); pkEntityInterface->GetPropertyData(ROTATION, vRot); pkEntityInterface->GetPropertyData(SCALE, fScale); pkLight->SetWorldTranslate(vPos); pkLight->SetRotate(vRot); pkLight->SetWorldScale(fScale); pkLight->Update(0.0f); /// 把Light放入Map m_LightsMap.insert(map::value_type(pkEntityInterface, pkLight) ); pkLight->AttachAffectedNode( m_pTerrain->GetTerrainRootNode() ); m_pTerrain->GetTerrainRootNode()->UpdateEffects(); NiFixedString strTrans(TRANSLATION); UpdateLight(pkEntityInterface, strTrans); */ return true; } //--------------------------------------------------------------------------- struct CollectGeometryFunctor { std::set* m_arrUnaffectList; CollectGeometryFunctor(std::set* arrUnaffectList) { m_arrUnaffectList = arrUnaffectList; } bool operator() (NiAVObject* pkObject) { NiGeometry* pkGeom = NiDynamicCast(NiGeometry, pkObject); if (pkGeom) { m_arrUnaffectList->insert(pkGeom); } return true; // continue travel } }; //--------------------------------------------------------------------------- void CLightsManager::BuildUnaffectCasterList(NiDirectionalLight* pkSun) { if (!pkSun) { return; } m_UnaffectCasterList.clear(); NiShadowGenerator* pkShadowGen = pkSun->GetShadowGenerator(); if (!pkShadowGen) return; // shadow generator 中的不投射阴影列表 const NiNodeList& kNodeList = pkShadowGen->GetUnaffectedCasterNodeList(); NiTListIterator kIter = kNodeList.GetHeadPos(); while (kIter) { NiNode* pkNode = kNodeList.GetNext(kIter); CollectGeometryFunctor kFunctor(&m_UnaffectCasterList); NiTNodeTraversal::DepthFirst_AllObjects(pkNode, kFunctor); } } //--------------------------------------------------------------------------- void CLightsManager::BuildUnaffectReceiverList(NiDirectionalLight* pkSun) { if (!pkSun) { return; } m_UnaffectReceiverList.clear(); NiShadowGenerator* pkShadowGen = pkSun->GetShadowGenerator(); if (!pkShadowGen) return; // shadow generator 中的不接受阴影列表 const NiNodeList& kNodeList = pkShadowGen->GetUnaffectedReceiverNodeList(); NiTListIterator kIter = kNodeList.GetHeadPos(); while (kIter) { NiNode* pkNode = kNodeList.GetNext(kIter); CollectGeometryFunctor kFunctor(&m_UnaffectReceiverList); NiTNodeTraversal::DepthFirst_AllObjects(pkNode, kFunctor); } } //--------------------------------------------------------------------------- void CLightsManager::UpdateLight(NiEntityInterface* pkEntityInterface, NiFixedString& pkPropertyName) { if (pkEntityInterface != NULL) { m_LightsMap[pkEntityInterface]->Update( .0f ); } // 如果是 sun 的 unaffected caster list 发生改变,重新构建本地 UnaffectCasterList //if (pkEntityInterface->GetName()=="sun" // && pkPropertyName == "Unaffected Casters") //{ // NiObject* pkObj; // pkEntityInterface->GetPropertyData("Scene Root Pointer", pkObj); // NiDirectionalLight* pkSun = NiDynamicCast(NiDirectionalLight, pkObj); // if (pkSun) // { // BuildUnaffectCasterList(pkSun); // } //} } void CLightsManager::RefreshAllLights() { map::iterator iter; // Add all lights affects //map::iterator iter; int iNumUpdate = 9; // 只更新前9盏灯 for (iter = m_LightsMap.begin(); iter!=m_LightsMap.end(); iter++) { NiLight* pkLight = iter->second; pkLight->AttachAffectedNode( m_pTerrain->GetTerrainRootNode() ); m_pTerrain->GetTerrainRootNode()->UpdateEffects(); pkLight->UpdateEffects(); if (iNumUpdate--<=0) break; } RefreshSunLight(); } void CLightsManager::RefreshSunLight() { if (m_pTerrain == NULL) return; if (m_pkSun != NULL ) { m_pkSun->AttachAffectedNode( m_pTerrain->GetTerrainRootNode() ); m_pTerrain->GetTerrainRootNode()->UpdateEffects(); m_pkSun->UpdateEffects(); } if (m_pkFillLight != NULL ) { m_pkFillLight->AttachAffectedNode( m_pTerrain->GetTerrainRootNode() ); m_pTerrain->GetTerrainRootNode()->UpdateEffects(); m_pkSun->UpdateEffects(); } } bool CLightsManager::RemoveLight(NiEntityInterface* pkEntityInterface) { map::iterator iter; iter = m_LightsMap.find(pkEntityInterface); if ( iter != m_LightsMap.end() ) { iter->second->DetachAffectedNode( m_pTerrain->GetTerrainRootNode() ); m_pTerrain->GetTerrainRootNode()->UpdateEffects(); //NiDelete iter->second; m_LightsMap.erase(pkEntityInterface); if (pkEntityInterface->GetName() == "sun") {m_pkSun = NULL;} else if (pkEntityInterface->GetName() == "fill_light") {m_pkFillLight = NULL;} return true; } else { return false; } } void CLightsManager::RemoveAllLights() { map::iterator iter; for (iter = m_LightsMap.begin(); iter!=m_LightsMap.end(); iter++) { iter->second->DetachAffectedNode( m_pTerrain->GetTerrainRootNode() ); m_pTerrain->GetTerrainRootNode()->UpdateEffects(); //NiDelete iter->second; } m_LightsMap.clear(); m_pkSun = NULL; m_pkFillLight = NULL; } bool CLightsManager::IsExited(NiEntityInterface* pkEntityInterface) { map::iterator it = m_LightsMap.find(pkEntityInterface); if (it == m_LightsMap.end()) { return false; } else { return true; } } #endif