| 3412 | } |
| 3413 | |
| 3414 | FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::vector<const AnimationCurveNode *> &nodes, |
| 3415 | int64_t start, int64_t stop) { |
| 3416 | KeyFrameListList inputs; |
| 3417 | inputs.reserve(nodes.size() * 3); |
| 3418 | |
| 3419 | // give some breathing room for rounding errors |
| 3420 | const int64_t adj_start = start - 10000; |
| 3421 | const int64_t adj_stop = stop + 10000; |
| 3422 | |
| 3423 | for (const AnimationCurveNode *node : nodes) { |
| 3424 | ai_assert(node); |
| 3425 | |
| 3426 | const AnimationCurveMap &curves = node->Curves(); |
| 3427 | for (const AnimationCurveMap::value_type &kv : curves) { |
| 3428 | |
| 3429 | unsigned int mapto; |
| 3430 | if (kv.first == "d|X") { |
| 3431 | mapto = 0; |
| 3432 | } else if (kv.first == "d|Y") { |
| 3433 | mapto = 1; |
| 3434 | } else if (kv.first == "d|Z") { |
| 3435 | mapto = 2; |
| 3436 | } else { |
| 3437 | FBXImporter::LogWarn("ignoring scale animation curve, did not recognize target component"); |
| 3438 | continue; |
| 3439 | } |
| 3440 | |
| 3441 | const AnimationCurve *const curve = kv.second; |
| 3442 | ai_assert(curve->GetKeys().size() == curve->GetValues().size()); |
| 3443 | ai_assert(curve->GetKeys().size()); |
| 3444 | |
| 3445 | // get values within the start/stop time window |
| 3446 | std::shared_ptr<KeyTimeList> Keys(new KeyTimeList()); |
| 3447 | std::shared_ptr<KeyValueList> Values(new KeyValueList()); |
| 3448 | const size_t count = curve->GetKeys().size(); |
| 3449 | |
| 3450 | int64_t tp = curve->GetKeys().at(0); |
| 3451 | float vp = curve->GetValues().at(0); |
| 3452 | Keys->push_back(tp); |
| 3453 | Values->push_back(vp); |
| 3454 | if (count > 1) { |
| 3455 | int64_t tc = curve->GetKeys().at(1); |
| 3456 | float vc = curve->GetValues().at(1); |
| 3457 | for (size_t n = 1; n < count; n++) { |
| 3458 | while (std::abs(vc - vp) >= 180.0f) { |
| 3459 | double step = std::floor(double(tc - tp) / std::abs(vc - vp) * 179.0f); |
| 3460 | int64_t tnew = tp + int64_t(step); |
| 3461 | float vnew = vp + (vc - vp) * float(step / (tc - tp)); |
| 3462 | if (tnew >= adj_start && tnew <= adj_stop) { |
| 3463 | Keys->push_back(tnew); |
| 3464 | Values->push_back(vnew); |
| 3465 | } else { |
| 3466 | // Something broke |
| 3467 | break; |
| 3468 | } |
| 3469 | tp = tnew; |
| 3470 | vp = vnew; |
| 3471 | } |