You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/Cry3DEngine/TimeOfDay.cpp

1254 lines
49 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "Cry3DEngine_precompiled.h"
#include <AzCore/Debug/Trace.h>
#include "TimeOfDay.h"
#include "Ocean.h"
#include "IPostEffectGroup.h"
#include <ISplines.h>
#include <IRemoteCommand.h>
#include "EnvironmentPreset.h"
#include <Environment/OceanEnvironmentBus.h>
// Maximum number of minutes in a day converted to a float value
static const float s_maxTime = ((24 * 60) - 1) / 60.0f;
class CBezierSplineFloat
: public spline::CBaseSplineInterpolator<float, spline::BezierSpline<float> >
{
public:
float m_fMinValue;
float m_fMaxValue;
virtual int GetNumDimensions() { return 1; };
virtual void Interpolate(float time, ValueType& value)
{
value_type v;
if (interpolate(time, v))
{
ToValueType(v, value);
}
// Clamp values
//value[0] = clamp_tpl(value[0],m_fMinValue,m_fMaxValue);
}
//////////////////////////////////////////////////////////////////////////
void SerializeSpline(XmlNodeRef& node, bool bLoading)
{
if (bLoading)
{
string keystr = node->getAttr("Keys");
resize(0);
int curPos = 0;
uint32 nKeys = 0;
string key = keystr.Tokenize(",", curPos);
while (!key.empty())
{
++nKeys;
key = keystr.Tokenize(",", curPos);
}
reserve_keys(nKeys);
curPos = 0;
key = keystr.Tokenize(",", curPos);
while (!key.empty())
{
float time, v;
int flags = 0;
int res = azsscanf(key, "%g:%g:%d", &time, &v, &flags);
if (res != 3)
{
res = azsscanf(key, "%g:%g", &time, &v);
if (res != 2)
{
continue;
}
}
ValueType val;
val[0] = v;
int keyIndex = InsertKey(time, val);
SetKeyFlags(keyIndex, flags);
key = keystr.Tokenize(",", curPos);
}
}
else
{
string keystr;
string skey;
for (int i = 0; i < num_keys(); i++)
{
skey.Format("%g:%g:%d,", key(i).time, key(i).value, key(i).flags);
keystr += skey;
}
node->setAttr("Keys", keystr);
}
}
};
//////////////////////////////////////////////////////////////////////////
class CBezierSplineVec3
: public spline::CBaseSplineInterpolator<Vec3, spline::BezierSpline<Vec3> >
{
public:
virtual int GetNumDimensions() { return 3; };
virtual void Interpolate(float time, ValueType& value)
{
value_type v;
if (interpolate(time, v))
{
ToValueType(v, value);
}
// Clamp for colors.
//value[0] = clamp_tpl(value[0],0.0f,1.0f);
//value[1] = clamp_tpl(value[1],0.0f,1.0f);
//value[2] = clamp_tpl(value[2],0.0f,1.0f);
}
//////////////////////////////////////////////////////////////////////////
void SerializeSpline(XmlNodeRef& node, bool bLoading)
{
if (bLoading)
{
string keystr = node->getAttr("Keys");
resize(0);
int curPos = 0;
uint32 nKeys = 0;
string key = keystr.Tokenize(",", curPos);
while (!key.empty())
{
++nKeys;
key = keystr.Tokenize(",", curPos);
}
reserve_keys(nKeys);
curPos = 0;
key = keystr.Tokenize(",", curPos);
while (!key.empty())
{
float time, val0, val1, val2;
int flags = 0;
int res = azsscanf(key, "%g:(%g:%g:%g):%d,", &time, &val0, &val1, &val2, &flags);
if (res != 5)
{
res = azsscanf(key, "%g:(%g:%g:%g),", &time, &val0, &val1, &val2);
if (res != 4)
{
continue;
}
}
ValueType val;
val[0] = val0;
val[1] = val1;
val[2] = val2;
int keyIndex = InsertKey(time, val);
SetKeyFlags(keyIndex, flags);
key = keystr.Tokenize(",", curPos);
}
}
else
{
string keystr;
string skey;
for (int i = 0; i < num_keys(); i++)
{
skey.Format("%g:(%g:%g:%g):%d,", key(i).time, key(i).value.x, key(i).value.y, key(i).value.z, key(i).flags);
keystr += skey;
}
node->setAttr("Keys", keystr);
}
}
void ClampValues([[maybe_unused]] float fMinValue, [[maybe_unused]] float fMaxValue)
{
for (int i = 0, nkeys = num_keys(); i < nkeys; i++)
{
ValueType val;
if (GetKeyValue(i, val))
{
//val[0] = clamp_tpl(val[0],fMinValue,fMaxValue);
//val[1] = clamp_tpl(val[1],fMinValue,fMaxValue);
//val[2] = clamp_tpl(val[2],fMinValue,fMaxValue);
SetKeyValue(i, val);
}
}
}
};
//////////////////////////////////////////////////////////////////////////
CTimeOfDay::CTimeOfDay()
{
m_pTimer = 0;
SetTimer(gEnv->pTimer);
m_fTime = 12;
m_fEditorTime = 12;
m_bEditMode = false;
m_advancedInfo.fAnimSpeed = 0;
m_advancedInfo.fStartTime = 0;
m_advancedInfo.fEndTime = 24;
m_fHDRMultiplier = 1.f;
m_pTimeOfDaySpeedCVar = gEnv->pConsole->GetCVar("e_TimeOfDaySpeed");
m_pUpdateCallback = 0;
m_sunRotationLatitude = 0;
m_sunRotationLongitude = 0;
m_bPaused = false;
m_bSunLinkedToTOD = true;
memset(m_vars, 0, sizeof(SVariableInfo) * ITimeOfDay::PARAM_TOTAL);
// fill local var list so, sandbox can access var list without level being loaded
// Cryengine supports the notion of environment presets which are set in code that is currently not
// in lumberyard. Therefore, create a default preset here that is used as the only one.
m_defaultPreset = new CEnvironmentPreset;
for (int i = 0; i < PARAM_TOTAL; ++i)
{
const CTimeOfDayVariable* presetVar = m_defaultPreset->GetVar((ETimeOfDayParamID)i);
SVariableInfo& var = m_vars[i];
var.name = presetVar->GetName();
var.displayName = presetVar->GetDisplayName();
var.group = presetVar->GetGroupName();
var.nParamId = i;
var.type = presetVar->GetType();
var.pInterpolator = NULL;
Vec3 presetVal = presetVar->GetValue();
var.fValue[0] = presetVal.x;
const EVariableType varType = presetVar->GetType();
if (varType == TYPE_FLOAT)
{
var.fValue[1] = presetVar->GetMinValue();
var.fValue[2] = presetVar->GetMaxValue();
}
else if (varType == TYPE_COLOR)
{
var.fValue[1] = presetVal.y;
var.fValue[2] = presetVal.z;
}
}
m_pCurrentPreset = m_defaultPreset;
ResetVariables();
}
//////////////////////////////////////////////////////////////////////////
CTimeOfDay::~CTimeOfDay()
{
for (int i = 0; i < GetVariableCount(); i++)
{
switch (m_vars[i].type)
{
case TYPE_FLOAT:
delete (CBezierSplineFloat*)(m_vars[i].pInterpolator);
break;
case TYPE_COLOR:
delete (CBezierSplineVec3*)(m_vars[i].pInterpolator);
break;
}
}
SAFE_DELETE(m_defaultPreset);
}
void CTimeOfDay::SetTimer(ITimer* pTimer)
{
AZ_Assert(pTimer, "Null pointer access in CTimeOfDay::SetTimer!");
m_pTimer = pTimer;
// Update timer for ocean also - Craig
COcean::SetTimer(pTimer);
}
ITimeOfDay::SVariableInfo& CTimeOfDay::GetVar(ETimeOfDayParamID id)
{
AZ_Assert(id == m_vars[id].nParamId, "Wrong ID in CTimeOfDay::GetVar!");
return(m_vars[ id ]);
}
//////////////////////////////////////////////////////////////////////////
bool CTimeOfDay::GetVariableInfo(int nIndex, SVariableInfo& varInfo) const
{
if (nIndex < 0 || nIndex >= GetVariableCount())
{
return false;
}
varInfo = m_vars[nIndex];
return true;
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::SetVariableValue(int nIndex, float fValue[3])
{
if (nIndex < 0 || nIndex >= GetVariableCount())
{
return;
}
m_vars[nIndex].fValue[0] = fValue[0];
m_vars[nIndex].fValue[1] = fValue[1];
m_vars[nIndex].fValue[2] = fValue[2];
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::ResetVariables()
{
if (!m_pCurrentPreset)
{
return;
}
m_pCurrentPreset->ResetVariables();
m_varsMap.clear();
for (int i = 0; i < PARAM_TOTAL; ++i)
{
const CTimeOfDayVariable* presetVar = m_pCurrentPreset->GetVar((ETimeOfDayParamID)i);
SVariableInfo& var = m_vars[i];
var.name = presetVar->GetName();
var.displayName = presetVar->GetDisplayName();
var.group = presetVar->GetGroupName();
var.nParamId = i;
var.type = presetVar->GetType();
SAFE_DELETE(var.pInterpolator);
Vec3 presetVal = presetVar->GetValue();
var.fValue[0] = presetVal.x;
const EVariableType varType = presetVar->GetType();
if (varType == TYPE_FLOAT)
{
var.fValue[1] = presetVar->GetMinValue();
var.fValue[2] = presetVar->GetMaxValue();
CBezierSplineFloat* pSpline = new CBezierSplineFloat;
pSpline->m_fMinValue = var.fValue[1];
pSpline->m_fMaxValue = var.fValue[2];
pSpline->reserve_keys(2);
pSpline->InsertKeyFloat(0, var.fValue[0]);
pSpline->InsertKeyFloat(1, var.fValue[0]);
var.pInterpolator = pSpline;
}
else if (varType == TYPE_COLOR)
{
var.fValue[1] = presetVal.y;
var.fValue[2] = presetVal.z;
CBezierSplineVec3* pSpline = new CBezierSplineVec3;
pSpline->reserve_keys(2);
pSpline->InsertKeyFloat3(0, var.fValue);
pSpline->InsertKeyFloat3(1, var.fValue);
var.pInterpolator = pSpline;
}
m_varsMap[var.name] = var.nParamId;
}
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::SetEnvironmentSettings(const SEnvironmentInfo& envInfo)
{
m_sunRotationLongitude = envInfo.sunRotationLongitude;
m_sunRotationLatitude = envInfo.sunRotationLatitude;
m_bSunLinkedToTOD = envInfo.bSunLinkedToTOD;
}
//////////////////////////////////////////////////////////////////////////
// Time of day is specified in hours.
void CTimeOfDay::SetTime(float fHour, bool bForceUpdate, bool bEnvUpdate)
{
// set new time
m_fTime = fHour;
// Change time variable.
Cry3DEngineBase::GetCVars()->e_TimeOfDay = m_fTime;
Update(true, bForceUpdate, bEnvUpdate);
gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_TIME_OF_DAY_SET, 0, 0);
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::SetSunPos(float longitude, float latitude)
{
m_sunRotationLongitude = longitude;
m_sunRotationLatitude = latitude;
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::Update(bool bInterpolate, bool bForceUpdate, bool bEnvUpdate)
{
FUNCTION_PROFILER(gEnv->pSystem, PROFILE_3DENGINE);
if (bInterpolate)
{
if (m_pUpdateCallback)
{
m_pUpdateCallback->BeginUpdate();
}
// normalized time for interpolation
float t = m_fTime / s_maxTime;
// interpolate all values
for (uint32 i = 0; i < static_cast<uint32>(GetVariableCount()); i++)
{
SVariableInfo& var = m_vars[i];
if (var.pInterpolator)
{
if (var.pInterpolator->GetNumDimensions() == 1)
{
var.pInterpolator->InterpolateFloat(t, var.fValue[0]);
}
else if (var.pInterpolator->GetNumDimensions() == 3)
{
var.pInterpolator->InterpolateFloat3(t, var.fValue);
}
if (m_pUpdateCallback)
{
const int dim = var.pInterpolator->GetNumDimensions();
float customValues[3] = {0, 0, 0};
float blendWeight = 0;
if (m_pUpdateCallback->GetCustomValue((ETimeOfDayParamID) var.nParamId, dim, customValues, blendWeight))
{
AZ_Assert(blendWeight >= 0 && blendWeight <= 1, "blendweight outside 0 and 1 in CTimeOfDay::Update!");
blendWeight = clamp_tpl(blendWeight, 0.0f, 1.0f);
for (int j = 0; j < dim; ++j)
{
var.fValue[j] = var.fValue[j] + blendWeight * (customValues[j] - var.fValue[j]);
}
}
}
switch (var.type)
{
case TYPE_FLOAT:
{
var.fValue[0] = clamp_tpl(var.fValue[0], var.fValue[1], var.fValue[2]);
if (fabs(var.fValue[0]) < 1e-10f)
{
var.fValue[0] = 0.0f;
}
break;
}
case TYPE_COLOR:
{
var.fValue[0] = clamp_tpl(var.fValue[0], 0.0f, 1.0f);
var.fValue[1] = clamp_tpl(var.fValue[1], 0.0f, 1.0f);
var.fValue[2] = clamp_tpl(var.fValue[2], 0.0f, 1.0f);
break;
}
default:
{
AZ_Error("TimeOfDay", false, "Invalid TimeOfDay object during CTimeOfDay::Update!");
}
}
}
}
if (m_pUpdateCallback)
{
m_pUpdateCallback->EndUpdate();
}
}
// update environment lighting according to new interpolated values
if (bEnvUpdate)
{
UpdateEnvLighting(bForceUpdate);
}
}
Vec3 ConvertIlluminanceToLightColor(float illuminance, Vec3 colorRGB)
{
illuminance /= RENDERER_LIGHT_UNIT_SCALE;
ColorF color(colorRGB);
color.adjust_luminance(illuminance);
// Divide by PI as this is not done in the BRDF at the moment
Vec3 finalColor = color.toVec3() / gf_PI;
return finalColor;
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::UpdateEnvLighting(bool forceUpdate)
{
C3DEngine* p3DEngine((C3DEngine*)gEnv->p3DEngine);
IRenderer* pRenderer(gEnv->pRenderer);
IPostEffectGroup* postEffectGroup = p3DEngine->GetPostEffectBaseGroup();
const float fRecip255 = 1.0f / 255.0f;
bool bHDRModeEnabled = false;
pRenderer->EF_Query(EFQ_HDRModeEnabled, bHDRModeEnabled);
if (bHDRModeEnabled)
{
const Vec3 vEyeAdaptationParams(GetVar(PARAM_HDR_EYEADAPTATION_EV_MIN).fValue[ 0 ],
GetVar(PARAM_HDR_EYEADAPTATION_EV_MAX).fValue[ 0 ],
GetVar(PARAM_HDR_EYEADAPTATION_EV_AUTO_COMPENSATION).fValue[ 0 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_HDR_EYEADAPTATION_PARAMS, vEyeAdaptationParams);
const Vec3 vEyeAdaptationParamsLegacy(GetVar(PARAM_HDR_EYEADAPTATION_SCENEKEY).fValue[ 0 ],
GetVar(PARAM_HDR_EYEADAPTATION_MIN_EXPOSURE).fValue[ 0 ],
GetVar(PARAM_HDR_EYEADAPTATION_MAX_EXPOSURE).fValue[ 0 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_HDR_EYEADAPTATION_PARAMS_LEGACY, vEyeAdaptationParamsLegacy);
float fHDRShoulderScale(GetVar(PARAM_HDR_FILMCURVE_SHOULDER_SCALE).fValue[ 0 ]);
float fHDRMidtonesScale(GetVar(PARAM_HDR_FILMCURVE_LINEAR_SCALE).fValue[ 0 ]);
float fHDRToeScale(GetVar(PARAM_HDR_FILMCURVE_TOE_SCALE).fValue[ 0 ]);
float fHDRWhitePoint(GetVar(PARAM_HDR_FILMCURVE_WHITEPOINT).fValue[ 0 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_HDR_FILMCURVE_SHOULDER_SCALE, Vec3(fHDRShoulderScale, 0, 0));
p3DEngine->SetGlobalParameter(E3DPARAM_HDR_FILMCURVE_LINEAR_SCALE, Vec3(fHDRMidtonesScale, 0, 0));
p3DEngine->SetGlobalParameter(E3DPARAM_HDR_FILMCURVE_TOE_SCALE, Vec3(fHDRToeScale, 0, 0));
p3DEngine->SetGlobalParameter(E3DPARAM_HDR_FILMCURVE_WHITEPOINT, Vec3(fHDRWhitePoint, 0, 0));
float fHDRBloomAmount(GetVar(PARAM_HDR_BLOOM_AMOUNT).fValue[ 0 ]);
postEffectGroup->SetParam("Global_User_HDRBloom", fHDRBloomAmount);
float fHDRSaturation(GetVar(PARAM_HDR_COLORGRADING_COLOR_SATURATION).fValue[ 0 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_HDR_COLORGRADING_COLOR_SATURATION, Vec3(fHDRSaturation, 0, 0));
Vec3 vColorBalance(GetVar(PARAM_HDR_COLORGRADING_COLOR_BALANCE).fValue[ 0 ],
GetVar(PARAM_HDR_COLORGRADING_COLOR_BALANCE).fValue[ 1 ],
GetVar(PARAM_HDR_COLORGRADING_COLOR_BALANCE).fValue[ 2 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_HDR_COLORGRADING_COLOR_BALANCE, vColorBalance);
}
pRenderer->SetShadowJittering(GetVar(PARAM_SHADOW_JITTERING).fValue[ 0 ]);
float sunMultiplier(1.0f);
float sunSpecMultiplier(GetVar(PARAM_SUN_SPECULAR_MULTIPLIER).fValue[ 0 ]);
float fogMultiplier(GetVar(PARAM_FOG_COLOR_MULTIPLIER).fValue[ 0 ]);
float fogMultiplier2(GetVar(PARAM_FOG_COLOR2_MULTIPLIER).fValue[ 0 ]);
float fogMultiplierRadial(GetVar(PARAM_FOG_RADIAL_COLOR_MULTIPLIER).fValue[ 0 ]);
float nightSkyHorizonMultiplier(GetVar(PARAM_NIGHSKY_HORIZON_COLOR_MULTIPLIER).fValue[ 0 ]);
float nightSkyZenithMultiplier(GetVar(PARAM_NIGHSKY_ZENITH_COLOR_MULTIPLIER).fValue[ 0 ]);
float nightSkyMoonMultiplier(GetVar(PARAM_NIGHSKY_MOON_COLOR_MULTIPLIER).fValue[ 0 ]);
float nightSkyMoonInnerCoronaMultiplier(GetVar(PARAM_NIGHSKY_MOON_INNERCORONA_COLOR_MULTIPLIER).fValue[ 0 ]);
float nightSkyMoonOuterCoronaMultiplier(GetVar(PARAM_NIGHSKY_MOON_OUTERCORONA_COLOR_MULTIPLIER).fValue[ 0 ]);
// set sun position
Vec3 sunPos;
if (m_bSunLinkedToTOD)
{
float timeAng(((m_fTime + 12.0f) / s_maxTime) * gf_PI * 2.0f);
float sunRot = gf_PI * (-m_sunRotationLatitude) / 180.0f;
float longitude = 0.5f * gf_PI - gf_PI * m_sunRotationLongitude / 180.0f;
Matrix33 a, b, c, m;
a.SetRotationZ(timeAng);
b.SetRotationX(longitude);
c.SetRotationY(sunRot);
m = a * b * c;
sunPos = Vec3(0, 1, 0) * m;
float h = sunPos.z;
sunPos.z = sunPos.y;
sunPos.y = -h;
}
else // when not linked, it behaves like the moon
{
float sunLati(-gf_PI + gf_PI* m_sunRotationLatitude / 180.0f);
float sunLong(0.5f * gf_PI - gf_PI* m_sunRotationLongitude / 180.0f);
float sinLon(sinf(sunLong));
float cosLon(cosf(sunLong));
float sinLat(sinf(sunLati));
float cosLat(cosf(sunLati));
sunPos = Vec3(sinLon * cosLat, sinLon * sinLat, cosLon);
}
Vec3 sunPosOrig = sunPos;
// transition phase for sun/moon lighting
AZ_Assert(p3DEngine->m_dawnStart <= p3DEngine->m_dawnEnd, "Invalid sun/moon transition parameters in CTimeOfDay::UpdateEnvLighting!");
AZ_Assert(p3DEngine->m_duskStart <= p3DEngine->m_duskEnd, "Invalid sun/moon transition parameters in CTimeOfDay::UpdateEnvLighting!");
AZ_Assert(p3DEngine->m_dawnEnd <= p3DEngine->m_duskStart, "Invalid sun/moon transition parameters in CTimeOfDay::UpdateEnvLighting!");
float sunIntensityMultiplier(1.0f);
// The ratio between night and day for adjusting luminance. Day = 1, Night = 0, transitions = [0..1]
float dayNightIndicator(1.0);
// The ratio [0..1] relative to high noon which represents maximum luminance.
float midDayIndicator(1.0);
if (m_fTime < p3DEngine->m_dawnStart || m_fTime >= p3DEngine->m_duskEnd)
{ // Night time
p3DEngine->GetGlobalParameter(E3DPARAM_NIGHSKY_MOON_DIRECTION, sunPos);
sunIntensityMultiplier = 0.0f;
midDayIndicator = 0.0f;
dayNightIndicator = 0.0f;
}
else
{ // Dawn, day and dusk time
// Calculating the energy multiplier where mid-day sun is 1.0 and night is 0
const float noonTime = 12.0f;
float dayTime = p3DEngine->m_duskEnd - p3DEngine->m_dawnStart;
if (m_fTime <= noonTime)
{
float dawnToNoon = noonTime - p3DEngine->m_dawnStart;
midDayIndicator = (m_fTime - p3DEngine->m_dawnStart) / dawnToNoon;
}
else
{
float noonToDusk = p3DEngine->m_duskEnd - noonTime;
midDayIndicator = (m_fTime - noonTime) / noonToDusk;
}
midDayIndicator = cos( 0.5f * midDayIndicator * 3.14159265f ); // Converting to the cosine to represent energy distribution
// Calculation of sun intensity and day-to-night indicator
if (m_fTime < p3DEngine->m_dawnEnd)
{
// dawn
AZ_Assert(p3DEngine->m_dawnStart < p3DEngine->m_dawnEnd, "Invalid sun/moon transition parameters in CTimeOfDay::UpdateEnvLighting!");
float b(0.5f * (p3DEngine->m_dawnStart + p3DEngine->m_dawnEnd));
if (m_fTime < b)
{
// fade out moon
sunMultiplier *= (b - m_fTime) / (b - p3DEngine->m_dawnStart);
sunIntensityMultiplier = 0.0f;
p3DEngine->GetGlobalParameter(E3DPARAM_NIGHSKY_MOON_DIRECTION, sunPos);
}
else
{
// fade in sun
float t((m_fTime - b) / (p3DEngine->m_dawnEnd - b));
sunMultiplier *= t;
sunIntensityMultiplier = t;
}
dayNightIndicator = (m_fTime - p3DEngine->m_dawnStart) / (p3DEngine->m_dawnEnd - p3DEngine->m_dawnStart);
}
else if (m_fTime < p3DEngine->m_duskStart)
{
// day
dayNightIndicator = 1.0;
}
else if (m_fTime < p3DEngine->m_duskEnd)
{
// dusk
AZ_Assert(p3DEngine->m_duskStart < p3DEngine->m_duskEnd, "Invalid sun/moon transition parameters in CTimeOfDay::UpdateEnvLighting!");
float b(0.5f * (p3DEngine->m_duskStart + p3DEngine->m_duskEnd));
if (m_fTime < b)
{
// fade out sun
float t((b - m_fTime) / (b - p3DEngine->m_duskStart));
sunMultiplier *= t;
sunIntensityMultiplier = t;
}
else
{
// fade in moon
sunMultiplier *= (m_fTime - b) / (p3DEngine->m_duskEnd - b);
sunIntensityMultiplier = 0.0;
p3DEngine->GetGlobalParameter(E3DPARAM_NIGHSKY_MOON_DIRECTION, sunPos);
}
dayNightIndicator = (p3DEngine->m_duskEnd - m_fTime) / (p3DEngine->m_duskEnd - p3DEngine->m_duskStart);
}
}
sunIntensityMultiplier = max(GetVar(PARAM_SKYLIGHT_SUN_INTENSITY_MULTIPLIER).fValue[0], 0.0f);
p3DEngine->SetGlobalParameter(E3DPARAM_DAY_NIGHT_INDICATOR, Vec3(dayNightIndicator, midDayIndicator, 0));
p3DEngine->SetSunDir(sunPos);
// set sun, sky, and fog color
Vec3 sunColor(Vec3(GetVar(PARAM_SUN_COLOR).fValue[ 0 ],
GetVar(PARAM_SUN_COLOR).fValue[ 1 ], GetVar(PARAM_SUN_COLOR).fValue[ 2 ]));
float sunIntensityLux(GetVar(PARAM_SUN_INTENSITY).fValue[ 0 ] * sunMultiplier);
p3DEngine->SetSunColor(ConvertIlluminanceToLightColor(sunIntensityLux, sunColor));
p3DEngine->SetGlobalParameter(E3DPARAM_SUN_SPECULAR_MULTIPLIER, Vec3(sunSpecMultiplier, 0, 0));
Vec3 fogColor(fogMultiplier* Vec3(GetVar(PARAM_FOG_COLOR).fValue[ 0 ],
GetVar(PARAM_FOG_COLOR).fValue[ 1 ], GetVar(PARAM_FOG_COLOR).fValue[ 2 ]));
p3DEngine->SetFogColor(fogColor);
const Vec3 fogColor2 = fogMultiplier2 * Vec3(GetVar(PARAM_FOG_COLOR2).fValue[0], GetVar(PARAM_FOG_COLOR2).fValue[1], GetVar(PARAM_FOG_COLOR2).fValue[2]);
p3DEngine->SetGlobalParameter(E3DPARAM_FOG_COLOR2, fogColor2);
const Vec3 fogColorRadial = fogMultiplierRadial * Vec3(GetVar(PARAM_FOG_RADIAL_COLOR).fValue[0], GetVar(PARAM_FOG_RADIAL_COLOR).fValue[1], GetVar(PARAM_FOG_RADIAL_COLOR).fValue[2]);
p3DEngine->SetGlobalParameter(E3DPARAM_FOG_RADIAL_COLOR, fogColorRadial);
const Vec3 volFogHeightDensity = Vec3(GetVar(PARAM_VOLFOG_HEIGHT).fValue[0], GetVar(PARAM_VOLFOG_DENSITY).fValue[0], 0);
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG_HEIGHT_DENSITY, volFogHeightDensity);
const Vec3 volFogHeightDensity2 = Vec3(GetVar(PARAM_VOLFOG_HEIGHT2).fValue[0], GetVar(PARAM_VOLFOG_DENSITY2).fValue[0], 0);
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG_HEIGHT_DENSITY2, volFogHeightDensity2);
const Vec3 volFogGradientCtrl = Vec3(GetVar(PARAM_VOLFOG_HEIGHT_OFFSET).fValue[0], GetVar(PARAM_VOLFOG_RADIAL_SIZE).fValue[0], GetVar(PARAM_VOLFOG_RADIAL_LOBE).fValue[0]);
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG_GRADIENT_CTRL, volFogGradientCtrl);
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG_GLOBAL_DENSITY, Vec3(GetVar(PARAM_VOLFOG_GLOBAL_DENSITY).fValue[0], 0, GetVar(PARAM_VOLFOG_FINAL_DENSITY_CLAMP).fValue[0]));
// set volumetric fog ramp
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG_RAMP, Vec3(GetVar(PARAM_VOLFOG_RAMP_START).fValue[0], GetVar(PARAM_VOLFOG_RAMP_END).fValue[0], GetVar(PARAM_VOLFOG_RAMP_INFLUENCE).fValue[0]));
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG_SHADOW_RANGE, Vec3(GetVar(PARAM_VOLFOG_SHADOW_RANGE).fValue[0], 0, 0));
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG_SHADOW_DARKENING, Vec3(GetVar(PARAM_VOLFOG_SHADOW_DARKENING).fValue[0], GetVar(PARAM_VOLFOG_SHADOW_DARKENING_SUN).fValue[0], GetVar(PARAM_VOLFOG_SHADOW_DARKENING_AMBIENT).fValue[0]));
// set HDR sky lighting properties
Vec3 sunIntensity(sunIntensityMultiplier* Vec3(GetVar(PARAM_SKYLIGHT_SUN_INTENSITY).fValue[ 0 ],
GetVar(PARAM_SKYLIGHT_SUN_INTENSITY).fValue[ 1 ], GetVar(PARAM_SKYLIGHT_SUN_INTENSITY).fValue[ 2 ]));
Vec3 rgbWaveLengths(GetVar(PARAM_SKYLIGHT_WAVELENGTH_R).fValue[ 0 ],
GetVar(PARAM_SKYLIGHT_WAVELENGTH_G).fValue[ 0 ], GetVar(PARAM_SKYLIGHT_WAVELENGTH_B).fValue[ 0 ]);
p3DEngine->SetSkyLightParameters(sunPosOrig, sunIntensity, GetVar(PARAM_SKYLIGHT_KM).fValue[ 0 ],
GetVar(PARAM_SKYLIGHT_KR).fValue[ 0 ], GetVar(PARAM_SKYLIGHT_G).fValue[ 0 ], rgbWaveLengths, forceUpdate);
// set night sky color properties
Vec3 nightSkyHorizonColor(nightSkyHorizonMultiplier* Vec3(GetVar(PARAM_NIGHSKY_HORIZON_COLOR).fValue[ 0 ],
GetVar(PARAM_NIGHSKY_HORIZON_COLOR).fValue[ 1 ], GetVar(PARAM_NIGHSKY_HORIZON_COLOR).fValue[ 2 ]));
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_HORIZON_COLOR, nightSkyHorizonColor);
Vec3 nightSkyZenithColor(nightSkyZenithMultiplier* Vec3(GetVar(PARAM_NIGHSKY_ZENITH_COLOR).fValue[ 0 ],
GetVar(PARAM_NIGHSKY_ZENITH_COLOR).fValue[ 1 ], GetVar(PARAM_NIGHSKY_ZENITH_COLOR).fValue[ 2 ]));
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_ZENITH_COLOR, nightSkyZenithColor);
float nightSkyZenithColorShift(GetVar(PARAM_NIGHSKY_ZENITH_SHIFT).fValue[ 0 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_ZENITH_SHIFT, Vec3(nightSkyZenithColorShift, 0, 0));
float nightSkyStarIntensity(GetVar(PARAM_NIGHSKY_START_INTENSITY).fValue[ 0 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_STAR_INTENSITY, Vec3(nightSkyStarIntensity, 0, 0));
Vec3 nightSkyMoonColor(nightSkyMoonMultiplier* Vec3(GetVar(PARAM_NIGHSKY_MOON_COLOR).fValue[ 0 ],
GetVar(PARAM_NIGHSKY_MOON_COLOR).fValue[ 1 ], GetVar(PARAM_NIGHSKY_MOON_COLOR).fValue[ 2 ]));
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_MOON_COLOR, nightSkyMoonColor);
Vec3 nightSkyMoonInnerCoronaColor(nightSkyMoonInnerCoronaMultiplier* Vec3(GetVar(PARAM_NIGHSKY_MOON_INNERCORONA_COLOR).fValue[ 0 ],
GetVar(PARAM_NIGHSKY_MOON_INNERCORONA_COLOR).fValue[ 1 ], GetVar(PARAM_NIGHSKY_MOON_INNERCORONA_COLOR).fValue[ 2 ]));
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_MOON_INNERCORONA_COLOR, nightSkyMoonInnerCoronaColor);
float nightSkyMoonInnerCoronaScale(GetVar(PARAM_NIGHSKY_MOON_INNERCORONA_SCALE).fValue[ 0 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_MOON_INNERCORONA_SCALE, Vec3(nightSkyMoonInnerCoronaScale, 0, 0));
Vec3 nightSkyMoonOuterCoronaColor(nightSkyMoonOuterCoronaMultiplier* Vec3(GetVar(PARAM_NIGHSKY_MOON_OUTERCORONA_COLOR).fValue[ 0 ],
GetVar(PARAM_NIGHSKY_MOON_OUTERCORONA_COLOR).fValue[ 1 ], GetVar(PARAM_NIGHSKY_MOON_OUTERCORONA_COLOR).fValue[ 2 ]));
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_MOON_OUTERCORONA_COLOR, nightSkyMoonOuterCoronaColor);
float nightSkyMoonOuterCoronaScale(GetVar(PARAM_NIGHSKY_MOON_OUTERCORONA_SCALE).fValue[ 0 ]);
p3DEngine->SetGlobalParameter(E3DPARAM_NIGHSKY_MOON_OUTERCORONA_SCALE, Vec3(nightSkyMoonOuterCoronaScale, 0, 0));
// set sun shafts visibility and activate if required
float fSunShaftsVis = GetVar(PARAM_SUN_SHAFTS_VISIBILITY).fValue[ 0 ];
fSunShaftsVis = clamp_tpl<float>(fSunShaftsVis, 0.0f, 0.3f);
float fSunRaysVis = GetVar(PARAM_SUN_RAYS_VISIBILITY).fValue[ 0 ];
float fSunRaysAtten = GetVar(PARAM_SUN_RAYS_ATTENUATION).fValue[ 0 ];
float fSunRaySunColInfluence = GetVar(PARAM_SUN_RAYS_SUNCOLORINFLUENCE).fValue[ 0 ];
float* pSunRaysCustomColorVar = GetVar(PARAM_SUN_RAYS_CUSTOMCOLOR).fValue;
Vec4 pSunRaysCustomColor = Vec4(pSunRaysCustomColorVar[0], pSunRaysCustomColorVar[1], pSunRaysCustomColorVar[2], 1.0f);
postEffectGroup->SetParam("SunShafts_Active", (fSunShaftsVis > 0.05f || fSunRaysVis > 0.05f) ? 1.f : 0.f);
postEffectGroup->SetParam("SunShafts_Amount", fSunShaftsVis);
postEffectGroup->SetParam("SunShafts_RaysAmount", fSunRaysVis);
postEffectGroup->SetParam("SunShafts_RaysAttenuation", fSunRaysAtten);
postEffectGroup->SetParam("SunShafts_RaysSunColInfluence", fSunRaySunColInfluence);
postEffectGroup->SetParam("SunShafts_RaysCustomColor", pSunRaysCustomColor);
{
const Vec3 cloudShadingMultipliers = Vec3(GetVar(PARAM_CLOUDSHADING_SUNLIGHT_MULTIPLIER).fValue[0], 0, 0);
p3DEngine->SetGlobalParameter(E3DPARAM_CLOUDSHADING_MULTIPLIERS, cloudShadingMultipliers);
const float cloudShadingCustomSunColorMult = GetVar(PARAM_CLOUDSHADING_SUNLIGHT_CUSTOM_COLOR_MULTIPLIER).fValue[0];
const Vec3 cloudShadingCustomSunColor = cloudShadingCustomSunColorMult * Vec3(GetVar(PARAM_CLOUDSHADING_SUNLIGHT_CUSTOM_COLOR).fValue[0], GetVar(PARAM_CLOUDSHADING_SUNLIGHT_CUSTOM_COLOR).fValue[1], GetVar(PARAM_CLOUDSHADING_SUNLIGHT_CUSTOM_COLOR).fValue[2]);
const float cloudShadingCustomSunColorInfluence = GetVar(PARAM_CLOUDSHADING_SUNLIGHT_CUSTOM_COLOR_INFLUENCE).fValue[0];
IObjManager* pObjMan = p3DEngine->GetObjectManager();
const Vec3 cloudShadingSunColor = pObjMan ? cloudShadingMultipliers.x* pObjMan->GetSunColor() : Vec3(0, 0, 0);
p3DEngine->SetGlobalParameter(E3DPARAM_CLOUDSHADING_SUNCOLOR, cloudShadingSunColor + (cloudShadingCustomSunColor - cloudShadingSunColor) * cloudShadingCustomSunColorInfluence);
}
bool bHasOceanFeature = false;
AZ::OceanFeatureToggleBus::BroadcastResult(bHasOceanFeature, &AZ::OceanFeatureToggleBus::Events::OceanComponentEnabled);
if (!bHasOceanFeature)
{
// set ocean fog color multiplier
const float oceanFogColorMultiplier = GetVar(PARAM_OCEANFOG_COLOR_MULTIPLIER).fValue[0];
const Vec3 oceanFogColor = Vec3(GetVar(PARAM_OCEANFOG_COLOR).fValue[0], GetVar(PARAM_OCEANFOG_COLOR).fValue[1], GetVar(PARAM_OCEANFOG_COLOR).fValue[2]);
p3DEngine->SetGlobalParameter(E3DPARAM_OCEANFOG_COLOR, oceanFogColor * oceanFogColorMultiplier);
// legacy style: set ocean color density
const float oceanFogColorDensity = GetVar(PARAM_OCEANFOG_DENSITY).fValue[0];
p3DEngine->SetGlobalParameter(E3DPARAM_OCEANFOG_DENSITY, Vec3(oceanFogColorDensity, 0, 0));
}
// set skybox multiplier
float skyBoxMultiplier(GetVar(PARAM_SKYBOX_MULTIPLIER).fValue[ 0 ] * m_fHDRMultiplier);
p3DEngine->SetGlobalParameter(E3DPARAM_SKYBOX_MULTIPLIER, Vec3(skyBoxMultiplier, 0, 0));
// Set color grading stuff
float fValue = GetVar(PARAM_COLORGRADING_FILTERS_GRAIN).fValue[ 0 ];
p3DEngine->SetGlobalParameter(E3DPARAM_COLORGRADING_FILTERS_GRAIN, Vec3(fValue, 0, 0));
Vec4 pColor = Vec4(GetVar(PARAM_COLORGRADING_FILTERS_PHOTOFILTER_COLOR).fValue[ 0 ],
GetVar(PARAM_COLORGRADING_FILTERS_PHOTOFILTER_COLOR).fValue[ 1 ],
GetVar(PARAM_COLORGRADING_FILTERS_PHOTOFILTER_COLOR).fValue[ 2 ], 1.0f);
p3DEngine->SetGlobalParameter(E3DPARAM_COLORGRADING_FILTERS_PHOTOFILTER_COLOR, Vec3(pColor.x, pColor.y, pColor.z));
fValue = GetVar(PARAM_COLORGRADING_FILTERS_PHOTOFILTER_DENSITY).fValue[ 0 ];
p3DEngine->SetGlobalParameter(E3DPARAM_COLORGRADING_FILTERS_PHOTOFILTER_DENSITY, Vec3(fValue, 0, 0));
fValue = GetVar(PARAM_COLORGRADING_DOF_FOCUSRANGE).fValue[ 0 ];
postEffectGroup->SetParam("Dof_Tod_FocusRange", fValue);
fValue = GetVar(PARAM_COLORGRADING_DOF_BLURAMOUNT).fValue[ 0 ];
postEffectGroup->SetParam("Dof_Tod_BlurAmount", fValue);
const float arrDepthConstBias[MAX_SHADOW_CASCADES_NUM] =
{
GetVar(PARAM_SHADOWSC0_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC1_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC2_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC3_BIAS).fValue[ 0 ],
GetVar(PARAM_SHADOWSC4_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC5_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC6_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC7_BIAS).fValue[ 0 ],
2.0f, 2.0f, 2.0f, 2.0f,
2.0f, 2.0f, 2.0f, 2.0f,
2.0f, 2.0f, 2.0f, 2.0f
};
const float arrDepthSlopeBias[MAX_SHADOW_CASCADES_NUM] =
{
GetVar(PARAM_SHADOWSC0_SLOPE_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC1_SLOPE_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC2_SLOPE_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC3_SLOPE_BIAS).fValue[ 0 ],
GetVar(PARAM_SHADOWSC4_SLOPE_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC5_SLOPE_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC6_SLOPE_BIAS).fValue[ 0 ], GetVar(PARAM_SHADOWSC7_SLOPE_BIAS).fValue[ 0 ],
0.5f, 0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f, 0.5f
};
p3DEngine->SetShadowsCascadesBias(arrDepthConstBias, arrDepthSlopeBias);
if (gEnv->IsEditing())
{
p3DEngine->SetRecomputeCachedShadows();
}
// set volumetric fog 2 params
const Vec3 volFogCtrlParams = Vec3(GetVar(PARAM_VOLFOG2_RANGE).fValue[0], GetVar(PARAM_VOLFOG2_BLEND_FACTOR).fValue[0], GetVar(PARAM_VOLFOG2_BLEND_MODE).fValue[0]);
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_CTRL_PARAMS, volFogCtrlParams);
const Vec3 volFogScatteringParams = Vec3(GetVar(PARAM_VOLFOG2_INSCATTER).fValue[0], GetVar(PARAM_VOLFOG2_EXTINCTION).fValue[0], GetVar(PARAM_VOLFOG2_ANISOTROPIC).fValue[0]);
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_SCATTERING_PARAMS, volFogScatteringParams);
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_RAMP, Vec3(GetVar(PARAM_VOLFOG2_RAMP_START).fValue[0], GetVar(PARAM_VOLFOG2_RAMP_END).fValue[0], 0.0f));
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_COLOR, Vec3(GetVar(PARAM_VOLFOG2_COLOR).fValue[0], GetVar(PARAM_VOLFOG2_COLOR).fValue[1], GetVar(PARAM_VOLFOG2_COLOR).fValue[2]));
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_GLOBAL_DENSITY, Vec3(GetVar(PARAM_VOLFOG2_GLOBAL_DENSITY).fValue[0], GetVar(PARAM_VOLFOG2_FINAL_DENSITY_CLAMP).fValue[0], GetVar(PARAM_VOLFOG2_GLOBAL_FOG_VISIBILITY).fValue[0]));
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_HEIGHT_DENSITY, Vec3(GetVar(PARAM_VOLFOG2_HEIGHT).fValue[0], GetVar(PARAM_VOLFOG2_DENSITY).fValue[0], GetVar(PARAM_VOLFOG2_ANISOTROPIC1).fValue[0]));
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_HEIGHT_DENSITY2, Vec3(GetVar(PARAM_VOLFOG2_HEIGHT2).fValue[0], GetVar(PARAM_VOLFOG2_DENSITY2).fValue[0], GetVar(PARAM_VOLFOG2_ANISOTROPIC2).fValue[0]));
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_COLOR1, Vec3(GetVar(PARAM_VOLFOG2_COLOR1).fValue[0], GetVar(PARAM_VOLFOG2_COLOR1).fValue[1], GetVar(PARAM_VOLFOG2_COLOR1).fValue[2]));
p3DEngine->SetGlobalParameter(E3DPARAM_VOLFOG2_COLOR2, Vec3(GetVar(PARAM_VOLFOG2_COLOR2).fValue[0], GetVar(PARAM_VOLFOG2_COLOR2).fValue[1], GetVar(PARAM_VOLFOG2_COLOR2).fValue[2]));
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::SetAdvancedInfo(const SAdvancedInfo& advInfo)
{
m_advancedInfo = advInfo;
if (m_pTimeOfDaySpeedCVar->GetFVal() != m_advancedInfo.fAnimSpeed)
{
m_pTimeOfDaySpeedCVar->Set(m_advancedInfo.fAnimSpeed);
}
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::GetAdvancedInfo(SAdvancedInfo& advInfo)
{
advInfo = m_advancedInfo;
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::MigrateLegacyData(bool bSunIntensity, const XmlNodeRef& node)
{
if (bSunIntensity) // Convert sun intensity as specified up to CE 3.8.2 to illuminance
{
SVariableInfo& varSunIntensity = GetVar(PARAM_SUN_INTENSITY);
SVariableInfo& varSunMult = GetVar(PARAM_SUN_COLOR_MULTIPLIER);
SVariableInfo& varSunColor = GetVar(PARAM_SUN_COLOR);
SVariableInfo& varHDRPower = GetVar(PARAM_HDR_DYNAMIC_POWER_FACTOR);
int numKeys = varSunMult.pInterpolator->GetKeyCount();
for (int key = 0; key < numKeys; ++key)
{
float time = varSunMult.pInterpolator->GetKeyTime(key);
float sunMult, sunColor[3], hdrPower;
varSunMult.pInterpolator->GetKeyValueFloat(key, sunMult);
varSunColor.pInterpolator->InterpolateFloat3(time, sunColor);
varHDRPower.pInterpolator->InterpolateFloat(time, hdrPower);
const float HDRDynamicMultiplier = 2.0f;
float hdrMult = powf(HDRDynamicMultiplier, hdrPower);
float sunColorLum = sunColor[0] * 0.2126f + sunColor[1] * 0.7152f + sunColor[2] * 0.0722f;
float sunIntensity = sunMult * sunColorLum * 10000.0f * gf_PI;
varSunIntensity.pInterpolator->InsertKeyFloat(time, sunIntensity);
}
}
// copy data from old node to new node if old nodes exist.
// this needs to maintain compatibility from CE 3.8.2 to above.
// this should be removed in the future.
string paramOldNameFogAlbedoColor = "Volumetric fog 2: Fog albedo color";
string paramOldNameAnisotropic = "Volumetric fog 2: Anisotropic factor";
for (int i = 0; i < node->getChildCount(); i++)
{
XmlNodeRef varNode = node->getChild(i);
const char* name = varNode->getAttr("Name");
if (paramOldNameFogAlbedoColor.compare(name) == 0)
{
LoadValueFromXmlNode(PARAM_VOLFOG2_COLOR1, varNode);
LoadValueFromXmlNode(PARAM_VOLFOG2_COLOR2, varNode);
LoadValueFromXmlNode(PARAM_VOLFOG2_COLOR, varNode);
}
else if (paramOldNameAnisotropic.compare(name) == 0)
{
LoadValueFromXmlNode(PARAM_VOLFOG2_ANISOTROPIC1, varNode);
LoadValueFromXmlNode(PARAM_VOLFOG2_ANISOTROPIC, varNode);
}
}
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::LoadValueFromXmlNode(ETimeOfDayParamID destId, const XmlNodeRef& varNode)
{
if (destId < 0 || destId >= PARAM_TOTAL)
{
return;
}
XmlNodeRef splineNode = varNode->findChild("Spline");
SVariableInfo& var = GetVar(destId);
switch (var.type)
{
case TYPE_FLOAT:
varNode->getAttr("Value", var.fValue[0]);
if (var.pInterpolator && splineNode != 0)
{
((CBezierSplineFloat*)var.pInterpolator)->SerializeSpline(splineNode, true);
}
break;
case TYPE_COLOR:
{
Vec3 v(var.fValue[0], var.fValue[1], var.fValue[2]);
varNode->getAttr("Color", v);
var.fValue[0] = v.x;
var.fValue[1] = v.y;
var.fValue[2] = v.z;
if (var.pInterpolator && splineNode != 0)
{
CBezierSplineVec3* pBezierSpline = ((CBezierSplineVec3*)var.pInterpolator);
pBezierSpline->SerializeSpline(splineNode, true);
// Clamp colors in case too big colors are provided.
pBezierSpline->ClampValues(-100, 100);
}
}
break;
}
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::Serialize(XmlNodeRef& node, bool bLoading)
{
if (bLoading)
{
node->getAttr("Time", m_fTime);
node->getAttr("TimeStart", m_advancedInfo.fStartTime);
node->getAttr("TimeEnd", m_advancedInfo.fEndTime);
node->getAttr("TimeAnimSpeed", m_advancedInfo.fAnimSpeed);
if (m_pTimeOfDaySpeedCVar->GetFVal() != m_advancedInfo.fAnimSpeed)
{
m_pTimeOfDaySpeedCVar->Set(m_advancedInfo.fAnimSpeed);
}
bool bSunIntensityFound = false;
// Load.
for (int i = 0; i < node->getChildCount(); i++)
{
XmlNodeRef varNode = node->getChild(i);
int nParamId = stl::find_in_map(m_varsMap, varNode->getAttr("Name"), -1);
if (nParamId < 0 || nParamId >= PARAM_TOTAL)
{
continue;
}
if (nParamId == PARAM_SUN_INTENSITY)
{
bSunIntensityFound = true;
}
LoadValueFromXmlNode((ETimeOfDayParamID)nParamId, varNode);
}
MigrateLegacyData(!bSunIntensityFound, node);
SetTime(m_fTime, false);
}
else
{
node->setAttr("Time", m_fTime);
node->setAttr("TimeStart", m_advancedInfo.fStartTime);
node->setAttr("TimeEnd", m_advancedInfo.fEndTime);
node->setAttr("TimeAnimSpeed", m_advancedInfo.fAnimSpeed);
// Save.
for (uint32 i = 0; i < static_cast<uint32>(GetVariableCount()); i++)
{
SVariableInfo& var = m_vars[i];
XmlNodeRef varNode = node->newChild("Variable");
varNode->setAttr("Name", var.name);
switch (var.type)
{
case TYPE_FLOAT:
varNode->setAttr("Value", var.fValue[0]);
if (var.pInterpolator)
{
XmlNodeRef splineNode = varNode->newChild("Spline");
((CBezierSplineFloat*)var.pInterpolator)->SerializeSpline(splineNode, bLoading);
}
break;
case TYPE_COLOR:
varNode->setAttr("Color", Vec3(var.fValue[0], var.fValue[1], var.fValue[2]));
if (var.pInterpolator)
{
XmlNodeRef splineNode = varNode->newChild("Spline");
((CBezierSplineVec3*)var.pInterpolator)->SerializeSpline(splineNode, bLoading);
}
break;
}
}
}
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::Serialize(TSerialize ser)
{
AZ_Assert(ser.GetSerializationTarget() != eST_Network, "Cannot serialize to network error in CTimeOfDay::Serialize");
string tempName;
ser.Value("time", m_fTime);
ser.Value("mode", m_bEditMode);
ser.Value("m_sunRotationLatitude", m_sunRotationLatitude);
ser.Value("m_sunRotationLongitude", m_sunRotationLongitude);
int size = GetVariableCount();
ser.BeginGroup("VariableValues");
for (int v = 0; v < size; v++)
{
tempName = m_vars[v].name;
tempName.replace(' ', '_');
tempName.replace('(', '_');
tempName.replace(')', '_');
tempName.replace(':', '_');
ser.BeginGroup(tempName);
ser.Value("Val0", m_vars[v].fValue[0]);
ser.Value("Val1", m_vars[v].fValue[1]);
ser.Value("Val2", m_vars[v].fValue[2]);
ser.EndGroup();
}
ser.EndGroup();
ser.Value("AdvInfoSpeed", m_advancedInfo.fAnimSpeed);
ser.Value("AdvInfoStart", m_advancedInfo.fStartTime);
ser.Value("AdvInfoEnd", m_advancedInfo.fEndTime);
if (ser.IsReading())
{
SetTime(m_fTime, true);
}
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::NetSerialize(TSerialize ser, float lag, uint32 flags)
{
if (0 == (flags & NETSER_STATICPROPS))
{
if (ser.IsWriting())
{
ser.Value("time", m_fTime, 'tod');
}
else
{
float serializedTime;
ser.Value("time", serializedTime, 'tod');
float remoteTime = serializedTime + ((flags & NETSER_COMPENSATELAG) != 0) * m_advancedInfo.fAnimSpeed * lag;
float setTime = remoteTime;
if (0 == (flags & NETSER_FORCESET))
{
const float adjustmentFactor = 0.05f;
const float wraparoundGuardHours = 2.0f;
float localTime = m_fTime;
// handle wraparound
if (localTime < wraparoundGuardHours && remoteTime > (s_maxTime - wraparoundGuardHours))
{
localTime += s_maxTime;
}
else if (remoteTime < wraparoundGuardHours && localTime > (s_maxTime - wraparoundGuardHours))
{
remoteTime += s_maxTime;
}
// don't blend times if they're very different
if (fabsf(remoteTime - localTime) < 1.0f)
{
setTime = adjustmentFactor * remoteTime + (1.0f - adjustmentFactor) * m_fTime;
if (setTime > s_maxTime)
{
setTime -= s_maxTime;
}
}
}
SetTime(setTime, (flags & NETSER_FORCESET) != 0);
}
}
else
{
// no static serialization (yet)
}
}
//////////////////////////////////////////////////////////////////////////
void CTimeOfDay::Tick()
{
AZ_TRACE_METHOD();
// if(!gEnv->bServer)
// return;
if (!m_bEditMode && !m_bPaused)
{
if (fabs(m_advancedInfo.fAnimSpeed) > 0.0001f)
{
// advance (forward or backward)
float fTime = m_fTime + m_advancedInfo.fAnimSpeed * m_pTimer->GetFrameTime();
// full cycle mode
if (m_advancedInfo.fStartTime <= 0.05f && m_advancedInfo.fEndTime >= 23.5f)
{
if (fTime > m_advancedInfo.fEndTime)
{
fTime = m_advancedInfo.fStartTime;
}
if (fTime < m_advancedInfo.fStartTime)
{
fTime = m_advancedInfo.fEndTime;
}
}
else if (fabs(m_advancedInfo.fStartTime - m_advancedInfo.fEndTime) <= 0.05f)//full cycle mode
{
if (fTime > s_maxTime)
{
fTime -= s_maxTime;
}
else if (fTime < 0.0f)
{
fTime += s_maxTime;
}
}
else
{
// clamp advancing time
if (fTime > m_advancedInfo.fEndTime)
{
fTime = m_advancedInfo.fEndTime;
}
if (fTime < m_advancedInfo.fStartTime)
{
fTime = m_advancedInfo.fStartTime;
}
}
SetTime(fTime);
}
}
}
void CTimeOfDay::SetUpdateCallback(ITimeOfDayUpdateCallback* pCallback)
{
m_pUpdateCallback = pCallback;
}
void CTimeOfDay::LerpWith(const ITimeOfDay& other, float lerpValue, ITimeOfDay& output) const
{
AZ_Assert(GetVariableCount() == other.GetVariableCount() && GetVariableCount() == output.GetVariableCount(), "Attempting to lerp mismatching TimeOfDay objects!");
CTimeOfDay& todOutput = static_cast<CTimeOfDay&>(output);
const CTimeOfDay& todOther = static_cast<const CTimeOfDay&>(other);
for (uint32 i = 0; i < static_cast<uint32>(GetVariableCount()); i++)
{
SVariableInfo& outvar = todOutput.m_vars[i];
const SVariableInfo& var0 = m_vars[i];
const SVariableInfo& var1 = todOther.m_vars[i];
if (outvar.nParamId == var0.nParamId && outvar.nParamId == var1.nParamId)
{
switch (outvar.type)
{
case TYPE_FLOAT:
{
outvar.fValue[0] = Lerp(var0.fValue[0], var1.fValue[0], lerpValue);
break;
}
case TYPE_COLOR:
{
outvar.fValue[0] = Lerp(var0.fValue[0], var1.fValue[0], lerpValue);
outvar.fValue[1] = Lerp(var0.fValue[1], var1.fValue[1], lerpValue);
outvar.fValue[2] = Lerp(var0.fValue[2], var1.fValue[2], lerpValue);
break;
}
default:
{
AZ_Error("TimeOfDay", false, "Attempting to lerp mismatching TimeOfDay objects!");
}
}
}
else
{
CryWarning(EValidatorModule::VALIDATOR_MODULE_3DENGINE, EValidatorSeverity::VALIDATOR_WARNING, "Lerping mismatched time of day settings!");
}
}
}
void CTimeOfDay::BeginEditMode()
{
m_bEditMode = true;
SetTime(m_fEditorTime);
}
void CTimeOfDay::EndEditMode()
{
m_bEditMode = false;
m_fEditorTime = m_fTime;
}