示例#1
0
AnimationChannel* createAnimationChannel(FbxNode* fbxNode, unsigned int targetAttrib, const vector<float>& keyTimes, const vector<float>& keyValues)
{
    AnimationChannel* channel = new AnimationChannel();
    channel->setTargetId(fbxNode->GetName());
    channel->setKeyTimes(keyTimes);
    channel->setKeyValues(keyValues);
    channel->setInterpolation(AnimationChannel::LINEAR);
    channel->setTargetAttribute(targetAttrib);
    return channel;
}
void FBXSceneEncoder::loadAnimationChannels(FbxAnimLayer* animLayer, FbxNode* fbxNode, Animation* animation)
{
    const char* name = fbxNode->GetName();
    //Node* node = _gamePlayFile.getNode(name);

    // Determine which properties are animated on this node
    // Find the transform at each key frame
    // TODO: Ignore properties that are not animated (scale, rotation, translation)
    // This should result in only one animation channel per animated node.

    float startTime = FLT_MAX, stopTime = -1.0f, frameRate = -FLT_MAX;
    bool tx = false, ty = false, tz = false, rx = false, ry = false, rz = false, sx = false, sy = false, sz = false;
    FbxAnimCurve* animCurve = NULL;
    animCurve = getCurve(fbxNode->LclTranslation, animLayer, FBXSDK_CURVENODE_COMPONENT_X);
    if (animCurve)
    {
        tx = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }
    animCurve = getCurve(fbxNode->LclTranslation, animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
    if (animCurve)
    {
        ty = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }
    animCurve = getCurve(fbxNode->LclTranslation, animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
    if (animCurve)
    {
        tz = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }
    animCurve = getCurve(fbxNode->LclRotation, animLayer, FBXSDK_CURVENODE_COMPONENT_X);
    if (animCurve)
    {
        rx = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }
    animCurve = getCurve(fbxNode->LclRotation, animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
    if (animCurve)
    {
        ry = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }
    animCurve = getCurve(fbxNode->LclRotation, animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
    if (animCurve)
    {
        rz = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }
    animCurve = getCurve(fbxNode->LclScaling, animLayer, FBXSDK_CURVENODE_COMPONENT_X);
    if (animCurve)
    {
        sx = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }
    animCurve = getCurve(fbxNode->LclScaling, animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
    if (animCurve)
    {
        sy = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }
    animCurve = getCurve(fbxNode->LclScaling, animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
    if (animCurve)
    {
        sz = true;
        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
    }

    if (!(sx || sy || sz || rx || ry || rz || tx || ty || tz))
        return; // no animation channels

    assert(startTime != FLT_MAX);
    assert(stopTime >= 0.0f);

    // Determine which animation channels to create
    vector<unsigned int> channelAttribs;
    if (sx && sy && sz)
    {
        if (rx || ry || rz)
        {
            if (tx && ty && tz)
            {
                channelAttribs.push_back(Transform::ANIMATE_SCALE_ROTATE_TRANSLATE);
            }
            else
            {
                channelAttribs.push_back(Transform::ANIMATE_SCALE_ROTATE);
                if (tx)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_X);
                if (ty)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Y);
                if (tz)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Z);
            }
        }
        else
        {
            if (tx && ty && tz)
            {
                channelAttribs.push_back(Transform::ANIMATE_SCALE_TRANSLATE);
            }
            else
            {
                channelAttribs.push_back(Transform::ANIMATE_SCALE);
                if (tx)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_X);
                if (ty)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Y);
                if (tz)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Z);
            }
        }
    }
    else
    {
        if (rx || ry || rz)
        {
            if (tx && ty && tz)
            {
                channelAttribs.push_back(Transform::ANIMATE_ROTATE_TRANSLATE);
            }
            else
            {
                channelAttribs.push_back(Transform::ANIMATE_ROTATE);
                if (tx)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_X);
                if (ty)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Y);
                if (tz)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Z);
            }
        }
        else
        {
            if (tx && ty && tz)
            {
                channelAttribs.push_back(Transform::ANIMATE_TRANSLATE);
            }
            else
            {
                if (tx)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_X);
                if (ty)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Y);
                if (tz)
                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Z);
            }
        }

        if (sx)
            channelAttribs.push_back(Transform::ANIMATE_SCALE_X);
        if (sy)
            channelAttribs.push_back(Transform::ANIMATE_SCALE_Y);
        if (sz)
            channelAttribs.push_back(Transform::ANIMATE_SCALE_Z);
    }
    unsigned int channelCount = channelAttribs.size();
    assert(channelCount > 0);

    // Allocate channel list
    const int channelStart = animation->getAnimationChannelCount();
    for (unsigned int i = 0; i < channelCount; ++i)
    {
        AnimationChannel* channel = new AnimationChannel();
        channel->setTargetId(name);
        channel->setInterpolation(AnimationChannel::LINEAR);
        channel->setTargetAttribute(channelAttribs[i]);
        animation->add(channel);
    }

    // Evaulate animation curve in increments of frameRate and populate channel data.
    FbxAMatrix fbxMatrix;
    Matrix matrix;
    double increment = 1000.0 / (double)frameRate;
    int frameCount = (int)ceil((double)(stopTime - startTime) / increment) + 1; // +1 because stop time is inclusive

    // If the animation for this node only has only 1 key frame and it is equal to the node's transform then ignore it.
    // This is a work around for a bug in the Blender FBX exporter.
    if (frameCount == 1 && fbxMatrix == fbxNode->EvaluateLocalTransform(0))
    {
        return;
    }

    for (int frame = 0; frame < frameCount; ++frame)
    {
        double time = startTime + (frame * (double)increment);

        // Note: We used to clamp time to stop time, but FBX sdk does not always produce
        // and accurate stopTime (sometimes it is rounded down for some reason), so I'm
        // disabling this clamping for now as it seems more accurate under normal circumstances.
        //time = std::min(time, (double)stopTime);

        // Evalulate the animation at this time
        FbxTime kTime;
        kTime.SetMilliSeconds((FbxLongLong)time);
        fbxMatrix = fbxNode->EvaluateLocalTransform(kTime);
        copyMatrix(fbxMatrix, matrix);

        // Decompose the evalulated transformation matrix into separate
        // scale, rotation and translation.
        Vector3 scale;
        Quaternion rotation;
        Vector3 translation;
        matrix.decompose(&scale, &rotation, &translation);
        rotation.normalize();

        // Append keyframe data to all channels
        for (unsigned int i = channelStart, channelEnd = channelStart + channelCount; i < channelEnd; ++i)
        {
            appendKeyFrame(fbxNode, animation->getAnimationChannel(i), (float)time, scale, rotation, translation);
        }
    }

    if (_groupAnimation != animation)
    {
        _gamePlayFile.addAnimation(animation);
    }
}
示例#3
0
void GPBFile::decomposeTransformAnimationChannel(Animation* animation, const AnimationChannel* channel)
{
    const std::vector<float>& keyTimes = channel->getKeyTimes();
    const std::vector<float>& keyValues = channel->getKeyValues();
    const size_t keyTimesSize = keyTimes.size();
    const size_t keyValuesSize = keyValues.size();

    std::vector<float> scaleKeyValues;
    std::vector<float> rotateKeyValues;
    std::vector<float> translateKeyValues;
                    
    scaleKeyValues.reserve(keyTimesSize * 3);
    rotateKeyValues.reserve(keyTimesSize * 4);
    translateKeyValues.reserve(keyTimesSize * 3);

    for (size_t kv = 0; kv < keyValuesSize; kv += 10)
    {
        scaleKeyValues.push_back(keyValues[kv]);
        scaleKeyValues.push_back(keyValues[kv+1]);
        scaleKeyValues.push_back(keyValues[kv+2]);

        rotateKeyValues.push_back(keyValues[kv+3]);
        rotateKeyValues.push_back(keyValues[kv+4]);
        rotateKeyValues.push_back(keyValues[kv+5]);
        rotateKeyValues.push_back(keyValues[kv+6]);

        translateKeyValues.push_back(keyValues[kv+7]);
        translateKeyValues.push_back(keyValues[kv+8]);
        translateKeyValues.push_back(keyValues[kv+9]);
    }

    // replace transform animation channel with translate, rotate and scale animation channels

    // Don't add the scale channel if all the key values are close to 1.0
    size_t oneCount = (size_t)std::count_if(scaleKeyValues.begin(), scaleKeyValues.end(), isAlmostOne);
    if (scaleKeyValues.size() != oneCount)
    {
        AnimationChannel* scaleChannel = new AnimationChannel();
        scaleChannel->setTargetId(channel->getTargetId());
        scaleChannel->setKeyTimes(channel->getKeyTimes());
        scaleChannel->setTangentsIn(channel->getTangentsIn());
        scaleChannel->setTangentsOut(channel->getTangentsOut());
        scaleChannel->setInterpolations(channel->getInterpolationTypes());
        scaleChannel->setTargetAttribute(Transform::ANIMATE_SCALE);
        scaleChannel->setKeyValues(scaleKeyValues);
        scaleChannel->removeDuplicates();
        animation->add(scaleChannel);
    }

    AnimationChannel* rotateChannel = new AnimationChannel();
    rotateChannel->setTargetId(channel->getTargetId());
    rotateChannel->setKeyTimes(channel->getKeyTimes());
    rotateChannel->setTangentsIn(channel->getTangentsIn());
    rotateChannel->setTangentsOut(channel->getTangentsOut());
    rotateChannel->setInterpolations(channel->getInterpolationTypes());
    rotateChannel->setTargetAttribute(Transform::ANIMATE_ROTATE);
    rotateChannel->setKeyValues(rotateKeyValues);
    rotateChannel->removeDuplicates();
    animation->add(rotateChannel);

    AnimationChannel* translateChannel = new AnimationChannel();
    translateChannel->setTargetId(channel->getTargetId());
    translateChannel->setKeyTimes(channel->getKeyTimes());
    translateChannel->setTangentsIn(channel->getTangentsIn());
    translateChannel->setTangentsOut(channel->getTangentsOut());
    translateChannel->setInterpolations(channel->getInterpolationTypes());
    translateChannel->setTargetAttribute(Transform::ANIMATE_TRANSLATE);
    translateChannel->setKeyValues(translateKeyValues);
    translateChannel->removeDuplicates();
    animation->add(translateChannel);
}