void CGlobalRendering::UpdateSunParams(float4 newSunDir, float startAngle, float orbitTime, bool iscompat) { newSunDir.ANormalize(); sunStartAngle = startAngle; sunOrbitTime = orbitTime; initialSunAngle = fastmath::coords2angle(newSunDir.x, newSunDir.z); if(iscompat) { // backwards compatible: sunDir is position where sun reaches highest altitude float sunLen = newSunDir.Length2D(); float sunAzimuth = (sunLen <= 0.001f) ? PI / 2.0f : atan(newSunDir.y / sunLen); float sunHeight = tan(sunAzimuth - 0.001f); float orbitMinSunHeight = 0.1f; // the lowest sun altitude for an auto generated orbit float3 v1(cos(initialSunAngle), sunHeight, sin(initialSunAngle)); v1.ANormalize(); if(v1.y <= orbitMinSunHeight) { newSunDir = float3(0.0f, 1.0f, 0.0f); sunOrbitHeight = v1.y; sunOrbitRad = sqrt(1.0f - sunOrbitHeight * sunOrbitHeight); } else { float3 v2(cos(initialSunAngle + PI), orbitMinSunHeight, sin(initialSunAngle + PI)); v2.ANormalize(); float3 v3 = v2 - v1; sunOrbitRad = v3.Length() / 2.0f; v3.ANormalize(); float3 v4 = v3.cross(float3(0.0f, 1.0f, 0.0f)); v4.ANormalize(); float3 v5 = v3.cross(v4); v5.ANormalize(); if(v5.y < 0) v5 = -v5; newSunDir = v5; sunOrbitHeight = v5.dot(v1); } } else { // new: sunDir is center position of orbit, and sunDir.w is orbit height sunOrbitHeight = std::max(-1.0f, std::min(newSunDir.w, 1.0f)); sunOrbitRad = sqrt(1.0f - sunOrbitHeight * sunOrbitHeight); } sunRotation.LoadIdentity(); sunRotation.SetUpVector(newSunDir); float4 peakSunDir = CalculateSunDir(0.0f); shadowDensityFactor = 1.0f / std::max(0.01f, peakSunDir.y); UpdateSun(true); }
void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { switch (event) { case eFE_Initialize: { m_blending = false; m_paused = false; break; } case eFE_Activate: { ITimeOfDay* pTOD = gEnv->p3DEngine->GetTimeOfDay(); if (!pTOD) break; if (IsPortActive(pActInfo,IN_START)) { pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, true ); m_durationLeft = GetPortFloat( pActInfo, IN_DURATION ); m_sunTimeToUpdate = GetPortFloat( pActInfo, IN_SUN_POSITION_UPDATE_INTERVAL ); m_TODTimeToUpdate = GetPortFloat( pActInfo, IN_TOD_FORCE_UPDATE_INTERVAL ); m_startSunLongitude = pTOD->GetSunLongitude(); m_startSunLatitude = pTOD->GetSunLatitude(); m_startTOD = pTOD->GetTime(); m_blending = true; m_paused = false; m_activeID = m_ID; } if (IsPortActive(pActInfo,IN_PAUSE)) { if (m_blending) { m_paused = !m_paused; pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, !m_paused ); } } break; } case eFE_Update: { if (m_activeID!=m_ID) { pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, false ); m_blending = false; break; } ITimeOfDay* pTOD = gEnv->p3DEngine->GetTimeOfDay(); if (!pTOD) break; m_durationLeft -= gEnv->pTimer->GetFrameTime(); bool forceUpdate = false; if (m_durationLeft<=0) { m_durationLeft = 0; m_blending = false; pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, false ); ActivateOutput( pActInfo, OUT_DONE, true ); forceUpdate = true; m_activeID = 0xffffffff; } float totalDuration = GetPortFloat(pActInfo, IN_DURATION); float blendPos = totalDuration==0 ? 1.f : 1.f - (m_durationLeft / totalDuration); bool needUpdate = UpdateTOD( blendPos, pActInfo, pTOD, forceUpdate ); needUpdate |= UpdateSun( blendPos, pActInfo, pTOD, forceUpdate ); if (needUpdate) pTOD->Update( true, true ); break; } } }