dl
dl_model_bone.h
浏览该文件的文档.
1
12#pragma once
13
14#include <vector>
15
18#include "math/dl_matrix.h"
19
20namespace dl
21{
22
25{
27 _t(-1.0f),//负数代表无效
29 _roationQuat{ 1.0f, 0.0f, 0.0f, 0.0f },
30 _scaling{ 1.0f, 1.0f, 1.0f }
31 {}
32
37};
38
39
42{
43 //关键帧插值
45 {
46 //没有关键帧直接返回(保持不变)
47 if (_allKeyFrame.empty())
48 return;
49 //变换顺序为SRT
50 mat.Identity();
51
52 if (t <= _allKeyFrame.front()._t)
53 {
54 BoneKeyFrame& key_frame = _allKeyFrame.front();
56 Matrix4 mat_r = Mat::CreateRotation(key_frame._roationQuat);
57 Matrix4 mat_s = Mat::CreateScaling(key_frame._scaling);
58 mat = mat_t * mat_r * mat_s;
59 }
60 else if (t >= _allKeyFrame.back()._t)
61 {
62 BoneKeyFrame& key_frame = _allKeyFrame.back();
64 Matrix4 mat_r = Mat::CreateRotation(key_frame._roationQuat);
65 Matrix4 mat_s = Mat::CreateScaling(key_frame._scaling);
66 mat = mat_t * mat_r * mat_s;
67 }
68 else
69 {
70 for (size_t i = 0; i < _allKeyFrame.size() - 1; ++i)
71 {//[0, n-1)
72 BoneKeyFrame& kf_0 = _allKeyFrame[i];
73 BoneKeyFrame& kf_1 = _allKeyFrame[i + 1];
74 //找到时间范围内
75 if (t >= kf_0._t && t <= kf_1._t)
76 {
77 FloatTime percent = (t - kf_0._t) / (kf_1._t - kf_0._t);
78
79 Position3 t = Each::Lerp(kf_0._translation, kf_1._translation, percent);
80 Position4 r = Math::Slerp(kf_0._roationQuat, kf_1._roationQuat, percent);
81 Position3 s = Each::Lerp(kf_0._scaling, kf_1._scaling, percent);
82
85 Matrix4 mat_s = Mat::CreateScaling(s);
86 mat = mat_t * mat_r * mat_s;
87 break;
88 }
89 }
90 }
91 }
92
93 std::vector<BoneKeyFrame> _allKeyFrame;
94};
97{
100 std::vector<BoneKeyFrameMulti> _allBoneKeyFrameMulti;
101public:
103 {
104 return _t1;
105 }
106 //插值
107 void Interpolate(FloatTime t, std::vector<Matrix4>& bone_trans)
108 {
109 for (size_t i = 0; i < _allBoneKeyFrameMulti.size(); ++i)
110 {
111 _allBoneKeyFrameMulti[i].Interpolate(t, bone_trans[i]);
112 }
113 }
114};
115
118{
119 friend class ModelLoader;
120 friend class FactoryImp;
121 friend class BoneAnimation;
122 friend class Actor;
123public:
124 //偏移矩阵先初始化
125 size_t GetBoneSize() { return _allBoneOffset.size(); }
126 FloatTime GetClipEndTime(std::string_view cilp_name)
127 {
128 auto clip = _allAnimation.find(std::string{ cilp_name });
129 return clip->second.GetClipEndTime();
130 }
131 //返回偏移矩阵(单位矩阵才是静止状态)
132 std::vector<Matrix4> GetBoneOffset()
133 {
134 return _allBoneOffset;
135 }
136
137 //或许可以缓存常用时刻的变换
138 void GetFinalTrans(std::string_view clip_name, FloatTime t,
139 std::vector<Matrix4>& final_trans)
140 {
141 //偏移矩阵数量(骨骼数量)
142 size_t num_bone = _allBoneOffset.size();
143 //变换到父骨骼的矩阵
144 std::vector<Matrix4> trans_to_parent = _allNodeTrans2Parent;
145
146 //对指定动画进行插值
147 auto clip = _allAnimation.find(std::string{ clip_name });
148 clip->second.Interpolate(t, trans_to_parent);
149
150 //将骨骼变换到根空间
151 std::vector<Matrix4> trans_to_root(num_bone);
152
153 //计算trans_to_root
154 for (size_t i = 0; i < num_bone; ++i)
155 {
156 //父骨骼下标
157 int index_parent = _allNodeParent[i];
158 if(index_parent == -1)//指向-1为根骨骼,无需计算
159 trans_to_root[i] = trans_to_parent[i];
160 else
161 {
162 //自己到父
163 Matrix4& mat_to_parent = trans_to_parent[i];
164 //父骨骼 到 根 的矩阵
165 Matrix4& parent_to_root = trans_to_root[index_parent];
166 //自己到根的矩阵 = 自己到父,再父到根
167 trans_to_root[i] = parent_to_root * mat_to_parent;
168 }
169 }
170
171 //计算最终矩阵
172 for (size_t i = 0; i < num_bone; ++i)
173 {
174 Matrix4& mat_offset = _allBoneOffset[i];
175 Matrix4& mat_to_root = trans_to_root[i];
176 final_trans[i] = mat_to_root * mat_offset;
177 }
178 }
179
181 {
182 s.Write(&_allNodeParent);
183 s.Write(&_allNodeTrans2Parent);
184 s.Write(&_allBoneOffset);
185
186 size_t size = _allAnimation.size();
187 s.Write(&size);
188 for (auto& iter : _allAnimation)
189 {
190 const std::string& name = iter.first;
191 const AnimationClip& clip = iter.second;
192 s.Write(&name);
193 s.Write(&clip._t0);
194 s.Write(&clip._t1);
195 size_t size1 = clip._allBoneKeyFrameMulti.size();
196 s.Write(&size1);
197 for (size_t i = 0; i < size1; ++i)
198 {
199 const BoneKeyFrameMulti& kf_mul = clip._allBoneKeyFrameMulti[i];
200 size_t size2 = kf_mul._allKeyFrame.size();
201 s.Write(&size2);
202 for (size_t j = 0; j < size2; ++j)
203 {
204 const BoneKeyFrame& kf = kf_mul._allKeyFrame[j];
205 s.Write(&kf);
206 }
207 }
208 }
209 }
211 {
212 s.Read(&_allNodeParent);
213 s.Read(&_allNodeTrans2Parent);
214 s.Read(&_allBoneOffset);
215
216 size_t size;
217 s.Read(&size);
218 for (size_t k = 0; k < size; ++k)
219 {
220 std::string name;
221 s.Read(&name);
222 AnimationClip& clip = _allAnimation[name];
223 s.Read(&clip._t0);
224 s.Read(&clip._t1);
225 size_t size1;
226 s.Read(&size1);
227 clip._allBoneKeyFrameMulti.resize(size1);
228 for (size_t i = 0; i < size1; ++i)
229 {
231 size_t size2;
232 s.Read(&size2);
233 kf_mul._allKeyFrame.resize(size2);
234 for (size_t j = 0; j < size2; ++j)
235 {
236 s.Read(&kf_mul._allKeyFrame[j]);
237 }
238 }
239 }
240 }
241private:
242 std::vector<int> _allNodeParent;//Node的父Node,下标为node_id
243 std::vector<Matrix4> _allNodeTrans2Parent;//Node到父Node的矩阵
244 std::vector<Matrix4> _allBoneOffset;//偏移矩阵
245 std::unordered_map<std::string, AnimationClip> _allAnimation;//动画片段
246};
247
250{
251public:
253 std::vector<Matrix4> _finalTrans;//某时间点的最终变换
254 std::string _clipName;//当前动画名称
255 FloatTime _t;//时间点
256 size_t _id;//骨骼实例下标(不是ub下标)
257
259 _skinndeData{ nullptr },
260 _t{},
261 _id{(size_t)-1}
262 {}
263
264 //t为-1代表 设为起始
265 void Set(std::string_view name, FloatTime t)
266 {
267 auto iter = _skinndeData->_allAnimation.find(std::string{ name });
268 if (iter == _skinndeData->_allAnimation.end())
269 {
270 log_err("指定动画不存在:{}", name);
271 return;
272 }
273 _clipName = std::string{ name };
274 AnimationClip& clip = iter->second;
275 if (t < 0)
276 _t = clip._t0;
277 else if (Math::IsOutRange(t, clip._t0, clip._t1))
278 {
279 log_err("设置动画时间越界:{},{}->{}", t, clip._t0, clip._t1);
280 _t = clip._t0;
281 }
282 else
283 _t = t;
284 }
285
288 {
289 _t += dt;
291 _t = 0;
292 if(true)
294 else
295 {
296 for (auto& iter : _finalTrans)
297 iter.Identity();
298 }
299 }
300};
301
302}
3D绘图对象
Definition: dl_actor.h:29
骨骼动画实例
void Update(FloatTime dt)
每帧调用,推进时间点进行插值
void Set(std::string_view name, FloatTime t)
BoneData * _skinndeData
std::vector< Matrix4 > _finalTrans
std::string _clipName
骨骼数据(多个骨骼)
void GetFinalTrans(std::string_view clip_name, FloatTime t, std::vector< Matrix4 > &final_trans)
void Save(StreamOutput &s)
FloatTime GetClipEndTime(std::string_view cilp_name)
size_t GetBoneSize()
std::vector< Matrix4 > GetBoneOffset()
void Load(StreamInput &s)
void Identity()
获得行列式的值,Determinant(A)
Definition: dl_matrix.h:160
注释参考StreamOutput
void Read(T *data)
void Write(const T *data)
写入一个对象
#define log_err(...)
Definition: dl_log.h:243
矩阵(列存储)
std::array< T, N > Lerp(const std::array< T, N > &a, const std::array< T, N > &b, T t)
线性插值
Definition: dl_range_each.h:74
Matrix4 CreateRotation(const Position3 &axis, Float angle)
创建旋转矩阵
Matrix4 CreateTranslation(const Position3 &t)
创建平移矩阵
Matrix4 CreateScaling(const Position3 &s)
创建缩放矩阵
constexpr bool IsOutRange(T x, T a, T b)
判断数值是否越界(前闭后开)
Definition: dl_math.h:90
Position4 Slerp(const Position4 &q0, const Position4 &q1, const Float &t)
球面线性插值
Definition: dl_array2.h:18
std::array< Float, 3 > Position3
Definition: dl_type_def.h:41
std::array< Float, 4 > Position4
Definition: dl_type_def.h:42
float FloatTime
Definition: dl_type_def.h:48
动画片段,包含多个骨骼
Definition: dl_model_bone.h:97
std::vector< BoneKeyFrameMulti > _allBoneKeyFrameMulti
void Interpolate(FloatTime t, std::vector< Matrix4 > &bone_trans)
FloatTime GetClipEndTime()
骨骼关键帧(不变量)
Definition: dl_model_bone.h:25
Position3 _translation
Definition: dl_model_bone.h:34
Position4 _roationQuat
Definition: dl_model_bone.h:35
Position3 _scaling
Definition: dl_model_bone.h:36
多个节点关键帧组成的一个骨架
Definition: dl_model_bone.h:42
void Interpolate(FloatTime t, Matrix4 &mat)
Definition: dl_model_bone.h:44
std::vector< BoneKeyFrame > _allKeyFrame
Definition: dl_model_bone.h:93