Files
SingularityViewer/indra/newview/llwlanimator.cpp
Inusaito Sayori 72080e79e9 Sync llcommon with Alchemy a bit.
llmath::llround->ll_round
LL_ICC->LL_INTELC
Add llpredicate
Add LL_CPP11 macro
Remove llhash
Update llinitparam, llsd and all relatives of it.
2015-03-20 22:04:04 -04:00

339 lines
7.9 KiB
C++

/**
* @file llwlanimator.cpp
* @brief Implementation for the LLWLAnimator class.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llwlanimator.h"
#include "llsky.h"
#include "pipeline.h"
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
F64 LLWLAnimator::INTERP_TOTAL_SECONDS = 3.f;
LLWLAnimator::LLWLAnimator() : mStartTime(0.f), mDayRate(1.f), mDayTime(0.f),
mIsRunning(FALSE), mIsInterpolating(FALSE), mIsInterpolatingSky(FALSE),
mTimeType(TIME_LINDEN), mInterpStartTime(), mInterpEndTime()
{
mInterpBeginWL = new LLWLParamSet();
mInterpEndWL = new LLWLParamSet();
mInterpBeginWater = new LLWaterParamSet();
mInterpEndWater = new LLWaterParamSet();
}
void LLWLAnimator::update(LLWLParamSet& curParams)
{
//llassert(mUseLindenTime != mUseLocalTime);
F64 curTime;
curTime = getDayTime();
// don't do anything if empty
if(mTimeTrack.size() == 0)
{
return;
}
// start it off
mFirstIt = mTimeTrack.begin();
mSecondIt = mTimeTrack.begin();
mSecondIt++;
// grab the two tween iterators
while(mSecondIt != mTimeTrack.end() && curTime > mSecondIt->first)
{
mFirstIt++;
mSecondIt++;
}
// scroll it around when you get to the end
if(mSecondIt == mTimeTrack.end() || mFirstIt->first > curTime)
{
mSecondIt = mTimeTrack.begin();
mFirstIt = mTimeTrack.end();
mFirstIt--;
}
F32 weight = 0;
if(mFirstIt->first < mSecondIt->first)
{
// get the delta time and the proper weight
weight = F32 (curTime - mFirstIt->first) /
(mSecondIt->first - mFirstIt->first);
// handle the ends
}
else if(mFirstIt->first > mSecondIt->first)
{
// right edge of time line
if(curTime >= mFirstIt->first)
{
weight = F32 (curTime - mFirstIt->first) /
((1 + mSecondIt->first) - mFirstIt->first);
// left edge of time line
}
else
{
weight = F32 ((1 + curTime) - mFirstIt->first) /
((1 + mSecondIt->first) - mFirstIt->first);
}
// handle same as whatever the last one is
}
else
{
weight = 1;
}
if(mIsInterpolating)
{
// *TODO_JACOB: this is kind of laggy. Not sure why. The part that lags is the curParams.mix call, and none of the other mixes. It works, though.
clock_t current = clock();
if(current >= mInterpEndTime)
{
if (mIsInterpolatingSky)
{
deactivate();
// FIRE-3245: Some settings do not get fully mixed properly (possibly due to value extremes)
// at the end of the interp cycle, force the end settings to get applied
curParams.setAll(mInterpEndWL->getAll());
}
LLWaterParamManager::getInstance()->mCurParams.setAll(mInterpEndWater->getAll());
mIsInterpolating = false;
mIsInterpolatingSky = false;
return;
}
if (mIsInterpolatingSky)
{
weight = (current - mInterpStartTime) / (INTERP_TOTAL_SECONDS * CLOCKS_PER_SEC);
curParams.mix(*mInterpBeginWL, *mInterpEndWL, weight);
}
else
{
// determine moving target for final interpolation value
// *TODO: this will not work with lazy loading of sky presets.
LLWLParamSet buf = LLWLParamSet();
buf.setAll(LLWLParamManager::getInstance()->mParamList[mFirstIt->second].getAll()); // just give it some values, otherwise it has no params to begin with (see comment in constructor)
buf.mix(LLWLParamManager::getInstance()->mParamList[mFirstIt->second], LLWLParamManager::getInstance()->mParamList[mSecondIt->second], weight); // mix to determine moving target for interpolation finish (as below)
// mix from previous value to moving target
weight = (current - mInterpStartTime) / (INTERP_TOTAL_SECONDS * CLOCKS_PER_SEC);
curParams.mix(*mInterpBeginWL, buf, weight);
}
// mix water
LLWaterParamManager::getInstance()->mCurParams.mix(*mInterpBeginWater, *mInterpEndWater, weight);
}
else
{
// do the interpolation and set the parameters
// *TODO: this will not work with lazy loading of sky presets.
curParams.mix(LLWLParamManager::getInstance()->mParamList[mFirstIt->second], LLWLParamManager::getInstance()->mParamList[mSecondIt->second], weight);
}
}
F64 LLWLAnimator::getDayTime()
{
if(!mIsRunning)
{
return mDayTime;
}
else if(mTimeType == TIME_LINDEN)
{
F32 phase = gSky.getSunPhase() / F_PI;
// we're not solving the non-linear equation that determines sun phase
// we're just linearly interpolating between the major points
if (phase <= 5.0 / 4.0) {
mDayTime = (1.0 / 3.0) * phase + (1.0 / 3.0);
}
else
{
mDayTime = phase - (1.0 / 2.0);
}
if(mDayTime > 1)
{
mDayTime--;
}
return mDayTime;
}
else if(mTimeType == TIME_LOCAL)
{
return getLocalTime();
}
// get the time;
mDayTime = (LLTimer::getElapsedSeconds() - mStartTime) / mDayRate;
// clamp it
if(mDayTime < 0)
{
mDayTime = 0;
}
while(mDayTime > 1)
{
mDayTime--;
}
return (F32)mDayTime;
}
void LLWLAnimator::setDayTime(F64 dayTime)
{
//retroactively set start time;
mStartTime = LLTimer::getElapsedSeconds() - dayTime * mDayRate;
mDayTime = dayTime;
// clamp it
if(mDayTime < 0)
{
mDayTime = 0;
}
else if(mDayTime > 1)
{
mDayTime = 1;
}
}
void LLWLAnimator::setTrack(std::map<F32, LLWLParamKey>& curTrack,
F32 dayRate, F64 dayTime, bool run)
{
mTimeTrack = curTrack;
mDayRate = dayRate;
setDayTime(dayTime);
mIsRunning = run;
}
void LLWLAnimator::startInterpolation(const LLSD& targetWater)
{
mInterpBeginWL->setAll(LLWLParamManager::getInstance()->mCurParams.getAll());
mInterpBeginWater->setAll(LLWaterParamManager::getInstance()->mCurParams.getAll());
mInterpStartTime = clock();
mInterpEndTime = mInterpStartTime + clock_t(INTERP_TOTAL_SECONDS) * CLOCKS_PER_SEC;
// Don't set any ending WL -- this is continuously calculated as the animator updates since it's a moving target
mInterpEndWater->setAll(targetWater);
mIsInterpolating = true;
}
void LLWLAnimator::startInterpolationSky(const LLSD& targetSky)
{
mInterpEndWL->setAll(targetSky);
mIsInterpolatingSky = true;
}
std::string LLWLAnimator::timeToString(F32 curTime)
{
S32 hours;
S32 min;
bool isPM = false;
// get hours and minutes
hours = (S32) (24.0 * curTime);
curTime -= ((F32) hours / 24.0f);
min = ll_round(24.0f * 60.0f * curTime);
// handle case where it's 60
if(min == 60)
{
hours++;
min = 0;
}
// set for PM
if(hours >= 12 && hours < 24)
{
isPM = true;
}
// convert to non-military notation
if(hours >= 24)
{
hours = 12;
}
else if(hours > 12)
{
hours -= 12;
}
else if(hours == 0)
{
hours = 12;
}
// make the string
std::stringstream newTime;
newTime << hours << ":";
// double 0
if(min < 10)
{
newTime << 0;
}
// finish it
newTime << min << " ";
if(isPM)
{
newTime << "PM";
}
else
{
newTime << "AM";
}
return newTime.str();
}
F64 LLWLAnimator::getLocalTime()
{
char buffer[9];
time_t rawtime;
struct tm* timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, 9, "%H:%M:%S", timeinfo);
std::string timeStr(buffer);
F64 tod = ((F64)atoi(timeStr.substr(0,2).c_str())) / 24.f +
((F64)atoi(timeStr.substr(3,2).c_str())) / 1440.f +
((F64)atoi(timeStr.substr(6,2).c_str())) / 86400.f;
return tod;
}