/*
|
|
* Copyright (C) 2017-2019 Christopher J. Howard
|
|
*
|
|
* This file is part of Antkeeper Source Code.
|
|
*
|
|
* Antkeeper Source Code 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.
|
|
*
|
|
* Antkeeper Source Code 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 Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "lens.hpp"
|
|
#include "camera-rig.hpp"
|
|
#include "../entity/systems/particle-system.hpp"
|
|
|
|
Lens::Lens(const Model* model, Animator* animator):
|
|
wasActive(false),
|
|
particleSystem(nullptr)
|
|
{
|
|
// Setup model instance
|
|
modelInstance.setModel(model);
|
|
modelInstance.setCullingEnabled(false);
|
|
|
|
// Setup spotlight
|
|
spotlight.setColor(Vector3(1.0f));
|
|
spotlight.setIntensity(1000.0f);
|
|
spotlight.setAttenuation(Vector3(1, 0, 1));
|
|
spotlight.setCutoff(std::cos(glm::radians(45.0f)));
|
|
spotlight.setExponent(150.0f);
|
|
spotlight.setActive(false);
|
|
|
|
unfocusedDistance = 18.0f;
|
|
unfocusDuration = 0.25f;
|
|
focusedDistance = 12.0f;
|
|
focusDuration = 0.75f;
|
|
|
|
lensDistance = unfocusedDistance;
|
|
focused = false;
|
|
lastDistance = unfocusedDistance;
|
|
sunDirection = Vector3(0, -1, 0);
|
|
|
|
// Construct focus animation clip
|
|
AnimationChannel<float>* channel;
|
|
focusClip.setInterpolator(easeOutCubic<float>);
|
|
channel = focusClip.addChannel(0);
|
|
channel->insertKeyframe(0.0f, 0.0f);
|
|
channel->insertKeyframe(focusDuration, 1.0f);
|
|
|
|
// Construct unfocus animation clip
|
|
unfocusClip.setInterpolator(easeOutCubic<float>);
|
|
channel = unfocusClip.addChannel(0);
|
|
channel->insertKeyframe(0.0f, 0.0f);
|
|
channel->insertKeyframe(unfocusDuration, 1.0f);
|
|
|
|
// Setup focus animation callbacks
|
|
focusAnimation.setTimeFrame(focusClip.getTimeFrame());
|
|
focusAnimation.setClip(&focusClip);
|
|
focusAnimation.setAnimateCallback
|
|
(
|
|
[this](std::size_t id, float distance)
|
|
{
|
|
this->lensDistance = lerp(lastDistance, focusedDistance, distance);
|
|
}
|
|
);
|
|
focusAnimation.setEndCallback
|
|
(
|
|
[this]()
|
|
{
|
|
this->focused = true;
|
|
}
|
|
);
|
|
|
|
// Setup unfocus animation callbacks
|
|
unfocusAnimation.setTimeFrame(unfocusClip.getTimeFrame());
|
|
unfocusAnimation.setClip(&unfocusClip);
|
|
unfocusAnimation.setAnimateCallback
|
|
(
|
|
[this](std::size_t id, float distance)
|
|
{
|
|
this->lensDistance = lerp(lastDistance, unfocusedDistance, distance);
|
|
}
|
|
);
|
|
|
|
// Add animations to animator
|
|
animator->addAnimation(&focusAnimation);
|
|
animator->addAnimation(&unfocusAnimation);
|
|
}
|
|
|
|
Lens::~Lens()
|
|
{}
|
|
|
|
void Lens::update(float dt)
|
|
{
|
|
//Quaternion alignment = glm::rotation(Vector3(0, 1, 0), -sunDirection) * glm::angleAxis(glm::radians(90.0f), Vector3(0, 1, 0));
|
|
Quaternion alignment = glm::rotation(Vector3(0, 1, 0), -sunDirection) * glm::angleAxis(orbitCam->getAzimuth() + glm::radians(90.0f), Vector3(0, 1, 0));
|
|
Quaternion rotation = glm::normalize(alignment);
|
|
Vector3 translation = pick + sunDirection * -lensDistance;
|
|
|
|
modelInstance.setTranslation(translation);
|
|
modelInstance.setRotation(rotation);
|
|
|
|
float t = (1.0 - (lensDistance - focusedDistance) / (unfocusedDistance - focusedDistance));
|
|
|
|
float unfocusedIntensity = 250.0f * 2.0f;
|
|
float focusedIntensity = 1000.0f * 2.0f;
|
|
float intensity = easeInExpo(unfocusedIntensity, focusedIntensity, t);
|
|
|
|
float unfocusedExponent = 100.0f;
|
|
float focusedExponent = 5000.0f;
|
|
float exponent = easeInExpo(unfocusedExponent, focusedExponent, t);
|
|
|
|
spotlight.setIntensity(intensity);
|
|
spotlight.setExponent(exponent);
|
|
spotlight.setTranslation(pick + sunDirection * -lensDistance);
|
|
spotlight.setDirection(sunDirection);
|
|
|
|
if (active && !wasActive)
|
|
{
|
|
modelInstance.resetTweens();
|
|
spotlight.resetTweens();
|
|
modelInstance.setActive(true);
|
|
spotlight.setActive(true);
|
|
}
|
|
else if (!active && wasActive)
|
|
{
|
|
modelInstance.setActive(false);
|
|
spotlight.setActive(false);
|
|
}
|
|
|
|
if (active && focused)
|
|
{
|
|
int count = 10;
|
|
for (int i = 0; i < count; ++i)
|
|
particleSystem->emit(pick);
|
|
}
|
|
|
|
wasActive = active;
|
|
}
|
|
|
|
void Lens::focus()
|
|
{
|
|
lastDistance = lensDistance;
|
|
|
|
unfocusAnimation.stop();
|
|
focusAnimation.rewind();
|
|
focusAnimation.play();
|
|
}
|
|
|
|
void Lens::unfocus()
|
|
{
|
|
lastDistance = lensDistance;
|
|
|
|
focusAnimation.stop();
|
|
unfocusAnimation.rewind();
|
|
unfocusAnimation.play();
|
|
focused = false;
|
|
}
|
|
|
|
void Lens::setSunDirection(const Vector3& direction)
|
|
{
|
|
sunDirection = direction;
|
|
}
|
|
|
|
void Lens::setParticleSystem(ParticleSystem* particleSystem)
|
|
{
|
|
this->particleSystem = particleSystem;
|
|
}
|
|
|