Animation.h#

Parent directory (model)

Contains an Animation class.

Includes#

  • PVRAssets/model/FormattedUserData.h

  • PVRCore/math/MathUtils.h

Included By#

Namespaces#

Classes#

Source Code#

#pragma once
#include "PVRCore/math/MathUtils.h"
#include "PVRAssets/model/FormattedUserData.h"

namespace pvr {
namespace assets {
struct KeyFrameData
{
    enum struct InterpolationType : uint32_t
    {
        Step = 0,
        Linear = 1,
        CubicSpline = 2,
    };

    std::vector<float> timeInSeconds;
    std::vector<glm::vec3> scale;
    std::vector<glm::quat> rotate;
    std::vector<glm::vec3> translation;
    std::vector<glm::mat4> mat4;
    InterpolationType interpolation = InterpolationType::Step;
};

class AnimationData
{
public:
    struct InternalData
    {
        // Since the size is shared by all of those items, we are eschewing the use of vectors in order to save the extra space of size and capacity.
        uint32_t flags;

        // Indices: If you will have loads of repeated value
        std::vector<uint32_t> positionIndices;
        std::vector<uint32_t> rotationIndices;
        std::vector<uint32_t> scaleIndices;
        std::vector<uint32_t> matrixIndices;

        uint32_t numFrames;

        std::string animationName;

        std::vector<float> timeInSeconds;

        std::vector<KeyFrameData> keyFrames;

        float startTime;
        float endTime;

        CustomData formattedUserData;

        InternalData() : flags(0), numFrames(0), startTime(0), endTime(0) {}
    };

public:
    AnimationData() : _cacheF1(0), _cacheF2(1) {}

    void setAnimationName(const std::string& animationName) { _data.animationName = animationName; }

    const std::string& getAnimationName() const { return _data.animationName; }

    void computeDuration();

    size_t getNumKeyFrames() const { return _data.keyFrames.size(); }

    void allocateKeyFrames(uint32_t keyFrames) { _data.keyFrames.resize(keyFrames); }

    KeyFrameData& getAnimationData(uint32_t index) { return _data.keyFrames[index]; }

    float getTotalTimeInSec() const { return _data.endTime - _data.startTime; }

    float getTotalTimeInMs() const { return getTotalTimeInSec() * 1000.f; }

    float getStartTimeInSec() const { return _data.startTime; }

    float getEndTimeInSec() const { return _data.endTime; }

    glm::mat4x4 getTransformationMatrix(uint32_t frame = 0, float interp = 0) const;

    uint32_t getNumFrames() const;

    uint32_t getFlags() const;

    const float* getPositions() const;

    const uint32_t* getPositionIndices() const;

    const float* getRotations() const;

    const uint32_t* getRotationIndices() const;

    const float* getScales() const;

    const uint32_t* getScaleIndices() const;

    const float* getMatrices() const;

    const uint32_t* getMatrixIndices() const;

    void setPositions(uint32_t numFrames, const float* data,
        const uint32_t* indices = nullptr); // Expects an array of 3 floats

    void setRotations(uint32_t numFrames, const float* const data,
        const uint32_t* const indices = nullptr); // Expects an array of 4 floats

    void setScales(uint32_t numFrames, const float* const data,
        const uint32_t* const indices = nullptr); // Expects an array of 7 floats

    void setMatrices(uint32_t numFrames, const float* const data,
        const uint32_t* const indices = nullptr); // Expects an array of 16 floats

    InternalData& getInternalData(); // If you know what you're doing

private:
    InternalData _data;
    // cache
    uint32_t _cacheF1, _cacheF2;
};

struct AnimationInstance
{
    struct KeyframeChannel
    {
        std::vector<void*> nodes;

        uint32_t keyFrame;

        KeyframeChannel() : keyFrame(0) {}
    };

    class AnimationData* animationData;
    std::vector<KeyframeChannel> keyframeChannels;

public:
    AnimationInstance() : animationData(nullptr) {}

    float getTotalTimeInMs() const { return animationData->getTotalTimeInMs(); }

    float getTotalTimeInSec() const { return animationData->getTotalTimeInSec(); }

    float getStartTimeInSec() const { return animationData->getStartTimeInSec(); }

    float getEndTimeInSec() const { return animationData->getEndTimeInSec(); }

    void updateAnimation(float timeInMs);

    void updateAnimationFromKey(uint32_t frameNumber);
};

} // namespace assets
} // namespace pvr