int rec(const string &s) { StringIntMap::const_iterator it = M.find(s); if (it != M.end()) { return it->second; } char temp[64]; strcpy(temp, s.c_str()); char *fg = strchr(temp, 'G'); char *rr = strrchr(temp, 'R'); int f = 0; int r = 0; if (rr > fg) { if (fg != NULL) { *fg = 'R'; f = rec(temp) + 1; *fg = 'G'; } if (rr != NULL) { *rr = 'G'; r = rec(temp) + 1; } } int result = min(f, r); M[s] = result; return result; }
bool AnimationExport::exportController() { vector<Niflib::ControllerLink> blocks = seq->GetControlledBlocks(); int nbones = skeleton->m_bones.getSize(); if (AnimationExport::noRootSiblings) { // Remove bones not children of root. This is a bit of a kludge. // Basically search for the first node after the root which also has no parent // This is typically Camera3. We then truncate tracks to exclude nodes appearing after. for (int i=1; i<nbones; ++i) { if (skeleton->m_parentIndices[i] < 0) { nbones = i; break; } } } int numTracks = nbones; float duration = seq->GetStopTime() - seq->GetStartTime(); int nframes = (int)roundf(duration / FramesIncrement); int nCurrentFrame = 0; hkRefPtr<hkaInterleavedUncompressedAnimation> tempAnim = new hkaInterleavedUncompressedAnimation(); tempAnim->m_duration = duration; tempAnim->m_numberOfTransformTracks = numTracks; tempAnim->m_numberOfFloatTracks = 0;//anim->m_numberOfFloatTracks; tempAnim->m_transforms.setSize(numTracks*nframes, hkQsTransform::getIdentity()); tempAnim->m_floats.setSize(tempAnim->m_numberOfFloatTracks); tempAnim->m_annotationTracks.setSize(numTracks); hkArray<hkQsTransform>& transforms = tempAnim->m_transforms; typedef map<string, int, ltstr> StringIntMap; StringIntMap boneMap; for (int i=0; i<nbones; ++i) { string name = skeleton->m_bones[i].m_name; boneMap[name] = i; } for ( vector<Niflib::ControllerLink>::iterator bitr = blocks.begin(); bitr != blocks.end(); ++bitr) { StringIntMap::iterator boneitr = boneMap.find((*bitr).nodeName); if (boneitr == boneMap.end()) { Log::Warn("Unknown bone '%s' found in animation. Skipping.", (*bitr).nodeName.c_str()); continue; } int boneIdx = boneitr->second; hkQsTransform localTransform = skeleton->m_referencePose[boneIdx]; FillTransforms(transforms, boneIdx, nbones, localTransform); // prefill transforms with bindpose if ( NiTransformInterpolatorRef interpolator = DynamicCast<NiTransformInterpolator>((*bitr).interpolator) ) { if (NiTransformDataRef data = interpolator->GetData()) { if ( data->GetTranslateType() == Niflib::LINEAR_KEY ) { vector<Vector3Key> keys = data->GetTranslateKeys(); int n = keys.size(); if (n > 0) { int frame = 0; float currentTime = 0.0f; Vector3Key* itr = &keys[0], *last = &keys[n-1]; SetTransformPositionRange(transforms, nbones, boneIdx, currentTime, (*itr).time, frame, *itr, *itr); for (int i=1; i<n; ++i) { Vector3Key* next = &keys[i]; SetTransformPositionRange(transforms, nbones, boneIdx, currentTime, (*next).time, frame, *itr, *next); itr = next; } SetTransformPositionRange(transforms, nbones, boneIdx, currentTime, duration, frame, *last, *last); } } else { Log::Verbose("Missing transform data for %s", boneitr->first.c_str()); } if ( data->GetRotateType() == Niflib::QUADRATIC_KEY ) { vector<QuatKey> keys = data->GetQuatRotateKeys(); int n = keys.size(); if (n > 0) { int frame = 0; float currentTime = 0.0f; QuatKey* itr = &keys[0], *last = &keys[n-1]; SetTransformRotationRange(transforms, nbones, boneIdx, currentTime, itr->time, frame, *itr, *itr); for (int i=1; i<n; ++i) { QuatKey* next = &keys[i]; SetTransformRotationRange(transforms, nbones, boneIdx, currentTime, next->time, frame, *itr, *next); itr = next; } SetTransformRotationRange(transforms, nbones, boneIdx, currentTime, duration, frame, *last, *last); } } else { Log::Verbose("Missing rotation data for %s", boneitr->first.c_str()); } if ( data->GetScaleType() == Niflib::LINEAR_KEY ) { vector<FloatKey> keys = data->GetScaleKeys(); int n = keys.size(); if (n > 0) { int frame = 0; float currentTime = 0.0f; FloatKey* itr = &keys[0], *last = &keys[n-1]; SetTransformScaleRange(transforms, nbones, boneIdx, currentTime, itr->time, frame, *itr, *itr); for (int i=1; i<n; ++i) { FloatKey* next = &keys[i]; SetTransformScaleRange(transforms, nbones, boneIdx, currentTime, next->time, frame, *itr, *next); itr = next; } SetTransformScaleRange(transforms, nbones, boneIdx, currentTime, duration, frame, *last, *last); } } else { Log::Verbose("Missing scaling data for %s", boneitr->first.c_str()); } } else { } } else { } } hkaSkeletonUtils::normalizeRotations (transforms.begin(), transforms.getSize()); // create the animation with default settings { hkaSplineCompressedAnimation::TrackCompressionParams tparams; hkaSplineCompressedAnimation::AnimationCompressionParams aparams; tparams.m_rotationTolerance = 0.001f; tparams.m_rotationQuantizationType = hkaSplineCompressedAnimation::TrackCompressionParams::THREECOMP40; hkRefPtr<hkaSplineCompressedAnimation> outAnim = new hkaSplineCompressedAnimation( *tempAnim.val(), tparams, aparams ); binding->m_animation = outAnim; } return true; }