void NifAnimationImporter::ImportControllers( NiAVObjectRef niAVObj, MDagPath & path ) { list<NiTimeControllerRef> controllers = niAVObj->GetControllers(); //Iterate over the controllers, reacting properly to each type for ( list<NiTimeControllerRef>::iterator it = controllers.begin(); it != controllers.end(); ++it ) { if ( (*it)->IsDerivedType( NiKeyframeController::TYPE ) ) { //--NiKeyframeController--// NiKeyframeControllerRef niKeyCont = DynamicCast<NiKeyframeController>(*it); NiKeyframeDataRef niKeyData = niKeyCont->GetData(); MFnTransform transFn( path.node() ); MFnAnimCurve traXFn; MFnAnimCurve traYFn; MFnAnimCurve traZFn; MObject traXcurve = traXFn.create( transFn.findPlug("translateX") ); MObject traYcurve = traYFn.create( transFn.findPlug("translateY") ); MObject traZcurve = traZFn.create( transFn.findPlug("translateZ") ); MTimeArray traTimes; MDoubleArray traXValues; MDoubleArray traYValues; MDoubleArray traZValues; vector<Key<Vector3> > tra_keys = niKeyData->GetTranslateKeys(); for ( size_t i = 0; i < tra_keys.size(); ++i) { traTimes.append( MTime( tra_keys[i].time, MTime::kSeconds ) ); traXValues.append( tra_keys[i].data.x ); traYValues.append( tra_keys[i].data.y ); traZValues.append( tra_keys[i].data.z ); //traXFn.addKeyframe( tra_keys[i].time * 24.0, tra_keys[i].data.x ); //traYFn.addKeyframe( tra_keys[i].time * 24.0, tra_keys[i].data.y ); //traZFn.addKeyframe( tra_keys[i].time * 24.0, tra_keys[i].data.z ); } traXFn.addKeys( &traTimes, &traXValues ); traYFn.addKeys( &traTimes, &traYValues ); traZFn.addKeys( &traTimes, &traZValues ); KeyType kt = niKeyData->GetRotateType(); if ( kt != XYZ_ROTATION_KEY ) { vector<Key<Quaternion> > rot_keys = niKeyData->GetQuatRotateKeys(); MFnAnimCurve rotXFn; MFnAnimCurve rotYFn; MFnAnimCurve rotZFn; MObject rotXcurve = rotXFn.create( transFn.findPlug("rotateX") ); //rotXFn.findPlug("rotationInterpolation").setValue(3); MObject rotYcurve = rotYFn.create( transFn.findPlug("rotateY") ); //rotYFn.findPlug("rotationInterpolation").setValue(3); MObject rotZcurve = rotZFn.create( transFn.findPlug("rotateZ") ); //rotZFn.findPlug("rotationInterpolation").setValue(3); MTimeArray rotTimes; MDoubleArray rotXValues; MDoubleArray rotYValues; MDoubleArray rotZValues; MEulerRotation mPrevRot; for( size_t i = 0; i < rot_keys.size(); ++i ) { Quaternion niQuat = rot_keys[i].data; MQuaternion mQuat( niQuat.x, niQuat.y, niQuat.z, niQuat.w ); MEulerRotation mRot = mQuat.asEulerRotation(); MEulerRotation mAlt; mAlt[0] = PI + mRot[0]; mAlt[1] = PI - mRot[1]; mAlt[2] = PI + mRot[2]; for ( size_t j = 0; j < 3; ++j ) { double prev_diff = abs(mRot[j] - mPrevRot[j]); //Try adding and subtracting multiples of 2 pi radians to get //closer to the previous angle while (true) { double new_angle = mRot[j] - (PI * 2); double diff = abs( new_angle - mPrevRot[j] ); if ( diff < prev_diff ) { mRot[j] = new_angle; prev_diff = diff; } else { break; } } while (true) { double new_angle = mRot[j] + (PI * 2); double diff = abs( new_angle - mPrevRot[j] ); if ( diff < prev_diff ) { mRot[j] = new_angle; prev_diff = diff; } else { break; } } } for ( size_t j = 0; j < 3; ++j ) { double prev_diff = abs(mAlt[j] - mPrevRot[j]); //Try adding and subtracting multiples of 2 pi radians to get //closer to the previous angle while (true) { double new_angle = mAlt[j] - (PI * 2); double diff = abs( new_angle - mPrevRot[j] ); if ( diff < prev_diff ) { mAlt[j] = new_angle; prev_diff = diff; } else { break; } } while (true) { double new_angle = mAlt[j] + (PI * 2); double diff = abs( new_angle - mPrevRot[j] ); if ( diff < prev_diff ) { mAlt[j] = new_angle; prev_diff = diff; } else { break; } } } //Try taking advantage of the fact that: //Rotate(x,y,z) = Rotate(pi + x, pi - y, pi +z) double rot_diff = ( (abs(mRot[0] - mPrevRot[0]) + abs(mRot[1] - mPrevRot[1]) + abs(mRot[2] - mPrevRot[2]) ) / 3.0 ); double alt_diff = ( (abs(mAlt[0] - mPrevRot[0]) + abs(mAlt[1] - mPrevRot[1]) + abs(mAlt[2] - mPrevRot[2]) ) / 3.0 ); if ( alt_diff < rot_diff ) { mRot = mAlt; } mPrevRot = mRot; rotTimes.append( MTime(rot_keys[i].time, MTime::kSeconds) ); rotXValues.append( mRot[0] ); rotYValues.append( mRot[1] ); rotZValues.append( mRot[2] ); } rotXFn.addKeys( &rotTimes, &rotXValues ); rotYFn.addKeys( &rotTimes, &rotYValues ); rotZFn.addKeys( &rotTimes, &rotZValues ); } } } }