Kale
Loading...
Searching...
No Matches
SkeletalAnimatable.cpp
Go to the documentation of this file.
1/*
2 Copyright 2022 Rishi Challa
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
18
19using namespace Kale;
20
25 // Empty Body
26}
27
33Skeleton::Skeleton(const std::vector<std::tuple<int, float, float>>& bones, AngleUnit unit) {
34 this->bones.reserve(bones.size());
35 for (const std::tuple<int, float, float>& bone : bones)
36 this->bones.push_back(Skeleton::calculateBone(this->bones, std::get<0>(bone), std::get<1>(bone), std::get<2>(bone), unit));
37}
38
43Skeleton::Skeleton(const std::vector<Bone>& bones) : bones(bones) {
44 // Empty Body
45}
46
53
59 // Empty Body
60}
61
67 base = skeleton;
68}
69
75 // Everything below is thread sensitive and modifies data accessed from other threads. We need mutual access to it
76 std::lock_guard lock(mutex);
77
78 // If the skeleton has already been recalculated, we don't need to recalculate.
79 if (skeletonRecalculated) return;
80
81 // Update the states and retrieve the composition. Also flag the skeleton as recalculated
82 updateState(deltaTime);
84 std::vector<std::pair<int, float>> composition = getStateComposition<int>();
85
86 // Resize the skeleton if it isn't already at the correct size
87 if (skeleton.size() != structures[composition[0].first].bones.size())
88 skeleton.resize(structures[composition[0].first].bones.size());
89
90 // If the composition size is 1, then the skeleton is simply a single state.
91 if (composition.size() == 1) {
92 // Simply take the state's worldToBones and multiply it by the inverse of our base
93 const std::vector<Skeleton::Bone>& skeletonState = structures[composition[0].first].bones;
94 for (size_t i = 0; i < skeleton.size(); i++) skeleton[i] = base.bones[i].inverseWorldToBone * skeletonState[i].worldToBone;
95 return;
96 }
97
98 // If the composition size is 2, then the skeleton is a lerp between two states
99 const std::vector<Skeleton::Bone>& fromSkeletonState = structures[composition[0].first].bones;
100 const std::vector<Skeleton::Bone>& toSkeletonState = structures[composition[1].first].bones;
101 for (size_t i = 0; i < skeleton.size(); i++) {
102 // Lerp the transformation matrices between the two states then multiply it with our inverse to get the offset matrix
103 skeleton[i] = fromSkeletonState[i].worldToBone * composition[0].second + toSkeletonState[i].worldToBone * composition[1].second;
104 skeleton[i] = base.bones[i].inverseWorldToBone * skeleton[i];
105 }
106}
107
114void SkeletalAnimatable::update(size_t threadNum, const Scene& scene, float deltaTime) {
115 skeletonRecalculated = false;
116}
117
124void SkeletalAnimatable::preUpdate(size_t threadNum, const Scene& scene, float deltaTime) {
125 recalculateSkeleton(deltaTime);
126}
127
134const std::vector<Transform>& SkeletalAnimatable::getSkeleton(float deltaTime) {
135 recalculateSkeleton(deltaTime);
136 return skeleton;
137}
138
145const std::vector<Transform>& SkeletalAnimatable::getSkeletonNoRecalc() const {
146 return skeleton;
147}
148
156Vector2f SkeletalAnimatable::transform(Vector2f vert, const std::array<std::pair<int, float>, 4>& weights, float deltaTime) {
157 recalculateSkeleton(deltaTime);
158 return Skeleton::transform(skeleton, vert, weights);
159}
160
168Vector2f SkeletalAnimatable::transformNoRecalc(Vector2f vert, const std::array<std::pair<int, float>, 4>& weights) const {
169 return Skeleton::transform(skeleton, vert, weights);
170}
Vector2f transform(Vector2f vert, const std::array< std::pair< int, float >, 4 > &weights, float deltaTime)
Vector2f transformNoRecalc(Vector2f vert, const std::array< std::pair< int, float >, 4 > &weights) const
void update(size_t threadNum, const Scene &scene, float deltaTime) override
void setBase(const Skeleton &skeleton)
std::vector< Transform > skeleton
void recalculateSkeleton(float deltaTime)
const std::vector< Transform > & getSkeletonNoRecalc() const
void preUpdate(size_t threadNum, const Scene &scene, float deltaTime) override
const std::vector< Transform > & getSkeleton(float deltaTime)
std::unordered_map< int, Skeleton > structures
AngleUnit
Definition Utils.hpp:30
static Vector2f transform(const std::vector< Transform > &offsets, Vector2f vert, const std::array< std::pair< int, float >, 4 > &weights)
std::vector< Bone > bones
static Bone calculateBone(const std::vector< Bone > &bones, int previousBone, float length, float rotation, AngleUnit unit)