init
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
/* Copyright (c) 2020-2023, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 the "License";
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "animation.h"
|
||||
|
||||
#include "scene_graph/node.h"
|
||||
|
||||
namespace vkb
|
||||
{
|
||||
namespace sg
|
||||
{
|
||||
Animation::Animation(const std::string &name) :
|
||||
Script{name}
|
||||
{
|
||||
}
|
||||
|
||||
Animation::Animation(const Animation &other) :
|
||||
channels{other.channels}
|
||||
{
|
||||
}
|
||||
|
||||
void Animation::add_channel(Node &node, const AnimationTarget &target, const AnimationSampler &sampler)
|
||||
{
|
||||
channels.push_back({node, target, sampler});
|
||||
}
|
||||
|
||||
void Animation::update(float delta_time)
|
||||
{
|
||||
current_time += delta_time;
|
||||
if (current_time > end_time)
|
||||
{
|
||||
current_time -= end_time;
|
||||
}
|
||||
|
||||
for (auto &channel : channels)
|
||||
{
|
||||
for (size_t i = 0; i < channel.sampler.inputs.size() - 1; ++i)
|
||||
{
|
||||
if ((current_time >= channel.sampler.inputs[i]) && (current_time <= channel.sampler.inputs[i + 1]))
|
||||
{
|
||||
float time = (current_time - channel.sampler.inputs[i]) / (channel.sampler.inputs[i + 1] - channel.sampler.inputs[i]);
|
||||
|
||||
auto &transform = channel.node.get_transform();
|
||||
|
||||
if (channel.sampler.type == AnimationType::Linear)
|
||||
{
|
||||
switch (channel.target)
|
||||
{
|
||||
case Translation:
|
||||
{
|
||||
transform.set_translation(glm::vec3(glm::mix(channel.sampler.outputs[i],
|
||||
channel.sampler.outputs[i + 1],
|
||||
time)));
|
||||
break;
|
||||
}
|
||||
case Rotation:
|
||||
{
|
||||
glm::quat q1;
|
||||
q1.x = channel.sampler.outputs[i].x;
|
||||
q1.y = channel.sampler.outputs[i].y;
|
||||
q1.z = channel.sampler.outputs[i].z;
|
||||
q1.w = channel.sampler.outputs[i].w;
|
||||
|
||||
glm::quat q2;
|
||||
q2.x = channel.sampler.outputs[i + 1].x;
|
||||
q2.y = channel.sampler.outputs[i + 1].y;
|
||||
q2.z = channel.sampler.outputs[i + 1].z;
|
||||
q2.w = channel.sampler.outputs[i + 1].w;
|
||||
|
||||
transform.set_rotation(glm::normalize(glm::slerp(q1, q2, time)));
|
||||
break;
|
||||
}
|
||||
|
||||
case Scale:
|
||||
{
|
||||
transform.set_scale(glm::vec3(glm::mix(channel.sampler.outputs[i],
|
||||
channel.sampler.outputs[i + 1],
|
||||
time)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (channel.sampler.type == AnimationType::Step)
|
||||
{
|
||||
switch (channel.target)
|
||||
{
|
||||
case Translation:
|
||||
{
|
||||
transform.set_translation(glm::vec3(channel.sampler.outputs[i]));
|
||||
break;
|
||||
}
|
||||
case Rotation:
|
||||
{
|
||||
glm::quat q1;
|
||||
q1.x = channel.sampler.outputs[i].x;
|
||||
q1.y = channel.sampler.outputs[i].y;
|
||||
q1.z = channel.sampler.outputs[i].z;
|
||||
q1.w = channel.sampler.outputs[i].w;
|
||||
|
||||
transform.set_rotation(glm::normalize(q1));
|
||||
break;
|
||||
}
|
||||
|
||||
case Scale:
|
||||
{
|
||||
transform.set_scale(glm::vec3(channel.sampler.outputs[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (channel.sampler.type == AnimationType::CubicSpline)
|
||||
{
|
||||
float delta = channel.sampler.inputs[i + 1] - channel.sampler.inputs[i];
|
||||
|
||||
glm::vec4 p0 = channel.sampler.outputs[i * 3 + 1]; // Starting point
|
||||
glm::vec4 p1 = channel.sampler.outputs[(i + 1) * 3 + 1]; // Ending point
|
||||
|
||||
glm::vec4 m0 = delta * channel.sampler.outputs[i * 3 + 2]; // Delta time * out tangent
|
||||
glm::vec4 m1 = delta * channel.sampler.outputs[(i + 1) * 3 + 0]; // Delta time * in tangent of next point
|
||||
|
||||
// This equation is taken from the GLTF 2.0 specification Appendix C (https://github.com/KhronosGroup/glTF/tree/main/specification/2.0#appendix-c-spline-interpolation)
|
||||
glm::vec4 result = (2.0f * glm::pow(time, 3.0f) - 3.0f * glm::pow(time, 2.0f) + 1.0f) * p0 + (glm::pow(time, 3.0f) - 2.0f * glm::pow(time, 2.0f) + time) * m0 + (-2.0f * glm::pow(time, 3.0f) + 3.0f * glm::pow(time, 2.0f)) * p1 + (glm::pow(time, 3.0f) - glm::pow(time, 2.0f)) * m1;
|
||||
|
||||
auto &transform = channel.node.get_transform();
|
||||
|
||||
switch (channel.target)
|
||||
{
|
||||
case Translation:
|
||||
{
|
||||
transform.set_translation(glm::vec3(result));
|
||||
break;
|
||||
}
|
||||
case Rotation:
|
||||
{
|
||||
glm::quat q1;
|
||||
q1.x = result.x;
|
||||
q1.y = result.y;
|
||||
q1.z = result.z;
|
||||
q1.w = result.w;
|
||||
|
||||
transform.set_rotation(glm::normalize(q1));
|
||||
break;
|
||||
}
|
||||
|
||||
case Scale:
|
||||
{
|
||||
transform.set_scale(glm::vec3(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::update_times(float new_start_time, float new_end_time)
|
||||
{
|
||||
if (new_start_time < start_time)
|
||||
{
|
||||
start_time = new_start_time;
|
||||
}
|
||||
if (new_end_time > end_time)
|
||||
{
|
||||
end_time = new_end_time;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sg
|
||||
} // namespace vkb
|
||||
Reference in New Issue
Block a user