💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

176 lines
4.7 KiB

/*
* 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;
}