PeriDyno 0.8.2
SkeletonLoader.cpp
Go to the documentation of this file.
1#include "SkeletonLoader.h"
2
3#define AXIS 0
4
5namespace dyno
6{
8
9 template<typename TDataType>
11 : Node()
12 {
13 auto defaultTopo = std::make_shared<DiscreteElements<TDataType>>();
14 this->stateTopology()->setDataPtr(defaultTopo);
15 }
16
17 template<typename TDataType>
19 {
20
21 }
22
23 template<typename TDataType>
24 bool SkeletonLoader<TDataType>::initFBX(const char* filepath)
25 {
26 FILE* fp = fopen(filepath, "rb");
27
28 if (!fp) return false;
29
30 fseek(fp, 0, SEEK_END);
31 long file_size = ftell(fp);
32 fseek(fp, 0, SEEK_SET);
33 auto* content = new ofbx::u8[file_size];
34 fread(content, 1, file_size, fp);
35
36 this->g_scene = ofbx::load((ofbx::u8*)content, file_size, (ofbx::u64)ofbx::LoadFlags::TRIANGULATE);
37
38 delete[] content;
39 fclose(fp);
40
41 return true;
42 }
43
44
45 template<typename TDataType>
47 {
48 if (object.getType() != ofbx::Object::Type::ANIMATION_CURVE_NODE) return;
49 if (strlen(object.name) != 1) return;
50 auto AnimObject = (ofbx::AnimationCurveNode*)&object;
51 Real d[3];
52 d[0] = AnimObject->getAnimationDX();
53 d[1] = AnimObject->getAnimationDY();
54 d[2] = AnimObject->getAnimationDZ();
55 auto curve0 = AnimObject->getCurve(0);
56 int key_allsize = (curve0 == nullptr)? 1: curve0->getKeyCount();
57 auto animCurve = std::make_shared<dyno::AnimationCurve<TDataType>>(key_allsize, d[0], d[1], d[2]);
58
59 for (int i = 0; i < 3; ++i)
60 {
61 std::vector<long long> times;
62 std::vector<float> values;
63
64 auto curve = AnimObject->getCurve(i);
65 if (curve == nullptr)
66 {
67 times.push_back(0);
68 values.push_back(d[i]);
69 }
70 else {
71 int key_count = curve->getKeyCount();
72
73 //assert(key_allsize == key_count);
74
75 const long long* t = curve->getKeyTime();
76 const float* v = curve->getKeyValue();
77 times.assign(t, t + key_count);
78 values.assign(v, v + key_count);
79 }
80
81 animCurve->set(i, times, values);
82 }
83
84 switch (object.name[0])
85 {
86 case 'T':
87 parent->setAnimTranslation(animCurve);
88 break;
89 case 'R':
90 parent->setAnimRotation(animCurve);
91 break;
92 case 'S':
93 parent->setAnimScaling(animCurve);
94 break;
95 default:
96 break;
97 }
98 }
99
100
101 template<typename TDataType>
103 {
104 cur->id = object.id;
105
106 //FIXME Pre可能出错了
107 copyVecR(cur->PreRotation, object.getPreRotation());
108 copyVecT(cur->LclTranslation, object.getLocalTranslation());
109 copyVecR(cur->LclRotation, object.getLocalRotation());
110 copyVec(cur->LclScaling, object.getLocalScaling());
111 cur->CurTranslation = cur->LclTranslation;
112 cur->CurRotation = cur->LclRotation;
113 cur->CurScaling = cur->LclScaling;
114
115 //DFS 序
116 m_jointMap.push_back(cur);
117 }
118
119 template<typename TDataType>
121 {
122 if (object.getType() != ofbx::Object::Type::LIMB_NODE) return;
123
124 std::shared_ptr<JointTree<TDataType>> cur;
125
126 if (object.getType() == ofbx::Object::Type::LIMB_NODE){
127
128 cur = std::make_shared<JointTree<TDataType>>();
129 if(parent != nullptr) parent->children.push_back(cur);
130 cur->parent = parent;
131 getModelProperties(object, cur);
132 }
133 int i = 0;
134 while (ofbx::Object* child = object.resolveObjectLink(i))
135 {
136 if (object.getType() == ofbx::Object::Type::LIMB_NODE)
137 {
138 getLimbNode(*child, cur);
139 // animation curve node
140 getAnimationCurve(*child, cur);
141 }
142 else getLimbNode(*child, parent);
143 ++i;
144 }
145 }
146 template<typename TDataType>
148 {
149 const ofbx::Object* root = scene.getRoot();
150 if (root) {
151 int i = 0;
152 while (ofbx::Object* child = root->resolveObjectLink(i))
153 {
154 getLimbNode(*child, nullptr);
155 ++i;
156 }
157 }
158 }
159
160 template<typename TDataType>
162 {
163 auto filename = this->varFileName()->getData();
164 std::string filepath = filename.string();
165 m_jointMap.clear();
166 initFBX(filepath.c_str());
167 getNodes(*g_scene);
168 }
169
170 // 以重心为坐标原点的旋转、平移四元数转换
171 template<typename TDataType>
173 {
174 Coord center = (v0 + v1) / 2.f;
175 Coord tmp = v1 - v0;
176 Vec3f dir = Vec3f(tmp[0], tmp[1], tmp[2]).normalize();
177
178 float cos2;
179 Vec3f axis;
180 switch (AXIS)
181 {
182 case 0: // X (1, 0, 0) × dir = u
183 cos2 = dir.x;
184 axis = Vec3f(0, -dir.z, dir.y).normalize();
185 break;
186 case 1: // Y (0, 1, 0) × dir = u
187 cos2 = dir.y;
188 axis = Vec3f(dir.z, 0, -dir.x).normalize();
189 break;
190 default: // Z (0, 0, 1) × dir = u
191 cos2 = dir.z;
192 axis = Vec3f(-dir.y, dir.x, 0).normalize();
193 break;
194 }
195 float cos1 = sqrtf((1 + cos2) / 2.0);
196 float sin1 = sqrtf((1 - cos2) / 2.0);
197 Quat<Real> q(axis.x * sin1, axis.y * sin1, axis.z * sin1, cos1);
198 Quat<Real> t(center[0], center[1], center[2], 0.f);
199 T = t;
200 R = q;
201 }
202
203 template<typename TDataType>
205 {
206 this->m_jointMap[0]->scale(s);
207
208 return true;
209 }
210
211 template<typename TDataType>
213 {
214 this->m_jointMap[0]->translate(t);
215 return true;
216 }
217
218 Vec3f DEBUG_T(0.25, 0.0, 0.0); // 用于平移骨架,以便对比演示
219
220 template<typename TDataType>
222 {
223 loadFBX();
224 if (m_jointMap.empty())
225 {
226 printf("Load Skeleton failed.");
227 return;
228 }
229
230 // init Bone
231 {
232 std::vector<Coord> v0;
233 std::vector<Coord> v1;
234 for (auto joint : this->m_jointMap)
235 {
236 joint->getGlobalQuat();
237 joint->getGlobalCoord();
238 }
239
240 int id_joint = 0;
241 int id_cap = 0;
242 m_capLists.clear();
243 m_T.clear();
244 m_R.clear();
245
246 for (auto joint : this->m_jointMap)
247 {
248 for (auto joint_son : joint->children)
249 {
250 m_capLists.push_back(JCapsule{id_joint, id_cap,
251 joint->GlCoord, joint_son->GlCoord});
252 Vec3f t0 = joint->GlCoord;
253 Vec3f t1 = joint_son->GlCoord;
254 t0 += DEBUG_T;
255 t1 += DEBUG_T;
256 v0.push_back(t0);
257 v1.push_back(t1);
258
259 Quat<Real> t, r;
260 getCenterQuat(joint->GlCoord, joint_son->GlCoord, t, r);
261 m_T.push_back(t);
262 m_R.push_back(r);
263 ++id_cap;
264 }
265 ++id_joint;
266 }
267 m_numCaps = id_cap;
268 m_numjoints = id_joint;
269
270
271 // vector -> DArray
272 this->outCapsule()->allocate();
273 this->outCapsule()->getData().resize(m_numCaps);
274 this->outCapsule()->getData().assign(m_capLists);
275
276 this->outTranslate()->allocate();
277 this->outTranslate()->getData().resize(m_numCaps);
278 this->outTranslate()->getData().assign(m_T);
279
280 this->outRotate()->allocate();
281 this->outRotate()->getData().resize(m_numCaps);
282 this->outRotate()->getData().assign(m_R);
283
284 this->outPosV()->allocate();
285 this->outPosV()->getData().resize(m_numCaps);
286 this->outPosV()->getData().assign(v0);
287
288 this->outPosU()->allocate();
289 this->outPosU()->getData().resize(m_numCaps);
290 this->outPosU()->getData().assign(v1);
291
292 }
293
294 // Init Capsule Topology
295 {
296 auto topo = TypeInfo::cast<DiscreteElements<DataType3f>>(this->stateTopology()->getDataPtr());
297 mHostCap3D.clear();
298 for (auto& cap : m_capLists)
299 {
300 Capsule3D cap3d;
301 cap3d.radius = this->varRadius()->getData();
302 cap3d.segment.v0 = cap.v0;
303 cap3d.segment.v1 = cap.v1;
304 mHostCap3D.push_back(cap3d);
305 }
306
307 auto& caps = topo->getCaps();
308 caps.resize(mHostCap3D.size());
309 caps.assign(mHostCap3D);
310
311 }
312 }
313
314 template<typename TDataType>
316 {
317 if (this->m_jointMap.empty())
318 {
319 printf("Load Skeleton failed.");
320 return;
321 }
322
323 //Animation
324 for (auto joint : this->m_jointMap)
325 {
326 // static int first = 0;
327 // if(first < 7)
328 {
329 joint->applyAnimationAll(this->stateElapsedTime()->getData());
330 // first++;
331 }
332 // joint->applyAnimationAll(0.05);
333 }
334
335 for (auto joint : m_jointMap)
336 {
337 joint->getGlobalQuat();
338 joint->getGlobalCoord();
339 }
340
341 // Update Bone
342 {
343 int index = 0;
344 std::vector<Coord> v0;
345 std::vector<Coord> v1;
346 for (auto joint : this->m_jointMap)
347 {
348 for (auto joint_son : joint->children)
349 {
350 m_capLists[index].v0 = joint->GlCoord;
351 m_capLists[index].v1 = joint_son->GlCoord;
352 Quat<Real> t, r;
353 getCenterQuat(joint->GlCoord, joint_son->GlCoord, t, r);
354 m_T[index] = t;
355 m_R[index] = r;
356
357 Vec3f t0 = joint->GlCoord;
358 Vec3f t1 = joint_son->GlCoord;
359 t0 += DEBUG_T;
360 t1 += DEBUG_T;
361 v0.push_back(t0);
362 v1.push_back(t1);
363
364 index++;
365 }
366 }
367
368 this->outCapsule()->getData().assign(m_capLists);
369 this->outTranslate()->getData().assign(m_T);
370 this->outRotate()->getData().assign(m_R);
371
372 this->outPosV()->getData().assign(v0);
373 this->outPosU()->getData().assign(v1);
374 }
375
376 // Update Capsule Topology
377 {
378 auto topo = TypeInfo::cast<DiscreteElements<DataType3f>>(this->stateTopology()->getDataPtr());
379 int index = 0;
380 for (auto& cap : m_capLists)
381 {
382 auto &cap3d = mHostCap3D[index++];
383 cap3d.segment.v0 = cap.v0;
384 cap3d.segment.v1 = cap.v1;
385 }
386
387 auto& caps = topo->getCaps();
388 caps.assign(mHostCap3D);
389 }
390 }
391
393}
#define AXIS
A JointTree(Skeleton) represents a hierarchical tree structure of joints.
Definition: JointTree.h:31
void resetStates() override
void getCenterQuat(Coord v0, Coord v1, Quat< Real > &T, Quat< Real > &R)
void getAnimationCurve(const ofbx::Object &object, std::shared_ptr< JointTree< TDataType > > parent)
bool initFBX(const char *filepath)
void getNodes(const ofbx::IScene &scene)
void updateTopology() override
TDataType::Coord Coord
TDataType::Real Real
void getModelProperties(const ofbx::Object &object, std::shared_ptr< JointTree< TDataType > > cur)
void getLimbNode(const ofbx::Object &object, std::shared_ptr< JointTree< TDataType > > parent)
TSegment3D< Real > segment
Definition: Primitive3D.h:693
#define T(t)
This is an implementation of AdditiveCCD based on peridyno.
Definition: Array.h:24
Vec3f DEBUG_T(0.25, 0.0, 0.0)
IMPLEMENT_TCLASS(FloatingNumber, TDataType)
DEFINE_CLASS(CircularEmitter)
Vector< float, 3 > Vec3f
Definition: Vector3D.h:93
unsigned char u8
Definition: ofbx.h:8
unsigned long u64
Definition: ofbx.h:16
IScene * load(const u8 *data, int size, u64 flags, JobProcessor job_processor, void *job_user_ptr)
Definition: ofbx.cpp:3597
TEMPLATE_TYPENAME_T VEC3_T axis(QUAT_T const &q)
Definition: vgMath.h:512
virtual const Object * getRoot() const =0
Object * resolveObjectLink(int idx) const
Definition: ofbx.cpp:3537